merge
[naja.git] / naja / gameboard.py
1 from random import choice
2
3 from naja.constants import BITS, DIRECTION_BITS, CONDITION_BITS
4
5
6 class GameBoard(object):
7     """
8     A representation of the game board.
9     """
10
11     def __init__(self, player, health, wins, state=None):
12         self.player = player
13
14         if state is None:
15             state = self.generate_state(health, wins)
16         self.update_state(state)
17
18     def export(self):
19         return {
20             'max_health': self.max_health,
21             'health': self.health,
22             'wins_required': self.wins_required,
23             'wins': self.wins,
24             'locations': self.export_locations(),
25         }
26
27     def export_locations(self):
28         return dict(
29             (position, location.export())
30             for position, location in self.locations)
31
32     @classmethod
33     def generate_locations(cls):
34         # TODO: Generate some locations.
35         return {}
36
37     def generate_state(self, max_health, wins_required):
38         return {
39             'max_health': max_health,
40             'health': max_health,
41             'wins_required': wins_required,
42             'wins': 0,
43             'locations': self.generate_locations(),
44         }
45
46     def update_state(self, state):
47         self.max_health = state['max_health']
48         self.wins_required = state['wins_required']
49         self.health = state['health']
50         self.wins = state['wins']
51         self.locations = self.import_locations(state['locations'])
52
53     def import_locations(self, locations):
54         return dict(
55             (position, LocationCard.import_location(definition))
56             for position, definition in locations.iteritems())
57
58     def lose_health(self):
59         self.health -= 1
60         # TODO: Check win/lose
61
62
63 class LocationCard(object):
64     """
65     A particular set of options available on a location.
66     """
67
68     def __init__(self, bitwise_operand, actions):
69         self.bitwise_operand = bitwise_operand
70         self.actions = actions
71
72     @classmethod
73     def import_location(cls, state):
74         # TODO: Import real locations.
75         return cls(state['bitwise_operand'], [])
76
77     @classmethod
78     def new_location(cls, definition):
79         return cls.import_location({
80             'bitwise_operand': cls.generate_bitwise_operand(),
81             'actions': cls.build_actions(definition),
82         })
83
84     def export(self):
85         return {
86             'bitwise_operand': self.bitwise_operand,
87             'actions': [action.export() for action in self.actions],
88         }
89
90     @classmethod
91     def build_actions(cls, definition):
92         raise NotImplementedError("TODO")
93
94     @staticmethod
95     def generate_bitwise_operand():
96         """
97         Generate a set of two or three bits. At least one direction and one
98         condition bit will be included. There is a low probability of choosing
99         a third bit from the complete set.
100         """
101         bits = set()
102         bits.add(choice(DIRECTION_BITS.values()))
103         bits.add(choice(CONDITION_BITS.values()))
104         # One in three chance of adding a third bit, with a further one in four
105         # chance that it will match a bit already chosen.
106         if choice(range(3)) == 0:
107             bits.add(choice(BITS.values()))
108         return frozenset(bits)