kaggle-environments 0.2.0__py3-none-any.whl → 1.20.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of kaggle-environments might be problematic. Click here for more details.

Files changed (215) hide show
  1. kaggle_environments/__init__.py +49 -13
  2. kaggle_environments/agent.py +177 -124
  3. kaggle_environments/api.py +31 -0
  4. kaggle_environments/core.py +298 -173
  5. kaggle_environments/envs/cabt/cabt.js +164 -0
  6. kaggle_environments/envs/cabt/cabt.json +28 -0
  7. kaggle_environments/envs/cabt/cabt.py +186 -0
  8. kaggle_environments/envs/cabt/cg/__init__.py +0 -0
  9. kaggle_environments/envs/cabt/cg/cg.dll +0 -0
  10. kaggle_environments/envs/cabt/cg/game.py +75 -0
  11. kaggle_environments/envs/cabt/cg/libcg.so +0 -0
  12. kaggle_environments/envs/cabt/cg/sim.py +48 -0
  13. kaggle_environments/envs/cabt/test_cabt.py +120 -0
  14. kaggle_environments/envs/chess/chess.js +4289 -0
  15. kaggle_environments/envs/chess/chess.json +60 -0
  16. kaggle_environments/envs/chess/chess.py +4241 -0
  17. kaggle_environments/envs/chess/test_chess.py +60 -0
  18. kaggle_environments/envs/connectx/connectx.ipynb +3186 -0
  19. kaggle_environments/envs/connectx/connectx.js +1 -1
  20. kaggle_environments/envs/connectx/connectx.json +15 -1
  21. kaggle_environments/envs/connectx/connectx.py +6 -23
  22. kaggle_environments/envs/connectx/test_connectx.py +70 -24
  23. kaggle_environments/envs/football/football.ipynb +75 -0
  24. kaggle_environments/envs/football/football.json +91 -0
  25. kaggle_environments/envs/football/football.py +277 -0
  26. kaggle_environments/envs/football/helpers.py +95 -0
  27. kaggle_environments/envs/football/test_football.py +360 -0
  28. kaggle_environments/envs/halite/__init__.py +0 -0
  29. kaggle_environments/envs/halite/halite.ipynb +44741 -0
  30. kaggle_environments/envs/halite/halite.js +199 -83
  31. kaggle_environments/envs/halite/halite.json +31 -18
  32. kaggle_environments/envs/halite/halite.py +164 -303
  33. kaggle_environments/envs/halite/helpers.py +720 -0
  34. kaggle_environments/envs/halite/test_halite.py +190 -0
  35. kaggle_environments/envs/hungry_geese/__init__.py +0 -0
  36. kaggle_environments/envs/{battlegeese/battlegeese.js → hungry_geese/hungry_geese.js} +38 -22
  37. kaggle_environments/envs/{battlegeese/battlegeese.json → hungry_geese/hungry_geese.json} +22 -15
  38. kaggle_environments/envs/hungry_geese/hungry_geese.py +316 -0
  39. kaggle_environments/envs/hungry_geese/test_hungry_geese.py +0 -0
  40. kaggle_environments/envs/identity/identity.json +6 -5
  41. kaggle_environments/envs/identity/identity.py +15 -2
  42. kaggle_environments/envs/kore_fleets/__init__.py +0 -0
  43. kaggle_environments/envs/kore_fleets/helpers.py +1005 -0
  44. kaggle_environments/envs/kore_fleets/kore_fleets.ipynb +114 -0
  45. kaggle_environments/envs/kore_fleets/kore_fleets.js +658 -0
  46. kaggle_environments/envs/kore_fleets/kore_fleets.json +164 -0
  47. kaggle_environments/envs/kore_fleets/kore_fleets.py +555 -0
  48. kaggle_environments/envs/kore_fleets/starter_bots/java/Bot.java +54 -0
  49. kaggle_environments/envs/kore_fleets/starter_bots/java/README.md +26 -0
  50. kaggle_environments/envs/kore_fleets/starter_bots/java/jars/hamcrest-core-1.3.jar +0 -0
  51. kaggle_environments/envs/kore_fleets/starter_bots/java/jars/junit-4.13.2.jar +0 -0
  52. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Board.java +518 -0
  53. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Cell.java +61 -0
  54. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Configuration.java +24 -0
  55. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Direction.java +166 -0
  56. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Fleet.java +72 -0
  57. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/KoreJson.java +97 -0
  58. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Observation.java +72 -0
  59. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Pair.java +13 -0
  60. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Player.java +68 -0
  61. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Point.java +65 -0
  62. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Shipyard.java +70 -0
  63. kaggle_environments/envs/kore_fleets/starter_bots/java/kore/ShipyardAction.java +59 -0
  64. kaggle_environments/envs/kore_fleets/starter_bots/java/main.py +73 -0
  65. kaggle_environments/envs/kore_fleets/starter_bots/java/test/BoardTest.java +567 -0
  66. kaggle_environments/envs/kore_fleets/starter_bots/java/test/ConfigurationTest.java +25 -0
  67. kaggle_environments/envs/kore_fleets/starter_bots/java/test/KoreJsonTest.java +62 -0
  68. kaggle_environments/envs/kore_fleets/starter_bots/java/test/ObservationTest.java +46 -0
  69. kaggle_environments/envs/kore_fleets/starter_bots/java/test/PointTest.java +21 -0
  70. kaggle_environments/envs/kore_fleets/starter_bots/java/test/ShipyardTest.java +22 -0
  71. kaggle_environments/envs/kore_fleets/starter_bots/java/test/configuration.json +1 -0
  72. kaggle_environments/envs/kore_fleets/starter_bots/java/test/fullob.json +1 -0
  73. kaggle_environments/envs/kore_fleets/starter_bots/java/test/observation.json +1 -0
  74. kaggle_environments/envs/kore_fleets/starter_bots/python/__init__.py +0 -0
  75. kaggle_environments/envs/kore_fleets/starter_bots/python/main.py +27 -0
  76. kaggle_environments/envs/kore_fleets/starter_bots/ts/Bot.ts +34 -0
  77. kaggle_environments/envs/kore_fleets/starter_bots/ts/DoNothingBot.ts +12 -0
  78. kaggle_environments/envs/kore_fleets/starter_bots/ts/MinerBot.ts +62 -0
  79. kaggle_environments/envs/kore_fleets/starter_bots/ts/README.md +55 -0
  80. kaggle_environments/envs/kore_fleets/starter_bots/ts/interpreter.ts +402 -0
  81. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Board.ts +514 -0
  82. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Cell.ts +63 -0
  83. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Configuration.ts +25 -0
  84. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Direction.ts +169 -0
  85. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Fleet.ts +76 -0
  86. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/KoreIO.ts +70 -0
  87. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Observation.ts +45 -0
  88. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Pair.ts +11 -0
  89. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Player.ts +68 -0
  90. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Point.ts +65 -0
  91. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Shipyard.ts +72 -0
  92. kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/ShipyardAction.ts +58 -0
  93. kaggle_environments/envs/kore_fleets/starter_bots/ts/main.py +73 -0
  94. kaggle_environments/envs/kore_fleets/starter_bots/ts/miner.py +73 -0
  95. kaggle_environments/envs/kore_fleets/starter_bots/ts/package.json +23 -0
  96. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/BoardTest.ts +551 -0
  97. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/ConfigurationTest.ts +16 -0
  98. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/ObservationTest.ts +33 -0
  99. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/PointTest.ts +17 -0
  100. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/ShipyardTest.ts +18 -0
  101. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/configuration.json +1 -0
  102. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/fullob.json +1 -0
  103. kaggle_environments/envs/kore_fleets/starter_bots/ts/test/observation.json +1 -0
  104. kaggle_environments/envs/kore_fleets/starter_bots/ts/tsconfig.json +22 -0
  105. kaggle_environments/envs/kore_fleets/test_kore_fleets.py +331 -0
  106. kaggle_environments/envs/lux_ai_2021/README.md +3 -0
  107. kaggle_environments/envs/lux_ai_2021/__init__.py +0 -0
  108. kaggle_environments/envs/lux_ai_2021/agents.py +11 -0
  109. kaggle_environments/envs/lux_ai_2021/dimensions/754.js +2 -0
  110. kaggle_environments/envs/lux_ai_2021/dimensions/754.js.LICENSE.txt +296 -0
  111. kaggle_environments/envs/lux_ai_2021/dimensions/main.js +1 -0
  112. kaggle_environments/envs/lux_ai_2021/index.html +43 -0
  113. kaggle_environments/envs/lux_ai_2021/lux_ai_2021.json +100 -0
  114. kaggle_environments/envs/lux_ai_2021/lux_ai_2021.py +231 -0
  115. kaggle_environments/envs/lux_ai_2021/test_agents/__init__.py +0 -0
  116. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/game_constants.js +6 -0
  117. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/game_constants.json +59 -0
  118. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/game_objects.js +145 -0
  119. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/io.js +14 -0
  120. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/kit.js +209 -0
  121. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/map.js +107 -0
  122. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/parser.js +79 -0
  123. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/main.js +88 -0
  124. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/main.py +75 -0
  125. kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/simple.tar.gz +0 -0
  126. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/__init__.py +0 -0
  127. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/annotate.py +20 -0
  128. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/constants.py +25 -0
  129. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game.py +86 -0
  130. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_constants.json +59 -0
  131. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_constants.py +7 -0
  132. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_map.py +106 -0
  133. kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_objects.py +154 -0
  134. kaggle_environments/envs/lux_ai_2021/test_agents/python/random_agent.py +38 -0
  135. kaggle_environments/envs/lux_ai_2021/test_agents/python/simple_agent.py +82 -0
  136. kaggle_environments/envs/lux_ai_2021/test_lux.py +19 -0
  137. kaggle_environments/envs/lux_ai_2021/testing.md +23 -0
  138. kaggle_environments/envs/lux_ai_2021/todo.md.og +18 -0
  139. kaggle_environments/envs/lux_ai_s3/README.md +21 -0
  140. kaggle_environments/envs/lux_ai_s3/agents.py +5 -0
  141. kaggle_environments/envs/lux_ai_s3/index.html +42 -0
  142. kaggle_environments/envs/lux_ai_s3/lux_ai_s3.json +47 -0
  143. kaggle_environments/envs/lux_ai_s3/lux_ai_s3.py +178 -0
  144. kaggle_environments/envs/lux_ai_s3/luxai_s3/__init__.py +1 -0
  145. kaggle_environments/envs/lux_ai_s3/luxai_s3/env.py +819 -0
  146. kaggle_environments/envs/lux_ai_s3/luxai_s3/globals.py +9 -0
  147. kaggle_environments/envs/lux_ai_s3/luxai_s3/params.py +101 -0
  148. kaggle_environments/envs/lux_ai_s3/luxai_s3/profiler.py +141 -0
  149. kaggle_environments/envs/lux_ai_s3/luxai_s3/pygame_render.py +222 -0
  150. kaggle_environments/envs/lux_ai_s3/luxai_s3/spaces.py +27 -0
  151. kaggle_environments/envs/lux_ai_s3/luxai_s3/state.py +464 -0
  152. kaggle_environments/envs/lux_ai_s3/luxai_s3/utils.py +12 -0
  153. kaggle_environments/envs/lux_ai_s3/luxai_s3/wrappers.py +156 -0
  154. kaggle_environments/envs/lux_ai_s3/test_agents/python/agent.py +78 -0
  155. kaggle_environments/envs/lux_ai_s3/test_agents/python/lux/__init__.py +0 -0
  156. kaggle_environments/envs/lux_ai_s3/test_agents/python/lux/kit.py +31 -0
  157. kaggle_environments/envs/lux_ai_s3/test_agents/python/lux/utils.py +17 -0
  158. kaggle_environments/envs/lux_ai_s3/test_agents/python/main.py +66 -0
  159. kaggle_environments/envs/lux_ai_s3/test_lux.py +9 -0
  160. kaggle_environments/envs/mab/__init__.py +0 -0
  161. kaggle_environments/envs/mab/agents.py +12 -0
  162. kaggle_environments/envs/mab/mab.js +100 -0
  163. kaggle_environments/envs/mab/mab.json +74 -0
  164. kaggle_environments/envs/mab/mab.py +146 -0
  165. kaggle_environments/envs/open_spiel/__init__.py +0 -0
  166. kaggle_environments/envs/open_spiel/games/__init__.py +0 -0
  167. kaggle_environments/envs/open_spiel/games/chess/chess.js +441 -0
  168. kaggle_environments/envs/open_spiel/games/chess/image_config.jsonl +20 -0
  169. kaggle_environments/envs/open_spiel/games/chess/openings.jsonl +20 -0
  170. kaggle_environments/envs/open_spiel/games/connect_four/__init__.py +0 -0
  171. kaggle_environments/envs/open_spiel/games/connect_four/connect_four.js +284 -0
  172. kaggle_environments/envs/open_spiel/games/connect_four/connect_four_proxy.py +86 -0
  173. kaggle_environments/envs/open_spiel/games/go/__init__.py +0 -0
  174. kaggle_environments/envs/open_spiel/games/go/go.js +481 -0
  175. kaggle_environments/envs/open_spiel/games/go/go_proxy.py +99 -0
  176. kaggle_environments/envs/open_spiel/games/tic_tac_toe/__init__.py +0 -0
  177. kaggle_environments/envs/open_spiel/games/tic_tac_toe/tic_tac_toe.js +345 -0
  178. kaggle_environments/envs/open_spiel/games/tic_tac_toe/tic_tac_toe_proxy.py +98 -0
  179. kaggle_environments/envs/open_spiel/games/universal_poker/__init__.py +0 -0
  180. kaggle_environments/envs/open_spiel/games/universal_poker/universal_poker.js +431 -0
  181. kaggle_environments/envs/open_spiel/games/universal_poker/universal_poker_proxy.py +159 -0
  182. kaggle_environments/envs/open_spiel/html_playthrough_generator.py +31 -0
  183. kaggle_environments/envs/open_spiel/observation.py +128 -0
  184. kaggle_environments/envs/open_spiel/open_spiel.py +565 -0
  185. kaggle_environments/envs/open_spiel/proxy.py +138 -0
  186. kaggle_environments/envs/open_spiel/test_open_spiel.py +191 -0
  187. kaggle_environments/envs/rps/__init__.py +0 -0
  188. kaggle_environments/envs/rps/agents.py +84 -0
  189. kaggle_environments/envs/rps/helpers.py +25 -0
  190. kaggle_environments/envs/rps/rps.js +117 -0
  191. kaggle_environments/envs/rps/rps.json +63 -0
  192. kaggle_environments/envs/rps/rps.py +90 -0
  193. kaggle_environments/envs/rps/test_rps.py +110 -0
  194. kaggle_environments/envs/rps/utils.py +7 -0
  195. kaggle_environments/envs/tictactoe/test_tictactoe.py +43 -77
  196. kaggle_environments/envs/tictactoe/tictactoe.ipynb +1397 -0
  197. kaggle_environments/envs/tictactoe/tictactoe.json +10 -2
  198. kaggle_environments/envs/tictactoe/tictactoe.py +1 -1
  199. kaggle_environments/errors.py +2 -4
  200. kaggle_environments/helpers.py +377 -0
  201. kaggle_environments/main.py +214 -50
  202. kaggle_environments/schemas.json +23 -18
  203. kaggle_environments/static/player.html +206 -74
  204. kaggle_environments/utils.py +46 -73
  205. kaggle_environments-1.20.0.dist-info/METADATA +25 -0
  206. kaggle_environments-1.20.0.dist-info/RECORD +211 -0
  207. {kaggle_environments-0.2.0.dist-info → kaggle_environments-1.20.0.dist-info}/WHEEL +1 -2
  208. kaggle_environments-1.20.0.dist-info/entry_points.txt +3 -0
  209. kaggle_environments/envs/battlegeese/battlegeese.py +0 -219
  210. kaggle_environments/temp.py +0 -14
  211. kaggle_environments-0.2.0.dist-info/METADATA +0 -393
  212. kaggle_environments-0.2.0.dist-info/RECORD +0 -33
  213. kaggle_environments-0.2.0.dist-info/entry_points.txt +0 -3
  214. kaggle_environments-0.2.0.dist-info/top_level.txt +0 -1
  215. {kaggle_environments-0.2.0.dist-info → kaggle_environments-1.20.0.dist-info/licenses}/LICENSE +0 -0
@@ -16,328 +16,191 @@ import copy
16
16
  import json
17
17
  import math
18
18
  from os import path
19
- from random import choice, randint, shuffle
19
+ from random import choice, randint, randrange, sample, seed
20
+
21
+ import numpy as np
22
+
23
+ from kaggle_environments import utils
24
+
25
+ from .helpers import Board, ShipAction, ShipyardAction, board_agent
20
26
 
21
27
 
22
28
  def get_col_row(size, pos):
23
- return (pos % size, pos // size)
29
+ return pos % size, pos // size
24
30
 
25
31
 
26
32
  def get_to_pos(size, pos, direction):
27
33
  col, row = get_col_row(size, pos)
28
34
  if direction == "NORTH":
29
- return pos - size if pos >= size else size ** 2 - size + col
35
+ return pos - size if pos >= size else size**2 - size + col
30
36
  elif direction == "SOUTH":
31
- return col if pos + size >= size ** 2 else pos + size
37
+ return col if pos + size >= size**2 else pos + size
32
38
  elif direction == "EAST":
33
39
  return pos + 1 if col < size - 1 else row * size
34
40
  elif direction == "WEST":
35
41
  return pos - 1 if col > 0 else (row + 1) * size - 1
36
42
 
37
43
 
38
- class Board:
39
- def __init__(self, obs, config):
40
- self.action = {}
41
- self.obs = obs
42
- self.config = config
43
- size = config.size
44
-
45
- self.shipyards = [-1] * size ** 2
46
- self.shipyards_by_uid = {}
47
- self.ships = [None] * size ** 2
48
- self.ships_by_uid = {}
49
- self.possible_ships = [{} for _ in range(size ** 2)]
50
-
51
- for index, player in enumerate(obs.players):
52
- _, shipyards, ships = player
53
- for uid, pos in shipyards.items():
54
- self.shipyards[pos] = index
55
- self.shipyards_by_uid[uid] = {"player_index": index, "uid": uid, "pos": pos}
56
- for uid, ship in ships.items():
57
- pos, ship_halite = ship
58
- details = {"halite": ship_halite, "player_index": index, "uid": uid, "pos": pos}
59
- self.ships[pos] = details
60
- self.ships_by_uid[uid] = details
61
- for direction in ["NORTH", "EAST", "SOUTH", "WEST"]:
62
- self.possible_ships[get_to_pos(size, pos, direction)][uid] = details
63
-
64
- def move(self, ship_uid, direction):
65
- self.action[ship_uid] = direction
66
- # Update the board.
67
- self.__remove_possibles(ship_uid)
68
- ship = self.ships_by_uid[ship_uid]
69
- pos = ship["pos"]
70
- to_pos = get_to_pos(self.config.size, pos, direction)
71
- ship["pos"] = to_pos
72
- self.ships[pos] = None
73
- self.ships[to_pos] = ship
74
-
75
- def convert(self, ship_uid):
76
- self.action[ship_uid] = "CONVERT"
77
- # Update the board.
78
- self.__remove_possibles(ship_uid)
79
- pos = self.ships_by_uid[ship_uid]["pos"]
80
- self.shipyards[pos] = self.obs.player
81
- self.ships[pos] = None
82
- del self.ships_by_uid[ship_uid]
83
-
84
- def spawn(self, shipyard_uid):
85
- self.action[shipyard_uid] = "SPAWN"
86
- # Update the board.
87
- temp_uid = f"Spawn_Ship_{shipyard_uid}"
88
- pos = self.shipyards_by_uid[shipyard_uid]["pos"]
89
- details = {"halite": 0, "player_index": self.obs.player, "uid": temp_uid, "pos": pos}
90
- self.ships[pos] = details
91
- self.ships_by_uid = details
92
-
93
- def __remove_possibles(self, ship_uid):
94
- pos = self.ships_by_uid[ship_uid]["pos"]
95
- for d in ["NORTH", "EAST", "SOUTH", "WEST"]:
96
- to_pos = get_to_pos(self.config.size, pos, d)
97
- del self.possible_ships[to_pos][ship_uid]
98
-
99
- def random_agent(obs, config):
100
- size = config.size
101
- halite = obs.halite
102
- board = Board(obs, config)
103
- player_halite, shipyards, ships = obs.players[obs.player]
104
-
105
- # Move, Convert, or have ships collect halite.
106
- ships_items = list(ships.items())
107
- shuffle(ships_items) # shuffle so ship1 doesn't always have first moving dibs.
108
- for uid, ship in ships_items:
109
- pos, ship_halite = ship
110
- # Collect Halite (50% probability when cell halite > ship_halite).
111
- if board.shipyards[pos] == -1 and halite[pos] > ship_halite and randint(0,1) == 1:
112
- continue
113
- # Convert to Shipyard (50% probability when no shipyards, 5% otherwise).
114
- if board.shipyards[pos] == -1 and player_halite > config.convertCost and randint(0, 20 if len(shipyards) else 1) == 1:
115
- board.convert(uid)
44
+ @board_agent
45
+ def random_agent(board):
46
+ me = board.current_player
47
+ remaining_halite = me.halite
48
+ ships = me.ships
49
+ # randomize ship order
50
+ ships = sample(ships, len(ships))
51
+ for ship in ships:
52
+ if ship.cell.halite > ship.halite and randint(0, 1) == 0:
53
+ # 50% chance to mine
116
54
  continue
117
- # Move Ship (random between all available directions).
118
- move_choices = [None]
119
- for direction in ["NORTH", "EAST", "SOUTH", "WEST"]:
120
- to_pos = get_to_pos(size, pos, direction)
121
- # Enemy shipyard present.
122
- if board.shipyards[to_pos] != obs.player and board.shipyards[to_pos] != -1:
55
+ if ship.cell.shipyard is None and remaining_halite > board.configuration.convert_cost:
56
+ # 5% chance to convert at any time
57
+ if randint(0, 19) == 0:
58
+ remaining_halite -= board.configuration.convert_cost
59
+ ship.next_action = ShipAction.CONVERT
123
60
  continue
124
- # Larger ship most likely staying in place.
125
- if board.ships[to_pos] != None and board.ships[to_pos]["halite"] >= ship_halite:
61
+ # 50% chance to convert if there are no shipyards
62
+ if randint(0, 1) == 0 and len(me.shipyards) == 0:
63
+ remaining_halite -= board.configuration.convert_cost
64
+ ship.next_action = ShipAction.CONVERT
126
65
  continue
127
- # Weigh the direction based on number of possible larger ships that could be present.
128
- weight = 6
129
- if board.ships[to_pos] != None and board.ships[to_pos]["player_index"] == obs.player:
130
- weight -= 1
131
- for s in board.possible_ships[to_pos].values():
132
- if s["halite"] > ship_halite:
133
- weight -= 1
134
- move_choices += [direction] * weight
135
- move = choice(move_choices)
136
- if move != None:
137
- board.move(uid, move)
138
-
139
- # Spawn ships (30% probability when possible, or 100% if no ships).
140
- for uid, pos in shipyards.items():
141
- if board.ships[pos] == None and player_halite >= config.spawnCost and (randint(0,2) == 2 or len(ships_items) == 0):
142
- board.spawn(uid)
143
-
144
- return board.action
66
+ # None represents the chance to do nothing
67
+ ship.next_action = choice(ShipAction.moves())
68
+ shipyards = me.shipyards
69
+ # randomize shipyard order
70
+ shipyards = sample(shipyards, len(shipyards))
71
+ ship_count = len(board.next().current_player.ships)
72
+ for shipyard in shipyards:
73
+ # If there are no ships, always spawn if possible
74
+ if ship_count == 0 and remaining_halite > board.configuration.spawn_cost:
75
+ remaining_halite -= board.configuration.spawn_cost
76
+ shipyard.next_action = ShipyardAction.SPAWN
77
+ # 20% chance to spawn if no ships
78
+ elif randint(0, 4) == 0 and remaining_halite > board.configuration.spawn_cost:
79
+ remaining_halite -= board.configuration.spawn_cost
80
+ shipyard.next_action = ShipyardAction.SPAWN
145
81
 
146
82
 
147
83
  agents = {"random": random_agent}
148
84
 
149
85
 
150
- def interpreter(state, env):
86
+ def populate_board(state, env):
151
87
  obs = state[0].observation
152
88
  config = env.configuration
153
89
  size = env.configuration.size
90
+ uid_counter = 0
154
91
 
155
- # Update step index.
156
- obs.step = len(env.steps)
92
+ # Set seed for random number generators
93
+ if not hasattr(config, "randomSeed"):
94
+ max_int_32 = (1 << 31) - 1
95
+ config.randomSeed = randrange(max_int_32)
157
96
 
158
- # UID generator.
159
- uid_counter = 0
97
+ np.random.seed(config.randomSeed)
98
+ seed(config.randomSeed)
160
99
 
100
+ # This is a consistent way to generate unique strings to form ship and shipyard ids
161
101
  def create_uid():
162
102
  nonlocal uid_counter
163
103
  uid_counter += 1
164
104
  return f"{obs.step}-{uid_counter}"
165
105
 
106
+ # Distribute Halite evenly into quartiles.
107
+ half = math.ceil(size / 2)
108
+ grid = [[0] * half for _ in range(half)]
109
+
110
+ # Randomly place a few halite "seeds".
111
+ for i in range(half):
112
+ # random distribution across entire quartile
113
+ grid[randint(0, half - 1)][randint(0, half - 1)] = i**2
114
+
115
+ # as well as a particular distribution weighted toward the center of the map
116
+ grid[randint(half // 2, half - 1)][randint(half // 2, half - 1)] = i**2
117
+
118
+ # Spread the seeds radially.
119
+ radius_grid = copy.deepcopy(grid)
120
+ for r in range(half):
121
+ for c in range(half):
122
+ value = grid[r][c]
123
+ if value == 0:
124
+ continue
125
+
126
+ # keep initial seed values, but constrain radius of clusters
127
+ radius = min(round((value / half) ** 0.5), 1)
128
+ for r2 in range(r - radius + 1, r + radius):
129
+ for c2 in range(c - radius + 1, c + radius):
130
+ if 0 <= r2 < half and 0 <= c2 < half:
131
+ distance = (abs(r2 - r) ** 2 + abs(c2 - c) ** 2) ** 0.5
132
+ radius_grid[r2][c2] += int(value / max(1, distance) ** distance)
133
+
134
+ # add some random sprouts of halite
135
+ radius_grid = np.asarray(radius_grid)
136
+ add_grid = np.random.gumbel(0, 300.0, size=(half, half)).astype(int)
137
+ sparse_radius_grid = np.random.binomial(1, 0.5, size=(half, half))
138
+ add_grid = np.clip(add_grid, 0, a_max=None) * sparse_radius_grid
139
+ radius_grid += add_grid
140
+
141
+ # add another set of random locations to the center corner
142
+ corner_grid = np.random.gumbel(0, 500.0, size=(half // 4, half // 4)).astype(int)
143
+ corner_grid = np.clip(corner_grid, 0, a_max=None)
144
+ radius_grid[half - (half // 4) :, half - (half // 4) :] += corner_grid
145
+
146
+ # Normalize the available halite against the defined configuration starting halite.
147
+ total = sum([sum(row) for row in radius_grid])
148
+ obs.halite = [0] * (size**2)
149
+ for r, row in enumerate(radius_grid):
150
+ for c, val in enumerate(row):
151
+ val = int(val * config.startingHalite / total / 4)
152
+ obs.halite[size * r + c] = val
153
+ obs.halite[size * r + (size - c - 1)] = val
154
+ obs.halite[size * (size - 1) - (size * r) + c] = val
155
+ obs.halite[size * (size - 1) - (size * r) + (size - c - 1)] = val
156
+
157
+ # Distribute the starting ships evenly.
158
+ num_agents = len(state)
159
+ starting_positions = [0] * num_agents
160
+ if num_agents == 1:
161
+ starting_positions[0] = size * (size // 2) + size // 2
162
+ elif num_agents == 2:
163
+ starting_positions[0] = size * (size // 2) + size // 4
164
+ starting_positions[1] = size * (size // 2) + math.ceil(3 * size / 4) - 1
165
+ elif num_agents == 4:
166
+ starting_positions[0] = size * (size // 4) + size // 4
167
+ starting_positions[1] = size * (size // 4) + 3 * size // 4
168
+ starting_positions[2] = size * (3 * size // 4) + size // 4
169
+ starting_positions[3] = size * (3 * size // 4) + 3 * size // 4
170
+
171
+ # Initialize the players.
172
+ obs.players = []
173
+ for i in range(num_agents):
174
+ ships = {create_uid(): [starting_positions[i], 0]}
175
+ obs.players.append([state[0].reward, {}, ships])
176
+
177
+ return state
178
+
179
+
180
+ def interpreter(state, env):
181
+ obs = state[0].observation
182
+ config = env.configuration
183
+
166
184
  # Initialize the board (place cell halite and starting ships).
167
185
  if env.done:
168
- # Distribute Halite evenly into quartiles.
169
- half = math.ceil(size / 2)
170
- grid = [[0] * half for _ in range(half)]
171
-
172
- # Randomly place a few halite "seeds".
173
- for i in range(half):
174
- grid[randint(0, half-1)][randint(0, half-1)] = i ** 2
175
-
176
- # Spread the seeds radially.
177
- radius_grid = copy.deepcopy(grid)
178
- for r in range(half):
179
- for c in range(half):
180
- value = grid[r][c]
181
- if value == 0:
182
- continue
183
- radius = round((value / half) ** (0.5))
184
- for r2 in range(r-radius+1, r+radius):
185
- for c2 in range(c-radius+1, c+radius):
186
- if r2 >= 0 and r2 < half and c2 >= 0 and c2 < half:
187
- distance = (abs(r2-r) ** 2 +
188
- abs(c2-c) ** 2) ** (0.5)
189
- radius_grid[r2][c2] += int(value /
190
- max(1, distance) ** distance)
191
-
192
- # Normalize the available halite against the defined configuration starting halite.
193
- total = sum([sum(row) for row in radius_grid])
194
- obs.halite = [0] * (size ** 2)
195
- for r, row in enumerate(radius_grid):
196
- for c, val in enumerate(row):
197
- val = int(val * config.halite / total / 4)
198
- obs.halite[size * r + c] = val
199
- obs.halite[size * r + (size - c - 1)] = val
200
- obs.halite[size * (size - 1) - (size * r) + c] = val
201
- obs.halite[size * (size - 1) - (size * r) +
202
- (size - c - 1)] = val
203
-
204
- # Distribute the starting ships evenly.
205
- num_agents = len(state)
206
- starting_positions = [0] * num_agents
207
- if num_agents == 1:
208
- starting_positions[0] = size * (size // 2) + size // 2
209
- elif num_agents == 2:
210
- starting_positions[0] = size * (size // 2) + size // 4
211
- starting_positions[1] = size * \
212
- (size // 2) + math.ceil(3 * size / 4) - 1
213
- elif num_agents == 4:
214
- starting_positions[0] = size * (size // 4) + size // 4
215
- starting_positions[1] = size * (size // 4) + 3 * size // 4
216
- starting_positions[2] = size * (3 * size // 4) + size // 4
217
- starting_positions[3] = size * (3 * size // 4) + 3 * size // 4
218
-
219
- # Initialize the players.
220
- obs.players = []
221
- for i in range(num_agents):
222
- ships = {create_uid(): [starting_positions[i], 0]}
223
- obs.players.append([state[0].reward, {}, ships])
224
-
225
- return state
226
-
227
- # Apply actions to create an updated observation.
228
- for index, agent in enumerate(state):
229
- player_halite, shipyards, ships = obs.players[index]
230
- if agent.action == None:
231
- continue
232
- for uid, action in agent.action.items():
233
- # Shipyard action (spawn ship):
234
- if action == "SPAWN":
235
- if not uid in shipyards:
236
- agent.status = f"{uid} shipyard asset not found."
237
- elif player_halite < config.spawnCost:
238
- agent.status = "Insufficient halite to spawn a ship from a shipyard."
239
- else:
240
- ships[create_uid()] = [shipyards[uid], 0]
241
- player_halite -= int(config.spawnCost)
242
- break
243
- # Ship Actions. Ship must be present.
244
- elif not uid in ships:
245
- agent.status = f"{uid} ship asset not found."
246
- break
247
- ship_pos, ship_halite = ships[uid]
248
-
249
- # Create a Shipyard.
250
- if action == "CONVERT":
251
- if player_halite < config.convertCost - ship_halite:
252
- agent.status = "Insufficient halite to convert a ship to a shipyard."
253
- elif ship_pos in shipyards.values():
254
- agent.status = "Shipyard already present. Cannot convert ship."
255
- else:
256
- shipyards[create_uid()] = ship_pos
257
- player_halite += int(ship_halite - config.convertCost)
258
- obs.halite[ship_pos] = 0
259
- del ships[uid]
260
- break
261
-
262
- # Move Ship Actions.
263
- to_pos = get_to_pos(size, ship_pos, action)
264
- ships[uid] = [to_pos, int(ship_halite * (1 - config.moveCost))]
265
-
266
- # Update the player.
267
- obs.players[index] = [player_halite, shipyards, ships]
268
-
269
- # Detect collisions
270
- # 1. Ships into Foreign Shipyards.
271
- # 2. Ships into Ships.
272
- board = [[-1, {}] for _ in range(size ** 2)]
273
- for index, agent in enumerate(state):
274
- if agent.status != "ACTIVE":
275
- continue
276
- _, shipyards, ships = obs.players[index]
277
- for uid, shipyard_pos in shipyards.items():
278
- board[shipyard_pos][0] = index
279
- for uid, ship in ships.items():
280
- board[ship[0]][1][uid] = index
281
- for pos, cell in enumerate(board):
282
- shipyard, ships = cell
283
- # Detect Shipyard Collisions.
284
- if shipyard > -1:
285
- for uid, index in list(ships.items()):
286
- if shipyard != index:
287
- del ships[uid]
288
- del obs.players[index][2][uid]
289
- # Detect Ship Collections.
290
- if len(ships) > 1:
291
- largest_ships = [[i, uid, obs.players[i][2][uid][1]]
292
- for uid, i in ships.items()]
293
- largest_ships.sort(key=lambda s: -s[2])
294
- for i, lship in enumerate(largest_ships):
295
- player_index, uid, ship_halite = lship
296
- # Remove collided ships.
297
- if i > 0 or ship_halite == largest_ships[i+1][2]:
298
- del obs.players[player_index][2][uid]
299
- # Reduce halite available with remaining ship.
300
- else:
301
- obs.players[player_index][2][uid][1] -= largest_ships[i+1][2]
302
- # Remove cell halite (destroyed in explosion)
303
- obs.halite[pos] = 0
304
-
305
- # Remove players with invalid status or insufficent potential.
186
+ return populate_board(state, env)
187
+
188
+ # Interpreter invoked here
189
+ actions = [agent.action for agent in state]
190
+ board = Board(obs, config, actions)
191
+ board = board.next()
192
+ state[0].observation = obs = utils.structify(board.observation)
193
+
194
+ # Remove players with invalid status or insufficient potential.
306
195
  for index, agent in enumerate(state):
307
196
  player_halite, shipyards, ships = obs.players[index]
308
197
  if agent.status == "ACTIVE" and len(ships) == 0 and (len(shipyards) == 0 or player_halite < config.spawnCost):
309
- agent.status = "No potential to gather halite remaining."
310
- if agent.status != "ACTIVE":
198
+ # Agent can no longer gather any halite
199
+ agent.status = "DONE"
200
+ agent.reward = board.step - board.configuration.episode_steps - 1
201
+ if agent.status != "ACTIVE" and agent.status != "DONE":
311
202
  obs.players[index] = [0, {}, {}]
312
203
 
313
- # Collect and Regenerate Halite.
314
- asset_positions = []
315
- for index, agent in enumerate(state):
316
- player_halite, shipyards, ships = obs.players[index]
317
- shipyard_positions = shipyards.values()
318
- asset_positions.extend(shipyard_positions)
319
- for uid, ship in ships.items():
320
- ship_pos, ship_halite = ship
321
- asset_positions.append(ship_pos)
322
- # Ship moved and not eligible for collection.
323
- if uid in agent.action:
324
- continue
325
- # Collect halite from ships into shipyards.
326
- if ship_pos in shipyard_positions:
327
- obs.players[index][0] += ship_halite
328
- ship[1] = 0
329
- # Collect halite from cells into ships.
330
- elif obs.halite[ship_pos] > 0:
331
- collect_halite = max(
332
- 1, int(obs.halite[ship_pos] * config.collectRate))
333
- obs.halite[ship_pos] -= collect_halite
334
- ship[1] += collect_halite
335
- for pos, halite in enumerate(obs.halite):
336
- if pos in asset_positions:
337
- continue
338
- obs.halite[pos] = halite * (1 + config.regenRate)
339
-
340
-
341
204
  # Check if done (< 2 players and num_agents > 1)
342
205
  if len(state) > 1 and sum(1 for agent in state if agent.status == "ACTIVE") < 2:
343
206
  for agent in state:
@@ -346,9 +209,9 @@ def interpreter(state, env):
346
209
 
347
210
  # Update Rewards.
348
211
  for index, agent in enumerate(state):
349
- if agent.status == "ACTIVE" or agent.status == "DONE":
212
+ if agent.status == "ACTIVE":
350
213
  agent.reward = obs.players[index][0]
351
- else:
214
+ elif agent.status != "DONE":
352
215
  agent.reward = 0
353
216
 
354
217
  return state
@@ -363,41 +226,39 @@ def renderer(state, env):
363
226
  for index, player in enumerate(obs.players):
364
227
  _, shipyards, ships = player
365
228
  for shipyard_pos in shipyards.values():
366
- board[shipyard_pos][1] = index
229
+ board[int(shipyard_pos)][1] = index
367
230
  for ship in ships.values():
368
231
  ship_pos, ship_halite = ship
369
- board[ship_pos][2] = index
370
- board[ship_pos][3] = ship_halite
232
+ board[int(ship_pos)][2] = index
233
+ board[int(ship_pos)][3] = ship_halite
371
234
 
372
- colDivider = "|"
373
- rowDivider = "+" + "+".join(["----"] * size) + "+\n"
235
+ col_divider = "|"
236
+ row_divider = "+" + "+".join(["----"] * size) + "+\n"
374
237
 
375
- out = rowDivider
238
+ out = row_divider
376
239
  for row in range(size):
377
240
  for col in range(size):
378
241
  _, _, ship, ship_halite = board[col + row * size]
379
- out += colDivider + (
380
- f"{min(int(ship_halite), 99)}S{ship}" if ship > -1 else ""
381
- ).ljust(4)
382
- out += colDivider + "\n"
242
+ out += col_divider + (f"{min(int(ship_halite), 99)}S{ship}" if ship > -1 else "").ljust(4)
243
+ out += col_divider + "\n"
383
244
  for col in range(size):
384
245
  halite, shipyard, _, _ = board[col + row * size]
385
246
  if shipyard > -1:
386
- out += colDivider + f"SY{shipyard}".ljust(4)
247
+ out += col_divider + f"SY{shipyard}".ljust(4)
387
248
  else:
388
- out += colDivider + str(min(int(halite), 9999)).rjust(4)
389
- out += colDivider + "\n" + rowDivider
249
+ out += col_divider + str(min(int(halite), 9999)).rjust(4)
250
+ out += col_divider + "\n" + row_divider
390
251
 
391
252
  return out
392
253
 
393
254
 
394
- dirpath = path.dirname(__file__)
395
- jsonpath = path.abspath(path.join(dirpath, "halite.json"))
396
- with open(jsonpath) as f:
397
- specification = json.load(f)
255
+ dir_path = path.dirname(__file__)
256
+ json_path = path.abspath(path.join(dir_path, "halite.json"))
257
+ with open(json_path) as json_file:
258
+ specification = json.load(json_file)
398
259
 
399
260
 
400
261
  def html_renderer():
401
- jspath = path.abspath(path.join(dirpath, "halite.js"))
402
- with open(jspath) as f:
403
- return f.read()
262
+ js_path = path.abspath(path.join(dir_path, "halite.js"))
263
+ with open(js_path, encoding="utf-8") as js_file:
264
+ return js_file.read()