aboutsummaryrefslogtreecommitdiff
path: root/internal/game/render_baccarat_felt.go
blob: 3120bd75fa92df9ac9f06aa762baede8ada01f50 (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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package game

import (
	"fmt"
	"strings"

	"thehouseoficarus/internal/casino"
)

// A baccarat felt: the three main wagers as betting boxes, the optional side
// bets and house settings in labelled boxes, and the punto banco drawing
// table across the bottom. Reuses the shared felt canvas and palette.
func renderBaccaratRulesFelt(cfg casino.TableConfig, mode string, unicode bool) string {
	b := cfg.Baccarat.Normalize()
	c := newCrapsCanvas(26)
	// Title block: variant, scoring, naturals.
	c.box(0, 0, 76, 4)
	c.center(1, 75, 1, baccaratVariantTitle(b), crapsGold)
	c.center(1, 75, 2, "ACE 1 | 2-9 FACE | 10/J/Q/K 0 — HIGHEST LAST DIGIT WINS", crapsInk)
	c.center(1, 75, 3, "AN INITIAL 8 OR 9 ON EITHER HAND STOPS ALL DRAWING", crapsMuted)
	// Three betting boxes: PLAYER | TIE | BANKER.
	spots := [3][2]int{{0, 25}, {25, 50}, {50, 76}}
	for _, x := range spots {
		c.box(x[0], 4, x[1], 8)
	}
	c.center(1, 24, 5, "PLAYER", crapsGold)
	c.center(26, 49, 5, "TIE", crapsGold)
	c.center(51, 75, 5, "BANKER", crapsGold)
	c.center(1, 24, 6, "PAYS 1:1", crapsInk)
	c.center(26, 49, 6, "PAYS "+ratioText(b.TiePayout), crapsInk)
	c.center(51, 75, 6, bankerPayoutText(b), crapsInk)
	c.center(1, 24, 7, "", crapsMuted)
	c.center(26, 49, 7, "PLAYER & BANKER PUSH", crapsMuted)
	c.center(51, 75, 7, bankerNoteText(b), crapsMuted)
	// Side bets and house settings.
	boxY := [2][2]int{{8, 15}, {8, 15}}
	xs := [2][2]int{{0, 38}, {38, 76}}
	for i := range boxY {
		c.box(xs[i][0], boxY[i][0], xs[i][1], boxY[i][1])
	}
	c.center(1, 37, 9, "SIDE BETS", crapsGold)
	c.center(39, 75, 9, "HOUSE", crapsGold)
	side := [][2]string{
		{"PLAYER PAIR", optionalText(b.PairBets, "11:1")},
		{"BANKER PAIR", optionalText(b.PairBets, "11:1")},
		{"DRAGON 7", optionalText(b.Dragon7, "40:1")},
		{"PANDA 8", optionalText(b.Panda8, "25:1")},
		{"SUPER 6", optionalText(b.Super6Bet, "12:1")},
	}
	house := [][2]string{
		{"DECKS", fmt.Sprintf("%d", b.Decks)},
		{"SHUFFLE AT", fmt.Sprintf("%.6g%% REMAINING", b.ShuffleAt*100)},
		{"BET LIMITS", betLimitsText(cfg.MinBet, cfg.MaxBet)},
		{"SEATS", fmt.Sprintf("%d", cfg.MaxPlayers)},
		{"BETTING WINDOW", fmt.Sprintf("%d TICKS", cfg.BettingTicks)},
	}
	for j, row := range side {
		c.bjRule(0, 38, 10+j, row[0], row[1])
	}
	for j, row := range house {
		c.bjRule(38, 76, 10+j, row[0], row[1])
	}
	// Drawing table across the bottom: one row per hand total, with the
	// player rule and each banker situation in its own column.
	c.box(0, 15, 76, 25)
	c.center(1, 75, 16, "DRAWING — AUTOMATIC PUNTO BANCO", crapsGold)
	c.text(3, 17, "HAND", crapsGold)
	c.text(9, 17, "PLAYER", crapsGold)
	c.text(18, 17, "BANKER (PLAYER STANDS)", crapsGold)
	c.text(44, 17, "BANKER (PLAYER DRAWS)", crapsGold)
	c.box(1, 18, 75, 18)
	drawRows := [][4]string{
		{"0-2", "draw", "draw", "draw"},
		{"3", "draw", "draw", "draw unless vs 8"},
		{"4", "draw", "draw", "draw vs 2-7"},
		{"5", "draw", "draw", "draw vs 4-7"},
		{"6", "stand", "stand", "draw vs 6-7"},
		{"7", "stand", "stand", "stand"},
	}
	for i, row := range drawRows {
		y := 19 + i
		c.text(3, y, row[0], crapsInk)
		c.text(9, y, row[1], crapsInk)
		c.text(18, y, row[2], crapsInk)
		c.text(44, y, row[3], crapsInk)
	}
	return c.render(mode, unicode)
}

func baccaratVariantTitle(b casino.BaccaratConfig) string {
	switch b.Variant {
	case casino.BaccaratSuper6:
		return "SUPER 6 BACCARAT — NO COMMISSION"
	case casino.BaccaratEZ:
		return "EZ BACCARAT — NO COMMISSION"
	default:
		return "PUNTO BANCO — COMMISSION"
	}
}
func bankerPayoutText(b casino.BaccaratConfig) string {
	switch b.Variant {
	case casino.BaccaratSuper6, casino.BaccaratEZ, casino.BaccaratCommission:
		return "PAYS 1:1"
	default:
		return "PAYS " + ratioText(b.BankerPayout)
	}
}
func bankerNoteText(b casino.BaccaratConfig) string {
	switch b.Variant {
	case casino.BaccaratSuper6:
		return "WINNING 6 PAYS 1:2"
	case casino.BaccaratEZ:
		return "3-CARD 7 PUSHES"
	default:
		return fmt.Sprintf("%s%% COMMISSION", strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.6f", (1-b.BankerPayout)*100), "0"), "."))
	}
}
func optionalText(enabled bool, payout string) string {
	if enabled {
		return payout
	}
	return "NOT OFFERED"
}