@arcanahq/cardgames 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +722 -0
- package/as-test.config.js +36 -0
- package/asconfig.json +22 -0
- package/assembly/__tests__/blackjack/actions/common.spec.ts +180 -0
- package/assembly/__tests__/blackjack/actions/dealer_scenarios.spec.ts +452 -0
- package/assembly/__tests__/blackjack/actions/double.spec.ts +128 -0
- package/assembly/__tests__/blackjack/actions/edge_cases.spec.ts +1041 -0
- package/assembly/__tests__/blackjack/actions/insurance.spec.ts +39 -0
- package/assembly/__tests__/blackjack/actions/split.spec.ts +96 -0
- package/assembly/__tests__/blackjack/actions/stand.spec.ts +103 -0
- package/assembly/__tests__/blackjack/actions/surrender.spec.ts +89 -0
- package/assembly/__tests__/blackjack/actions/test.ts +18 -0
- package/assembly/__tests__/blackjack/rules.spec.ts +231 -0
- package/assembly/__tests__/deck/deck.spec.ts +551 -0
- package/assembly/__tests__/deck/shoe.spec.ts +410 -0
- package/assembly/__tests__/poker/betting_round.spec.ts +103 -0
- package/assembly/__tests__/poker/omaha.spec.ts +171 -0
- package/assembly/__tests__/poker/pots.spec.ts +255 -0
- package/assembly/__tests__/poker/showdown.spec.ts +324 -0
- package/assembly/__tests__/poker/six_plus.spec.ts +152 -0
- package/assembly/__tests__/poker/stakes.spec.ts +384 -0
- package/assembly/__tests__/poker/stud.spec.ts +190 -0
- package/assembly/__tests__/poker/test.ts +13 -0
- package/assembly/__tests__/test.ts +11 -0
- package/assembly/blackjack/actions.ts +191 -0
- package/assembly/blackjack/blackjack.ts +571 -0
- package/assembly/blackjack/rules.ts +11 -0
- package/assembly/cardgames.ts +314 -0
- package/assembly/cards.ts +314 -0
- package/assembly/cashgames/cash_game_types.ts +142 -0
- package/assembly/cashgames/cash_game_utils.ts +223 -0
- package/assembly/cashgames/index.ts +10 -0
- package/assembly/deck/deck.ts +744 -0
- package/assembly/deck/index.ts +9 -0
- package/assembly/index.ts +28 -0
- package/assembly/poker/index.ts +17 -0
- package/assembly/poker/omaha_evaluator.ts +121 -0
- package/assembly/poker/poker_game_types.ts +233 -0
- package/assembly/poker/poker_game_utils.ts +671 -0
- package/assembly/poker/showdown.ts +106 -0
- package/assembly/poker/showdown_evaluator.ts +225 -0
- package/assembly/poker/six_plus_showdown.ts +96 -0
- package/assembly/poker/stud_evaluator.ts +60 -0
- package/assembly/poker/variant_utils.ts +51 -0
- package/assembly/poker/variants.ts +182 -0
- package/assembly/poker.ts +307 -0
- package/package.json +51 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Poker Showdown Utilities
|
|
4
|
+
*
|
|
5
|
+
* Utilities for comparing multiple poker hands and determining winners
|
|
6
|
+
* Supports both 5-card and 7-card (Hold'em) hands
|
|
7
|
+
*
|
|
8
|
+
* Provides both a concrete StandardShowdownEvaluator and convenience functions
|
|
9
|
+
* that use the standard evaluator by default.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { Card, HandRank } from "../cards";
|
|
13
|
+
import { evaluateHand, compareHands, getBestFiveCards } from "../poker";
|
|
14
|
+
import { ShowdownEvaluator, ShowdownResult } from "./showdown_evaluator";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Standard showdown evaluator for traditional poker games
|
|
18
|
+
* Uses standard 52-card deck evaluation
|
|
19
|
+
*/
|
|
20
|
+
export class StandardShowdownEvaluator extends ShowdownEvaluator {
|
|
21
|
+
evaluateHand(holeCards: Card[], communityCards: Card[]): HandRank {
|
|
22
|
+
return evaluateHand(holeCards, communityCards);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getBestFiveCards(holeCards: Card[], communityCards: Card[]): Card[] {
|
|
26
|
+
return getBestFiveCards(holeCards, communityCards);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
compareHands(hand1: HandRank, hand2: HandRank): i32 {
|
|
30
|
+
return compareHands(hand1, hand2);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Default evaluator instance for convenience functions
|
|
35
|
+
const defaultEvaluator = new StandardShowdownEvaluator();
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Compare multiple poker hands and determine winners
|
|
39
|
+
* Uses the default StandardShowdownEvaluator
|
|
40
|
+
*
|
|
41
|
+
* @param holeCardsMap Map of seat ID to their hole cards (2 cards for Hold'em)
|
|
42
|
+
* @param communityCards Community cards (5 cards for Hold'em: flop + turn + river)
|
|
43
|
+
* @returns ShowdownResult with winners, hand ranks, and best 5-card hands
|
|
44
|
+
*/
|
|
45
|
+
export function compareHandsShowdown(
|
|
46
|
+
holeCardsMap: Map<i32, Card[]>,
|
|
47
|
+
communityCards: Card[]
|
|
48
|
+
): ShowdownResult {
|
|
49
|
+
return defaultEvaluator.compareHandsShowdown(holeCardsMap, communityCards);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Compare exactly 5 cards and determine winner
|
|
54
|
+
* Useful for games like 5-card draw
|
|
55
|
+
* Uses the default StandardShowdownEvaluator
|
|
56
|
+
*
|
|
57
|
+
* @param handsMap Map of seat ID to their 5-card hand
|
|
58
|
+
* @returns ShowdownResult with winners
|
|
59
|
+
*/
|
|
60
|
+
export function compareFiveCardHands(handsMap: Map<i32, Card[]>): ShowdownResult {
|
|
61
|
+
return defaultEvaluator.compareFiveCardHands(handsMap);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get hand rank for a single player
|
|
66
|
+
* Convenience function for evaluating one player's hand
|
|
67
|
+
* Uses the default StandardShowdownEvaluator
|
|
68
|
+
*
|
|
69
|
+
* @param holeCards Player's hole cards (2 cards for Hold'em)
|
|
70
|
+
* @param communityCards Community cards (5 cards for Hold'em)
|
|
71
|
+
* @returns HandRank for the player's best hand
|
|
72
|
+
*/
|
|
73
|
+
export function getPlayerHandRank(holeCards: Card[], communityCards: Card[]): HandRank {
|
|
74
|
+
return defaultEvaluator.getPlayerHandRank(holeCards, communityCards);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get best 5-card hand for a single player
|
|
79
|
+
* Convenience function for getting a player's best 5-card hand
|
|
80
|
+
* Uses the default StandardShowdownEvaluator
|
|
81
|
+
*
|
|
82
|
+
* @param holeCards Player's hole cards (2 cards for Hold'em)
|
|
83
|
+
* @param communityCards Community cards (5 cards for Hold'em)
|
|
84
|
+
* @returns Best 5-card hand
|
|
85
|
+
*/
|
|
86
|
+
export function getPlayerBestHand(holeCards: Card[], communityCards: Card[]): Card[] {
|
|
87
|
+
return defaultEvaluator.getPlayerBestHand(holeCards, communityCards);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Compare two specific hands and return winner
|
|
92
|
+
* Uses the default StandardShowdownEvaluator
|
|
93
|
+
*
|
|
94
|
+
* @param holeCards1 First player's hole cards
|
|
95
|
+
* @param holeCards2 Second player's hole cards
|
|
96
|
+
* @param communityCards Community cards
|
|
97
|
+
* @returns 1 if player 1 wins, -1 if player 2 wins, 0 if tie
|
|
98
|
+
*/
|
|
99
|
+
export function compareTwoHands(
|
|
100
|
+
holeCards1: Card[],
|
|
101
|
+
holeCards2: Card[],
|
|
102
|
+
communityCards: Card[]
|
|
103
|
+
): i32 {
|
|
104
|
+
return defaultEvaluator.compareTwoHands(holeCards1, holeCards2, communityCards);
|
|
105
|
+
}
|
|
106
|
+
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Showdown Evaluator Interface
|
|
4
|
+
*
|
|
5
|
+
* Abstract interface for evaluating poker showdowns.
|
|
6
|
+
* Allows different implementations for different poker variants
|
|
7
|
+
* (e.g., standard Hold'em, Six-plus Hold'em, etc.)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Card, HandRank } from "../cards";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Result of a showdown comparison
|
|
14
|
+
*/
|
|
15
|
+
export class ShowdownResult {
|
|
16
|
+
winners: i32[]; // Array of seat IDs that tied for the win
|
|
17
|
+
handRanks: Map<i32, HandRank>; // Map of seat ID to their hand rank
|
|
18
|
+
bestFiveCards: Map<i32, Card[]>; // Map of seat ID to their best 5-card hand
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
winners: i32[],
|
|
22
|
+
handRanks: Map<i32, HandRank>,
|
|
23
|
+
bestFiveCards: Map<i32, Card[]>
|
|
24
|
+
) {
|
|
25
|
+
this.winners = winners;
|
|
26
|
+
this.handRanks = handRanks;
|
|
27
|
+
this.bestFiveCards = bestFiveCards;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Abstract interface for showdown evaluation
|
|
33
|
+
* Implement this for different poker variants
|
|
34
|
+
*
|
|
35
|
+
* This interface is flexible enough to support:
|
|
36
|
+
* - Hold'em variants (Texas Hold'em, Six-Plus, etc.) - uses community cards
|
|
37
|
+
* - Stud variants (5-card, 7-card) - no community cards, all cards in holeCards
|
|
38
|
+
* - Omaha variants - must use specific number of hole cards
|
|
39
|
+
* - Lowball variants - lowest hand wins
|
|
40
|
+
*/
|
|
41
|
+
export abstract class ShowdownEvaluator {
|
|
42
|
+
/**
|
|
43
|
+
* Evaluate a single player's hand from hole cards and community cards
|
|
44
|
+
*
|
|
45
|
+
* For Hold'em: holeCards = 2 cards, communityCards = 5 cards
|
|
46
|
+
* For Stud: holeCards = 5 or 7 cards, communityCards = [] (empty)
|
|
47
|
+
* For Omaha: holeCards = 4 cards, communityCards = 5 cards (must use exactly 2 hole cards)
|
|
48
|
+
*
|
|
49
|
+
* @param holeCards Player's hole cards (or all cards for stud variants)
|
|
50
|
+
* @param communityCards Community cards (empty for stud variants)
|
|
51
|
+
* @returns HandRank for the player's best hand
|
|
52
|
+
*/
|
|
53
|
+
abstract evaluateHand(holeCards: Card[], communityCards: Card[]): HandRank;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get the best 5-card hand from hole cards and community cards
|
|
57
|
+
* @param holeCards Player's hole cards
|
|
58
|
+
* @param communityCards Community cards
|
|
59
|
+
* @returns Best 5-card hand
|
|
60
|
+
*/
|
|
61
|
+
abstract getBestFiveCards(holeCards: Card[], communityCards: Card[]): Card[];
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Compare two hand ranks
|
|
65
|
+
* @param hand1 First hand rank
|
|
66
|
+
* @param hand2 Second hand rank
|
|
67
|
+
* @returns -1 if hand1 < hand2, 0 if equal, 1 if hand1 > hand2
|
|
68
|
+
*/
|
|
69
|
+
abstract compareHands(hand1: HandRank, hand2: HandRank): i32;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Compare multiple poker hands and determine winners
|
|
73
|
+
* @param holeCardsMap Map of seat ID to their hole cards
|
|
74
|
+
* @param communityCards Community cards
|
|
75
|
+
* @returns ShowdownResult with winners, hand ranks, and best 5-card hands
|
|
76
|
+
*/
|
|
77
|
+
compareHandsShowdown(
|
|
78
|
+
holeCardsMap: Map<i32, Card[]>,
|
|
79
|
+
communityCards: Card[]
|
|
80
|
+
): ShowdownResult {
|
|
81
|
+
const handRanks = new Map<i32, HandRank>();
|
|
82
|
+
const bestFiveCards = new Map<i32, Card[]>();
|
|
83
|
+
const winners = new Array<i32>(0);
|
|
84
|
+
|
|
85
|
+
// Evaluate each player's hand
|
|
86
|
+
const seatIds = holeCardsMap.keys();
|
|
87
|
+
for (let i = 0; i < seatIds.length; i++) {
|
|
88
|
+
const seatId = seatIds[i];
|
|
89
|
+
const holeCards = holeCardsMap.get(seatId);
|
|
90
|
+
|
|
91
|
+
if (holeCards.length === 0) {
|
|
92
|
+
continue; // Skip empty hands
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Evaluate hand using the abstract method
|
|
96
|
+
const handRank = this.evaluateHand(holeCards, communityCards);
|
|
97
|
+
handRanks.set(seatId, handRank);
|
|
98
|
+
|
|
99
|
+
// Get best 5-card hand using the abstract method
|
|
100
|
+
const bestFive = this.getBestFiveCards(holeCards, communityCards);
|
|
101
|
+
bestFiveCards.set(seatId, bestFive);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (handRanks.size === 0) {
|
|
105
|
+
return new ShowdownResult(winners, handRanks, bestFiveCards);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Find the best hand(s)
|
|
109
|
+
let bestRank: HandRank | null = null;
|
|
110
|
+
const seatIdsForComparison = handRanks.keys();
|
|
111
|
+
|
|
112
|
+
for (let i = 0; i < seatIdsForComparison.length; i++) {
|
|
113
|
+
const seatId = seatIdsForComparison[i];
|
|
114
|
+
const rank = handRanks.get(seatId);
|
|
115
|
+
|
|
116
|
+
if (bestRank === null) {
|
|
117
|
+
bestRank = rank;
|
|
118
|
+
winners.push(seatId);
|
|
119
|
+
} else {
|
|
120
|
+
const comparison = this.compareHands(rank, bestRank);
|
|
121
|
+
if (comparison > 0) {
|
|
122
|
+
// New best hand
|
|
123
|
+
bestRank = rank;
|
|
124
|
+
winners.length = 0;
|
|
125
|
+
winners.push(seatId);
|
|
126
|
+
} else if (comparison === 0) {
|
|
127
|
+
// Tie
|
|
128
|
+
winners.push(seatId);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return new ShowdownResult(winners, handRanks, bestFiveCards);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Compare exactly 5 cards and determine winner
|
|
138
|
+
* Useful for games like 5-card draw
|
|
139
|
+
* @param handsMap Map of seat ID to their 5-card hand
|
|
140
|
+
* @returns ShowdownResult with winners
|
|
141
|
+
*/
|
|
142
|
+
compareFiveCardHands(handsMap: Map<i32, Card[]>): ShowdownResult {
|
|
143
|
+
const handRanks = new Map<i32, HandRank>();
|
|
144
|
+
const bestFiveCards = new Map<i32, Card[]>();
|
|
145
|
+
const winners = new Array<i32>(0);
|
|
146
|
+
|
|
147
|
+
// Evaluate each player's 5-card hand
|
|
148
|
+
const seatIds = handsMap.keys();
|
|
149
|
+
for (let i = 0; i < seatIds.length; i++) {
|
|
150
|
+
const seatId = seatIds[i];
|
|
151
|
+
const hand = handsMap.get(seatId);
|
|
152
|
+
|
|
153
|
+
if (hand.length !== 5) {
|
|
154
|
+
continue; // Skip invalid hands
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Evaluate 5-card hand directly (no community cards)
|
|
158
|
+
const handRank = this.evaluateHand(hand, new Array<Card>(0));
|
|
159
|
+
handRanks.set(seatId, handRank);
|
|
160
|
+
bestFiveCards.set(seatId, hand);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (handRanks.size === 0) {
|
|
164
|
+
return new ShowdownResult(winners, handRanks, bestFiveCards);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Find the best hand(s)
|
|
168
|
+
let bestRank: HandRank | null = null;
|
|
169
|
+
const seatIdsForComparison = handRanks.keys();
|
|
170
|
+
|
|
171
|
+
for (let i = 0; i < seatIdsForComparison.length; i++) {
|
|
172
|
+
const seatId = seatIdsForComparison[i];
|
|
173
|
+
const rank = handRanks.get(seatId);
|
|
174
|
+
|
|
175
|
+
if (bestRank === null) {
|
|
176
|
+
bestRank = rank;
|
|
177
|
+
winners.push(seatId);
|
|
178
|
+
} else {
|
|
179
|
+
const comparison = this.compareHands(rank, bestRank);
|
|
180
|
+
if (comparison > 0) {
|
|
181
|
+
// New best hand
|
|
182
|
+
bestRank = rank;
|
|
183
|
+
winners.length = 0;
|
|
184
|
+
winners.push(seatId);
|
|
185
|
+
} else if (comparison === 0) {
|
|
186
|
+
// Tie
|
|
187
|
+
winners.push(seatId);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return new ShowdownResult(winners, handRanks, bestFiveCards);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Get hand rank for a single player
|
|
197
|
+
* Convenience method
|
|
198
|
+
*/
|
|
199
|
+
getPlayerHandRank(holeCards: Card[], communityCards: Card[]): HandRank {
|
|
200
|
+
return this.evaluateHand(holeCards, communityCards);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get best 5-card hand for a single player
|
|
205
|
+
* Convenience method
|
|
206
|
+
*/
|
|
207
|
+
getPlayerBestHand(holeCards: Card[], communityCards: Card[]): Card[] {
|
|
208
|
+
return this.getBestFiveCards(holeCards, communityCards);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Compare two specific hands and return winner
|
|
213
|
+
* @returns 1 if hand1 wins, -1 if hand2 wins, 0 if tie
|
|
214
|
+
*/
|
|
215
|
+
compareTwoHands(
|
|
216
|
+
holeCards1: Card[],
|
|
217
|
+
holeCards2: Card[],
|
|
218
|
+
communityCards: Card[]
|
|
219
|
+
): i32 {
|
|
220
|
+
const rank1 = this.evaluateHand(holeCards1, communityCards);
|
|
221
|
+
const rank2 = this.evaluateHand(holeCards2, communityCards);
|
|
222
|
+
return this.compareHands(rank1, rank2);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Six-Plus Hold'em Showdown Evaluator
|
|
4
|
+
*
|
|
5
|
+
* Six-Plus Hold'em (also known as Short Deck Hold'em) uses a 36-card deck
|
|
6
|
+
* (removes 2-5 cards) and has different hand rankings:
|
|
7
|
+
* - Flush beats Full House
|
|
8
|
+
* - Three of a Kind beats Straight
|
|
9
|
+
*
|
|
10
|
+
* This evaluator implements the Six-Plus Hold'em hand ranking rules.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { Card, HandRank, HandType, Rank } from "../cards";
|
|
14
|
+
import { ShowdownEvaluator, ShowdownResult } from "./showdown_evaluator";
|
|
15
|
+
import { evaluateHand, getBestFiveCards } from "../poker";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Six-Plus Hold'em showdown evaluator
|
|
19
|
+
* Uses modified hand rankings for 36-card deck
|
|
20
|
+
*/
|
|
21
|
+
export class SixPlusShowdownEvaluator extends ShowdownEvaluator {
|
|
22
|
+
/**
|
|
23
|
+
* Evaluate a hand using Six-Plus Hold'em rules
|
|
24
|
+
* Hand rankings are different: Flush > Full House, Three of a Kind > Straight
|
|
25
|
+
*/
|
|
26
|
+
evaluateHand(holeCards: Card[], communityCards: Card[]): HandRank {
|
|
27
|
+
// First evaluate using standard rules
|
|
28
|
+
const standardRank = evaluateHand(holeCards, communityCards);
|
|
29
|
+
|
|
30
|
+
// Then adjust for Six-Plus Hold'em rankings
|
|
31
|
+
return this.adjustForSixPlusRanking(standardRank);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get best 5-card hand (same as standard)
|
|
36
|
+
*/
|
|
37
|
+
getBestFiveCards(holeCards: Card[], communityCards: Card[]): Card[] {
|
|
38
|
+
return getBestFiveCards(holeCards, communityCards);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Compare hands using Six-Plus Hold'em rules
|
|
43
|
+
* Override to handle Six-Plus ranking swaps
|
|
44
|
+
*/
|
|
45
|
+
compareHands(hand1: HandRank, hand2: HandRank): i32 {
|
|
46
|
+
// Get adjusted types for comparison
|
|
47
|
+
const type1 = this.getSixPlusType(hand1.handType);
|
|
48
|
+
const type2 = this.getSixPlusType(hand2.handType);
|
|
49
|
+
|
|
50
|
+
// Compare types first
|
|
51
|
+
if (type1 < type2) return -1;
|
|
52
|
+
if (type1 > type2) return 1;
|
|
53
|
+
|
|
54
|
+
// Same type, compare kickers
|
|
55
|
+
const maxLen = hand1.kickers.length > hand2.kickers.length ? hand1.kickers.length : hand2.kickers.length;
|
|
56
|
+
for (let i = 0; i < maxLen; i++) {
|
|
57
|
+
const kicker1 = i < hand1.kickers.length ? hand1.kickers[i] : 0;
|
|
58
|
+
const kicker2 = i < hand2.kickers.length ? hand2.kickers[i] : 0;
|
|
59
|
+
if (kicker1 < kicker2) return -1;
|
|
60
|
+
if (kicker1 > kicker2) return 1;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get Six-Plus Hold'em type value for comparison
|
|
68
|
+
* Returns a value where higher = better hand
|
|
69
|
+
* Hand rankings: Royal Flush > Straight Flush > Four of a Kind > Flush > Full House > Three of a Kind > Straight > Two Pair > Pair > High Card
|
|
70
|
+
*/
|
|
71
|
+
private getSixPlusType(handType: i32): i32 {
|
|
72
|
+
// Map standard types to Six-Plus ranking values
|
|
73
|
+
// Higher number = better hand
|
|
74
|
+
if (handType === HandType.ROYAL_FLUSH) return 10;
|
|
75
|
+
if (handType === HandType.STRAIGHT_FLUSH) return 9;
|
|
76
|
+
if (handType === HandType.FOUR_OF_A_KIND) return 8;
|
|
77
|
+
if (handType === HandType.FLUSH) return 7; // Flush beats Full House in Six-Plus
|
|
78
|
+
if (handType === HandType.FULL_HOUSE) return 6; // Full House loses to Flush in Six-Plus
|
|
79
|
+
if (handType === HandType.THREE_OF_A_KIND) return 5; // Three of a Kind beats Straight in Six-Plus
|
|
80
|
+
if (handType === HandType.STRAIGHT) return 4; // Straight loses to Three of a Kind in Six-Plus
|
|
81
|
+
if (handType === HandType.TWO_PAIR) return 3;
|
|
82
|
+
if (handType === HandType.PAIR) return 2;
|
|
83
|
+
return 1; // HIGH_CARD
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Adjust hand rank for Six-Plus Hold'em rules
|
|
88
|
+
* This is used for display/logging purposes
|
|
89
|
+
*/
|
|
90
|
+
private adjustForSixPlusRanking(rank: HandRank): HandRank {
|
|
91
|
+
// This method is kept for potential future use
|
|
92
|
+
// The actual comparison is handled in compareHands via getSixPlusType
|
|
93
|
+
return rank;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Stud Poker Showdown Evaluator
|
|
4
|
+
*
|
|
5
|
+
* Evaluator for 5-card and 7-card stud poker variants.
|
|
6
|
+
* In stud poker, there are no community cards - each player has their own complete hand.
|
|
7
|
+
*
|
|
8
|
+
* For 7-card stud: Players receive 7 cards and choose the best 5
|
|
9
|
+
* For 5-card stud: Players receive 5 cards (use all 5)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { Card, HandRank } from "../cards";
|
|
13
|
+
import { ShowdownEvaluator } from "./showdown_evaluator";
|
|
14
|
+
import { evaluateHand, getBestFiveCards } from "../poker";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Standard stud poker evaluator
|
|
18
|
+
* Works for both 5-card and 7-card stud
|
|
19
|
+
*/
|
|
20
|
+
export class StudShowdownEvaluator extends ShowdownEvaluator {
|
|
21
|
+
/**
|
|
22
|
+
* Evaluate a stud hand
|
|
23
|
+
* In stud, all cards are in holeCards, communityCards is empty
|
|
24
|
+
*
|
|
25
|
+
* @param holeCards All player's cards (5 for 5-card stud, 7 for 7-card stud)
|
|
26
|
+
* @param communityCards Empty array for stud variants
|
|
27
|
+
*/
|
|
28
|
+
evaluateHand(holeCards: Card[], communityCards: Card[]): HandRank {
|
|
29
|
+
// For stud, all cards are in holeCards, communityCards should be empty
|
|
30
|
+
// We can use the standard evaluator with empty community cards
|
|
31
|
+
return evaluateHand(holeCards, communityCards);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get best 5-card hand from stud cards
|
|
36
|
+
* For 5-card stud, returns all cards
|
|
37
|
+
* For 7-card stud, returns best 5 cards
|
|
38
|
+
*/
|
|
39
|
+
getBestFiveCards(holeCards: Card[], communityCards: Card[]): Card[] {
|
|
40
|
+
// For stud, all cards are in holeCards
|
|
41
|
+
if (holeCards.length === 5) {
|
|
42
|
+
// 5-card stud: use all cards
|
|
43
|
+
return holeCards;
|
|
44
|
+
} else if (holeCards.length === 7) {
|
|
45
|
+
// 7-card stud: choose best 5
|
|
46
|
+
return getBestFiveCards(holeCards, new Array<Card>(0));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Fallback: use standard logic
|
|
50
|
+
return getBestFiveCards(holeCards, communityCards);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Compare hands (same as standard)
|
|
55
|
+
*/
|
|
56
|
+
compareHands(hand1: HandRank, hand2: HandRank): i32 {
|
|
57
|
+
return hand1.compare(hand2);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Poker Variant Utilities
|
|
4
|
+
*
|
|
5
|
+
* Helper functions for working with different poker variants
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ShowdownEvaluator } from "./showdown_evaluator";
|
|
9
|
+
import { StandardShowdownEvaluator } from "./showdown";
|
|
10
|
+
import { SixPlusShowdownEvaluator } from "./six_plus_showdown";
|
|
11
|
+
import { StudShowdownEvaluator } from "./stud_evaluator";
|
|
12
|
+
import { OmahaShowdownEvaluator } from "./omaha_evaluator";
|
|
13
|
+
import { PokerVariant, PokerVariantConfig } from "./variants";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get the appropriate showdown evaluator for a poker variant
|
|
17
|
+
*
|
|
18
|
+
* @param variant Variant name (e.g., PokerVariant.TEXAS_HOLDEM)
|
|
19
|
+
* @param config Optional variant configuration
|
|
20
|
+
* @returns ShowdownEvaluator instance for the variant
|
|
21
|
+
*/
|
|
22
|
+
export function getEvaluatorForVariant(
|
|
23
|
+
variant: string,
|
|
24
|
+
config: PokerVariantConfig | null = null
|
|
25
|
+
): ShowdownEvaluator {
|
|
26
|
+
if (variant === PokerVariant.SIX_PLUS_HOLDEM || variant === PokerVariant.SHORT_DECK_HOLDEM) {
|
|
27
|
+
return new SixPlusShowdownEvaluator();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (variant === PokerVariant.SEVEN_CARD_STUD || variant === PokerVariant.FIVE_CARD_STUD || variant === PokerVariant.RAZZ) {
|
|
31
|
+
return new StudShowdownEvaluator();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (variant === PokerVariant.OMAHA || variant === PokerVariant.OMAHA_HI_LO) {
|
|
35
|
+
return new OmahaShowdownEvaluator();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Default to standard Hold'em
|
|
39
|
+
return new StandardShowdownEvaluator();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create evaluator from variant configuration
|
|
44
|
+
*
|
|
45
|
+
* @param config Poker variant configuration
|
|
46
|
+
* @returns ShowdownEvaluator instance
|
|
47
|
+
*/
|
|
48
|
+
export function createEvaluator(config: PokerVariantConfig): ShowdownEvaluator {
|
|
49
|
+
return getEvaluatorForVariant(config.variant, config);
|
|
50
|
+
}
|
|
51
|
+
|