Save game.
[naja.git] / naja / tests / test_gameboard.py
1 from unittest import TestCase
2
3 from naja.constants import BITS, MOVES
4 from naja.gameboard import GameBoard, LocationCard
5 from naja import actions
6
7
8 class TestGameBoard(TestCase):
9     def assert_state(self, state1, state2, exclude=(), player_exclude=()):
10         def filter_dict(source, exclude_keys):
11             return dict((k, v) for k, v in source.items()
12                         if k not in exclude_keys)
13
14         state1 = filter_dict(state1, exclude)
15         if 'player' in state1:
16             state1['player'] = filter_dict(state1['player'], player_exclude)
17         state2 = filter_dict(state2, exclude)
18         if 'player' in state2:
19             state2['player'] = filter_dict(state2['player'], player_exclude)
20
21         self.assertEqual(state1, state2)
22
23     def test_export_new_board(self):
24         board = GameBoard.new_game([{'actions': [
25             {
26                 'action_class': 'LoseHealthOrMSB',
27                 'required_bits': [],
28             }, {
29                 'action_class': 'GainHealth',
30                 'required_bits': [BITS.RED],
31             },
32         ]}])
33         exported_state = board.export()
34         board_locations = exported_state.pop('board_locations')
35         self.assertEqual(exported_state, {
36             'max_health': 4,
37             'health': 4,
38             'wins_required': 4,
39             'wins': 0,
40             'locations': [{'actions': [
41                 {
42                     'action_class': 'LoseHealthOrMSB',
43                     'required_bits': [],
44                 }, {
45                     'action_class': 'GainHealth',
46                     'required_bits': [BITS.RED],
47                 },
48             ]}],
49             'player': board.player.export(),
50         })
51         positions = []
52         for position, location_state in board_locations:
53             positions.append(position)
54             self.assertEqual(
55                 sorted(location_state.keys()), ['actions', 'bitwise_operand'])
56             self.assertEqual(location_state['actions'], [
57                 {
58                     'action_class': 'LoseHealthOrMSB',
59                     'required_bits': [],
60                     'data': {},
61                 }, {
62                     'action_class': 'GainHealth',
63                     'required_bits': [BITS.RED],
64                     'data': {},
65                 },
66             ])
67             self.assertTrue(2 <= len(location_state['bitwise_operand']) <= 3)
68         self.assertEqual(
69             positions, sorted((x, y) for x in range(5) for y in range(5)))
70
71     def test_lose_health(self):
72         board = GameBoard.new_game([{'actions': []}])
73         self.assertEqual(board.health, 4)
74         state_1 = board.export()
75
76         board.lose_health()
77         self.assertEqual(board.health, 3)
78         state_2 = board.export()
79
80         self.assert_state(state_1, state_2, exclude=['health'])
81
82     def test_gain_health(self):
83         board = GameBoard.new_game([{'actions': []}])
84         board.health = 2
85         self.assertEqual(board.health, 2)
86         state_1 = board.export()
87
88         board.gain_health()
89         self.assertEqual(board.health, 3)
90         state_2 = board.export()
91
92         self.assert_state(state_1, state_2, exclude=['health'])
93
94     def test_gain_health_at_max(self):
95         board = GameBoard.new_game([{'actions': []}])
96         self.assertEqual(board.health, 4)
97         state_1 = board.export()
98
99         board.gain_health()
100         self.assertEqual(board.health, 4)
101         state_2 = board.export()
102
103         self.assert_state(state_1, state_2)
104
105     def generate_locations(self, override_dict=None):
106         locations_dict = dict(((x, y), '%s%s' % (x, y))
107                               for x in range(5) for y in range(5))
108         if override_dict:
109             locations_dict.update(override_dict)
110         return locations_dict
111
112     def test_shift_locations_north(self):
113         board = GameBoard.new_game([{'actions': []}])
114         board.board_locations = self.generate_locations()
115         board.shift_locations('NORTH')
116         self.assertEqual(board.board_locations, self.generate_locations({
117             (2, 0): '21', (2, 1): '23', (2, 3): '24', (2, 4): '20',
118         }))
119
120     def test_shift_locations_south(self):
121         board = GameBoard.new_game([{'actions': []}])
122         board.board_locations = self.generate_locations()
123         board.shift_locations('SOUTH')
124         self.assertEqual(board.board_locations, self.generate_locations({
125             (2, 0): '24', (2, 1): '20', (2, 3): '21', (2, 4): '23',
126         }))
127
128     def test_shift_locations_east(self):
129         board = GameBoard.new_game([{'actions': []}])
130         board.board_locations = self.generate_locations()
131         board.shift_locations('EAST')
132         self.assertEqual(board.board_locations, self.generate_locations({
133             (0, 2): '42', (1, 2): '02', (3, 2): '12', (4, 2): '32',
134         }))
135
136     def test_shift_locations_west(self):
137         board = GameBoard.new_game([{'actions': []}])
138         board.board_locations = self.generate_locations()
139         board.shift_locations('WEST')
140         self.assertEqual(board.board_locations, self.generate_locations({
141             (0, 2): '12', (1, 2): '32', (3, 2): '42', (4, 2): '02',
142         }))
143
144     def test_rotate_locations_clockwise(self):
145         board = GameBoard.new_game([{'actions': []}])
146         board.board_locations = self.generate_locations()
147         board.rotate_locations('CLOCKWISE')
148         self.assertEqual(board.board_locations, self.generate_locations({
149             (1, 1): '21', (2, 1): '31', (3, 1): '32',
150             (1, 2): '11',               (3, 2): '33',
151             (1, 3): '12', (2, 3): '13', (3, 3): '23',
152         }))
153
154     def test_rotate_locations_clockwise_top(self):
155         board = GameBoard.new_game([{'actions': []}], initial_pos=(2, 0))
156         board.board_locations = self.generate_locations()
157         board.rotate_locations('CLOCKWISE')
158         self.assertEqual(board.board_locations, self.generate_locations({
159             (1, 0): '30',               (3, 0): '31',
160             (1, 1): '10', (2, 1): '11', (3, 1): '21',
161         }))
162
163     def test_rotate_locations_clockwise_right(self):
164         board = GameBoard.new_game([{'actions': []}], initial_pos=(0, 2))
165         board.board_locations = self.generate_locations()
166         board.rotate_locations('CLOCKWISE')
167         self.assertEqual(board.board_locations, self.generate_locations({
168             (0, 1): '11', (1, 1): '12',
169                           (1, 2): '13',
170             (0, 3): '01', (1, 3): '03',
171         }))
172
173     def test_rotate_locations_clockwise_corner(self):
174         board = GameBoard.new_game([{'actions': []}], initial_pos=(0, 4))
175         board.board_locations = self.generate_locations()
176         board.rotate_locations('CLOCKWISE')
177         self.assertEqual(board.board_locations, self.generate_locations({
178             (0, 3): '13', (1, 3): '14',
179                           (1, 4): '03',
180         }))
181
182     def test_rotate_locations_anticlockwise(self):
183         board = GameBoard.new_game([{'actions': []}])
184         board.board_locations = self.generate_locations()
185         board.rotate_locations('ANTICLOCKWISE')
186         self.assertEqual(board.board_locations, self.generate_locations({
187             (1, 1): '12', (2, 1): '11', (3, 1): '21',
188             (1, 2): '13',               (3, 2): '31',
189             (1, 3): '23', (2, 3): '33', (3, 3): '32',
190         }))
191
192     def test_allow_chess_move_knight(self):
193         board = GameBoard.new_game([{'actions': []}])
194         board.allow_chess_move(MOVES.KNIGHT)
195         self.assertEqual(board.player.movement_mode, MOVES.KNIGHT)
196
197     def test_allow_chess_move_bishop(self):
198         board = GameBoard.new_game([{'actions': []}])
199         board.allow_chess_move(MOVES.BISHOP)
200         self.assertEqual(board.player.movement_mode, MOVES.BISHOP)
201
202     def test_allow_chess_move_castle(self):
203         board = GameBoard.new_game([{'actions': []}])
204         board.allow_chess_move(MOVES.CASTLE)
205         self.assertEqual(board.player.movement_mode, MOVES.CASTLE)
206
207
208 class TestLocationCard(TestCase):
209     def test_generate_bitwise_operand(self):
210         # This is testing a random process, so it may fail occasionally.
211         operand_sets = []
212         for _ in range(100):
213             operand_sets.append(LocationCard.generate_bitwise_operand())
214         sizes = {2: 0, 3: 0}
215         bits = set()
216         for operand_set in operand_sets:
217             sizes[len(operand_set)] += 1
218             bits.update(operand_set)
219             # TODO: Test that there's at least one condition and one direction.
220         self.assertTrue(sizes[2] > 0)
221         self.assertTrue(sizes[3] > 0)
222         self.assertTrue(sizes[2] > sizes[3])
223         self.assertEqual(bits, set(BITS.values()))
224
225     def test_new_location_no_actions(self):
226         location = LocationCard.new_location({'actions': []})
227         [action] = location.actions
228         self.assertEqual(type(action), actions.DoNothing)
229         self.assertEqual(action.required_bits, set())
230
231     def test_new_location_one_action(self):
232         location = LocationCard.new_location({'actions': [
233             {'required_bits': [], 'action_class': 'DoNothing'},
234         ]})
235         [action] = location.actions
236         self.assertEqual(type(action), actions.DoNothing)
237         self.assertEqual(action.required_bits, set())
238
239     def test_parse_bits(self):
240         self.assertEqual(
241             LocationCard.parse_bits([]), frozenset([]))
242         self.assertEqual(
243             LocationCard.parse_bits(['RED']), frozenset([BITS.RED]))
244         self.assertEqual(
245             LocationCard.parse_bits([BITS.BLUE]), frozenset([BITS.BLUE]))
246         self.assertEqual(
247             LocationCard.parse_bits([BITS.NORTH, 'MSB']),
248             frozenset([BITS.NORTH, BITS.MSB]))