From a5b9c1052c4640ba519e608e0c97e603ce6aa5ef Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Wed, 30 Sep 2026 18:57:30 -0400 Subject: feat: blackjack and baccarat rules felt added, casino layout simplified --- internal/game/render_baccarat_felt_test.go | 92 ++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 internal/game/render_baccarat_felt_test.go (limited to 'internal/game/render_baccarat_felt_test.go') diff --git a/internal/game/render_baccarat_felt_test.go b/internal/game/render_baccarat_felt_test.go new file mode 100644 index 0000000..dabaa36 --- /dev/null +++ b/internal/game/render_baccarat_felt_test.go @@ -0,0 +1,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 WAGER PER PLAYER PER ROUND", + } { + 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") + } +} -- cgit v1.2.3