summaryrefslogtreecommitdiff
path: root/napoleon.py
diff options
context:
space:
mode:
Diffstat (limited to 'napoleon.py')
-rw-r--r--napoleon.py146
1 files changed, 0 insertions, 146 deletions
diff --git a/napoleon.py b/napoleon.py
deleted file mode 100644
index 15685eb..0000000
--- a/napoleon.py
+++ /dev/null
@@ -1,146 +0,0 @@
-# Strategiser
-# Goals
-
-from collections import defaultdict
-from functools import lru_cache
-from random import choice
-
-import robots
-
-from robots.algorithms import distance_relaxer
-from robots.constants import City
-
-def get_close_spawns(whoami, state, threshold):
- distances = []
- for y, row in enumerate(state.cities):
- distances.append([])
- for x, cell in enumerate(row):
- if cell not in City.traversable:
- d = None
- elif (
- cell == City.FACTORY and
- state.allegiances.get((x, y)) != whoami
- ):
- d = 0
- else:
- d = float('inf')
- distances[-1].append(d)
-
- predecessors = distance_relaxer(distances, threshold)
- return predecessors, distances
-
-@lru_cache(maxsize=16)
-def closest_unpainted(whoami, state):
- distances = []
- for y, row in enumerate(state.cities):
- distances.append([])
- for x, cell in enumerate(row):
- if cell == City.GHOST:
- d = None
- elif state.allegiances.get((x, y)) != whoami:
- d = 0
- else:
- d = float('inf')
- distances[-1].append(d)
-
- return distance_relaxer(distances)
-
-def good_moves(state, x, y, moves):
- return [
- move
- for move in moves
- if not state.robots[state.expected_position(x, y, move)]
- ]
-
-class Napoleon:
- def __init__(self, capturers_frac=1, dampening=0.01):
- # (x, y) -> (goal, goal_state)
- self.bot_goals = {}
- self.capturers_frac = capturers_frac
- self.dampening = dampening
-
- def goal_capture(self, whoami, state, x, y, goal_state):
- moves = goal_state
- good = good_moves(state, x, y, moves)
- if good:
- return choice(good)
- return choice(moves or 'P')
-
- def goal_paint(self, whoami, state, x, y, goal_state):
- predecessors = closest_unpainted(whoami, state)
- moves = predecessors[y][x]
- good = good_moves(state, x, y, moves)
- if good:
- return choice(good)
- return choice(moves or 'P')
-
- def strategise(self, whoami, state):
- bot_goals = {}
-
- robots = state.robots_by_player[whoami]
-
- if len(state.factories_by_player[whoami]) <= 3:
- self.capturers_frac = 1.0
- if len(robots) <= 10:
- self.capturers_frac = 1.0
-
-# threshold = 10 if early_stages else None
- threshold = None
- spawns, spawns_dist = get_close_spawns(whoami, state, threshold)
-
- max_capturers = max(3, int(len(robots) * self.capturers_frac))
- self.capturers_frac = max(0.01, self.capturers_frac - self.dampening)
- capturers = {
- (x, y)
- for x, y, _ in sorted(
- robots,
- key=lambda r: spawns_dist[r[1]][r[0]],
- )[:max_capturers]
- if threshold is None or spawns_dist[y][x] <= threshold
- }
- assert len(capturers) <= max_capturers
-
- for x, y, energy in robots:
- if (x, y) in capturers:
- goal = 'capture'
- goal_state = spawns[y][x]
- else:
- goal = 'paint'
- goal_state = None
-
- bot_goals[x, y] = (goal, goal_state)
-
-# print(whoami, ''.join(v[0].upper() for v, _ in bot_goals.values()))
- return bot_goals
-
- def __call__(self, whoami, state):
- self.bot_goals = self.strategise(whoami, state)
-
- results = {}
-
- todo = self.bot_goals.keys()
-
- for _ in range(2):
- by_dest = defaultdict(list)
-
- for x, y in todo:
- goal, goal_state = self.bot_goals[x, y]
- goal_fn = getattr(self, 'goal_' + goal)
- action = goal_fn(whoami, state, x, y, goal_state)
- by_dest[state.expected_position(x, y, action)].append((x, y))
- results[x, y] = action
-
- todo = []
- for robots in by_dest.values():
- if len(robots) > 1:
- todo.extend(robots)
-
- return ''.join(
- results[x, y]
- for x, y, _ in state.robots_by_player[whoami]
- )
-
-if __name__ == '__main__':
- server = robots.Server()
- server.add_bot(Napoleon, 'Napoleon')
- server.run()