From 79764732406d6484f67d3dec045483dcb5d08c28 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Fri, 18 Sep 2026 20:03:13 -0400 Subject: feat: better card ascii art --- internal/casino/core.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'internal/casino/core.go') diff --git a/internal/casino/core.go b/internal/casino/core.go index 85a5e28..a0ac1c8 100644 --- a/internal/casino/core.go +++ b/internal/casino/core.go @@ -127,6 +127,40 @@ func (c *tableCore[P]) refundAllLocked() []Event { return events } +// settleStakeOutcome applies one wager's outcome through the wallet and +// reports whether the settlement could NOT be made durable. It carries the +// money-critical ordering shared by every table game (documented in +// building_guide/concurrency.md): compute the payout, pay it via +// PayStakeCover BEFORE announcing the win, and only then resolve the stakes +// the settlement returned. On a persistence failure the stakes are left open +// so recovery re-applies the owed payout and a shutdown refund never returns +// them a second time; the caller must not announce a paid win and must not +// run the player-wide ResolveStakes. +// +// payoutErr is a payout-computation error (for example an overflowed +// multiplier): it is treated exactly like a persistence failure so a +// clamped or absurd amount is never paid. A nil wallet (test scaffolding) +// resolves the stakes in memory only. +func settleStakeOutcome(w Wallet, payout int, stakeIDs []string, payoutErr error) (failed bool) { + if payoutErr != nil { + return true + } + if w == nil { + return false + } + if payout > 0 { + if err := w.PayStakeCover(payout, stakeIDs); err != nil { + return true + } + } + for _, id := range stakeIDs { + if id != "" { + w.ResolveStake(id) + } + } + return false +} + // gameTitle renders a configured game name as a message heading. func gameTitle(game GameName) string { name := string(game) -- cgit v1.2.3