-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdefault_agent.py
89 lines (81 loc) · 4.84 KB
/
default_agent.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
from lux.kit import obs_to_game_state, GameState, EnvConfig
from lux.utils import direction_to, my_turn_to_place_factory
import numpy as np
import sys
class Default_Agent():
def __init__(self, player: str, env_cfg: EnvConfig) -> None:
self.player = player
self.opp_player = "player_1" if self.player == "player_0" else "player_0"
np.random.seed(0)
self.env_cfg: EnvConfig = env_cfg
def early_setup(self, step: int, obs, remainingOverageTime: int = 60):
if step == 0:
# bid 0 to not waste resources bidding and declare as the default faction
return dict(faction="AlphaStrike", bid=0)
else:
game_state = obs_to_game_state(step, self.env_cfg, obs)
# factory placement period
# how much water and metal you have in your starting pool to give to new factories
water_left = game_state.teams[self.player].water
metal_left = game_state.teams[self.player].metal
# how many factories you have left to place
factories_to_place = game_state.teams[self.player].factories_to_place
# whether it is your turn to place a factory
my_turn_to_place = my_turn_to_place_factory(game_state.teams[self.player].place_first, step)
if factories_to_place > 0 and my_turn_to_place:
# we will spawn our factory in a random location with 150 metal and water if it is our turn to place
potential_spawns = np.array(list(zip(*np.where(obs["board"]["valid_spawns_mask"] == 1))))
spawn_loc = potential_spawns[np.random.randint(0, len(potential_spawns))]
return dict(spawn=spawn_loc, metal=150, water=150)
return dict()
def act(self, step: int, obs, remainingOverageTime: int = 60):
actions = dict()
game_state = obs_to_game_state(step, self.env_cfg, obs)
factories = game_state.factories[self.player]
game_state.teams[self.player].place_first
factory_tiles, factory_units = [], []
for unit_id, factory in factories.items():
if factory.power >= self.env_cfg.ROBOTS["HEAVY"].POWER_COST and \
factory.cargo.metal >= self.env_cfg.ROBOTS["HEAVY"].METAL_COST:
actions[unit_id] = factory.build_heavy()
if self.env_cfg.max_episode_length - game_state.real_env_steps < 50:
if factory.water_cost(game_state) <= factory.cargo.water:
actions[unit_id] = factory.water()
factory_tiles += [factory.pos]
factory_units += [factory]
factory_tiles = np.array(factory_tiles)
units = game_state.units[self.player]
ice_map = game_state.board.ice
ice_tile_locations = np.argwhere(ice_map == 1)
for unit_id, unit in units.items():
# track the closest factory
closest_factory = None
adjacent_to_factory = False
if len(factory_tiles) > 0:
factory_distances = np.mean((factory_tiles - unit.pos) ** 2, 1)
closest_factory_tile = factory_tiles[np.argmin(factory_distances)]
closest_factory = factory_units[np.argmin(factory_distances)]
adjacent_to_factory = np.mean((closest_factory_tile - unit.pos) ** 2) == 0
# previous ice mining code
if unit.cargo.ice < 40:
ice_tile_distances = np.mean((ice_tile_locations - unit.pos) ** 2, 1)
closest_ice_tile = ice_tile_locations[np.argmin(ice_tile_distances)]
if np.all(closest_ice_tile == unit.pos):
if unit.power >= unit.dig_cost(game_state) + unit.action_queue_cost(game_state):
actions[unit_id] = [unit.dig(repeat=0)]
else:
direction = direction_to(unit.pos, closest_ice_tile)
move_cost = unit.move_cost(game_state, direction)
if move_cost is not None and unit.power >= move_cost + unit.action_queue_cost(game_state):
actions[unit_id] = [unit.move(direction, repeat=0)]
# else if we have enough ice, we go back to the factory and dump it.
elif unit.cargo.ice >= 40:
direction = direction_to(unit.pos, closest_factory_tile)
if adjacent_to_factory:
if unit.power >= unit.action_queue_cost(game_state):
actions[unit_id] = [unit.transfer(direction, 0, unit.cargo.ice, repeat=0)]
else:
move_cost = unit.move_cost(game_state, direction)
if move_cost is not None and unit.power >= move_cost + unit.action_queue_cost(game_state):
actions[unit_id] = [unit.move(direction, repeat=0)]
return actions