Esempio n. 1
0
def test_pawn_enpassant():
    # Advance pawn by two spaces
    conducted_move_history = []
    board = get_enpassant_board()
    board, move_history_element = conduct_move(
        board, Move(MoveType.NORMAL, [1, 5], [3, 5]), "black")
    conducted_move_history.append(move_history_element)

    # Assert white pawn can only do regular attack, one space advance AND enpassant
    en_passant_move = Move.en_passant([3, 6], [2, 5])
    assert_contains(
        board[3][6].get_attack_set(board, [3, 6], conducted_move_history),
        [en_passant_move])

    # Actually execute en passant move
    board, move_history_element = conduct_move(board, en_passant_move, "white")
    conducted_move_history.append(move_history_element)

    __ = BlankPiece()
    p2 = Pawn("black")
    wp = Pawn("white")
    #             0   1   2   3   4   5   6   7
    expected_board = [
        [__, __, __, __, __, __, __, __],  # 0
        [__, __, __, __, __, __, __, p2],  # 1
        [__, __, __, __, __, wp, __, __],  # 2
        [__, __, __, __, __, __, __, __],  # 3
        [__, __, __, __, __, __, __, __],  # 4
        [__, __, __, __, __, __, __, __],  # 5
        [__, __, __, __, __, __, __, __],  # 6
        [__, __, __, __, __, __, __, __]  # 7
    ]
    assert_row_contain_same_type_elements(expected_board[1], board[1])
    assert_row_contain_same_type_elements(expected_board[2], board[2])
    assert_row_contain_same_type_elements(expected_board[3], board[3])
Esempio n. 2
0
def test_board_state_without_pawn_enpassant():
    conducted_move_history = []
    board = get_enpassant_board()
    board, move_history_element = conduct_move(board, Move(MoveType.NORMAL, [1,  5], [2, 5]), "black")
    conducted_move_history.append(move_history_element)

    # Assert white pawn can only do regular attack and one space advance
    assert_contains(
        board[3][6].get_attack_set(board, [3, 6], conducted_move_history),
        [
            Move(MoveType.NORMAL, [3, 6], [2, 5])
        ]
    )
    assert_contains(
        board[3][6].get_move_set(board, [3, 6], conducted_move_history),
        [Move(MoveType.NORMAL, [3, 6], [2, 6])]
    )

    # Advance the black pawn one more space
    board, move_history_element = conduct_move(board, Move(MoveType.NORMAL, [2, 5], [3, 5]), "black")
    conducted_move_history.append(move_history_element)

    # Assert white pawn can only do do a one space advance
    assert_length(board[3][6].get_attack_set(board, [3, 6], []), 0)
    assert_contains(
        board[3][6].get_move_set(board, [3, 6], []),
        [
            Move(MoveType.NORMAL, [3, 6], [2, 6])
        ]
    )
Esempio n. 3
0
    def make_move(self, player_color, selected_move):
        if player_color != self.player_turn:
            return False
        chosen_move = Move.create_from_dict(selected_move)

        update_move_history(self.game_board, self.potential_moveset_history, self.player_turn, self.conducted_move_history)
        self.game_board, move_history_element = conduct_move(self.game_board, chosen_move, self.player_turn)
        self.conducted_move_history.append(move_history_element)

        if not self.game_board:
            print("Illegal move not caught by game logic")

        if is_being_checked(self.game_board, opposite_col(self.player_turn)):
            if can_player_leave_check_state(self.game_board, opposite_col(self.player_turn), self.conducted_move_history):
                self.progress_state = ProgressState.CHECK
            else:
                print_board(self.game_board)
                self.progress_state = ProgressState.CHECKMATE
        else:
            self.progress_state = ProgressState.IN_PROGRESS

        self.player_turn = opposite_col(self.player_turn)
        if is_stalemate(self.game_board, self.player_turn, self.conducted_move_history):
            self.progress_state = ProgressState.DRAW_STALEMATE
        elif is_impossible_to_reach_checkmate(self.game_board):
            self.progress_state = ProgressState.DRAW_INSUFFICIENT_MATERIALS
        elif is_threefold_repetition_stalemate(self.potential_moveset_history):
            self.progress_state = self.progress_state.DRAW_THREEFOLD_REPETITION
        elif is_fifty_move_rule_draw(self.conducted_move_history):
            self.progress_state = self.progress_state.DRAW_FIFTY_MOVE_RULE

        print(self.player_turn + 's turn. Waiting for selection')
        return True
Esempio n. 4
0
def test_conducting_col_h_castle_move():
    board = get_castling_board()
    col_h_castle = Move(MoveType.CASTLING, [7, 4], [7, 6])
    board, move_history_element = conduct_move(board, col_h_castle, "white")

    _ = BlankPiece()
    expected_row = [Rook("white"), _, _, _, _, Rook("white"), King("white"), _]
    actual_row = board[7]
    assert_row_contain_same_type_elements(expected_row, actual_row)
Esempio n. 5
0
def test_fifty_move_rule():
    # Test moving white King to cause a 50-move rule draw
    board, conducted_move_history = get_fifty_move_rule_board()
    board, move_history_element = conduct_move(board, Move(MoveType.NORMAL, [7, 3], [7, 4]), "white")
    conducted_move_history.append(move_history_element)
    assert_true("Should be 50-move rule draw", is_fifty_move_rule_draw(conducted_move_history))

    # Black rook captures white pawn to prevent 50-move rule draw (via piece-capture code-path)
    board, conducted_move_history = get_fifty_move_rule_board()
    board, move_history_element = conduct_move(board, Move(MoveType.NORMAL, [3, 1], [6, 1]), "black")
    conducted_move_history.append(move_history_element)
    assert_false("Should NOT be draw", is_fifty_move_rule_draw(conducted_move_history))

    # Advance a pawn to prevent 50-move rule draw (via Pawn-type movement code-path)
    board, conducted_move_history = get_fifty_move_rule_board()
    board, move_history_element = conduct_move(board, Move(MoveType.NORMAL, [6, 1], [5, 2]), "white")
    conducted_move_history.append(move_history_element)
    assert_false("Should NOT be draw", is_fifty_move_rule_draw(conducted_move_history))
Esempio n. 6
0
def get_fifty_move_rule_board():
    """
    Helper function to run through the first 3 moves in a "four move rule" (use a smaller deque for sanity here -- 50
    is a lot),
    """
    #
    conducted_move_history = deque([], 4)

    __ = BlankPiece()
    wk = King("white")
    wp = Pawn("white")
    br = Rook("black")
    bk = King("black")

    #     0   1   2   3   4   5   6   7
    board = [
        [__, __, __, bk, __, __, __, __],  # 0
        [__, __, __, __, __, __, __, __],  # 1
        [__, __, __, __, __, __, __, __],  # 2
        [__, br, __, __, __, __, __, __],  # 3
        [__, __, __, __, __, __, __, __],  # 4
        [__, __, __, __, __, __, __, __],  # 5
        [__, wp, __, __, __, __, __, __],  # 6
        [__, __, __, __, wk, __, __, __]  # 7
    ]

    msg = "Should NOT be 50-move rule draw"

    board, move_history_element = conduct_move(
        board, Move(MoveType.NORMAL, [7, 4], [7, 1]), "white")
    conducted_move_history.append(move_history_element)
    assert_false(msg, is_fifty_move_rule_draw(conducted_move_history))

    board, move_history_element = conduct_move(
        board, Move(MoveType.NORMAL, [7, 1], [7, 2]), "white")
    conducted_move_history.append(move_history_element)
    assert_false(msg, is_fifty_move_rule_draw(conducted_move_history))

    board, move_history_element = conduct_move(
        board, Move(MoveType.NORMAL, [7, 2], [7, 3]), "white")
    conducted_move_history.append(move_history_element)
    assert_false(msg, is_fifty_move_rule_draw(conducted_move_history))
    return board, conducted_move_history
Esempio n. 7
0
def get_fifty_move_rule_board():
    """
    Helper function to run through the first 3 moves in a "four move rule" (use a smaller deque for sanity here -- 50
    is a lot),
    """
    #
    conducted_move_history = deque([], 4)

    __ = BlankPiece()
    wk = King("white")
    wp = Pawn("white")
    br = Rook("black")
    bk = King("black")

    #     0   1   2   3   4   5   6   7
    board = [
        [__, __, __, bk, __, __, __, __],  # 0
        [__, __, __, __, __, __, __, __],  # 1
        [__, __, __, __, __, __, __, __],  # 2
        [__, br, __, __, __, __, __, __],  # 3
        [__, __, __, __, __, __, __, __],  # 4
        [__, __, __, __, __, __, __, __],  # 5
        [__, wp, __, __, __, __, __, __],  # 6
        [__, __, __, __, wk, __, __, __]  # 7
    ]

    msg = "Should NOT be 50-move rule draw"

    board, move_history_element = conduct_move(board, Move(MoveType.NORMAL, [7, 4], [7, 1]), "white")
    conducted_move_history.append(move_history_element)
    assert_false(msg, is_fifty_move_rule_draw(conducted_move_history))

    board, move_history_element = conduct_move(board, Move(MoveType.NORMAL, [7, 1], [7, 2]), "white")
    conducted_move_history.append(move_history_element)
    assert_false(msg, is_fifty_move_rule_draw(conducted_move_history))

    board, move_history_element = conduct_move(board, Move(MoveType.NORMAL, [7, 2], [7, 3]), "white")
    conducted_move_history.append(move_history_element)
    assert_false(msg, is_fifty_move_rule_draw(conducted_move_history))
    return board, conducted_move_history
Esempio n. 8
0
def test_pawn_enpassant():
    # Advance pawn by two spaces
    conducted_move_history = []
    board = get_enpassant_board()
    board, move_history_element = conduct_move(board, Move(MoveType.NORMAL, [1, 5], [3, 5]), "black")
    conducted_move_history.append(move_history_element)

    # Assert white pawn can only do regular attack, one space advance AND enpassant
    en_passant_move = Move.en_passant([3, 6], [2, 5])
    assert_contains(
        board[3][6].get_attack_set(board, [3, 6], conducted_move_history),
        [
            en_passant_move
        ]
    )

    # Actually execute en passant move
    board, move_history_element = conduct_move(board, en_passant_move, "white")
    conducted_move_history.append(move_history_element)

    __ = BlankPiece()
    p2 = Pawn("black")
    wp = Pawn("white")
    #             0   1   2   3   4   5   6   7
    expected_board = [
                [__, __, __, __, __, __, __, __],  # 0
                [__, __, __, __, __, __, __, p2],  # 1
                [__, __, __, __, __, wp, __, __],  # 2
                [__, __, __, __, __, __, __, __],  # 3
                [__, __, __, __, __, __, __, __],  # 4
                [__, __, __, __, __, __, __, __],  # 5
                [__, __, __, __, __, __, __, __],  # 6
                [__, __, __, __, __, __, __, __]  # 7
            ]
    assert_row_contain_same_type_elements(expected_board[1], board[1])
    assert_row_contain_same_type_elements(expected_board[2], board[2])
    assert_row_contain_same_type_elements(expected_board[3], board[3])
Esempio n. 9
0
def test_board_state_without_pawn_enpassant():
    conducted_move_history = []
    board = get_enpassant_board()
    board, move_history_element = conduct_move(
        board, Move(MoveType.NORMAL, [1, 5], [2, 5]), "black")
    conducted_move_history.append(move_history_element)

    # Assert white pawn can only do regular attack and one space advance
    assert_contains(
        board[3][6].get_attack_set(board, [3, 6], conducted_move_history),
        [Move(MoveType.NORMAL, [3, 6], [2, 5])])
    assert_contains(
        board[3][6].get_move_set(board, [3, 6], conducted_move_history),
        [Move(MoveType.NORMAL, [3, 6], [2, 6])])

    # Advance the black pawn one more space
    board, move_history_element = conduct_move(
        board, Move(MoveType.NORMAL, [2, 5], [3, 5]), "black")
    conducted_move_history.append(move_history_element)

    # Assert white pawn can only do do a one space advance
    assert_length(board[3][6].get_attack_set(board, [3, 6], []), 0)
    assert_contains(board[3][6].get_move_set(board, [3, 6], []),
                    [Move(MoveType.NORMAL, [3, 6], [2, 6])])
Esempio n. 10
0
def test_fifty_move_rule():
    # Test moving white King to cause a 50-move rule draw
    board, conducted_move_history = get_fifty_move_rule_board()
    board, move_history_element = conduct_move(
        board, Move(MoveType.NORMAL, [7, 3], [7, 4]), "white")
    conducted_move_history.append(move_history_element)
    assert_true("Should be 50-move rule draw",
                is_fifty_move_rule_draw(conducted_move_history))

    # Black rook captures white pawn to prevent 50-move rule draw (via piece-capture code-path)
    board, conducted_move_history = get_fifty_move_rule_board()
    board, move_history_element = conduct_move(
        board, Move(MoveType.NORMAL, [3, 1], [6, 1]), "black")
    conducted_move_history.append(move_history_element)
    assert_false("Should NOT be draw",
                 is_fifty_move_rule_draw(conducted_move_history))

    # Advance a pawn to prevent 50-move rule draw (via Pawn-type movement code-path)
    board, conducted_move_history = get_fifty_move_rule_board()
    board, move_history_element = conduct_move(
        board, Move(MoveType.NORMAL, [6, 1], [5, 2]), "white")
    conducted_move_history.append(move_history_element)
    assert_false("Should NOT be draw",
                 is_fifty_move_rule_draw(conducted_move_history))
Esempio n. 11
0
    def make_move(self, player_color, selected_move):
        if player_color != self.player_turn:
            return False
        chosen_move = Move.create_from_dict(selected_move)

        update_move_history(self.game_board, self.potential_moveset_history,
                            self.player_turn, self.conducted_move_history)
        self.game_board, move_history_element = conduct_move(
            self.game_board, chosen_move, self.player_turn)
        self.conducted_move_history.append(move_history_element)

        if not self.game_board:
            print("Illegal move not caught by game logic")

        if is_being_checked(self.game_board, opposite_col(self.player_turn)):
            if can_player_leave_check_state(self.game_board,
                                            opposite_col(self.player_turn),
                                            self.conducted_move_history):
                self.progress_state = ProgressState.CHECK
            else:
                print_board(self.game_board)
                self.progress_state = ProgressState.CHECKMATE
        else:
            self.progress_state = ProgressState.IN_PROGRESS

        self.player_turn = opposite_col(self.player_turn)
        if is_stalemate(self.game_board, self.player_turn,
                        self.conducted_move_history):
            self.progress_state = ProgressState.DRAW_STALEMATE
        elif is_impossible_to_reach_checkmate(self.game_board):
            self.progress_state = ProgressState.DRAW_INSUFFICIENT_MATERIALS
        elif is_threefold_repetition_stalemate(self.potential_moveset_history):
            self.progress_state = self.progress_state.DRAW_THREEFOLD_REPETITION
        elif is_fifty_move_rule_draw(self.conducted_move_history):
            self.progress_state = self.progress_state.DRAW_FIFTY_MOVE_RULE

        print(self.player_turn + 's turn. Waiting for selection')
        return True
Esempio n. 12
0
def main():
    player_turn = "white"

    game_board = create()
    # Maintain complete history of all potential game moves (for the three-fold repetition rule)
    potential_moveset_history = []
    # The Wikipedia page for the 50-move rule suggests that for the purposes the rule, a move is a player's turn
    # followed by opponents turn.
    history_length = 50 * 2
    # Maintain complete history of actually completed moves (for the 50-move rule, and en passant)
    conducted_move_history = deque([], history_length)

    while 1:
        print_board(game_board)
        print(player_turn + 's turn. Select piece')

        valid_selection = False
        while not valid_selection:
            coords = request_user_move(' Select piece to move. Example: e2 \n')
            if not coords:
                continue
            if selected_piece(game_board, coords).is_blank_piece:
                print('...Error invalid piece. Choose another piece\n')
                continue
            if selected_piece(game_board, coords).col != player_turn:
                print(
                    '...Error selected opponents\' piece. Choose another piece\n'
                )
                continue

            piece_total_move_set = selected_piece(game_board,
                                                  coords).get_move_set(
                                                      game_board, coords,
                                                      conducted_move_history)
            piece_total_move_set += selected_piece(game_board,
                                                   coords).get_attack_set(
                                                       game_board, coords,
                                                       conducted_move_history)
            piece_legal_move_set = filter_self_checking_moves(
                game_board, piece_total_move_set, player_turn,
                conducted_move_history)
            if len(piece_legal_move_set) == 0:
                print(
                    '...Error no legal moves available. Choose another piece\n'
                )
                continue
            valid_selection = True

            print(
                'Selected: \'' + selected_piece(game_board, coords).type +
                '\'.', )
            print('Possible moves: ', )
            for move in piece_legal_move_set:
                print(move, ": ", py_to_a1_convert(move.end_coords))
            print()

            # Choose end location:
            chosen_move = False
            while not chosen_move:
                user_end_coords = request_user_move(
                    ' Select location to move piece to: ')
                if not user_end_coords:
                    continue
                for move in piece_legal_move_set:
                    if move.end_coords[0] == user_end_coords[
                            0] and move.end_coords[1] == user_end_coords[1]:
                        chosen_move = move
                if not chosen_move:
                    continue
                if chosen_move.move_type == MoveType.PROMOTION:
                    # If we chose one a promotion end coordinates, we need to find the exact promotion choice we desire
                    chosen_move = request_promotion_type(piece_legal_move_set)
                if not chosen_move:
                    print('Invalid move\n')
                    continue

        update_move_history(game_board, potential_moveset_history, player_turn,
                            conducted_move_history)
        game_board, move_history_element = conduct_move(
            game_board, chosen_move, player_turn)
        conducted_move_history.append(move_history_element)

        if not game_board:
            print("Illegal move not caught by game logic")

        if is_being_checked(game_board, opposite_col(player_turn)):
            if can_player_leave_check_state(game_board,
                                            opposite_col(player_turn),
                                            conducted_move_history):
                print('CHECK\n')
            else:
                print_board(game_board)
                print('CHECKMATE. ' + player_turn + ' wins!\n')
                sys.exit(0)

        player_turn = opposite_col(player_turn)
        if is_stalemate(game_board, player_turn, conducted_move_history):
            print('DRAW (STALEMATE)\n')
            sys.exit(0)
        if is_impossible_to_reach_checkmate(game_board):
            print('DRAW (INSUFFICIENT MATERIALS)\n')
            sys.exit(0)
        if is_threefold_repetition_stalemate(potential_moveset_history):
            print('DRAW (THREEFOLD REPETITION)\n')
            sys.exit(0)
        if is_fifty_move_rule_draw(conducted_move_history):
            print('DRAW (FIFTY-MOVE RULE)\n')
            sys.exit(0)