diff options
| author | historia <[not public]> | 2026-09-30 05:33:45 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-09-30 05:33:45 -0400 |
| commit | 0fcb03633e3008169173d76c8408f5410592b3eb (patch) | |
| tree | 814797fb33a129b1c49f8ae309c6647027f5e528 /internal/casino/craps_clock.go | |
| parent | 735428f0667f67c12fdf3caca872d7dc65e2ce26 (diff) | |
| download | thehouseoficarus-0fcb03633e3008169173d76c8408f5410592b3eb.tar.gz | |
feat: bank craps added to casino
Diffstat (limited to 'internal/casino/craps_clock.go')
| -rw-r--r-- | internal/casino/craps_clock.go | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/internal/casino/craps_clock.go b/internal/casino/craps_clock.go new file mode 100644 index 0000000..cb43731 --- /dev/null +++ b/internal/casino/craps_clock.go @@ -0,0 +1,120 @@ +package casino + +import ( + "fmt" + "time" +) + +const ( + crapsBetDelay = 10 * time.Second + crapsDealerDelay = 60 * time.Second + crapsAutoDelay = 3 * time.Second +) + +func crapsSeconds(d time.Duration) int { + if d <= 0 { + return 0 + } + return int((d + time.Second - 1) / time.Second) +} +func (t *crapsTable) shooter() *crapsPlayer { + if len(t.queue) == 0 { + return nil + } + return t.players.get(t.queue[0]) +} +func (t *crapsTable) hasLiveBets() bool { + for _, p := range t.players.ordered() { + if p.HasBet { + return true + } + } + return false +} +func (t *crapsTable) activePlayers() int { + n := 0 + for _, p := range t.players.ordered() { + if p.Connected && !p.SittingOut { + n++ + } + } + return n +} + +// Called under the table lock whenever seats or wagers change. Only entering +// multiplayer or starting a new round opens a window; adding bets never +// extends it. A solo player has no forced deadline at all. +func (t *crapsTable) syncRoundClock() []Event { + multi := t.activePlayers() > 1 + if !t.hasLiveBets() { + t.phase = phaseWaiting + t.roundElapsed = 0 + t.lastCall = false + t.multiplayer = multi + return nil + } + fresh := t.phase == phaseWaiting || (multi && !t.multiplayer) + t.multiplayer = multi + if fresh { + t.roundElapsed = 0 + t.lastCall = false + } + t.phase = phasePlaying + if multi && t.roundElapsed < crapsBetDelay { + t.phase = phaseBetting + } + if fresh && multi { + return []Event{t.event("{casino_emphasis}Bets open{/} — 10 seconds before the shooter can roll. Betting stays open until the dice roll.", true)} + } + return nil +} + +func (t *crapsTable) tickElapsed(elapsed time.Duration) []Event { + t.mu.Lock() + defer t.mu.Unlock() + events := t.syncRoundClock() + if elapsed <= 0 || !t.hasLiveBets() { + return events + } + t.roundElapsed += elapsed + p := t.shooter() + if p == nil { + return events + } + if p.autoRoll && p.HasBet { + p.autoElapsed += elapsed + } + if t.multiplayer && !t.lastCall && t.roundElapsed >= crapsBetDelay-3*time.Second { + t.lastCall = true + events = append(events, t.event(fmt.Sprintf("{casino_warning}Last call for bets! 3 seconds until %s can shoot!{/}", p.Name), true)) + } + if t.multiplayer && t.roundElapsed < crapsBetDelay { + return events + } + if t.phase == phaseBetting { + events = append(events, t.event(fmt.Sprintf("{casino_emphasis}%s can shoot!{/} Bets stay open until the roll. Dealer rolls in 60 seconds if needed.", p.Name), true)) + } + t.phase = phasePlaying + if (p.autoRoll && p.HasBet && p.autoElapsed >= crapsAutoDelay) || (t.multiplayer && t.roundElapsed >= crapsBetDelay+crapsDealerDelay) { + return append(events, t.roll()...) + } + return events +} + +// StopAutoRoll is atomic with ticking and does not queue a departure or touch +// any wager. A second stop, in manual mode, retains normal casino leave behavior. +func (t *Table) StopAutoRoll(name string) ([]Event, bool) { + game, ok := t.game.(*crapsTable) + if !ok { + return nil, false + } + game.mu.Lock() + defer game.mu.Unlock() + p := game.players.get(name) + if p == nil || !p.autoRoll { + return nil, false + } + p.autoRoll = false + p.autoElapsed = 0 + return []Event{game.private(name, "{casino_emphasis}Autoroll OFF{/} — manual play resumed. Your bets stay on the table.")}, true +} |
