aboutsummaryrefslogtreecommitdiff
path: root/internal/casino/blackjack.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-18 16:13:49 -0400
committerhistoria <[not public]>2026-09-18 16:13:49 -0400
commit194164a77eb4f2479b94c19e6f0e1278ab608781 (patch)
tree53413add8ed6f32a34d1733397e380cc98ef70ef /internal/casino/blackjack.go
parent67e01aab85607b9e601185c7d62dff576af3bb43 (diff)
downloadthehouseoficarus-194164a77eb4f2479b94c19e6f0e1278ab608781.tar.gz
fix: more casino, economy, gameplay, security, and world data hardening gaps
Diffstat (limited to 'internal/casino/blackjack.go')
-rw-r--r--internal/casino/blackjack.go50
1 files changed, 33 insertions, 17 deletions
diff --git a/internal/casino/blackjack.go b/internal/casino/blackjack.go
index 16a480c..fd0572b 100644
--- a/internal/casino/blackjack.go
+++ b/internal/casino/blackjack.go
@@ -618,7 +618,16 @@ func (t *blackjackTable) settle() []Event {
}
payoutFailed := false
for _, hand := range p.hands {
- result, payout := settleHand(hand, dealerTotal, dealerBlackjack, t.Rules)
+ result, payout, settleErr := settleHand(hand, dealerTotal, dealerBlackjack, t.Rules)
+ if settleErr != nil {
+ // A payout multiplier that overflows the credit cap is a
+ // configuration defect, not a payable win. Treat it like a
+ // failed settlement so the stake stays open for recovery to
+ // refund rather than paying a clamped/absurd amount.
+ payoutFailed = true
+ events = append(events, t.playerAction(p.Name, "Settlement unavailable.", payoutFailedMessage()))
+ continue
+ }
if payout > 0 && p.Wallet != nil {
if err := p.Wallet.PayStakeCover(payout, hand.stakes); err != nil {
// The payout could not be made durable. The journal
@@ -658,10 +667,17 @@ func (t *blackjackTable) settle() []Event {
}
if p.insurance > 0 {
insurancePayout := 0
+ var insuranceErr error
if dealerBlackjack {
- insurancePayout, _ = MulPayout(p.insurance, 1+t.Rules.InsurancePayout)
+ insurancePayout, insuranceErr = MulPayout(p.insurance, 1+t.Rules.InsurancePayout)
}
- if insurancePayout > 0 {
+ switch {
+ case insuranceErr != nil:
+ // Overflow is a config defect: leave the insurance stake open
+ // for recovery to refund instead of paying a clamped amount.
+ payoutFailed = true
+ events = append(events, t.private(p.Name, payoutFailedMessage()))
+ case insurancePayout > 0:
if err := p.Wallet.PayStakeCover(insurancePayout, []string{p.insuranceStakeID}); err != nil {
payoutFailed = true
events = append(events, t.private(p.Name, payoutFailedMessage()))
@@ -669,7 +685,7 @@ func (t *blackjackTable) settle() []Event {
p.Wallet.ResolveStake(p.insuranceStakeID)
events = append(events, t.private(p.Name, fmt.Sprintf("Insurance pays %d credits.", insurancePayout)))
}
- } else {
+ default:
// Insurance lost: its stake was consumed by the rules.
p.Wallet.ResolveStake(p.insuranceStakeID)
events = append(events, t.private(p.Name, "Insurance pays 0 credits."))
@@ -690,36 +706,36 @@ func (t *blackjackTable) settle() []Event {
return events
}
-func settleHand(hand *blackjackHand, dealerTotal int, dealerBlackjack bool, rules BlackjackConfig) (string, int) {
+func settleHand(hand *blackjackHand, dealerTotal int, dealerBlackjack bool, rules BlackjackConfig) (string, int, error) {
total, _ := hand.total()
if hand.surrendered {
- return "surrender", hand.bet / 2
+ return "surrender", hand.bet / 2, nil
}
if hand.bust {
- return "bust", 0
+ return "bust", 0, nil
}
playerBlackjack := hand.blackjack(rules)
if playerBlackjack && dealerBlackjack {
- return "push", hand.bet
+ return "push", hand.bet, nil
}
if dealerBlackjack {
- return "dealer blackjack", 0
+ return "dealer blackjack", 0, nil
}
if playerBlackjack {
// Winnings round down to whole credits; never bet less than two.
- blackjackWin, _ := MulPayout(hand.bet, rules.BlackjackPayout)
- return "blackjack", hand.bet + blackjackWin
+ blackjackWin, err := MulPayout(hand.bet, rules.BlackjackPayout)
+ if err != nil {
+ return "blackjack", 0, err
+ }
+ return "blackjack", hand.bet + blackjackWin, nil
}
if total > 21 || dealerTotal > total && dealerTotal <= 21 {
- return "loss", 0
+ return "loss", 0, nil
}
if dealerTotal == total {
- return "push", hand.bet
- }
- if dealerTotal > 21 {
- return "win", hand.bet * 2
+ return "push", hand.bet, nil
}
- return "win", hand.bet * 2
+ return "win", hand.bet * 2, nil
}
func (t *blackjackTable) resetRound() {