Пример #1
0
    // Searches the world for an action
    public ActionWithFiller ComputeBestAction(World world, WorldAction currentFillerAction,
                                              int currentPathIndex)
    {
        WorldAction bestAction        = WorldAction.NoAction;
        WorldAction bestFillerAction  = WorldAction.NoAction;
        float       bestActionUtility = float.MinValue;

        // Determine which actions are possible
        World.Player       currentPlayer   = playerNum == 1 ? world.Player1 : world.Player2;
        List <WorldAction> possibleActions = currentPlayer.GetPossibleActions();

        // Choose maximum-utility action out of all possibilies
        foreach (WorldAction action in possibleActions)
        {
            // Make a new clone of the world to run a simulated step
            World        newState         = world.Clone();
            World.Player newCurrentPlayer = playerNum == 1 ? newState.Player1 : newState.Player2;

            newCurrentPlayer.Advance(new List <WorldAction>()
            {
                action
            });
            newState.Advance(emptyList, false, false);
            //currentPathIndex = PathIndexFunction(newCurrentPlayer, currentPathIndex);

            // Decide filler action and do it repeatedly
            WorldAction        potentialFillerAction = FillerActionFunction(action, currentFillerAction);
            List <WorldAction> fillerActionList      = new List <WorldAction>()
            {
                potentialFillerAction
            };
            for (int i = 0; i < StepSize - 1; i++)
            {
                newCurrentPlayer.Advance(fillerActionList);
                newState.Advance(emptyList, false, false);
                //currentPathIndex = PathIndexFunction(newCurrentPlayer, currentPathIndex);
            }

            // Calculate utility and update maximum
            //float utility = 0.0f;
            float utility = calculateUtility(newState, 0, true, float.MinValue, float.MaxValue, potentialFillerAction,
                                             currentPathIndex);

            if (utility > bestActionUtility)
            {
                bestAction        = action;
                bestFillerAction  = potentialFillerAction;
                bestActionUtility = utility;
            }
        }

        return(new ActionWithFiller(bestAction, bestFillerAction));
    }
Пример #2
0
    // Calculates the utility of a state
    protected float calculateUtility(World state, int depth, bool isOpponentsTurn, float alpha, float beta,
                                     WorldAction prevFillerAction, int currentPathIndex)
    {
        // Check if terminal and return terminal utility
        if (state.IsTerminal())
        {
            float p1sTermUtil = state.TerminalUtility();
            return(playerNum == 1 ? p1sTermUtil : -p1sTermUtil);
        }

        // Use heuristic for over max depth
        if (depth > SearchDepth)
        {
            // Uncomment below to check heuristic bounds between -1 and 1
            //float h = Heuristic(state, currentPathIndex);
            //if (h > 1.0f || h < -1.0f) Debug.LogWarning("Heuristic has magnitude greater than 1!");
            //return h;
            return(Heuristic(state, currentPathIndex));
        }

        if (isOpponentsTurn)
        {
            // Determine which actions are possible
            World.Player       currentPlayer   = playerNum == 1 ? state.Player2 : state.Player1;
            List <WorldAction> possibleActions = currentPlayer.GetPossibleActions();

            // Minimize utility
            float minUtil = float.MaxValue;

            // Find utility of possible actions
            foreach (WorldAction action in possibleActions)
            {
                // Make a new clone of the world to run a simulated step of *only the opponent*
                World        newState         = state.Clone();
                World.Player newCurrentPlayer = playerNum == 1 ? newState.Player2 : newState.Player1;
                newCurrentPlayer.Advance(new List <WorldAction>()
                {
                    action
                });

                // Do filler action
                WorldAction        potentialFillerAction = FillerActionFunction(action, prevFillerAction);
                List <WorldAction> fillerActionList      = new List <WorldAction>()
                {
                    potentialFillerAction
                };
                for (int i = 0; i < StepSize - 1; i++)
                {
                    newCurrentPlayer.Advance(fillerActionList);
                }

                // Calculate utility and update minimum
                float utility = calculateUtility(newState, depth + 1, false, alpha, beta, potentialFillerAction,
                                                 currentPathIndex);
                if (utility < minUtil)
                {
                    minUtil = utility;

                    // Alpha check
                    if (minUtil <= alpha)
                    {
                        return(minUtil);
                    }

                    // Beta update
                    if (minUtil < beta)
                    {
                        beta = minUtil;
                    }
                }
            }

            return(minUtil);
        }
        else
        {
            // Determine which actions are possible
            World.Player       currentPlayer   = playerNum == 1 ? state.Player1 : state.Player2;
            List <WorldAction> possibleActions = currentPlayer.GetPossibleActions();

            // Maximize utility
            float maxUtil = float.MinValue;

            // Find utility of possible actions
            foreach (WorldAction action in possibleActions)
            {
                // Make a new clone of the world to run a simulated step with *player and projectiles*
                World        newState         = state.Clone();
                World.Player newCurrentPlayer = playerNum == 1 ? newState.Player1 : newState.Player2;
                newCurrentPlayer.Advance(new List <WorldAction>()
                {
                    action
                });
                newState.Advance(emptyList, false, false);
                //currentPathIndex = PathIndexFunction(newCurrentPlayer, currentPathIndex);

                // Do filler action
                WorldAction        potentialFillerAction = FillerActionFunction(action, prevFillerAction);
                List <WorldAction> fillerActionList      = new List <WorldAction>()
                {
                    potentialFillerAction
                };
                for (int i = 0; i < StepSize - 1; i++)
                {
                    newCurrentPlayer.Advance(fillerActionList);
                    newState.Advance(emptyList, false, false);
                    //currentPathIndex = PathIndexFunction(newCurrentPlayer, currentPathIndex);
                }

                // Calculate utility and update maximum
                float utility = calculateUtility(newState, depth + 1, true, alpha, beta, potentialFillerAction,
                                                 currentPathIndex);
                if (utility > maxUtil)
                {
                    maxUtil = utility;

                    // Beta check
                    if (maxUtil >= beta)
                    {
                        return(maxUtil);
                    }

                    // Alpha update
                    if (maxUtil > alpha)
                    {
                        alpha = maxUtil;
                    }
                }
            }

            return(maxUtil);
        }
    }