示例#1
0
 /// <summary>
 /// Crears all values.
 /// </summary>
 private void Clear()
 {
     this._parent      = null;
     this._runningCost = 0;
     this._weight      = 0;
     this._state       = null;
     this._action      = null;
 }
示例#2
0
 /// <summary>
 /// Reinitializes node with new values.
 /// </summary>
 public void Reinitialize(GOAPNode parent, float runningCost, float weight, Dictionary <string, bool> state,
                          GOAPAction action)
 {
     Clear();
     this._parent      = parent;
     this._runningCost = runningCost;
     this._weight      = weight;
     this._state       = state;
     this._action      = action;
 }
示例#3
0
        /// <summary>
        /// Compares nodes.
        /// </summary>
        /// <param name="valueToCompareWith"></param>
        public bool BetterThen(GOAPNode valueToCompareWith)
        {
            if (_weight > valueToCompareWith._weight && _runningCost < valueToCompareWith._runningCost)
            {
                return(true);
            }

            if (_weight < valueToCompareWith._weight && _runningCost > valueToCompareWith._runningCost)
            {
                return(false);
            }

            // Make weight > cost.
            bool better = (_weight / valueToCompareWith._weight - 1) >= (_runningCost / valueToCompareWith._runningCost - 1);

            return(better);
        }
示例#4
0
        /// <summary>
        /// Reinitializes free node, turns it into used one and returns it. If there is not enough free nodes, creates a new one.
        /// </summary>
        public static GOAPNode GetFreeNode(GOAPNode parent, float runningCost, float weight, Dictionary <string, bool> state,
                                           GOAPAction action)
        {
            GOAPNode free = null;

            if (_freeNodes.Count <= 0)
            {
                free = new GOAPNode(parent, runningCost, weight, state, action);
            }
            else
            {
                free = _freeNodes.Pop();
                free.Reinitialize(parent, runningCost, weight, state, action);
            }

            _usedNodes.Push(free);
            return(free);
        }
示例#5
0
        /// <summary>
        /// Builds the plan of actions. Returns true if at least one solution was found.
        /// The possible paths are stored in the leaves list. Each leaf has a 'runningCost' value where the lowest cost will be the best action sequence.
        /// </summary>
        /// <param name="parent">Parent node</param>
        /// <param name="leaves">List of nodes with possible paths</param>
        /// <param name="usableActions">Actions available to the GOAPAgent</param>
        /// <param name="goal">Goal that GOAPAgent is trying to achieve</param>
        private bool BuildGraph(GOAPNode parent, List <GOAPNode> leaves, HashSet <GOAPAction> usableActions, KeyValuePair <string, bool> goal)
        {
            bool foundOne = false;

            // Go through each action available at this node and see if we can use it here.
            foreach (GOAPAction action in usableActions)
            {
                // If the parent state has the conditions for this action's preconditions, we can use it here.
                if (InState(action.Preconditions, parent._state))
                {
                    // Apply the action's effects to the parent state.
                    Dictionary <string, bool> currentState = PopulateState(parent._state, action.Effects);
                    GOAPNode node = GOAPPlannerHelper.GetFreeNode(parent, parent._runningCost + action.GetCost(), parent._weight + action.GetWeight(), currentState, action);

                    // If there's no match between child's precondition and parent's effects or child's precondition is empty.
                    if (parent._action != null && (action.Preconditions.Count == 0 || !CondRelation(action.Preconditions, parent._action.Effects)))
                    {
                        continue;
                    }

                    if (GoalInState(goal, currentState))
                    {
                        // There is a solution.
                        leaves.Add(node);
                        foundOne = true;
                    }
                    else
                    {
                        // Not at a solution yet, so we're testing all of the remaining actions and branching out the tree.
                        HashSet <GOAPAction> subset = ActionSubset(usableActions, action);
                        bool found = BuildGraph(node, leaves, subset, goal);
                        if (found)
                        {
                            foundOne = true;
                        }
                    }
                }
            }

            return(foundOne);
        }
示例#6
0
        /// <summary>
        /// Plans what sequence of actions can fulfill the goal.
        /// Returns null if a plan could not be found, or a list of the actions that must be performed, in order, to fulfill the goal.
        /// </summary>
        /// <param name="agent">GOAPAgent</param>
        /// <param name="availableActions">Actions that can be performed</param>
        /// <param name="worldState">Starting world state</param>
        /// <param name="goal">Goal that GOAPAgent is trying to achieve</param>
        /// <param name="AIAgent">Implementing class that provides our world data and listens to feedback on planning</param>
        public Queue <GOAPAction> Plan(GameObject agent,
                                       HashSet <GOAPAction> availableActions,
                                       Dictionary <string, bool> worldState,
                                       KeyValuePair <string, bool> goal,
                                       IAIAgent AIAgent)
        {
            // Reset all of the actions that can be performed.
            foreach (GOAPAction action in availableActions)
            {
                action.DoReset();
            }

            // Loops through the available actions and adds the ones that can be performed to a list.
            HashSet <GOAPAction> usableActions = GOAPPlannerHelper.GetFreeActionSet();

            foreach (GOAPAction action in availableActions)
            {
                // If the the action can be performed.
                if (action.CheckProceduralPrecondition(agent, AIAgent.DataHolder))
                {
                    usableActions.Add(action);
                }
            }

            // Create a "tree" of actions that will lead to the wanted goal.
            List <GOAPNode> leaves  = new List <GOAPNode>();
            GOAPNode        start   = GOAPPlannerHelper.GetFreeNode(null, 0, 0, worldState, null);
            bool            success = BuildGraph(start, leaves, usableActions, goal);

            if (!success)
            {
                return(null);
            }

            // Find the cheapest plan of action out of each generated plan.
            GOAPNode cheapest = null;

            foreach (GOAPNode leaf in leaves)
            {
                if (cheapest == null)
                {
                    cheapest = leaf;
                }
                else
                {
                    if (leaf.BetterThen(cheapest))
                    {
                        cheapest = leaf;
                    }
                }
            }

            // Get its node and work back through the parents.
            List <GOAPAction> result = new List <GOAPAction>();
            GOAPNode          n      = cheapest;

            while (n != null)
            {
                if (n._action != null)
                {
                    // Insert the action in the front.
                    result.Insert(0, n._action);
                }
                n = n._parent;
            }

            // Clean up after we're done.
            GOAPPlannerHelper.Release();

            // Create a final plan to follow.
            Queue <GOAPAction> finalQueue = new Queue <GOAPAction>();

            foreach (GOAPAction action in result)
            {
                finalQueue.Enqueue(action);
            }

            return(finalQueue);
        }
示例#7
0
 /// <summary>
 /// Constructor.
 /// </summary>
 public GOAPNode(GOAPNode parent, float runningCost, float weight, Dictionary <string, bool> state,
                 GOAPAction action)
 {
     _ID = MaxID++;
     Reinitialize(parent, runningCost, weight, state, action);
 }