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
|
package game
import (
"strings"
"testing"
"thehouseoficarus/internal/casino"
"thehouseoficarus/internal/color"
)
func TestBaccaratRulesFeltGeometryAndPhrases(t *testing.T) {
cfg := casino.TableConfig{ID: "harbor", Game: casino.GameBaccarat, MinBet: 1, MaxBet: 100, MaxPlayers: 8, BettingTicks: 35,
Baccarat: casino.BaccaratConfig{Variant: casino.BaccaratCommission, PairBets: true, Decks: 8, ShuffleAt: 0.25, TiePayout: 8, BankerPayout: 0.95}}
for _, unicode := range []bool{false, true} {
art := renderBaccaratRulesFelt(cfg, "none", unicode)
rows := strings.Split(strings.TrimSuffix(art, "\n"), "\n")
if len(rows) != 22 {
t.Fatalf("felt height %d", len(rows))
}
for _, row := range rows {
if color.VisibleLen(row) != 77 {
t.Fatalf("misaligned (%d): %s", color.VisibleLen(row), row)
}
}
for _, want := range []string{
"PUNTO BANCO — COMMISSION", "HIGHEST LAST DIGIT WINS", "STOPS ALL DRAWING",
"PLAYER", "TIE", "BANKER", "PAYS 1:1", "PAYS 8 TO 1", "5% COMMISSION",
"PLAYER & BANKER PUSH",
"SIDE BETS", "HOUSE", "PLAYER PAIR", "BANKER PAIR", "11:1",
"DRAGON 7", "PANDA 8", "SUPER 6", "NOT OFFERED",
"DECKS", "SHUFFLE AT", "BET LIMITS", "1-100 CREDITS", "35 TICKS",
"DRAWING — AUTOMATIC PUNTO BANCO", "DRAWS 0-5", "6 DRAWS VS 6-7",
"ONE MAIN BET (PLAYER/BANKER/TIE) PLUS SIDE BETS",
} {
if !strings.Contains(art, want) {
t.Fatalf("missing %q in unicode=%v felt", want, unicode)
}
}
// The raw dump's phrases must not leak onto the felt.
for _, stale := range []string{"Number of decks", "Drawing: Automatic", "Fractional credits:"} {
if strings.Contains(art, stale) {
t.Fatalf("stale prose %q on felt", stale)
}
}
}
}
func TestBaccaratRulesFeltFollowsConfig(t *testing.T) {
cfg := casino.TableConfig{ID: "crown", Game: casino.GameBaccarat, MinBet: 100, MaxBet: 10000, BettingTicks: 35,
Baccarat: casino.BaccaratConfig{Variant: casino.BaccaratEZ, Dragon7: true, Panda8: true, Decks: 6, TiePayout: 9, BankerPayout: 1, ShuffleAt: 0.5}}
art := renderBaccaratRulesFelt(cfg, "none", true)
for _, want := range []string{"EZ BACCARAT — NO COMMISSION", "PAYS 9 TO 1", "3-CARD 7 PUSHES",
"DRAGON 7" + strings.Repeat(" ", 23) + "40:1", "PANDA 8" + strings.Repeat(" ", 24) + "25:1",
"100-10000 CREDITS", "50% REMAINING"} {
if !strings.Contains(art, want) {
t.Fatalf("missing %q: %s", want, art)
}
}
cfg2 := casino.TableConfig{ID: "charter", Game: casino.GameBaccarat,
Baccarat: casino.BaccaratConfig{Variant: casino.BaccaratSuper6, Super6Bet: true, TiePayout: 9}}
art2 := renderBaccaratRulesFelt(cfg2, "none", true)
for _, want := range []string{"SUPER 6 BACCARAT — NO COMMISSION", "WINNING 6 PAYS 1:2", "SUPER 6" + strings.Repeat(" ", 24) + "12:1", "PAYS 9 TO 1"} {
if !strings.Contains(art2, want) {
t.Fatalf("missing %q: %s", want, art2)
}
}
}
func TestBaccaratJoinPrintsFeltNotProse(t *testing.T) {
g := &Game{Casino: casino.NewManager(1)}
g.Casino.Join(1, casino.TableConfig{ID: "bac", Game: casino.GameBaccarat}, "alice")
events := g.Casino.Join(1, casino.TableConfig{ID: "bac", Game: casino.GameBaccarat}, "bob")
found := false
for _, e := range events {
if view, ok := e.Snapshot.(*casino.BaccaratRulesView); ok {
found = true
art := renderBaccaratRulesFelt(view.Config, "none", true)
if !strings.Contains(art, "PUNTO BANCO — COMMISSION") || !strings.Contains(art, "DECKS") {
t.Fatal("rules felt missing phrases", art)
}
if e.Message != "" {
t.Fatal("rules event carries prose", e.Message)
}
}
if strings.Contains(e.Message+e.PrivateMessage, "Number of decks") {
t.Fatal("raw rules prose leaked onto join", e)
}
}
if !found {
t.Fatal("join did not attach the rules felt")
}
}
|