-from naja.constants import BITS
+from naja.constants import BITS, MOVES
class PlayerBits(object):
# Operate on individual bits
def check_bit(self, bit):
- return bool(self.bits & bit)
+ return bool(self.bits & (1 << bit))
def set_bit(self, bit):
- self.bits |= bit
+ self.bits |= (1 << bit)
def clear_bit(self, bit):
- self.bits &= (0xff ^ bit)
+ self.bits &= (0xff ^ (1 << bit))
def toggle_bit(self, bit):
- self.bits ^= bit
+ self.bits ^= (1 << bit)
# Operate on sets of bits
for bit in bits:
self.toggle_bit(bit)
+ def shift_bits_left(self, shift):
+ wrap = self.bits >> (8 - shift)
+ self.bits = (self.bits << shift & 0xff | wrap)
+
+ def shift_bits_right(self, shift):
+ wrap = self.bits << (8 - shift) & 0xff
+ self.bits = (self.bits >> shift | wrap)
+
class Player(object):
"""
A representation of the player.
"""
- def __init__(self, bits, position):
+ 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):
- return cls(definition['bits'], tuple(definition['position']))
+ def import_player(cls, definition, gameboard=None):
+ return cls(
+ definition['bits'],
+ tuple(definition['position']),
+ definition['movement_mode'],
+ gameboard=gameboard)
def export(self):
return {
'bits': self.bits.bits,
'position': list(self.position),
+ 'movement_mode': self.movement_mode,
}
- def move(self, direction):
- if not self.bits.check_bit(direction):
- return False
- # TODO: Something cleaner than this.
+ def get_adjacent_positions(self):
+ positions = [self.position]
+
x, y = self.position
- if direction == BITS.NORTH:
- if y > 0 and self.bits.check_bit(BITS.NORTH):
- self.position = (x, y - 1)
- return True
- elif direction == BITS.SOUTH:
- if y < 4 and self.bits.check_bit(BITS.SOUTH):
- self.position = (x, y + 1)
- return True
- elif direction == BITS.EAST:
- if x < 4 and self.bits.check_bit(BITS.EAST):
- self.position = (x + 1, y)
- return True
- elif direction == BITS.WEST:
- if x > 0 and self.bits.check_bit(BITS.WEST):
- self.position = (x - 1, y)
- return True
+ 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 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,
+ MOVES.KNIGHT: self.get_knight_positions,
+ MOVES.BISHOP: self.get_bishop_positions,
+ MOVES.CASTLE: self.get_castle_positions,
+ }
+ positions = POSITION_FUNCTION[self.movement_mode]()
+ return self.filter_moves_with_no_actions(positions)
+
+ def allow_chess_move(self, chesspiece):
+ self.movement_mode = chesspiece