package game import ( "path/filepath" "strings" "testing" "thehouseoficarus/internal/casino" "thehouseoficarus/internal/color" "thehouseoficarus/internal/world" ) func TestCrapsVariantRendering(t *testing.T) { for _, v := range []string{"simplified", "high_point", "crapless", "new_york", "die_rich", "diceless"} { for _, unicode := range []bool{false, true} { for _, mode := range []string{"none", "xterm256"} { for _, style := range []string{"dark", "light"} { dice := [2]int{4, 2} if v == "die_rich" { dice[1] = 0 } text := renderCrapsSnapshot(&casino.CrapsSnapshot{Variant: v, Point: 4, Dice: dice}, mode, unicode, style) plain := plainRoulette(text) if !strings.Contains(plain, strings.ToUpper(strings.ReplaceAll(v, "_", " "))+" CRAPS") { t.Fatal(v, "title") } if v == "diceless" { for _, token := range []string{"PACK A", "PACK B", "Cards total: 6", "FIRE"} { if !strings.Contains(plain, token) { t.Fatal(v, token) } } if strings.Contains(plain, "Total:") { t.Fatal("dice rendered instead of cards") } } else { if strings.Contains(plain, "FIRE") || strings.Contains(plain, "SMALL") { t.Fatal(v, "unsupported bonus display") } } if v == "die_rich" && !strings.Contains(plain, "Total: 4") { t.Fatal("single die absent") } if mode == "xterm256" && v == "diceless" { bg := 0 if style == "light" { bg = 15 } if !strings.Contains(text, color.BgCode(mode, bg)) { t.Fatal(v, "style") } } if mode == "xterm256" && v == "die_rich" && !strings.Contains(text, color.BgCode(mode, 15)) { t.Fatal(v, "die should use a white background") } } } } } for n := 1; n <= 6; n++ { text := renderCrapsDice([2]int{n, 0}, "none", false) if strings.Count(text, "\n") != 5 { t.Fatal("single die needs three pip rows and two caps", text) } if got := strings.Count(strings.ReplaceAll(text, "Total:", ""), "o"); got != n { t.Fatalf("single die %d rendered %d pips", n, got) } } } func TestShippedCrapsGallery(t *testing.T) { w := world.New(filepath.Join("..", "..", "data")) northVariants := []string{"simplified", "high_point", "crapless"} southVariants := []string{"new_york", "die_rich", "diceless"} for i, v := range northVariants { id := 6186 + i room := loadCrapsRoom(t, w, id, v) if i > 0 && room.Exits["south"].Room != id-1 { t.Fatal(id, "missing return exit") } if i < len(northVariants)-1 && room.Exits["north"].Room != id+1 { t.Fatal(id, "unreachable next table") } } for i, v := range southVariants { id := 6189 + i room := loadCrapsRoom(t, w, id, v) if i == 0 && room.Exits["north"].Room != 6185 { t.Fatal(id, "south gallery unreachable from the bank pit") } if i > 0 && room.Exits["north"].Room != id-1 { t.Fatal(id, "missing return exit") } if i < len(southVariants)-1 && room.Exits["south"].Room != id+1 { t.Fatal(id, "unreachable next table") } } room := loadCrapsRoom(t, w, 6185, "bank") if room.Exits["west"].Room != 6182 || room.Exits["east"].Room != 6118 { t.Fatal("pit exits missing", room.Exits) } } func loadCrapsRoom(t *testing.T, w *world.World, id int, variant string) *world.Room { t.Helper() room, err := w.LoadRoom(id) if err != nil { t.Fatal(err) } if len(room.CasinoTables) != 1 { t.Fatal(id, "missing table") } cfg := room.CasinoTables[0] if cfg.Game != casino.GameCraps || cfg.Craps.Variant != variant { t.Fatal(id, cfg) } if err := cfg.Validate(); err != nil { t.Fatal(id, err) } m := casino.NewManager(1) m.Join(id, cfg, "a") if m.Table(id, cfg.ID) == nil { t.Fatal(id, "table registration") } return room }