diff options
author | Peter Ward <peteraward@gmail.com> | 2014-04-06 21:41:27 +1000 |
---|---|---|
committer | Peter Ward <peteraward@gmail.com> | 2014-04-06 21:41:27 +1000 |
commit | 2fe31caf455648f3bb8603d804a4a873244acec6 (patch) | |
tree | 480392d67e11c394e4e21676df49893fc1fe0b8a /robots/state.py | |
parent | aa86046a411409a41c95493e9913759146515613 (diff) |
Ripping out functionality to meet new spec.
Diffstat (limited to 'robots/state.py')
-rw-r--r-- | robots/state.py | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/robots/state.py b/robots/state.py new file mode 100644 index 0000000..1fe9c26 --- /dev/null +++ b/robots/state.py @@ -0,0 +1,105 @@ +from collections import defaultdict, Counter + +from robots.constants import City +from robots.utils import ceil_div + +class GameState: + """The state of a game at a point in time. + + Instances can be serialized for inter-process communication. + """ + + def __init__(self, board): + # _[y][x] = City + self.cities = board + # _[x, y] = str (player id) + self.allegiances = {} + # _[player_id] = [(x, y, energy), ...] + self.robots_by_player = {} + + def __hash__(self): + return hash(self._authorative_state) + + def __eq__(self, other): + if isinstance(other, GameState): + return self._authorative_state == other._authorative_state + + @property + def _authorative_state(self): + return (self.cities, self.allegiances, self.robots_by_player) + + @property + def players(self): + return self.robots_by_player.keys() + + @property + def robots(self): + result = defaultdict(list) + for player, robots in self.robots_by_player.items(): + for x, y, energy in robots: + result[x, y].append((player, energy)) + return result + + @property + def allegiances_by_player(self): + result = defaultdict(list) + for (x, y), player in self.allegiances.items(): + result[player].append((x, y)) + return result + + @property + def board(self): + # TODO: remove this once I've figured out caching. + self_robots = self.robots + + result = [] + for y, row in enumerate(self.cities): + result_row = [] + for x, city in enumerate(row): + allegiance = self.allegiances.get((x, y)) + robots = self_robots[x, y] + + result_row.append({ + 'city': city, + 'allegiance': allegiance, + 'robots': robots, + }) + result.append(result_row) + return result + + @property + def width(self): + return len(self.cities[0]) + + @property + def height(self): + return len(self.cities) + + @property + def n_alive_players(self): + """How many players are still alive.""" + return sum( + 1 + for player, robots in self.robots_by_player.items() + if robots + ) + + @property + def n_allegiable_cities(self): + """How many cities are capable of pledging allegiance.""" + return sum( + 1 + for row in self.cities + for city in row + if city in City.allegiable + ) + + @property + def n_allegiances_by_player(self): + """How many cities have pledged allegiance to each player.""" + return Counter(self.allegiances.values()) + + @property + def n_cities_to_win(self): + """How many cities you need to pledge allegiance to you to win.""" + return ceil_div(self.n_allegiable_cities, self.n_alive_players) |