summaryrefslogtreecommitdiff
path: root/robots/state.py
diff options
context:
space:
mode:
authorPeter Ward <peteraward@gmail.com>2014-04-06 21:41:27 +1000
committerPeter Ward <peteraward@gmail.com>2014-04-06 21:41:27 +1000
commit2fe31caf455648f3bb8603d804a4a873244acec6 (patch)
tree480392d67e11c394e4e21676df49893fc1fe0b8a /robots/state.py
parentaa86046a411409a41c95493e9913759146515613 (diff)
Ripping out functionality to meet new spec.
Diffstat (limited to 'robots/state.py')
-rw-r--r--robots/state.py105
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)