@block52/poker-vm-sdk 1.6.0 → 1.8.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/dist/index.d.ts +28 -3
- package/dist/index.esm.js +89 -8
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +89 -8
- package/dist/index.js.map +1 -1
- package/dist/pokerSolver.d.ts +15 -3
- package/dist/pokerSolver.d.ts.map +1 -1
- package/dist/pokerchain.poker.v1/types/pokerchain/poker/v1/tx.d.ts +8 -0
- package/dist/pokerchain.poker.v1/types/pokerchain/poker/v1/tx.d.ts.map +1 -1
- package/dist/signingClient.d.ts +7 -0
- package/dist/signingClient.d.ts.map +1 -1
- package/dist/types/game.d.ts +5 -1
- package/dist/types/game.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2848,6 +2848,7 @@ function createBaseMsgCreateGame() {
|
|
|
2848
2848
|
entryFee: Long.UZERO,
|
|
2849
2849
|
name: "",
|
|
2850
2850
|
bettingLimit: "",
|
|
2851
|
+
startTime: Long.ZERO,
|
|
2851
2852
|
};
|
|
2852
2853
|
}
|
|
2853
2854
|
const MsgCreateGame = {
|
|
@@ -2909,6 +2910,9 @@ const MsgCreateGame = {
|
|
|
2909
2910
|
if (message.bettingLimit !== "") {
|
|
2910
2911
|
writer.uint32(162).string(message.bettingLimit);
|
|
2911
2912
|
}
|
|
2913
|
+
if (!message.startTime.equals(Long.ZERO)) {
|
|
2914
|
+
writer.uint32(168).int64(message.startTime.toString());
|
|
2915
|
+
}
|
|
2912
2916
|
return writer;
|
|
2913
2917
|
},
|
|
2914
2918
|
decode(input, length) {
|
|
@@ -3051,6 +3055,13 @@ const MsgCreateGame = {
|
|
|
3051
3055
|
message.bettingLimit = reader.string();
|
|
3052
3056
|
continue;
|
|
3053
3057
|
}
|
|
3058
|
+
case 21: {
|
|
3059
|
+
if (tag !== 168) {
|
|
3060
|
+
break;
|
|
3061
|
+
}
|
|
3062
|
+
message.startTime = Long.fromString(reader.int64().toString());
|
|
3063
|
+
continue;
|
|
3064
|
+
}
|
|
3054
3065
|
}
|
|
3055
3066
|
if ((tag & 7) === 4 || tag === 0) {
|
|
3056
3067
|
break;
|
|
@@ -3080,6 +3091,7 @@ const MsgCreateGame = {
|
|
|
3080
3091
|
entryFee: isSet$2b(object.entryFee) ? Long.fromValue(object.entryFee) : Long.UZERO,
|
|
3081
3092
|
name: isSet$2b(object.name) ? globalThis.String(object.name) : "",
|
|
3082
3093
|
bettingLimit: isSet$2b(object.bettingLimit) ? globalThis.String(object.bettingLimit) : "",
|
|
3094
|
+
startTime: isSet$2b(object.startTime) ? Long.fromValue(object.startTime) : Long.ZERO,
|
|
3083
3095
|
};
|
|
3084
3096
|
},
|
|
3085
3097
|
toJSON(message) {
|
|
@@ -3141,6 +3153,9 @@ const MsgCreateGame = {
|
|
|
3141
3153
|
if (message.bettingLimit !== "") {
|
|
3142
3154
|
obj.bettingLimit = message.bettingLimit;
|
|
3143
3155
|
}
|
|
3156
|
+
if (!message.startTime.equals(Long.ZERO)) {
|
|
3157
|
+
obj.startTime = (message.startTime || Long.ZERO).toString();
|
|
3158
|
+
}
|
|
3144
3159
|
return obj;
|
|
3145
3160
|
},
|
|
3146
3161
|
create(base) {
|
|
@@ -3186,6 +3201,9 @@ const MsgCreateGame = {
|
|
|
3186
3201
|
message.gameVariant = object.gameVariant ?? "";
|
|
3187
3202
|
message.name = object.name ?? "";
|
|
3188
3203
|
message.bettingLimit = object.bettingLimit ?? "";
|
|
3204
|
+
message.startTime = (object.startTime !== undefined && object.startTime !== null)
|
|
3205
|
+
? Long.fromValue(object.startTime)
|
|
3206
|
+
: Long.ZERO;
|
|
3189
3207
|
message.entryFee = (object.entryFee !== undefined && object.entryFee !== null)
|
|
3190
3208
|
? Long.fromValue(object.entryFee)
|
|
3191
3209
|
: Long.UZERO;
|
|
@@ -56093,6 +56111,10 @@ exports.NonPlayerActionType = void 0;
|
|
|
56093
56111
|
// current turn. Rejected off-turn, past the deadline, or with no bank left.
|
|
56094
56112
|
NonPlayerActionType["TIME_BANK"] = "time-bank";
|
|
56095
56113
|
NonPlayerActionType["TOP_UP"] = "top-up";
|
|
56114
|
+
// Scheduled single-table tournament (poker-vm#2680): any registered player
|
|
56115
|
+
// starts the sit-and-go once gameOptions.scheduledStartTime has passed and
|
|
56116
|
+
// at least minPlayers are seated. Offered in legalActions when it is due.
|
|
56117
|
+
NonPlayerActionType["START"] = "start";
|
|
56096
56118
|
})(exports.NonPlayerActionType || (exports.NonPlayerActionType = {}));
|
|
56097
56119
|
const AllPlayerActions = { ...exports.PlayerActionType, ...exports.NonPlayerActionType };
|
|
56098
56120
|
/**
|
|
@@ -56774,6 +56796,41 @@ class PokerSolver {
|
|
|
56774
56796
|
}
|
|
56775
56797
|
return bestHand;
|
|
56776
56798
|
}
|
|
56799
|
+
/**
|
|
56800
|
+
* Find the best Omaha hand: EXACTLY 2 of the 4 hole cards and EXACTLY 3 of
|
|
56801
|
+
* the 5 board cards — C(4,2) x C(5,3) = 60 candidates, ranked like Hold'em.
|
|
56802
|
+
* Mirrors the engine's FindBestOmahaHand (poker-vm#2650).
|
|
56803
|
+
*/
|
|
56804
|
+
static findBestOmahaHand(holeCards, communityCards) {
|
|
56805
|
+
if (holeCards.length !== 4) {
|
|
56806
|
+
throw new Error("Omaha requires exactly 4 hole cards");
|
|
56807
|
+
}
|
|
56808
|
+
if (communityCards.length !== 5) {
|
|
56809
|
+
throw new Error("Omaha requires exactly 5 community cards");
|
|
56810
|
+
}
|
|
56811
|
+
let bestHand = null;
|
|
56812
|
+
for (const pair of this.getCombinationsFlexible(holeCards, 2)) {
|
|
56813
|
+
for (const triple of this.getCombinationsFlexible(communityCards, 3)) {
|
|
56814
|
+
const evaluation = this.evaluateHand([...pair, ...triple]);
|
|
56815
|
+
if (!bestHand || this.compareHands(evaluation, bestHand) > 0) {
|
|
56816
|
+
bestHand = evaluation;
|
|
56817
|
+
}
|
|
56818
|
+
}
|
|
56819
|
+
}
|
|
56820
|
+
if (!bestHand) {
|
|
56821
|
+
throw new Error("Failed to evaluate hand");
|
|
56822
|
+
}
|
|
56823
|
+
return bestHand;
|
|
56824
|
+
}
|
|
56825
|
+
/**
|
|
56826
|
+
* Best hand for a variant from hole cards and a full 5-card board.
|
|
56827
|
+
*/
|
|
56828
|
+
static bestHandForVariant(variant, holeCards, communityCards) {
|
|
56829
|
+
if (variant === exports.GameVariant.OMAHA) {
|
|
56830
|
+
return this.findBestOmahaHand(holeCards, communityCards);
|
|
56831
|
+
}
|
|
56832
|
+
return this.findBestHand([...holeCards, ...communityCards]);
|
|
56833
|
+
}
|
|
56777
56834
|
/**
|
|
56778
56835
|
* Evaluate a hand with any number of cards (2-7)
|
|
56779
56836
|
* This is useful for showing hand strength during all betting rounds
|
|
@@ -57168,12 +57225,14 @@ class PokerSolver {
|
|
|
57168
57225
|
}
|
|
57169
57226
|
/**
|
|
57170
57227
|
* Calculate win percentages for multiple players (2+) using Monte Carlo simulation
|
|
57171
|
-
* @param hands Array of hole cards for each player (each
|
|
57228
|
+
* @param hands Array of hole cards for each player (2 each for Hold'em, 4 for Omaha)
|
|
57172
57229
|
* @param communityCards Current community cards (0-5 cards)
|
|
57173
57230
|
* @param simulations Number of simulations to run (default: 10000)
|
|
57231
|
+
* @param variant The table's variant; omitted = Texas Hold'em. Omaha hands are
|
|
57232
|
+
* scored with the two-plus-three rule (ui#769).
|
|
57174
57233
|
* @returns Object containing win percentages for each player and overall tie percentage
|
|
57175
57234
|
*/
|
|
57176
|
-
static calculateMultiPlayerEquity(hands, communityCards = [], simulations = 10000) {
|
|
57235
|
+
static calculateMultiPlayerEquity(hands, communityCards = [], simulations = 10000, variant) {
|
|
57177
57236
|
// Validate inputs
|
|
57178
57237
|
if (hands.length < 2) {
|
|
57179
57238
|
throw new Error("Need at least 2 hands to calculate equity");
|
|
@@ -57181,9 +57240,10 @@ class PokerSolver {
|
|
|
57181
57240
|
if (hands.length > 10) {
|
|
57182
57241
|
throw new Error("Maximum 10 hands supported");
|
|
57183
57242
|
}
|
|
57243
|
+
const holeCount = holeCardsPerPlayer(variant);
|
|
57184
57244
|
for (let i = 0; i < hands.length; i++) {
|
|
57185
|
-
if (hands[i].length !==
|
|
57186
|
-
throw new Error(`Hand ${i} must have exactly
|
|
57245
|
+
if (hands[i].length !== holeCount) {
|
|
57246
|
+
throw new Error(`Hand ${i} must have exactly ${holeCount} cards`);
|
|
57187
57247
|
}
|
|
57188
57248
|
}
|
|
57189
57249
|
if (communityCards.length > 5) {
|
|
@@ -57210,10 +57270,7 @@ class PokerSolver {
|
|
|
57210
57270
|
// Deal remaining community cards
|
|
57211
57271
|
const fullCommunityCards = [...communityCards, ...shuffledDeck.slice(0, cardsNeeded)];
|
|
57212
57272
|
// Evaluate all hands
|
|
57213
|
-
const evaluations = hands.map(hand =>
|
|
57214
|
-
const fullHand = [...hand, ...fullCommunityCards];
|
|
57215
|
-
return this.findBestHand(fullHand);
|
|
57216
|
-
});
|
|
57273
|
+
const evaluations = hands.map(hand => this.bestHandForVariant(variant, hand, fullCommunityCards));
|
|
57217
57274
|
// Find winners using existing findWinners method
|
|
57218
57275
|
const winnerIndices = this.findWinners(evaluations);
|
|
57219
57276
|
// Update win counters
|
|
@@ -70971,6 +71028,26 @@ function gaslessFee(gasLimit = DEFAULT_GAS_LIMIT) {
|
|
|
70971
71028
|
gas: gasLimit.toString()
|
|
70972
71029
|
};
|
|
70973
71030
|
}
|
|
71031
|
+
/**
|
|
71032
|
+
* Fail fast on a sit-and-go field the chain would refuse (poker-vm#2680):
|
|
71033
|
+
* seats 2..9, min <= max, and a flexible field (min < max) needs a scheduled
|
|
71034
|
+
* start in the future. Mirrors x/poker/keeper/msg_server_create_game.go.
|
|
71035
|
+
*/
|
|
71036
|
+
function assertCreatableSngField(minPlayers, maxPlayers, sngConfig, nowSeconds = Math.floor(Date.now() / 1000)) {
|
|
71037
|
+
if (maxPlayers < 2 || maxPlayers > 9) {
|
|
71038
|
+
throw new Error(`sit-and-go maxPlayers must be 2..9; got ${maxPlayers}.`);
|
|
71039
|
+
}
|
|
71040
|
+
if (minPlayers < 2 || minPlayers > maxPlayers) {
|
|
71041
|
+
throw new Error(`sit-and-go minPlayers must be 2..maxPlayers (${maxPlayers}); got ${minPlayers}.`);
|
|
71042
|
+
}
|
|
71043
|
+
const startTime = sngConfig?.startTime;
|
|
71044
|
+
if (minPlayers !== maxPlayers && !startTime) {
|
|
71045
|
+
throw new Error("sit-and-go with minPlayers < maxPlayers needs sngConfig.startTime (a scheduled start).");
|
|
71046
|
+
}
|
|
71047
|
+
if (startTime !== undefined && startTime <= nowSeconds) {
|
|
71048
|
+
throw new Error(`sngConfig.startTime ${startTime} must be in the future (now ${nowSeconds}).`);
|
|
71049
|
+
}
|
|
71050
|
+
}
|
|
70974
71051
|
/**
|
|
70975
71052
|
* Signing Cosmos Client that extends the read-only CosmosClient with transaction capabilities
|
|
70976
71053
|
*/
|
|
@@ -71102,6 +71179,7 @@ class SigningCosmosClient extends CosmosClient {
|
|
|
71102
71179
|
if (!sngConfig.blindLevelDuration || sngConfig.blindLevelDuration <= 0) {
|
|
71103
71180
|
throw new Error(`${gameFormat} games require a positive blindLevelDuration; got ${sngConfig.blindLevelDuration}.`);
|
|
71104
71181
|
}
|
|
71182
|
+
assertCreatableSngField(minPlayers, maxPlayers, sngConfig);
|
|
71105
71183
|
}
|
|
71106
71184
|
assertCreatableBettingLimit(bettingLimit);
|
|
71107
71185
|
await this.initializeSigningClient();
|
|
@@ -71139,6 +71217,9 @@ class SigningCosmosClient extends CosmosClient {
|
|
|
71139
71217
|
// Betting structure (block52/pokerchain#407). "" = the variant's default
|
|
71140
71218
|
// on chain, and an empty proto3 string is not encoded at all.
|
|
71141
71219
|
bettingLimit: bettingLimit ?? "",
|
|
71220
|
+
// Scheduled start (poker-vm#2680), unix seconds. 0 = unscheduled, and
|
|
71221
|
+
// a zero proto3 int64 is not encoded at all.
|
|
71222
|
+
startTime: sngConfig?.startTime ? Long.fromNumber(sngConfig.startTime) : Long.ZERO,
|
|
71142
71223
|
});
|
|
71143
71224
|
// Create the transaction message
|
|
71144
71225
|
const msg = {
|