aboutsummaryrefslogtreecommitdiff
path: root/internal/game/render_blackjack_felt_test.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-30 18:57:30 -0400
committerhistoria <[not public]>2026-09-30 18:57:30 -0400
commita5b9c1052c4640ba519e608e0c97e603ce6aa5ef (patch)
treec48ac64ca8d1ec2505eedd18fb9e2fc39a885689 /internal/game/render_blackjack_felt_test.go
parent2317022c16b520dd5272facfd5092a4c58cac44b (diff)
downloadthehouseoficarus-a5b9c1052c4640ba519e608e0c97e603ce6aa5ef.tar.gz
feat: blackjack and baccarat rules felt added, casino layout simplified
Diffstat (limited to 'internal/game/render_blackjack_felt_test.go')
-rw-r--r--internal/game/render_blackjack_felt_test.go84
1 files changed, 84 insertions, 0 deletions
diff --git a/internal/game/render_blackjack_felt_test.go b/internal/game/render_blackjack_felt_test.go
new file mode 100644
index 0000000..a67251a
--- /dev/null
+++ b/internal/game/render_blackjack_felt_test.go
@@ -0,0 +1,84 @@
+package game
+
+import (
+ "strings"
+ "testing"
+
+ "thehouseoficarus/internal/casino"
+ "thehouseoficarus/internal/color"
+)
+
+func TestBlackjackRulesFeltGeometryAndPhrases(t *testing.T) {
+ cfg := casino.TableConfig{ID: "midnight", Game: casino.GameBlackjack, MinBet: 100, MaxBet: 10000, MaxPlayers: 6, BettingTicks: 18,
+ Blackjack: casino.BlackjackConfig{ActionTicks: 15, DoubleSplitBlackjack: &[]bool{false}[0]}}
+ for _, unicode := range []bool{false, true} {
+ art := renderBlackjackRulesFelt(cfg, "none", unicode)
+ rows := strings.Split(strings.TrimSuffix(art, "\n"), "\n")
+ if len(rows) != 21 {
+ 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{
+ "BLACKJACK PAYS 3 TO 2", "DEALER MUST STAND ON 17 AND DRAW TO 16", "INSURANCE PAYS 2 TO 1",
+ "THE SHOE", "PAYS", "DOUBLE & SPLIT", "HOUSE",
+ "DECKS", "SHUFFLE AT", "25% REMAINING", "RESHUFFLE MID-ROUND", "HOLE CARD",
+ "ORDINARY WIN", "SPLIT+DOUBLE 21", "DOUBLE", "ANY TWO, ONE CARD", "MAX HANDS", "ONE CARD, NO HITS",
+ "SURRENDER", "NOT OFFERED", "100-10000 CREDITS", "18 TICKS", "15 TICKS",
+ } {
+ if !strings.Contains(art, want) {
+ t.Fatalf("missing %q in unicode=%v felt", want, unicode)
+ }
+ }
+ // The raw dump's phrases and fixed engine rules must not leak onto the felt.
+ for _, stale := range []string{"Number of decks", "Dealer hole card / peek:", "FRACTIONS", "BJ CHECK", "HOUSE BLACKJACK"} {
+ if strings.Contains(art, stale) {
+ t.Fatalf("stale prose %q on felt", stale)
+ }
+ }
+ }
+}
+
+func TestBlackjackRulesFeltFollowsConfig(t *testing.T) {
+ yes, no := true, false
+ cfg := casino.TableConfig{ID: "high", Game: casino.GameBlackjack, MinBet: 5, MaxBet: 500,
+ Blackjack: casino.BlackjackConfig{Decks: 1, BlackjackPayout: 1.2, DealerHitSoft17: &yes, Surrender: &yes,
+ ShuffleAt: 0.5, MaxSplitHands: 2, DoubleAfterSplit: &no, ResplitAces: &yes, SplitUnlikeTenValues: &no,
+ DoubleSplitBlackjack: &no, InsurancePayout: 2}}
+ art := renderBlackjackRulesFelt(cfg, "none", true)
+ for _, want := range []string{"BLACKJACK PAYS 6 TO 5", "DEALER HITS SOFT 17", "LATE, TWO CARDS", "50% REMAINING",
+ "AFTER SPLIT NO", "RESPLIT ACES YES", "PAIRS IDENTICAL RANKS",
+ "SPLIT+DOUBLE 21 1:1", "5-500 CREDITS"} {
+ if !strings.Contains(art, want) {
+ t.Fatalf("missing %q: %s", want, art)
+ }
+ }
+}
+
+func TestBlackjackJoinPrintsFeltNotProse(t *testing.T) {
+ g := &Game{Casino: casino.NewManager(1)}
+ g.Casino.Join(1, casino.TableConfig{ID: "bj", Game: casino.GameBlackjack, BettingTicks: 2}, "alice")
+ events := g.Casino.Join(1, casino.TableConfig{ID: "bj", Game: casino.GameBlackjack, BettingTicks: 2}, "bob")
+ found := false
+ for _, e := range events {
+ if view, ok := e.Snapshot.(*casino.BlackjackRulesView); ok {
+ found = true
+ art := renderBlackjackRulesFelt(view.Config, "none", true)
+ if !strings.Contains(art, "BLACKJACK PAYS 3 TO 2") || !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")
+ }
+}