All puzzles to have cards without default actions.
authorSimon Cross <hodgestar@gmail.com>
Sat, 17 May 2014 17:00:18 +0000 (19:00 +0200)
committerSimon Cross <hodgestar@gmail.com>
Sat, 17 May 2014 17:01:43 +0000 (19:01 +0200)
naja/gameboard.py
naja/player.py
naja/tests/test_gameboard.py
naja/tests/test_player.py
naja/widgets/info_area.py
naja/widgets/tile.py

index 2ed511afeb81eab12875286c3506899ecb49ec9b..d70a49890f99fc4a183aed48813ca6b7d53b8378 100644 (file)
@@ -77,7 +77,9 @@ class GameBoard(object):
         player = Player(initial_bits, initial_pos)
         board_locations = cls.import_board_locations(
             cls.generate_board(deck))
-        return cls(state, player, board_locations)
+        board = cls(state, player, board_locations)
+        player.set_gameboard(board)
+        return board
 
     @classmethod
     def import_game(cls, definition):
@@ -138,7 +140,7 @@ class GameBoard(object):
         board_locations = [
             [(i % 5, i // 5),
              LocationCard.new_location(
-                 card.copy(), replacement_params).export()]
+                 card.copy(), replacement_params, puzzle=True).export()]
             for i, card in enumerate(deck['cards'])
         ]
         return board_locations
@@ -297,12 +299,11 @@ class LocationCard(object):
     """
 
     def __init__(self, card_name, bitwise_operand, location_actions,
-                 replacement_time, max_number=25):
+                 replacement_time=None, max_number=25):
         self.card_name = card_name
         self.bitwise_operand = bitwise_operand
         self.actions = location_actions
         self.max_number = max_number
-        self.check_actions()
         self.replacement_time = replacement_time
 
     @classmethod
@@ -321,7 +322,7 @@ class LocationCard(object):
         return action_class(required_bits, **data)
 
     @classmethod
-    def new_location(cls, definition, replacement_params):
+    def new_location(cls, definition, replacement_params=None, puzzle=False):
         if 'bits' in definition:
             bits = cls.parse_bits(definition['bits'])
         else:
@@ -335,13 +336,16 @@ class LocationCard(object):
 
         max_number = definition.get('max_number', 25)
         card_name = definition['card_name']
-        return cls.import_location({
+        location = cls.import_location({
             'bitwise_operand': bits,
             'actions': definition['actions'],
             'max_number': max_number,
             'card_name': card_name,
             'replacement_time': replacement_time,
         })
+        if not puzzle:
+            location.check_actions()
+        return location
 
     @classmethod
     def parse_bits(self, bit_list):
index fc95a8fa55f66990d2116782d2e836c3af1429cf..892fa05b32f88c117a59f98d6025a7b0821a5469 100644 (file)
@@ -63,10 +63,11 @@ class Player(object):
     A representation of the player.
     """
 
-    def __init__(self, bits, position, movement_mode=None):
+    def __init__(self, bits, position, movement_mode=None, gameboard=None):
         self.bits = PlayerBits(bits)
         self.position = position
         self.movement_mode = movement_mode if movement_mode else MOVES.ADJACENT
+        self.gameboard = gameboard
 
     @classmethod
     def import_player(cls, definition):
@@ -149,6 +150,19 @@ class Player(object):
             return True
         return False
 
+    def set_gameboard(self, gameboard):
+        self.gameboard = gameboard
+
+    def pos_has_action(self, pos):
+        card = self.gameboard.board_locations[pos]
+        for action in card.actions:
+            if self.bits.check_bits(action.required_bits):
+                return True
+        return False
+
+    def filter_moves_with_no_actions(self, positions):
+        return [pos for pos in positions if self.pos_has_action(pos)]
+
     def legal_moves(self):
         POSITION_FUNCTION = {
             MOVES.ADJACENT: self.get_adjacent_positions,
@@ -156,7 +170,8 @@ class Player(object):
             MOVES.BISHOP: self.get_bishop_positions,
             MOVES.CASTLE: self.get_castle_positions,
         }
-        return POSITION_FUNCTION[self.movement_mode]()
+        positions = POSITION_FUNCTION[self.movement_mode]()
+        return self.filter_moves_with_no_actions(positions)
 
     def allow_chess_move(self, chesspiece):
         self.movement_mode = chesspiece
index f8672b45d149aad1bd8a719f1d8f2d61229808c7..4675968fd50e375c1f58a1be072399429213acae 100644 (file)
@@ -43,6 +43,7 @@ class TestGameBoard(TestCase):
         exported_state = board.export()
         board_locations = exported_state.pop('board_locations')
         self.assertEqual(exported_state, {
+            'clock_count': 0,
             'max_health': 4,
             'health': 4,
             'wins_required': 4,
@@ -60,7 +61,6 @@ class TestGameBoard(TestCase):
             'puzzle': False,
             'player_mode': EXAMINE,
             'replacement_params': None,
-            'clock_count': 0,
         })
         positions = []
         for position, location_state in board_locations:
index 07583b3bf11a312bdefed1c267f623b069b42c18..b1457c8876d3ad28c85fe118b861e01840f2a9aa 100644 (file)
@@ -2,6 +2,7 @@ from unittest import TestCase
 
 from naja.constants import BITS, MOVES
 from naja.player import PlayerBits, Player
+from naja.gameboard import GameBoard
 
 
 class TestPlayerBits(TestCase):
@@ -103,8 +104,22 @@ class TestPlayerBits(TestCase):
 
 
 class TestPlayer(TestCase):
+
+    def setUp(self):
+        self.board = GameBoard.new_game({'cards': [
+            {'card_name': 'card1', 'actions': [
+                {
+                    'action_class': 'LoseHealthOrMSB',
+                    'required_bits': [],
+                }, {
+                    'action_class': 'GainHealth',
+                    'required_bits': [BITS.RED],
+                },
+            ]}
+        ]})
+
     def test_new_player(self):
-        player = Player(0x0f, (0, 1))
+        player = Player(0x0f, (0, 1), self.board)
         self.assertEqual(player.bits.bits, 0x0f)
         self.assertEqual(player.position, (0, 1))
 
@@ -135,32 +150,32 @@ class TestPlayer(TestCase):
         })
 
     def test_legal_moves_all_available(self):
-        player = Player(0x0f, (2, 2))
+        player = Player(0x0f, (2, 2), gameboard=self.board)
         self.assertEqual(
             player.legal_moves(), [(2, 2), (2, 1), (2, 3), (3, 2), (1, 2)])
 
     def test_legal_moves_some_unavailable(self):
-        player = Player(0x0f, (0, 2))
+        player = Player(0x0f, (0, 2), gameboard=self.board)
         player.bits.clear_bit(BITS.NORTH)
         self.assertEqual(player.legal_moves(), [(0, 2), (0, 3), (1, 2)])
 
     def test_legal_moves_castle(self):
-        player = Player(0x0f, (1, 3), MOVES.CASTLE)
+        player = Player(0x0f, (1, 3), MOVES.CASTLE, gameboard=self.board)
         self.assertEqual(player.legal_moves(), [
             (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 3), (3, 3),
             (4, 3)])
 
     def test_legal_moves_bishop(self):
-        player = Player(0x0f, (1, 3), MOVES.BISHOP)
+        player = Player(0x0f, (1, 3), MOVES.BISHOP, gameboard=self.board)
         self.assertEqual(player.legal_moves(), [
             (0, 2), (0, 4), (1, 3), (2, 2), (2, 4), (3, 1), (4, 0)])
 
     def test_legal_moves_knight(self):
-        player = Player(0x0f, (1, 3), MOVES.KNIGHT)
+        player = Player(0x0f, (1, 3), MOVES.KNIGHT, gameboard=self.board)
         self.assertEqual(player.legal_moves(), [
             (0, 1), (1, 3), (2, 1), (3, 2), (3, 4)])
 
     def test_set_position(self):
-        player = Player(0x0f, (3, 3), MOVES.BISHOP)
+        player = Player(0x0f, (3, 3), MOVES.BISHOP, gameboard=self.board)
         player.set_position((4, 4))
         self.assertEqual(player.movement_mode, MOVES.ADJACENT)
index e5ee88c9e875160a4eed586c0e3610d0e5ce0aa3..7dbef1b70c226402303d15e3d4fdb553a029c066 100644 (file)
@@ -138,7 +138,7 @@ class InfoAreaWidget(Widget):
                               [(x_offset, y_offset), (right, y_offset),
                                (right, bottom), (x_offset, bottom)], 4)
 
-        if action.required_bits:
+        if action.required_bits in BIT_MAP:
             img_name = BIT_MAP[action.required_bits].replace(
                 '.png', '_small.png')
             img = resources.get_image(img_name,
index 8ccb99db2671c5efdde8f0ba1de4dd7926cfdbb7..cf6f04c92d4ef498163dc1f694ff6255fca46af7 100644 (file)
@@ -94,7 +94,7 @@ class TileWidget(Widget):
         self.surface.blit(img, (TILE_SIZE[0] - 20, 0))
 
     def _prepare_lock(self, action, y_offset):
-        if not action.required_bits:
+        if action.required_bits not in BIT_MAP:
             return 4
 
         img_name = BIT_MAP[action.required_bits]