Search code examples
pythonartificial-intelligenceminimaxalpha-beta-pruning

What is going wrong with my Minimax Algorithm?


I tried to make a MiniMax AI using a tutorial,

The AI doesn't work and just goes on the bottom row and build up each time, reporting a column index of 0, 1, 2, 3, 4, 5, 6 and then for the next row and so on. The only thing I managed to find a lot different in the code output compared to mine and the tutorials working version was the depth of the minimax algorithm as it goes along. Where this was the depth of the working one as it recurred, and this was the depth of my one (it was longer than this but my console didn't keep all of it). I've tried a lot of things to get it working including reworking the board system to multiple lists inside a list and many other things like deleting some parts of the code and reworking scores but it doesn't seem to change.

My minimax function is:

def minimax(board, depth, alpha, beta, maximizingPlayer):
    print (depth)
    validLocations = getValidLocations(board)
    isTerminal = isTerminalNode(board)
    if depth == 0 or isTerminal:
        if isTerminal:
            if checkWin(board, computerDisc):
                return (None, math.inf)
            elif checkWin(board, playerDisc):
                return (None, -math.inf)
            else: # Game is over, no more spaces
                return (None, 0)
        else: # Depth is zero
            # print ("THIS IS DEPTH 0")
            return (None, scorePos(board, computerDisc))

    if maximizingPlayer:
        value = -math.inf
        column = random.choice(validLocations)
        for c in validLocations:
            boardCopy = copy.deepcopy(board)
            dropPiece(boardCopy, c, computerDisc)
            newScore = minimax(boardCopy, depth-1, alpha, beta, False)[1]
            if newScore > value:
                value = newScore
                column = c
            alpha = max(alpha, value)
            if alpha >= beta:
                break
        return (column, value)

    else: # Minimizing player
        value = math.inf
        column = random.choice(validLocations)
        for c in validLocations:
            boardCopy = copy.deepcopy(board)
            dropPiece(boardCopy, c, playerDisc)
            newScore = minimax(boardCopy, depth-1, alpha, beta, True)[1]
            if newScore < value:
                value = newScore
                column = c
            beta = min(beta, value)
            if alpha >= beta:
                break

        return (column, value)

And the tutorials function is:

def minimax(board, depth, alpha, beta, maximizingPlayer):
valid_locations = get_valid_locations(board)
is_terminal = is_terminal_node(board)
if depth == 0 or is_terminal:
    if is_terminal:
        if winning_move(board, AI_PIECE):
            return (None, 100000000000000)
        elif winning_move(board, PLAYER_PIECE):
            return (None, -10000000000000)
        else: # Game is over, no more valid moves
            return (None, 0)
    else: # Depth is zero
        return (None, score_position(board, AI_PIECE))
if maximizingPlayer:
    value = -math.inf
    column = random.choice(valid_locations)
    for col in valid_locations:
        row = get_next_open_row(board, col)
        b_copy = board.copy()
        drop_piece(b_copy, row, col, AI_PIECE)
        new_score = minimax(b_copy, depth-1, alpha, beta, False)[1]
        if new_score > value:
            value = new_score
            column = col
        alpha = max(alpha, value)
        if alpha >= beta:
            break
    return column, value

else: # Minimizing player
    value = math.inf
    column = random.choice(valid_locations)
    for col in valid_locations:
        row = get_next_open_row(board, col)
        b_copy = board.copy()
        drop_piece(b_copy, row, col, PLAYER_PIECE)
        new_score = minimax(b_copy, depth-1, alpha, beta, True)[1]
        if new_score < value:
            value = new_score
            column = col
        beta = min(beta, value)
        if alpha >= beta:
            break
    return column, value

When mine didn't work I tried to make it as close as possible to the tutorials function but it still doesn't seem to work. What do I need to do so it works?

The full programs: Mine: https://repl.it/@MyloBishop/Connect-4 Tutorials: https://github.com/KeithGalli/Connect4-Python/blob/master/connect4_with_ai.py


Solution

  • The board is passed passed to your minimax function as a parameter node, but inside the function you use board.

    Reference program: def minimax(board, depth, alpha, beta, maximizingPlayer):

    Your program: def minimax(node, depth, alpha, beta, maximizingPlayer):

    Your recursive minimax function is therefore not working as expected.

    Edit: To fix this replace board inside minimax with node (don't change node in the function definition to board)

    Edit 2: Also check the function scorePos - you have a hardcoded computerDisc instead of using the function argument.

    Edit 3: Additionally, other helper functions like isBoardFull() and isSpaceFree() should operate on the board copy, not the global variable.