aboutsummaryrefslogtreecommitdiff
path: root/internal/casino/pai_gow_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/casino/pai_gow_test.go')
-rw-r--r--internal/casino/pai_gow_test.go126
1 files changed, 123 insertions, 3 deletions
diff --git a/internal/casino/pai_gow_test.go b/internal/casino/pai_gow_test.go
index 3936704..7be9e8a 100644
--- a/internal/casino/pai_gow_test.go
+++ b/internal/casino/pai_gow_test.go
@@ -675,11 +675,11 @@ func TestPaiGowUnbetAndStopRefundBeforeDeal(t *testing.T) {
tab.join("a")
tab.join("b")
tab.bet("a", "main", 10, wa)
- if events := tab.action("a", "unbet main"); !hasMessage(events, "take back") {
- t.Fatalf("unbet main failed: %+v", events)
+ if events := tab.action("a", "unbet"); !hasMessage(events, "take back") {
+ t.Fatalf("unbet failed: %+v", events)
}
if wa.chips+wa.paid != 100 || len(wa.open) != 0 || tab.phase != "waiting" || tab.player("a").main.Total != 0 {
- t.Fatalf("unbet main left state: chips=%d paid=%d phase=%s", wa.chips, wa.paid, tab.phase)
+ t.Fatalf("unbet left state: chips=%d paid=%d phase=%s", wa.chips, wa.paid, tab.phase)
}
// A side bet placed and then abandoned is returned when the seat leaves.
tab.bet("a", "fortune", 5, wa)
@@ -718,3 +718,123 @@ func TestPaiGowRefundAllReturnsSideBetsWithoutMain(t *testing.T) {
t.Fatalf("side-only refund failed: chips=%d open=%d", w.chips, len(w.open))
}
}
+
+func TestPaiGowDealtCardsSortedLowToHigh(t *testing.T) {
+ tab := pgTestTable(false)
+ w := &testWallet{chips: 100}
+ tab.join("a")
+ tab.bet("a", "", 10, w)
+ p := tab.player("a")
+ if len(p.cards) != 7 {
+ t.Fatalf("no seven-card deal: %v", p.cards)
+ }
+ for i := 1; i < len(p.cards); i++ {
+ if pgSortRank(p.cards[i-1]) > pgSortRank(p.cards[i]) {
+ t.Fatalf("cards not sorted small to large: %v", p.cards)
+ }
+ }
+}
+
+func TestPaiGowNewSideBetClearsLastRound(t *testing.T) {
+ tab := pgTestTable(false)
+ w := &testWallet{chips: 100}
+ tab.join("a")
+ tab.bet("a", "", 10, w) // a lone bettor deals at once
+ tab.action("a", "house")
+ tab.action("a", "set")
+ p := tab.player("a")
+ if p.showdown == nil {
+ t.Fatal("setup: round did not settle")
+ }
+ // A side bet for the next round must not re-show the previous result.
+ tab.bet("a", "fortune", 5, w)
+ if p.showdown != nil || p.result != "" || len(p.cards) != 0 {
+ t.Fatalf("stale round leaked into a new bet: showdown=%v result=%q cards=%d", p.showdown != nil, p.result, len(p.cards))
+ }
+}
+
+func TestPaiGowUnbetRemovesEveryWager(t *testing.T) {
+ tab := pgTestTable(false)
+ wa, _ := &testWallet{chips: 100}, &testWallet{chips: 100}
+ tab.join("a")
+ tab.join("b")
+ tab.bet("a", "fortune", 5, wa)
+ tab.bet("a", "main", 10, wa)
+ // b has not bet, so the round is still in the betting window.
+ if tab.phase != "betting" {
+ t.Fatalf("setup: wanted betting phase, got %s", tab.phase)
+ }
+ if events := tab.action("a", "unbet"); !hasMessage(events, "take back") {
+ t.Fatalf("unbet failed: %+v", events)
+ }
+ p := tab.player("a")
+ if wa.chips+wa.paid != 100 || len(wa.open) != 0 || p.main.Total != 0 || p.fortune.Total != 0 {
+ t.Fatalf("unbet left state: chips=%d paid=%d open=%d main=%d fortune=%d", wa.chips, wa.paid, len(wa.open), p.main.Total, p.fortune.Total)
+ }
+}
+
+func TestPaiGowSoloSettingNeverTimesOut(t *testing.T) {
+ cfg := TableConfig{ID: "pg", Game: GamePaiGow, PaiGow: PaiGowConfig{ActionTicks: 1}}.Normalize()
+ tab := newPaiGowTable(1, cfg, rand.New(rand.NewSource(3))).(*paiGowTable)
+ w := &testWallet{chips: 100}
+ tab.join("a")
+ tab.bet("a", "", 10, w)
+ if tab.phase != "setting" {
+ t.Fatalf("setup: wanted setting, got %s", tab.phase)
+ }
+ for i := 0; i < 5; i++ {
+ tab.tick()
+ }
+ if tab.phase != "setting" || tab.player("a").ready {
+ t.Fatalf("a lone player was timed out: phase=%s ready=%v", tab.phase, tab.player("a").ready)
+ }
+}
+
+func TestPaiGowMultiplayerTimeoutWarnsAndSets(t *testing.T) {
+ tab := pgTestTable(false) // ActionTicks 2
+ wa, wb := &testWallet{chips: 100}, &testWallet{chips: 100}
+ tab.join("a")
+ tab.join("b")
+ tab.bet("a", "main", 10, wa)
+ tab.bet("b", "main", 10, wb) // the second main wager deals
+ if tab.phase != "setting" {
+ t.Fatalf("setup: wanted setting, got %s", tab.phase)
+ }
+ tab.action("a", "house")
+ tab.action("a", "set")
+ warned := false
+ for i := 0; i < 3; i++ {
+ for _, e := range tab.tick() {
+ if e.Color == "casino_warning" && strings.Contains(e.Message, "timed out") {
+ warned = true
+ }
+ }
+ }
+ if !warned {
+ t.Fatal("multiplayer timeout did not announce the auto-set")
+ }
+ if tab.phase != "waiting" || tab.player("b").showdown == nil {
+ t.Fatal("timed-out hand was not set and settled")
+ }
+}
+
+func TestPaiGowBettingWindowTimeoutNotifiesNonBettor(t *testing.T) {
+ tab := pgTestTable(false) // BettingTicks 2
+ wa, wb := &testWallet{chips: 100}, &testWallet{chips: 100}
+ tab.join("a")
+ tab.join("b")
+ tab.join("c")
+ tab.bet("a", "main", 10, wa)
+ tab.bet("b", "main", 10, wb)
+ notified := false
+ for i := 0; i < 3; i++ {
+ for _, e := range tab.tick() {
+ if e.PrivateTo == "c" && strings.Contains(e.Message, "betting window closed") {
+ notified = true
+ }
+ }
+ }
+ if !notified {
+ t.Fatal("non-bettor was not told the betting window closed")
+ }
+}