/// <summary> /// Creates a subset of the actions excluding the actionToRemove. Creates a new set. /// </summary> /// <param name="actions">Usuable actions</param> /// <param name="actionToRemove">Action to exclude from this branch</param> private HashSet <GOAPAction> ActionSubset(HashSet <GOAPAction> actions, GOAPAction actionToRemove) { HashSet <GOAPAction> subset = GOAPPlannerHelper.GetFreeActionSet(); foreach (GOAPAction action in actions) { if (!action.Equals(actionToRemove)) { subset.Add(action); } } return(subset); }
/// <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); }