kaggle-environments 1.17.6__py2.py3-none-any.whl → 1.17.7__py2.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/__init__.py +1 -1
- kaggle_environments/envs/chess/chess.js +27 -23
- kaggle_environments/envs/open_spiel/games/chess/chess.js +32 -25
- kaggle_environments/envs/open_spiel/open_spiel.py +86 -42
- kaggle_environments/envs/open_spiel/test_open_spiel.py +66 -3
- kaggle_environments/static/player.html +50 -13
- {kaggle_environments-1.17.6.dist-info → kaggle_environments-1.17.7.dist-info}/METADATA +1 -1
- {kaggle_environments-1.17.6.dist-info → kaggle_environments-1.17.7.dist-info}/RECORD +12 -12
- {kaggle_environments-1.17.6.dist-info → kaggle_environments-1.17.7.dist-info}/WHEEL +1 -1
- {kaggle_environments-1.17.6.dist-info → kaggle_environments-1.17.7.dist-info}/entry_points.txt +0 -0
- {kaggle_environments-1.17.6.dist-info → kaggle_environments-1.17.7.dist-info}/licenses/LICENSE +0 -0
- {kaggle_environments-1.17.6.dist-info → kaggle_environments-1.17.7.dist-info}/top_level.txt +0 -0
kaggle_environments/__init__.py
CHANGED
|
@@ -4045,14 +4045,14 @@ async function renderer(context) {
|
|
|
4045
4045
|
|
|
4046
4046
|
// Create the Download PGN button
|
|
4047
4047
|
let downloadButton = parent.querySelector("#copy-pgn");
|
|
4048
|
-
if (!downloadButton) {
|
|
4048
|
+
if (!downloadButton && environment.steps.length) {
|
|
4049
4049
|
try {
|
|
4050
4050
|
const board = environment.steps[0][0].observation.board;
|
|
4051
4051
|
const info = environment.info;
|
|
4052
4052
|
const agent1 = info?.TeamNames?.[0] || "Agent 1";
|
|
4053
4053
|
const agent2 = info?.TeamNames?.[1] || "Agent 2";
|
|
4054
4054
|
const game = new Chess();
|
|
4055
|
-
let result = environment.rewards;
|
|
4055
|
+
let result = environment.rewards ?? [];
|
|
4056
4056
|
if (result.some((r) => r === undefined || r === null)) {
|
|
4057
4057
|
result = result.map((r) => (r === undefined || r === null ? 0 : 1));
|
|
4058
4058
|
}
|
|
@@ -4103,7 +4103,9 @@ async function renderer(context) {
|
|
|
4103
4103
|
downloadButton.style.top = "10px";
|
|
4104
4104
|
downloadButton.style.left = "10px";
|
|
4105
4105
|
downloadButton.style.zIndex = 1;
|
|
4106
|
-
|
|
4106
|
+
if(!environment.viewer) {
|
|
4107
|
+
parent.appendChild(downloadButton);
|
|
4108
|
+
}
|
|
4107
4109
|
|
|
4108
4110
|
downloadButton.addEventListener("click", async () => {
|
|
4109
4111
|
try {
|
|
@@ -4179,26 +4181,28 @@ async function renderer(context) {
|
|
|
4179
4181
|
}
|
|
4180
4182
|
}
|
|
4181
4183
|
// Draw the team names and game status
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4184
|
+
if (!environment.viewer) {
|
|
4185
|
+
const info = environment.info;
|
|
4186
|
+
const agent1 = info?.TeamNames?.[0] || "Agent 1";
|
|
4187
|
+
const agent2 = info?.TeamNames?.[1] || "Agent 2";
|
|
4188
|
+
const firstGame = environment.steps[step][0].observation.mark == "white";
|
|
4189
|
+
const fontSize = Math.round(0.33 * offset);
|
|
4190
|
+
c.font = `${fontSize}px sans-serif`;
|
|
4191
|
+
c.fillStyle = "#FFFFFF";
|
|
4192
|
+
const agent1Reward = environment.steps[step][0].reward;
|
|
4193
|
+
const agent2Reward = environment.steps[step][1].reward;
|
|
4194
|
+
const charCount = agent1.length + agent2.length + 12;
|
|
4195
|
+
const title = `${
|
|
4196
|
+
firstGame ? "\u25A0" : "\u25A1"
|
|
4197
|
+
}${agent1} (${agent1Reward}) vs ${
|
|
4198
|
+
firstGame ? "\u25A1" : "\u25A0"
|
|
4199
|
+
}${agent2} (${agent2Reward})`;
|
|
4200
|
+
c.fillText(
|
|
4201
|
+
title,
|
|
4202
|
+
offset + 4 * squareSize - Math.floor((charCount * fontSize) / 4),
|
|
4203
|
+
40
|
|
4204
|
+
);
|
|
4205
|
+
}
|
|
4202
4206
|
|
|
4203
4207
|
// Draw the Pieces
|
|
4204
4208
|
const board = environment.steps[step][0].observation.board;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
function renderer(options) {
|
|
2
|
-
const { environment, step, parent,
|
|
2
|
+
const { environment, step, parent, width = 400, height = 400 } = options;
|
|
3
3
|
|
|
4
4
|
// Chess-specific constants
|
|
5
5
|
const DEFAULT_NUM_ROWS = 8;
|
|
@@ -28,6 +28,7 @@ function renderer(options) {
|
|
|
28
28
|
let currentMessageBoxElement = typeof document !== 'undefined' ? document.getElementById('messageBox') : null;
|
|
29
29
|
let currentRendererContainer = null;
|
|
30
30
|
let currentTitleElement = null;
|
|
31
|
+
let squareSize = 50;
|
|
31
32
|
|
|
32
33
|
function _showMessage(message, type = 'info', duration = 3000) {
|
|
33
34
|
if (typeof document === 'undefined' || !document.body) return;
|
|
@@ -74,25 +75,30 @@ function renderer(options) {
|
|
|
74
75
|
fontFamily: "'Inter', sans-serif"
|
|
75
76
|
});
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
if (!environment.viewer) {
|
|
79
|
+
currentTitleElement = document.createElement('h1');
|
|
80
|
+
currentTitleElement.textContent = 'Chess';
|
|
81
|
+
// Identical styling to the Connect Four renderer's title
|
|
82
|
+
Object.assign(currentTitleElement.style, {
|
|
81
83
|
fontSize: '1.875rem',
|
|
82
84
|
fontWeight: 'bold',
|
|
83
85
|
marginBottom: '1rem',
|
|
84
86
|
textAlign: 'center',
|
|
85
87
|
color: '#2563eb'
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
});
|
|
89
|
+
currentRendererContainer.appendChild(currentTitleElement);
|
|
90
|
+
}
|
|
91
|
+
parentElementToClear.appendChild(currentRendererContainer);
|
|
88
92
|
|
|
93
|
+
const smallestParentEdge = Math.min(width, height);
|
|
94
|
+
squareSize = Math.floor(smallestParentEdge / DEFAULT_NUM_COLS);
|
|
89
95
|
currentBoardElement = document.createElement('div');
|
|
90
96
|
Object.assign(currentBoardElement.style, {
|
|
91
97
|
display: 'grid',
|
|
92
|
-
gridTemplateColumns: `repeat(${cols},
|
|
93
|
-
gridTemplateRows: `repeat(${rows},
|
|
94
|
-
width: `${cols *
|
|
95
|
-
height: `${rows *
|
|
98
|
+
gridTemplateColumns: `repeat(${cols}, ${squareSize}px)`,
|
|
99
|
+
gridTemplateRows: `repeat(${rows}, ${squareSize}px)`,
|
|
100
|
+
width: `${cols * squareSize}px`,
|
|
101
|
+
height: `${rows * squareSize}px`,
|
|
96
102
|
border: '2px solid #333'
|
|
97
103
|
});
|
|
98
104
|
|
|
@@ -101,8 +107,8 @@ function renderer(options) {
|
|
|
101
107
|
const square = document.createElement('div');
|
|
102
108
|
square.id = `cell-${r}-${c}`;
|
|
103
109
|
Object.assign(square.style, {
|
|
104
|
-
width:
|
|
105
|
-
height:
|
|
110
|
+
width: `${squareSize}px`,
|
|
111
|
+
height: `${squareSize}px`,
|
|
106
112
|
backgroundColor: (r + c) % 2 === 0 ? LIGHT_SQUARE_COLOR : DARK_SQUARE_COLOR,
|
|
107
113
|
display: 'flex',
|
|
108
114
|
alignItems: 'center',
|
|
@@ -126,7 +132,9 @@ function renderer(options) {
|
|
|
126
132
|
maxWidth: '90vw',
|
|
127
133
|
marginTop: '20px'
|
|
128
134
|
});
|
|
129
|
-
|
|
135
|
+
if (!environment.viewer) {
|
|
136
|
+
currentRendererContainer.appendChild(statusContainer);
|
|
137
|
+
}
|
|
130
138
|
|
|
131
139
|
currentStatusTextElement = document.createElement('p');
|
|
132
140
|
Object.assign(currentStatusTextElement.style, {
|
|
@@ -144,8 +152,6 @@ function renderer(options) {
|
|
|
144
152
|
});
|
|
145
153
|
statusContainer.appendChild(currentWinnerTextElement);
|
|
146
154
|
|
|
147
|
-
parentElementToClear.appendChild(currentRendererContainer);
|
|
148
|
-
|
|
149
155
|
if (typeof document !== 'undefined' && !document.body.hasAttribute('data-renderer-initialized')) {
|
|
150
156
|
document.body.setAttribute('data-renderer-initialized', 'true');
|
|
151
157
|
}
|
|
@@ -204,8 +210,9 @@ function renderer(options) {
|
|
|
204
210
|
}
|
|
205
211
|
|
|
206
212
|
|
|
207
|
-
const { board, activeColor,
|
|
213
|
+
const { board, activeColor, isTerminal, winner } = gameStateToDisplay;
|
|
208
214
|
|
|
215
|
+
const pieceSize = Math.floor(squareSize * 0.9);
|
|
209
216
|
for (let r_data = 0; r_data < displayRows; r_data++) {
|
|
210
217
|
for (let c_data = 0; c_data < displayCols; c_data++) {
|
|
211
218
|
const piece = board[r_data][c_data];
|
|
@@ -213,8 +220,8 @@ function renderer(options) {
|
|
|
213
220
|
if (squareElement && piece) {
|
|
214
221
|
const pieceImg = document.createElement('img');
|
|
215
222
|
pieceImg.src = PIECE_SVG_URLS[piece];
|
|
216
|
-
pieceImg.style.width =
|
|
217
|
-
pieceImg.style.height =
|
|
223
|
+
pieceImg.style.width = `${pieceSize}px`;
|
|
224
|
+
pieceImg.style.height = `${pieceSize}px`;
|
|
218
225
|
squareElement.appendChild(pieceImg);
|
|
219
226
|
}
|
|
220
227
|
}
|
|
@@ -222,7 +229,7 @@ function renderer(options) {
|
|
|
222
229
|
|
|
223
230
|
currentStatusTextElement.innerHTML = '';
|
|
224
231
|
currentWinnerTextElement.innerHTML = '';
|
|
225
|
-
if (
|
|
232
|
+
if (isTerminal) {
|
|
226
233
|
currentStatusTextElement.textContent = "Game Over!";
|
|
227
234
|
if (winner) {
|
|
228
235
|
if (String(winner).toLowerCase() === 'draw') {
|
|
@@ -235,8 +242,8 @@ function renderer(options) {
|
|
|
235
242
|
currentWinnerTextElement.textContent = "Game ended.";
|
|
236
243
|
}
|
|
237
244
|
} else {
|
|
238
|
-
|
|
239
|
-
|
|
245
|
+
const playerColor = String(activeColor).toLowerCase() === 'w' ? 'White' : 'Black';
|
|
246
|
+
currentStatusTextElement.innerHTML = `Current Player: <span style="font-weight: bold;">${playerColor}</span>`;
|
|
240
247
|
}
|
|
241
248
|
}
|
|
242
249
|
|
|
@@ -278,10 +285,10 @@ function renderer(options) {
|
|
|
278
285
|
const fen = observationForRenderer.observationString;
|
|
279
286
|
const parsedFen = _parseFen(fen);
|
|
280
287
|
if (parsedFen) {
|
|
281
|
-
// Assuming `
|
|
288
|
+
// Assuming `isTerminal` and `winner` are provided in the top-level observation
|
|
282
289
|
gameSpecificState = {
|
|
283
290
|
...parsedFen,
|
|
284
|
-
|
|
291
|
+
isTerminal: observationForRenderer.isTerminal,
|
|
285
292
|
winner: observationForRenderer.winner
|
|
286
293
|
};
|
|
287
294
|
}
|
|
@@ -291,4 +298,4 @@ function renderer(options) {
|
|
|
291
298
|
}
|
|
292
299
|
|
|
293
300
|
_renderBoardDisplay(gameSpecificState, DEFAULT_NUM_ROWS, DEFAULT_NUM_COLS);
|
|
294
|
-
}
|
|
301
|
+
}
|
|
@@ -19,6 +19,7 @@ DONE = "DONE"
|
|
|
19
19
|
INACTIVE = "INACTIVE"
|
|
20
20
|
ACTIVE = "ACTIVE"
|
|
21
21
|
TIMEOUT = "TIMEOUT"
|
|
22
|
+
INVALID = "INVALID"
|
|
22
23
|
|
|
23
24
|
_log = logging.getLogger(__name__)
|
|
24
25
|
_log.setLevel(logging.INFO)
|
|
@@ -41,8 +42,16 @@ for proxy_file in GAMES_DIR.glob("**/*_proxy.py"):
|
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
# --- Constants ---
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
# TODO(jhtschultz): Make this configurable per-game. For instance, in poker, a
|
|
46
|
+
# invalid action would likely result in a fold, forfeiting the player's
|
|
47
|
+
# contribution to the pot.
|
|
48
|
+
DEFAULT_INVALID_ACTION_REWARD = -1
|
|
49
|
+
|
|
50
|
+
# Can be used by agents to signal an internal error to the environement.
|
|
51
|
+
AGENT_ERROR_ACTION = -2
|
|
52
|
+
|
|
53
|
+
DEFAULT_ACT_TIMEOUT = 60 * 60 # sixty minutes
|
|
54
|
+
DEFAULT_RUN_TIMEOUT = 60 * 60 * 30 # thirty hours
|
|
46
55
|
# Buffer in addition to max game length to account for timeouts, retrys, etc.
|
|
47
56
|
DEFAULT_STEP_BUFFER = 100
|
|
48
57
|
# TODO(jhtschultz): Add individual game descriptions.
|
|
@@ -71,6 +80,11 @@ CONFIGURATION_SPEC_TEMPLATE = {
|
|
|
71
80
|
"type": "object",
|
|
72
81
|
"default": {}
|
|
73
82
|
},
|
|
83
|
+
"metadata": {
|
|
84
|
+
"description": "Arbitrary metadata.",
|
|
85
|
+
"type": "object",
|
|
86
|
+
"default": {}
|
|
87
|
+
},
|
|
74
88
|
}
|
|
75
89
|
|
|
76
90
|
OBSERVATION_SPEC_TEMPLATE = {
|
|
@@ -113,6 +127,10 @@ OBSERVATION_SPEC_TEMPLATE = {
|
|
|
113
127
|
"description": "Boolean indicating game end.",
|
|
114
128
|
"type": "boolean"
|
|
115
129
|
},
|
|
130
|
+
"serializedGameAndState": {
|
|
131
|
+
"description": "Enables reconstructing the Game and State objects.",
|
|
132
|
+
"type": "string"
|
|
133
|
+
},
|
|
116
134
|
"remainingOverageTime": 60,
|
|
117
135
|
"step": 0
|
|
118
136
|
},
|
|
@@ -171,19 +189,6 @@ def interpreter(
|
|
|
171
189
|
os_game = env.os_game
|
|
172
190
|
os_state = env.os_state
|
|
173
191
|
num_players = os_game.num_players()
|
|
174
|
-
statuses = [
|
|
175
|
-
kaggle_state[player_id].status for player_id in range(num_players)
|
|
176
|
-
]
|
|
177
|
-
if not any(status == ACTIVE for status in statuses):
|
|
178
|
-
for player_id in range(num_players):
|
|
179
|
-
p = kaggle_state[player_id]
|
|
180
|
-
if p.status in [ERROR, TIMEOUT]:
|
|
181
|
-
# TODO: properly set the reward per game
|
|
182
|
-
p.reward = -1
|
|
183
|
-
elif p.status in [INACTIVE]:
|
|
184
|
-
p.reward = 1
|
|
185
|
-
p.status = DONE
|
|
186
|
-
return;
|
|
187
192
|
|
|
188
193
|
# TODO(jhtschultz): Test reset behavior.
|
|
189
194
|
is_initial_step = len(env.steps) == 1
|
|
@@ -193,31 +198,36 @@ def interpreter(
|
|
|
193
198
|
|
|
194
199
|
# --- Apply agent action ---
|
|
195
200
|
acting_agent = os_state.current_player()
|
|
196
|
-
action_submitted = None
|
|
197
|
-
|
|
201
|
+
action_submitted: int | None = None
|
|
202
|
+
action_submitted_to_string: str | None = None
|
|
203
|
+
action_applied: int | None = None
|
|
204
|
+
move_duration: float | None = None
|
|
198
205
|
if is_initial_step:
|
|
199
206
|
pass
|
|
200
207
|
elif 0 <= acting_agent < num_players:
|
|
201
|
-
if kaggle_state[acting_agent]
|
|
208
|
+
if kaggle_state[acting_agent]["status"] != "ACTIVE":
|
|
202
209
|
pass
|
|
203
210
|
else:
|
|
204
|
-
action_submitted = kaggle_state[acting_agent]
|
|
211
|
+
action_submitted = kaggle_state[acting_agent]["action"]["submission"]
|
|
205
212
|
if action_submitted in os_state.legal_actions():
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
kaggle_state[acting_agent].status = "ERROR"
|
|
214
|
-
else:
|
|
215
|
-
kaggle_state[acting_agent].status = "INVALID"
|
|
216
|
-
if "duration" in logs[acting_agent]:
|
|
217
|
-
move_duration = round(logs[acting_agent]["duration"], 3)
|
|
218
|
-
env.info["moveDurations"].append(move_duration)
|
|
213
|
+
action_submitted_to_string = os_state.action_to_string(action_submitted)
|
|
214
|
+
os_state.apply_action(action_submitted)
|
|
215
|
+
action_applied = action_submitted
|
|
216
|
+
env.info['actionHistory'].append(str(action_applied))
|
|
217
|
+
env.info['stateHistory'].append(str(os_state))
|
|
218
|
+
elif action_submitted == AGENT_ERROR_ACTION:
|
|
219
|
+
kaggle_state[acting_agent]["status"] = "ERROR"
|
|
219
220
|
else:
|
|
220
|
-
|
|
221
|
+
kaggle_state[acting_agent]["status"] = "INVALID"
|
|
222
|
+
try:
|
|
223
|
+
if "duration" in logs[acting_agent]:
|
|
224
|
+
move_duration = round(logs[acting_agent]["duration"], 3)
|
|
225
|
+
env.info["moveDurations"].append(move_duration)
|
|
226
|
+
else:
|
|
227
|
+
env.info["moveDurations"].append(None)
|
|
228
|
+
except Exception:
|
|
229
|
+
pass # No logs when stepping the env manually.
|
|
230
|
+
|
|
221
231
|
elif acting_agent == pyspiel.PlayerId.SIMULTANEOUS:
|
|
222
232
|
raise NotImplementedError
|
|
223
233
|
elif acting_agent == pyspiel.PlayerId.TERMINAL:
|
|
@@ -236,10 +246,36 @@ def interpreter(
|
|
|
236
246
|
env.info['stateHistory'].append(str(os_state))
|
|
237
247
|
|
|
238
248
|
# --- Update agent states ---
|
|
249
|
+
agent_error = any(
|
|
250
|
+
kaggle_state[player_id]["status"] in ["TIMEOUT", "ERROR"]
|
|
251
|
+
for player_id in range(num_players)
|
|
252
|
+
)
|
|
253
|
+
if agent_error:
|
|
254
|
+
_log.info("AGENT ERROR DETECTED")
|
|
255
|
+
|
|
256
|
+
invalid_action = any(
|
|
257
|
+
kaggle_state[player_id]["status"] == "INVALID"
|
|
258
|
+
for player_id in range(num_players)
|
|
259
|
+
)
|
|
260
|
+
if invalid_action:
|
|
261
|
+
_log.info("INVALID ACTION DETECTED")
|
|
262
|
+
|
|
263
|
+
status: str | None = None
|
|
239
264
|
for player_id, agent_state in enumerate(kaggle_state):
|
|
240
265
|
reward = None
|
|
241
|
-
if
|
|
242
|
-
|
|
266
|
+
if agent_error:
|
|
267
|
+
# Set all agent statuses to ERROR in order not to score episode. Preserve
|
|
268
|
+
# TIMEOUT which has the same effect.
|
|
269
|
+
if agent_state["status"] == "TIMEOUT":
|
|
270
|
+
status = "TIMEOUT"
|
|
271
|
+
else:
|
|
272
|
+
status = "ERROR"
|
|
273
|
+
elif invalid_action:
|
|
274
|
+
if agent_state["status"] == "INVALID":
|
|
275
|
+
reward = DEFAULT_INVALID_ACTION_REWARD
|
|
276
|
+
else:
|
|
277
|
+
reward = -DEFAULT_INVALID_ACTION_REWARD
|
|
278
|
+
status = "DONE"
|
|
243
279
|
elif os_state.is_terminal():
|
|
244
280
|
status = "DONE"
|
|
245
281
|
reward = os_state.returns()[player_id]
|
|
@@ -251,11 +287,17 @@ def interpreter(
|
|
|
251
287
|
)
|
|
252
288
|
else:
|
|
253
289
|
status = "INACTIVE"
|
|
290
|
+
assert status is not None
|
|
254
291
|
|
|
255
292
|
info_dict = {}
|
|
256
293
|
if acting_agent == player_id:
|
|
257
294
|
info_dict["actionSubmitted"] = action_submitted
|
|
295
|
+
info_dict["actionSubmittedToString"] = action_submitted_to_string
|
|
258
296
|
info_dict["actionApplied"] = action_applied
|
|
297
|
+
info_dict["timeTaken"] = move_duration
|
|
298
|
+
info_dict[
|
|
299
|
+
"agentSelfReportedStatus"
|
|
300
|
+
] = kaggle_state[acting_agent]["action"].get("status") if kaggle_state[acting_agent]["action"] else "unknown"
|
|
259
301
|
|
|
260
302
|
obs_update_dict = {
|
|
261
303
|
"observationString": os_state.observation_string(player_id),
|
|
@@ -267,14 +309,17 @@ def interpreter(
|
|
|
267
309
|
"currentPlayer": os_state.current_player(),
|
|
268
310
|
"playerId": player_id,
|
|
269
311
|
"isTerminal": os_state.is_terminal(),
|
|
312
|
+
"serializedGameAndState": pyspiel.serialize_game_and_state(
|
|
313
|
+
os_game, os_state
|
|
314
|
+
),
|
|
270
315
|
}
|
|
271
316
|
|
|
272
317
|
# Apply updates
|
|
273
318
|
for k, v in obs_update_dict.items():
|
|
274
319
|
setattr(agent_state.observation, k, v)
|
|
275
|
-
agent_state
|
|
276
|
-
agent_state
|
|
277
|
-
agent_state
|
|
320
|
+
agent_state["reward"] = reward
|
|
321
|
+
agent_state["info"] = info_dict
|
|
322
|
+
agent_state["status"] = status
|
|
278
323
|
|
|
279
324
|
return kaggle_state
|
|
280
325
|
|
|
@@ -400,14 +445,13 @@ def _build_env(game_string: str) -> dict[str, Any]:
|
|
|
400
445
|
env_spec["title"] = f"Open Spiel: {short_name}"
|
|
401
446
|
env_spec["agents"] = [game.num_players()]
|
|
402
447
|
|
|
403
|
-
env_config =
|
|
404
|
-
env_spec["configuration"] = env_config
|
|
448
|
+
env_config = env_spec["configuration"]
|
|
405
449
|
env_config["episodeSteps"] = game.max_history_length() + DEFAULT_STEP_BUFFER
|
|
406
450
|
env_config["openSpielGameString"]["default"] = str(game)
|
|
407
451
|
env_config["openSpielGameName"]["default"] = short_name
|
|
452
|
+
env_config["openSpielGameParameters"]["default"] = game.get_parameters()
|
|
408
453
|
|
|
409
|
-
env_obs =
|
|
410
|
-
env_spec["observation"] = env_obs
|
|
454
|
+
env_obs = env_spec["observation"]
|
|
411
455
|
env_obs["properties"]["openSpielGameString"]["default"] = str(game)
|
|
412
456
|
env_obs["properties"]["openSpielGameName"]["default"] = short_name
|
|
413
457
|
|
|
@@ -19,15 +19,78 @@ class OpenSpielEnvTest(absltest.TestCase):
|
|
|
19
19
|
)
|
|
20
20
|
self.assertTrue(len(envs) > _REGISTERED_GAMES_THRESHOLD)
|
|
21
21
|
|
|
22
|
-
def
|
|
22
|
+
def test_tic_tac_toe_agent_playthrough(self):
|
|
23
23
|
envs = open_spiel_env._register_game_envs(["tic_tac_toe"])
|
|
24
|
-
print(envs)
|
|
25
24
|
env = make("open_spiel_tic_tac_toe", debug=True)
|
|
26
25
|
env.run(["random", "random"])
|
|
27
26
|
json = env.toJSON()
|
|
28
27
|
self.assertEqual(json["name"], "open_spiel_tic_tac_toe")
|
|
29
28
|
self.assertTrue(all([status == "DONE" for status in json["statuses"]]))
|
|
30
29
|
|
|
30
|
+
def test_tic_tac_toe_manual_playthrough(self):
|
|
31
|
+
envs = open_spiel_env._register_game_envs(["tic_tac_toe"])
|
|
32
|
+
env = make("open_spiel_tic_tac_toe", debug=True)
|
|
33
|
+
env.reset()
|
|
34
|
+
env.step([{"submission": -1}, {"submission": -1}]) # Initial setup step.
|
|
35
|
+
env.step([{"submission": 0}, {"submission": -1}])
|
|
36
|
+
env.step([{"submission": -1}, {"submission": 1}])
|
|
37
|
+
env.step([{"submission": 3}, {"submission": -1}])
|
|
38
|
+
env.step([{"submission": -1}, {"submission": 4}])
|
|
39
|
+
env.step([{"submission": 6}, {"submission": -1}])
|
|
40
|
+
self.assertTrue(env.done)
|
|
41
|
+
self.assertEqual(env.toJSON()["rewards"], [1, -1])
|
|
42
|
+
|
|
43
|
+
def test_invalid_action(self):
|
|
44
|
+
envs = open_spiel_env._register_game_envs(["tic_tac_toe"])
|
|
45
|
+
env = make("open_spiel_tic_tac_toe", debug=True)
|
|
46
|
+
env.reset()
|
|
47
|
+
for i in range(5): # Try repeatedly applying an illegal action
|
|
48
|
+
env.step([
|
|
49
|
+
{"submission": pyspiel.INVALID_ACTION},
|
|
50
|
+
{"submission": pyspiel.INVALID_ACTION},
|
|
51
|
+
])
|
|
52
|
+
if env.done:
|
|
53
|
+
break
|
|
54
|
+
self.assertEqual(i, 1) # Zeroth step is setup step, should fail next step.
|
|
55
|
+
json = env.toJSON()
|
|
56
|
+
self.assertTrue(all([status == "DONE" for status in json["statuses"]]))
|
|
57
|
+
self.assertEqual(
|
|
58
|
+
json["rewards"],
|
|
59
|
+
[
|
|
60
|
+
open_spiel_env.DEFAULT_INVALID_ACTION_REWARD,
|
|
61
|
+
-open_spiel_env.DEFAULT_INVALID_ACTION_REWARD,
|
|
62
|
+
]
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def test_serialized_game_and_state(self):
|
|
66
|
+
envs = open_spiel_env._register_game_envs(["tic_tac_toe"])
|
|
67
|
+
env = make("open_spiel_tic_tac_toe", debug=True)
|
|
68
|
+
env.reset()
|
|
69
|
+
env.step([{"submission": -1}, {"submission": -1}]) # Initial setup step.
|
|
70
|
+
kaggle_state = env.step([{"submission": 0}, {"submission": -1}])
|
|
71
|
+
serialize_game_and_state = kaggle_state[1]["observation"]["serializedGameAndState"]
|
|
72
|
+
game, state = pyspiel.deserialize_game_and_state(serialize_game_and_state)
|
|
73
|
+
self.assertEqual(game.get_type().short_name, "tic_tac_toe_proxy")
|
|
74
|
+
self.assertEqual(state.history(), [0])
|
|
75
|
+
|
|
76
|
+
def test_agent_error(self):
|
|
77
|
+
envs = open_spiel_env._register_game_envs(["tic_tac_toe"])
|
|
78
|
+
env = make("open_spiel_tic_tac_toe", debug=True)
|
|
79
|
+
env.reset()
|
|
80
|
+
# Setup step
|
|
81
|
+
env.step([
|
|
82
|
+
{"submission": pyspiel.INVALID_ACTION},
|
|
83
|
+
{"submission": pyspiel.INVALID_ACTION},
|
|
84
|
+
])
|
|
85
|
+
env.step([
|
|
86
|
+
{"submission": open_spiel_env.AGENT_ERROR_ACTION},
|
|
87
|
+
{"submission": pyspiel.INVALID_ACTION},
|
|
88
|
+
])
|
|
89
|
+
self.assertTrue(env.done)
|
|
90
|
+
json = env.toJSON()
|
|
91
|
+
self.assertEqual(json["rewards"], [None, None])
|
|
92
|
+
self.assertEqual(json["statuses"], ["ERROR", "ERROR"])
|
|
93
|
+
|
|
31
94
|
|
|
32
95
|
if __name__ == '__main__':
|
|
33
|
-
absltest.main()
|
|
96
|
+
absltest.main()
|
|
@@ -199,12 +199,7 @@
|
|
|
199
199
|
${processing && h`<${Processing} />`}
|
|
200
200
|
</div>`;
|
|
201
201
|
})`
|
|
202
|
-
background-color: #
|
|
203
|
-
background-image: radial-gradient(
|
|
204
|
-
circle closest-side,
|
|
205
|
-
#000b49,
|
|
206
|
-
#000b2a
|
|
207
|
-
);
|
|
202
|
+
background-color: #1C1D20;
|
|
208
203
|
display: flex;
|
|
209
204
|
flex: 1;
|
|
210
205
|
overflow: hidden;
|
|
@@ -242,7 +237,7 @@
|
|
|
242
237
|
</ul>`)}
|
|
243
238
|
</div>`;
|
|
244
239
|
})`
|
|
245
|
-
background-color: #
|
|
240
|
+
background-color: #1C1D20;
|
|
246
241
|
font-family: sans-serif;
|
|
247
242
|
font-size: 14px;
|
|
248
243
|
height: 48px;
|
|
@@ -442,7 +437,6 @@
|
|
|
442
437
|
})`
|
|
443
438
|
align-items: center;
|
|
444
439
|
background: #212121;
|
|
445
|
-
border: 4px solid #212121;
|
|
446
440
|
box-sizing: border-box;
|
|
447
441
|
display: flex;
|
|
448
442
|
flex-direction: column;
|
|
@@ -450,6 +444,10 @@
|
|
|
450
444
|
justify-content: center;
|
|
451
445
|
position: relative;
|
|
452
446
|
width: 100%;
|
|
447
|
+
|
|
448
|
+
&:not(.no-border) {
|
|
449
|
+
border: 4px solid #212121;
|
|
450
|
+
}
|
|
453
451
|
`;
|
|
454
452
|
|
|
455
453
|
const App = () => {
|
|
@@ -545,7 +543,7 @@
|
|
|
545
543
|
// Initialize context with window.kaggle.
|
|
546
544
|
updateContext(window.kaggle || {});
|
|
547
545
|
|
|
548
|
-
if (window.kaggle
|
|
546
|
+
if (window.kaggle?.playing) {
|
|
549
547
|
play(true);
|
|
550
548
|
}
|
|
551
549
|
|
|
@@ -556,10 +554,49 @@
|
|
|
556
554
|
// Ensure the environment names match before updating.
|
|
557
555
|
try {
|
|
558
556
|
if (
|
|
559
|
-
event.data.environment.name
|
|
560
|
-
contextRef.current.environment.name
|
|
557
|
+
event.data.environment?.name == contextRef.current.environment.name ||
|
|
558
|
+
event.data.environment?.name && !contextRef.current.environment.name ||
|
|
559
|
+
event.data.environment?.loading !== contextRef.current.environment.loading
|
|
561
560
|
) {
|
|
562
|
-
|
|
561
|
+
const nextContext = {
|
|
562
|
+
...event.data,
|
|
563
|
+
environment: {
|
|
564
|
+
...event.data.environment,
|
|
565
|
+
steps: event.data.environment?.steps ?? []
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
window.kaggle = nextContext;
|
|
569
|
+
if (!window.kaggle.renderer) {
|
|
570
|
+
window.kaggle.renderer = window.renderer;
|
|
571
|
+
}
|
|
572
|
+
updateContext(nextContext);
|
|
573
|
+
}
|
|
574
|
+
if (event.data.setSteps) {
|
|
575
|
+
const nextContext = {
|
|
576
|
+
...(window.kaggle ?? {}),
|
|
577
|
+
environment: {
|
|
578
|
+
...(window.kaggle?.environment ?? {}),
|
|
579
|
+
steps: event.data.setSteps
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
window.kaggle = nextContext;
|
|
583
|
+
if (!window.kaggle.renderer) {
|
|
584
|
+
window.kaggle.renderer = window.renderer;
|
|
585
|
+
}
|
|
586
|
+
updateContext(nextContext)
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// Side load the renderer script if it is specified by the post message event and not already loaded.
|
|
590
|
+
const renderScriptId = 'rendererScript'
|
|
591
|
+
if (event.data.environment?.rendererUrl && !document.querySelector(`#${renderScriptId}`)) {
|
|
592
|
+
window.rendererUrl = event.data.environment?.rendererUrl;
|
|
593
|
+
const script = document.createElement('script');
|
|
594
|
+
script.id = renderScriptId;
|
|
595
|
+
script.onload = () => {
|
|
596
|
+
window.kaggle.renderer = window.renderer;
|
|
597
|
+
};
|
|
598
|
+
script.src = window.rendererUrl;
|
|
599
|
+
document.body.appendChild(script);
|
|
563
600
|
}
|
|
564
601
|
} catch {}
|
|
565
602
|
},
|
|
@@ -674,7 +711,7 @@
|
|
|
674
711
|
|
|
675
712
|
return h`
|
|
676
713
|
<${Context.Provider} value=${contextRef.current}>
|
|
677
|
-
<${Player} />
|
|
714
|
+
<${Player} className="${contextRef.current.environment.viewer ? 'no-border' : ''}" />
|
|
678
715
|
<//>`;
|
|
679
716
|
};
|
|
680
717
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
kaggle_environments/__init__.py,sha256=
|
|
1
|
+
kaggle_environments/__init__.py,sha256=GzrKQBWH-dKbhfDK2K0GYTnHxw31m8DhnbzcHNMRn7c,2175
|
|
2
2
|
kaggle_environments/agent.py,sha256=j9rLnCK_Gy0eRIuvlJ9vcMh3vxn-Wvu-pjCpannOolc,6703
|
|
3
3
|
kaggle_environments/api.py,sha256=eLBKqr11Ku4tdsMUdUqy74FIVEA_hdV3_QUpX84x3Z8,798
|
|
4
4
|
kaggle_environments/core.py,sha256=Ense_M-2rP4KmVeuKFjM0NQ8M6ucUZTbhwrGekyR9LY,27857
|
|
@@ -8,7 +8,7 @@ kaggle_environments/main.py,sha256=10wtcEFcGIjdOd9AEps5WOAwslc6Wsx3eZ43LXJa8jE,1
|
|
|
8
8
|
kaggle_environments/schemas.json,sha256=zGzLyhqPdH6QQ0d48SrP5LKbvupprrWvgfQBerLqmhw,3307
|
|
9
9
|
kaggle_environments/status_codes.json,sha256=6a8HuS_Vth95W0f2fov21QLdRfA3KbizUvjKmJhYtBc,995
|
|
10
10
|
kaggle_environments/utils.py,sha256=FcI17PA4QK2-hyNp0dryS0TQ2pFlH9K19zDUMmuF4-E,5713
|
|
11
|
-
kaggle_environments/envs/chess/chess.js,sha256=
|
|
11
|
+
kaggle_environments/envs/chess/chess.js,sha256=QYA1arYF_qOfchN8HHQ4hL5z3C9XeT5hYigT75CgvKo,274596
|
|
12
12
|
kaggle_environments/envs/chess/chess.json,sha256=fc8Qa1IHWmYbiEgorXIjMj2JmqP95x_reqFe6Mon2Wk,1692
|
|
13
13
|
kaggle_environments/envs/chess/chess.py,sha256=41LMA8--APQOhl6aeWgJvkSaRBjAch2FgS7ELIoOT3w,245361
|
|
14
14
|
kaggle_environments/envs/chess/test_chess.py,sha256=ayZEIWRSD3D6BqhJv0q_M5a-j8-pMm8kb4ACAW-DhBE,1748
|
|
@@ -191,12 +191,12 @@ kaggle_environments/envs/mab/mab.py,sha256=bkSIxkstS98Vr3eOA9kxQkseDqa1MlG2Egfze
|
|
|
191
191
|
kaggle_environments/envs/open_spiel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
192
192
|
kaggle_environments/envs/open_spiel/html_playthrough_generator.py,sha256=qzvi9wMZKz1WfpaIpBxP5LPlVYKAk9npEtdKLXYHMWo,950
|
|
193
193
|
kaggle_environments/envs/open_spiel/observation.py,sha256=yrJ_iZ9sBUTB6YOyEpKNwYiQEWmsPPtaDYtL4zsw1Ko,4834
|
|
194
|
-
kaggle_environments/envs/open_spiel/open_spiel.py,sha256=
|
|
194
|
+
kaggle_environments/envs/open_spiel/open_spiel.py,sha256=HzN1ngjeOqxLoetI1g56PdlioRY26VoCJMQpbD4S-Vk,17517
|
|
195
195
|
kaggle_environments/envs/open_spiel/proxy.py,sha256=8Shane4KWYKvbP9nV3l8VQfAFOfFSUrS78h_4xQthVM,4881
|
|
196
196
|
kaggle_environments/envs/open_spiel/proxy_test.py,sha256=QkmRo_uS0DgDDm2pbU2vwal5KOMCWKw92rC2_g3MziM,1837
|
|
197
|
-
kaggle_environments/envs/open_spiel/test_open_spiel.py,sha256=
|
|
197
|
+
kaggle_environments/envs/open_spiel/test_open_spiel.py,sha256=MwyjH-e00-3SP8_r10drYTFvplacbo0cDCI0XKtE4wU,3596
|
|
198
198
|
kaggle_environments/envs/open_spiel/games/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
199
|
-
kaggle_environments/envs/open_spiel/games/chess/chess.js,sha256=
|
|
199
|
+
kaggle_environments/envs/open_spiel/games/chess/chess.js,sha256=e5QFnMCaNXMRskO0qbdhy7q0W3ov9yFGmvfpC48Dd6k,12931
|
|
200
200
|
kaggle_environments/envs/open_spiel/games/connect_four/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
201
201
|
kaggle_environments/envs/open_spiel/games/connect_four/connect_four.js,sha256=iO74ar3Hh64VYEx9v3eysgrPU-Mcokl9dkFxie6uISg,14893
|
|
202
202
|
kaggle_environments/envs/open_spiel/games/connect_four/connect_four_proxy.py,sha256=2otG99felDYhNhWpsadbM9YUaHtrXqhV1GFNEHhuPwA,2348
|
|
@@ -223,10 +223,10 @@ kaggle_environments/envs/tictactoe/test_tictactoe.py,sha256=6CgQbRz-yxNoMfD5tzmC
|
|
|
223
223
|
kaggle_environments/envs/tictactoe/tictactoe.js,sha256=NZDT-oSG0a6a-rso9Ldh9qkJwVrxrAsjKUC3_tJu3tw,8002
|
|
224
224
|
kaggle_environments/envs/tictactoe/tictactoe.json,sha256=zMXZ8-fpT7FBhzz2FFBvRLn4XwtngjEqOieMvI6cCj8,1121
|
|
225
225
|
kaggle_environments/envs/tictactoe/tictactoe.py,sha256=uq3sTHWNMg0dxX2v9pTbJAKM7fwerxQt7OQjCX96m-Y,3657
|
|
226
|
-
kaggle_environments/static/player.html,sha256=
|
|
227
|
-
kaggle_environments-1.17.
|
|
228
|
-
kaggle_environments-1.17.
|
|
229
|
-
kaggle_environments-1.17.
|
|
230
|
-
kaggle_environments-1.17.
|
|
231
|
-
kaggle_environments-1.17.
|
|
232
|
-
kaggle_environments-1.17.
|
|
226
|
+
kaggle_environments/static/player.html,sha256=TTxN-EU7_KCNIVDX4E4TrZ61FRWkGUDHMSbnUYsQSvg,24975
|
|
227
|
+
kaggle_environments-1.17.7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
228
|
+
kaggle_environments-1.17.7.dist-info/METADATA,sha256=va0iBjyCpXB4osbBWVdDGdhgUUig8nPEIR540OJU7vM,10955
|
|
229
|
+
kaggle_environments-1.17.7.dist-info/WHEEL,sha256=7wAbZI8A1UjN-j4-aYf66qBxOZ0Ioy0QNykkY5NcGJo,109
|
|
230
|
+
kaggle_environments-1.17.7.dist-info/entry_points.txt,sha256=HbVC-LKGQFV6lEEYBYyDTtrkHgdHJUWQ8_qt9KHGqz4,70
|
|
231
|
+
kaggle_environments-1.17.7.dist-info/top_level.txt,sha256=v3MMWIPMQFcI-WuF_dJngHWe9Bb2yH_6p4wat1x4gAc,20
|
|
232
|
+
kaggle_environments-1.17.7.dist-info/RECORD,,
|
{kaggle_environments-1.17.6.dist-info → kaggle_environments-1.17.7.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{kaggle_environments-1.17.6.dist-info → kaggle_environments-1.17.7.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|