diff options
Diffstat (limited to 'internal/casino/roulette.go')
| -rw-r--r-- | internal/casino/roulette.go | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/internal/casino/roulette.go b/internal/casino/roulette.go index 109306a..44c5f30 100644 --- a/internal/casino/roulette.go +++ b/internal/casino/roulette.go @@ -467,11 +467,15 @@ type roulettePlayer struct { func (p *roulettePlayer) participantPtr() *Participant { return &p.Participant } +// Keep a small, table-local window of completed spins (oldest first). +const rouletteHistoryLimit = 50 + type rouletteTable struct { tableCore[*roulettePlayer] rng *rand.Rand spinRemaining int lastResult *RouletteSnapshot + history []string } func newRouletteTable(room int, cfg TableConfig, rng *rand.Rand) *rouletteTable { @@ -479,7 +483,7 @@ func newRouletteTable(room int, cfg TableConfig, rng *rand.Rand) *rouletteTable return &rouletteTable{tableCore: newTableCore[*roulettePlayer](&tableBase{RoomID: room, Config: cfg}), rng: rng} } func (t *rouletteTable) view() *RouletteSnapshot { - s := &RouletteSnapshot{DoubleZero: t.Config.Roulette.DoubleZero, Racetrack: t.Config.Roulette.Racetrack, Phase: string(t.phase), Wheel: rouletteWheel(t.Config.Roulette.DoubleZero)} + s := &RouletteSnapshot{DoubleZero: t.Config.Roulette.DoubleZero, Racetrack: t.Config.Roulette.Racetrack, Phase: string(t.phase), Wheel: rouletteWheel(t.Config.Roulette.DoubleZero), History: append([]string(nil), t.history...)} for _, p := range t.players.ordered() { s.Players = append(s.Players, p.Name) } @@ -555,12 +559,14 @@ func (t *rouletteTable) bet(name, spot string, amount int, w Wallet) []Event { } p.HasBet, p.Wager, p.Wallet, p.lastSpot, p.lastBet, p.SittingOut = true, wager, w, spot, amount, false events := []Event{t.playerAction(name, fmt.Sprintf("%s bets %d on %s.", name, amount, spot), fmt.Sprintf("You bet %d on %s.", amount, spot))} - // Always offer a real betting phase, even with only one player. + // Always offer a real betting phase, even with only one player. The + // board is not attached here: it is sent once per round by the menu event + // (join, settlement, or an explicit "table"), so placing a wager never + // redraws it. if t.phase == phaseWaiting { t.phase = phaseBetting t.window.open(t.Config.BettingTicks) e := t.event(fmt.Sprintf("Roulette betting is open for %d ticks.", t.Config.BettingTicks), true) - e.Snapshot = t.view() events = append(events, e) } return events @@ -601,9 +607,20 @@ func (t *rouletteTable) settle() []Event { wheel := rouletteWheel(t.Config.Roulette.DoubleZero) index := t.rng.Intn(len(wheel)) pocket := wheel[index] + t.history = append(t.history, pocket) + if len(t.history) > rouletteHistoryLimit { + copy(t.history, t.history[len(t.history)-rouletteHistoryLimit:]) + t.history = t.history[:rouletteHistoryLimit] + } s := t.view() s.Phase = "result" - s.Pockets = [3]string{wheel[(index+len(wheel)-1)%len(wheel)], pocket, wheel[(index+1)%len(wheel)]} + // Show the winning pocket with two physical neighbours on each side so + // the result reads like a slice of the real wheel. + n := len(wheel) + s.Pockets = [5]string{ + wheel[(index-2+n)%n], wheel[(index-1+n)%n], pocket, + wheel[(index+1)%n], wheel[(index+2)%n], + } t.lastResult = s e := t.event("The ball lands in "+pocket+"!", true) e.Snapshot = s @@ -728,12 +745,15 @@ type RouletteSnapshot struct { // neighbours bets, so the renderer draws the racetrack panel. Racetrack bool Phase string - Pockets [3]string // physical wheel neighbors, not numerical neighbors + Pockets [5]string // winning pocket and two physical wheel neighbours each side Players []string // Wheel is the pocket order clockwise from the top; the renderer colors // and places each pocket. It carries the zero count (one or two) so the // drawn wheel always matches the configured table. Wheel []string + // History is a detached copy of the last 50 completed spins, oldest first. + // It is table-local, survives round resets, and is not persisted on restart. + History []string } func (*RouletteSnapshot) snapshot() {} |
