kaggle-environments 1.23.4__py3-none-any.whl → 1.23.6__py3-none-any.whl
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.
Potentially problematic release.
This version of kaggle-environments might be problematic. Click here for more details.
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/components/getRepeatedPokerStateForStep.js +316 -173
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/main.ts +27 -27
- kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/repeated_poker_renderer.js +22 -17
- {kaggle_environments-1.23.4.dist-info → kaggle_environments-1.23.6.dist-info}/METADATA +1 -1
- {kaggle_environments-1.23.4.dist-info → kaggle_environments-1.23.6.dist-info}/RECORD +8 -8
- {kaggle_environments-1.23.4.dist-info → kaggle_environments-1.23.6.dist-info}/WHEEL +0 -0
- {kaggle_environments-1.23.4.dist-info → kaggle_environments-1.23.6.dist-info}/entry_points.txt +0 -0
- {kaggle_environments-1.23.4.dist-info → kaggle_environments-1.23.6.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,91 +1,65 @@
|
|
|
1
|
-
|
|
2
|
-
// We will store all human-readable moves here
|
|
3
|
-
const allMoves = [];
|
|
1
|
+
const PLACEHOLDER_CARD = '2c';
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
function _getActionStringsFromACPC(bettingString, nextPlayerIndex, numPlayers = 2) {
|
|
4
|
+
const moves = [];
|
|
6
5
|
const streets = bettingString.split('/');
|
|
7
|
-
|
|
8
|
-
// Process each street's actions
|
|
9
6
|
for (let streetIndex = 0; streetIndex < streets.length; streetIndex++) {
|
|
10
7
|
const streetAction = streets[streetIndex];
|
|
11
8
|
let i = 0;
|
|
12
|
-
|
|
13
|
-
// Preflop (streetIndex 0), action is "open" due to blinds.
|
|
14
|
-
// Postflop (streetIndex > 0), action is "not open" (first player checks or bets).
|
|
15
|
-
let isAggressiveActionOpen = (streetIndex === 0);
|
|
16
|
-
|
|
17
|
-
// 4. Parse the moves within the street
|
|
18
9
|
while (i < streetAction.length) {
|
|
19
10
|
const char = streetAction[i];
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (char === 'c') {
|
|
23
|
-
// 'c' (call/check)
|
|
24
|
-
if (isAggressiveActionOpen) {
|
|
25
|
-
move = 'Call';
|
|
26
|
-
} else {
|
|
27
|
-
move = 'Check';
|
|
28
|
-
}
|
|
29
|
-
isAggressiveActionOpen = false; // 'c' never leaves action open
|
|
30
|
-
i++;
|
|
31
|
-
} else if (char === 'f') {
|
|
32
|
-
// 'f' (fold)
|
|
33
|
-
move = 'Fold';
|
|
34
|
-
isAggressiveActionOpen = false; // 'f' ends the hand
|
|
35
|
-
i++;
|
|
36
|
-
} else if (char === 'r') {
|
|
37
|
-
// 'r' (raise/bet)
|
|
11
|
+
if (char === 'r') {
|
|
38
12
|
let amount = '';
|
|
39
13
|
i++;
|
|
40
|
-
// Continue to parse all digits of the raise amount
|
|
41
14
|
while (i < streetAction.length && streetAction[i] >= '0' && streetAction[i] <= '9') {
|
|
42
15
|
amount += streetAction[i];
|
|
43
16
|
i++;
|
|
44
17
|
}
|
|
45
|
-
|
|
46
|
-
isAggressiveActionOpen = true; // 'r' always leaves action open
|
|
18
|
+
moves.push(`r${amount}`);
|
|
47
19
|
} else {
|
|
48
|
-
|
|
20
|
+
moves.push(char);
|
|
49
21
|
i++;
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// 5. Store this move in the history
|
|
54
|
-
if (move) {
|
|
55
|
-
allMoves.push(move);
|
|
56
22
|
}
|
|
57
23
|
}
|
|
58
24
|
}
|
|
59
25
|
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
const secondLastMove = allMoves.length > 1 ? allMoves[allMoves.length - 2] : null;
|
|
26
|
+
const lastMove = moves.length > 0 ? moves[moves.length - 1] : null;
|
|
27
|
+
const actionStrings = Array(numPlayers).fill('');
|
|
63
28
|
|
|
64
|
-
|
|
29
|
+
if (lastMove) {
|
|
30
|
+
if (typeof nextPlayerIndex === 'number' && nextPlayerIndex >= 0) {
|
|
31
|
+
const lastActor = (nextPlayerIndex + numPlayers - 1) % numPlayers;
|
|
32
|
+
actionStrings[lastActor] = lastMove;
|
|
33
|
+
} else {
|
|
34
|
+
const inferredActor = (moves.length - 1) % numPlayers;
|
|
35
|
+
actionStrings[inferredActor] = lastMove;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
65
38
|
|
|
66
|
-
return
|
|
39
|
+
return actionStrings;
|
|
67
40
|
}
|
|
68
41
|
|
|
69
|
-
function _parseStepHistoryData(universalPokerJSON) {
|
|
42
|
+
function _parseStepHistoryData(universalPokerJSON, nextPlayerIndex, numPlayers = 2) {
|
|
70
43
|
const result = {
|
|
71
44
|
cards: [],
|
|
72
45
|
communityCards: '',
|
|
73
46
|
bets: [],
|
|
74
|
-
|
|
47
|
+
playerActionStrings: Array(numPlayers).fill(''),
|
|
75
48
|
winOdds: [0, 0],
|
|
76
49
|
};
|
|
77
50
|
|
|
78
|
-
|
|
51
|
+
if (!universalPokerJSON) {
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
|
|
79
55
|
const lines = universalPokerJSON.acpc_state.trim().split('\n');
|
|
80
56
|
if (lines.length < 2) {
|
|
81
|
-
console.error("Invalid state string format.");
|
|
82
57
|
return result;
|
|
83
58
|
}
|
|
84
59
|
|
|
85
|
-
const stateLine = lines[0];
|
|
86
|
-
const spentLine = lines[1];
|
|
60
|
+
const stateLine = lines[0];
|
|
61
|
+
const spentLine = lines[1];
|
|
87
62
|
|
|
88
|
-
// --- Parse the Spent Line ---
|
|
89
63
|
if (spentLine) {
|
|
90
64
|
const p0BetMatch = spentLine.match(/P0:\s*(\d+)/);
|
|
91
65
|
const p1BetMatch = spentLine.match(/P1:\s*(\d+)/);
|
|
@@ -103,165 +77,334 @@ function _parseStepHistoryData(universalPokerJSON) {
|
|
|
103
77
|
result.bets = bets;
|
|
104
78
|
}
|
|
105
79
|
|
|
106
|
-
// --- Parse the State Line ---
|
|
107
80
|
if (stateLine) {
|
|
108
81
|
const stateParts = stateLine.split(':');
|
|
82
|
+
const cardString = stateParts[stateParts.length - 1];
|
|
83
|
+
const cardSegments = cardString.split('/');
|
|
109
84
|
|
|
110
|
-
// --- Parse Cards ---
|
|
111
|
-
// The card string is always the last part
|
|
112
|
-
const cardString = stateParts[stateParts.length - 1]; // example: "6cKd|AsJc/7hQh6d/2c"
|
|
113
|
-
|
|
114
|
-
// Split card string by '/' to separate hand block from board blocks
|
|
115
|
-
const cardSegments = cardString.split('/'); // example: ["6cKd|AsJc", "7hQh6d", "2c"]
|
|
116
|
-
|
|
117
|
-
// Parse the first segment (player hands)
|
|
118
85
|
if (cardSegments[0]) {
|
|
119
86
|
const playerHands = cardSegments[0].split('|');
|
|
120
87
|
if (playerHands.length >= 2) {
|
|
121
|
-
// example: "6cKd"
|
|
122
88
|
result.cards = [playerHands[0], playerHands[1]];
|
|
123
89
|
}
|
|
124
90
|
}
|
|
125
91
|
|
|
126
|
-
// The rest of the segments are community cards, one per street
|
|
127
92
|
result.communityCards = cardSegments
|
|
128
|
-
.slice(1)
|
|
129
|
-
.filter(Boolean)
|
|
130
|
-
.join('');
|
|
93
|
+
.slice(1)
|
|
94
|
+
.filter(Boolean)
|
|
95
|
+
.join('');
|
|
131
96
|
|
|
132
|
-
// --- Parse Betting String --
|
|
133
|
-
// The betting string is everything between the 2nd colon and the last colon.
|
|
134
|
-
// This handles edge cases like "STATE:0:r5c/cr11c/:cards"
|
|
135
97
|
const bettingString = stateParts.slice(2, stateParts.length - 1).join(':');
|
|
136
|
-
|
|
137
98
|
if (bettingString) {
|
|
138
|
-
result.
|
|
99
|
+
result.playerActionStrings = _getActionStringsFromACPC(
|
|
100
|
+
bettingString,
|
|
101
|
+
nextPlayerIndex,
|
|
102
|
+
numPlayers
|
|
103
|
+
);
|
|
139
104
|
}
|
|
140
105
|
}
|
|
141
106
|
|
|
142
|
-
|
|
143
|
-
const p0WinOdds = Number(
|
|
144
|
-
|
|
107
|
+
const odds = universalPokerJSON.odds || [];
|
|
108
|
+
const p0WinOdds = Number(odds[0] ?? 0).toLocaleString(undefined, {
|
|
109
|
+
style: 'percent',
|
|
110
|
+
minimumFractionDigits: 2
|
|
111
|
+
});
|
|
112
|
+
const p1WinOdds = Number(odds[1] ?? 0).toLocaleString(undefined, {
|
|
113
|
+
style: 'percent',
|
|
114
|
+
minimumFractionDigits: 2
|
|
115
|
+
});
|
|
145
116
|
result.winOdds = [p0WinOdds, p1WinOdds];
|
|
146
117
|
|
|
147
118
|
return result;
|
|
148
119
|
}
|
|
149
120
|
|
|
121
|
+
function splitCards(cardString) {
|
|
122
|
+
if (!cardString) {
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
return cardString.match(/.{1,2}/g) || [];
|
|
126
|
+
}
|
|
150
127
|
|
|
151
|
-
function
|
|
152
|
-
|
|
128
|
+
function isPlaceholderString(cardString) {
|
|
129
|
+
return typeof cardString === 'string' && /^((2c)+)$/i.test(cardString);
|
|
130
|
+
}
|
|
153
131
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
132
|
+
function sanitizeCardList(cards) {
|
|
133
|
+
return (cards || []).filter((card) => card);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function formatActionDisplay(actionString) {
|
|
137
|
+
if (!actionString) {
|
|
138
|
+
return '';
|
|
139
|
+
}
|
|
140
|
+
const playerMatch = actionString.match(/move=([^\s]+)/);
|
|
141
|
+
if (!playerMatch) {
|
|
142
|
+
return '';
|
|
143
|
+
}
|
|
144
|
+
const moveRaw = playerMatch[1];
|
|
145
|
+
const moveLower = moveRaw.toLowerCase();
|
|
146
|
+
if (moveLower.startsWith('bet') || moveLower.startsWith('raise')) {
|
|
147
|
+
const amountMatch = moveRaw.match(/\d+/);
|
|
148
|
+
return amountMatch ? `r${amountMatch[0]}` : 'r';
|
|
149
|
+
}
|
|
150
|
+
if (moveLower === 'call') {
|
|
151
|
+
return 'c';
|
|
152
|
+
}
|
|
153
|
+
if (moveLower === 'check') {
|
|
154
|
+
return 'k';
|
|
157
155
|
}
|
|
158
|
-
|
|
156
|
+
if (moveLower === 'fold') {
|
|
157
|
+
return 'f';
|
|
158
|
+
}
|
|
159
|
+
return moveRaw;
|
|
159
160
|
}
|
|
160
161
|
|
|
162
|
+
function getBlinds(configuration) {
|
|
163
|
+
const blindConfig = configuration?.openSpielGameParameters?.universal_poker_game_string?.blind;
|
|
164
|
+
if (typeof blindConfig !== 'string') {
|
|
165
|
+
return { bigBlind: null, smallBlind: null };
|
|
166
|
+
}
|
|
167
|
+
const parts = blindConfig
|
|
168
|
+
.trim()
|
|
169
|
+
.split(/\s+/)
|
|
170
|
+
.map((entry) => Number(entry))
|
|
171
|
+
.filter((n) => !Number.isNaN(n));
|
|
172
|
+
if (parts.length >= 2) {
|
|
173
|
+
return { bigBlind: parts[0], smallBlind: parts[1] };
|
|
174
|
+
}
|
|
175
|
+
return { bigBlind: null, smallBlind: null };
|
|
176
|
+
}
|
|
161
177
|
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return
|
|
178
|
+
function getCommunityCardsFromUniversal(universal, numPlayers) {
|
|
179
|
+
const parsed = _parseStepHistoryData(universal, null, numPlayers);
|
|
180
|
+
const cards = splitCards(parsed.communityCards);
|
|
181
|
+
const actual = cards.filter((card) => card && card.toLowerCase() !== PLACEHOLDER_CARD);
|
|
182
|
+
if (actual.length < 3) {
|
|
183
|
+
return [];
|
|
168
184
|
}
|
|
185
|
+
return actual;
|
|
186
|
+
}
|
|
169
187
|
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
188
|
+
function getHandCardsFromUniversal(universal, numPlayers) {
|
|
189
|
+
const parsed = _parseStepHistoryData(universal, null, numPlayers);
|
|
190
|
+
return (parsed.cards || []).map((cardString) => {
|
|
191
|
+
if (isPlaceholderString(cardString)) {
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
return sanitizeCardList(splitCards(cardString));
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function buildTimeline(environment, numPlayers) {
|
|
199
|
+
const stateHistory = environment?.info?.stateHistory || [];
|
|
200
|
+
if (!stateHistory.length) {
|
|
201
|
+
return [];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const parsedStates = stateHistory.map((entry, idx) => {
|
|
205
|
+
const outer = JSON.parse(entry);
|
|
206
|
+
return {
|
|
207
|
+
idx,
|
|
208
|
+
outer,
|
|
209
|
+
universal: JSON.parse(outer.current_universal_poker_json)
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const hands = [];
|
|
214
|
+
let currentHandNumber = parsedStates[0]?.outer?.hand_number ?? 0;
|
|
215
|
+
let currentStates = [];
|
|
216
|
+
parsedStates.forEach((stateInfo) => {
|
|
217
|
+
const handNumber = stateInfo.outer?.hand_number ?? currentHandNumber;
|
|
218
|
+
if (handNumber !== currentHandNumber) {
|
|
219
|
+
if (currentStates.length) {
|
|
220
|
+
hands.push({ handNumber: currentHandNumber, states: currentStates });
|
|
221
|
+
}
|
|
222
|
+
currentStates = [];
|
|
223
|
+
currentHandNumber = handNumber;
|
|
224
|
+
}
|
|
225
|
+
currentStates.push(stateInfo);
|
|
226
|
+
});
|
|
227
|
+
if (currentStates.length) {
|
|
228
|
+
hands.push({ handNumber: currentHandNumber, states: currentStates });
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const processedSteps = environment.__processedSteps || environment.steps || [];
|
|
232
|
+
const actionsByHand = new Map();
|
|
233
|
+
processedSteps.forEach((step) => {
|
|
234
|
+
const handNumber = step?.hand ?? 0;
|
|
235
|
+
if (!actionsByHand.has(handNumber)) {
|
|
236
|
+
actionsByHand.set(handNumber, []);
|
|
237
|
+
}
|
|
238
|
+
if (!step?.isEndState && step?.step?.action && step.step.action.submission !== -1) {
|
|
239
|
+
const actionString = step.step.action.actionString || '';
|
|
240
|
+
const playerMatch = actionString.match(/player=(\d+)/);
|
|
241
|
+
const playerIndex = playerMatch ? parseInt(playerMatch[1], 10) : null;
|
|
242
|
+
actionsByHand.get(handNumber).push({
|
|
243
|
+
playerIndex,
|
|
244
|
+
actionText: formatActionDisplay(actionString),
|
|
245
|
+
stateHistoryIndex: step.stateHistoryIndex
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
const events = [];
|
|
251
|
+
let orderCounter = 0;
|
|
252
|
+
const pushEvent = (stateIndex, event) => {
|
|
253
|
+
events.push({
|
|
254
|
+
order: orderCounter++,
|
|
255
|
+
stateIndex,
|
|
256
|
+
highlightPlayer: event.highlightPlayer,
|
|
257
|
+
actionText: event.actionText,
|
|
258
|
+
hideHoleCards: event.hideHoleCards,
|
|
259
|
+
hideCommunity: event.hideCommunity
|
|
260
|
+
});
|
|
198
261
|
};
|
|
199
262
|
|
|
200
|
-
|
|
201
|
-
|
|
263
|
+
hands.forEach(({ handNumber, states }) => {
|
|
264
|
+
if (!states.length) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
202
267
|
|
|
203
|
-
|
|
204
|
-
|
|
268
|
+
const firstState = states[0];
|
|
269
|
+
const dealer = firstState.outer?.dealer ?? 0;
|
|
270
|
+
const { bigBlind, smallBlind } = getBlinds(environment.configuration);
|
|
271
|
+
const smallBlindPlayer = dealer % numPlayers;
|
|
272
|
+
const bigBlindPlayer = (dealer + 1) % numPlayers;
|
|
273
|
+
|
|
274
|
+
pushEvent(firstState.idx, { highlightPlayer: null, actionText: '', hideHoleCards: true, hideCommunity: true });
|
|
275
|
+
pushEvent(firstState.idx, { highlightPlayer: smallBlindPlayer, actionText: smallBlind != null ? `SB ${smallBlind}` : 'SB', hideHoleCards: true, hideCommunity: true });
|
|
276
|
+
pushEvent(firstState.idx, { highlightPlayer: bigBlindPlayer, actionText: bigBlind != null ? `BB ${bigBlind}` : 'BB', hideHoleCards: true, hideCommunity: true });
|
|
277
|
+
|
|
278
|
+
const firstActionState = states.find((stateInfo) => stateInfo.universal.current_player !== -1) || firstState;
|
|
279
|
+
pushEvent(firstActionState.idx, { highlightPlayer: null, actionText: '', hideHoleCards: false, hideCommunity: true });
|
|
280
|
+
|
|
281
|
+
const actions = actionsByHand.get(handNumber) || [];
|
|
282
|
+
actions.forEach((action) => {
|
|
283
|
+
const targetIndex = typeof action.stateHistoryIndex === 'number' ? action.stateHistoryIndex : states[0].idx;
|
|
284
|
+
const postState = states.find((stateInfo) => stateInfo.idx > targetIndex) || states[states.length - 1];
|
|
285
|
+
pushEvent(postState.idx, {
|
|
286
|
+
highlightPlayer: action.playerIndex,
|
|
287
|
+
actionText: action.actionText,
|
|
288
|
+
hideHoleCards: false,
|
|
289
|
+
hideCommunity: false
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
let currentStageCommunityLength = 0;
|
|
294
|
+
states.forEach((stateInfo) => {
|
|
295
|
+
const communityCards = getCommunityCardsFromUniversal(stateInfo.universal, numPlayers);
|
|
296
|
+
const communityLength = communityCards.length;
|
|
297
|
+
if (communityLength > currentStageCommunityLength) {
|
|
298
|
+
currentStageCommunityLength = communityLength;
|
|
299
|
+
if (communityLength === 3 || communityLength === 4 || communityLength === 5) {
|
|
300
|
+
pushEvent(stateInfo.idx, {
|
|
301
|
+
highlightPlayer: null,
|
|
302
|
+
actionText: '',
|
|
303
|
+
hideHoleCards: false,
|
|
304
|
+
hideCommunity: false
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
events.sort((a, b) => a.order - b.order);
|
|
312
|
+
return events.map(({ stateIndex, highlightPlayer, actionText, hideHoleCards, hideCommunity }) => ({
|
|
313
|
+
stateIndex,
|
|
314
|
+
highlightPlayer,
|
|
315
|
+
actionText,
|
|
316
|
+
hideHoleCards: !!hideHoleCards,
|
|
317
|
+
hideCommunity: !!hideCommunity
|
|
318
|
+
}));
|
|
319
|
+
}
|
|
205
320
|
|
|
206
|
-
|
|
207
|
-
|
|
321
|
+
function getTimeline(environment, numPlayers) {
|
|
322
|
+
if (!environment.__timeline) {
|
|
323
|
+
environment.__timeline = buildTimeline(environment, numPlayers);
|
|
324
|
+
}
|
|
325
|
+
return environment.__timeline;
|
|
326
|
+
}
|
|
208
327
|
|
|
209
|
-
|
|
328
|
+
function getUniversalState(environment, index) {
|
|
329
|
+
const entry = environment?.info?.stateHistory?.[index];
|
|
330
|
+
if (!entry) {
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
const outer = JSON.parse(entry);
|
|
334
|
+
return {
|
|
335
|
+
outer,
|
|
336
|
+
universal: JSON.parse(outer.current_universal_poker_json)
|
|
337
|
+
};
|
|
338
|
+
}
|
|
210
339
|
|
|
211
|
-
|
|
212
|
-
const
|
|
340
|
+
export const getPokerStateForStep = (environment, step) => {
|
|
341
|
+
const numPlayers = 2;
|
|
342
|
+
if (!environment || !environment.info?.stateHistory) {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
213
345
|
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
346
|
+
const timeline = getTimeline(environment, numPlayers);
|
|
347
|
+
const event = timeline[step];
|
|
348
|
+
if (!event) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
const stateInfo = getUniversalState(environment, event.stateIndex);
|
|
352
|
+
if (!stateInfo) {
|
|
353
|
+
return null;
|
|
217
354
|
}
|
|
218
355
|
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
pData.isWinner = true;
|
|
257
|
-
pData.status = null;
|
|
258
|
-
} else {
|
|
259
|
-
pData.status = null;
|
|
260
|
-
}
|
|
261
|
-
} else if (pData.stack === 0 && pData.currentBet > 0) {
|
|
262
|
-
pData.status = "All-in";
|
|
356
|
+
const parsedStateHistory = _parseStepHistoryData(
|
|
357
|
+
stateInfo.universal,
|
|
358
|
+
stateInfo.universal?.current_player,
|
|
359
|
+
numPlayers
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
const startingStacks = stateInfo.universal?.starting_stacks || Array(numPlayers).fill(0);
|
|
363
|
+
const contributions = stateInfo.universal?.player_contributions || parsedStateHistory.bets || Array(numPlayers).fill(0);
|
|
364
|
+
const rewards = stateInfo.outer?.hand_returns || [];
|
|
365
|
+
const communityCards = getCommunityCardsFromUniversal(stateInfo.universal, numPlayers);
|
|
366
|
+
|
|
367
|
+
const players = Array(numPlayers)
|
|
368
|
+
.fill(null)
|
|
369
|
+
.map((_, i) => {
|
|
370
|
+
const agentName = environment?.info?.TeamNames?.[i] || `Player ${i}`;
|
|
371
|
+
const thumbnail = environment?.info?.Agents?.[i]?.ThumbnailUrl;
|
|
372
|
+
return {
|
|
373
|
+
id: `player${i}`,
|
|
374
|
+
name: agentName,
|
|
375
|
+
thumbnail,
|
|
376
|
+
stack: startingStacks[i] - (contributions[i] || 0),
|
|
377
|
+
cards: [],
|
|
378
|
+
currentBet: contributions[i] || 0,
|
|
379
|
+
isDealer: stateInfo.outer?.dealer === i,
|
|
380
|
+
isTurn: stateInfo.universal?.current_player === i,
|
|
381
|
+
isLastActor: event.highlightPlayer === i,
|
|
382
|
+
reward: rewards[0]?.[i] ?? null,
|
|
383
|
+
actionDisplayText: event.highlightPlayer === i ? event.actionText : ''
|
|
384
|
+
};
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
const handCards = getHandCardsFromUniversal(stateInfo.universal, numPlayers);
|
|
388
|
+
players.forEach((player, index) => {
|
|
389
|
+
if (event.hideHoleCards) {
|
|
390
|
+
player.cards = [];
|
|
391
|
+
} else {
|
|
392
|
+
player.cards = handCards[index] || [];
|
|
263
393
|
}
|
|
264
|
-
}
|
|
394
|
+
});
|
|
265
395
|
|
|
266
|
-
|
|
267
|
-
|
|
396
|
+
const displayCommunity = event.hideCommunity ? [] : communityCards;
|
|
397
|
+
|
|
398
|
+
return {
|
|
399
|
+
players,
|
|
400
|
+
communityCards: displayCommunity,
|
|
401
|
+
pot: contributions.reduce((sum, value) => sum + (value || 0), 0),
|
|
402
|
+
isTerminal: false,
|
|
403
|
+
rawObservation: stateInfo.universal,
|
|
404
|
+
step,
|
|
405
|
+
winOdds: parsedStateHistory.winOdds,
|
|
406
|
+
fiveCardBestHands: [],
|
|
407
|
+
currentPlayer: stateInfo.universal?.current_player ?? -1,
|
|
408
|
+
winner: -1
|
|
409
|
+
};
|
|
410
|
+
};
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import { Player, GameAdapter, ReplayData } from
|
|
2
|
-
import { renderer } from
|
|
3
|
-
import { render } from
|
|
1
|
+
import { Player, GameAdapter, ReplayData } from "@kaggle-environments/core";
|
|
2
|
+
import { renderer } from "./repeated_poker_renderer.js";
|
|
3
|
+
import { render } from "preact";
|
|
4
4
|
|
|
5
5
|
class LegacyAdapter implements GameAdapter {
|
|
6
|
-
|
|
6
|
+
private container: HTMLElement | null = null;
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
mount(container: HTMLElement): void {
|
|
9
|
+
this.container = container;
|
|
10
|
+
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
12
|
+
render(step: number, replay: ReplayData, agents: any[]): void {
|
|
13
|
+
if (!this.container) return;
|
|
14
|
+
this.container.innerHTML = ""; // Clear container before rendering
|
|
15
|
+
renderer({
|
|
16
|
+
parent: this.container,
|
|
17
|
+
environment: replay,
|
|
18
|
+
step: step,
|
|
19
|
+
agents: agents,
|
|
20
|
+
// These are probably not used by poker but good to have
|
|
21
|
+
width: this.container.clientWidth,
|
|
22
|
+
height: this.container.clientHeight,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
this.container = null;
|
|
26
|
+
unmount(): void {
|
|
27
|
+
if (this.container) {
|
|
28
|
+
render(null, this.container);
|
|
31
29
|
}
|
|
30
|
+
this.container = null;
|
|
31
|
+
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const app = document.getElementById(
|
|
34
|
+
const app = document.getElementById("app");
|
|
35
35
|
if (app) {
|
|
36
|
-
|
|
36
|
+
new Player(app, new LegacyAdapter());
|
|
37
37
|
}
|
|
@@ -151,6 +151,10 @@ export function renderer(options) {
|
|
|
151
151
|
border-color: #20BEFF;
|
|
152
152
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4), 0 0 20px rgba(32, 190, 255, 0.5);
|
|
153
153
|
}
|
|
154
|
+
.player-info-area.winner-player {
|
|
155
|
+
border-color: #FFEB70;
|
|
156
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4), 0 0 20px rgba(255, 235, 112, 0.6);
|
|
157
|
+
}
|
|
154
158
|
.player-container-0 .player-info-area { flex-direction: column-reverse; }
|
|
155
159
|
.player-name-wrapper {
|
|
156
160
|
display: flex;
|
|
@@ -226,6 +230,7 @@ export function renderer(options) {
|
|
|
226
230
|
text-align: center;
|
|
227
231
|
height: 20pxrem; line-height: 20px;
|
|
228
232
|
width: 150px;
|
|
233
|
+
height: 20px;
|
|
229
234
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
230
235
|
}
|
|
231
236
|
.blind-indicator { font-size: 0.7rem; color: #a0aec0; margin-top: 3px; }
|
|
@@ -520,7 +525,6 @@ export function renderer(options) {
|
|
|
520
525
|
// --- State Parsing ---
|
|
521
526
|
function _parseKagglePokerState(options) {
|
|
522
527
|
const { environment, step } = options;
|
|
523
|
-
const numPlayers = 2;
|
|
524
528
|
|
|
525
529
|
// --- Default State ---
|
|
526
530
|
const defaultStateUiData = {
|
|
@@ -531,7 +535,7 @@ export function renderer(options) {
|
|
|
531
535
|
};
|
|
532
536
|
|
|
533
537
|
// --- Step Validation ---
|
|
534
|
-
if (!environment || !
|
|
538
|
+
if (!environment || !step) {
|
|
535
539
|
return defaultStateUiData;
|
|
536
540
|
}
|
|
537
541
|
|
|
@@ -554,13 +558,13 @@ export function renderer(options) {
|
|
|
554
558
|
elements.gameLayout.style.transform = `scale(${scale})`;
|
|
555
559
|
}
|
|
556
560
|
|
|
557
|
-
function _renderPokerTableUI(data
|
|
561
|
+
function _renderPokerTableUI(data) {
|
|
558
562
|
if (!elements.pokerTable || !data) return;
|
|
559
563
|
const { players, communityCards, pot, isTerminal, step } = data;
|
|
560
564
|
|
|
561
565
|
// Update step counter
|
|
562
566
|
if (elements.stepCounter && step !== undefined) {
|
|
563
|
-
elements.stepCounter.textContent = `Step: ${step}`;
|
|
567
|
+
elements.stepCounter.textContent = `Debug Step: ${step}`;
|
|
564
568
|
}
|
|
565
569
|
|
|
566
570
|
if (elements.diagnosticHeader && data.rawObservation) {
|
|
@@ -596,12 +600,10 @@ export function renderer(options) {
|
|
|
596
600
|
players.forEach((playerData, index) => {
|
|
597
601
|
const playerNameElement = elements.playerNames[index];
|
|
598
602
|
if (playerNameElement) {
|
|
599
|
-
|
|
600
|
-
!playerData.isTurn && !isTerminal ? `${playerData.name} responding...` : playerData.name;
|
|
601
|
-
playerNameElement.textContent = playerNameText;
|
|
603
|
+
playerNameElement.textContent = playerData.name;
|
|
602
604
|
|
|
603
|
-
// Highlight
|
|
604
|
-
if (playerData.
|
|
605
|
+
// Highlight the player who took the most recent action
|
|
606
|
+
if (playerData.isLastActor) {
|
|
605
607
|
playerNameElement.classList.add('current-turn');
|
|
606
608
|
} else {
|
|
607
609
|
playerNameElement.classList.remove('current-turn');
|
|
@@ -647,24 +649,27 @@ export function renderer(options) {
|
|
|
647
649
|
const playerInfoArea = elements.playerInfoAreas[index];
|
|
648
650
|
if (playerInfoArea) {
|
|
649
651
|
// Highlight active player's pod
|
|
650
|
-
if (playerData.
|
|
652
|
+
if (playerData.isLastActor) {
|
|
651
653
|
playerInfoArea.classList.add('active-player');
|
|
652
654
|
} else {
|
|
653
655
|
playerInfoArea.classList.remove('active-player');
|
|
654
656
|
}
|
|
655
657
|
|
|
658
|
+
// Highlight winner's pod
|
|
659
|
+
if (playerData.isWinner) {
|
|
660
|
+
playerInfoArea.classList.add('winner-player');
|
|
661
|
+
} else {
|
|
662
|
+
playerInfoArea.classList.remove('winner-player');
|
|
663
|
+
}
|
|
664
|
+
|
|
656
665
|
playerInfoArea.querySelector('.player-stack-value').textContent = `${playerData.stack}`;
|
|
657
666
|
|
|
658
667
|
const betDisplay = playerInfoArea.querySelector('.bet-display');
|
|
659
668
|
if (playerData.currentBet > 0) {
|
|
660
|
-
if (
|
|
661
|
-
betDisplay.textContent =
|
|
669
|
+
if (playerData.actionDisplayText) {
|
|
670
|
+
betDisplay.textContent = playerData.actionDisplayText;
|
|
662
671
|
} else {
|
|
663
|
-
|
|
664
|
-
betDisplay.textContent = 'Small Blind';
|
|
665
|
-
} else {
|
|
666
|
-
betDisplay.textContent = 'Big Blind';
|
|
667
|
-
}
|
|
672
|
+
betDisplay.textContent = '';
|
|
668
673
|
}
|
|
669
674
|
betDisplay.style.display = 'block';
|
|
670
675
|
} else {
|
|
@@ -194,9 +194,9 @@ kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/
|
|
|
194
194
|
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/tsconfig.json,sha256=3X9dsQOgFw_cZ_uXByZIsGrQ5jhFfAZZL7QC6ApJWak,133
|
|
195
195
|
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/vite.config.ts,sha256=KhIjUn0WWhaoQzQ5YKuWjNndimRF0kFlYDgEnZ0cg7U,208
|
|
196
196
|
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/replays/test-replay.json,sha256=jf4ilR6SmOYPNohkIGJvmKP5Gju5FY6sfSStX1qtFZg,28919900
|
|
197
|
-
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/main.ts,sha256=
|
|
198
|
-
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/repeated_poker_renderer.js,sha256=
|
|
199
|
-
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/components/getRepeatedPokerStateForStep.js,sha256=
|
|
197
|
+
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/main.ts,sha256=Its2m61qv7RHlHUzIW6JkmySaHWq1h2bJ5sWY9woots,1000
|
|
198
|
+
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/repeated_poker_renderer.js,sha256=rEAJf5I7GKyot9H8BqyatneWvzKJFUfl7G9_hNPHA5Y,26482
|
|
199
|
+
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/components/getRepeatedPokerStateForStep.js,sha256=6nTmNT2iD2wpc0li2RU-URHM8jlKd4MRJDsVMLRcMI8,12490
|
|
200
200
|
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/components/utils.js,sha256=pXDAu4V2OppRCvMdJKQ56q1uFTJReMPIvBL6gwxIJoI,5734
|
|
201
201
|
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/images/poker_chip_1.svg,sha256=v9yCvpnaQAg8OSUJdJ5PhuTHm9_zXnww-9_7oR_DJpc,22160
|
|
202
202
|
kaggle_environments/envs/open_spiel_env/games/repeated_poker/visualizer/default/src/images/poker_chip_10.svg,sha256=z3CP2h5eUGlgBdqNoWGcioekAyPgiuzhyRNr-nbutOE,22160
|
|
@@ -279,8 +279,8 @@ kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_p
|
|
|
279
279
|
kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_parallel_voting_no_tie_exile.yaml,sha256=sfSFlFU4F7doZ-wXUWBl-JgJtmpjrLR-SpCAqKnUYeQ,3662
|
|
280
280
|
kaggle_environments/envs/werewolf/scripts/configs/run/rule_experiment/standard_parallel_voting_roundbiddiscussion.yaml,sha256=UGSLfOhmC-4pRqWsJvOtZRU0YLUuOMAGeEHtxTf3wf8,3710
|
|
281
281
|
kaggle_environments/static/player.html,sha256=Icl5yYscPe4BRoWt0HLOSRJWnznQq2MdTHHCaC2OrQQ,27753
|
|
282
|
-
kaggle_environments-1.23.
|
|
283
|
-
kaggle_environments-1.23.
|
|
284
|
-
kaggle_environments-1.23.
|
|
285
|
-
kaggle_environments-1.23.
|
|
286
|
-
kaggle_environments-1.23.
|
|
282
|
+
kaggle_environments-1.23.6.dist-info/entry_points.txt,sha256=h03sq76TdcHvXKcsre1Qm3lIni9dkWehu61xJqI-p8k,69
|
|
283
|
+
kaggle_environments-1.23.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
284
|
+
kaggle_environments-1.23.6.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
285
|
+
kaggle_environments-1.23.6.dist-info/METADATA,sha256=EQ9xVZR7e9fuaBqASk1B3rEJwOTii36QXXSU198jlLA,916
|
|
286
|
+
kaggle_environments-1.23.6.dist-info/RECORD,,
|
|
File without changes
|
{kaggle_environments-1.23.4.dist-info → kaggle_environments-1.23.6.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{kaggle_environments-1.23.4.dist-info → kaggle_environments-1.23.6.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|