aboutsummaryrefslogtreecommitdiff
path: root/internal/game/render_casino_help.go
blob: 26927aeffa0e02d383d16a6957a5c853c8b1acce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package game

import (
	"fmt"
	"strings"

	"thehouseoficarus/internal/casino"
	"thehouseoficarus/internal/net"
	"thehouseoficarus/internal/ui"
)

// casinoBetTable uses the shared ANSI-aware table renderer, rather than
// letting the session wrap a long, pipe-separated payout paragraph.
func (g *Game) casinoBetTable(sess *net.Session, title string, columns []string, rows [][]string) string {
	t := ui.Table{Title: g.colorize(sess, "casino_action", title)}
	for _, col := range columns {
		t.Columns = append(t.Columns, g.colorize(sess, "casino_action", col))
	}
	for _, row := range rows {
		cells := append([]string(nil), row...)
		for i, cell := range cells {
			category := "casino_action"
			if i == 0 {
				category = "command"
			}
			if i == len(cells)-1 {
				category = "casino_payout"
			}
			cells[i] = g.colorize(sess, category, cell)
		}
		t.Rows = append(t.Rows, cells)
	}
	unicode, width := true, 78
	if p := sess.Player; p != nil {
		unicode = p.OptionBool("unicode")
		if wrap := p.OptionInt("wrap_width"); wrap > 0 {
			width = min(width, wrap)
		}
	}
	return strings.Join(t.Render(unicode, width), "\n")
}

// rouletteReminder is shown by table/table rules, not on ambient boards.
// Hit chances count equally likely pockets; all ratios are NET profit odds.
func (g *Game) rouletteReminder(sess *net.Session, cfg casino.TableConfig) string {
	pockets, basketCount, basketOdds := 37, 4, "8:1"
	if cfg.Roulette.DoubleZero {
		pockets, basketCount, basketOdds = 38, 5, "6:1"
	}
	chance := func(n int) string { return fmt.Sprintf("%d/%d", n, pockets) }
	rows := [][]string{
		{"Number", "17 (or 0)", chance(1), "35:1"},
		{"Split", "split 1 2", chance(2), "17:1"},
		{"Street", "street 1 2 3", chance(3), "11:1"},
		{"Trio", "trio 0 1 2", chance(3), "11:1"},
		{"Corner", "corner 1 2 4 5", chance(4), "8:1"},
		{"Six line", "line 1 2 3 4 5 6", chance(6), "5:1"},
		{"Dozen", "1to12/13to24/25to36", chance(12), "2:1"},
		{"Row", "row1/row2/row3", chance(12), "2:1"},
		{"Color", "red / black", chance(18), "1:1"},
		{"Parity", "odd / even", chance(18), "1:1"},
		{"Low / high", "low / high", chance(18), "1:1"},
		{"Basket", "basket", chance(basketCount), basketOdds},
	}
	if cfg.Roulette.DoubleZero {
		rows[0][1] = "17 (or 0, 00)"
	}
	blocks := []string{g.casinoBetTable(sess, "Roulette payouts", []string{"Bet", "Target / example", "Chance", "Profit"}, rows)}
	if cfg.Roulette.Racetrack && !cfg.Roulette.DoubleZero {
		blocks = append(blocks, g.casinoBetTable(sess, "Racetrack payouts", []string{"Target", "Winning pockets", "Chance", "Profit"}, [][]string{
			{"voisins", "0, 2, 3", chance(3), "5:3"},
			{"voisins", "Other covered", chance(14), "1:1"},
			{"tiers", "Any covered", chance(12), "2:1"},
			{"orphelins", "1, 17", chance(2), "31:5"},
			{"orphelins", "Other covered", chance(6), "13:5"},
			{"zero / jeu zero", "26", chance(1), "8:1"},
			{"zero / jeu zero", "Other covered", chance(6), "7:2"},
			{"neighbors <n>", "Any covered", chance(9), "3:1"},
		}))
		blocks = append(blocks, "Profit is on the total stake; each row lists its winning pockets.\nCall bets split your stake; fractional returns round down.\nUse help racetrack for the chip placements.")
	}
	blocks = append(blocks,
		"Profit excludes your returned stake: 1:1 on 10 returns 20.\n"+
			"Low: 1-18; high: 19-36. Zero pockets lose outside bets.\n"+
			"Use bet <amount> on <target>, e.g. bet 10 on split 1 2.\n"+
			"Learn more: help roulette / help casino; table rules for this table.")
	return strings.Join(blocks, "\n")
}