def negamax(board, player_to_move): """Use a variation of the Negamax algorithm to choose the next move. Recursively determine the best next move for the given player. Return a tuple containing the score and the board index of the move (chosen randomly if there are several best moves). The score is the likely outcome of the game on that line of play: -1 for a loss, 0 for a draw, 1 for a win. Source: http://en.wikipedia.org/wiki/Negamax. """ # Stop recursing if you just lost. That's the worst possible outcome. if rules.getWinner(board) == rules.getOpposite(player_to_move): return (-1, None) # Second stop case: a cat's game, no moves left. if rules.isFull(board): return (0, None) # Make a pretend move in each legal square and see how it turns out. best_score = -1 best_moves = [] for s in rules.getOpenSquares(board): new_board = copy.deepcopy(board) new_board[s] = player_to_move # Get the best response to this move. Don't care what it was, just # score it. score, _ = negamax(new_board, rules.getOpposite(player_to_move)) # The score for you is the opposite of the score for the other player. score *= -1 if score == 1: # That move led to a win, so return it return (1, s) elif score > best_score: best_score = score best_moves = [s] elif score == best_score: best_moves.append(s) assert best_moves return (best_score, random.choice(best_moves))
player_char = 'o' comp_char = 'x' board = [' '] * 9 winner = None first_move = True legend = "123456789" rules.printBoard(legend) print "\nComputer goes first\n" while not winner and not rules.isFull(board): # On the first turn, skip the human player to let the computer go first. if not first_move: # Player's turn board[ai.humanPlayer(board)] = player_char winner = rules.getWinner(board) # Computer's turn if not winner and not rules.isFull(board): if first_move: board[ai.firstMove()] = comp_char else: # Don't care what the score was, just take the best move. _, move = ai.negamax(board, comp_char) assert move is not None board[move] = comp_char winner = rules.getWinner(board) # Either the game just ended or we're on to the next round. first_move = False rules.printBoard(board)