kaggle-environments 0.2.0__py3-none-any.whl → 1.20.0__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.

Files changed (215) hide show
  1. kaggle_environments/__init__.py +49 -13
  2. kaggle_environments/agent.py +177 -124
  3. kaggle_environments/api.py +31 -0
  4. kaggle_environments/core.py +298 -173
  5. kaggle_environments/envs/cabt/cabt.js +164 -0
  6. kaggle_environments/envs/cabt/cabt.json +28 -0
  7. kaggle_environments/envs/cabt/cabt.py +186 -0
  8. kaggle_environments/envs/cabt/cg/__init__.py +0 -0
  9. kaggle_environments/envs/cabt/cg/cg.dll +0 -0
  10. kaggle_environments/envs/cabt/cg/game.py +75 -0
  11. kaggle_environments/envs/cabt/cg/libcg.so +0 -0
  12. kaggle_environments/envs/cabt/cg/sim.py +48 -0
  13. kaggle_environments/envs/cabt/test_cabt.py +120 -0
  14. kaggle_environments/envs/chess/chess.js +4289 -0
  15. kaggle_environments/envs/chess/chess.json +60 -0
  16. kaggle_environments/envs/chess/chess.py +4241 -0
  17. kaggle_environments/envs/chess/test_chess.py +60 -0
  18. kaggle_environments/envs/connectx/connectx.ipynb +3186 -0
  19. kaggle_environments/envs/connectx/connectx.js +1 -1
  20. kaggle_environments/envs/connectx/connectx.json +15 -1
  21. kaggle_environments/envs/connectx/connectx.py +6 -23
  22. kaggle_environments/envs/connectx/test_connectx.py +70 -24
  23. kaggle_environments/envs/football/football.ipynb +75 -0
  24. kaggle_environments/envs/football/football.json +91 -0
  25. kaggle_environments/envs/football/football.py +277 -0
  26. kaggle_environments/envs/football/helpers.py +95 -0
  27. kaggle_environments/envs/football/test_football.py +360 -0
  28. kaggle_environments/envs/halite/__init__.py +0 -0
  29. kaggle_environments/envs/halite/halite.ipynb +44741 -0
  30. kaggle_environments/envs/halite/halite.js +199 -83
  31. kaggle_environments/envs/halite/halite.json +31 -18
  32. kaggle_environments/envs/halite/halite.py +164 -303
  33. kaggle_environments/envs/halite/helpers.py +720 -0
  34. kaggle_environments/envs/halite/test_halite.py +190 -0
  35. kaggle_environments/envs/hungry_geese/__init__.py +0 -0
  36. kaggle_environments/envs/{battlegeese/battlegeese.js → hungry_geese/hungry_geese.js} +38 -22
  37. kaggle_environments/envs/{battlegeese/battlegeese.json → hungry_geese/hungry_geese.json} +22 -15
  38. kaggle_environments/envs/hungry_geese/hungry_geese.py +316 -0
  39. kaggle_environments/envs/hungry_geese/test_hungry_geese.py +0 -0
  40. kaggle_environments/envs/identity/identity.json +6 -5
  41. kaggle_environments/envs/identity/identity.py +15 -2
  42. kaggle_environments/envs/kore_fleets/__init__.py +0 -0
  43. kaggle_environments/envs/kore_fleets/helpers.py +1005 -0
  44. kaggle_environments/envs/kore_fleets/kore_fleets.ipynb +114 -0
  45. kaggle_environments/envs/kore_fleets/kore_fleets.js +658 -0
  46. kaggle_environments/envs/kore_fleets/kore_fleets.json +164 -0
  47. kaggle_environments/envs/kore_fleets/kore_fleets.py +555 -0
  48. kaggle_environments/envs/kore_fleets/starter_bots/java/Bot.java +54 -0
  49. kaggle_environments/envs/kore_fleets/starter_bots/java/README.md +26 -0
  50. kaggle_environments/envs/kore_fleets/starter_bots/java/jars/hamcrest-core-1.3.jar +0 -0
  51. kaggle_environments/envs/kore_fleets/starter_bots/java/jars/junit-4.13.2.jar +0 -0
  52. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Board.java +518 -0
  53. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Cell.java +61 -0
  54. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Configuration.java +24 -0
  55. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Direction.java +166 -0
  56. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Fleet.java +72 -0
  57. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/KoreJson.java +97 -0
  58. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Observation.java +72 -0
  59. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Pair.java +13 -0
  60. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Player.java +68 -0
  61. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Point.java +65 -0
  62. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Shipyard.java +70 -0
  63. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/ShipyardAction.java +59 -0
  64. kaggle_environments/envs/kore_fleets/starter_bots/java/main.py +73 -0
  65. kaggle_environments/envs/kore_fleets/starter_bots/java/test/BoardTest.java +567 -0
  66. kaggle_environments/envs/kore_fleets/starter_bots/java/test/ConfigurationTest.java +25 -0
  67. kaggle_environments/envs/kore_fleets/starter_bots/java/test/KoreJsonTest.java +62 -0
  68. kaggle_environments/envs/kore_fleets/starter_bots/java/test/ObservationTest.java +46 -0
  69. kaggle_environments/envs/kore_fleets/starter_bots/java/test/PointTest.java +21 -0
  70. kaggle_environments/envs/kore_fleets/starter_bots/java/test/ShipyardTest.java +22 -0
  71. kaggle_environments/envs/kore_fleets/starter_bots/java/test/configuration.json +1 -0
  72. kaggle_environments/envs/kore_fleets/starter_bots/java/test/fullob.json +1 -0
  73. kaggle_environments/envs/kore_fleets/starter_bots/java/test/observation.json +1 -0
  74. kaggle_environments/envs/kore_fleets/starter_bots/python/__init__.py +0 -0
  75. kaggle_environments/envs/kore_fleets/starter_bots/python/main.py +27 -0
  76. kaggle_environments/envs/kore_fleets/starter_bots/ts/Bot.ts +34 -0
  77. kaggle_environments/envs/kore_fleets/starter_bots/ts/DoNothingBot.ts +12 -0
  78. kaggle_environments/envs/kore_fleets/starter_bots/ts/MinerBot.ts +62 -0
  79. kaggle_environments/envs/kore_fleets/starter_bots/ts/README.md +55 -0
  80. kaggle_environments/envs/kore_fleets/starter_bots/ts/interpreter.ts +402 -0
  81. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Board.ts +514 -0
  82. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Cell.ts +63 -0
  83. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Configuration.ts +25 -0
  84. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Direction.ts +169 -0
  85. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Fleet.ts +76 -0
  86. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/KoreIO.ts +70 -0
  87. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Observation.ts +45 -0
  88. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Pair.ts +11 -0
  89. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Player.ts +68 -0
  90. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Point.ts +65 -0
  91. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Shipyard.ts +72 -0
  92. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/ShipyardAction.ts +58 -0
  93. kaggle_environments/envs/kore_fleets/starter_bots/ts/main.py +73 -0
  94. kaggle_environments/envs/kore_fleets/starter_bots/ts/miner.py +73 -0
  95. kaggle_environments/envs/kore_fleets/starter_bots/ts/package.json +23 -0
  96. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/BoardTest.ts +551 -0
  97. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/ConfigurationTest.ts +16 -0
  98. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/ObservationTest.ts +33 -0
  99. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/PointTest.ts +17 -0
  100. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/ShipyardTest.ts +18 -0
  101. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/configuration.json +1 -0
  102. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/fullob.json +1 -0
  103. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/observation.json +1 -0
  104. kaggle_environments/envs/kore_fleets/starter_bots/ts/tsconfig.json +22 -0
  105. kaggle_environments/envs/kore_fleets/test_kore_fleets.py +331 -0
  106. kaggle_environments/envs/lux_ai_2021/README.md +3 -0
  107. kaggle_environments/envs/lux_ai_2021/__init__.py +0 -0
  108. kaggle_environments/envs/lux_ai_2021/agents.py +11 -0
  109. kaggle_environments/envs/lux_ai_2021/dimensions/754.js +2 -0
  110. kaggle_environments/envs/lux_ai_2021/dimensions/754.js.LICENSE.txt +296 -0
  111. kaggle_environments/envs/lux_ai_2021/dimensions/main.js +1 -0
  112. kaggle_environments/envs/lux_ai_2021/index.html +43 -0
  113. kaggle_environments/envs/lux_ai_2021/lux_ai_2021.json +100 -0
  114. kaggle_environments/envs/lux_ai_2021/lux_ai_2021.py +231 -0
  115. kaggle_environments/envs/lux_ai_2021/test_agents/__init__.py +0 -0
  116. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/game_constants.js +6 -0
  117. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/game_constants.json +59 -0
  118. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/game_objects.js +145 -0
  119. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/io.js +14 -0
  120. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/kit.js +209 -0
  121. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/map.js +107 -0
  122. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/parser.js +79 -0
  123. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/main.js +88 -0
  124. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/main.py +75 -0
  125. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/simple.tar.gz +0 -0
  126. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/__init__.py +0 -0
  127. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/annotate.py +20 -0
  128. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/constants.py +25 -0
  129. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game.py +86 -0
  130. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_constants.json +59 -0
  131. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_constants.py +7 -0
  132. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_map.py +106 -0
  133. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_objects.py +154 -0
  134. kaggle_environments/envs/lux_ai_2021/test_agents/python/random_agent.py +38 -0
  135. kaggle_environments/envs/lux_ai_2021/test_agents/python/simple_agent.py +82 -0
  136. kaggle_environments/envs/lux_ai_2021/test_lux.py +19 -0
  137. kaggle_environments/envs/lux_ai_2021/testing.md +23 -0
  138. kaggle_environments/envs/lux_ai_2021/todo.md.og +18 -0
  139. kaggle_environments/envs/lux_ai_s3/README.md +21 -0
  140. kaggle_environments/envs/lux_ai_s3/agents.py +5 -0
  141. kaggle_environments/envs/lux_ai_s3/index.html +42 -0
  142. kaggle_environments/envs/lux_ai_s3/lux_ai_s3.json +47 -0
  143. kaggle_environments/envs/lux_ai_s3/lux_ai_s3.py +178 -0
  144. kaggle_environments/envs/lux_ai_s3/luxai_s3/__init__.py +1 -0
  145. kaggle_environments/envs/lux_ai_s3/luxai_s3/env.py +819 -0
  146. kaggle_environments/envs/lux_ai_s3/luxai_s3/globals.py +9 -0
  147. kaggle_environments/envs/lux_ai_s3/luxai_s3/params.py +101 -0
  148. kaggle_environments/envs/lux_ai_s3/luxai_s3/profiler.py +141 -0
  149. kaggle_environments/envs/lux_ai_s3/luxai_s3/pygame_render.py +222 -0
  150. kaggle_environments/envs/lux_ai_s3/luxai_s3/spaces.py +27 -0
  151. kaggle_environments/envs/lux_ai_s3/luxai_s3/state.py +464 -0
  152. kaggle_environments/envs/lux_ai_s3/luxai_s3/utils.py +12 -0
  153. kaggle_environments/envs/lux_ai_s3/luxai_s3/wrappers.py +156 -0
  154. kaggle_environments/envs/lux_ai_s3/test_agents/python/agent.py +78 -0
  155. kaggle_environments/envs/lux_ai_s3/test_agents/python/lux/__init__.py +0 -0
  156. kaggle_environments/envs/lux_ai_s3/test_agents/python/lux/kit.py +31 -0
  157. kaggle_environments/envs/lux_ai_s3/test_agents/python/lux/utils.py +17 -0
  158. kaggle_environments/envs/lux_ai_s3/test_agents/python/main.py +66 -0
  159. kaggle_environments/envs/lux_ai_s3/test_lux.py +9 -0
  160. kaggle_environments/envs/mab/__init__.py +0 -0
  161. kaggle_environments/envs/mab/agents.py +12 -0
  162. kaggle_environments/envs/mab/mab.js +100 -0
  163. kaggle_environments/envs/mab/mab.json +74 -0
  164. kaggle_environments/envs/mab/mab.py +146 -0
  165. kaggle_environments/envs/open_spiel/__init__.py +0 -0
  166. kaggle_environments/envs/open_spiel/games/__init__.py +0 -0
  167. kaggle_environments/envs/open_spiel/games/chess/chess.js +441 -0
  168. kaggle_environments/envs/open_spiel/games/chess/image_config.jsonl +20 -0
  169. kaggle_environments/envs/open_spiel/games/chess/openings.jsonl +20 -0
  170. kaggle_environments/envs/open_spiel/games/connect_four/__init__.py +0 -0
  171. kaggle_environments/envs/open_spiel/games/connect_four/connect_four.js +284 -0
  172. kaggle_environments/envs/open_spiel/games/connect_four/connect_four_proxy.py +86 -0
  173. kaggle_environments/envs/open_spiel/games/go/__init__.py +0 -0
  174. kaggle_environments/envs/open_spiel/games/go/go.js +481 -0
  175. kaggle_environments/envs/open_spiel/games/go/go_proxy.py +99 -0
  176. kaggle_environments/envs/open_spiel/games/tic_tac_toe/__init__.py +0 -0
  177. kaggle_environments/envs/open_spiel/games/tic_tac_toe/tic_tac_toe.js +345 -0
  178. kaggle_environments/envs/open_spiel/games/tic_tac_toe/tic_tac_toe_proxy.py +98 -0
  179. kaggle_environments/envs/open_spiel/games/universal_poker/__init__.py +0 -0
  180. kaggle_environments/envs/open_spiel/games/universal_poker/universal_poker.js +431 -0
  181. kaggle_environments/envs/open_spiel/games/universal_poker/universal_poker_proxy.py +159 -0
  182. kaggle_environments/envs/open_spiel/html_playthrough_generator.py +31 -0
  183. kaggle_environments/envs/open_spiel/observation.py +128 -0
  184. kaggle_environments/envs/open_spiel/open_spiel.py +565 -0
  185. kaggle_environments/envs/open_spiel/proxy.py +138 -0
  186. kaggle_environments/envs/open_spiel/test_open_spiel.py +191 -0
  187. kaggle_environments/envs/rps/__init__.py +0 -0
  188. kaggle_environments/envs/rps/agents.py +84 -0
  189. kaggle_environments/envs/rps/helpers.py +25 -0
  190. kaggle_environments/envs/rps/rps.js +117 -0
  191. kaggle_environments/envs/rps/rps.json +63 -0
  192. kaggle_environments/envs/rps/rps.py +90 -0
  193. kaggle_environments/envs/rps/test_rps.py +110 -0
  194. kaggle_environments/envs/rps/utils.py +7 -0
  195. kaggle_environments/envs/tictactoe/test_tictactoe.py +43 -77
  196. kaggle_environments/envs/tictactoe/tictactoe.ipynb +1397 -0
  197. kaggle_environments/envs/tictactoe/tictactoe.json +10 -2
  198. kaggle_environments/envs/tictactoe/tictactoe.py +1 -1
  199. kaggle_environments/errors.py +2 -4
  200. kaggle_environments/helpers.py +377 -0
  201. kaggle_environments/main.py +214 -50
  202. kaggle_environments/schemas.json +23 -18
  203. kaggle_environments/static/player.html +206 -74
  204. kaggle_environments/utils.py +46 -73
  205. kaggle_environments-1.20.0.dist-info/METADATA +25 -0
  206. kaggle_environments-1.20.0.dist-info/RECORD +211 -0
  207. {kaggle_environments-0.2.0.dist-info → kaggle_environments-1.20.0.dist-info}/WHEEL +1 -2
  208. kaggle_environments-1.20.0.dist-info/entry_points.txt +3 -0
  209. kaggle_environments/envs/battlegeese/battlegeese.py +0 -219
  210. kaggle_environments/temp.py +0 -14
  211. kaggle_environments-0.2.0.dist-info/METADATA +0 -393
  212. kaggle_environments-0.2.0.dist-info/RECORD +0 -33
  213. kaggle_environments-0.2.0.dist-info/entry_points.txt +0 -3
  214. kaggle_environments-0.2.0.dist-info/top_level.txt +0 -1
  215. {kaggle_environments-0.2.0.dist-info → kaggle_environments-1.20.0.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,284 @@
1
+ function renderer(options) {
2
+ const { environment, step, parent, interactive, isInteractive } = options;
3
+
4
+ const DEFAULT_NUM_ROWS = 6;
5
+ const DEFAULT_NUM_COLS = 7;
6
+ const PLAYER_SYMBOLS = ['O', 'X']; // O: Player 0 (Yellow), X: Player 1 (Red)
7
+ const PLAYER_COLORS = ['#facc15', '#ef4444']; // Yellow for 'O', Red for 'X'
8
+ const EMPTY_CELL_COLOR = '#e5e7eb';
9
+ const BOARD_COLOR = '#3b82f6';
10
+
11
+ const SVG_NS = "http://www.w3.org/2000/svg";
12
+ const CELL_UNIT_SIZE = 100;
13
+ const CIRCLE_RADIUS = CELL_UNIT_SIZE * 0.42;
14
+ const SVG_VIEWBOX_WIDTH = DEFAULT_NUM_COLS * CELL_UNIT_SIZE;
15
+ const SVG_VIEWBOX_HEIGHT = DEFAULT_NUM_ROWS * CELL_UNIT_SIZE;
16
+
17
+ let currentBoardSvgElement = null;
18
+ let currentStatusTextElement = null;
19
+ let currentWinnerTextElement = null;
20
+ let currentMessageBoxElement = typeof document !== 'undefined' ? document.getElementById('messageBox') : null;
21
+ let currentRendererContainer = null;
22
+ let currentTitleElement = null;
23
+
24
+ function _showMessage(message, type = 'info', duration = 3000) {
25
+ if (typeof document === 'undefined' || !document.body) return;
26
+ if (!currentMessageBoxElement) {
27
+ currentMessageBoxElement = document.createElement('div');
28
+ currentMessageBoxElement.id = 'messageBox';
29
+ currentMessageBoxElement.style.position = 'fixed';
30
+ currentMessageBoxElement.style.top = '10px';
31
+ currentMessageBoxElement.style.left = '50%';
32
+ currentMessageBoxElement.style.transform = 'translateX(-50%)';
33
+ currentMessageBoxElement.style.padding = '0.75rem 1rem';
34
+ currentMessageBoxElement.style.borderRadius = '0.375rem';
35
+ currentMessageBoxElement.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
36
+ currentMessageBoxElement.style.zIndex = '1000';
37
+ currentMessageBoxElement.style.opacity = '0';
38
+ currentMessageBoxElement.style.transition = 'opacity 0.3s ease-in-out, background-color 0.3s';
39
+ currentMessageBoxElement.style.fontSize = '0.875rem';
40
+ currentMessageBoxElement.style.fontFamily = "'Inter', sans-serif";
41
+ document.body.appendChild(currentMessageBoxElement);
42
+ }
43
+ currentMessageBoxElement.textContent = message;
44
+ currentMessageBoxElement.style.backgroundColor = type === 'error' ? '#ef4444' : '#10b981';
45
+ currentMessageBoxElement.style.color = 'white';
46
+ currentMessageBoxElement.style.opacity = '1';
47
+ setTimeout(() => { if (currentMessageBoxElement) currentMessageBoxElement.style.opacity = '0'; }, duration);
48
+ }
49
+
50
+ function _ensureRendererElements(parentElementToClear, rows, cols) {
51
+ if (!parentElementToClear) return false;
52
+ parentElementToClear.innerHTML = '';
53
+
54
+ currentRendererContainer = document.createElement('div');
55
+ currentRendererContainer.style.display = 'flex';
56
+ currentRendererContainer.style.flexDirection = 'column';
57
+ currentRendererContainer.style.alignItems = 'center';
58
+ currentRendererContainer.style.padding = '20px';
59
+ currentRendererContainer.style.boxSizing = 'border-box';
60
+ currentRendererContainer.style.width = '100%';
61
+ currentRendererContainer.style.height = '100%';
62
+ currentRendererContainer.style.fontFamily = "'Inter', sans-serif";
63
+
64
+ currentTitleElement = document.createElement('h1');
65
+ currentTitleElement.textContent = 'Connect Four';
66
+ currentTitleElement.style.fontSize = '1.875rem';
67
+ currentTitleElement.style.fontWeight = 'bold';
68
+ currentTitleElement.style.marginBottom = '1rem';
69
+ currentTitleElement.style.textAlign = 'center';
70
+ currentTitleElement.style.color = '#2563eb';
71
+ currentRendererContainer.appendChild(currentTitleElement);
72
+
73
+ currentBoardSvgElement = document.createElementNS(SVG_NS, "svg");
74
+ currentBoardSvgElement.setAttribute("viewBox", `0 0 ${SVG_VIEWBOX_WIDTH} ${SVG_VIEWBOX_HEIGHT}`);
75
+ currentBoardSvgElement.setAttribute("preserveAspectRatio", "xMidYMid meet");
76
+ currentBoardSvgElement.style.width = "auto";
77
+ currentBoardSvgElement.style.maxWidth = "500px";
78
+ currentBoardSvgElement.style.maxHeight = `calc(100vh - 200px)`;
79
+ currentBoardSvgElement.style.aspectRatio = `${cols} / ${rows}`;
80
+ currentBoardSvgElement.style.display = "block";
81
+ currentBoardSvgElement.style.margin = "0 auto 20px auto";
82
+
83
+ const boardBgRect = document.createElementNS(SVG_NS, "rect");
84
+ boardBgRect.setAttribute("x", "0");
85
+ boardBgRect.setAttribute("y", "0");
86
+ boardBgRect.setAttribute("width", SVG_VIEWBOX_WIDTH.toString());
87
+ boardBgRect.setAttribute("height", SVG_VIEWBOX_HEIGHT.toString());
88
+ boardBgRect.setAttribute("fill", BOARD_COLOR);
89
+ boardBgRect.setAttribute("rx", (CELL_UNIT_SIZE * 0.1).toString());
90
+ currentBoardSvgElement.appendChild(boardBgRect);
91
+
92
+ // SVG Circles are created with (0,0) being top-left visual circle
93
+ for (let r_visual = 0; r_visual < rows; r_visual++) {
94
+ for (let c_visual = 0; c_visual < cols; c_visual++) {
95
+ const circle = document.createElementNS(SVG_NS, "circle");
96
+ const cx = c_visual * CELL_UNIT_SIZE + CELL_UNIT_SIZE / 2;
97
+ const cy = r_visual * CELL_UNIT_SIZE + CELL_UNIT_SIZE / 2;
98
+ circle.setAttribute("id", `cell-${r_visual}-${c_visual}`);
99
+ circle.setAttribute("cx", cx.toString());
100
+ circle.setAttribute("cy", cy.toString());
101
+ circle.setAttribute("r", CIRCLE_RADIUS.toString());
102
+ circle.setAttribute("fill", EMPTY_CELL_COLOR);
103
+ currentBoardSvgElement.appendChild(circle);
104
+ }
105
+ }
106
+ currentRendererContainer.appendChild(currentBoardSvgElement);
107
+
108
+ const statusContainer = document.createElement('div');
109
+ statusContainer.style.padding = '10px 15px';
110
+ statusContainer.style.backgroundColor = 'white';
111
+ statusContainer.style.borderRadius = '8px';
112
+ statusContainer.style.boxShadow = '0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06)';
113
+ statusContainer.style.textAlign = 'center';
114
+ statusContainer.style.width = 'auto';
115
+ statusContainer.style.minWidth = '200px';
116
+ statusContainer.style.maxWidth = '90vw';
117
+ currentRendererContainer.appendChild(statusContainer);
118
+
119
+ currentStatusTextElement = document.createElement('p');
120
+ currentStatusTextElement.style.fontSize = '1.1rem';
121
+ currentStatusTextElement.style.fontWeight = '600';
122
+ currentStatusTextElement.style.margin = '0 0 5px 0';
123
+ statusContainer.appendChild(currentStatusTextElement);
124
+
125
+ currentWinnerTextElement = document.createElement('p');
126
+ currentWinnerTextElement.style.fontSize = '1.25rem';
127
+ currentWinnerTextElement.style.fontWeight = '700';
128
+ currentWinnerTextElement.style.margin = '5px 0 0 0';
129
+ statusContainer.appendChild(currentWinnerTextElement);
130
+
131
+ parentElementToClear.appendChild(currentRendererContainer);
132
+
133
+ if (typeof document !== 'undefined' && !document.body.hasAttribute('data-renderer-initialized')) {
134
+ document.body.setAttribute('data-renderer-initialized', 'true');
135
+ }
136
+ return true;
137
+ }
138
+
139
+ function _renderBoardDisplay_svg(gameStateToDisplay, displayRows, displayCols) {
140
+ if (!currentBoardSvgElement || !currentStatusTextElement || !currentWinnerTextElement) return;
141
+
142
+ if (!gameStateToDisplay || typeof gameStateToDisplay.board !== 'object' || !Array.isArray(gameStateToDisplay.board) || gameStateToDisplay.board.length === 0) {
143
+ currentStatusTextElement.textContent = "Waiting for game data...";
144
+ currentWinnerTextElement.textContent = "";
145
+ for (let r_visual = 0; r_visual < displayRows; r_visual++) {
146
+ for (let c_visual = 0; c_visual < displayCols; c_visual++) {
147
+ const circleElement = currentBoardSvgElement.querySelector(`#cell-${r_visual}-${c_visual}`);
148
+ if (circleElement) {
149
+ circleElement.setAttribute("fill", EMPTY_CELL_COLOR);
150
+ }
151
+ }
152
+ }
153
+ return;
154
+ }
155
+
156
+ const { board, current_player, is_terminal, winner } = gameStateToDisplay;
157
+
158
+ for (let r_data = 0; r_data < displayRows; r_data++) {
159
+ const dataRow = board[r_data];
160
+ if (!dataRow || !Array.isArray(dataRow) || dataRow.length !== displayCols) {
161
+ // Error handling for malformed row
162
+ for (let c_fill = 0; c_fill < displayCols; c_fill++) {
163
+ // Determine visual row for error display. If r_data=0 is top data,
164
+ // and we want to flip, then this error is for visual row (displayRows-1)-0.
165
+ const visual_row_for_error = (displayRows - 1) - r_data;
166
+ const circleElement = currentBoardSvgElement.querySelector(`#cell-${visual_row_for_error}-${c_fill}`);
167
+ if (circleElement) circleElement.setAttribute("fill", '#FF00FF'); // Magenta for error
168
+ }
169
+ continue;
170
+ }
171
+
172
+ const visual_svg_row_index = (displayRows - 1) - r_data;
173
+
174
+ for (let c_data = 0; c_data < displayCols; c_data++) { // c_data iterates through columns of `board[r_data]`
175
+ const originalCellValue = dataRow[c_data];
176
+ const cellValueForComparison = String(originalCellValue).trim().toLowerCase();
177
+
178
+ // The column index for SVG is the same as c_data
179
+ const visual_svg_col_index = c_data;
180
+ const circleElement = currentBoardSvgElement.querySelector(`#cell-${visual_svg_row_index}-${visual_svg_col_index}`);
181
+
182
+ if (!circleElement) continue;
183
+
184
+ let fillColor = EMPTY_CELL_COLOR;
185
+ if (cellValueForComparison === "o") {
186
+ fillColor = PLAYER_COLORS[0]; // Yellow
187
+ } else if (cellValueForComparison === "x") {
188
+ fillColor = PLAYER_COLORS[1]; // Red
189
+ }
190
+ circleElement.setAttribute("fill", fillColor);
191
+ }
192
+ }
193
+
194
+ currentStatusTextElement.innerHTML = '';
195
+ currentWinnerTextElement.innerHTML = '';
196
+ if (is_terminal) {
197
+ currentStatusTextElement.textContent = "Game Over!";
198
+ if (winner !== null && winner !== undefined) {
199
+ if (String(winner).toLowerCase() === 'draw') {
200
+ currentWinnerTextElement.textContent = "It's a Draw!";
201
+ } else {
202
+ let winnerSymbolDisplay, winnerColorDisplay;
203
+ if (String(winner).toLowerCase() === "o") {
204
+ winnerSymbolDisplay = PLAYER_SYMBOLS[0];
205
+ winnerColorDisplay = PLAYER_COLORS[0];
206
+ } else if (String(winner).toLowerCase() === "x") {
207
+ winnerSymbolDisplay = PLAYER_SYMBOLS[1];
208
+ winnerColorDisplay = PLAYER_COLORS[1];
209
+ }
210
+ if (winnerSymbolDisplay) {
211
+ currentWinnerTextElement.innerHTML = `Player <span style="color: ${winnerColorDisplay}; font-weight: bold;">${winnerSymbolDisplay}</span> Wins!`;
212
+ } else {
213
+ currentWinnerTextElement.textContent = `Winner: ${String(winner).toUpperCase()}`;
214
+ }
215
+ }
216
+ } else { currentWinnerTextElement.textContent = "Game ended."; }
217
+ } else {
218
+ let playerSymbolToDisplay, playerColorToDisplay;
219
+ if (String(current_player).toLowerCase() === "o") {
220
+ playerSymbolToDisplay = PLAYER_SYMBOLS[0];
221
+ playerColorToDisplay = PLAYER_COLORS[0];
222
+ } else if (String(current_player).toLowerCase() === "x") {
223
+ playerSymbolToDisplay = PLAYER_SYMBOLS[1];
224
+ playerColorToDisplay = PLAYER_COLORS[1];
225
+ }
226
+ if (playerSymbolToDisplay) {
227
+ currentStatusTextElement.innerHTML = `Current Player: <span style="color: ${playerColorToDisplay}; font-weight: bold;">${playerSymbolToDisplay}</span>`;
228
+ } else {
229
+ currentStatusTextElement.textContent = "Waiting for player...";
230
+ }
231
+ }
232
+ }
233
+
234
+ // --- Main execution logic ---
235
+ if (!_ensureRendererElements(parent, DEFAULT_NUM_ROWS, DEFAULT_NUM_COLS)) {
236
+ if (parent && typeof parent.innerHTML !== 'undefined') {
237
+ parent.innerHTML = "<p style='color:red; font-family: sans-serif;'>Critical Error: Renderer element setup failed.</p>";
238
+ }
239
+ return;
240
+ }
241
+
242
+ if (!environment || !environment.steps || !environment.steps[step]) {
243
+ _renderBoardDisplay_svg(null, DEFAULT_NUM_ROWS, DEFAULT_NUM_COLS);
244
+ if(currentStatusTextElement) currentStatusTextElement.textContent = "Initializing environment...";
245
+ return;
246
+ }
247
+
248
+ const currentStepAgents = environment.steps[step];
249
+ if (!currentStepAgents || !Array.isArray(currentStepAgents) || currentStepAgents.length === 0) {
250
+ _renderBoardDisplay_svg(null, DEFAULT_NUM_ROWS, DEFAULT_NUM_COLS);
251
+ if(currentStatusTextElement) currentStatusTextElement.textContent = "Waiting for agent data...";
252
+ return;
253
+ }
254
+
255
+ const gameMasterAgentIndex = currentStepAgents.length - 1;
256
+ const gameMasterAgent = currentStepAgents[gameMasterAgentIndex];
257
+
258
+ if (!gameMasterAgent || typeof gameMasterAgent.observation === 'undefined') {
259
+ _renderBoardDisplay_svg(null, DEFAULT_NUM_ROWS, DEFAULT_NUM_COLS);
260
+ if(currentStatusTextElement) currentStatusTextElement.textContent = "Waiting for observation data...";
261
+ return;
262
+ }
263
+ const observationForRenderer = gameMasterAgent.observation;
264
+
265
+ let gameSpecificState = null;
266
+
267
+ if (observationForRenderer && typeof observationForRenderer.observationString === 'string' && observationForRenderer.observationString.trim() !== '') {
268
+ try {
269
+ gameSpecificState = JSON.parse(observationForRenderer.observationString);
270
+ } catch (e) {
271
+ _showMessage("Error: Corrupted game state (obs_string).", 'error');
272
+ }
273
+ }
274
+
275
+ if (!gameSpecificState && observationForRenderer && typeof observationForRenderer.json === 'string' && observationForRenderer.json.trim() !== '') {
276
+ try {
277
+ gameSpecificState = JSON.parse(observationForRenderer.json);
278
+ } catch (e) {
279
+ _showMessage("Error: Corrupted game state (json).", 'error');
280
+ }
281
+ }
282
+
283
+ _renderBoardDisplay_svg(gameSpecificState, DEFAULT_NUM_ROWS, DEFAULT_NUM_COLS);
284
+ }
@@ -0,0 +1,86 @@
1
+ """Change Connect Four state and action string representations."""
2
+
3
+ import json
4
+ from typing import Any
5
+
6
+ import pyspiel
7
+
8
+ from ... import proxy
9
+
10
+
11
+ class ConnectFourState(proxy.State):
12
+ """Connect Four state proxy."""
13
+
14
+ def _player_string(self, player: int) -> str:
15
+ if player < 0:
16
+ return pyspiel.PlayerId(player).name.lower()
17
+ elif player == 0:
18
+ return "x"
19
+ elif player == 1:
20
+ return "o"
21
+ else:
22
+ raise ValueError(f"Invalid player: {player}")
23
+
24
+ def state_dict(self) -> dict[str, Any]:
25
+ # row 0 is now bottom row
26
+ rows = reversed(self.to_string().strip().split("\n"))
27
+ board = [list(row) for row in rows]
28
+ winner = None
29
+ if self.is_terminal():
30
+ if self.returns()[0] > self.returns()[1]:
31
+ winner = "x"
32
+ elif self.returns()[1] > self.returns()[0]:
33
+ winner = "o"
34
+ else:
35
+ winner = "draw"
36
+ return {
37
+ "board": board,
38
+ "current_player": self._player_string(self.current_player()),
39
+ "is_terminal": self.is_terminal(),
40
+ "winner": winner,
41
+ }
42
+
43
+ def to_json(self) -> str:
44
+ return json.dumps(self.state_dict())
45
+
46
+ def action_to_dict(self, action: int) -> dict[str, Any]:
47
+ return {"col": action}
48
+
49
+ def action_to_json(self, action: int) -> str:
50
+ return json.dumps(self.action_to_dict(action))
51
+
52
+ def dict_to_action(self, action_dict: dict[str, Any]) -> int:
53
+ return int(action_dict["col"])
54
+
55
+ def json_to_action(self, action_json: str) -> int:
56
+ action_dict = json.loads(action_json)
57
+ return self.dict_to_action(action_dict)
58
+
59
+ def observation_string(self, player: int) -> str:
60
+ return self.observation_json(player)
61
+
62
+ def observation_json(self, player: int) -> str:
63
+ del player
64
+ return self.to_json()
65
+
66
+ def __str__(self):
67
+ return self.to_json()
68
+
69
+
70
+ class ConnectFourGame(proxy.Game):
71
+ """Connect Four game proxy."""
72
+
73
+ def __init__(self, params: Any | None = None):
74
+ params = params or {}
75
+ wrapped = pyspiel.load_game("connect_four", params)
76
+ super().__init__(
77
+ wrapped,
78
+ short_name="connect_four_proxy",
79
+ long_name="Connect Four (proxy)",
80
+ )
81
+
82
+ def new_initial_state(self, *args) -> ConnectFourState:
83
+ return ConnectFourState(self.__wrapped__.new_initial_state(*args), game=self)
84
+
85
+
86
+ pyspiel.register_game(ConnectFourGame().get_type(), ConnectFourGame)