-from naja.constants import BITS
+from naja.constants import BITS, MOVES, CHESS_PIECES
class PlayerBits(object):
A representation of the player.
"""
- def __init__(self, bits, position):
+ def __init__(self, bits, position, movement_mode=None):
self.bits = PlayerBits(bits)
self.position = position
+ self.movement_mode = movement_mode if movement_mode else MOVES.ADJACENT
@classmethod
def import_player(cls, definition):
- return cls(definition['bits'], tuple(definition['position']))
+ return cls(definition['bits'], tuple(definition['position']), definition['movement_mode'])
def export(self):
return {
'bits': self.bits.bits,
'position': list(self.position),
+ 'movement_mode': self.movement_mode,
}
- def get_adjacent_position(self, direction):
+ def get_adjacent_positions(self):
+ positions = [self.position]
+
x, y = self.position
- if direction == BITS.NORTH and y > 0:
- return (x, y - 1)
- elif direction == BITS.SOUTH and y < 4:
- return (x, y + 1)
- elif direction == BITS.EAST and x < 4:
- return (x + 1, y)
- elif direction == BITS.WEST and x > 0:
- return (x - 1, y)
- else:
- # Not a legal space.
- return None
-
- def move(self, direction):
- if not self.bits.check_bit(direction):
- return False
- new_position = self.get_adjacent_position(direction)
- if new_position is not None:
- self.position = new_position
- return True
- return False
+
+ if self.bits.check_bit(BITS.NORTH) and y > 0:
+ positions.append((x, y - 1))
+ if self.bits.check_bit(BITS.SOUTH) and y < 4:
+ positions.append((x, y + 1))
+ if self.bits.check_bit(BITS.EAST) and x < 4:
+ positions.append((x + 1, y))
+ if self.bits.check_bit(BITS.WEST) and x > 0:
+ positions.append((x - 1, y))
+
+ return positions
+
+ def get_knight_positions(self):
+ positions = set([self.position])
+
+ x, y = self.position
+
+ for a in (2, -2):
+ for b in (1, -1):
+ i, j = x + a, y + b
+ if 0 <= i < 5 and 0 <= j < 5:
+ positions.add((i, j))
+
+ i, j = x + b, y + a
+ if 0 <= i < 5 and 0 <= j < 5:
+ positions.add((i, j))
+
+ return sorted(list(positions))
+
+ def get_bishop_positions(self):
+ positions = set()
+
+ x, y = self.position
+
+ for i in range(5):
+ j = i + y - x
+ if 0 <= j < 5:
+ positions.add((i, j))
+
+ j = x + y - i
+ if 0 <= j < 5:
+ positions.add((i, j))
+
+ return sorted(list(positions))
+
+ def get_castle_positions(self):
+ positions = set()
+
+ x, y = self.position
+
+ for i in range(5):
+ positions.add((x, i))
+ positions.add((i, y))
+
+ return sorted(list(positions))
def set_position(self, new_position):
if new_position in self.legal_moves():
self.position = new_position
+ self.movement_mode = MOVES.ADJACENT
return True
return False
def legal_moves(self):
- positions = [self.position]
- for direction in [BITS.NORTH, BITS.SOUTH, BITS.EAST, BITS.WEST]:
- position = self.get_adjacent_position(direction)
- if position is not None and self.bits.check_bit(direction):
- positions.append(position)
- return positions
+ POSITION_FUNCTION = {
+ MOVES.ADJACENT: self.get_adjacent_positions,
+ MOVES.KNIGHT: self.get_knight_positions,
+ MOVES.BISHOP: self.get_bishop_positions,
+ MOVES.CASTLE: self.get_castle_positions,
+ }
+ return POSITION_FUNCTION[self.movement_mode]()
+
+ def allow_chess_move(self, chesspiece):
+ self.movement_mode = chesspiece
player = Player.import_player({
'bits': 0xaa,
'position': [1, 2],
+ 'movement_mode': MOVES.CASTLE,
})
self.assertEqual(player.bits.bits, 0xaa)
self.assertEqual(player.position, (1, 2))
+ self.assertEqual(player.movement_mode, MOVES.CASTLE)
def test_export_player(self):
- player = Player(0xaa, (1, 2))
+ player = Player(0xaa, (1, 2), MOVES.CASTLE)
self.assertEqual(player.export(), {
'bits': 0xaa,
'position': [1, 2],
+ 'movement_mode': MOVES.CASTLE,
})
- def test_move(self):
- player = Player(0x0f, (2, 2))
- self.assertEqual(player.move(BITS.NORTH), True)
- self.assertEqual(player.position, (2, 1))
-
- player = Player(0x0f, (2, 2))
- self.assertEqual(player.move(BITS.SOUTH), True)
- self.assertEqual(player.position, (2, 3))
-
- player = Player(0x0f, (2, 2))
- self.assertEqual(player.move(BITS.WEST), True)
- self.assertEqual(player.position, (1, 2))
-
- player = Player(0x0f, (2, 2))
- self.assertEqual(player.move(BITS.EAST), True)
- self.assertEqual(player.position, (3, 2))
-
- def test_move_flags_clear(self):
- player = Player(0x00, (2, 2))
- self.assertEqual(player.move(BITS.NORTH), False)
- self.assertEqual(player.position, (2, 2))
-
- player = Player(0x00, (2, 2))
- self.assertEqual(player.move(BITS.SOUTH), False)
- self.assertEqual(player.position, (2, 2))
-
- player = Player(0x00, (2, 2))
- self.assertEqual(player.move(BITS.WEST), False)
- self.assertEqual(player.position, (2, 2))
-
- player = Player(0x00, (2, 2))
- self.assertEqual(player.move(BITS.EAST), False)
- self.assertEqual(player.position, (2, 2))
-
- def test_move_flags_edges(self):
- player = Player(0x0f, (2, 0))
- self.assertEqual(player.move(BITS.NORTH), False)
- self.assertEqual(player.position, (2, 0))
-
- player = Player(0x0f, (2, 4))
- self.assertEqual(player.move(BITS.SOUTH), False)
- self.assertEqual(player.position, (2, 4))
-
- player = Player(0x0f, (0, 2))
- self.assertEqual(player.move(BITS.WEST), False)
- self.assertEqual(player.position, (0, 2))
-
- player = Player(0x0f, (4, 2))
- self.assertEqual(player.move(BITS.EAST), False)
- self.assertEqual(player.position, (4, 2))
+ def test_export_player_default_movement_mode(self):
+ player = Player(0xaa, (1, 2))
+ self.assertEqual(player.export(), {
+ 'bits': 0xaa,
+ 'position': [1, 2],
+ 'movement_mode': MOVES.ADJACENT,
+ })
def test_legal_moves_all_available(self):
player = Player(0x0f, (2, 2))
player = Player(0x0f, (0, 2))
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)
+ 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)
+ self.assertEqual(player.legal_moves(), [(0, 2), (0, 4), (1, 3), (2, 2),
+ (2, 4), (3, 1), (3, 4), (4, 0)])
+
+ def test_legal_moves_knight(self):
+ player = Player(0x0f, (1, 3), MOVES.KNIGHT)
+ self.assertEqual(player.legal_moves(), [(0, 1), (2, 1), (3, 2), (3, 4)])
+
+ def test_set_position(self):
+ player = Player(0x0f, (3, 3), MOVES.BISHOP)
+ player.set_position((4, 4))
+ self.assertEqual(player.movement_mode, MOVES.ADJACENT)