Ejemplo n.º 1
0
def evaluate_line(board, player, index1, index2, index3):
    """
    Evaluates a line in board given by index1, index2, index3
    for the provided player.  Returns a score for that line assuming
    player is the max player and get_opponent(player) is the min player.
    You can see more details at the sites where I researched this
    algorithm.

    @param board: the tic-tac-toe board you want to evaluate.
    @param player: the max player you are scoring the line for.
    @param index1: first index in board that you want to check.
    @param index2: second index in board that you want to check.
    @param index3: third index in board that you want to check.
    @return: will return an int value based on the contents of the line
    given by index1, index2, and index3.  Possible values are:
        - +100: all three spaces have player values (player wins)
        - +10: two spaces have player values, the remaining one is blank
        - +1: one space has a player value, the remaining two are blank
        - 0: there is at least one player value and one opponent value
            (the line is dead)
        - -1: one space has an opponent value, the remaining two are blank
        - -10: two spaces have opponent values, the remaining one is blank
        - -100: all three spaces have opponent values (opponent wins)
    """
    opponent = utils.get_opponent(player)
    line_counts = Counter([board[index1], board[index2], board[index3]])
    if line_counts[player] > 0 and line_counts[opponent] > 0:
        return 0  # line has player and opponent values = dead line
    if line_counts[opponent] == 0:
        return int(pow(10, line_counts[player] - 1))  # line has only player values
    return -int(pow(10, line_counts[opponent] - 1))  # line has only opponent values
Ejemplo n.º 2
0
def _minimax_score(board, player_to_move, player_to_optimize):
    winner = ttt.get_winner(board)
    if winner is not None:
        if winner == player_to_optimize:
            return 10
        else:
            return -10
    elif ttt.is_board_full(board):
        return 0

    legal_moves = utils.get_all_legal_moves(board)

    scores = []
    for move in legal_moves:
        _board = copy.deepcopy(board)
        ttt.make_move(player_to_move, _board, move)

        opp = utils.get_opponent(player_to_move)
        opp_best_response_score = _minimax_score(_board, opp,
                                                 player_to_optimize)
        scores.append(opp_best_response_score)

    if player_to_move == player_to_optimize:
        return max(scores)
    else:
        return min(scores)
Ejemplo n.º 3
0
def minimax_score(board, player_to_move, current_player):

    winner = has_winner(board)
    if winner is not None:
        if winner == current_player:
            return 10
        else:
            return -10
    elif is_board_full(board):
        return 0

    legal_moves = get_all_available_moves(board)

    scores = []
    for move in legal_moves:
        # First make the move
        if move == None:
            continue
        _board = copy.deepcopy(board)
        make_move(_board, move, player_to_move)

        opponent = get_opponent(player_to_move)
        score = minimax_score(_board, opponent, current_player)
        scores.append(score)

    if player_to_move == current_player:
        return max(scores)
    else:
        return min(scores)
Ejemplo n.º 4
0
def blocks_their_winning_moves_ai(board, who_am_i):
    their_winning_move = _find_winning_move(board,
                                            utils.get_opponent(who_am_i))
    if their_winning_move:
        return their_winning_move
    else:
        return _random_move(board)
Ejemplo n.º 5
0
def _cached_minimax_score(board, player_current, player_main):
    winner = engine.get_winner(board)
    opponent = utils.get_opponent(player_current)

    if winner == player_main:
        return 10
    elif winner == opponent:
        return -10
    elif engine.is_board_full(board):
        return 0

    board_cache_key = str(board)
    is_main_player = player_current == player_main
    if board_cache_key in cache:
        scores = cache[board_cache_key]
        return max(scores) if is_main_player else min(scores)

    legal_moves = utils.get_legal_moves(board, player_current)
    scores = []

    for move in legal_moves:
        _board = copy.deepcopy(board)
        engine.make_move(_board, move, player_current)
        score = _cached_minimax_score(_board, opponent, player_main)
        scores.append(score)

    cache[board_cache_key] = scores
    if player_current == player_main:
        return max(scores)
    else:
        return min(scores)
Ejemplo n.º 6
0
def finds_all_winning_moves_ai(board, who_am_i):
    my_winning_move = _find_winning_move(board, who_am_i)
    if my_winning_move:
        return my_winning_move

    their_winning_move = _find_winning_move(board,
                                            utils.get_opponent(who_am_i))
    if their_winning_move:
        return their_winning_move

    return _random_move(board)
Ejemplo n.º 7
0
def minimax_ai(board, player):
    legal_moves = utils.get_legal_moves(board, player)
    opponent = utils.get_opponent(player)
    scores = []

    for move in legal_moves:
        _board = copy.deepcopy(board)
        engine.make_move(_board, move, player)
        score = _cached_minimax_score(_board, opponent, player)
        scores.append(score)

    sorted_best_moves = [x for _, x in sorted(zip(scores, legal_moves))]
    return sorted_best_moves[-1]
Ejemplo n.º 8
0
def minimax_ai(board, who_am_i):
    best_move = None
    best_score = None

    for move in utils.get_all_legal_moves(board):
        _board = copy.deepcopy(board)
        ttt.make_move(who_am_i, _board, move)

        opp = utils.get_opponent(who_am_i)
        score = _minimax_score(_board, opp, who_am_i)
        if best_score is None or score > best_score:
            best_move = move
            best_score = score

    return best_move
Ejemplo n.º 9
0
def minimax(state, actions, player):  # minimax(state, actions, player = 'O')
    """heiristic algorithm to improve the winning ratio"""
    winner = check_winner(state)

    if winner:
        return (None, None), winner

    else:
        state = (list([list(row) for row in state]))
        draw_move = None
        # print("I am going to evaluate", actions)
        for action in actions:
            # print("Evaluated Action: ", action)
            newBoard = deepcopy(state)
            row = action[0]
            column = action[1]
            newBoard[row][column] = player  # insert 'O'

            # updates the empty_cells list and calls the function itself with the board as the newBoard
            _newBoard = (tuple([tuple(row) for row in newBoard]))
            newEmptyCells = findEmptyCells(_newBoard)
            # print("Who is the winner for?", newBoard)
            move, winner = minimax(_newBoard, newEmptyCells,
                                   get_opponent(player))
            # print("The winner is", winner)

            # output: who is going to win?
            # ----> 'O', 'X', DRAW
            if player == 'O':
                if winner == 'O':
                    # print("The winner is 'O'")
                    return (row, column), winner
                if winner == "It's a Draw":
                    draw_move = action

            if player == 'X':
                if winner == 'X':
                    return (row, column), winner

        output = pick_random_move(state)

        # TODO: BUG HERE! vvvv
        return output, winner
Ejemplo n.º 10
0
def minimax(board, player, depth, alpha, beta):
    """
    I researched the algorithm for the tic-tac-toe ai here:
    http://www.ntu.edu.sg/home/ehchua/programming/java/JavaGame_TicTacToe_AI.html
    Additional research at :
    http://en.wikipedia.org/wiki/Minimax#Minimax_algorithm_with_alternate_moves
    http://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning

    Uses the Minimax algorithm with alpha-beta pruning.
    Returns the best move for the provided player on the given board as a
    minimax_result namedtuple.  This tuple has the score of the minimax algorithm
    as well as the x and y of the best move.

    @param board: a 1D array as generated by the game_board module representing the
    current tic-tac-toe board.
    @param player: the (int) value of the player looking to get the best move possible.
    @param depth: the depth of the tree to search.  In tic-tac-toe, we are only looking one
    move ahead so we use 2 as the value.
    @param alpha: the default alpha for alpha-beta pruning.  We use -inf.
    @param beta: the default beta for alpha-beta pruning.  We use inf.
    @return: An int representing the best move for the provided player.  The int will
    be the index on the given board where the given player should make their move.
    """
    best_index = -1
    moves = get_all_moves(board, player)
    opponent = utils.get_opponent(player)
    if moves == [] or depth == 0:
        return minimax_result(score=evaluate(board, config.COMPUTER), index=best_index)
    else:
        for move in moves:
            new_board = make_move(board, move, player)
            result = minimax(new_board, opponent, depth - 1, alpha, beta)
            if player == config.COMPUTER and result.score > alpha:
                alpha = result.score
                best_index = move
            elif player == config.HUMAN and result.score < beta:
                beta = result.score
                best_index = move
            if alpha >= beta:
                break
    best_score = alpha if player == config.COMPUTER else beta
    return minimax_result(score=best_score, index=best_index)
Ejemplo n.º 11
0
def minimax_ai(board, player_state):
    best_move = None
    best_score = None

    legal_moves = get_all_available_moves(board)

    for move in legal_moves:
        _board = copy.deepcopy(board)

        make_move(_board, move, player_state)

        opp = get_opponent(player_state)

        score = _minimax_score(_board, opp, player_state)

        if best_score is None or score > best_score:
            best_move = move
            best_score = score

    return best_move
Ejemplo n.º 12
0
def get_all_moves(board, player):
    """
    Get a list of all moves available to the player in the current board.

    @param board: the board state you want to evaluate.
    @param player: the player you are getting moves for.
    @return: A list of all the moves available to the given player on the
    given board.  If the board is invalid, the player has won, or the
    player's opponent has won, then there are no moves to make so an
    empty list is returned.
    """
    moves = []
    if not (
        player_has_won(board, player)
        or player_has_won(board, utils.get_opponent(player))
        or (not is_valid_board(board))
    ):
        for index in range(9):
            if board[index] == config.NO_PLAYER:
                moves += [index]
    return moves
Ejemplo n.º 13
0
def _minimax_score(board, player_current, player_main):
    winner = engine.get_winner(board)
    opponent = utils.get_opponent(player_current)

    if winner == player_main:
        return 10
    elif winner == opponent:
        return -10
    elif engine.is_board_full(board):
        return 0

    legal_moves = utils.get_legal_moves(board, player_current)
    scores = []

    for move in legal_moves:
        _board = copy.deepcopy(board)
        engine.make_move(_board, move, player_current)
        score = _minimax_score(_board, opponent, player_main)
        scores.append(score)

    if player_current == player_main:
        return max(scores)
    else:
        return min(scores)