// keep only missing differences in values public int ReplaceWithMissingDifference(GoapState <T, W> other, int stopAt = int.MaxValue, Func <KeyValuePair <T, W>, W, bool> predicate = null, bool test = false) { lock (values) { var count = 0; var buffer = values; values = values == bufferA ? bufferB : bufferA; values.Clear(); foreach (var pair in buffer) { W otherValue; other.values.TryGetValue(pair.Key, out otherValue); if (!Equals(pair.Value, otherValue) && (predicate == null || predicate(pair, otherValue))) { count++; values[pair.Key] = pair.Value; if (count >= stopAt) { break; } } } return(count); } }
// write differences in "difference" public int MissingDifference(GoapState <T, W> other, ref GoapState <T, W> difference, int stopAt = int.MaxValue, Func <KeyValuePair <T, W>, W, bool> predicate = null, bool test = false) { lock (values) { var count = 0; foreach (var pair in values) { W otherValue; other.values.TryGetValue(pair.Key, out otherValue); if (!Equals(pair.Value, otherValue) && (predicate == null || predicate(pair, otherValue))) { count++; if (difference != null) { difference.values[pair.Key] = pair.Value; } if (count >= stopAt) { break; } } } return(count); } }
public void AddFromState(GoapState <T, W> b) { lock (values) lock (b.values) { foreach (var pair in b.values) { values[pair.Key] = pair.Value; } } }
private void Init(GoapState <T, W> old) { values.Clear(); if (old != null) { lock (old.values) { foreach (var pair in old.values) { values[pair.Key] = pair.Value; } } } }
public static GoapState <T, W> Instantiate(GoapState <T, W> old = null) { GoapState <T, W> state; if (cachedStates == null) { cachedStates = new Stack <GoapState <T, W> >(); } lock (cachedStates) { state = cachedStates.Count > 0 ? cachedStates.Pop() : new GoapState <T, W>(); } state.Init(old); return(state); }
public bool HasAny(GoapState <T, W> other) { lock (values) lock (other.values) { foreach (var pair in other.values) { W thisValue; values.TryGetValue(pair.Key, out thisValue); if (Equals(thisValue, pair.Value)) { return(true); } } return(false); } }
public int MissingDifference(GoapState <T, W> other, int stopAt = int.MaxValue) { lock (values) { var count = 0; foreach (var pair in values) { W otherValue; other.values.TryGetValue(pair.Key, out otherValue); if (!Equals(pair.Value, otherValue)) { count++; if (count >= stopAt) { break; } } } return(count); } }
public bool HasAnyConflict(GoapState <T, W> other) // used only in backward for now { lock (values) lock (other.values) { foreach (var pair in other.values) { var otherValue = pair.Value; // not here, ignore this check W thisValue; if (!values.TryGetValue(pair.Key, out thisValue)) { continue; } if (!Equals(otherValue, thisValue)) { return(true); } } return(false); } }
// this method is more relaxed than the other, also accepts conflits that are fixed by "changes" public bool HasAnyConflict(GoapState <T, W> changes, GoapState <T, W> other) { lock (values) lock (other.values) { foreach (var pair in other.values) { var otherValue = pair.Value; // not here, ignore this check W thisValue; if (!values.TryGetValue(pair.Key, out thisValue)) { continue; } W effectValue; changes.values.TryGetValue(pair.Key, out effectValue); if (!Equals(otherValue, thisValue) && !Equals(effectValue, thisValue)) { return(true); } } return(false); } }
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); }