def set_up_game(self): """Create the pieces for a new game, store them in two lists white pieces and black pieces""" self.black_king = King(self, BLACK, Position(4, 7)) self.white_king = King(self, WHITE, Position(4, 0)) self.white_pieces = [self.white_king] self.black_pieces = [self.black_king] self.white_pieces.append(Queen(self, WHITE, Position(3, 0))) self.black_pieces.append(Queen(self, BLACK, Position(3, 7))) self.black_pieces.append(Rook(self, BLACK, Position(0, 7))) self.black_pieces.append(Rook(self, BLACK, Position(7, 7))) self.white_pieces.append(Rook(self, WHITE, Position(7, 0))) self.white_pieces.append(Rook(self, WHITE, Position(0, 0))) self.black_pieces.append(Bishop(self, BLACK, Position(2, 7))) self.black_pieces.append(Bishop(self, BLACK, Position(5, 7))) self.white_pieces.append(Bishop(self, WHITE, Position(2, 0))) self.white_pieces.append(Bishop(self, WHITE, Position(5, 0))) self.black_pieces.append(Knight(self, BLACK, Position(1, 7))) self.black_pieces.append(Knight(self, BLACK, Position(6, 7))) self.white_pieces.append(Knight(self, WHITE, Position(1, 0))) self.white_pieces.append(Knight(self, WHITE, Position(6, 0))) for i in range(0, 8): self.white_pieces.append(Pawn(self, WHITE, Position(i, 1))) self.black_pieces.append(Pawn(self, BLACK, Position(i, 6)))
def test_castling_moves_both_sides(self): """Test king castling moves returns correct moves when castling is open on both sides""" king_side_rook = Rook(None, WHITE, Position(0, 0)) queen_side_rook = Rook(None, WHITE, Position(7, 0)) test_board = {'white_pieces': [king_side_rook, queen_side_rook]} board = set_up_test_board(new_game=False, test_board=test_board) white_king = board.get_piece(Position(4, 0)) self.assertEqual(len(white_king.castling_moves), 2)
def test_castling_moves_empty_when_attacked(self): """Test castling moves is empty when an enemy is attacking a square in between king and rook""" black_knight = Knight(None, BLACK, Position(2, 2)) white_rook = Rook(None, WHITE, Position(0, 0)) white_rook2 = Rook(None, WHITE, Position(7, 0)) test_board = { 'white_pieces': [white_rook, white_rook2], 'black_pieces': [black_knight] } board = set_up_test_board(new_game=False, test_board=test_board) white_king = board.get_piece(Position(4, 0)) self.assertEqual(len(white_king.castling_moves), 1)
def test_player_move_fails_into_check(self): """Test trying to make a move into check fails""" white_rook_position = Position(4, 1) black_rook = Rook(None, constants.BLACK, Position(4, 5)) white_rook = Rook(None, constants.WHITE, white_rook_position) test_board = { 'white_pieces': [white_rook], 'black_pieces': [black_rook] } board = set_up_test_board(new_game=False, test_board=test_board) game = set_up_test_game(board) with pytest.raises(InvalidMoveError): game.player_move(white_rook_position, Position(2, 1))
def test_try_move_with_capture(self, board): white_rook_position = Position(4, 4) white_rook = Rook(board, constants.WHITE, white_rook_position) to_position = Position(5, 4) black_rook = Rook(board, constants.BLACK, to_position) board.in_check.return_value = False game = Game() game._board = board self.assertTrue(game.try_move(white_rook, to_position)) self.assertEqual(white_rook.position, white_rook_position) self.assertEqual(black_rook.position, to_position) board.in_check.return_value = True self.assertFalse(game.try_move(white_rook, to_position)) self.assertEqual(white_rook.position, white_rook_position) self.assertEqual(black_rook.position, to_position)
def test_player_move_castle_fails(self): """Test castling fails when a position in between king and rook is attacked""" white_rook_position = Position(0, 0) black_rook = Rook(None, constants.BLACK, Position(2, 5)) white_rook = Rook(None, constants.WHITE, white_rook_position) test_board = { 'white_pieces': [white_rook], 'black_pieces': [black_rook] } board = set_up_test_board(new_game=False, test_board=test_board) game = set_up_test_game(board) with pytest.raises(InvalidMoveError): game.player_move(Position(4, 0), Position(2, 0)) self.assertEqual(white_rook.position, white_rook_position) self.assertTrue(isinstance(board.get_piece(Position(4, 0)), King))
def test_player_move_already_in_check_fails(self): """Test trying to move when you're in check and still in check after the move fails""" white_bishop_position = Position(3, 3) black_rook = Rook(None, constants.BLACK, Position(4, 5)) white_bishop = Rook(None, constants.WHITE, white_bishop_position) test_board = { 'white_pieces': [white_bishop], 'black_pieces': [black_rook] } board = set_up_test_board(new_game=False, test_board=test_board) game = set_up_test_game(board) with pytest.raises(InvalidMoveError): game.player_move(white_bishop_position, Position(6, 6))
def test_player_move_capture_success(self): """Test a basic capture of a piece works as expected""" white_rook_position = Position(2, 0) black_rook_position = Position(2, 5) black_rook = Rook(None, constants.BLACK, black_rook_position) white_rook = Rook(None, constants.WHITE, white_rook_position) test_board = { 'white_pieces': [white_rook], 'black_pieces': [black_rook] } board = set_up_test_board(new_game=False, test_board=test_board) game = set_up_test_game(board) game.player_move(white_rook_position, black_rook_position) self.assertEqual(white_rook.position, black_rook_position) self.assertIsNone(black_rook.position) self.assertNotIn(black_rook, board.black_pieces)
def test_in_check(self): """Test in_check returns true when king is in_check""" black_rook = Rook(None, BLACK, Position(4, 4)) test_board = { 'black_pieces': [black_rook] } board = set_up_test_board(new_game=False, test_board=test_board) self.assertTrue(board.in_check(WHITE))
def test_player_move_fails_wrong_turn(self, board): rook_position = Position(1, 1) board.get_piece.return_value = Rook(board, constants.BLACK, rook_position) game = Game() game._board = board game._turn = constants.WHITE with pytest.raises(InvalidMoveError): game.player_move(rook_position, Position)
def test_try_move_without_capture(self, board): rook_position = Position(4, 4) rook = Rook(board, constants.WHITE, rook_position) board.in_check.return_value = False game = Game() game._board = board self.assertTrue(game.try_move(rook, Position(5, 4))) self.assertEqual(rook.position, rook_position) board.in_check.return_value = True self.assertFalse(game.try_move(rook, Position(5, 4))) self.assertEqual(rook.position, rook_position)
def test_player_move_castle_success(self): """Test player move castling is successful when it is a valid move""" white_rook_position = Position(0, 0) white_rook = Rook(None, constants.WHITE, white_rook_position) test_board = {'white_pieces': [white_rook]} board = set_up_test_board(new_game=False, test_board=test_board) game = set_up_test_game(board) game.player_move(Position(4, 0), Position(2, 0)) self.assertEqual(white_rook.position, Position(3, 0)) self.assertTrue(isinstance(board.get_piece(Position(2, 0)), King))
def test_get_moves_no_special(self, board, try_move): invalid_position = Position(3, 3) def my_side_effect(*args): if args[1] == invalid_position: return False return True try_move.side_effect = my_side_effect game = Game() game._board = board rook = Rook(board, constants.WHITE, Position(4, 4)) bishop = Bishop(board, constants.WHITE, Position(1, 1)) knight = Knight(board, constants.WHITE, Position(7, 0)) mocked_board_moves = { rook: { constants.MOVES: [Position(5, 4), Position(3, 4)], constants.SPECIAL_MOVES: {} }, bishop: { constants.MOVES: [Position(2, 2), invalid_position], constants.SPECIAL_MOVES: {} }, knight: { constants.MOVES: [], constants.SPECIAL_MOVES: {} } } valid_moves = { rook: { constants.MOVES: [Position(5, 4), Position(3, 4)], constants.SPECIAL_MOVES: {} }, bishop: { constants.MOVES: [Position(2, 2)], constants.SPECIAL_MOVES: {} }, knight: { constants.MOVES: [], constants.SPECIAL_MOVES: {} } } board.get_moves.return_value = mocked_board_moves all_game_moves = game.get_moves(constants.WHITE) self.assertEqual(len(mocked_board_moves), len(all_game_moves)) for key in valid_moves.keys(): self.assertIn(key, all_game_moves) self.assertEqual(len(valid_moves[key]), len(all_game_moves[key])) for move in mocked_board_moves[key]: self.assertIn(move, all_game_moves[key]) self.assertEqual(game.status, constants.IN_PROGRESS)
def test_castling_kingside_only(self): """Test castling moves only contains kingside castle, when pieces are in the way of a queenside castle""" queen_side_rook = Rook(None, WHITE, Position(0, 0)) king_side_rook = Rook(None, WHITE, Position(7, 0)) white_bishop = Bishop(None, WHITE, Position(2, 0)) test_board = { 'white_pieces': [king_side_rook, queen_side_rook, white_bishop] } board = set_up_test_board(new_game=False, test_board=test_board) white_king = board.get_piece(Position(4, 0)) self.assertEqual(len(white_king.castling_moves), 1) king_move_key = (6, 0) self.assertIn(king_move_key, white_king.castling_moves.keys()) test_castle_move = { TYPE: CASTLE, ROOK: king_side_rook, ROOK_TO: Position(5, 0) } for key in test_castle_move.keys(): self.assertEqual(test_castle_move[key], white_king.castling_moves[king_move_key][key])
def test_white_rook_moves_random(self): """Test bishop moves returns correct moves when, friendlies and enemies are on it's lines""" white_rook = Rook(None, WHITE, Position(4, 4)) board = set_up_test_board(new_game=True) board.white_pieces.append(white_rook) white_rook.board = board self.assertEqual(len(white_rook.moves), 11) moves = [ Position(4, 5), Position(4, 6), Position(4, 3), Position(4, 2), Position(5, 4), Position(6, 4), Position(7, 4), Position(3, 4), Position(2, 4), Position(1, 4), Position(0, 4) ] for m in moves: self.assertIn(m, white_rook.moves)
def test_is_enemy_pawn(self): """Test is_enemy_pawn returns True if enemy pawn and False otherwise""" black_pawn_position = Position(1, 4) black_rook_position = Position(2, 4) black_pawn = Pawn(None, BLACK, black_pawn_position) black_rook = Rook(None, BLACK, black_rook_position) test_board = { 'black_pieces': [black_rook, black_pawn] } board = set_up_test_board(new_game=False, test_board=test_board) self.assertTrue(board.is_enemy_pawn(black_pawn_position, WHITE)) self.assertFalse(board.is_enemy_pawn(black_rook_position, WHITE))
def test_player_move_fails_invalid_move(self, board, mock_get_moves): rook_position = Position(1, 1) rook = Rook(board, constants.WHITE, rook_position) board.get_piece.return_value = rook mock_get_moves.return_value = { rook: { constants.MOVES: [Position(0, 1), Position(1, 2)], constants.SPECIAL_MOVES: {} } } game = Game() game._board = board with pytest.raises(InvalidMoveError): game.player_move(rook.position, Position(2, 2))
def test_player_move_en_passant_fails(self): """Test calling making an en passant move is fails when not valid""" white_position = Position(0, 3) black_position = Position(1, 3) white_rook = Rook(None, constants.WHITE, white_position) black_pawn = Pawn(None, constants.BLACK, black_position) test_board = { 'white_pieces': [white_rook], 'black_pieces': [black_pawn] } board = set_up_test_board(new_game=False, test_board=test_board) game = set_up_test_game(board, turn=constants.BLACK, history=get_pawn_move_record_passant( white_position, Position(0, 1))) en_passant_position = Position(0, 2) with pytest.raises(InvalidMoveError): game.player_move(black_position, en_passant_position)
def test_player_move_success(self, mock_get_moves): rook_position = Position(1, 1) rook = Rook(None, constants.WHITE, rook_position) test_board = {'black_pieces': [rook]} mock_get_moves.return_value = { rook: { constants.MOVES: [Position(0, 1), Position(1, 2), Position(2, 2)], constants.SPECIAL_MOVES: {} } } board = set_up_test_board(new_game=False, test_board=test_board) game = Game() game._board = board game.player_move(rook.position, Position(2, 2)) self.assertEqual(rook.position, Position(2, 2))
def test_white_are_bishop_and_rook_moves(self): """Test that queen moves are equal to the sum of bishop and rook moves from the same position""" white_bishop = Bishop(None, WHITE, Position(4, 4)) white_queen = Queen(None, WHITE, Position(4, 4)) white_rook = Rook(None, WHITE, Position(4, 4)) test_board1 = {'white_pieces': [white_bishop]} test_board2 = {'white_pieces': [white_rook]} test_board3 = {'white_pieces': [white_queen]} set_up_test_board(test_board=test_board1) set_up_test_board(test_board=test_board2) set_up_test_board(test_board=test_board3) bishop_rook_moves = white_bishop.moves + white_rook.moves self.assertEqual(len(bishop_rook_moves), len(white_queen.moves)) for m in bishop_rook_moves: self.assertIn(m, white_queen.moves)
def test_get_moves(self): """Test the get moves method returns the correct moves""" black_pawn = Pawn(None, BLACK, Position(2, 3)) black_rook = Rook(None, BLACK, Position(4, 4)) test_board = { 'black_pieces': [black_rook, black_pawn] } board = set_up_test_board(new_game=False, test_board=test_board) moves = board.get_moves(BLACK) for piece in test_board['black_pieces']: self.assertIn(piece, moves.keys()) for move in black_pawn.moves: self.assertIn(move, moves[black_pawn]['moves']) for move in black_pawn.en_passant_moves: self.assertIn(move, moves[black_pawn]['special_moves']) for move in black_rook.moves: self.assertIn(move, moves[black_rook]['moves'])
def test_is_valid_passant(self, board): white_pawn_position = Position(3, 3) black_pawn_position = Position(4, 3) black_pawn = Pawn(board, constants.BLACK, black_pawn_position) white_pawn = Pawn(board, constants.WHITE, white_pawn_position) game = Game() game._board = board en_passant_move = Position(3, 2) game._history.append({ constants.COLOUR: white_pawn.colour, constants.FROM: Position(3, 1), constants.TO: white_pawn.position, constants.PIECE_TYPE: type(white_pawn), constants.CAPTURED: None, constants.TYPE: constants.EN_PASSANT, constants.FIRST_MOVE: True }) board.get_piece.return_value = white_pawn board.in_check.return_value = True self.assertFalse( game.is_valid_passant(black_pawn, en_passant_move, white_pawn)) self.assertEqual(white_pawn.position, white_pawn_position) self.assertEqual(black_pawn.position, black_pawn_position) board.in_check.return_value = False self.assertTrue( game.is_valid_passant(black_pawn, en_passant_move, white_pawn)) self.assertEqual(white_pawn.position, white_pawn_position) self.assertEqual(black_pawn.position, black_pawn_position) game._history[0][constants.FIRST_MOVE] = False self.assertFalse( game.is_valid_passant(black_pawn, en_passant_move, white_pawn)) game._history[0][constants.FIRST_MOVE] = True board.get_piece.return_value = Rook(board, constants.BLACK, Position(1, 1)) self.assertFalse( game.is_valid_passant(black_pawn, en_passant_move, white_pawn))
def test_white_rook_moves_empty_board(self): """Test rook moves returns correct moves when only dealing with empty squares""" white_rook = Rook(None, WHITE, Position(4, 4)) test_board = {'white_pieces': [white_rook]} board = set_up_test_board(test_board=test_board) self.assertEqual(len(white_rook.moves), 13) moves = [ Position(5, 4), Position(6, 4), Position(7, 4), Position(3, 4), Position(2, 4), Position(1, 4), Position(0, 4), Position(4, 5), Position(4, 6), Position(4, 7), Position(4, 3), Position(4, 2), Position(4, 1) ] for m in moves: self.assertIn(m, white_rook.moves)