diff options
Diffstat (limited to 'internal/casino/roulette.go')
| -rw-r--r-- | internal/casino/roulette.go | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/internal/casino/roulette.go b/internal/casino/roulette.go index 761af47..163ed20 100644 --- a/internal/casino/roulette.go +++ b/internal/casino/roulette.go @@ -482,6 +482,19 @@ func newRouletteTable(room int, cfg TableConfig, rng *rand.Rand) *rouletteTable cfg = cfg.Normalize() return &rouletteTable{tableCore: newTableCore[*roulettePlayer](&tableBase{RoomID: room, Config: cfg}), rng: rng} } + +// activePlayersLocked counts connected, non-sitting-out seats. A lone player +// never has a betting deadline; the wheel spins as soon as they wager. +func (t *rouletteTable) activePlayersLocked() int { + n := 0 + for _, p := range t.players.ordered() { + if p.Connected && !p.SittingOut { + n++ + } + } + return n +} + 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), History: append([]string(nil), t.history...)} for _, p := range t.players.ordered() { @@ -569,15 +582,24 @@ 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. 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. + // With two or more players a timed betting window lets the table bet + // together. A lone player has no time limit: once their wager lands, + // the wheel spins. 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) - events = append(events, e) + if t.activePlayersLocked() > 1 { + 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) + events = append(events, e) + } else { + t.phase = phasePlaying + t.spinRemaining = t.Config.Roulette.SpinTicks + e := t.event("No more bets! The roulette wheel spins...", true) + e.Snapshot = t.view() + events = append(events, e) + } } return events } @@ -692,6 +714,13 @@ func (t *rouletteTable) resetRound() { func (t *rouletteTable) action(name, action string) []Event { t.mu.Lock() defer t.mu.Unlock() + if action == "unbet" { + events, _ := t.unbetLocked(name) + if !anyBet(t.players.participants()) { + t.resetRound() + } + return events + } if events, ok := t.controlLocked(name, action); ok { return events } |
