示例#1
0
def test_check_end_state_row():
    board = cm.initialize_game_state()
    board[0, 0] = cm.PLAYER1
    board[0, 1] = cm.PLAYER1
    board[0, 2] = cm.PLAYER1
    board[0, 3] = cm.PLAYER1
    assert cm.GameState.IS_WIN == cm.check_end_state(board, cm.PLAYER1)
    assert not cm.GameState.IS_WIN == cm.check_end_state(board, cm.PLAYER2)
示例#2
0
def test_check_end_state_column():
    board = cm.initialize_game_state()
    board[0, 0] = cm.PLAYER1
    board[1, 0] = cm.PLAYER1
    board[2, 0] = cm.PLAYER1
    board[3, 0] = cm.PLAYER1
    assert cm.GameState.IS_WIN == cm.check_end_state(board, cm.PLAYER1)
    assert not cm.GameState.IS_WIN == cm.check_end_state(board, cm.PLAYER2)
示例#3
0
def test_check_end_state_left_diagonal():
    board = cm.initialize_game_state()
    board[0, 1] = cm.PLAYER1
    board[1, 1] = cm.PLAYER1
    board[2, 1] = cm.PLAYER1
    board[3, 1] = cm.PLAYER2
    board[0, 2] = cm.PLAYER2
    board[1, 2] = cm.PLAYER2
    board[2, 2] = cm.PLAYER2
    board[0, 3] = cm.PLAYER1
    board[1, 3] = cm.PLAYER2
    board[0, 4] = cm.PLAYER2
    print(cm.pretty_print_board(board))
    assert cm.GameState.IS_WIN == cm.check_end_state(board, cm.PLAYER2)
    assert not cm.GameState.IS_WIN == cm.check_end_state(board, cm.PLAYER1)
示例#4
0
    def get_open_moves(self) -> np.ndarray:
        """
        Getter function to obtain possible open columns
        :return:
        An array of column numbers
        """

        if common.check_end_state(self.state,
                                  self.player) == common.GameState.IS_WIN:
            return np.array([])
        else:
            return np.array(common.get_free_columns(self.state))
示例#5
0
def human_vs_agent(
    generate_move_1: GenMove,
    generate_move_2: GenMove = user_move,
    player_1: str = "Player 1",
    player_2: str = "Player 2",
    args_1: tuple = (),
    args_2: tuple = (),
    init_1: Callable = lambda board, player: None,
    init_2: Callable = lambda board, player: None,
):
    players = (PLAYER1, PLAYER2)
    for play_first in (1, -1):
        for init, player in zip((init_1, init_2)[::play_first], players):
            init(initialize_game_state(), player)

        saved_state = {PLAYER1: None, PLAYER2: None}
        board = initialize_game_state()
        gen_moves = (generate_move_1, generate_move_2)[::play_first]
        player_names = (player_1, player_2)[::play_first]
        gen_args = (args_1, args_2)[::play_first]

        playing = True
        end_state = GameState.STILL_PLAYING
        while playing:
            for player, player_name, gen_move, args in zip(
                    players,
                    player_names,
                    gen_moves,
                    gen_args,
            ):
                t0 = time.time()
                print(pretty_print_board(board))
                action, saved_state[player] = gen_move(board.copy(), player,
                                                       saved_state[player],
                                                       *args)
                print('{} \'s action is {}'.format(player_name, action))
                print(f"Move time: {time.time() - t0:.3f}s")
                board, r_board = apply_player_action(board, action, player,
                                                     True)
                end_state = check_end_state(board, player)
                if end_state != GameState.STILL_PLAYING:
                    print(pretty_print_board(board))
                    if end_state == GameState.IS_DRAW:
                        print("Game ended in draw")
                    else:
                        print(f'{player_name} won playing \
                            {"X" if player == PLAYER1 else "O"}')
                    playing = False
                    break
示例#6
0
def minimax(board: np.ndarray, depth: int, alpha: int, beta: int,
            maximizing_player: bool) -> tuple:
    """
    Applies the minimax algorithm on the board to
    give a suggested column number and maximising/minimising score

    :parameter board: the playing board of type np.ndarray
    :parameter depth: the depth till which to evaluate the
     board with the algorithm
    :parameter alpha: the minimum score the maximising player is assured of
    :parameter beta: the maximum score the minimising player is assured of
    :parameter maximizing_player: boolean flag suggesting if the
    algorithm needs to maximise or minimise

    :return: The column and computed maximum/minimum score
    """
    # if depth is 0 or node is terminal, return heuristic value of the node
    # if terminal check if it is win , loss or draw
    if cn.connected_four(board, AGENT):
        return None, 10000
    if cn.connected_four(board, HUMAN):
        return None, -10000
    # Check if there is a draw
    if cn.check_end_state(board, AGENT) == cn.GameState.IS_DRAW:
        return None, 0
    # if depth is 0, calculate heuristic scoring
    if depth == 0:
        return None, heuristic_scoring(board, AGENT)

    # get a list of columns open for placement
    col_list = cn.get_free_columns(board)
    if maximizing_player:
        # value = -infinity
        value = -math.inf
        column = np.random.choice(col_list)
        # for child node (interpreted it as available columns)
        for col in col_list:
            # apply a random column to check the minimax
            b_copy, ori_board = cn.apply_player_action(board, col, AGENT, True)
            # get the score only
            new_score = minimax(b_copy, depth - 1, alpha, beta, False)[1]
            # personal debugging
            if depth == GLOBAL_DEPTH:
                print('For col {}, the score is {}'.format(col, new_score))
            # use the new score if higher
            if new_score > value:
                value = new_score
                column = col
            # prune in the maximising node
            alpha = max(alpha, value)
            if alpha >= beta:
                break
        return column, value

    # minimising branch
    else:
        # value = +infinity
        value = math.inf
        column = np.random.choice(col_list)
        for col in col_list:
            b_copy, ori_board = cn.apply_player_action(board, col, HUMAN, True)
            new_score = minimax(b_copy, depth - 1, alpha, beta, True)[1]
            # get the minimizing score
            if new_score < value:
                value = new_score
                column = col
            # do beta pruning check
            beta = min(beta, value)
            if alpha >= beta:
                break
        return column, value
示例#7
0
def test_end_state_draw():
    board = 5 * np.ones((6, 7), dtype=BoardPiece)
    assert cm.GameState.IS_DRAW == cm.check_end_state(board, cm.PLAYER1)