aboutsummaryrefslogtreecommitdiff
path: root/internal/game/render_craps_test.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-30 05:33:45 -0400
committerhistoria <[not public]>2026-09-30 05:33:45 -0400
commit0fcb03633e3008169173d76c8408f5410592b3eb (patch)
tree814797fb33a129b1c49f8ae309c6647027f5e528 /internal/game/render_craps_test.go
parent735428f0667f67c12fdf3caca872d7dc65e2ce26 (diff)
downloadthehouseoficarus-0fcb03633e3008169173d76c8408f5410592b3eb.tar.gz
feat: bank craps added to casino
Diffstat (limited to 'internal/game/render_craps_test.go')
-rw-r--r--internal/game/render_craps_test.go130
1 files changed, 130 insertions, 0 deletions
diff --git a/internal/game/render_craps_test.go b/internal/game/render_craps_test.go
new file mode 100644
index 0000000..9d75630
--- /dev/null
+++ b/internal/game/render_craps_test.go
@@ -0,0 +1,130 @@
+package game
+
+import (
+ "strings"
+ "testing"
+
+ "thehouseoficarus/internal/casino"
+ "thehouseoficarus/internal/color"
+ "thehouseoficarus/internal/combat"
+ "thehouseoficarus/internal/net"
+ "thehouseoficarus/internal/player"
+ "thehouseoficarus/internal/world"
+)
+
+func TestCrapsHalfTableGeometryAndPuck(t *testing.T) {
+ for _, unicode := range []bool{false, true} {
+ for _, point := range []int{0, 4, 5, 6, 8, 9, 10} {
+ s := &casino.CrapsSnapshot{Point: point, Field12: 3}
+ art := renderCrapsFelt(s, "none", unicode)
+ rows := strings.Split(strings.TrimSuffix(art, "\n"), "\n")
+ if len(rows) != 26 {
+ t.Fatal(len(rows))
+ }
+ for _, row := range rows {
+ if color.VisibleLen(row) != 77 {
+ t.Fatalf("misaligned (%d): %s", color.VisibleLen(row), row)
+ }
+ }
+ // Check connected box edges at the main rail and centre-action partition.
+ if unicode {
+ for _, r := range []rune{'┌', '┬', '┼', '├', '┤', '┴', '┘'} {
+ if !strings.ContainsRune(art, r) {
+ t.Fatalf("missing joint %c", r)
+ }
+ }
+ }
+ v := "|"
+ if unicode {
+ v = "│"
+ }
+ want := v + "OFF" + v
+ if point != 0 {
+ want = v + "ON " + v
+ }
+ if strings.Count(art, want) != 1 {
+ t.Fatalf("missing/duplicate puck %d: %s", point, art)
+ }
+ if !strings.Contains(art, "12 PAYS 3:1") {
+ t.Fatal("field variant invisible")
+ }
+ for _, bet := range []string{"DON'T COME", "C O M E", "FIELD", "DON'T PASS", "PASS LINE", "HARD 4", "HARD 6", "HARD 8", "HARD 10", "SEVEN", "CRAPS", "ELEVEN", "ACES", "ACE 3", "BOXCARS", "HORN", "HOP"} {
+ if strings.Count(art, bet) != 1 {
+ t.Fatalf("missing or duplicate %q", bet)
+ }
+ }
+ }
+ }
+ t.Log("\n" + renderCrapsSnapshot(&casino.CrapsSnapshot{Point: 6, Field12: 3, Dice: [2]int{3, 3}, Queue: []string{"Alice", "Bob"}, Made: []int{4, 5}, Seen: []int{2, 4, 5, 6, 9}, Phase: "betting", ShootIn: 10, DealerIn: 70}, "none", true))
+}
+func TestCrapsTrackersAndDiceStyles(t *testing.T) {
+ s := &casino.CrapsSnapshot{Made: []int{4, 6}, Seen: []int{2, 12}}
+ art := renderCrapsTrackers(s, "xterm256", true)
+ plain := plainRoulette(art)
+ for _, token := range []string{"[ 4*]", "[ 5 ]", "[ 6*]", " 2*", "12*"} {
+ if !strings.Contains(plain, token) {
+ t.Fatal("tracker missing", token)
+ }
+ }
+ if strings.Count(art, color.BgCode("xterm256", 220)) != 4 {
+ t.Fatal("wrong number of filled tracker tokens")
+ }
+ if !strings.Contains(renderCrapsFelt(s, "xterm256", true), color.BgCode("xterm256", 22)) {
+ t.Fatal("felt not dark green")
+ }
+ g := &Game{}
+ p := player.New("Alice")
+ p.Options = map[string]any{"card_style": "light", "unicode": true}
+ sess := &net.Session{Player: p}
+ s.Dice = [2]int{2, 5}
+ light := g.renderCasinoSnapshot(sess, s)
+ p.Options["card_style"] = "dark"
+ dark := g.renderCasinoSnapshot(sess, s)
+ if light == dark {
+ t.Fatal("card_style not wired to craps")
+ }
+ for a := 1; a <= 6; a++ {
+ for b := 1; b <= 6; b++ {
+ for _, unicode := range []bool{false, true} {
+ lit := renderCrapsDice([2]int{a, b}, "xterm256", unicode, "light")
+ dim := renderCrapsDice([2]int{a, b}, "xterm256", unicode, "dark")
+ if !strings.Contains(lit, color.BgCode("xterm256", 15)) || !strings.Contains(dim, color.BgCode("xterm256", 0)) {
+ t.Fatal("incorrect dice background")
+ }
+ pip := "o"
+ if unicode {
+ pip = "●"
+ }
+ if strings.Count(strings.ReplaceAll(plainRoulette(lit), "Total:", ""), pip) != a+b {
+ t.Fatal("wrong pip count", a, b)
+ }
+ if plainRoulette(lit) != plainRoulette(dim) {
+ t.Fatal("style changed dice outcome")
+ }
+ }
+ }
+ }
+}
+func TestCrapsRemindersFollowArt(t *testing.T) {
+ g := &Game{Casino: casino.NewManager(1), Combat: combat.NewTracker(), Deps: Deps{World: world.New(t.TempDir())}}
+ g.Casino.Join(1, casino.TableConfig{ID: "c", Game: casino.GameCraps}, "alice")
+ conn := &casinoTestConn{}
+ p := player.New("alice")
+ sess := &net.Session{Player: p, Conn: conn}
+ g.loggedInChars = map[string]*net.Session{"alice": sess}
+ for _, display := range []string{"full", "compact"} {
+ p.Options = map[string]any{"casino_display": display}
+ conn.data = nil
+ g.emitCasinoEvents(g.Casino.Table(1, "c").Status("alice"))
+ text := plainRoulette(string(conn.data))
+ felt, commands := strings.Index(text, "PASS LINE"), strings.Index(text, "bet <amount> on <target>")
+ if felt < 0 || commands < felt {
+ t.Fatal("reminder above graphic", text)
+ }
+ for _, old := range []string{"Next in order:", "Fire points made:", "ATS numbers:", "Phase:", "Timer: 0"} {
+ if strings.Contains(text, old) {
+ t.Fatal("raw status leaked", old)
+ }
+ }
+ }
+}