kaggle-environments 0.2.1__py3-none-any.whl → 1.20.1__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 (214) 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 +295 -170
  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} +21 -14
  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 +340 -0
  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-0.2.1.dist-info → kaggle_environments-1.20.1.dist-info}/METADATA +36 -114
  206. kaggle_environments-1.20.1.dist-info/RECORD +211 -0
  207. {kaggle_environments-0.2.1.dist-info → kaggle_environments-1.20.1.dist-info}/WHEEL +1 -2
  208. kaggle_environments-1.20.1.dist-info/entry_points.txt +3 -0
  209. kaggle_environments/envs/battlegeese/battlegeese.py +0 -223
  210. kaggle_environments/temp.py +0 -14
  211. kaggle_environments-0.2.1.dist-info/RECORD +0 -32
  212. kaggle_environments-0.2.1.dist-info/entry_points.txt +0 -3
  213. kaggle_environments-0.2.1.dist-info/top_level.txt +0 -1
  214. {kaggle_environments-0.2.1.dist-info → kaggle_environments-1.20.1.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,3186 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# ConnectX - Kaggle Environment"
8
+ ]
9
+ },
10
+ {
11
+ "cell_type": "code",
12
+ "execution_count": 1,
13
+ "metadata": {},
14
+ "outputs": [
15
+ {
16
+ "name": "stdout",
17
+ "output_type": "stream",
18
+ "text": [
19
+ "connectx 1.0.1\n",
20
+ "Default Agents: random negamax\n"
21
+ ]
22
+ }
23
+ ],
24
+ "source": [
25
+ "from kaggle_environments import make\n",
26
+ "\n",
27
+ "env = make(\"connectx\")\n",
28
+ "print(env.name, env.version)\n",
29
+ "print(\"Default Agents: \", *env.agents)"
30
+ ]
31
+ },
32
+ {
33
+ "cell_type": "markdown",
34
+ "metadata": {},
35
+ "source": [
36
+ "## TLDR;"
37
+ ]
38
+ },
39
+ {
40
+ "cell_type": "code",
41
+ "execution_count": 2,
42
+ "metadata": {},
43
+ "outputs": [
44
+ {
45
+ "data": {
46
+ "text/html": [
47
+ "<iframe srcdoc=\"<!--\n",
48
+ " Copyright 2020 Kaggle Inc\n",
49
+ "\n",
50
+ " Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);\n",
51
+ " you may not use this file except in compliance with the License.\n",
52
+ " You may obtain a copy of the License at\n",
53
+ "\n",
54
+ " http://www.apache.org/licenses/LICENSE-2.0\n",
55
+ "\n",
56
+ " Unless required by applicable law or agreed to in writing, software\n",
57
+ " distributed under the License is distributed on an &quot;AS IS&quot; BASIS,\n",
58
+ " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
59
+ " See the License for the specific language governing permissions and\n",
60
+ " limitations under the License.\n",
61
+ "-->\n",
62
+ "<!DOCTYPE html>\n",
63
+ "<html lang=&quot;en&quot;>\n",
64
+ " <head>\n",
65
+ " <title>Kaggle Simulation Player</title>\n",
66
+ " <meta name=&quot;viewport&quot; content=&quot;width=device-width,initial-scale=1&quot; />\n",
67
+ " <link\n",
68
+ " rel=&quot;stylesheet&quot;\n",
69
+ " href=&quot;https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.css&quot;\n",
70
+ " crossorigin=&quot;anonymous&quot;\n",
71
+ " />\n",
72
+ " <style type=&quot;text/css&quot;>\n",
73
+ " html,\n",
74
+ " body {\n",
75
+ " height: 100%;\n",
76
+ " font-family: sans-serif;\n",
77
+ " }\n",
78
+ " canvas {\n",
79
+ " /* image-rendering: -moz-crisp-edges;\n",
80
+ " image-rendering: -webkit-crisp-edges;\n",
81
+ " image-rendering: pixelated;\n",
82
+ " image-rendering: crisp-edges; */\n",
83
+ " }\n",
84
+ " </style>\n",
85
+ " <script src=&quot;https://unpkg.com/preact@10.0.1/dist/preact.umd.js&quot;></script>\n",
86
+ " <script src=&quot;https://unpkg.com/preact@10.0.1/hooks/dist/hooks.umd.js&quot;></script>\n",
87
+ " <script src=&quot;https://unpkg.com/htm@2.2.1/dist/htm.umd.js&quot;></script>\n",
88
+ " <script>\n",
89
+ " // Polyfill for Styled Components\n",
90
+ " window.React = {\n",
91
+ " ...preact,\n",
92
+ " createElement: preact.h,\n",
93
+ " PropTypes: { func: {} },\n",
94
+ " };\n",
95
+ " </script>\n",
96
+ " <script src=&quot;https://unpkg.com/styled-components@3.5.0-0/dist/styled-components.min.js&quot;></script>\n",
97
+ " </head>\n",
98
+ " <body>\n",
99
+ " <script>\n",
100
+ " \n",
101
+ "window.kaggle = {\n",
102
+ " &quot;debug&quot;: true,\n",
103
+ " &quot;autoplay&quot;: true,\n",
104
+ " &quot;step&quot;: 0,\n",
105
+ " &quot;controls&quot;: true,\n",
106
+ " &quot;environment&quot;: {\n",
107
+ " &quot;id&quot;: &quot;44d5d36c-8bfb-11ea-8609-acde48001122&quot;,\n",
108
+ " &quot;name&quot;: &quot;connectx&quot;,\n",
109
+ " &quot;title&quot;: &quot;ConnectX&quot;,\n",
110
+ " &quot;description&quot;: &quot;Classic Connect in a row but configurable.&quot;,\n",
111
+ " &quot;version&quot;: &quot;1.0.1&quot;,\n",
112
+ " &quot;configuration&quot;: {\n",
113
+ " &quot;episodeSteps&quot;: 1000,\n",
114
+ " &quot;agentExec&quot;: &quot;PROCESS&quot;,\n",
115
+ " &quot;agentTimeout&quot;: 10,\n",
116
+ " &quot;actTimeout&quot;: 2,\n",
117
+ " &quot;runTimeout&quot;: 600,\n",
118
+ " &quot;columns&quot;: 7,\n",
119
+ " &quot;rows&quot;: 6,\n",
120
+ " &quot;inarow&quot;: 4\n",
121
+ " },\n",
122
+ " &quot;specification&quot;: {\n",
123
+ " &quot;action&quot;: {\n",
124
+ " &quot;description&quot;: &quot;Column to drop a checker onto the board.&quot;,\n",
125
+ " &quot;type&quot;: &quot;integer&quot;,\n",
126
+ " &quot;minimum&quot;: 0,\n",
127
+ " &quot;default&quot;: 0\n",
128
+ " },\n",
129
+ " &quot;agents&quot;: [\n",
130
+ " 2\n",
131
+ " ],\n",
132
+ " &quot;configuration&quot;: {\n",
133
+ " &quot;episodeSteps&quot;: {\n",
134
+ " &quot;description&quot;: &quot;Maximum number of steps in the episode.&quot;,\n",
135
+ " &quot;type&quot;: &quot;integer&quot;,\n",
136
+ " &quot;minimum&quot;: 1,\n",
137
+ " &quot;default&quot;: 1000\n",
138
+ " },\n",
139
+ " &quot;agentExec&quot;: {\n",
140
+ " &quot;description&quot;: &quot;How the agent is executed alongside the running envionment.&quot;,\n",
141
+ " &quot;type&quot;: &quot;string&quot;,\n",
142
+ " &quot;default&quot;: &quot;PROCESS&quot;,\n",
143
+ " &quot;enum&quot;: [\n",
144
+ " &quot;LOCAL&quot;,\n",
145
+ " &quot;PROCESS&quot;\n",
146
+ " ]\n",
147
+ " },\n",
148
+ " &quot;agentTimeout&quot;: {\n",
149
+ " &quot;description&quot;: &quot;Maximum runtime (seconds) to initialize an agent.&quot;,\n",
150
+ " &quot;type&quot;: &quot;integer&quot;,\n",
151
+ " &quot;minimum&quot;: 1,\n",
152
+ " &quot;default&quot;: 10\n",
153
+ " },\n",
154
+ " &quot;actTimeout&quot;: {\n",
155
+ " &quot;description&quot;: &quot;Maximum runtime (seconds) to obtain an action from an agent.&quot;,\n",
156
+ " &quot;type&quot;: &quot;integer&quot;,\n",
157
+ " &quot;minimum&quot;: 1,\n",
158
+ " &quot;default&quot;: 2\n",
159
+ " },\n",
160
+ " &quot;runTimeout&quot;: {\n",
161
+ " &quot;description&quot;: &quot;Maximum runtime (seconds) of an episode (not necessarily DONE).&quot;,\n",
162
+ " &quot;type&quot;: &quot;integer&quot;,\n",
163
+ " &quot;minimum&quot;: 1,\n",
164
+ " &quot;default&quot;: 600\n",
165
+ " },\n",
166
+ " &quot;columns&quot;: {\n",
167
+ " &quot;description&quot;: &quot;The number of columns on the board&quot;,\n",
168
+ " &quot;type&quot;: &quot;integer&quot;,\n",
169
+ " &quot;default&quot;: 7,\n",
170
+ " &quot;minimum&quot;: 1\n",
171
+ " },\n",
172
+ " &quot;rows&quot;: {\n",
173
+ " &quot;description&quot;: &quot;The number of rows on the board&quot;,\n",
174
+ " &quot;type&quot;: &quot;integer&quot;,\n",
175
+ " &quot;default&quot;: 6,\n",
176
+ " &quot;minimum&quot;: 1\n",
177
+ " },\n",
178
+ " &quot;inarow&quot;: {\n",
179
+ " &quot;description&quot;: &quot;The number of checkers in a row required to win.&quot;,\n",
180
+ " &quot;type&quot;: &quot;integer&quot;,\n",
181
+ " &quot;default&quot;: 4,\n",
182
+ " &quot;minimum&quot;: 1\n",
183
+ " }\n",
184
+ " },\n",
185
+ " &quot;info&quot;: {},\n",
186
+ " &quot;observation&quot;: {\n",
187
+ " &quot;board&quot;: {\n",
188
+ " &quot;description&quot;: &quot;Serialized grid (rows x columns). 0 = Empty, 1 = P1, 2 = P2&quot;,\n",
189
+ " &quot;type&quot;: &quot;array&quot;,\n",
190
+ " &quot;shared&quot;: true,\n",
191
+ " &quot;default&quot;: []\n",
192
+ " },\n",
193
+ " &quot;mark&quot;: {\n",
194
+ " &quot;defaults&quot;: [\n",
195
+ " 1,\n",
196
+ " 2\n",
197
+ " ],\n",
198
+ " &quot;description&quot;: &quot;Which checkers are the agents.&quot;,\n",
199
+ " &quot;enum&quot;: [\n",
200
+ " 1,\n",
201
+ " 2\n",
202
+ " ]\n",
203
+ " }\n",
204
+ " },\n",
205
+ " &quot;reward&quot;: {\n",
206
+ " &quot;description&quot;: &quot;-1 = Lost, 0 = Draw/Ongoing, 1 = Won&quot;,\n",
207
+ " &quot;enum&quot;: [\n",
208
+ " -1,\n",
209
+ " 0,\n",
210
+ " 1\n",
211
+ " ],\n",
212
+ " &quot;default&quot;: 0,\n",
213
+ " &quot;type&quot;: [\n",
214
+ " &quot;number&quot;,\n",
215
+ " &quot;null&quot;\n",
216
+ " ]\n",
217
+ " }\n",
218
+ " },\n",
219
+ " &quot;steps&quot;: [\n",
220
+ " [\n",
221
+ " {\n",
222
+ " &quot;action&quot;: 0,\n",
223
+ " &quot;reward&quot;: 0,\n",
224
+ " &quot;info&quot;: {},\n",
225
+ " &quot;observation&quot;: {\n",
226
+ " &quot;board&quot;: [\n",
227
+ " 0,\n",
228
+ " 0,\n",
229
+ " 0,\n",
230
+ " 0,\n",
231
+ " 0,\n",
232
+ " 0,\n",
233
+ " 0,\n",
234
+ " 0,\n",
235
+ " 0,\n",
236
+ " 0,\n",
237
+ " 0,\n",
238
+ " 0,\n",
239
+ " 0,\n",
240
+ " 0,\n",
241
+ " 0,\n",
242
+ " 0,\n",
243
+ " 0,\n",
244
+ " 0,\n",
245
+ " 0,\n",
246
+ " 0,\n",
247
+ " 0,\n",
248
+ " 0,\n",
249
+ " 0,\n",
250
+ " 0,\n",
251
+ " 0,\n",
252
+ " 0,\n",
253
+ " 0,\n",
254
+ " 0,\n",
255
+ " 0,\n",
256
+ " 0,\n",
257
+ " 0,\n",
258
+ " 0,\n",
259
+ " 0,\n",
260
+ " 0,\n",
261
+ " 0,\n",
262
+ " 0,\n",
263
+ " 0,\n",
264
+ " 0,\n",
265
+ " 0,\n",
266
+ " 0,\n",
267
+ " 0,\n",
268
+ " 0\n",
269
+ " ],\n",
270
+ " &quot;mark&quot;: 1\n",
271
+ " },\n",
272
+ " &quot;status&quot;: &quot;ACTIVE&quot;\n",
273
+ " },\n",
274
+ " {\n",
275
+ " &quot;action&quot;: 0,\n",
276
+ " &quot;reward&quot;: 0,\n",
277
+ " &quot;info&quot;: {},\n",
278
+ " &quot;observation&quot;: {\n",
279
+ " &quot;mark&quot;: 2\n",
280
+ " },\n",
281
+ " &quot;status&quot;: &quot;INACTIVE&quot;\n",
282
+ " }\n",
283
+ " ],\n",
284
+ " [\n",
285
+ " {\n",
286
+ " &quot;action&quot;: 0,\n",
287
+ " &quot;reward&quot;: 0,\n",
288
+ " &quot;info&quot;: {},\n",
289
+ " &quot;observation&quot;: {\n",
290
+ " &quot;board&quot;: [\n",
291
+ " 0,\n",
292
+ " 0,\n",
293
+ " 0,\n",
294
+ " 0,\n",
295
+ " 0,\n",
296
+ " 0,\n",
297
+ " 0,\n",
298
+ " 0,\n",
299
+ " 0,\n",
300
+ " 0,\n",
301
+ " 0,\n",
302
+ " 0,\n",
303
+ " 0,\n",
304
+ " 0,\n",
305
+ " 0,\n",
306
+ " 0,\n",
307
+ " 0,\n",
308
+ " 0,\n",
309
+ " 0,\n",
310
+ " 0,\n",
311
+ " 0,\n",
312
+ " 0,\n",
313
+ " 0,\n",
314
+ " 0,\n",
315
+ " 0,\n",
316
+ " 0,\n",
317
+ " 0,\n",
318
+ " 0,\n",
319
+ " 0,\n",
320
+ " 0,\n",
321
+ " 0,\n",
322
+ " 0,\n",
323
+ " 0,\n",
324
+ " 0,\n",
325
+ " 0,\n",
326
+ " 1,\n",
327
+ " 0,\n",
328
+ " 0,\n",
329
+ " 0,\n",
330
+ " 0,\n",
331
+ " 0,\n",
332
+ " 0\n",
333
+ " ],\n",
334
+ " &quot;mark&quot;: 1\n",
335
+ " },\n",
336
+ " &quot;status&quot;: &quot;INACTIVE&quot;\n",
337
+ " },\n",
338
+ " {\n",
339
+ " &quot;action&quot;: 0,\n",
340
+ " &quot;reward&quot;: 0,\n",
341
+ " &quot;info&quot;: {},\n",
342
+ " &quot;observation&quot;: {\n",
343
+ " &quot;mark&quot;: 2\n",
344
+ " },\n",
345
+ " &quot;status&quot;: &quot;ACTIVE&quot;\n",
346
+ " }\n",
347
+ " ],\n",
348
+ " [\n",
349
+ " {\n",
350
+ " &quot;action&quot;: 0,\n",
351
+ " &quot;reward&quot;: 0,\n",
352
+ " &quot;info&quot;: {},\n",
353
+ " &quot;observation&quot;: {\n",
354
+ " &quot;board&quot;: [\n",
355
+ " 0,\n",
356
+ " 0,\n",
357
+ " 0,\n",
358
+ " 0,\n",
359
+ " 0,\n",
360
+ " 0,\n",
361
+ " 0,\n",
362
+ " 0,\n",
363
+ " 0,\n",
364
+ " 0,\n",
365
+ " 0,\n",
366
+ " 0,\n",
367
+ " 0,\n",
368
+ " 0,\n",
369
+ " 0,\n",
370
+ " 0,\n",
371
+ " 0,\n",
372
+ " 0,\n",
373
+ " 0,\n",
374
+ " 0,\n",
375
+ " 0,\n",
376
+ " 0,\n",
377
+ " 0,\n",
378
+ " 0,\n",
379
+ " 0,\n",
380
+ " 0,\n",
381
+ " 0,\n",
382
+ " 0,\n",
383
+ " 0,\n",
384
+ " 0,\n",
385
+ " 0,\n",
386
+ " 0,\n",
387
+ " 0,\n",
388
+ " 0,\n",
389
+ " 0,\n",
390
+ " 1,\n",
391
+ " 0,\n",
392
+ " 2,\n",
393
+ " 0,\n",
394
+ " 0,\n",
395
+ " 0,\n",
396
+ " 0\n",
397
+ " ],\n",
398
+ " &quot;mark&quot;: 1\n",
399
+ " },\n",
400
+ " &quot;status&quot;: &quot;ACTIVE&quot;\n",
401
+ " },\n",
402
+ " {\n",
403
+ " &quot;action&quot;: 2,\n",
404
+ " &quot;reward&quot;: 0,\n",
405
+ " &quot;info&quot;: {},\n",
406
+ " &quot;observation&quot;: {\n",
407
+ " &quot;mark&quot;: 2\n",
408
+ " },\n",
409
+ " &quot;status&quot;: &quot;INACTIVE&quot;\n",
410
+ " }\n",
411
+ " ],\n",
412
+ " [\n",
413
+ " {\n",
414
+ " &quot;action&quot;: 0,\n",
415
+ " &quot;reward&quot;: 0,\n",
416
+ " &quot;info&quot;: {},\n",
417
+ " &quot;observation&quot;: {\n",
418
+ " &quot;board&quot;: [\n",
419
+ " 0,\n",
420
+ " 0,\n",
421
+ " 0,\n",
422
+ " 0,\n",
423
+ " 0,\n",
424
+ " 0,\n",
425
+ " 0,\n",
426
+ " 0,\n",
427
+ " 0,\n",
428
+ " 0,\n",
429
+ " 0,\n",
430
+ " 0,\n",
431
+ " 0,\n",
432
+ " 0,\n",
433
+ " 0,\n",
434
+ " 0,\n",
435
+ " 0,\n",
436
+ " 0,\n",
437
+ " 0,\n",
438
+ " 0,\n",
439
+ " 0,\n",
440
+ " 0,\n",
441
+ " 0,\n",
442
+ " 0,\n",
443
+ " 0,\n",
444
+ " 0,\n",
445
+ " 0,\n",
446
+ " 0,\n",
447
+ " 1,\n",
448
+ " 0,\n",
449
+ " 0,\n",
450
+ " 0,\n",
451
+ " 0,\n",
452
+ " 0,\n",
453
+ " 0,\n",
454
+ " 1,\n",
455
+ " 0,\n",
456
+ " 2,\n",
457
+ " 0,\n",
458
+ " 0,\n",
459
+ " 0,\n",
460
+ " 0\n",
461
+ " ],\n",
462
+ " &quot;mark&quot;: 1\n",
463
+ " },\n",
464
+ " &quot;status&quot;: &quot;INACTIVE&quot;\n",
465
+ " },\n",
466
+ " {\n",
467
+ " &quot;action&quot;: 0,\n",
468
+ " &quot;reward&quot;: 0,\n",
469
+ " &quot;info&quot;: {},\n",
470
+ " &quot;observation&quot;: {\n",
471
+ " &quot;mark&quot;: 2\n",
472
+ " },\n",
473
+ " &quot;status&quot;: &quot;ACTIVE&quot;\n",
474
+ " }\n",
475
+ " ],\n",
476
+ " [\n",
477
+ " {\n",
478
+ " &quot;action&quot;: 0,\n",
479
+ " &quot;reward&quot;: 0,\n",
480
+ " &quot;info&quot;: {},\n",
481
+ " &quot;observation&quot;: {\n",
482
+ " &quot;board&quot;: [\n",
483
+ " 0,\n",
484
+ " 0,\n",
485
+ " 0,\n",
486
+ " 0,\n",
487
+ " 0,\n",
488
+ " 0,\n",
489
+ " 0,\n",
490
+ " 0,\n",
491
+ " 0,\n",
492
+ " 0,\n",
493
+ " 0,\n",
494
+ " 0,\n",
495
+ " 0,\n",
496
+ " 0,\n",
497
+ " 0,\n",
498
+ " 0,\n",
499
+ " 0,\n",
500
+ " 0,\n",
501
+ " 0,\n",
502
+ " 0,\n",
503
+ " 0,\n",
504
+ " 0,\n",
505
+ " 0,\n",
506
+ " 0,\n",
507
+ " 0,\n",
508
+ " 0,\n",
509
+ " 0,\n",
510
+ " 0,\n",
511
+ " 1,\n",
512
+ " 0,\n",
513
+ " 0,\n",
514
+ " 0,\n",
515
+ " 0,\n",
516
+ " 0,\n",
517
+ " 0,\n",
518
+ " 1,\n",
519
+ " 2,\n",
520
+ " 2,\n",
521
+ " 0,\n",
522
+ " 0,\n",
523
+ " 0,\n",
524
+ " 0\n",
525
+ " ],\n",
526
+ " &quot;mark&quot;: 1\n",
527
+ " },\n",
528
+ " &quot;status&quot;: &quot;ACTIVE&quot;\n",
529
+ " },\n",
530
+ " {\n",
531
+ " &quot;action&quot;: 1,\n",
532
+ " &quot;reward&quot;: 0,\n",
533
+ " &quot;info&quot;: {},\n",
534
+ " &quot;observation&quot;: {\n",
535
+ " &quot;mark&quot;: 2\n",
536
+ " },\n",
537
+ " &quot;status&quot;: &quot;INACTIVE&quot;\n",
538
+ " }\n",
539
+ " ],\n",
540
+ " [\n",
541
+ " {\n",
542
+ " &quot;action&quot;: 0,\n",
543
+ " &quot;reward&quot;: 0,\n",
544
+ " &quot;info&quot;: {},\n",
545
+ " &quot;observation&quot;: {\n",
546
+ " &quot;board&quot;: [\n",
547
+ " 0,\n",
548
+ " 0,\n",
549
+ " 0,\n",
550
+ " 0,\n",
551
+ " 0,\n",
552
+ " 0,\n",
553
+ " 0,\n",
554
+ " 0,\n",
555
+ " 0,\n",
556
+ " 0,\n",
557
+ " 0,\n",
558
+ " 0,\n",
559
+ " 0,\n",
560
+ " 0,\n",
561
+ " 0,\n",
562
+ " 0,\n",
563
+ " 0,\n",
564
+ " 0,\n",
565
+ " 0,\n",
566
+ " 0,\n",
567
+ " 0,\n",
568
+ " 1,\n",
569
+ " 0,\n",
570
+ " 0,\n",
571
+ " 0,\n",
572
+ " 0,\n",
573
+ " 0,\n",
574
+ " 0,\n",
575
+ " 1,\n",
576
+ " 0,\n",
577
+ " 0,\n",
578
+ " 0,\n",
579
+ " 0,\n",
580
+ " 0,\n",
581
+ " 0,\n",
582
+ " 1,\n",
583
+ " 2,\n",
584
+ " 2,\n",
585
+ " 0,\n",
586
+ " 0,\n",
587
+ " 0,\n",
588
+ " 0\n",
589
+ " ],\n",
590
+ " &quot;mark&quot;: 1\n",
591
+ " },\n",
592
+ " &quot;status&quot;: &quot;INACTIVE&quot;\n",
593
+ " },\n",
594
+ " {\n",
595
+ " &quot;action&quot;: 0,\n",
596
+ " &quot;reward&quot;: 0,\n",
597
+ " &quot;info&quot;: {},\n",
598
+ " &quot;observation&quot;: {\n",
599
+ " &quot;mark&quot;: 2\n",
600
+ " },\n",
601
+ " &quot;status&quot;: &quot;ACTIVE&quot;\n",
602
+ " }\n",
603
+ " ],\n",
604
+ " [\n",
605
+ " {\n",
606
+ " &quot;action&quot;: 0,\n",
607
+ " &quot;reward&quot;: 0,\n",
608
+ " &quot;info&quot;: {},\n",
609
+ " &quot;observation&quot;: {\n",
610
+ " &quot;board&quot;: [\n",
611
+ " 0,\n",
612
+ " 0,\n",
613
+ " 0,\n",
614
+ " 0,\n",
615
+ " 0,\n",
616
+ " 0,\n",
617
+ " 0,\n",
618
+ " 0,\n",
619
+ " 0,\n",
620
+ " 0,\n",
621
+ " 0,\n",
622
+ " 0,\n",
623
+ " 0,\n",
624
+ " 0,\n",
625
+ " 0,\n",
626
+ " 0,\n",
627
+ " 0,\n",
628
+ " 0,\n",
629
+ " 0,\n",
630
+ " 0,\n",
631
+ " 0,\n",
632
+ " 1,\n",
633
+ " 0,\n",
634
+ " 0,\n",
635
+ " 0,\n",
636
+ " 0,\n",
637
+ " 0,\n",
638
+ " 0,\n",
639
+ " 1,\n",
640
+ " 0,\n",
641
+ " 0,\n",
642
+ " 0,\n",
643
+ " 0,\n",
644
+ " 0,\n",
645
+ " 0,\n",
646
+ " 1,\n",
647
+ " 2,\n",
648
+ " 2,\n",
649
+ " 0,\n",
650
+ " 0,\n",
651
+ " 0,\n",
652
+ " 2\n",
653
+ " ],\n",
654
+ " &quot;mark&quot;: 1\n",
655
+ " },\n",
656
+ " &quot;status&quot;: &quot;ACTIVE&quot;\n",
657
+ " },\n",
658
+ " {\n",
659
+ " &quot;action&quot;: 6,\n",
660
+ " &quot;reward&quot;: 0,\n",
661
+ " &quot;info&quot;: {},\n",
662
+ " &quot;observation&quot;: {\n",
663
+ " &quot;mark&quot;: 2\n",
664
+ " },\n",
665
+ " &quot;status&quot;: &quot;INACTIVE&quot;\n",
666
+ " }\n",
667
+ " ],\n",
668
+ " [\n",
669
+ " {\n",
670
+ " &quot;action&quot;: 0,\n",
671
+ " &quot;reward&quot;: 1,\n",
672
+ " &quot;info&quot;: {},\n",
673
+ " &quot;observation&quot;: {\n",
674
+ " &quot;board&quot;: [\n",
675
+ " 0,\n",
676
+ " 0,\n",
677
+ " 0,\n",
678
+ " 0,\n",
679
+ " 0,\n",
680
+ " 0,\n",
681
+ " 0,\n",
682
+ " 0,\n",
683
+ " 0,\n",
684
+ " 0,\n",
685
+ " 0,\n",
686
+ " 0,\n",
687
+ " 0,\n",
688
+ " 0,\n",
689
+ " 1,\n",
690
+ " 0,\n",
691
+ " 0,\n",
692
+ " 0,\n",
693
+ " 0,\n",
694
+ " 0,\n",
695
+ " 0,\n",
696
+ " 1,\n",
697
+ " 0,\n",
698
+ " 0,\n",
699
+ " 0,\n",
700
+ " 0,\n",
701
+ " 0,\n",
702
+ " 0,\n",
703
+ " 1,\n",
704
+ " 0,\n",
705
+ " 0,\n",
706
+ " 0,\n",
707
+ " 0,\n",
708
+ " 0,\n",
709
+ " 0,\n",
710
+ " 1,\n",
711
+ " 2,\n",
712
+ " 2,\n",
713
+ " 0,\n",
714
+ " 0,\n",
715
+ " 0,\n",
716
+ " 2\n",
717
+ " ],\n",
718
+ " &quot;mark&quot;: 1\n",
719
+ " },\n",
720
+ " &quot;status&quot;: &quot;DONE&quot;\n",
721
+ " },\n",
722
+ " {\n",
723
+ " &quot;action&quot;: 0,\n",
724
+ " &quot;reward&quot;: -1,\n",
725
+ " &quot;info&quot;: {},\n",
726
+ " &quot;observation&quot;: {\n",
727
+ " &quot;mark&quot;: 2\n",
728
+ " },\n",
729
+ " &quot;status&quot;: &quot;DONE&quot;\n",
730
+ " }\n",
731
+ " ]\n",
732
+ " ],\n",
733
+ " &quot;rewards&quot;: [\n",
734
+ " 1,\n",
735
+ " -1\n",
736
+ " ],\n",
737
+ " &quot;statuses&quot;: [\n",
738
+ " &quot;DONE&quot;,\n",
739
+ " &quot;DONE&quot;\n",
740
+ " ],\n",
741
+ " &quot;schema_version&quot;: 1\n",
742
+ " },\n",
743
+ " &quot;mode&quot;: &quot;ipython&quot;,\n",
744
+ " &quot;width&quot;: 600,\n",
745
+ " &quot;height&quot;: 500,\n",
746
+ " &quot;header&quot;: false\n",
747
+ "};\n",
748
+ "\n",
749
+ "\n",
750
+ "window.kaggle.renderer = // Copyright 2020 Kaggle Inc\n",
751
+ "//\n",
752
+ "// Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);\n",
753
+ "// you may not use this file except in compliance with the License.\n",
754
+ "// You may obtain a copy of the License at\n",
755
+ "//\n",
756
+ "// http://www.apache.org/licenses/LICENSE-2.0\n",
757
+ "//\n",
758
+ "// Unless required by applicable law or agreed to in writing, software\n",
759
+ "// distributed under the License is distributed on an &quot;AS IS&quot; BASIS,\n",
760
+ "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
761
+ "// See the License for the specific language governing permissions and\n",
762
+ "// limitations under the License.\n",
763
+ "\n",
764
+ "function renderer({\n",
765
+ " act,\n",
766
+ " agents,\n",
767
+ " environment,\n",
768
+ " frame,\n",
769
+ " height = 400,\n",
770
+ " interactive,\n",
771
+ " isInteractive,\n",
772
+ " parent,\n",
773
+ " step,\n",
774
+ " update,\n",
775
+ " width = 400,\n",
776
+ "}) {\n",
777
+ " // Configuration.\n",
778
+ " const { rows, columns, inarow } = environment.configuration;\n",
779
+ "\n",
780
+ " // Common Dimensions.\n",
781
+ " const unit = 8;\n",
782
+ " const minCanvasSize = Math.min(height, width);\n",
783
+ " const minOffset = minCanvasSize > 400 ? 30 : unit / 2;\n",
784
+ " const cellSize = Math.min(\n",
785
+ " (width - minOffset * 2) / columns,\n",
786
+ " (height - minOffset * 2) / rows\n",
787
+ " );\n",
788
+ " const cellInset = 0.8;\n",
789
+ " const pieceScale = cellSize / 100;\n",
790
+ " const xOffset = Math.max(0, (width - cellSize * columns) / 2);\n",
791
+ " const yOffset = Math.max(0, (height - cellSize * rows) / 2);\n",
792
+ "\n",
793
+ " // Canvas Setup.\n",
794
+ " let canvas = parent.querySelector(&quot;canvas&quot;);\n",
795
+ " if (!canvas) {\n",
796
+ " canvas = document.createElement(&quot;canvas&quot;);\n",
797
+ " parent.appendChild(canvas);\n",
798
+ "\n",
799
+ " if (interactive) {\n",
800
+ " canvas.addEventListener(&quot;click&quot;, evt => {\n",
801
+ " if (!isInteractive()) return;\n",
802
+ " const rect = evt.target.getBoundingClientRect();\n",
803
+ " const col = Math.floor((evt.clientX - rect.left - xOffset) / cellSize);\n",
804
+ " if (col >= 0 && col < columns) act(col);\n",
805
+ " });\n",
806
+ " }\n",
807
+ " }\n",
808
+ " canvas.style.cursor = isInteractive() ? &quot;pointer&quot; : &quot;default&quot;;\n",
809
+ "\n",
810
+ " // Character Paths (based on 100x100 tiles).\n",
811
+ " const kPath = new Path2D(\n",
812
+ " `M78.3,96.5c-0.1,0.4-0.5,0.6-1.1,0.6H64.9c-0.7,0-1.4-0.3-1.9-1l-20.3-26L37,75.5v20.1 c0,0.9-0.5,1.4-1.4,1.4H26c-0.9,0-1.4-0.5-1.4-1.4V3.9c0-0.9,0.5-1.4,1.4-1.4h9.5C36.5,2.5,37,3,37,3.9v56.5l24.3-24.7 c0.6-0.6,1.3-1,1.9-1H76c0.6,0,0.9,0.2,1.1,0.7c0.2,0.6,0.1,1-0.1,1.2l-25.7,25L78,95.1C78.4,95.5,78.5,95.9,78.3,96.5z`\n",
813
+ " );\n",
814
+ " const goose1Path = new Path2D(\n",
815
+ " `M8.8,92.7c-4-18.5,4.7-37.2,20.7-46.2c0,0,2.7-1.4,3.4-1.9c2.2-1.6,3-2.1,3-5c0-5-2.1-7.2-2.1-7.2 c-3.9-3.3-6.3-8.2-6.3-13.7c0-10,8.1-18.1,18.1-18.1s18.1,8.1,18.1,18.1c0,6-1.5,32.7-2.3,38.8l-0.1,1`\n",
816
+ " );\n",
817
+ " const goose2Path = new Path2D(\n",
818
+ " `M27.4,19L8.2,27.6c0,0-7.3,2.9,2.6,5c6.1,1.3,24,5.9,24,5.9l1,0.3`\n",
819
+ " );\n",
820
+ " const goose3Path = new Path2D(\n",
821
+ " `M63.7,99.6C52.3,99.6,43,90.3,43,78.9s9.3-20.7,20.7-20.7c10.6,0,34.4,0.1,35.8,9`\n",
822
+ " );\n",
823
+ "\n",
824
+ " // Canvas setup and reset.\n",
825
+ " let c = canvas.getContext(&quot;2d&quot;);\n",
826
+ " canvas.width = width;\n",
827
+ " canvas.height = height;\n",
828
+ " c.fillStyle = &quot;#000B2A&quot;;\n",
829
+ " c.fillRect(0, 0, canvas.width, canvas.height);\n",
830
+ "\n",
831
+ " const getRowCol = cell => [Math.floor(cell / columns), cell % columns];\n",
832
+ "\n",
833
+ " const getColor = (mark, opacity = 1) => {\n",
834
+ " if (mark === 1) return `rgba(0,255,255,${opacity})`;\n",
835
+ " if (mark === 2) return `rgba(255,255,255,${opacity})`;\n",
836
+ " return &quot;#fff&quot;;\n",
837
+ " };\n",
838
+ "\n",
839
+ " const drawCellCircle = (cell, xFrame = 1, yFrame = 1, radiusOffset = 0) => {\n",
840
+ " const [row, col] = getRowCol(cell);\n",
841
+ " c.arc(\n",
842
+ " xOffset + xFrame * (col * cellSize + cellSize / 2),\n",
843
+ " yOffset + yFrame * (row * cellSize + cellSize / 2),\n",
844
+ " (cellInset * cellSize) / 2 - radiusOffset,\n",
845
+ " 2 * Math.PI,\n",
846
+ " false\n",
847
+ " );\n",
848
+ " };\n",
849
+ "\n",
850
+ " // Render the pieces.\n",
851
+ " const board = environment.steps[step][0].observation.board;\n",
852
+ "\n",
853
+ " const drawPiece = mark => {\n",
854
+ " // Base Styles.\n",
855
+ " const opacity = minCanvasSize < 300 ? 0.6 - minCanvasSize / 1000 : 0.1;\n",
856
+ " c.fillStyle = getColor(mark, opacity);\n",
857
+ " c.strokeStyle = getColor(mark);\n",
858
+ " c.shadowColor = getColor(mark);\n",
859
+ " c.shadowBlur = 8 / cellInset;\n",
860
+ " c.lineWidth = 1 / cellInset;\n",
861
+ "\n",
862
+ " // Outer circle.\n",
863
+ " c.save();\n",
864
+ " c.beginPath();\n",
865
+ " c.arc(50, 50, 50, 2 * Math.PI, false);\n",
866
+ " c.closePath();\n",
867
+ " c.lineWidth *= 4;\n",
868
+ " c.stroke();\n",
869
+ " c.fill();\n",
870
+ " c.restore();\n",
871
+ "\n",
872
+ " // Inner circle.\n",
873
+ " c.beginPath();\n",
874
+ " c.arc(50, 50, 40, 2 * Math.PI, false);\n",
875
+ " c.closePath();\n",
876
+ " c.stroke();\n",
877
+ "\n",
878
+ " // Kaggle &quot;K&quot;.\n",
879
+ " if (mark === 1) {\n",
880
+ " const scale = 0.54;\n",
881
+ " c.save();\n",
882
+ " c.translate(23, 23);\n",
883
+ " c.scale(scale, scale);\n",
884
+ " c.lineWidth /= scale;\n",
885
+ " c.shadowBlur /= scale;\n",
886
+ " c.stroke(kPath);\n",
887
+ " c.restore();\n",
888
+ " }\n",
889
+ "\n",
890
+ " // Kaggle &quot;Goose&quot;.\n",
891
+ " if (mark === 2) {\n",
892
+ " const scale = 0.6;\n",
893
+ " c.save();\n",
894
+ " c.translate(24, 28);\n",
895
+ " c.scale(scale, scale);\n",
896
+ " c.lineWidth /= scale;\n",
897
+ " c.shadowBlur /= scale;\n",
898
+ " c.stroke(goose1Path);\n",
899
+ " c.stroke(goose2Path);\n",
900
+ " c.stroke(goose3Path);\n",
901
+ " c.beginPath();\n",
902
+ " c.arc(38.5, 18.6, 2.7, 0, Math.PI * 2, false);\n",
903
+ " c.closePath();\n",
904
+ " c.fill();\n",
905
+ " c.restore();\n",
906
+ " }\n",
907
+ " };\n",
908
+ "\n",
909
+ " for (let i = 0; i < board.length; i++) {\n",
910
+ " const [row, col] = getRowCol(i);\n",
911
+ " if (board[i] === 0) continue;\n",
912
+ " // Easing In.\n",
913
+ " let yFrame = Math.min(\n",
914
+ " (columns * Math.pow(frame, 3)) / Math.floor(i / columns),\n",
915
+ " 1\n",
916
+ " );\n",
917
+ "\n",
918
+ " if (\n",
919
+ " step > 1 &&\n",
920
+ " environment.steps[step - 1][0].observation.board[i] === board[i]\n",
921
+ " ) {\n",
922
+ " yFrame = 1;\n",
923
+ " }\n",
924
+ "\n",
925
+ " c.save();\n",
926
+ " c.translate(\n",
927
+ " xOffset + cellSize * col + (cellSize - cellSize * cellInset) / 2,\n",
928
+ " yOffset +\n",
929
+ " yFrame * (cellSize * row) +\n",
930
+ " (cellSize - cellSize * cellInset) / 2\n",
931
+ " );\n",
932
+ " c.scale(pieceScale * cellInset, pieceScale * cellInset);\n",
933
+ " drawPiece(board[i]);\n",
934
+ " c.restore();\n",
935
+ " }\n",
936
+ "\n",
937
+ " // Background Gradient.\n",
938
+ " const bgRadius = (Math.min(rows, columns) * cellSize) / 2;\n",
939
+ " const bgStyle = c.createRadialGradient(\n",
940
+ " xOffset + (cellSize * columns) / 2,\n",
941
+ " yOffset + (cellSize * rows) / 2,\n",
942
+ " 0,\n",
943
+ " xOffset + (cellSize * columns) / 2,\n",
944
+ " yOffset + (cellSize * rows) / 2,\n",
945
+ " bgRadius\n",
946
+ " );\n",
947
+ " bgStyle.addColorStop(0, &quot;#000B49&quot;);\n",
948
+ " bgStyle.addColorStop(1, &quot;#000B2A&quot;);\n",
949
+ "\n",
950
+ " // Render the board overlay.\n",
951
+ " c.beginPath();\n",
952
+ " c.rect(0, 0, canvas.width, canvas.height);\n",
953
+ " c.closePath();\n",
954
+ " c.shadowBlur = 0;\n",
955
+ " for (let i = 0; i < board.length; i++) {\n",
956
+ " drawCellCircle(i);\n",
957
+ " c.closePath();\n",
958
+ " }\n",
959
+ " c.fillStyle = bgStyle;\n",
960
+ " c.fill(&quot;evenodd&quot;);\n",
961
+ "\n",
962
+ " // Render the board overlay cell outlines.\n",
963
+ " for (let i = 0; i < board.length; i++) {\n",
964
+ " c.beginPath();\n",
965
+ " drawCellCircle(i);\n",
966
+ " c.strokeStyle = &quot;#0361B2&quot;;\n",
967
+ " c.lineWidth = 1;\n",
968
+ " c.stroke();\n",
969
+ " c.closePath();\n",
970
+ " }\n",
971
+ "\n",
972
+ " const drawLine = (fromCell, toCell) => {\n",
973
+ " if (frame < 0.5) return;\n",
974
+ " const lineFrame = (frame - 0.5) / 0.5;\n",
975
+ " const x1 = xOffset + (fromCell % columns) * cellSize + cellSize / 2;\n",
976
+ " const x2 =\n",
977
+ " x1 +\n",
978
+ " lineFrame *\n",
979
+ " (xOffset + ((toCell % columns) * cellSize + cellSize / 2) - x1);\n",
980
+ " const y1 =\n",
981
+ " yOffset + Math.floor(fromCell / columns) * cellSize + cellSize / 2;\n",
982
+ " const y2 =\n",
983
+ " y1 +\n",
984
+ " lineFrame *\n",
985
+ " (yOffset + Math.floor(toCell / columns) * cellSize + cellSize / 2 - y1);\n",
986
+ " c.beginPath();\n",
987
+ " c.lineCap = &quot;round&quot;;\n",
988
+ " c.lineWidth = 4;\n",
989
+ " c.strokeStyle = getColor(board[fromCell]);\n",
990
+ " c.shadowBlur = 8;\n",
991
+ " c.shadowColor = getColor(board[fromCell]);\n",
992
+ " c.moveTo(x1, y1);\n",
993
+ " c.lineTo(x2, y2);\n",
994
+ " c.stroke();\n",
995
+ " };\n",
996
+ "\n",
997
+ " // Generate a graph of the board.\n",
998
+ " const getCell = (cell, rowOffset, columnOffset) => {\n",
999
+ " const row = Math.floor(cell / columns) + rowOffset;\n",
1000
+ " const col = (cell % columns) + columnOffset;\n",
1001
+ " if (row < 0 || row >= rows || col < 0 || col >= columns) return -1;\n",
1002
+ " return col + row * columns;\n",
1003
+ " };\n",
1004
+ " const makeNode = cell => {\n",
1005
+ " const node = { cell, directions: [], value: board[cell] };\n",
1006
+ " for (let r = -1; r <= 1; r++) {\n",
1007
+ " for (let c = -1; c <= 1; c++) {\n",
1008
+ " if (r === 0 && c === 0) continue;\n",
1009
+ " node.directions.push(getCell(cell, r, c));\n",
1010
+ " }\n",
1011
+ " }\n",
1012
+ " return node;\n",
1013
+ " };\n",
1014
+ " const graph = board.map((_, i) => makeNode(i));\n",
1015
+ "\n",
1016
+ " // Check for any wins!\n",
1017
+ " const getSequence = (node, direction) => {\n",
1018
+ " const sequence = [node.cell];\n",
1019
+ " while (sequence.length < inarow) {\n",
1020
+ " const next = graph[node.directions[direction]];\n",
1021
+ " if (!next || node.value !== next.value || next.value === 0) return;\n",
1022
+ " node = next;\n",
1023
+ " sequence.push(node.cell);\n",
1024
+ " }\n",
1025
+ " return sequence;\n",
1026
+ " };\n",
1027
+ "\n",
1028
+ " // Check all nodes.\n",
1029
+ " for (let i = 0; i < board.length; i++) {\n",
1030
+ " // Check all directions (not the most efficient).\n",
1031
+ " for (let d = 0; d < 8; d++) {\n",
1032
+ " const seq = getSequence(graph[i], d);\n",
1033
+ " if (seq) {\n",
1034
+ " drawLine(seq[0], seq[3]);\n",
1035
+ " i = board.length;\n",
1036
+ " break;\n",
1037
+ " }\n",
1038
+ " }\n",
1039
+ " }\n",
1040
+ "\n",
1041
+ " // Upgrade the legend.\n",
1042
+ " if (agents.length && (!agents[0].color || !agents[0].image)) {\n",
1043
+ " const getPieceImage = mark => {\n",
1044
+ " const pieceCanvas = document.createElement(&quot;canvas&quot;);\n",
1045
+ " parent.appendChild(pieceCanvas);\n",
1046
+ " pieceCanvas.style.marginLeft = &quot;10000px&quot;;\n",
1047
+ " pieceCanvas.width = 100;\n",
1048
+ " pieceCanvas.height = 100;\n",
1049
+ " c = pieceCanvas.getContext(&quot;2d&quot;);\n",
1050
+ " c.translate(10, 10);\n",
1051
+ " c.scale(0.8, 0.8);\n",
1052
+ " drawPiece(mark);\n",
1053
+ " const dataUrl = pieceCanvas.toDataURL();\n",
1054
+ " parent.removeChild(pieceCanvas);\n",
1055
+ " return dataUrl;\n",
1056
+ " };\n",
1057
+ "\n",
1058
+ " agents.forEach(agent => {\n",
1059
+ " agent.color = getColor(agent.index + 1);\n",
1060
+ " agent.image = getPieceImage(agent.index + 1);\n",
1061
+ " });\n",
1062
+ " update({ agents });\n",
1063
+ " }\n",
1064
+ "};\n",
1065
+ "\n",
1066
+ "\n",
1067
+ " \n",
1068
+ " </script>\n",
1069
+ " <script>\n",
1070
+ " const h = htm.bind(preact.h);\n",
1071
+ " const { useContext, useEffect, useRef, useState } = preactHooks;\n",
1072
+ " const styled = window.styled.default;\n",
1073
+ "\n",
1074
+ " const Context = preact.createContext({});\n",
1075
+ "\n",
1076
+ " const Loading = styled.div`\n",
1077
+ " animation: rotate360 1.1s infinite linear;\n",
1078
+ " border: 8px solid rgba(255, 255, 255, 0.2);\n",
1079
+ " border-left-color: #0cb1ed;\n",
1080
+ " border-radius: 50%;\n",
1081
+ " height: 40px;\n",
1082
+ " position: relative;\n",
1083
+ " transform: translateZ(0);\n",
1084
+ " width: 40px;\n",
1085
+ "\n",
1086
+ " @keyframes rotate360 {\n",
1087
+ " 0% {\n",
1088
+ " transform: rotate(0deg);\n",
1089
+ " }\n",
1090
+ " 100% {\n",
1091
+ " transform: rotate(360deg);\n",
1092
+ " }\n",
1093
+ " }\n",
1094
+ " `;\n",
1095
+ "\n",
1096
+ " const Logo = styled(\n",
1097
+ " (props) => h`\n",
1098
+ " <a href=&quot;https://kaggle.com&quot; target=&quot;_blank&quot; className=${props.className}>\n",
1099
+ " <svg width=&quot;62px&quot; height=&quot;20px&quot; viewBox=&quot;0 0 62 24&quot; version=&quot;1.1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;>\n",
1100
+ " <g fill=&quot;#1EBEFF&quot; fill-rule=&quot;nonzero&quot;>\n",
1101
+ " <path d=&quot;M10.2,17.8c0,0.1-0.1,0.1-0.2,0.1H7.7c-0.1,0-0.3-0.1-0.4-0.2l-3.8-4.9l-1.1,1v3.8 c0,0.2-0.1,0.3-0.3,0.3H0.3c-0.2,0-0.3-0.1-0.3-0.3V0.3C0.1,0.1,0.2,0,0.3,0h1.8c0.2,0,0.3,0.1,0.3,0.3V11L7,6.3 c0.1-0.1,0.2-0.2,0.4-0.2h2.4c0.1,0,0.2,0,0.2,0.1c0,0.1,0,0.2,0,0.2l-4.9,4.7l5.1,6.3C10.2,17.6,10.2,17.7,10.2,17.8z&quot;/>\n",
1102
+ " <path d=&quot;M19.6,17.9h-1.8c-0.2,0-0.3-0.1-0.3-0.3v-0.4c-0.8,0.6-1.8,0.9-3,0.9c-1.1,0-2-0.3-2.8-1 c-0.8-0.7-1.2-1.6-1.2-2.7c0-1.7,1.1-2.9,3.2-3.5c0.8-0.2,2.1-0.5,3.8-0.6c0.1-0.6-0.1-1.2-0.5-1.7c-0.4-0.5-1-0.7-1.7-0.7 c-1,0-2,0.4-3,1C12.2,9.1,12.1,9.1,12,9l-0.9-1.3C11,7.5,11,7.4,11.1,7.3c1.3-0.9,2.7-1.4,4.2-1.4c1.1,0,2.1,0.3,2.8,0.8 c1.1,0.8,1.7,2,1.7,3.7v7.3C19.9,17.8,19.8,17.9,19.6,17.9z M17.5,12.4c-1.7,0.2-2.9,0.4-3.5,0.7c-0.9,0.4-1.2,0.9-1.1,1.6 c0.1,0.4,0.2,0.7,0.6,0.9c0.3,0.2,0.7,0.4,1.1,0.4c1.2,0.1,2.2-0.2,2.9-1V12.4z&quot;/>\n",
1103
+ " <path d=&quot;M30.6,22.5c-0.9,1-2.3,1.5-4,1.5c-1,0-2-0.3-2.9-0.8c-0.2-0.1-0.4-0.3-0.7-0.5 c-0.3-0.2-0.6-0.5-0.9-0.7c-0.1-0.1-0.1-0.2,0-0.4l1.2-1.2c0.1-0.1,0.1-0.1,0.2-0.1c0.1,0,0.1,0,0.2,0.1c1,1,1.9,1.5,2.8,1.5 c2.1,0,3.2-1.1,3.2-3.3v-1.4c-0.8,0.7-1.9,1-3.3,1c-1.7,0-3-0.6-4-1.9c-0.8-1.1-1.3-2.5-1.3-4.2c0-1.6,0.4-3,1.2-4.1 c0.9-1.3,2.3-2,4-2c1.3,0,2.4,0.3,3.3,1V6.4c0-0.2,0.1-0.3,0.3-0.3h1.8c0.2,0,0.3,0.1,0.3,0.3v11.7C32,20,31.5,21.5,30.6,22.5z M29.7,9.9c-0.4-1.1-1.4-1.7-3-1.7c-2,0-3.1,1.3-3.1,3.8c0,1.4,0.3,2.4,1,3.1c0.5,0.5,1.2,0.8,2,0.8c1.6,0,2.7-0.6,3.1-1.7V9.9z&quot;/>\n",
1104
+ " <path d=&quot;M42.9,22.5c-0.9,1-2.3,1.5-4,1.5c-1,0-2-0.3-2.9-0.8c-0.2-0.1-0.4-0.3-0.7-0.5 c-0.3-0.2-0.6-0.5-0.9-0.7c-0.1-0.1-0.1-0.2,0-0.4l1.2-1.2c0.1-0.1,0.1-0.1,0.2-0.1c0.1,0,0.1,0,0.2,0.1c1,1,1.9,1.5,2.8,1.5 c2.1,0,3.2-1.1,3.2-3.3v-1.4c-0.8,0.7-1.9,1-3.3,1c-1.7,0-3-0.6-4-1.9c-0.8-1.1-1.3-2.5-1.3-4.2c0-1.6,0.4-3,1.2-4.1 c0.9-1.3,2.3-2,4-2c1.3,0,2.4,0.3,3.3,1V6.4c0-0.2,0.1-0.3,0.3-0.3H44c0.2,0,0.3,0.1,0.3,0.3v11.7C44.3,20,43.8,21.5,42.9,22.5z M42,9.9c-0.4-1.1-1.4-1.7-3-1.7c-2,0-3.1,1.3-3.1,3.8c0,1.4,0.3,2.4,1,3.1c0.5,0.5,1.2,0.8,2,0.8c1.6,0,2.7-0.6,3.1-1.7L42,9.9 L42,9.9z&quot;/>\n",
1105
+ " <path d=&quot;M48.3,17.9h-1.8c-0.2,0-0.3-0.1-0.3-0.3V0.3c0-0.2,0.1-0.3,0.3-0.3h1.8c0.2,0,0.3,0.1,0.3,0.3 v17.3C48.5,17.8,48.5,17.9,48.3,17.9z&quot;/>\n",
1106
+ " <path d=&quot;M61.4,12.6c0,0.2-0.1,0.3-0.3,0.3h-8.5c0.1,0.9,0.5,1.6,1.1,2.2c0.7,0.6,1.6,0.9,2.7,0.9 c1,0,1.8-0.3,2.6-0.8c0.2-0.1,0.3-0.1,0.4,0l1.2,1.3c0.1,0.1,0.1,0.3,0,0.4c-1.3,0.9-2.7,1.4-4.4,1.4c-1.8,0-3.3-0.6-4.4-1.8 c-1.1-1.2-1.7-2.7-1.7-4.5c0-1.7,0.6-3.2,1.7-4.4c1-1.1,2.4-1.6,4.1-1.6c1.6,0,2.9,0.6,4,1.7c1.1,1.2,1.6,2.6,1.5,4.4L61.4,12.6 z M58,8.7c-0.6-0.5-1.3-0.8-2.1-0.8c-0.8,0-1.5,0.3-2.1,0.8c-0.6,0.5-1,1.2-1.1,2H59C59,9.9,58.6,9.3,58,8.7z&quot;/>\n",
1107
+ " </g>\n",
1108
+ " </svg>\n",
1109
+ " </a>\n",
1110
+ " `\n",
1111
+ " )`\n",
1112
+ " display: inline-flex;\n",
1113
+ " `;\n",
1114
+ "\n",
1115
+ " const Header = styled((props) => {\n",
1116
+ " const { environment } = useContext(Context);\n",
1117
+ "\n",
1118
+ " return h`<div className=${props.className} >\n",
1119
+ " <${Logo} />\n",
1120
+ " ${environment.title}\n",
1121
+ " </div>`;\n",
1122
+ " })`\n",
1123
+ " align-items: center;\n",
1124
+ " border-bottom: 4px solid #212121;\n",
1125
+ " box-sizing: border-box;\n",
1126
+ " color: #fff;\n",
1127
+ " display: flex;\n",
1128
+ " flex: 0 0 36px;\n",
1129
+ " font-size: 14px;\n",
1130
+ " justify-content: space-between;\n",
1131
+ " padding: 0 8px;\n",
1132
+ " width: 100%;\n",
1133
+ " `;\n",
1134
+ "\n",
1135
+ " const Renderer = styled((props) => {\n",
1136
+ " const context = useContext(Context);\n",
1137
+ " const { animate, debug, playing, renderer, speed } = context;\n",
1138
+ " const ref = preact.createRef();\n",
1139
+ "\n",
1140
+ " useEffect(async () => {\n",
1141
+ " if (!ref.current) return;\n",
1142
+ "\n",
1143
+ " const renderFrame = async (start, step, lastFrame) => {\n",
1144
+ " if (step !== context.step) return;\n",
1145
+ " if (lastFrame === 1) {\n",
1146
+ " if (!animate) return;\n",
1147
+ " start = Date.now();\n",
1148
+ " }\n",
1149
+ " const frame =\n",
1150
+ " playing || animate\n",
1151
+ " ? Math.min((Date.now() - start) / speed, 1)\n",
1152
+ " : 1;\n",
1153
+ " try {\n",
1154
+ " if (debug) console.time(&quot;render&quot;);\n",
1155
+ " await renderer({\n",
1156
+ " ...context,\n",
1157
+ " frame,\n",
1158
+ " height: ref.current.clientHeight,\n",
1159
+ " hooks: preactHooks,\n",
1160
+ " parent: ref.current,\n",
1161
+ " preact,\n",
1162
+ " styled,\n",
1163
+ " width: ref.current.clientWidth,\n",
1164
+ " });\n",
1165
+ " } catch (error) {\n",
1166
+ " if (debug) console.error(error);\n",
1167
+ " console.log({ ...context, frame, error });\n",
1168
+ " } finally {\n",
1169
+ " if (debug) console.timeEnd(&quot;render&quot;);\n",
1170
+ " }\n",
1171
+ " window.requestAnimationFrame(() => renderFrame(start, step, frame));\n",
1172
+ " };\n",
1173
+ "\n",
1174
+ " await renderFrame(Date.now(), context.step);\n",
1175
+ " }, [ref.current, context.step, context.renderer]);\n",
1176
+ "\n",
1177
+ " return h`<div className=${props.className} ref=${ref} />`;\n",
1178
+ " })`\n",
1179
+ " align-items: center;\n",
1180
+ " box-sizing: border-box;\n",
1181
+ " display: flex;\n",
1182
+ " height: 100%;\n",
1183
+ " left: 0;\n",
1184
+ " justify-content: center;\n",
1185
+ " position: absolute;\n",
1186
+ " top: 0;\n",
1187
+ " width: 100%;\n",
1188
+ " `;\n",
1189
+ "\n",
1190
+ " const Processing = styled((props) => {\n",
1191
+ " const { processing } = useContext(Context);\n",
1192
+ " const text = processing === true ? &quot;Processing...&quot; : processing;\n",
1193
+ " return h`<div className=${props.className}>${text}</div>`;\n",
1194
+ " })`\n",
1195
+ " bottom: 0;\n",
1196
+ " color: #fff;\n",
1197
+ " font-size: 12px;\n",
1198
+ " left: 0;\n",
1199
+ " line-height: 24px;\n",
1200
+ " position: absolute;\n",
1201
+ " text-align: center;\n",
1202
+ " width: 100%;\n",
1203
+ " `;\n",
1204
+ "\n",
1205
+ " const Viewer = styled((props) => {\n",
1206
+ " const { processing } = useContext(Context);\n",
1207
+ " return h`<div className=${props.className}>\n",
1208
+ " <${Renderer} />\n",
1209
+ " ${processing && h`<${Processing} />`}\n",
1210
+ " </div>`;\n",
1211
+ " })`\n",
1212
+ " background-color: #000b2a;\n",
1213
+ " background-image: radial-gradient(\n",
1214
+ " circle closest-side,\n",
1215
+ " #000b49,\n",
1216
+ " #000b2a\n",
1217
+ " );\n",
1218
+ " display: flex;\n",
1219
+ " flex: 1;\n",
1220
+ " overflow: hidden;\n",
1221
+ " position: relative;\n",
1222
+ " width: 100%;\n",
1223
+ " `;\n",
1224
+ "\n",
1225
+ " const Legend = styled((props) => {\n",
1226
+ " const { agents, legend } = useContext(Context);\n",
1227
+ "\n",
1228
+ " return h`<div className=${props.className}>\n",
1229
+ " <ul>\n",
1230
+ " ${agents\n",
1231
+ " .sort((a, b) => a.index - b.index)\n",
1232
+ " .map(\n",
1233
+ " (a) =>\n",
1234
+ " h`<li key=${a.id} title=&quot;id: ${a.id}&quot; style=&quot;color:${\n",
1235
+ " a.color || &quot;#FFF&quot;\n",
1236
+ " }&quot;>${a.image && h`<img src=${a.image} />`}<span>${\n",
1237
+ " a.name\n",
1238
+ " }</span></li>`\n",
1239
+ " )}\n",
1240
+ " </ul>\n",
1241
+ " </div>`;\n",
1242
+ " })`\n",
1243
+ " background-color: #000b2a;\n",
1244
+ " font-family: sans-serif;\n",
1245
+ " font-size: 14px;\n",
1246
+ " width: 100%;\n",
1247
+ "\n",
1248
+ " ul {\n",
1249
+ " align-items: center;\n",
1250
+ " display: flex;\n",
1251
+ " flex-direction: row;\n",
1252
+ " justify-content: center;\n",
1253
+ " }\n",
1254
+ "\n",
1255
+ " li {\n",
1256
+ " align-items: center;\n",
1257
+ " display: inline-flex;\n",
1258
+ " padding: 8px;\n",
1259
+ " transition: color 1s;\n",
1260
+ " }\n",
1261
+ "\n",
1262
+ " span {\n",
1263
+ " max-width: 100px;\n",
1264
+ " overflow: hidden;\n",
1265
+ " text-overflow: ellipsis;\n",
1266
+ " white-space: nowrap;\n",
1267
+ " }\n",
1268
+ "\n",
1269
+ " img {\n",
1270
+ " height: 24px;\n",
1271
+ " margin-right: 4px;\n",
1272
+ " width: 24px;\n",
1273
+ " }\n",
1274
+ " `;\n",
1275
+ "\n",
1276
+ " const StepInput = styled.input.attrs({\n",
1277
+ " type: &quot;range&quot;,\n",
1278
+ " })`\n",
1279
+ " appearance: none;\n",
1280
+ " background: rgba(255, 255, 255, 0.15);\n",
1281
+ " border-radius: 2px;\n",
1282
+ " display: block;\n",
1283
+ " flex: 1;\n",
1284
+ " height: 4px;\n",
1285
+ " opacity: 0.8;\n",
1286
+ " outline: none;\n",
1287
+ " transition: opacity 0.2s;\n",
1288
+ " width: 100%;\n",
1289
+ "\n",
1290
+ " &:hover {\n",
1291
+ " opacity: 1;\n",
1292
+ " }\n",
1293
+ "\n",
1294
+ " &::-webkit-slider-thumb {\n",
1295
+ " appearance: none;\n",
1296
+ " background: #1ebeff;\n",
1297
+ " border-radius: 100%;\n",
1298
+ " cursor: pointer;\n",
1299
+ " height: 12px;\n",
1300
+ " margin: 0;\n",
1301
+ " position: relative;\n",
1302
+ " width: 12px;\n",
1303
+ "\n",
1304
+ " &::after {\n",
1305
+ " content: &quot;&quot;;\n",
1306
+ " position: absolute;\n",
1307
+ " top: 0px;\n",
1308
+ " left: 0px;\n",
1309
+ " width: 200px;\n",
1310
+ " height: 8px;\n",
1311
+ " background: green;\n",
1312
+ " }\n",
1313
+ " }\n",
1314
+ " `;\n",
1315
+ "\n",
1316
+ " const PlayButton = styled.button`\n",
1317
+ " align-items: center;\n",
1318
+ " background: none;\n",
1319
+ " border: none;\n",
1320
+ " color: white;\n",
1321
+ " cursor: pointer;\n",
1322
+ " display: flex;\n",
1323
+ " flex: 0 0 56px;\n",
1324
+ " font-size: 20px;\n",
1325
+ " height: 40px;\n",
1326
+ " justify-content: center;\n",
1327
+ " opacity: 0.8;\n",
1328
+ " outline: none;\n",
1329
+ " transition: opacity 0.2s;\n",
1330
+ "\n",
1331
+ " &:hover {\n",
1332
+ " opacity: 1;\n",
1333
+ " }\n",
1334
+ " `;\n",
1335
+ "\n",
1336
+ " const StepCount = styled.span`\n",
1337
+ " align-items: center;\n",
1338
+ " color: white;\n",
1339
+ " display: flex;\n",
1340
+ " font-size: 14px;\n",
1341
+ " justify-content: center;\n",
1342
+ " opacity: 0.8;\n",
1343
+ " padding: 0 16px;\n",
1344
+ " pointer-events: none;\n",
1345
+ " `;\n",
1346
+ "\n",
1347
+ " const Controls = styled((props) => {\n",
1348
+ " const { environment, pause, play, playing, setStep, step } = useContext(\n",
1349
+ " Context\n",
1350
+ " );\n",
1351
+ " const value = step + 1;\n",
1352
+ " const onClick = () => (playing ? pause() : play());\n",
1353
+ " const onInput = (e) => {\n",
1354
+ " pause();\n",
1355
+ " setStep(parseInt(e.target.value) - 1);\n",
1356
+ " };\n",
1357
+ "\n",
1358
+ " return h`\n",
1359
+ " <div className=${props.className}>\n",
1360
+ " <${PlayButton} onClick=${onClick}><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;24px&quot; height=&quot;24px&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;#FFFFFF&quot;>${\n",
1361
+ " playing\n",
1362
+ " ? h`<path d=&quot;M6 19h4V5H6v14zm8-14v14h4V5h-4z&quot;/><path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;/>`\n",
1363
+ " : h`<path d=&quot;M8 5v14l11-7z&quot;/><path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;/>`\n",
1364
+ " }</svg><//>\n",
1365
+ " <${StepInput} min=&quot;1&quot; max=${\n",
1366
+ " environment.steps.length\n",
1367
+ " } value=&quot;${value}&quot; onInput=${onInput} />\n",
1368
+ " <${StepCount}>${value} / ${environment.steps.length}<//>\n",
1369
+ " </div>\n",
1370
+ " `;\n",
1371
+ " })`\n",
1372
+ " align-items: center;\n",
1373
+ " border-top: 4px solid #212121;\n",
1374
+ " display: flex;\n",
1375
+ " flex: 0 0 44px;\n",
1376
+ " width: 100%;\n",
1377
+ " `;\n",
1378
+ "\n",
1379
+ " const Info = styled((props) => {\n",
1380
+ " const {\n",
1381
+ " environment,\n",
1382
+ " playing,\n",
1383
+ " step,\n",
1384
+ " speed,\n",
1385
+ " animate,\n",
1386
+ " header,\n",
1387
+ " controls,\n",
1388
+ " settings,\n",
1389
+ " } = useContext(Context);\n",
1390
+ "\n",
1391
+ " return h`\n",
1392
+ " <div className=${props.className}>\n",
1393
+ " info:\n",
1394
+ " step(${step}),\n",
1395
+ " playing(${playing ? &quot;T&quot; : &quot;F&quot;}),\n",
1396
+ " speed(${speed}),\n",
1397
+ " animate(${animate ? &quot;T&quot; : &quot;F&quot;})\n",
1398
+ " </div>`;\n",
1399
+ " })`\n",
1400
+ " color: #888;\n",
1401
+ " font-family: monospace;\n",
1402
+ " font-size: 12px;\n",
1403
+ " `;\n",
1404
+ "\n",
1405
+ " const Settings = styled((props) => {\n",
1406
+ " const { environment, pause, play, playing, setStep, step } = useContext(\n",
1407
+ " Context\n",
1408
+ " );\n",
1409
+ "\n",
1410
+ " return h`\n",
1411
+ " <div className=${props.className}>\n",
1412
+ " <${Info} />\n",
1413
+ " </div>\n",
1414
+ " `;\n",
1415
+ " })`\n",
1416
+ " background: #fff;\n",
1417
+ " border-top: 4px solid #212121;\n",
1418
+ " box-sizing: border-box;\n",
1419
+ " padding: 20px;\n",
1420
+ " width: 100%;\n",
1421
+ "\n",
1422
+ " h1 {\n",
1423
+ " font-size: 20px;\n",
1424
+ " }\n",
1425
+ " `;\n",
1426
+ "\n",
1427
+ " const Player = styled((props) => {\n",
1428
+ " const context = useContext(Context);\n",
1429
+ " const { agents, controls, header, legend, loading, settings } = context;\n",
1430
+ " return h`\n",
1431
+ " <div className=${props.className}>\n",
1432
+ " ${loading && h`<${Loading} />`}\n",
1433
+ " ${!loading && header && h`<${Header} />`}\n",
1434
+ " ${!loading && h`<${Viewer} />`}\n",
1435
+ " ${!loading && agents.length > 0 && legend && h`<${Legend} />`}\n",
1436
+ " ${!loading && controls && h`<${Controls} />`}\n",
1437
+ " ${!loading && settings && h`<${Settings} />`}\n",
1438
+ " </div>`;\n",
1439
+ " })`\n",
1440
+ " align-items: center;\n",
1441
+ " background: #212121;\n",
1442
+ " border: 4px solid #212121;\n",
1443
+ " box-sizing: border-box;\n",
1444
+ " display: flex;\n",
1445
+ " flex-direction: column;\n",
1446
+ " height: 100%;\n",
1447
+ " justify-content: center;\n",
1448
+ " position: relative;\n",
1449
+ " width: 100%;\n",
1450
+ " `;\n",
1451
+ "\n",
1452
+ " const App = () => {\n",
1453
+ " const renderCountRef = useRef(0);\n",
1454
+ " const [_, setRenderCount] = useState(0);\n",
1455
+ "\n",
1456
+ " const contextRef = useRef({\n",
1457
+ " animate: false,\n",
1458
+ " agents: [],\n",
1459
+ " autoplay: false,\n",
1460
+ " controls: false,\n",
1461
+ " debug: false,\n",
1462
+ " environment: { steps: [] },\n",
1463
+ " header: window.innerHeight >= 600,\n",
1464
+ " interactive: false,\n",
1465
+ " legend: true,\n",
1466
+ " loading: false,\n",
1467
+ " playing: false,\n",
1468
+ " processing: false,\n",
1469
+ " renderer: () => &quot;DNE&quot;,\n",
1470
+ " settings: false,\n",
1471
+ " speed: 500,\n",
1472
+ " step: 0,\n",
1473
+ " });\n",
1474
+ "\n",
1475
+ " // Context helpers.\n",
1476
+ " const rerender = (contextRef.current.rerender = () =>\n",
1477
+ " setRenderCount((renderCountRef.current += 1)));\n",
1478
+ " const setStep = (contextRef.current.setStep = (newStep) => {\n",
1479
+ " contextRef.current.step = newStep;\n",
1480
+ " rerender();\n",
1481
+ " });\n",
1482
+ " const setPlaying = (contextRef.current.setPlaying = (playing) => {\n",
1483
+ " contextRef.current.playing = playing;\n",
1484
+ " rerender();\n",
1485
+ " });\n",
1486
+ " const pause = (contextRef.current.pause = () => setPlaying(false));\n",
1487
+ "\n",
1488
+ " const playNext = () => {\n",
1489
+ " const context = contextRef.current;\n",
1490
+ "\n",
1491
+ " if (\n",
1492
+ " context.playing &&\n",
1493
+ " context.step < context.environment.steps.length - 1\n",
1494
+ " ) {\n",
1495
+ " setStep(context.step + 1);\n",
1496
+ " play(true);\n",
1497
+ " } else {\n",
1498
+ " pause();\n",
1499
+ " }\n",
1500
+ " };\n",
1501
+ "\n",
1502
+ " const play = (contextRef.current.play = (continuing) => {\n",
1503
+ " const context = contextRef.current;\n",
1504
+ " if (context.playing && !continuing) return;\n",
1505
+ " if (!context.playing) setPlaying(true);\n",
1506
+ " if (\n",
1507
+ " !continuing &&\n",
1508
+ " context.step === context.environment.steps.length - 1\n",
1509
+ " ) {\n",
1510
+ " setStep(0);\n",
1511
+ " }\n",
1512
+ " setTimeout(playNext, context.speed);\n",
1513
+ " });\n",
1514
+ "\n",
1515
+ " const updateContext = (o) => {\n",
1516
+ " const context = contextRef.current;\n",
1517
+ " Object.assign(context, o, {\n",
1518
+ " environment: { ...context.environment, ...(o.environment || {}) },\n",
1519
+ " });\n",
1520
+ " rerender();\n",
1521
+ "\n",
1522
+ " // If autoplay, toggle to playing.\n",
1523
+ " if (context.autoplay) play();\n",
1524
+ " };\n",
1525
+ "\n",
1526
+ " // First time setup.\n",
1527
+ " useEffect(() => {\n",
1528
+ " // Timeout is used to ensure useEffect renders once.\n",
1529
+ " setTimeout(() => {\n",
1530
+ " // Initialize context with window.kaggle.\n",
1531
+ " updateContext(window.kaggle || {});\n",
1532
+ " // Listen for messages received to update the context.\n",
1533
+ " window.addEventListener(\n",
1534
+ " &quot;message&quot;,\n",
1535
+ " (event) => {\n",
1536
+ " // Ensure the environment names match before updating.\n",
1537
+ " try {\n",
1538
+ " if (\n",
1539
+ " event.data.environment.name ==\n",
1540
+ " contextRef.current.environment.name\n",
1541
+ " ) {\n",
1542
+ " updateContext(event.data);\n",
1543
+ " }\n",
1544
+ " } catch {}\n",
1545
+ " },\n",
1546
+ " false\n",
1547
+ " );\n",
1548
+ " // Listen for keyboard commands.\n",
1549
+ " window.addEventListener(\n",
1550
+ " &quot;keydown&quot;,\n",
1551
+ " (event) => {\n",
1552
+ " const {\n",
1553
+ " interactive,\n",
1554
+ " isInteractive,\n",
1555
+ " playing,\n",
1556
+ " step,\n",
1557
+ " environment,\n",
1558
+ " } = contextRef.current;\n",
1559
+ " const key = event.keyCode;\n",
1560
+ " if (\n",
1561
+ " interactive ||\n",
1562
+ " isInteractive() ||\n",
1563
+ " (key !== 32 && key !== 37 && key !== 39)\n",
1564
+ " )\n",
1565
+ " return;\n",
1566
+ "\n",
1567
+ " if (key === 32) {\n",
1568
+ " playing ? pause() : play();\n",
1569
+ " } else if (event.keyCode === 39) {\n",
1570
+ " contextRef.current.playing = false;\n",
1571
+ " if (step < environment.steps.length - 1) setStep(step + 1);\n",
1572
+ " rerender();\n",
1573
+ " } else if (event.keyCode === 37) {\n",
1574
+ " contextRef.current.playing = false;\n",
1575
+ " if (step > 0) setStep(step - 1);\n",
1576
+ " rerender();\n",
1577
+ " }\n",
1578
+ " event.preventDefault();\n",
1579
+ " return false;\n",
1580
+ " },\n",
1581
+ " false\n",
1582
+ " );\n",
1583
+ " }, 1);\n",
1584
+ " }, []);\n",
1585
+ "\n",
1586
+ " if (contextRef.current.debug) {\n",
1587
+ " console.log(&quot;context&quot;, contextRef.current);\n",
1588
+ " }\n",
1589
+ "\n",
1590
+ " // Ability to update context.\n",
1591
+ " contextRef.current.update = updateContext;\n",
1592
+ "\n",
1593
+ " // Ability to communicate with ipython.\n",
1594
+ " const execute = (contextRef.current.execute = (source) =>\n",
1595
+ " new Promise((resolve, reject) => {\n",
1596
+ " try {\n",
1597
+ " window.parent.IPython.notebook.kernel.execute(source, {\n",
1598
+ " iopub: {\n",
1599
+ " output: (resp) => {\n",
1600
+ " const type = resp.msg_type;\n",
1601
+ " if (type === &quot;stream&quot;) return resolve(resp.content.text);\n",
1602
+ " if (type === &quot;error&quot;) return reject(new Error(resp.evalue));\n",
1603
+ " return reject(new Error(&quot;Unknown message type: &quot; + type));\n",
1604
+ " },\n",
1605
+ " },\n",
1606
+ " });\n",
1607
+ " } catch (e) {\n",
1608
+ " reject(new Error(&quot;IPython Unavailable: &quot; + e));\n",
1609
+ " }\n",
1610
+ " }));\n",
1611
+ "\n",
1612
+ " // Ability to return an action from an interactive session.\n",
1613
+ " contextRef.current.act = (action) => {\n",
1614
+ " const id = contextRef.current.environment.id;\n",
1615
+ " updateContext({ processing: true });\n",
1616
+ " execute(`\n",
1617
+ " import json\n",
1618
+ " from kaggle_environments import interactives\n",
1619
+ " if &quot;${id}&quot; in interactives:\n",
1620
+ " action = json.loads('${JSON.stringify(action)}')\n",
1621
+ " env, trainer = interactives[&quot;${id}&quot;]\n",
1622
+ " trainer.step(action)\n",
1623
+ " print(json.dumps(env.steps))`)\n",
1624
+ " .then((resp) => {\n",
1625
+ " try {\n",
1626
+ " updateContext({\n",
1627
+ " processing: false,\n",
1628
+ " environment: { steps: JSON.parse(resp) },\n",
1629
+ " });\n",
1630
+ " play();\n",
1631
+ " } catch (e) {\n",
1632
+ " updateContext({ processing: resp.split(&quot;\\n&quot;)[0] });\n",
1633
+ " console.error(resp, e);\n",
1634
+ " }\n",
1635
+ " })\n",
1636
+ " .catch((e) => console.error(e));\n",
1637
+ " };\n",
1638
+ "\n",
1639
+ " // Check if currently interactive.\n",
1640
+ " contextRef.current.isInteractive = () => {\n",
1641
+ " const context = contextRef.current;\n",
1642
+ " const steps = context.environment.steps;\n",
1643
+ " return (\n",
1644
+ " context.interactive &&\n",
1645
+ " !context.processing &&\n",
1646
+ " context.step === steps.length - 1 &&\n",
1647
+ " steps[context.step].some((s) => s.status === &quot;ACTIVE&quot;)\n",
1648
+ " );\n",
1649
+ " };\n",
1650
+ "\n",
1651
+ " return h`\n",
1652
+ " <${Context.Provider} value=${contextRef.current}>\n",
1653
+ " <${Player} />\n",
1654
+ " <//>`;\n",
1655
+ " };\n",
1656
+ "\n",
1657
+ " preact.render(h`<${App} />`, document.body);\n",
1658
+ " </script>\n",
1659
+ " </body>\n",
1660
+ "</html>\n",
1661
+ "\" width=\"600\" height=\"500\" frameborder=\"0\"></iframe> "
1662
+ ],
1663
+ "text/plain": [
1664
+ "<IPython.core.display.HTML object>"
1665
+ ]
1666
+ },
1667
+ "metadata": {},
1668
+ "output_type": "display_data"
1669
+ }
1670
+ ],
1671
+ "source": [
1672
+ "def agent(observation, configuration):\n",
1673
+ " board = observation.board\n",
1674
+ " columns = configuration.columns\n",
1675
+ " return [c for c in range(columns) if board[c] == 0][0]\n",
1676
+ "\n",
1677
+ "\n",
1678
+ "env = make(\"connectx\", debug=True)\n",
1679
+ "# play agent above vs default random agent.\n",
1680
+ "env.run([agent, \"random\"])\n",
1681
+ "env.render(mode=\"ipython\", width=600, height=500, header=False)"
1682
+ ]
1683
+ },
1684
+ {
1685
+ "cell_type": "markdown",
1686
+ "metadata": {},
1687
+ "source": [
1688
+ "## Specification"
1689
+ ]
1690
+ },
1691
+ {
1692
+ "cell_type": "code",
1693
+ "execution_count": 3,
1694
+ "metadata": {},
1695
+ "outputs": [
1696
+ {
1697
+ "name": "stdout",
1698
+ "output_type": "stream",
1699
+ "text": [
1700
+ "Configuration: {\n",
1701
+ " \"actTimeout\": {\n",
1702
+ " \"default\": 2,\n",
1703
+ " \"description\": \"Maximum runtime (seconds) to obtain an action from an agent.\",\n",
1704
+ " \"minimum\": 1,\n",
1705
+ " \"type\": \"integer\"\n",
1706
+ " },\n",
1707
+ " \"agentExec\": {\n",
1708
+ " \"default\": \"PROCESS\",\n",
1709
+ " \"description\": \"How the agent is executed alongside the running envionment.\",\n",
1710
+ " \"enum\": [\n",
1711
+ " \"LOCAL\",\n",
1712
+ " \"PROCESS\"\n",
1713
+ " ],\n",
1714
+ " \"type\": \"string\"\n",
1715
+ " },\n",
1716
+ " \"agentTimeout\": {\n",
1717
+ " \"default\": 10,\n",
1718
+ " \"description\": \"Maximum runtime (seconds) to initialize an agent.\",\n",
1719
+ " \"minimum\": 1,\n",
1720
+ " \"type\": \"integer\"\n",
1721
+ " },\n",
1722
+ " \"columns\": {\n",
1723
+ " \"default\": 7,\n",
1724
+ " \"description\": \"The number of columns on the board\",\n",
1725
+ " \"minimum\": 1,\n",
1726
+ " \"type\": \"integer\"\n",
1727
+ " },\n",
1728
+ " \"episodeSteps\": {\n",
1729
+ " \"default\": 1000,\n",
1730
+ " \"description\": \"Maximum number of steps in the episode.\",\n",
1731
+ " \"minimum\": 1,\n",
1732
+ " \"type\": \"integer\"\n",
1733
+ " },\n",
1734
+ " \"inarow\": {\n",
1735
+ " \"default\": 4,\n",
1736
+ " \"description\": \"The number of checkers in a row required to win.\",\n",
1737
+ " \"minimum\": 1,\n",
1738
+ " \"type\": \"integer\"\n",
1739
+ " },\n",
1740
+ " \"rows\": {\n",
1741
+ " \"default\": 6,\n",
1742
+ " \"description\": \"The number of rows on the board\",\n",
1743
+ " \"minimum\": 1,\n",
1744
+ " \"type\": \"integer\"\n",
1745
+ " },\n",
1746
+ " \"runTimeout\": {\n",
1747
+ " \"default\": 600,\n",
1748
+ " \"description\": \"Maximum runtime (seconds) of an episode (not necessarily DONE).\",\n",
1749
+ " \"minimum\": 1,\n",
1750
+ " \"type\": \"integer\"\n",
1751
+ " }\n",
1752
+ "}\n",
1753
+ "Observation: {\n",
1754
+ " \"board\": {\n",
1755
+ " \"default\": [],\n",
1756
+ " \"description\": \"Serialized grid (rows x columns). 0 = Empty, 1 = P1, 2 = P2\",\n",
1757
+ " \"shared\": true,\n",
1758
+ " \"type\": \"array\"\n",
1759
+ " },\n",
1760
+ " \"mark\": {\n",
1761
+ " \"defaults\": [\n",
1762
+ " 1,\n",
1763
+ " 2\n",
1764
+ " ],\n",
1765
+ " \"description\": \"Which checkers are the agents.\",\n",
1766
+ " \"enum\": [\n",
1767
+ " 1,\n",
1768
+ " 2\n",
1769
+ " ]\n",
1770
+ " }\n",
1771
+ "}\n",
1772
+ "Action: {\n",
1773
+ " \"default\": 0,\n",
1774
+ " \"description\": \"Column to drop a checker onto the board.\",\n",
1775
+ " \"minimum\": 0,\n",
1776
+ " \"type\": \"integer\"\n",
1777
+ "}\n"
1778
+ ]
1779
+ }
1780
+ ],
1781
+ "source": [
1782
+ "import json\n",
1783
+ "\n",
1784
+ "print(\"Configuration:\", json.dumps(env.specification.configuration, indent=4, sort_keys=True))\n",
1785
+ "print(\"Observation:\", json.dumps(env.specification.observation, indent=4, sort_keys=True))\n",
1786
+ "print(\"Action:\", json.dumps(env.specification.action, indent=4, sort_keys=True))"
1787
+ ]
1788
+ },
1789
+ {
1790
+ "cell_type": "markdown",
1791
+ "metadata": {},
1792
+ "source": [
1793
+ "## Manual Play"
1794
+ ]
1795
+ },
1796
+ {
1797
+ "cell_type": "code",
1798
+ "execution_count": 4,
1799
+ "metadata": {},
1800
+ "outputs": [
1801
+ {
1802
+ "data": {
1803
+ "text/html": [
1804
+ "<iframe srcdoc=\"<!--\n",
1805
+ " Copyright 2020 Kaggle Inc\n",
1806
+ "\n",
1807
+ " Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);\n",
1808
+ " you may not use this file except in compliance with the License.\n",
1809
+ " You may obtain a copy of the License at\n",
1810
+ "\n",
1811
+ " http://www.apache.org/licenses/LICENSE-2.0\n",
1812
+ "\n",
1813
+ " Unless required by applicable law or agreed to in writing, software\n",
1814
+ " distributed under the License is distributed on an &quot;AS IS&quot; BASIS,\n",
1815
+ " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
1816
+ " See the License for the specific language governing permissions and\n",
1817
+ " limitations under the License.\n",
1818
+ "-->\n",
1819
+ "<!DOCTYPE html>\n",
1820
+ "<html lang=&quot;en&quot;>\n",
1821
+ " <head>\n",
1822
+ " <title>Kaggle Simulation Player</title>\n",
1823
+ " <meta name=&quot;viewport&quot; content=&quot;width=device-width,initial-scale=1&quot; />\n",
1824
+ " <link\n",
1825
+ " rel=&quot;stylesheet&quot;\n",
1826
+ " href=&quot;https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.css&quot;\n",
1827
+ " crossorigin=&quot;anonymous&quot;\n",
1828
+ " />\n",
1829
+ " <style type=&quot;text/css&quot;>\n",
1830
+ " html,\n",
1831
+ " body {\n",
1832
+ " height: 100%;\n",
1833
+ " font-family: sans-serif;\n",
1834
+ " }\n",
1835
+ " canvas {\n",
1836
+ " /* image-rendering: -moz-crisp-edges;\n",
1837
+ " image-rendering: -webkit-crisp-edges;\n",
1838
+ " image-rendering: pixelated;\n",
1839
+ " image-rendering: crisp-edges; */\n",
1840
+ " }\n",
1841
+ " </style>\n",
1842
+ " <script src=&quot;https://unpkg.com/preact@10.0.1/dist/preact.umd.js&quot;></script>\n",
1843
+ " <script src=&quot;https://unpkg.com/preact@10.0.1/hooks/dist/hooks.umd.js&quot;></script>\n",
1844
+ " <script src=&quot;https://unpkg.com/htm@2.2.1/dist/htm.umd.js&quot;></script>\n",
1845
+ " <script>\n",
1846
+ " // Polyfill for Styled Components\n",
1847
+ " window.React = {\n",
1848
+ " ...preact,\n",
1849
+ " createElement: preact.h,\n",
1850
+ " PropTypes: { func: {} },\n",
1851
+ " };\n",
1852
+ " </script>\n",
1853
+ " <script src=&quot;https://unpkg.com/styled-components@3.5.0-0/dist/styled-components.min.js&quot;></script>\n",
1854
+ " </head>\n",
1855
+ " <body>\n",
1856
+ " <script>\n",
1857
+ " \n",
1858
+ "window.kaggle = {\n",
1859
+ " &quot;debug&quot;: false,\n",
1860
+ " &quot;autoplay&quot;: false,\n",
1861
+ " &quot;step&quot;: 0,\n",
1862
+ " &quot;controls&quot;: false,\n",
1863
+ " &quot;environment&quot;: {\n",
1864
+ " &quot;id&quot;: &quot;4504cadc-8bfb-11ea-ad45-acde48001122&quot;,\n",
1865
+ " &quot;name&quot;: &quot;connectx&quot;,\n",
1866
+ " &quot;title&quot;: &quot;ConnectX&quot;,\n",
1867
+ " &quot;description&quot;: &quot;Classic Connect in a row but configurable.&quot;,\n",
1868
+ " &quot;version&quot;: &quot;1.0.1&quot;,\n",
1869
+ " &quot;configuration&quot;: {\n",
1870
+ " &quot;episodeSteps&quot;: 1000,\n",
1871
+ " &quot;agentExec&quot;: &quot;PROCESS&quot;,\n",
1872
+ " &quot;agentTimeout&quot;: 10,\n",
1873
+ " &quot;actTimeout&quot;: 2,\n",
1874
+ " &quot;runTimeout&quot;: 600,\n",
1875
+ " &quot;columns&quot;: 7,\n",
1876
+ " &quot;rows&quot;: 6,\n",
1877
+ " &quot;inarow&quot;: 4\n",
1878
+ " },\n",
1879
+ " &quot;specification&quot;: {\n",
1880
+ " &quot;action&quot;: {\n",
1881
+ " &quot;description&quot;: &quot;Column to drop a checker onto the board.&quot;,\n",
1882
+ " &quot;type&quot;: &quot;integer&quot;,\n",
1883
+ " &quot;minimum&quot;: 0,\n",
1884
+ " &quot;default&quot;: 0\n",
1885
+ " },\n",
1886
+ " &quot;agents&quot;: [\n",
1887
+ " 2\n",
1888
+ " ],\n",
1889
+ " &quot;configuration&quot;: {\n",
1890
+ " &quot;episodeSteps&quot;: {\n",
1891
+ " &quot;description&quot;: &quot;Maximum number of steps in the episode.&quot;,\n",
1892
+ " &quot;type&quot;: &quot;integer&quot;,\n",
1893
+ " &quot;minimum&quot;: 1,\n",
1894
+ " &quot;default&quot;: 1000\n",
1895
+ " },\n",
1896
+ " &quot;agentExec&quot;: {\n",
1897
+ " &quot;description&quot;: &quot;How the agent is executed alongside the running envionment.&quot;,\n",
1898
+ " &quot;type&quot;: &quot;string&quot;,\n",
1899
+ " &quot;default&quot;: &quot;PROCESS&quot;,\n",
1900
+ " &quot;enum&quot;: [\n",
1901
+ " &quot;LOCAL&quot;,\n",
1902
+ " &quot;PROCESS&quot;\n",
1903
+ " ]\n",
1904
+ " },\n",
1905
+ " &quot;agentTimeout&quot;: {\n",
1906
+ " &quot;description&quot;: &quot;Maximum runtime (seconds) to initialize an agent.&quot;,\n",
1907
+ " &quot;type&quot;: &quot;integer&quot;,\n",
1908
+ " &quot;minimum&quot;: 1,\n",
1909
+ " &quot;default&quot;: 10\n",
1910
+ " },\n",
1911
+ " &quot;actTimeout&quot;: {\n",
1912
+ " &quot;description&quot;: &quot;Maximum runtime (seconds) to obtain an action from an agent.&quot;,\n",
1913
+ " &quot;type&quot;: &quot;integer&quot;,\n",
1914
+ " &quot;minimum&quot;: 1,\n",
1915
+ " &quot;default&quot;: 2\n",
1916
+ " },\n",
1917
+ " &quot;runTimeout&quot;: {\n",
1918
+ " &quot;description&quot;: &quot;Maximum runtime (seconds) of an episode (not necessarily DONE).&quot;,\n",
1919
+ " &quot;type&quot;: &quot;integer&quot;,\n",
1920
+ " &quot;minimum&quot;: 1,\n",
1921
+ " &quot;default&quot;: 600\n",
1922
+ " },\n",
1923
+ " &quot;columns&quot;: {\n",
1924
+ " &quot;description&quot;: &quot;The number of columns on the board&quot;,\n",
1925
+ " &quot;type&quot;: &quot;integer&quot;,\n",
1926
+ " &quot;default&quot;: 7,\n",
1927
+ " &quot;minimum&quot;: 1\n",
1928
+ " },\n",
1929
+ " &quot;rows&quot;: {\n",
1930
+ " &quot;description&quot;: &quot;The number of rows on the board&quot;,\n",
1931
+ " &quot;type&quot;: &quot;integer&quot;,\n",
1932
+ " &quot;default&quot;: 6,\n",
1933
+ " &quot;minimum&quot;: 1\n",
1934
+ " },\n",
1935
+ " &quot;inarow&quot;: {\n",
1936
+ " &quot;description&quot;: &quot;The number of checkers in a row required to win.&quot;,\n",
1937
+ " &quot;type&quot;: &quot;integer&quot;,\n",
1938
+ " &quot;default&quot;: 4,\n",
1939
+ " &quot;minimum&quot;: 1\n",
1940
+ " }\n",
1941
+ " },\n",
1942
+ " &quot;info&quot;: {},\n",
1943
+ " &quot;observation&quot;: {\n",
1944
+ " &quot;board&quot;: {\n",
1945
+ " &quot;description&quot;: &quot;Serialized grid (rows x columns). 0 = Empty, 1 = P1, 2 = P2&quot;,\n",
1946
+ " &quot;type&quot;: &quot;array&quot;,\n",
1947
+ " &quot;shared&quot;: true,\n",
1948
+ " &quot;default&quot;: []\n",
1949
+ " },\n",
1950
+ " &quot;mark&quot;: {\n",
1951
+ " &quot;defaults&quot;: [\n",
1952
+ " 1,\n",
1953
+ " 2\n",
1954
+ " ],\n",
1955
+ " &quot;description&quot;: &quot;Which checkers are the agents.&quot;,\n",
1956
+ " &quot;enum&quot;: [\n",
1957
+ " 1,\n",
1958
+ " 2\n",
1959
+ " ]\n",
1960
+ " }\n",
1961
+ " },\n",
1962
+ " &quot;reward&quot;: {\n",
1963
+ " &quot;description&quot;: &quot;-1 = Lost, 0 = Draw/Ongoing, 1 = Won&quot;,\n",
1964
+ " &quot;enum&quot;: [\n",
1965
+ " -1,\n",
1966
+ " 0,\n",
1967
+ " 1\n",
1968
+ " ],\n",
1969
+ " &quot;default&quot;: 0,\n",
1970
+ " &quot;type&quot;: [\n",
1971
+ " &quot;number&quot;,\n",
1972
+ " &quot;null&quot;\n",
1973
+ " ]\n",
1974
+ " }\n",
1975
+ " },\n",
1976
+ " &quot;steps&quot;: [\n",
1977
+ " [\n",
1978
+ " {\n",
1979
+ " &quot;action&quot;: 0,\n",
1980
+ " &quot;reward&quot;: 0,\n",
1981
+ " &quot;info&quot;: {},\n",
1982
+ " &quot;observation&quot;: {\n",
1983
+ " &quot;board&quot;: [\n",
1984
+ " 0,\n",
1985
+ " 0,\n",
1986
+ " 0,\n",
1987
+ " 0,\n",
1988
+ " 0,\n",
1989
+ " 0,\n",
1990
+ " 0,\n",
1991
+ " 0,\n",
1992
+ " 0,\n",
1993
+ " 0,\n",
1994
+ " 0,\n",
1995
+ " 0,\n",
1996
+ " 0,\n",
1997
+ " 0,\n",
1998
+ " 0,\n",
1999
+ " 0,\n",
2000
+ " 0,\n",
2001
+ " 0,\n",
2002
+ " 0,\n",
2003
+ " 0,\n",
2004
+ " 0,\n",
2005
+ " 0,\n",
2006
+ " 0,\n",
2007
+ " 0,\n",
2008
+ " 0,\n",
2009
+ " 0,\n",
2010
+ " 0,\n",
2011
+ " 0,\n",
2012
+ " 0,\n",
2013
+ " 0,\n",
2014
+ " 0,\n",
2015
+ " 0,\n",
2016
+ " 0,\n",
2017
+ " 0,\n",
2018
+ " 0,\n",
2019
+ " 0,\n",
2020
+ " 0,\n",
2021
+ " 0,\n",
2022
+ " 0,\n",
2023
+ " 0,\n",
2024
+ " 0,\n",
2025
+ " 0\n",
2026
+ " ],\n",
2027
+ " &quot;mark&quot;: 1\n",
2028
+ " },\n",
2029
+ " &quot;status&quot;: &quot;ACTIVE&quot;\n",
2030
+ " },\n",
2031
+ " {\n",
2032
+ " &quot;action&quot;: 0,\n",
2033
+ " &quot;reward&quot;: 0,\n",
2034
+ " &quot;info&quot;: {},\n",
2035
+ " &quot;observation&quot;: {\n",
2036
+ " &quot;mark&quot;: 2\n",
2037
+ " },\n",
2038
+ " &quot;status&quot;: &quot;INACTIVE&quot;\n",
2039
+ " }\n",
2040
+ " ]\n",
2041
+ " ],\n",
2042
+ " &quot;rewards&quot;: [\n",
2043
+ " 0,\n",
2044
+ " 0\n",
2045
+ " ],\n",
2046
+ " &quot;statuses&quot;: [\n",
2047
+ " &quot;ACTIVE&quot;,\n",
2048
+ " &quot;INACTIVE&quot;\n",
2049
+ " ],\n",
2050
+ " &quot;schema_version&quot;: 1\n",
2051
+ " },\n",
2052
+ " &quot;mode&quot;: &quot;ipython&quot;,\n",
2053
+ " &quot;interactive&quot;: true,\n",
2054
+ " &quot;width&quot;: 800,\n",
2055
+ " &quot;height&quot;: 600\n",
2056
+ "};\n",
2057
+ "\n",
2058
+ "\n",
2059
+ "window.kaggle.renderer = // Copyright 2020 Kaggle Inc\n",
2060
+ "//\n",
2061
+ "// Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);\n",
2062
+ "// you may not use this file except in compliance with the License.\n",
2063
+ "// You may obtain a copy of the License at\n",
2064
+ "//\n",
2065
+ "// http://www.apache.org/licenses/LICENSE-2.0\n",
2066
+ "//\n",
2067
+ "// Unless required by applicable law or agreed to in writing, software\n",
2068
+ "// distributed under the License is distributed on an &quot;AS IS&quot; BASIS,\n",
2069
+ "// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
2070
+ "// See the License for the specific language governing permissions and\n",
2071
+ "// limitations under the License.\n",
2072
+ "\n",
2073
+ "function renderer({\n",
2074
+ " act,\n",
2075
+ " agents,\n",
2076
+ " environment,\n",
2077
+ " frame,\n",
2078
+ " height = 400,\n",
2079
+ " interactive,\n",
2080
+ " isInteractive,\n",
2081
+ " parent,\n",
2082
+ " step,\n",
2083
+ " update,\n",
2084
+ " width = 400,\n",
2085
+ "}) {\n",
2086
+ " // Configuration.\n",
2087
+ " const { rows, columns, inarow } = environment.configuration;\n",
2088
+ "\n",
2089
+ " // Common Dimensions.\n",
2090
+ " const unit = 8;\n",
2091
+ " const minCanvasSize = Math.min(height, width);\n",
2092
+ " const minOffset = minCanvasSize > 400 ? 30 : unit / 2;\n",
2093
+ " const cellSize = Math.min(\n",
2094
+ " (width - minOffset * 2) / columns,\n",
2095
+ " (height - minOffset * 2) / rows\n",
2096
+ " );\n",
2097
+ " const cellInset = 0.8;\n",
2098
+ " const pieceScale = cellSize / 100;\n",
2099
+ " const xOffset = Math.max(0, (width - cellSize * columns) / 2);\n",
2100
+ " const yOffset = Math.max(0, (height - cellSize * rows) / 2);\n",
2101
+ "\n",
2102
+ " // Canvas Setup.\n",
2103
+ " let canvas = parent.querySelector(&quot;canvas&quot;);\n",
2104
+ " if (!canvas) {\n",
2105
+ " canvas = document.createElement(&quot;canvas&quot;);\n",
2106
+ " parent.appendChild(canvas);\n",
2107
+ "\n",
2108
+ " if (interactive) {\n",
2109
+ " canvas.addEventListener(&quot;click&quot;, evt => {\n",
2110
+ " if (!isInteractive()) return;\n",
2111
+ " const rect = evt.target.getBoundingClientRect();\n",
2112
+ " const col = Math.floor((evt.clientX - rect.left - xOffset) / cellSize);\n",
2113
+ " if (col >= 0 && col < columns) act(col);\n",
2114
+ " });\n",
2115
+ " }\n",
2116
+ " }\n",
2117
+ " canvas.style.cursor = isInteractive() ? &quot;pointer&quot; : &quot;default&quot;;\n",
2118
+ "\n",
2119
+ " // Character Paths (based on 100x100 tiles).\n",
2120
+ " const kPath = new Path2D(\n",
2121
+ " `M78.3,96.5c-0.1,0.4-0.5,0.6-1.1,0.6H64.9c-0.7,0-1.4-0.3-1.9-1l-20.3-26L37,75.5v20.1 c0,0.9-0.5,1.4-1.4,1.4H26c-0.9,0-1.4-0.5-1.4-1.4V3.9c0-0.9,0.5-1.4,1.4-1.4h9.5C36.5,2.5,37,3,37,3.9v56.5l24.3-24.7 c0.6-0.6,1.3-1,1.9-1H76c0.6,0,0.9,0.2,1.1,0.7c0.2,0.6,0.1,1-0.1,1.2l-25.7,25L78,95.1C78.4,95.5,78.5,95.9,78.3,96.5z`\n",
2122
+ " );\n",
2123
+ " const goose1Path = new Path2D(\n",
2124
+ " `M8.8,92.7c-4-18.5,4.7-37.2,20.7-46.2c0,0,2.7-1.4,3.4-1.9c2.2-1.6,3-2.1,3-5c0-5-2.1-7.2-2.1-7.2 c-3.9-3.3-6.3-8.2-6.3-13.7c0-10,8.1-18.1,18.1-18.1s18.1,8.1,18.1,18.1c0,6-1.5,32.7-2.3,38.8l-0.1,1`\n",
2125
+ " );\n",
2126
+ " const goose2Path = new Path2D(\n",
2127
+ " `M27.4,19L8.2,27.6c0,0-7.3,2.9,2.6,5c6.1,1.3,24,5.9,24,5.9l1,0.3`\n",
2128
+ " );\n",
2129
+ " const goose3Path = new Path2D(\n",
2130
+ " `M63.7,99.6C52.3,99.6,43,90.3,43,78.9s9.3-20.7,20.7-20.7c10.6,0,34.4,0.1,35.8,9`\n",
2131
+ " );\n",
2132
+ "\n",
2133
+ " // Canvas setup and reset.\n",
2134
+ " let c = canvas.getContext(&quot;2d&quot;);\n",
2135
+ " canvas.width = width;\n",
2136
+ " canvas.height = height;\n",
2137
+ " c.fillStyle = &quot;#000B2A&quot;;\n",
2138
+ " c.fillRect(0, 0, canvas.width, canvas.height);\n",
2139
+ "\n",
2140
+ " const getRowCol = cell => [Math.floor(cell / columns), cell % columns];\n",
2141
+ "\n",
2142
+ " const getColor = (mark, opacity = 1) => {\n",
2143
+ " if (mark === 1) return `rgba(0,255,255,${opacity})`;\n",
2144
+ " if (mark === 2) return `rgba(255,255,255,${opacity})`;\n",
2145
+ " return &quot;#fff&quot;;\n",
2146
+ " };\n",
2147
+ "\n",
2148
+ " const drawCellCircle = (cell, xFrame = 1, yFrame = 1, radiusOffset = 0) => {\n",
2149
+ " const [row, col] = getRowCol(cell);\n",
2150
+ " c.arc(\n",
2151
+ " xOffset + xFrame * (col * cellSize + cellSize / 2),\n",
2152
+ " yOffset + yFrame * (row * cellSize + cellSize / 2),\n",
2153
+ " (cellInset * cellSize) / 2 - radiusOffset,\n",
2154
+ " 2 * Math.PI,\n",
2155
+ " false\n",
2156
+ " );\n",
2157
+ " };\n",
2158
+ "\n",
2159
+ " // Render the pieces.\n",
2160
+ " const board = environment.steps[step][0].observation.board;\n",
2161
+ "\n",
2162
+ " const drawPiece = mark => {\n",
2163
+ " // Base Styles.\n",
2164
+ " const opacity = minCanvasSize < 300 ? 0.6 - minCanvasSize / 1000 : 0.1;\n",
2165
+ " c.fillStyle = getColor(mark, opacity);\n",
2166
+ " c.strokeStyle = getColor(mark);\n",
2167
+ " c.shadowColor = getColor(mark);\n",
2168
+ " c.shadowBlur = 8 / cellInset;\n",
2169
+ " c.lineWidth = 1 / cellInset;\n",
2170
+ "\n",
2171
+ " // Outer circle.\n",
2172
+ " c.save();\n",
2173
+ " c.beginPath();\n",
2174
+ " c.arc(50, 50, 50, 2 * Math.PI, false);\n",
2175
+ " c.closePath();\n",
2176
+ " c.lineWidth *= 4;\n",
2177
+ " c.stroke();\n",
2178
+ " c.fill();\n",
2179
+ " c.restore();\n",
2180
+ "\n",
2181
+ " // Inner circle.\n",
2182
+ " c.beginPath();\n",
2183
+ " c.arc(50, 50, 40, 2 * Math.PI, false);\n",
2184
+ " c.closePath();\n",
2185
+ " c.stroke();\n",
2186
+ "\n",
2187
+ " // Kaggle &quot;K&quot;.\n",
2188
+ " if (mark === 1) {\n",
2189
+ " const scale = 0.54;\n",
2190
+ " c.save();\n",
2191
+ " c.translate(23, 23);\n",
2192
+ " c.scale(scale, scale);\n",
2193
+ " c.lineWidth /= scale;\n",
2194
+ " c.shadowBlur /= scale;\n",
2195
+ " c.stroke(kPath);\n",
2196
+ " c.restore();\n",
2197
+ " }\n",
2198
+ "\n",
2199
+ " // Kaggle &quot;Goose&quot;.\n",
2200
+ " if (mark === 2) {\n",
2201
+ " const scale = 0.6;\n",
2202
+ " c.save();\n",
2203
+ " c.translate(24, 28);\n",
2204
+ " c.scale(scale, scale);\n",
2205
+ " c.lineWidth /= scale;\n",
2206
+ " c.shadowBlur /= scale;\n",
2207
+ " c.stroke(goose1Path);\n",
2208
+ " c.stroke(goose2Path);\n",
2209
+ " c.stroke(goose3Path);\n",
2210
+ " c.beginPath();\n",
2211
+ " c.arc(38.5, 18.6, 2.7, 0, Math.PI * 2, false);\n",
2212
+ " c.closePath();\n",
2213
+ " c.fill();\n",
2214
+ " c.restore();\n",
2215
+ " }\n",
2216
+ " };\n",
2217
+ "\n",
2218
+ " for (let i = 0; i < board.length; i++) {\n",
2219
+ " const [row, col] = getRowCol(i);\n",
2220
+ " if (board[i] === 0) continue;\n",
2221
+ " // Easing In.\n",
2222
+ " let yFrame = Math.min(\n",
2223
+ " (columns * Math.pow(frame, 3)) / Math.floor(i / columns),\n",
2224
+ " 1\n",
2225
+ " );\n",
2226
+ "\n",
2227
+ " if (\n",
2228
+ " step > 1 &&\n",
2229
+ " environment.steps[step - 1][0].observation.board[i] === board[i]\n",
2230
+ " ) {\n",
2231
+ " yFrame = 1;\n",
2232
+ " }\n",
2233
+ "\n",
2234
+ " c.save();\n",
2235
+ " c.translate(\n",
2236
+ " xOffset + cellSize * col + (cellSize - cellSize * cellInset) / 2,\n",
2237
+ " yOffset +\n",
2238
+ " yFrame * (cellSize * row) +\n",
2239
+ " (cellSize - cellSize * cellInset) / 2\n",
2240
+ " );\n",
2241
+ " c.scale(pieceScale * cellInset, pieceScale * cellInset);\n",
2242
+ " drawPiece(board[i]);\n",
2243
+ " c.restore();\n",
2244
+ " }\n",
2245
+ "\n",
2246
+ " // Background Gradient.\n",
2247
+ " const bgRadius = (Math.min(rows, columns) * cellSize) / 2;\n",
2248
+ " const bgStyle = c.createRadialGradient(\n",
2249
+ " xOffset + (cellSize * columns) / 2,\n",
2250
+ " yOffset + (cellSize * rows) / 2,\n",
2251
+ " 0,\n",
2252
+ " xOffset + (cellSize * columns) / 2,\n",
2253
+ " yOffset + (cellSize * rows) / 2,\n",
2254
+ " bgRadius\n",
2255
+ " );\n",
2256
+ " bgStyle.addColorStop(0, &quot;#000B49&quot;);\n",
2257
+ " bgStyle.addColorStop(1, &quot;#000B2A&quot;);\n",
2258
+ "\n",
2259
+ " // Render the board overlay.\n",
2260
+ " c.beginPath();\n",
2261
+ " c.rect(0, 0, canvas.width, canvas.height);\n",
2262
+ " c.closePath();\n",
2263
+ " c.shadowBlur = 0;\n",
2264
+ " for (let i = 0; i < board.length; i++) {\n",
2265
+ " drawCellCircle(i);\n",
2266
+ " c.closePath();\n",
2267
+ " }\n",
2268
+ " c.fillStyle = bgStyle;\n",
2269
+ " c.fill(&quot;evenodd&quot;);\n",
2270
+ "\n",
2271
+ " // Render the board overlay cell outlines.\n",
2272
+ " for (let i = 0; i < board.length; i++) {\n",
2273
+ " c.beginPath();\n",
2274
+ " drawCellCircle(i);\n",
2275
+ " c.strokeStyle = &quot;#0361B2&quot;;\n",
2276
+ " c.lineWidth = 1;\n",
2277
+ " c.stroke();\n",
2278
+ " c.closePath();\n",
2279
+ " }\n",
2280
+ "\n",
2281
+ " const drawLine = (fromCell, toCell) => {\n",
2282
+ " if (frame < 0.5) return;\n",
2283
+ " const lineFrame = (frame - 0.5) / 0.5;\n",
2284
+ " const x1 = xOffset + (fromCell % columns) * cellSize + cellSize / 2;\n",
2285
+ " const x2 =\n",
2286
+ " x1 +\n",
2287
+ " lineFrame *\n",
2288
+ " (xOffset + ((toCell % columns) * cellSize + cellSize / 2) - x1);\n",
2289
+ " const y1 =\n",
2290
+ " yOffset + Math.floor(fromCell / columns) * cellSize + cellSize / 2;\n",
2291
+ " const y2 =\n",
2292
+ " y1 +\n",
2293
+ " lineFrame *\n",
2294
+ " (yOffset + Math.floor(toCell / columns) * cellSize + cellSize / 2 - y1);\n",
2295
+ " c.beginPath();\n",
2296
+ " c.lineCap = &quot;round&quot;;\n",
2297
+ " c.lineWidth = 4;\n",
2298
+ " c.strokeStyle = getColor(board[fromCell]);\n",
2299
+ " c.shadowBlur = 8;\n",
2300
+ " c.shadowColor = getColor(board[fromCell]);\n",
2301
+ " c.moveTo(x1, y1);\n",
2302
+ " c.lineTo(x2, y2);\n",
2303
+ " c.stroke();\n",
2304
+ " };\n",
2305
+ "\n",
2306
+ " // Generate a graph of the board.\n",
2307
+ " const getCell = (cell, rowOffset, columnOffset) => {\n",
2308
+ " const row = Math.floor(cell / columns) + rowOffset;\n",
2309
+ " const col = (cell % columns) + columnOffset;\n",
2310
+ " if (row < 0 || row >= rows || col < 0 || col >= columns) return -1;\n",
2311
+ " return col + row * columns;\n",
2312
+ " };\n",
2313
+ " const makeNode = cell => {\n",
2314
+ " const node = { cell, directions: [], value: board[cell] };\n",
2315
+ " for (let r = -1; r <= 1; r++) {\n",
2316
+ " for (let c = -1; c <= 1; c++) {\n",
2317
+ " if (r === 0 && c === 0) continue;\n",
2318
+ " node.directions.push(getCell(cell, r, c));\n",
2319
+ " }\n",
2320
+ " }\n",
2321
+ " return node;\n",
2322
+ " };\n",
2323
+ " const graph = board.map((_, i) => makeNode(i));\n",
2324
+ "\n",
2325
+ " // Check for any wins!\n",
2326
+ " const getSequence = (node, direction) => {\n",
2327
+ " const sequence = [node.cell];\n",
2328
+ " while (sequence.length < inarow) {\n",
2329
+ " const next = graph[node.directions[direction]];\n",
2330
+ " if (!next || node.value !== next.value || next.value === 0) return;\n",
2331
+ " node = next;\n",
2332
+ " sequence.push(node.cell);\n",
2333
+ " }\n",
2334
+ " return sequence;\n",
2335
+ " };\n",
2336
+ "\n",
2337
+ " // Check all nodes.\n",
2338
+ " for (let i = 0; i < board.length; i++) {\n",
2339
+ " // Check all directions (not the most efficient).\n",
2340
+ " for (let d = 0; d < 8; d++) {\n",
2341
+ " const seq = getSequence(graph[i], d);\n",
2342
+ " if (seq) {\n",
2343
+ " drawLine(seq[0], seq[3]);\n",
2344
+ " i = board.length;\n",
2345
+ " break;\n",
2346
+ " }\n",
2347
+ " }\n",
2348
+ " }\n",
2349
+ "\n",
2350
+ " // Upgrade the legend.\n",
2351
+ " if (agents.length && (!agents[0].color || !agents[0].image)) {\n",
2352
+ " const getPieceImage = mark => {\n",
2353
+ " const pieceCanvas = document.createElement(&quot;canvas&quot;);\n",
2354
+ " parent.appendChild(pieceCanvas);\n",
2355
+ " pieceCanvas.style.marginLeft = &quot;10000px&quot;;\n",
2356
+ " pieceCanvas.width = 100;\n",
2357
+ " pieceCanvas.height = 100;\n",
2358
+ " c = pieceCanvas.getContext(&quot;2d&quot;);\n",
2359
+ " c.translate(10, 10);\n",
2360
+ " c.scale(0.8, 0.8);\n",
2361
+ " drawPiece(mark);\n",
2362
+ " const dataUrl = pieceCanvas.toDataURL();\n",
2363
+ " parent.removeChild(pieceCanvas);\n",
2364
+ " return dataUrl;\n",
2365
+ " };\n",
2366
+ "\n",
2367
+ " agents.forEach(agent => {\n",
2368
+ " agent.color = getColor(agent.index + 1);\n",
2369
+ " agent.image = getPieceImage(agent.index + 1);\n",
2370
+ " });\n",
2371
+ " update({ agents });\n",
2372
+ " }\n",
2373
+ "};\n",
2374
+ "\n",
2375
+ "\n",
2376
+ " \n",
2377
+ " </script>\n",
2378
+ " <script>\n",
2379
+ " const h = htm.bind(preact.h);\n",
2380
+ " const { useContext, useEffect, useRef, useState } = preactHooks;\n",
2381
+ " const styled = window.styled.default;\n",
2382
+ "\n",
2383
+ " const Context = preact.createContext({});\n",
2384
+ "\n",
2385
+ " const Loading = styled.div`\n",
2386
+ " animation: rotate360 1.1s infinite linear;\n",
2387
+ " border: 8px solid rgba(255, 255, 255, 0.2);\n",
2388
+ " border-left-color: #0cb1ed;\n",
2389
+ " border-radius: 50%;\n",
2390
+ " height: 40px;\n",
2391
+ " position: relative;\n",
2392
+ " transform: translateZ(0);\n",
2393
+ " width: 40px;\n",
2394
+ "\n",
2395
+ " @keyframes rotate360 {\n",
2396
+ " 0% {\n",
2397
+ " transform: rotate(0deg);\n",
2398
+ " }\n",
2399
+ " 100% {\n",
2400
+ " transform: rotate(360deg);\n",
2401
+ " }\n",
2402
+ " }\n",
2403
+ " `;\n",
2404
+ "\n",
2405
+ " const Logo = styled(\n",
2406
+ " (props) => h`\n",
2407
+ " <a href=&quot;https://kaggle.com&quot; target=&quot;_blank&quot; className=${props.className}>\n",
2408
+ " <svg width=&quot;62px&quot; height=&quot;20px&quot; viewBox=&quot;0 0 62 24&quot; version=&quot;1.1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;>\n",
2409
+ " <g fill=&quot;#1EBEFF&quot; fill-rule=&quot;nonzero&quot;>\n",
2410
+ " <path d=&quot;M10.2,17.8c0,0.1-0.1,0.1-0.2,0.1H7.7c-0.1,0-0.3-0.1-0.4-0.2l-3.8-4.9l-1.1,1v3.8 c0,0.2-0.1,0.3-0.3,0.3H0.3c-0.2,0-0.3-0.1-0.3-0.3V0.3C0.1,0.1,0.2,0,0.3,0h1.8c0.2,0,0.3,0.1,0.3,0.3V11L7,6.3 c0.1-0.1,0.2-0.2,0.4-0.2h2.4c0.1,0,0.2,0,0.2,0.1c0,0.1,0,0.2,0,0.2l-4.9,4.7l5.1,6.3C10.2,17.6,10.2,17.7,10.2,17.8z&quot;/>\n",
2411
+ " <path d=&quot;M19.6,17.9h-1.8c-0.2,0-0.3-0.1-0.3-0.3v-0.4c-0.8,0.6-1.8,0.9-3,0.9c-1.1,0-2-0.3-2.8-1 c-0.8-0.7-1.2-1.6-1.2-2.7c0-1.7,1.1-2.9,3.2-3.5c0.8-0.2,2.1-0.5,3.8-0.6c0.1-0.6-0.1-1.2-0.5-1.7c-0.4-0.5-1-0.7-1.7-0.7 c-1,0-2,0.4-3,1C12.2,9.1,12.1,9.1,12,9l-0.9-1.3C11,7.5,11,7.4,11.1,7.3c1.3-0.9,2.7-1.4,4.2-1.4c1.1,0,2.1,0.3,2.8,0.8 c1.1,0.8,1.7,2,1.7,3.7v7.3C19.9,17.8,19.8,17.9,19.6,17.9z M17.5,12.4c-1.7,0.2-2.9,0.4-3.5,0.7c-0.9,0.4-1.2,0.9-1.1,1.6 c0.1,0.4,0.2,0.7,0.6,0.9c0.3,0.2,0.7,0.4,1.1,0.4c1.2,0.1,2.2-0.2,2.9-1V12.4z&quot;/>\n",
2412
+ " <path d=&quot;M30.6,22.5c-0.9,1-2.3,1.5-4,1.5c-1,0-2-0.3-2.9-0.8c-0.2-0.1-0.4-0.3-0.7-0.5 c-0.3-0.2-0.6-0.5-0.9-0.7c-0.1-0.1-0.1-0.2,0-0.4l1.2-1.2c0.1-0.1,0.1-0.1,0.2-0.1c0.1,0,0.1,0,0.2,0.1c1,1,1.9,1.5,2.8,1.5 c2.1,0,3.2-1.1,3.2-3.3v-1.4c-0.8,0.7-1.9,1-3.3,1c-1.7,0-3-0.6-4-1.9c-0.8-1.1-1.3-2.5-1.3-4.2c0-1.6,0.4-3,1.2-4.1 c0.9-1.3,2.3-2,4-2c1.3,0,2.4,0.3,3.3,1V6.4c0-0.2,0.1-0.3,0.3-0.3h1.8c0.2,0,0.3,0.1,0.3,0.3v11.7C32,20,31.5,21.5,30.6,22.5z M29.7,9.9c-0.4-1.1-1.4-1.7-3-1.7c-2,0-3.1,1.3-3.1,3.8c0,1.4,0.3,2.4,1,3.1c0.5,0.5,1.2,0.8,2,0.8c1.6,0,2.7-0.6,3.1-1.7V9.9z&quot;/>\n",
2413
+ " <path d=&quot;M42.9,22.5c-0.9,1-2.3,1.5-4,1.5c-1,0-2-0.3-2.9-0.8c-0.2-0.1-0.4-0.3-0.7-0.5 c-0.3-0.2-0.6-0.5-0.9-0.7c-0.1-0.1-0.1-0.2,0-0.4l1.2-1.2c0.1-0.1,0.1-0.1,0.2-0.1c0.1,0,0.1,0,0.2,0.1c1,1,1.9,1.5,2.8,1.5 c2.1,0,3.2-1.1,3.2-3.3v-1.4c-0.8,0.7-1.9,1-3.3,1c-1.7,0-3-0.6-4-1.9c-0.8-1.1-1.3-2.5-1.3-4.2c0-1.6,0.4-3,1.2-4.1 c0.9-1.3,2.3-2,4-2c1.3,0,2.4,0.3,3.3,1V6.4c0-0.2,0.1-0.3,0.3-0.3H44c0.2,0,0.3,0.1,0.3,0.3v11.7C44.3,20,43.8,21.5,42.9,22.5z M42,9.9c-0.4-1.1-1.4-1.7-3-1.7c-2,0-3.1,1.3-3.1,3.8c0,1.4,0.3,2.4,1,3.1c0.5,0.5,1.2,0.8,2,0.8c1.6,0,2.7-0.6,3.1-1.7L42,9.9 L42,9.9z&quot;/>\n",
2414
+ " <path d=&quot;M48.3,17.9h-1.8c-0.2,0-0.3-0.1-0.3-0.3V0.3c0-0.2,0.1-0.3,0.3-0.3h1.8c0.2,0,0.3,0.1,0.3,0.3 v17.3C48.5,17.8,48.5,17.9,48.3,17.9z&quot;/>\n",
2415
+ " <path d=&quot;M61.4,12.6c0,0.2-0.1,0.3-0.3,0.3h-8.5c0.1,0.9,0.5,1.6,1.1,2.2c0.7,0.6,1.6,0.9,2.7,0.9 c1,0,1.8-0.3,2.6-0.8c0.2-0.1,0.3-0.1,0.4,0l1.2,1.3c0.1,0.1,0.1,0.3,0,0.4c-1.3,0.9-2.7,1.4-4.4,1.4c-1.8,0-3.3-0.6-4.4-1.8 c-1.1-1.2-1.7-2.7-1.7-4.5c0-1.7,0.6-3.2,1.7-4.4c1-1.1,2.4-1.6,4.1-1.6c1.6,0,2.9,0.6,4,1.7c1.1,1.2,1.6,2.6,1.5,4.4L61.4,12.6 z M58,8.7c-0.6-0.5-1.3-0.8-2.1-0.8c-0.8,0-1.5,0.3-2.1,0.8c-0.6,0.5-1,1.2-1.1,2H59C59,9.9,58.6,9.3,58,8.7z&quot;/>\n",
2416
+ " </g>\n",
2417
+ " </svg>\n",
2418
+ " </a>\n",
2419
+ " `\n",
2420
+ " )`\n",
2421
+ " display: inline-flex;\n",
2422
+ " `;\n",
2423
+ "\n",
2424
+ " const Header = styled((props) => {\n",
2425
+ " const { environment } = useContext(Context);\n",
2426
+ "\n",
2427
+ " return h`<div className=${props.className} >\n",
2428
+ " <${Logo} />\n",
2429
+ " ${environment.title}\n",
2430
+ " </div>`;\n",
2431
+ " })`\n",
2432
+ " align-items: center;\n",
2433
+ " border-bottom: 4px solid #212121;\n",
2434
+ " box-sizing: border-box;\n",
2435
+ " color: #fff;\n",
2436
+ " display: flex;\n",
2437
+ " flex: 0 0 36px;\n",
2438
+ " font-size: 14px;\n",
2439
+ " justify-content: space-between;\n",
2440
+ " padding: 0 8px;\n",
2441
+ " width: 100%;\n",
2442
+ " `;\n",
2443
+ "\n",
2444
+ " const Renderer = styled((props) => {\n",
2445
+ " const context = useContext(Context);\n",
2446
+ " const { animate, debug, playing, renderer, speed } = context;\n",
2447
+ " const ref = preact.createRef();\n",
2448
+ "\n",
2449
+ " useEffect(async () => {\n",
2450
+ " if (!ref.current) return;\n",
2451
+ "\n",
2452
+ " const renderFrame = async (start, step, lastFrame) => {\n",
2453
+ " if (step !== context.step) return;\n",
2454
+ " if (lastFrame === 1) {\n",
2455
+ " if (!animate) return;\n",
2456
+ " start = Date.now();\n",
2457
+ " }\n",
2458
+ " const frame =\n",
2459
+ " playing || animate\n",
2460
+ " ? Math.min((Date.now() - start) / speed, 1)\n",
2461
+ " : 1;\n",
2462
+ " try {\n",
2463
+ " if (debug) console.time(&quot;render&quot;);\n",
2464
+ " await renderer({\n",
2465
+ " ...context,\n",
2466
+ " frame,\n",
2467
+ " height: ref.current.clientHeight,\n",
2468
+ " hooks: preactHooks,\n",
2469
+ " parent: ref.current,\n",
2470
+ " preact,\n",
2471
+ " styled,\n",
2472
+ " width: ref.current.clientWidth,\n",
2473
+ " });\n",
2474
+ " } catch (error) {\n",
2475
+ " if (debug) console.error(error);\n",
2476
+ " console.log({ ...context, frame, error });\n",
2477
+ " } finally {\n",
2478
+ " if (debug) console.timeEnd(&quot;render&quot;);\n",
2479
+ " }\n",
2480
+ " window.requestAnimationFrame(() => renderFrame(start, step, frame));\n",
2481
+ " };\n",
2482
+ "\n",
2483
+ " await renderFrame(Date.now(), context.step);\n",
2484
+ " }, [ref.current, context.step, context.renderer]);\n",
2485
+ "\n",
2486
+ " return h`<div className=${props.className} ref=${ref} />`;\n",
2487
+ " })`\n",
2488
+ " align-items: center;\n",
2489
+ " box-sizing: border-box;\n",
2490
+ " display: flex;\n",
2491
+ " height: 100%;\n",
2492
+ " left: 0;\n",
2493
+ " justify-content: center;\n",
2494
+ " position: absolute;\n",
2495
+ " top: 0;\n",
2496
+ " width: 100%;\n",
2497
+ " `;\n",
2498
+ "\n",
2499
+ " const Processing = styled((props) => {\n",
2500
+ " const { processing } = useContext(Context);\n",
2501
+ " const text = processing === true ? &quot;Processing...&quot; : processing;\n",
2502
+ " return h`<div className=${props.className}>${text}</div>`;\n",
2503
+ " })`\n",
2504
+ " bottom: 0;\n",
2505
+ " color: #fff;\n",
2506
+ " font-size: 12px;\n",
2507
+ " left: 0;\n",
2508
+ " line-height: 24px;\n",
2509
+ " position: absolute;\n",
2510
+ " text-align: center;\n",
2511
+ " width: 100%;\n",
2512
+ " `;\n",
2513
+ "\n",
2514
+ " const Viewer = styled((props) => {\n",
2515
+ " const { processing } = useContext(Context);\n",
2516
+ " return h`<div className=${props.className}>\n",
2517
+ " <${Renderer} />\n",
2518
+ " ${processing && h`<${Processing} />`}\n",
2519
+ " </div>`;\n",
2520
+ " })`\n",
2521
+ " background-color: #000b2a;\n",
2522
+ " background-image: radial-gradient(\n",
2523
+ " circle closest-side,\n",
2524
+ " #000b49,\n",
2525
+ " #000b2a\n",
2526
+ " );\n",
2527
+ " display: flex;\n",
2528
+ " flex: 1;\n",
2529
+ " overflow: hidden;\n",
2530
+ " position: relative;\n",
2531
+ " width: 100%;\n",
2532
+ " `;\n",
2533
+ "\n",
2534
+ " const Legend = styled((props) => {\n",
2535
+ " const { agents, legend } = useContext(Context);\n",
2536
+ "\n",
2537
+ " return h`<div className=${props.className}>\n",
2538
+ " <ul>\n",
2539
+ " ${agents\n",
2540
+ " .sort((a, b) => a.index - b.index)\n",
2541
+ " .map(\n",
2542
+ " (a) =>\n",
2543
+ " h`<li key=${a.id} title=&quot;id: ${a.id}&quot; style=&quot;color:${\n",
2544
+ " a.color || &quot;#FFF&quot;\n",
2545
+ " }&quot;>${a.image && h`<img src=${a.image} />`}<span>${\n",
2546
+ " a.name\n",
2547
+ " }</span></li>`\n",
2548
+ " )}\n",
2549
+ " </ul>\n",
2550
+ " </div>`;\n",
2551
+ " })`\n",
2552
+ " background-color: #000b2a;\n",
2553
+ " font-family: sans-serif;\n",
2554
+ " font-size: 14px;\n",
2555
+ " width: 100%;\n",
2556
+ "\n",
2557
+ " ul {\n",
2558
+ " align-items: center;\n",
2559
+ " display: flex;\n",
2560
+ " flex-direction: row;\n",
2561
+ " justify-content: center;\n",
2562
+ " }\n",
2563
+ "\n",
2564
+ " li {\n",
2565
+ " align-items: center;\n",
2566
+ " display: inline-flex;\n",
2567
+ " padding: 8px;\n",
2568
+ " transition: color 1s;\n",
2569
+ " }\n",
2570
+ "\n",
2571
+ " span {\n",
2572
+ " max-width: 100px;\n",
2573
+ " overflow: hidden;\n",
2574
+ " text-overflow: ellipsis;\n",
2575
+ " white-space: nowrap;\n",
2576
+ " }\n",
2577
+ "\n",
2578
+ " img {\n",
2579
+ " height: 24px;\n",
2580
+ " margin-right: 4px;\n",
2581
+ " width: 24px;\n",
2582
+ " }\n",
2583
+ " `;\n",
2584
+ "\n",
2585
+ " const StepInput = styled.input.attrs({\n",
2586
+ " type: &quot;range&quot;,\n",
2587
+ " })`\n",
2588
+ " appearance: none;\n",
2589
+ " background: rgba(255, 255, 255, 0.15);\n",
2590
+ " border-radius: 2px;\n",
2591
+ " display: block;\n",
2592
+ " flex: 1;\n",
2593
+ " height: 4px;\n",
2594
+ " opacity: 0.8;\n",
2595
+ " outline: none;\n",
2596
+ " transition: opacity 0.2s;\n",
2597
+ " width: 100%;\n",
2598
+ "\n",
2599
+ " &:hover {\n",
2600
+ " opacity: 1;\n",
2601
+ " }\n",
2602
+ "\n",
2603
+ " &::-webkit-slider-thumb {\n",
2604
+ " appearance: none;\n",
2605
+ " background: #1ebeff;\n",
2606
+ " border-radius: 100%;\n",
2607
+ " cursor: pointer;\n",
2608
+ " height: 12px;\n",
2609
+ " margin: 0;\n",
2610
+ " position: relative;\n",
2611
+ " width: 12px;\n",
2612
+ "\n",
2613
+ " &::after {\n",
2614
+ " content: &quot;&quot;;\n",
2615
+ " position: absolute;\n",
2616
+ " top: 0px;\n",
2617
+ " left: 0px;\n",
2618
+ " width: 200px;\n",
2619
+ " height: 8px;\n",
2620
+ " background: green;\n",
2621
+ " }\n",
2622
+ " }\n",
2623
+ " `;\n",
2624
+ "\n",
2625
+ " const PlayButton = styled.button`\n",
2626
+ " align-items: center;\n",
2627
+ " background: none;\n",
2628
+ " border: none;\n",
2629
+ " color: white;\n",
2630
+ " cursor: pointer;\n",
2631
+ " display: flex;\n",
2632
+ " flex: 0 0 56px;\n",
2633
+ " font-size: 20px;\n",
2634
+ " height: 40px;\n",
2635
+ " justify-content: center;\n",
2636
+ " opacity: 0.8;\n",
2637
+ " outline: none;\n",
2638
+ " transition: opacity 0.2s;\n",
2639
+ "\n",
2640
+ " &:hover {\n",
2641
+ " opacity: 1;\n",
2642
+ " }\n",
2643
+ " `;\n",
2644
+ "\n",
2645
+ " const StepCount = styled.span`\n",
2646
+ " align-items: center;\n",
2647
+ " color: white;\n",
2648
+ " display: flex;\n",
2649
+ " font-size: 14px;\n",
2650
+ " justify-content: center;\n",
2651
+ " opacity: 0.8;\n",
2652
+ " padding: 0 16px;\n",
2653
+ " pointer-events: none;\n",
2654
+ " `;\n",
2655
+ "\n",
2656
+ " const Controls = styled((props) => {\n",
2657
+ " const { environment, pause, play, playing, setStep, step } = useContext(\n",
2658
+ " Context\n",
2659
+ " );\n",
2660
+ " const value = step + 1;\n",
2661
+ " const onClick = () => (playing ? pause() : play());\n",
2662
+ " const onInput = (e) => {\n",
2663
+ " pause();\n",
2664
+ " setStep(parseInt(e.target.value) - 1);\n",
2665
+ " };\n",
2666
+ "\n",
2667
+ " return h`\n",
2668
+ " <div className=${props.className}>\n",
2669
+ " <${PlayButton} onClick=${onClick}><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;24px&quot; height=&quot;24px&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;#FFFFFF&quot;>${\n",
2670
+ " playing\n",
2671
+ " ? h`<path d=&quot;M6 19h4V5H6v14zm8-14v14h4V5h-4z&quot;/><path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;/>`\n",
2672
+ " : h`<path d=&quot;M8 5v14l11-7z&quot;/><path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;/>`\n",
2673
+ " }</svg><//>\n",
2674
+ " <${StepInput} min=&quot;1&quot; max=${\n",
2675
+ " environment.steps.length\n",
2676
+ " } value=&quot;${value}&quot; onInput=${onInput} />\n",
2677
+ " <${StepCount}>${value} / ${environment.steps.length}<//>\n",
2678
+ " </div>\n",
2679
+ " `;\n",
2680
+ " })`\n",
2681
+ " align-items: center;\n",
2682
+ " border-top: 4px solid #212121;\n",
2683
+ " display: flex;\n",
2684
+ " flex: 0 0 44px;\n",
2685
+ " width: 100%;\n",
2686
+ " `;\n",
2687
+ "\n",
2688
+ " const Info = styled((props) => {\n",
2689
+ " const {\n",
2690
+ " environment,\n",
2691
+ " playing,\n",
2692
+ " step,\n",
2693
+ " speed,\n",
2694
+ " animate,\n",
2695
+ " header,\n",
2696
+ " controls,\n",
2697
+ " settings,\n",
2698
+ " } = useContext(Context);\n",
2699
+ "\n",
2700
+ " return h`\n",
2701
+ " <div className=${props.className}>\n",
2702
+ " info:\n",
2703
+ " step(${step}),\n",
2704
+ " playing(${playing ? &quot;T&quot; : &quot;F&quot;}),\n",
2705
+ " speed(${speed}),\n",
2706
+ " animate(${animate ? &quot;T&quot; : &quot;F&quot;})\n",
2707
+ " </div>`;\n",
2708
+ " })`\n",
2709
+ " color: #888;\n",
2710
+ " font-family: monospace;\n",
2711
+ " font-size: 12px;\n",
2712
+ " `;\n",
2713
+ "\n",
2714
+ " const Settings = styled((props) => {\n",
2715
+ " const { environment, pause, play, playing, setStep, step } = useContext(\n",
2716
+ " Context\n",
2717
+ " );\n",
2718
+ "\n",
2719
+ " return h`\n",
2720
+ " <div className=${props.className}>\n",
2721
+ " <${Info} />\n",
2722
+ " </div>\n",
2723
+ " `;\n",
2724
+ " })`\n",
2725
+ " background: #fff;\n",
2726
+ " border-top: 4px solid #212121;\n",
2727
+ " box-sizing: border-box;\n",
2728
+ " padding: 20px;\n",
2729
+ " width: 100%;\n",
2730
+ "\n",
2731
+ " h1 {\n",
2732
+ " font-size: 20px;\n",
2733
+ " }\n",
2734
+ " `;\n",
2735
+ "\n",
2736
+ " const Player = styled((props) => {\n",
2737
+ " const context = useContext(Context);\n",
2738
+ " const { agents, controls, header, legend, loading, settings } = context;\n",
2739
+ " return h`\n",
2740
+ " <div className=${props.className}>\n",
2741
+ " ${loading && h`<${Loading} />`}\n",
2742
+ " ${!loading && header && h`<${Header} />`}\n",
2743
+ " ${!loading && h`<${Viewer} />`}\n",
2744
+ " ${!loading && agents.length > 0 && legend && h`<${Legend} />`}\n",
2745
+ " ${!loading && controls && h`<${Controls} />`}\n",
2746
+ " ${!loading && settings && h`<${Settings} />`}\n",
2747
+ " </div>`;\n",
2748
+ " })`\n",
2749
+ " align-items: center;\n",
2750
+ " background: #212121;\n",
2751
+ " border: 4px solid #212121;\n",
2752
+ " box-sizing: border-box;\n",
2753
+ " display: flex;\n",
2754
+ " flex-direction: column;\n",
2755
+ " height: 100%;\n",
2756
+ " justify-content: center;\n",
2757
+ " position: relative;\n",
2758
+ " width: 100%;\n",
2759
+ " `;\n",
2760
+ "\n",
2761
+ " const App = () => {\n",
2762
+ " const renderCountRef = useRef(0);\n",
2763
+ " const [_, setRenderCount] = useState(0);\n",
2764
+ "\n",
2765
+ " const contextRef = useRef({\n",
2766
+ " animate: false,\n",
2767
+ " agents: [],\n",
2768
+ " autoplay: false,\n",
2769
+ " controls: false,\n",
2770
+ " debug: false,\n",
2771
+ " environment: { steps: [] },\n",
2772
+ " header: window.innerHeight >= 600,\n",
2773
+ " interactive: false,\n",
2774
+ " legend: true,\n",
2775
+ " loading: false,\n",
2776
+ " playing: false,\n",
2777
+ " processing: false,\n",
2778
+ " renderer: () => &quot;DNE&quot;,\n",
2779
+ " settings: false,\n",
2780
+ " speed: 500,\n",
2781
+ " step: 0,\n",
2782
+ " });\n",
2783
+ "\n",
2784
+ " // Context helpers.\n",
2785
+ " const rerender = (contextRef.current.rerender = () =>\n",
2786
+ " setRenderCount((renderCountRef.current += 1)));\n",
2787
+ " const setStep = (contextRef.current.setStep = (newStep) => {\n",
2788
+ " contextRef.current.step = newStep;\n",
2789
+ " rerender();\n",
2790
+ " });\n",
2791
+ " const setPlaying = (contextRef.current.setPlaying = (playing) => {\n",
2792
+ " contextRef.current.playing = playing;\n",
2793
+ " rerender();\n",
2794
+ " });\n",
2795
+ " const pause = (contextRef.current.pause = () => setPlaying(false));\n",
2796
+ "\n",
2797
+ " const playNext = () => {\n",
2798
+ " const context = contextRef.current;\n",
2799
+ "\n",
2800
+ " if (\n",
2801
+ " context.playing &&\n",
2802
+ " context.step < context.environment.steps.length - 1\n",
2803
+ " ) {\n",
2804
+ " setStep(context.step + 1);\n",
2805
+ " play(true);\n",
2806
+ " } else {\n",
2807
+ " pause();\n",
2808
+ " }\n",
2809
+ " };\n",
2810
+ "\n",
2811
+ " const play = (contextRef.current.play = (continuing) => {\n",
2812
+ " const context = contextRef.current;\n",
2813
+ " if (context.playing && !continuing) return;\n",
2814
+ " if (!context.playing) setPlaying(true);\n",
2815
+ " if (\n",
2816
+ " !continuing &&\n",
2817
+ " context.step === context.environment.steps.length - 1\n",
2818
+ " ) {\n",
2819
+ " setStep(0);\n",
2820
+ " }\n",
2821
+ " setTimeout(playNext, context.speed);\n",
2822
+ " });\n",
2823
+ "\n",
2824
+ " const updateContext = (o) => {\n",
2825
+ " const context = contextRef.current;\n",
2826
+ " Object.assign(context, o, {\n",
2827
+ " environment: { ...context.environment, ...(o.environment || {}) },\n",
2828
+ " });\n",
2829
+ " rerender();\n",
2830
+ "\n",
2831
+ " // If autoplay, toggle to playing.\n",
2832
+ " if (context.autoplay) play();\n",
2833
+ " };\n",
2834
+ "\n",
2835
+ " // First time setup.\n",
2836
+ " useEffect(() => {\n",
2837
+ " // Timeout is used to ensure useEffect renders once.\n",
2838
+ " setTimeout(() => {\n",
2839
+ " // Initialize context with window.kaggle.\n",
2840
+ " updateContext(window.kaggle || {});\n",
2841
+ " // Listen for messages received to update the context.\n",
2842
+ " window.addEventListener(\n",
2843
+ " &quot;message&quot;,\n",
2844
+ " (event) => {\n",
2845
+ " // Ensure the environment names match before updating.\n",
2846
+ " try {\n",
2847
+ " if (\n",
2848
+ " event.data.environment.name ==\n",
2849
+ " contextRef.current.environment.name\n",
2850
+ " ) {\n",
2851
+ " updateContext(event.data);\n",
2852
+ " }\n",
2853
+ " } catch {}\n",
2854
+ " },\n",
2855
+ " false\n",
2856
+ " );\n",
2857
+ " // Listen for keyboard commands.\n",
2858
+ " window.addEventListener(\n",
2859
+ " &quot;keydown&quot;,\n",
2860
+ " (event) => {\n",
2861
+ " const {\n",
2862
+ " interactive,\n",
2863
+ " isInteractive,\n",
2864
+ " playing,\n",
2865
+ " step,\n",
2866
+ " environment,\n",
2867
+ " } = contextRef.current;\n",
2868
+ " const key = event.keyCode;\n",
2869
+ " if (\n",
2870
+ " interactive ||\n",
2871
+ " isInteractive() ||\n",
2872
+ " (key !== 32 && key !== 37 && key !== 39)\n",
2873
+ " )\n",
2874
+ " return;\n",
2875
+ "\n",
2876
+ " if (key === 32) {\n",
2877
+ " playing ? pause() : play();\n",
2878
+ " } else if (event.keyCode === 39) {\n",
2879
+ " contextRef.current.playing = false;\n",
2880
+ " if (step < environment.steps.length - 1) setStep(step + 1);\n",
2881
+ " rerender();\n",
2882
+ " } else if (event.keyCode === 37) {\n",
2883
+ " contextRef.current.playing = false;\n",
2884
+ " if (step > 0) setStep(step - 1);\n",
2885
+ " rerender();\n",
2886
+ " }\n",
2887
+ " event.preventDefault();\n",
2888
+ " return false;\n",
2889
+ " },\n",
2890
+ " false\n",
2891
+ " );\n",
2892
+ " }, 1);\n",
2893
+ " }, []);\n",
2894
+ "\n",
2895
+ " if (contextRef.current.debug) {\n",
2896
+ " console.log(&quot;context&quot;, contextRef.current);\n",
2897
+ " }\n",
2898
+ "\n",
2899
+ " // Ability to update context.\n",
2900
+ " contextRef.current.update = updateContext;\n",
2901
+ "\n",
2902
+ " // Ability to communicate with ipython.\n",
2903
+ " const execute = (contextRef.current.execute = (source) =>\n",
2904
+ " new Promise((resolve, reject) => {\n",
2905
+ " try {\n",
2906
+ " window.parent.IPython.notebook.kernel.execute(source, {\n",
2907
+ " iopub: {\n",
2908
+ " output: (resp) => {\n",
2909
+ " const type = resp.msg_type;\n",
2910
+ " if (type === &quot;stream&quot;) return resolve(resp.content.text);\n",
2911
+ " if (type === &quot;error&quot;) return reject(new Error(resp.evalue));\n",
2912
+ " return reject(new Error(&quot;Unknown message type: &quot; + type));\n",
2913
+ " },\n",
2914
+ " },\n",
2915
+ " });\n",
2916
+ " } catch (e) {\n",
2917
+ " reject(new Error(&quot;IPython Unavailable: &quot; + e));\n",
2918
+ " }\n",
2919
+ " }));\n",
2920
+ "\n",
2921
+ " // Ability to return an action from an interactive session.\n",
2922
+ " contextRef.current.act = (action) => {\n",
2923
+ " const id = contextRef.current.environment.id;\n",
2924
+ " updateContext({ processing: true });\n",
2925
+ " execute(`\n",
2926
+ " import json\n",
2927
+ " from kaggle_environments import interactives\n",
2928
+ " if &quot;${id}&quot; in interactives:\n",
2929
+ " action = json.loads('${JSON.stringify(action)}')\n",
2930
+ " env, trainer = interactives[&quot;${id}&quot;]\n",
2931
+ " trainer.step(action)\n",
2932
+ " print(json.dumps(env.steps))`)\n",
2933
+ " .then((resp) => {\n",
2934
+ " try {\n",
2935
+ " updateContext({\n",
2936
+ " processing: false,\n",
2937
+ " environment: { steps: JSON.parse(resp) },\n",
2938
+ " });\n",
2939
+ " play();\n",
2940
+ " } catch (e) {\n",
2941
+ " updateContext({ processing: resp.split(&quot;\\n&quot;)[0] });\n",
2942
+ " console.error(resp, e);\n",
2943
+ " }\n",
2944
+ " })\n",
2945
+ " .catch((e) => console.error(e));\n",
2946
+ " };\n",
2947
+ "\n",
2948
+ " // Check if currently interactive.\n",
2949
+ " contextRef.current.isInteractive = () => {\n",
2950
+ " const context = contextRef.current;\n",
2951
+ " const steps = context.environment.steps;\n",
2952
+ " return (\n",
2953
+ " context.interactive &&\n",
2954
+ " !context.processing &&\n",
2955
+ " context.step === steps.length - 1 &&\n",
2956
+ " steps[context.step].some((s) => s.status === &quot;ACTIVE&quot;)\n",
2957
+ " );\n",
2958
+ " };\n",
2959
+ "\n",
2960
+ " return h`\n",
2961
+ " <${Context.Provider} value=${contextRef.current}>\n",
2962
+ " <${Player} />\n",
2963
+ " <//>`;\n",
2964
+ " };\n",
2965
+ "\n",
2966
+ " preact.render(h`<${App} />`, document.body);\n",
2967
+ " </script>\n",
2968
+ " </body>\n",
2969
+ "</html>\n",
2970
+ "\" width=\"800\" height=\"600\" frameborder=\"0\"></iframe> "
2971
+ ],
2972
+ "text/plain": [
2973
+ "<IPython.core.display.HTML object>"
2974
+ ]
2975
+ },
2976
+ "metadata": {},
2977
+ "output_type": "display_data"
2978
+ }
2979
+ ],
2980
+ "source": [
2981
+ "env = make(\"connectx\")\n",
2982
+ "# Play against 3 default shortest agents.\n",
2983
+ "env.play([None, \"negamax\"], width=800, height=600)"
2984
+ ]
2985
+ },
2986
+ {
2987
+ "cell_type": "markdown",
2988
+ "metadata": {},
2989
+ "source": [
2990
+ "## Training using Gym"
2991
+ ]
2992
+ },
2993
+ {
2994
+ "cell_type": "code",
2995
+ "execution_count": 5,
2996
+ "metadata": {
2997
+ "scrolled": false
2998
+ },
2999
+ "outputs": [
3000
+ {
3001
+ "name": "stdout",
3002
+ "output_type": "stream",
3003
+ "text": [
3004
+ "+---+---+---+---+---+---+---+\n",
3005
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3006
+ "+---+---+---+---+---+---+---+\n",
3007
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3008
+ "+---+---+---+---+---+---+---+\n",
3009
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3010
+ "+---+---+---+---+---+---+---+\n",
3011
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3012
+ "+---+---+---+---+---+---+---+\n",
3013
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3014
+ "+---+---+---+---+---+---+---+\n",
3015
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3016
+ "+---+---+---+---+---+---+---+\n",
3017
+ "\n",
3018
+ "+---+---+---+---+---+---+---+\n",
3019
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3020
+ "+---+---+---+---+---+---+---+\n",
3021
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3022
+ "+---+---+---+---+---+---+---+\n",
3023
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3024
+ "+---+---+---+---+---+---+---+\n",
3025
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3026
+ "+---+---+---+---+---+---+---+\n",
3027
+ "| 2 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3028
+ "+---+---+---+---+---+---+---+\n",
3029
+ "| 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3030
+ "+---+---+---+---+---+---+---+\n",
3031
+ "\n",
3032
+ "+---+---+---+---+---+---+---+\n",
3033
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3034
+ "+---+---+---+---+---+---+---+\n",
3035
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3036
+ "+---+---+---+---+---+---+---+\n",
3037
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3038
+ "+---+---+---+---+---+---+---+\n",
3039
+ "| 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3040
+ "+---+---+---+---+---+---+---+\n",
3041
+ "| 2 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3042
+ "+---+---+---+---+---+---+---+\n",
3043
+ "| 1 | 0 | 0 | 0 | 2 | 0 | 0 |\n",
3044
+ "+---+---+---+---+---+---+---+\n",
3045
+ "\n",
3046
+ "+---+---+---+---+---+---+---+\n",
3047
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3048
+ "+---+---+---+---+---+---+---+\n",
3049
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3050
+ "+---+---+---+---+---+---+---+\n",
3051
+ "| 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3052
+ "+---+---+---+---+---+---+---+\n",
3053
+ "| 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3054
+ "+---+---+---+---+---+---+---+\n",
3055
+ "| 2 | 0 | 0 | 0 | 2 | 0 | 0 |\n",
3056
+ "+---+---+---+---+---+---+---+\n",
3057
+ "| 1 | 0 | 0 | 0 | 2 | 0 | 0 |\n",
3058
+ "+---+---+---+---+---+---+---+\n",
3059
+ "\n",
3060
+ "+---+---+---+---+---+---+---+\n",
3061
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3062
+ "+---+---+---+---+---+---+---+\n",
3063
+ "| 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3064
+ "+---+---+---+---+---+---+---+\n",
3065
+ "| 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3066
+ "+---+---+---+---+---+---+---+\n",
3067
+ "| 1 | 0 | 0 | 0 | 2 | 0 | 0 |\n",
3068
+ "+---+---+---+---+---+---+---+\n",
3069
+ "| 2 | 0 | 0 | 0 | 2 | 0 | 0 |\n",
3070
+ "+---+---+---+---+---+---+---+\n",
3071
+ "| 1 | 0 | 0 | 0 | 2 | 0 | 0 |\n",
3072
+ "+---+---+---+---+---+---+---+\n",
3073
+ "\n",
3074
+ "+---+---+---+---+---+---+---+\n",
3075
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3076
+ "+---+---+---+---+---+---+---+\n",
3077
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3078
+ "+---+---+---+---+---+---+---+\n",
3079
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3080
+ "+---+---+---+---+---+---+---+\n",
3081
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3082
+ "+---+---+---+---+---+---+---+\n",
3083
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3084
+ "+---+---+---+---+---+---+---+\n",
3085
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3086
+ "+---+---+---+---+---+---+---+\n",
3087
+ "\n",
3088
+ "+---+---+---+---+---+---+---+\n",
3089
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3090
+ "+---+---+---+---+---+---+---+\n",
3091
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3092
+ "+---+---+---+---+---+---+---+\n",
3093
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3094
+ "+---+---+---+---+---+---+---+\n",
3095
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3096
+ "+---+---+---+---+---+---+---+\n",
3097
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3098
+ "+---+---+---+---+---+---+---+\n",
3099
+ "| 1 | 0 | 0 | 0 | 0 | 0 | 2 |\n",
3100
+ "+---+---+---+---+---+---+---+\n",
3101
+ "\n",
3102
+ "+---+---+---+---+---+---+---+\n",
3103
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3104
+ "+---+---+---+---+---+---+---+\n",
3105
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3106
+ "+---+---+---+---+---+---+---+\n",
3107
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3108
+ "+---+---+---+---+---+---+---+\n",
3109
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3110
+ "+---+---+---+---+---+---+---+\n",
3111
+ "| 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3112
+ "+---+---+---+---+---+---+---+\n",
3113
+ "| 1 | 0 | 0 | 0 | 2 | 0 | 2 |\n",
3114
+ "+---+---+---+---+---+---+---+\n",
3115
+ "\n",
3116
+ "+---+---+---+---+---+---+---+\n",
3117
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3118
+ "+---+---+---+---+---+---+---+\n",
3119
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3120
+ "+---+---+---+---+---+---+---+\n",
3121
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3122
+ "+---+---+---+---+---+---+---+\n",
3123
+ "| 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3124
+ "+---+---+---+---+---+---+---+\n",
3125
+ "| 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3126
+ "+---+---+---+---+---+---+---+\n",
3127
+ "| 1 | 0 | 2 | 0 | 2 | 0 | 2 |\n",
3128
+ "+---+---+---+---+---+---+---+\n",
3129
+ "\n",
3130
+ "+---+---+---+---+---+---+---+\n",
3131
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3132
+ "+---+---+---+---+---+---+---+\n",
3133
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3134
+ "+---+---+---+---+---+---+---+\n",
3135
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3136
+ "+---+---+---+---+---+---+---+\n",
3137
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3138
+ "+---+---+---+---+---+---+---+\n",
3139
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3140
+ "+---+---+---+---+---+---+---+\n",
3141
+ "| 0 | 0 | 0 | 0 | 0 | 0 | 0 |\n",
3142
+ "+---+---+---+---+---+---+---+\n",
3143
+ "\n"
3144
+ ]
3145
+ }
3146
+ ],
3147
+ "source": [
3148
+ "from kaggle_environments import make\n",
3149
+ "\n",
3150
+ "env = make(\"connectx\", debug=True)\n",
3151
+ "\n",
3152
+ "# Training agent in first position (player 1) against the default random agent.\n",
3153
+ "trainer = env.train([None, \"random\"])\n",
3154
+ "\n",
3155
+ "obs = trainer.reset()\n",
3156
+ "for _ in range(10):\n",
3157
+ " env.render()\n",
3158
+ " action = 0 # Action for the agent being trained.\n",
3159
+ " obs, reward, done, info = trainer.step(action)\n",
3160
+ " if done:\n",
3161
+ " obs = trainer.reset()"
3162
+ ]
3163
+ }
3164
+ ],
3165
+ "metadata": {
3166
+ "kernelspec": {
3167
+ "display_name": "Python 3",
3168
+ "language": "python",
3169
+ "name": "python3"
3170
+ },
3171
+ "language_info": {
3172
+ "codemirror_mode": {
3173
+ "name": "ipython",
3174
+ "version": 3
3175
+ },
3176
+ "file_extension": ".py",
3177
+ "mimetype": "text/x-python",
3178
+ "name": "python",
3179
+ "nbconvert_exporter": "python",
3180
+ "pygments_lexer": "ipython3",
3181
+ "version": "3.6.6"
3182
+ }
3183
+ },
3184
+ "nbformat": 4,
3185
+ "nbformat_minor": 2
3186
+ }