diff options
| author | historia <[not public]> | 2026-09-29 13:28:06 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-09-29 13:28:06 -0400 |
| commit | 9803facd4368420a5dce3af59c835e13cb015cf5 (patch) | |
| tree | 4ecb75f9c88b16ae72d3573bef026d760eb8d7a8 /internal/game | |
| parent | 13db3e50cb6e29eedbf25416e5284bf08b0adefb (diff) | |
| download | thehouseoficarus-9803facd4368420a5dce3af59c835e13cb015cf5.tar.gz | |
feat: roulette in domita casino
Diffstat (limited to 'internal/game')
| -rw-r--r-- | internal/game/blackjack_rules.go | 10 | ||||
| -rw-r--r-- | internal/game/casino.go | 2 | ||||
| -rw-r--r-- | internal/game/casino_ux.go | 13 | ||||
| -rw-r--r-- | internal/game/look_target.go | 2 | ||||
| -rw-r--r-- | internal/game/roulette_test.go | 78 |
5 files changed, 94 insertions, 11 deletions
diff --git a/internal/game/blackjack_rules.go b/internal/game/blackjack_rules.go index 61aab47..b56d3ee 100644 --- a/internal/game/blackjack_rules.go +++ b/internal/game/blackjack_rules.go @@ -16,6 +16,10 @@ func (g *Game) lookBaccaratTable(sess *net.Session, target string) bool { return g.lookCardTable(sess, target, casino.GameBaccarat) } +func (g *Game) lookRouletteTable(sess *net.Session, target string) bool { + return g.lookCardTable(sess, target, casino.GameRoulette) +} + func (g *Game) lookCardTable(sess *net.Session, target string, game casino.GameName) bool { room, err := g.World.LoadRoom(sess.Player.RoomID) if err != nil { @@ -35,11 +39,7 @@ func (g *Game) lookCardTable(sess *net.Session, target string, game casino.GameN if !ok { return false } - if game == casino.GameBaccarat { - sess.WriteLine(table.Config.BaccaratRulesText()) - } else { - sess.WriteLine(table.Config.BlackjackRulesText()) - } + sess.WriteLine(table.Config.RulesText()) return true } return false diff --git a/internal/game/casino.go b/internal/game/casino.go index 579371c..857a6a8 100644 --- a/internal/game/casino.go +++ b/internal/game/casino.go @@ -673,6 +673,8 @@ func (g *Game) renderCasinoSnapshot(sess *net.Session, snapshot casino.Snapshot) size = 1 } switch s := snapshot.(type) { + case *casino.RouletteSnapshot: + return s.ASCII() case *casino.SlotSnapshot: return renderSlotSnapshot(s, mode, unicode) case *casino.BlackjackSnapshot: diff --git a/internal/game/casino_ux.go b/internal/game/casino_ux.go index fdd4533..d5ed67e 100644 --- a/internal/game/casino_ux.go +++ b/internal/game/casino_ux.go @@ -107,10 +107,7 @@ func (g *Game) executeTableStatus(sess *net.Session, args []string, _ string) { return } if len(args) > 0 && args[0] == "rules" { - text := t.Config.BlackjackRulesText() - if t.Config.Game == casino.GameBaccarat { - text = t.Config.BaccaratRulesText() - } + text := t.Config.RulesText() sess.WriteLine(g.colorize(sess, "casino_action", text)) return } @@ -154,7 +151,7 @@ func (g *Game) executeWatch(sess *net.Session, args []string, _ string) { } c, ok := resolveCasinoChoice(choices, input) if !ok { - sess.WriteLine("Choose a table to watch: watch blackjack or watch baccarat.") + sess.WriteLine("Choose a table to watch: watch blackjack, watch baccarat, or watch roulette.") return } t, ok := g.casinoTable(sess.Player.RoomID, c.address) @@ -181,6 +178,12 @@ func (g *Game) seesCasinoDetails(sess *net.Session, event casino.Event) bool { // Settlement may have removed a queued departure before these events // are delivered. Their own final cards must still be visible. switch s := event.Snapshot.(type) { + case *casino.RouletteSnapshot: + for _, name := range s.Players { + if name == sess.Player.Name { + return true + } + } case *casino.BlackjackSnapshot: for _, p := range s.Players { if p.Name == sess.Player.Name { diff --git a/internal/game/look_target.go b/internal/game/look_target.go index 76836d6..8d970e4 100644 --- a/internal/game/look_target.go +++ b/internal/game/look_target.go @@ -47,7 +47,7 @@ func (g *Game) doLookTarget(sess *net.Session, input string) { return } - if g.lookBlackjackTable(sess, lower) || g.lookBaccaratTable(sess, lower) { + if g.lookBlackjackTable(sess, lower) || g.lookBaccaratTable(sess, lower) || g.lookRouletteTable(sess, lower) { return } diff --git a/internal/game/roulette_test.go b/internal/game/roulette_test.go new file mode 100644 index 0000000..0487b0b --- /dev/null +++ b/internal/game/roulette_test.go @@ -0,0 +1,78 @@ +package game + +import ( + "strings" + "testing" + + "thehouseoficarus/internal/casino" + "thehouseoficarus/internal/net" + "thehouseoficarus/internal/player" +) + +func TestRouletteNumericTargetsAndRendering(t *testing.T) { + for _, double := range []bool{false, true} { + g := &Game{Casino: casino.NewManager(1)} + cfg := casino.TableConfig{ID: "roulette", Game: casino.GameRoulette, Roulette: casino.RouletteConfig{DoubleZero: double}} + g.Casino.Join(1, cfg, "alice") + conn := &casinoTestConn{} + sess := &net.Session{Player: player.New("alice"), Conn: conn} + g.loggedInChars = map[string]*net.Session{"alice": sess} + for _, target := range []string{"0", "17", "00", "red", "column2"} { + conn.data = nil + g.executeBet(sess, []string{"10", "on", target}, "bet 10 on "+target) + expected := "You don't have enough chips and credits" + if target == "00" && !double { + expected = "Unknown roulette target" + } + if !strings.Contains(string(conn.data), expected) { + t.Fatalf("target=%s double=%v: %s", target, double, conn.data) + } + } + conn.data = nil + g.executeTableStatus(sess, []string{"rules"}, "table rules") + if !strings.Contains(string(conn.data), "Straight numbers pay 35:1") || strings.Contains(string(conn.data), "Blackjack") { + t.Fatal("wrong rules", string(conn.data)) + } + snapshot := &casino.RouletteSnapshot{DoubleZero: double, Phase: "playing", Players: []string{"alice"}} + if got := g.renderCasinoSnapshot(sess, snapshot); got != snapshot.ASCII() { + t.Fatal("snapshot not rendered", got) + } + if !g.seesCasinoDetails(sess, casino.Event{RoomID: 1, TableID: "roulette", Snapshot: snapshot}) { + t.Fatal("player cannot see wheel") + } + } +} + +func TestCasinoTestPortalAuthoredContract(t *testing.T) { + g, rooms, _ := loadVesta(t) + found := false + for _, obj := range rooms[1001].Objects { + found = found || obj.ID == "casino_test_portal" + } + if !found { + t.Fatal("portal missing from starting room") + } + obj, err := g.ObjectStore.Load("casino_test_portal") + if err != nil { + t.Fatal(err) + } + if len(obj.OnUse) != 1 || len(obj.OnUse[0].Steps) != 2 { + t.Fatal("unexpected portal sequence") + } + steps := obj.OnUse[0].Steps + if len(steps[0].DropTable) != 1 || steps[0].DropTable[0].ItemID != "chips" || steps[0].DropTable[0].Quantity != 1000 { + t.Fatal("portal does not grant 1000 chips") + } + if steps[1].Teleport != 6100 || rooms[6100] == nil { + t.Fatal("wrong casino destination") + } + for _, id := range []int{6182, 6183} { + cfg := rooms[id].CasinoTables[0] + if err := cfg.Validate(); err != nil { + t.Fatal(err) + } + if cfg.Game != casino.GameRoulette || cfg.Roulette.DoubleZero != (id == 6183) { + t.Fatal("wrong roulette rules", id) + } + } +} |
