1 from naja.constants import BITS, MOVES
4 class PlayerBits(object):
9 def __init__(self, bits):
17 def bits(self, value):
18 assert 0 <= value <= 0xff
21 # Operate on individual bits
23 def check_bit(self, bit):
24 return bool(self.bits & (1 << bit))
26 def set_bit(self, bit):
27 self.bits |= (1 << bit)
29 def clear_bit(self, bit):
30 self.bits &= (0xff ^ (1 << bit))
32 def toggle_bit(self, bit):
33 self.bits ^= (1 << bit)
35 # Operate on sets of bits
37 def check_bits(self, bits):
38 return all(self.check_bit(bit) for bit in bits)
40 def set_bits(self, bits):
44 def clear_bits(self, bits):
48 def toggle_bits(self, bits):
52 def shift_bits_left(self, shift):
53 wrap = self.bits >> (8 - shift)
54 self.bits = (self.bits << shift & 0xff | wrap)
56 def shift_bits_right(self, shift):
57 wrap = self.bits << (8 - shift) & 0xff
58 self.bits = (self.bits >> shift | wrap)
63 A representation of the player.
66 def __init__(self, bits, position, movement_mode=None, gameboard=None):
67 self.bits = PlayerBits(bits)
68 self.position = position
69 self.movement_mode = movement_mode if movement_mode else MOVES.ADJACENT
70 self.gameboard = gameboard
73 def import_player(cls, definition, gameboard=None):
76 tuple(definition['position']),
77 definition['movement_mode'],
82 'bits': self.bits.bits,
83 'position': list(self.position),
84 'movement_mode': self.movement_mode,
87 def get_adjacent_positions(self):
88 positions = [self.position]
92 if self.bits.check_bit(BITS.NORTH) and y > 0:
93 positions.append((x, y - 1))
94 if self.bits.check_bit(BITS.SOUTH) and y < 4:
95 positions.append((x, y + 1))
96 if self.bits.check_bit(BITS.EAST) and x < 4:
97 positions.append((x + 1, y))
98 if self.bits.check_bit(BITS.WEST) and x > 0:
99 positions.append((x - 1, y))
103 def get_knight_positions(self):
104 positions = set([self.position])
111 if 0 <= i < 5 and 0 <= j < 5:
112 positions.add((i, j))
115 if 0 <= i < 5 and 0 <= j < 5:
116 positions.add((i, j))
118 return sorted(list(positions))
120 def get_bishop_positions(self):
128 positions.add((i, j))
132 positions.add((i, j))
134 return sorted(list(positions))
136 def get_castle_positions(self):
142 positions.add((x, i))
143 positions.add((i, y))
145 return sorted(list(positions))
147 def set_position(self, new_position):
148 if new_position in self.legal_moves():
149 self.position = new_position
150 self.movement_mode = MOVES.ADJACENT
154 def set_gameboard(self, gameboard):
155 self.gameboard = gameboard
157 def pos_has_action(self, pos):
158 card = self.gameboard.board_locations[pos]
159 for action in card.actions:
160 if self.bits.check_bits(action.required_bits):
164 def filter_moves_with_no_actions(self, positions):
165 return [pos for pos in positions if self.pos_has_action(pos)]
167 def legal_moves(self):
168 POSITION_FUNCTION = {
169 MOVES.ADJACENT: self.get_adjacent_positions,
170 MOVES.KNIGHT: self.get_knight_positions,
171 MOVES.BISHOP: self.get_bishop_positions,
172 MOVES.CASTLE: self.get_castle_positions,
174 positions = POSITION_FUNCTION[self.movement_mode]()
175 return self.filter_moves_with_no_actions(positions)
177 def allow_chess_move(self, chesspiece):
178 self.movement_mode = chesspiece