aboutsummaryrefslogtreecommitdiff
path: root/internal/casino
diff options
context:
space:
mode:
Diffstat (limited to 'internal/casino')
-rw-r--r--internal/casino/blackjack.go9
-rw-r--r--internal/casino/blackjack_split_regression_test.go36
2 files changed, 42 insertions, 3 deletions
diff --git a/internal/casino/blackjack.go b/internal/casino/blackjack.go
index bc038c7..39146f7 100644
--- a/internal/casino/blackjack.go
+++ b/internal/casino/blackjack.go
@@ -365,12 +365,15 @@ func (t *blackjackTable) splitHand(name string, p *blackjackPlayer, hand *blackj
e.Blackjack = t.snapshot(false)
events := []Event{e}
if left.cards[0].rank == "A" {
+ // Split aces receive one card each; they only stay live when a
+ // re-split of aces is allowed and the new card is itself an ace.
left.stood = !(t.Rules.AllowsResplitAces() && left.cards[1].rank == "A")
right.stood = !(t.Rules.AllowsResplitAces() && right.cards[1].rank == "A")
- events = append(events, t.finishHand()...)
- } else {
- events = append(events, t.prompt()...)
}
+ // Route through finishHand, not a raw prompt: a split draw can already
+ // total 21 (e.g. K,K splits into A+K), and prompting a complete hand
+ // offered hit/double on an unplayable 21.
+ events = append(events, t.finishHand()...)
return events
}
diff --git a/internal/casino/blackjack_split_regression_test.go b/internal/casino/blackjack_split_regression_test.go
new file mode 100644
index 0000000..1674d40
--- /dev/null
+++ b/internal/casino/blackjack_split_regression_test.go
@@ -0,0 +1,36 @@
+package casino
+
+// Regression: a non-ace split can draw to 21 on the first hand (K,K splits
+// into A+K). finishHand must skip that complete hand instead of prompting it,
+// which offered hit/double on an unplayable 21 and stalled the round until
+// the action timer fired.
+
+import "testing"
+
+func TestBlackjackSplitTwentyOneAdvancesToNextHand(t *testing.T) {
+ table := newBlackjackTable(1, TableConfig{ID: "blackjack", Game: GameBlackjack}, newTestRand())
+ wallet := &testWallet{credits: 100}
+ table.join("alice")
+ // Dealer 17; player K,K; the split draws A (hand one) and 5 (hand two).
+ table.shoe = tableauShoe(
+ card{rank: "10"}, card{rank: "7"},
+ card{rank: "K"}, card{rank: "K"},
+ card{rank: "A"}, card{rank: "5"}, card{rank: "2"},
+ )
+ table.shoe.shuffleAt = 0
+ table.bet("alice", "", 10, wallet)
+ if events := table.action("alice", "split"); len(events) == 0 {
+ t.Fatal("split produced no events")
+ }
+ p := table.players.get("alice")
+ if len(p.hands) != 2 {
+ t.Fatalf("split failed: %+v", p.hands)
+ }
+ if total, _ := p.hands[0].total(); total != 21 {
+ t.Fatalf("fixture: first split hand totals %d, want 21", total)
+ }
+ if table.activeHand != 1 {
+ t.Fatalf("split 21 stayed active (hand %d, actions %v); the turn must advance to the second hand",
+ table.activeHand, table.availableActions(p, p.hands[table.activeHand]))
+ }
+}