def test_is_valid_obstructed(self): q = pc.Queen(3, 3) p = pc.Pawn(3, 4) b = board.Board() b.pieces.extend([q, p]) self.assertTrue(move.Move(q, T(1, 1, 1)).is_valid(b)) self.assertFalse(move.Move(q, T(0, 1, 2)).is_valid(b)) self.assertFalse(move.Move(q, T(0, 1, 1)).is_valid(b))
def test_is_valid_capture(self): q = pc.Queen(3, 3) p = pc.Pawn(3, 4) r = pc.Rook(2, 3, True) b = board.Board() b.pieces.extend([q, p, r]) self.assertTrue(move.Move(q, T(1, 1, 1)).is_valid(b)) self.assertFalse(move.Move(q, T(0, 1, 1)).is_valid(b)) self.assertTrue(move.Move(q, T(-1, 0, 1)).is_valid(b))
def test_capture_value(self): q = pc.Queen(3, 3) p = pc.Pawn(3, 4) r = pc.Rook(2, 3, True) b = board.Board() b.pieces.extend([q, p, r]) m1 = move.Move(q, T(1, 1, 1)) self.assertTrue(m1.is_valid(b)) self.assertEqual(m1.value(b), 0) self.assertFalse(move.Move(q, T(0, 1, 1)).is_valid(b)) m2 = move.Move(q, T(-1, 0, 1)) self.assertTrue(m2.is_valid(b)) self.assertEqual(m2.value(b), 5)
def set_candidate(self, letters, pos, horizontal): """ Shortcut for setting the candidate move. Specify the letters (in order) to play, the position of the first letter, and the direction of the move and this method will place the letters sequentially in the correct positions, accounting properly for any existing tiles on the board that have to be skipped. @param letters: string or list of letters to play. @param pos: x,y position of the first tile of the play. @param horizontal: True if the play is horizontal, False otherwise. @return: True if function succeeds, False if any letters aren't in player's rack, there's already a candidate, the move goes out of the board, or the game is over. """ if self.game_over: return False from_rack = self.players[self.current_turn].valid_play(letters) b_height, b_width = len(self.board), len(self.board[0]) # Candidate exists already or no letters are being played if self.candidate is not None or not letters: return False # Not a valid play given current rack if not from_rack: return False # First letter placed out of bounds if pos[0] < 0 or pos[0] >= b_height or pos[1] < 0 or pos[1] >= b_width: return False self.candidate = move.Move() self.candidate.horizontal = horizontal x, y = pos j = 0 for i, letter in enumerate(from_rack): if horizontal: while self.board[x][y + j] not in board.empty_locations: j += 1 if y + j >= b_width: return False # Move goes out of the board self.candidate.add_letter(letter, (x, y + j)) else: while self.board[x + j][y] not in board.empty_locations: j += 1 if x + j >= b_height: return False # Move goes out of the board self.candidate.add_letter(letter, (x + j, y)) j += 1 # Check bounds if (horizontal and y + j >= b_width) or ( not horizontal and x + j >= b_height): # Was the last letter placed before incrementing? return i == len(from_rack) - 1 return True
def test_negative_magnitude(self): p = pc.Pawn(5, 5, True) bo = board.Board() bo._clear_board() bo.pieces.append(p) m = move.Move(p, T(0, -1, 1)) m.is_valid(bo) m.apply(bo) self.assertEqual(p.get_position()[0], 5) self.assertEqual(p.get_position()[1], 4)
def test_apply(self): b = pc.Bishop(5, 5) m = move.Move(b, T(-1, -1, 3)) bo = board.Board() self.assertTrue(bo.to_play == bo.WHITE) m.is_valid(bo) m.apply(bo) self.assertTrue(bo.to_play == bo.BLACK) self.assertEqual(b.get_position()[0], 2) self.assertEqual(b.get_position()[1], 2) self.assertTrue(bo.get_piece_at(5, 5) is None)
def test_undo(self): b = pc.Bishop(5, 5) q = pc.Queen(6, 6, True) bo = board.Board() bo._clear_board() bo.pieces.append(b) bo.pieces.append(q) m = move.Move(b, T(1, 1, 1)) m.is_valid(bo) self.assertTrue(bo.to_play == bo.WHITE) m.apply(bo) m.undo(bo) self.assertTrue(bo.to_play == bo.WHITE) self.assertEqual(b.get_position()[0], 5) self.assertEqual(b.get_position()[1], 5) self.assertEqual(bo.get_piece_at(6, 6), q)
def test_is_valid_board_limits(self): q = pc.Queen(0, 0) b = board.Board() # Remove initial board setup b.pieces = [q] self.assertTrue(move.Move(q, T(1, 1, 1)).is_valid(b)) self.assertFalse(move.Move(q, T(-1, 1, 1)).is_valid(b)) self.assertFalse(move.Move(q, T(1, -1, 1)).is_valid(b)) n = pc.Knight(6, 6) self.assertTrue(move.Move(n, T(-2, 1, 1)).is_valid(b)) self.assertFalse(move.Move(n, T(2, 1, 1)).is_valid(b)) self.assertFalse(move.Move(n, T(-1, 2, 1)).is_valid(b))
def exchange_tiles(self, letters): """ Current player exchanges up to 7 letters with the bag. If there are not enough letters in the bag to exchange, this method will not do anything. Otherwise, the letters are exchanged and the move is committed to the game tree. @param letters: Letters to exchange @return: True if everything was valid, False if any errors were encountered. """ if len(self.bag) < len( letters) or self.candidate is not None or self.game_over: return False self.candidate = move.Move() holder = [] rack = self.players[self.current_turn].rack for letter in letters: try: holder.append(rack.pop(rack.index(letter))) except ValueError: self.players[self.current_turn].rack += holder self.candidate = None return False self.candidate.drawn = [ self.bag.pop(random.randint(0, len(self.bag) - 1)) for _ in xrange(0, len(letters))] self.players[self.current_turn].rack += self.candidate.drawn self.bag += holder newstate = StateNode(self.candidate) newstate.action = MoveTypes.Exchange self.__commit_state(newstate) self.passes += 1 if self.passes >= 6: self.game_over = True return True