kaggle-environments 0.2.1__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.
- kaggle_environments/__init__.py +49 -13
- kaggle_environments/agent.py +177 -124
- kaggle_environments/api.py +31 -0
- kaggle_environments/core.py +295 -170
- kaggle_environments/envs/cabt/cabt.js +164 -0
- kaggle_environments/envs/cabt/cabt.json +28 -0
- kaggle_environments/envs/cabt/cabt.py +186 -0
- kaggle_environments/envs/cabt/cg/__init__.py +0 -0
- kaggle_environments/envs/cabt/cg/cg.dll +0 -0
- kaggle_environments/envs/cabt/cg/game.py +75 -0
- kaggle_environments/envs/cabt/cg/libcg.so +0 -0
- kaggle_environments/envs/cabt/cg/sim.py +48 -0
- kaggle_environments/envs/cabt/test_cabt.py +120 -0
- kaggle_environments/envs/chess/chess.js +4289 -0
- kaggle_environments/envs/chess/chess.json +60 -0
- kaggle_environments/envs/chess/chess.py +4241 -0
- kaggle_environments/envs/chess/test_chess.py +60 -0
- kaggle_environments/envs/connectx/connectx.ipynb +3186 -0
- kaggle_environments/envs/connectx/connectx.js +1 -1
- kaggle_environments/envs/connectx/connectx.json +15 -1
- kaggle_environments/envs/connectx/connectx.py +6 -23
- kaggle_environments/envs/connectx/test_connectx.py +70 -24
- kaggle_environments/envs/football/football.ipynb +75 -0
- kaggle_environments/envs/football/football.json +91 -0
- kaggle_environments/envs/football/football.py +277 -0
- kaggle_environments/envs/football/helpers.py +95 -0
- kaggle_environments/envs/football/test_football.py +360 -0
- kaggle_environments/envs/halite/__init__.py +0 -0
- kaggle_environments/envs/halite/halite.ipynb +44741 -0
- kaggle_environments/envs/halite/halite.js +199 -83
- kaggle_environments/envs/halite/halite.json +31 -18
- kaggle_environments/envs/halite/halite.py +164 -303
- kaggle_environments/envs/halite/helpers.py +720 -0
- kaggle_environments/envs/halite/test_halite.py +190 -0
- kaggle_environments/envs/hungry_geese/__init__.py +0 -0
- kaggle_environments/envs/{battlegeese/battlegeese.js → hungry_geese/hungry_geese.js} +38 -22
- kaggle_environments/envs/{battlegeese/battlegeese.json → hungry_geese/hungry_geese.json} +21 -14
- kaggle_environments/envs/hungry_geese/hungry_geese.py +316 -0
- kaggle_environments/envs/hungry_geese/test_hungry_geese.py +0 -0
- kaggle_environments/envs/identity/identity.json +6 -5
- kaggle_environments/envs/identity/identity.py +15 -2
- kaggle_environments/envs/kore_fleets/__init__.py +0 -0
- kaggle_environments/envs/kore_fleets/helpers.py +1005 -0
- kaggle_environments/envs/kore_fleets/kore_fleets.ipynb +114 -0
- kaggle_environments/envs/kore_fleets/kore_fleets.js +658 -0
- kaggle_environments/envs/kore_fleets/kore_fleets.json +164 -0
- kaggle_environments/envs/kore_fleets/kore_fleets.py +555 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/Bot.java +54 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/README.md +26 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/jars/hamcrest-core-1.3.jar +0 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/jars/junit-4.13.2.jar +0 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Board.java +518 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Cell.java +61 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Configuration.java +24 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Direction.java +166 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Fleet.java +72 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/KoreJson.java +97 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Observation.java +72 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Pair.java +13 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Player.java +68 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Point.java +65 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/Shipyard.java +70 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/kore/ShipyardAction.java +59 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/main.py +73 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/test/BoardTest.java +567 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/test/ConfigurationTest.java +25 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/test/KoreJsonTest.java +62 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/test/ObservationTest.java +46 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/test/PointTest.java +21 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/test/ShipyardTest.java +22 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/test/configuration.json +1 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/test/fullob.json +1 -0
- kaggle_environments/envs/kore_fleets/starter_bots/java/test/observation.json +1 -0
- kaggle_environments/envs/kore_fleets/starter_bots/python/__init__.py +0 -0
- kaggle_environments/envs/kore_fleets/starter_bots/python/main.py +27 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/Bot.ts +34 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/DoNothingBot.ts +12 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/MinerBot.ts +62 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/README.md +55 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/interpreter.ts +402 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Board.ts +514 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Cell.ts +63 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Configuration.ts +25 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Direction.ts +169 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Fleet.ts +76 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/KoreIO.ts +70 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Observation.ts +45 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Pair.ts +11 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Player.ts +68 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Point.ts +65 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/Shipyard.ts +72 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/kore/ShipyardAction.ts +58 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/main.py +73 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/miner.py +73 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/package.json +23 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/test/BoardTest.ts +551 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/test/ConfigurationTest.ts +16 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/test/ObservationTest.ts +33 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/test/PointTest.ts +17 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/test/ShipyardTest.ts +18 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/test/configuration.json +1 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/test/fullob.json +1 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/test/observation.json +1 -0
- kaggle_environments/envs/kore_fleets/starter_bots/ts/tsconfig.json +22 -0
- kaggle_environments/envs/kore_fleets/test_kore_fleets.py +331 -0
- kaggle_environments/envs/lux_ai_2021/README.md +3 -0
- kaggle_environments/envs/lux_ai_2021/__init__.py +0 -0
- kaggle_environments/envs/lux_ai_2021/agents.py +11 -0
- kaggle_environments/envs/lux_ai_2021/dimensions/754.js +2 -0
- kaggle_environments/envs/lux_ai_2021/dimensions/754.js.LICENSE.txt +296 -0
- kaggle_environments/envs/lux_ai_2021/dimensions/main.js +1 -0
- kaggle_environments/envs/lux_ai_2021/index.html +43 -0
- kaggle_environments/envs/lux_ai_2021/lux_ai_2021.json +100 -0
- kaggle_environments/envs/lux_ai_2021/lux_ai_2021.py +231 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/__init__.py +0 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/game_constants.js +6 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/game_constants.json +59 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/game_objects.js +145 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/io.js +14 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/kit.js +209 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/map.js +107 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/lux/parser.js +79 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/main.js +88 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/main.py +75 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/js_simple/simple.tar.gz +0 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/__init__.py +0 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/annotate.py +20 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/constants.py +25 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game.py +86 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_constants.json +59 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_constants.py +7 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_map.py +106 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/python/lux/game_objects.py +154 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/python/random_agent.py +38 -0
- kaggle_environments/envs/lux_ai_2021/test_agents/python/simple_agent.py +82 -0
- kaggle_environments/envs/lux_ai_2021/test_lux.py +19 -0
- kaggle_environments/envs/lux_ai_2021/testing.md +23 -0
- kaggle_environments/envs/lux_ai_2021/todo.md.og +18 -0
- kaggle_environments/envs/lux_ai_s3/README.md +21 -0
- kaggle_environments/envs/lux_ai_s3/agents.py +5 -0
- kaggle_environments/envs/lux_ai_s3/index.html +42 -0
- kaggle_environments/envs/lux_ai_s3/lux_ai_s3.json +47 -0
- kaggle_environments/envs/lux_ai_s3/lux_ai_s3.py +178 -0
- kaggle_environments/envs/lux_ai_s3/luxai_s3/__init__.py +1 -0
- kaggle_environments/envs/lux_ai_s3/luxai_s3/env.py +819 -0
- kaggle_environments/envs/lux_ai_s3/luxai_s3/globals.py +9 -0
- kaggle_environments/envs/lux_ai_s3/luxai_s3/params.py +101 -0
- kaggle_environments/envs/lux_ai_s3/luxai_s3/profiler.py +141 -0
- kaggle_environments/envs/lux_ai_s3/luxai_s3/pygame_render.py +222 -0
- kaggle_environments/envs/lux_ai_s3/luxai_s3/spaces.py +27 -0
- kaggle_environments/envs/lux_ai_s3/luxai_s3/state.py +464 -0
- kaggle_environments/envs/lux_ai_s3/luxai_s3/utils.py +12 -0
- kaggle_environments/envs/lux_ai_s3/luxai_s3/wrappers.py +156 -0
- kaggle_environments/envs/lux_ai_s3/test_agents/python/agent.py +78 -0
- kaggle_environments/envs/lux_ai_s3/test_agents/python/lux/__init__.py +0 -0
- kaggle_environments/envs/lux_ai_s3/test_agents/python/lux/kit.py +31 -0
- kaggle_environments/envs/lux_ai_s3/test_agents/python/lux/utils.py +17 -0
- kaggle_environments/envs/lux_ai_s3/test_agents/python/main.py +66 -0
- kaggle_environments/envs/lux_ai_s3/test_lux.py +9 -0
- kaggle_environments/envs/mab/__init__.py +0 -0
- kaggle_environments/envs/mab/agents.py +12 -0
- kaggle_environments/envs/mab/mab.js +100 -0
- kaggle_environments/envs/mab/mab.json +74 -0
- kaggle_environments/envs/mab/mab.py +146 -0
- kaggle_environments/envs/open_spiel/__init__.py +0 -0
- kaggle_environments/envs/open_spiel/games/__init__.py +0 -0
- kaggle_environments/envs/open_spiel/games/chess/chess.js +441 -0
- kaggle_environments/envs/open_spiel/games/chess/image_config.jsonl +20 -0
- kaggle_environments/envs/open_spiel/games/chess/openings.jsonl +20 -0
- kaggle_environments/envs/open_spiel/games/connect_four/__init__.py +0 -0
- kaggle_environments/envs/open_spiel/games/connect_four/connect_four.js +284 -0
- kaggle_environments/envs/open_spiel/games/connect_four/connect_four_proxy.py +86 -0
- kaggle_environments/envs/open_spiel/games/go/__init__.py +0 -0
- kaggle_environments/envs/open_spiel/games/go/go.js +481 -0
- kaggle_environments/envs/open_spiel/games/go/go_proxy.py +99 -0
- kaggle_environments/envs/open_spiel/games/tic_tac_toe/__init__.py +0 -0
- kaggle_environments/envs/open_spiel/games/tic_tac_toe/tic_tac_toe.js +345 -0
- kaggle_environments/envs/open_spiel/games/tic_tac_toe/tic_tac_toe_proxy.py +98 -0
- kaggle_environments/envs/open_spiel/games/universal_poker/__init__.py +0 -0
- kaggle_environments/envs/open_spiel/games/universal_poker/universal_poker.js +431 -0
- kaggle_environments/envs/open_spiel/games/universal_poker/universal_poker_proxy.py +159 -0
- kaggle_environments/envs/open_spiel/html_playthrough_generator.py +31 -0
- kaggle_environments/envs/open_spiel/observation.py +128 -0
- kaggle_environments/envs/open_spiel/open_spiel.py +565 -0
- kaggle_environments/envs/open_spiel/proxy.py +138 -0
- kaggle_environments/envs/open_spiel/test_open_spiel.py +191 -0
- kaggle_environments/envs/rps/__init__.py +0 -0
- kaggle_environments/envs/rps/agents.py +84 -0
- kaggle_environments/envs/rps/helpers.py +25 -0
- kaggle_environments/envs/rps/rps.js +117 -0
- kaggle_environments/envs/rps/rps.json +63 -0
- kaggle_environments/envs/rps/rps.py +90 -0
- kaggle_environments/envs/rps/test_rps.py +110 -0
- kaggle_environments/envs/rps/utils.py +7 -0
- kaggle_environments/envs/tictactoe/test_tictactoe.py +43 -77
- kaggle_environments/envs/tictactoe/tictactoe.ipynb +1397 -0
- kaggle_environments/envs/tictactoe/tictactoe.json +10 -2
- kaggle_environments/envs/tictactoe/tictactoe.py +1 -1
- kaggle_environments/errors.py +2 -4
- kaggle_environments/helpers.py +377 -0
- kaggle_environments/main.py +340 -0
- kaggle_environments/schemas.json +23 -18
- kaggle_environments/static/player.html +206 -74
- kaggle_environments/utils.py +46 -73
- kaggle_environments-1.20.0.dist-info/METADATA +25 -0
- kaggle_environments-1.20.0.dist-info/RECORD +211 -0
- {kaggle_environments-0.2.1.dist-info → kaggle_environments-1.20.0.dist-info}/WHEEL +1 -2
- kaggle_environments-1.20.0.dist-info/entry_points.txt +3 -0
- kaggle_environments/envs/battlegeese/battlegeese.py +0 -223
- kaggle_environments/temp.py +0 -14
- kaggle_environments-0.2.1.dist-info/METADATA +0 -393
- kaggle_environments-0.2.1.dist-info/RECORD +0 -32
- kaggle_environments-0.2.1.dist-info/entry_points.txt +0 -3
- kaggle_environments-0.2.1.dist-info/top_level.txt +0 -1
- {kaggle_environments-0.2.1.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,
|
|
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
|
|
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
|
|
35
|
+
return pos - size if pos >= size else size**2 - size + col
|
|
30
36
|
elif direction == "SOUTH":
|
|
31
|
-
return col if pos + size >= 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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
#
|
|
125
|
-
if
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
|
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
|
-
#
|
|
156
|
-
|
|
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
|
-
|
|
159
|
-
|
|
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
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
310
|
-
|
|
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"
|
|
212
|
+
if agent.status == "ACTIVE":
|
|
350
213
|
agent.reward = obs.players[index][0]
|
|
351
|
-
|
|
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
|
-
|
|
373
|
-
|
|
235
|
+
col_divider = "|"
|
|
236
|
+
row_divider = "+" + "+".join(["----"] * size) + "+\n"
|
|
374
237
|
|
|
375
|
-
out =
|
|
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 +=
|
|
380
|
-
|
|
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 +=
|
|
247
|
+
out += col_divider + f"SY{shipyard}".ljust(4)
|
|
387
248
|
else:
|
|
388
|
-
out +=
|
|
389
|
-
out +=
|
|
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
|
-
|
|
395
|
-
|
|
396
|
-
with open(
|
|
397
|
-
specification = json.load(
|
|
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
|
-
|
|
402
|
-
with open(
|
|
403
|
-
return
|
|
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()
|