예제 #1
0
    def _minimax(self, root_move: tuple[int, int], depth: int,
                 game: ReversiGame, alpha: float, beta: float) -> GameTree:
        """
        _minimax is a minimax function with alpha-beta pruning implemented that returns
        a full GameTree where each node stores the given evaluation

        Preconditions
            - depth >= 0
        """
        white_move = (game.get_current_player() == -1)
        ret = GameTree(move=root_move, is_white_move=white_move)
        # early return at max depth
        if depth == self.depth:
            ret.evaluation = heuristic(game, self.heuristic_list)
            return ret
        possible_moves = list(game.get_valid_moves())
        if not possible_moves:
            if game.get_winner() == 'white':
                ret.evaluation = 10000
            elif game.get_winner() == 'black':
                ret.evaluation = -10000
            else:
                ret.evaluation = 0
            return ret
        random.shuffle(possible_moves)
        best_value = float('-inf')
        if not white_move:
            best_value = float('inf')
        for move in possible_moves:
            new_game = game.copy_and_make_move(move)
            new_tree = self._minimax(move, depth + 1, new_game, alpha, beta)
            ret.add_subtree(new_tree)
            # we update the alpha value when the maximizer is playing (white)
            if white_move and best_value < new_tree.evaluation:
                best_value = new_tree.evaluation
                alpha = max(alpha, best_value)
                if beta <= alpha:
                    break
            # we update the beta value when the minimizer is playing (black)
            elif not white_move and best_value > new_tree.evaluation:
                best_value = new_tree.evaluation
                beta = min(beta, best_value)
                if beta <= alpha:
                    break
        ret.evaluation = best_value
        return ret
예제 #2
0
 def _minimax(self, root_move: tuple[int, int], game: ReversiGame,
              depth: int) -> GameTree:
     """
     _minimax is a function that returns a tree where each node has a value determined by
     the minimax search algorithm
     """
     white_move = (game.get_current_player() == -1)
     ret = GameTree(move=root_move, is_white_move=white_move)
     # early return if we have reached max depth
     if depth == self.depth:
         ret.evaluation = heuristic(game, self.heuristic_list)
         return ret
     possible_moves = list(game.get_valid_moves())
     # game is over if there are no possible moves in a position
     if not possible_moves:
         # if there are no moves, then the game is over so we check for the winner
         if game.get_winner() == 'white':
             ret.evaluation = 10000
         elif game.get_winner() == 'black':
             ret.evaluation = -10000
         else:
             ret.evaluation = 0
         return ret
     # shuffle for randomness
     random.shuffle(possible_moves)
     # best_value tracks the best possible move that the player can make
     # this value is maximized by white and minimized by black
     best_value = float('-inf')
     if not white_move:
         best_value = float('inf')
     for move in possible_moves:
         new_game = game.copy_and_make_move(move)
         new_subtree = self._minimax(move, new_game, depth + 1)
         if white_move:
             best_value = max(best_value, new_subtree.evaluation)
         else:
             best_value = min(best_value, new_subtree.evaluation)
         ret.add_subtree(new_subtree)
     # update the evaluation value of the tree once all subtrees are added
     ret.evaluation = best_value
     return ret