public IGoapGoal Plan(IGoapAgent agent) { m_agent = agent; m_currentGoal = null; List <IGoapGoal> possibleGoals = GetPossibleGoals(agent); if (possibleGoals.Count == 0) { GoapLogger.LogWarning("[ReGoapPlanner] Agent does not have any Goals to perform. " + m_agent.GetName()); } while (possibleGoals.Count > 0) { m_currentGoal = possibleGoals[possibleGoals.Count - 1]; possibleGoals.RemoveAt(possibleGoals.Count - 1); if (CanFullfillWithActions(m_agent, m_currentGoal) == false) { //No actions can't handle this goal GoapLogger.LogWarning("GoalPlanner :: No Actions to handle Goal (" + m_currentGoal.GetName() + ")"); m_currentGoal = null; continue; } GoapState targetState = m_currentGoal.GetGoalState(agent); GoapNode <GoapState> leaf = (GoapNode <GoapState>)m_aStar.Run(GoapNode <GoapState> .Instantiate(this, targetState, null, null), targetState); if (leaf == null) { GoapLogger.LogWarning("GoapPlanner :: Pathfinding failed!"); m_currentGoal = null; continue; } Queue <IGoapAction> actions = leaf.CalculatePath(); if (actions.Count == 0) { GoapLogger.LogWarning("GoapPlanner :: Calculating Path failed!"); m_currentGoal = null; continue; } m_currentGoal.SetPlan(actions); break; } if (m_currentGoal != null) { GoapLogger.Log(string.Format("[ReGoapPlanner] Calculated plan for goal '{0}', plan length: {1}", m_currentGoal, m_currentGoal.GetPlan().Count)); } else { GoapLogger.LogWarning("[ReGoapPlanner] Error while calculating plan."); } return(m_currentGoal); }
public IGoapGoal <T, W> Plan(IGoapAgent <T, W> agent, IGoapGoal <T, W> blacklistGoal = null, Queue <GoapActionState <T, W> > currentPlan = null, Action <IGoapGoal <T, W> > callback = null) { if (GoapLogger.Level == GoapLogger.DebugLevel.Full) { GoapLogger.Log("[ReGoalPlanner] Starting planning calculation for agent: " + agent); } goapAgent = agent; Calculated = false; currentGoal = null; var possibleGoals = new List <IGoapGoal <T, W> >(); foreach (var goal in goapAgent.GetGoalsSet()) { if (goal == blacklistGoal) { continue; } goal.Precalculations(this); if (goal.IsGoalPossible()) { possibleGoals.Add(goal); } } possibleGoals.Sort((x, y) => x.GetPriority().CompareTo(y.GetPriority())); var currentState = agent.GetMemory().GetWorldState(); while (possibleGoals.Count > 0) { currentGoal = possibleGoals[possibleGoals.Count - 1]; possibleGoals.RemoveAt(possibleGoals.Count - 1); var goalState = currentGoal.GetGoalState(); // can't work with dynamic actions, of course if (!settings.UsingDynamicActions) { var wantedGoalCheck = currentGoal.GetGoalState(); GoapActionStackData <T, W> stackData; stackData.agent = goapAgent; stackData.currentState = currentState; stackData.goalState = goalState; stackData.next = null; stackData.settings = null; // we check if the goal can be archived through actions first, so we don't brute force it with A* if we can't foreach (var action in goapAgent.GetActionsSet()) { action.Precalculations(stackData); if (!action.CheckProceduralCondition(stackData)) { continue; } // check if the effects of all actions can archieve currentGoal var previous = wantedGoalCheck; wantedGoalCheck = GoapState <T, W> .Instantiate(); previous.MissingDifference(action.GetEffects(stackData), ref wantedGoalCheck); } // finally push the current world state var current = wantedGoalCheck; wantedGoalCheck = GoapState <T, W> .Instantiate(); current.MissingDifference(GetCurrentAgent().GetMemory().GetWorldState(), ref wantedGoalCheck); // can't validate goal if (wantedGoalCheck.Count > 0) { currentGoal = null; continue; } } goalState = goalState.Clone(); var leaf = (GoapNode <T, W>)astar.Run( GoapNode <T, W> .Instantiate(this, goalState, null, null, null), goalState, settings.MaxIterations, settings.PlanningEarlyExit, debugPlan: settings.DebugPlan); if (leaf == null) { currentGoal = null; continue; } var result = leaf.CalculatePath(); if (currentPlan != null && currentPlan == result) { currentGoal = null; break; } if (result.Count == 0) { currentGoal = null; continue; } currentGoal.SetPlan(result); break; } Calculated = true; callback?.Invoke(currentGoal); if (currentGoal != null) { GoapLogger.Log(string.Format("[ReGoapPlanner] Calculated plan for goal '{0}', plan length: {1}", currentGoal, currentGoal.GetPlan().Count)); if (GoapLogger.Level == GoapLogger.DebugLevel.Full) { int i = 0; GoapActionStackData <T, W> stackData; stackData.agent = agent; stackData.currentState = currentState; stackData.goalState = currentGoal.GetGoalState(); stackData.next = null; foreach (var action in currentGoal.GetPlan()) { stackData.settings = action.Settings; GoapLogger.Log(string.Format("[ReGoapPlanner] {0}) {1}", i++, action.Action.ToString(stackData))); } } } else { GoapLogger.LogWarning("[ReGoapPlanner] Error while calculating plan."); } return(currentGoal); }