protected virtual void OnDonePlanning(IReGoapGoal <T, W> newGoal) { startedPlanning = false; currentReGoapPlanWorker = default(ReGoapPlanWork <T, W>); if (newGoal == null) { if (currentGoal == null) { ReGoapLogger.LogWarning("GoapAgent " + this + " could not find a plan."); } return; } if (currentActionState != null) { currentActionState.Action.Exit(null); } currentActionState = null; currentGoal = newGoal; if (startingPlan != null) { for (int i = 0; i < startingPlan.Count; i++) { startingPlan[i].Action.PlanExit(i > 0 ? startingPlan[i - 1].Action : null, i + 1 < startingPlan.Count ? startingPlan[i + 1].Action : null, startingPlan[i].Settings, currentGoal.GetGoalState()); } } startingPlan = currentGoal.GetPlan().ToList(); ClearPlanValues(); for (int i = 0; i < startingPlan.Count; i++) { startingPlan[i].Action.PlanEnter(i > 0 ? startingPlan[i - 1].Action : null, i + 1 < startingPlan.Count ? startingPlan[i + 1].Action : null, startingPlan[i].Settings, currentGoal.GetGoalState()); } currentGoal.Run(WarnGoalEnd); PushAction(); }
private static double Profile(string description, Action func, int iterations = 100) { // from: http://stackoverflow.com/questions/1047218/benchmarking-small-code-samples-in-c-can-this-implementation-be-improved //Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; //Thread.CurrentThread.Priority = ThreadPriority.Highest; // warm up func(); var watch = new Stopwatch(); ReGoapLogger.Level = ReGoapLogger.DebugLevel.None; // clean up GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); watch.Start(); for (int i = 0; i < iterations; i++) { func(); } watch.Stop(); // clean up GC.Collect(); ReGoapLogger.Level = ReGoapLogger.DebugLevel.Full; ReGoapLogger.Log(string.Format("[Profile] {0} took {1}ms (iters: {2} ; avg: {3}ms).", description, watch.Elapsed.TotalMilliseconds, iterations, watch.Elapsed.TotalMilliseconds / iterations)); return(watch.Elapsed.TotalMilliseconds); }
protected virtual void OnDonePlanning(IReGoapGoal newGoal) { currentPlanWorker = null; if (newGoal == null) { if (currentGoal == null) { ReGoapLogger.LogWarning("GoapAgent " + this + " could not find a plan."); } return; } if (currentActionState != null) { currentActionState.Action.Exit(null); } currentActionState = null; currentGoal = newGoal; var plan = currentGoal.GetPlan(); startingPlan = plan.ToList(); ClearPlanValues(); foreach (var actionState in startingPlan) { actionState.Action.PostPlanCalculations(this); } currentGoal.Run(WarnGoalEnd); PushAction(); }
public IReGoapGoal Plan(IReGoapAgent agent, IReGoapGoal blacklistGoal = null, Queue <ReGoapActionState> currentPlan = null, Action <IReGoapGoal> callback = null) { ReGoapLogger.Log("[ReGoalPlanner] Starting planning calculation for agent: " + agent); goapAgent = agent; Calculated = false; currentGoal = null; var possibleGoals = new List <IReGoapGoal>(); foreach (var goal in goapAgent.GetGoalsSet()) { if (goal == blacklistGoal) { continue; } goal.Precalculations(this); if (goal.IsGoalPossible()) //goal.GetPriority() > bestPriority && { possibleGoals.Add(goal); } } possibleGoals.Sort((x, y) => x.GetPriority().CompareTo(y.GetPriority())); while (possibleGoals.Count > 0) { currentGoal = possibleGoals[possibleGoals.Count - 1]; possibleGoals.RemoveAt(possibleGoals.Count - 1); var goalState = currentGoal.GetGoalState(); var leaf = (BGoapNode)astar.Run( new BGoapNode(this, goalState, null, null), goapAgent.GetMemory().GetWorldState(), settings.MaxIterations, settings.PlanningEarlyExit); if (leaf == null) { currentGoal = null; continue; } var path = leaf.CalculatePath(); if (currentPlan != null && currentPlan == path) { currentGoal = null; break; } currentGoal.SetPlan(path); break; } Calculated = true; if (callback != null) { callback(currentGoal); } if (currentGoal != null) { ReGoapLogger.Log(string.Format("[ReGoapPlanner] Calculated plan for goal '{0}', plan length: {1}", currentGoal, currentGoal.GetPlan().Count)); } else { ReGoapLogger.LogWarning("[ReGoapPlanner] Error while calculating plan."); } return(currentGoal); }
public virtual void WarnGoalEnd(IReGoapGoal goal) { if (goal != currentGoal) { ReGoapLogger.LogWarning(string.Format("[GoapAgent] Goal {0} warned for end but is not current goal.", goal)); return; } CalculateNewGoal(); }
public void MainLoop() { while (isRunning) { threadEvents.WaitOne(); try { CheckWorkers(); } catch (Exception e) { ReGoapLogger.LogError(e.ToString()); } } }
public INode <T> Run(INode <T> start, T goal, int maxIterations = 100, bool earlyExit = true) { frontier.Clear(); stateToNode.Clear(); explored.Clear(); frontier.Enqueue(start, start.GetCost()); var iterations = 0; while ((frontier.Count > 0) && (iterations < maxIterations) && (frontier.Count + 1 < frontier.MaxSize)) { iterations++; var node = frontier.Dequeue(); if (node.IsGoal(goal)) { ReGoapLogger.Log("[Astar] Success iterations: " + iterations); return(node); } explored[node.GetState()] = node; foreach (var child in node.Expand()) { if (earlyExit && child.IsGoal(goal)) { ReGoapLogger.Log("[Astar] (early exit) Success iterations: " + iterations); return(child); } var childCost = child.GetCost(); var state = child.GetState(); if (explored.ContainsKey(state)) { continue; } INode <T> similiarNode; stateToNode.TryGetValue(state, out similiarNode); if (similiarNode != null) { if (similiarNode.GetCost() > childCost) { frontier.Remove(similiarNode); } else { break; } } frontier.Enqueue(child, childCost); stateToNode[state] = child; } } ReGoapLogger.LogWarning("[Astar] failed."); return(null); }
public virtual void WarnActionFailure(IReGoapAction thisAction) { if (thisAction != currentActionState.Action) { ReGoapLogger.LogWarning(string.Format("[GoapAgent] Action {0} warned for failure but is not current action.", thisAction)); return; } if (BlackListGoalOnFailure) { goalBlacklist[currentGoal] = Time.time + currentGoal.GetErrorDelay(); } CalculateNewGoal(true); }
private bool CheckIfStuck() { if (Time.time > stuckCheckCooldown) { stuckCheckCooldown = Time.time + StuckCheckDelay; if ((lastStuckCheckUpdatePosition - transform.position).magnitude < MaxStuckDistance) { ReGoapLogger.Log("[SmsGoTo] '" + name + "' is stuck."); return(true); } lastStuckCheckUpdatePosition = transform.position; } return(false); }
public override void Run(IReGoapAction previous, IReGoapAction next, IReGoapActionSettings settings, ReGoapState goalState, Action <IReGoapAction> done, Action <IReGoapAction> fail) { base.Run(previous, next, settings, goalState, done, fail); var workstation = agent.GetMemory().GetWorldState().Get <Workstation>("nearestWorkstation"); if (workstation.CraftResource(resourcesBag, recipe)) { ReGoapLogger.Log("[CraftRecipeAction] crafted recipe " + recipe.GetCraftedResource()); done(this); } else { fail(this); } }
public override void Run(IReGoapAction <string, object> previous, IReGoapAction <string, object> next, IReGoapActionSettings <string, object> settings, ReGoapState <string, object> goalState, Action <IReGoapAction <string, object> > done, Action <IReGoapAction <string, object> > fail) { base.Run(previous, next, settings, goalState, done, fail); var workstation = agent.GetMemory().GetWorldState().Get("nearestWorkstation") as Workstation; if (workstation != null && workstation.CraftResource(resourcesBag, recipe)) { ReGoapLogger.Log("[CraftRecipeAction] crafted recipe " + recipe.GetCraftedResource()); done(this); } else { fail(this); } }
public override void Run(IReGoapAction previous, IReGoapAction next, IReGoapActionSettings settings, ReGoapState goalState, Action <IReGoapAction> done, Action <IReGoapAction> fail) { base.Run(previous, next, settings, goalState, done, fail); SetNeededResources(settings); if (resource == null || resource.GetCapacity() < ResourcePerAction) { failCallback(this); } else { ReGoapLogger.Log("[GatherResourceAction] acquired " + ResourcePerAction + " " + resource.GetName()); resource.RemoveResource(ResourcePerAction); bag.AddResource(resource.GetName(), ResourcePerAction); doneCallback(this); } }
protected void Update() { if (resource == null || resource.GetCapacity() < ResourcePerAction) { failCallback(this); return; } if (Time.time > gatherCooldown) { gatherCooldown = float.MaxValue; ReGoapLogger.Log("[GatherResourceAction] acquired " + ResourcePerAction + " " + resource.GetName()); resource.RemoveResource(ResourcePerAction); bag.AddResource(resource.GetName(), ResourcePerAction); doneCallback(this); } }
// called in another thread private void OnDonePlan(ReGoapPlannerThread <T, W> plannerThread, ReGoapPlanWork <T, W> work, IReGoapGoal <T, W> newGoal) { work.NewGoal = newGoal; lock (doneWorks) { doneWorks.Add(work); } if (work.NewGoal != null && ReGoapLogger.Level == ReGoapLogger.DebugLevel.Full) { ReGoapLogger.Log("[GoapPlannerManager] Done calculating plan, actions list:"); var i = 0; foreach (var action in work.NewGoal.GetPlan()) { ReGoapLogger.Log(string.Format("{0}: {1}", i++, action.Action)); } } }
// called in another thread private void OnDonePlan(GoapPlannerThread plannerThread, PlanWork work, IReGoapGoal newGoal) { work.NewGoal = newGoal; lock (doneWorks) { doneWorks.Add(work); #if DEBUG if (work.NewGoal != null) { ReGoapLogger.Log("[GoapPlannerManager] Done calculating plan, actions list:"); var i = 0; foreach (var action in work.NewGoal.GetPlan()) { ReGoapLogger.Log(string.Format("{0}: {1}", i++, action.Action)); } } #endif } }
protected void Update() { if (resource == null || resource.GetCapacity() < ResourcePerAction) { failCallback(this); return; } if (Time.time > gatherCooldown) { gatherCooldown = float.MaxValue; ReGoapLogger.Log("[GatherResourceAction] acquired " + ResourcePerAction + " " + resource.GetName()); resource.RemoveResource(ResourcePerAction); bag.AddResource(resource.GetName(), ResourcePerAction); doneCallback(this); if (settings.HasKey("resource")) { ((IResource)settings.Get("resource")).Unreserve(GetHashCode()); } } }
protected virtual void Awake() { ReGoapNode <T, W> .Warmup(NodeWarmupCount); ReGoapState <T, W> .Warmup(StatesWarmupCount); ReGoapLogger.Level = LogLevel; if (Instance != null) { Destroy(this); var errorString = "[GoapPlannerManager] Trying to instantiate a new manager but there can be only one per scene."; ReGoapLogger.LogError(errorString); throw new UnityException(errorString); } Instance = this; doneWorks = new List <ReGoapPlanWork <T, W> >(); ReGoapPlannerThread <T, W> .WorksQueue = new Queue <ReGoapPlanWork <T, W> >(); planners = new ReGoapPlannerThread <T, W> [ThreadsCount]; threads = new Thread[ThreadsCount]; if (MultiThread) { ReGoapLogger.Log(String.Format("[GoapPlannerManager] Running in multi-thread mode ({0} threads).", ThreadsCount)); for (int i = 0; i < ThreadsCount; i++) { planners[i] = new ReGoapPlannerThread <T, W>(PlannerSettings, OnDonePlan); var thread = new Thread(planners[i].MainLoop); thread.Start(); threads[i] = thread; } } // no threads run else { ReGoapLogger.Log("[GoapPlannerManager] Running in single-thread mode."); planners[0] = new ReGoapPlannerThread <T, W>(PlannerSettings, OnDonePlan); } }
protected virtual void Awake() { if (Instance != null) { Destroy(this); var errorString = "[GoapPlannerManager] Trying to instantiate a new manager but there can be only one per scene."; ReGoapLogger.LogError(errorString); throw new UnityException(errorString); } Instance = this; doneWorks = new List <PlanWork>(); worksQueue = new Queue <PlanWork>(); planners = new GoapPlannerThread[ThreadsCount]; threads = new Thread[ThreadsCount]; threadEvents = new AutoResetEvent(false); if (ThreadsCount > 1) { ReGoapLogger.Log("[GoapPlannerManager] Running in multi-thread mode."); for (int i = 0; i < ThreadsCount; i++) { planners[i] = new GoapPlannerThread(threadEvents, PlannerSettings, worksQueue, OnDonePlan); var thread = new Thread(planners[i].MainLoop) { IsBackground = true }; thread.Start(); threads[i] = thread; } } // no threads run else { ReGoapLogger.Log("[GoapPlannerManager] Running in single-thread mode."); planners[0] = new GoapPlannerThread(threadEvents, PlannerSettings, worksQueue, OnDonePlan); } }
public IReGoapGoal Plan(IReGoapAgent agent, IReGoapGoal blacklistGoal = null, Queue <ReGoapActionState> currentPlan = null, Action <IReGoapGoal> callback = null) { ReGoapLogger.Log("[ReGoalPlanner] Starting planning calculation for agent: " + agent); goapAgent = agent; Calculated = false; currentGoal = null; var possibleGoals = new List <IReGoapGoal>(); foreach (var goal in goapAgent.GetGoalsSet()) { if (goal == blacklistGoal) { continue; } goal.Precalculations(this); if (goal.IsGoalPossible()) //goal.GetPriority() > bestPriority && { possibleGoals.Add(goal); } } possibleGoals.Sort((x, y) => x.GetPriority().CompareTo(y.GetPriority())); 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(); // 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(goapAgent, goalState); if (!action.CheckProceduralCondition(goapAgent, wantedGoalCheck)) { continue; } // check if the effects of all actions can archieve currentGoal var previous = wantedGoalCheck; wantedGoalCheck = new ReGoapState(); previous.MissingDifference(action.GetEffects(wantedGoalCheck), ref wantedGoalCheck); } // can't validate goal if (wantedGoalCheck.Count > 0) { currentGoal = null; continue; } } var leaf = (ReGoapNode)astar.Run( new ReGoapNode(this, goalState, null, null), goalState, settings.MaxIterations, settings.PlanningEarlyExit); if (leaf == null) { currentGoal = null; continue; } var path = leaf.CalculatePath(); if (currentPlan != null && currentPlan == path) { currentGoal = null; break; } currentGoal.SetPlan(path); break; } Calculated = true; if (callback != null) { callback(currentGoal); } if (currentGoal != null) { ReGoapLogger.Log(string.Format("[ReGoapPlanner] Calculated plan for goal '{0}', plan length: {1}", currentGoal, currentGoal.GetPlan().Count)); } else { ReGoapLogger.LogWarning("[ReGoapPlanner] Error while calculating plan."); } return(currentGoal); }
public INode <T> Run(INode <T> start, T goal, int maxIterations = 100, bool earlyExit = true, bool clearNodes = true, bool debugPlan = false) { _debugPlan = debugPlan; frontier.Clear(); stateToNode.Clear(); explored.Clear(); if (clearNodes) { ClearNodes(); createdNodes.Add(start); } frontier.Enqueue(start, start.GetCost()); _DebugPlan(start, null); var iterations = 0; while ((frontier.Count > 0) && (iterations < maxIterations) && (frontier.Count + 1 < frontier.MaxSize)) { var node = frontier.Dequeue(); Utilities.ReGoapLogger.Log(string.Format("\n++++Explored action: {0}({3}), state ({1})\n goal ({2})\n effect: ({4})", node.Name, node.GetState(), node.GoalString, node.GetCost(), node.EffectString)); if (node.IsGoal(goal)) { ReGoapLogger.Log("[Astar] Success iterations: " + iterations); _EndDebugPlan(node); return(node); } explored[node.GetState()] = node; foreach (var child in node.Expand()) { iterations++; if (clearNodes) { createdNodes.Add(child); } if (earlyExit && child.IsGoal(goal)) { ReGoapLogger.Log("[Astar] (early exit) Success iterations: " + iterations); _EndDebugPlan(child); return(child); } var childCost = child.GetCost(); var state = child.GetState(); if (explored.ContainsKey(state)) { continue; } INode <T> similiarNode; stateToNode.TryGetValue(state, out similiarNode); if (similiarNode != null) { if (similiarNode.GetCost() > childCost) { frontier.Remove(similiarNode); } else { break; } } _DebugPlan(child, node); Utilities.ReGoapLogger.Log(string.Format(" Enqueue frontier: {0}, cost: {1}", child.Name, childCost)); frontier.Enqueue(child, childCost); stateToNode[state] = child; } } string failReason = (frontier.Count <= 0 ? "Depleted Search Space. " : "") + ((iterations >= maxIterations) ? "Too many iter: " + iterations : "") + (frontier.Count + 1 >= frontier.MaxSize ? "FrontierQueue too large: " + frontier.MaxSize : ""); ReGoapLogger.LogWarning("[Astar] failed. " + failReason); _EndDebugPlan(null); return(null); }
public IReGoapGoal <T, W> Plan(IReGoapAgent <T, W> agent, IReGoapGoal <T, W> blacklistGoal = null, Queue <ReGoapActionState <T, W> > currentPlan = null, Action <IReGoapGoal <T, W> > callback = null) { if (ReGoapLogger.Level == ReGoapLogger.DebugLevel.Full) { ReGoapLogger.Log("[ReGoalPlanner] Starting planning calculation for agent: " + agent); } goapAgent = agent; Calculated = false; currentGoal = null; var possibleGoals = new List <IReGoapGoal <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())); 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(); // 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(goapAgent, goalState); if (!action.CheckProceduralCondition(goapAgent, wantedGoalCheck)) { continue; } // check if the effects of all actions can archieve currentGoal var previous = wantedGoalCheck; wantedGoalCheck = ReGoapState <T, W> .Instantiate(); previous.MissingDifference(action.GetEffects(wantedGoalCheck), ref wantedGoalCheck); } // can't validate goal if (wantedGoalCheck.Count > 0) { currentGoal = null; continue; } } //Utilities.ReGoapLogger.Log(string.Format("**** Goal: {0}, Expected State = ({1})", currentGoal.GetName(), goalState)); goalState = goalState.Clone(); var leaf = (ReGoapNode <T, W>)astar.Run( ReGoapNode <T, W> .Instantiate(this, goalState, null, null), goalState, settings.MaxIterations, settings.PlanningEarlyExit, debugPlan: agent.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; if (callback != null) { callback(currentGoal); } if (currentGoal != null) { ReGoapLogger.Log(string.Format("[ReGoapPlanner] Calculated plan for goal '{0}', plan length: {1}", currentGoal, currentGoal.GetPlan().Count)); if (ReGoapLogger.Level == ReGoapLogger.DebugLevel.Full) { int i = 0; foreach (var action in currentGoal.GetPlan()) { ReGoapLogger.Log(string.Format("[ReGoapPlanner] {0}) {1}", i++, action.Action)); } } } else { ReGoapLogger.LogWarning("[ReGoapPlanner] Error while calculating plan."); } return(currentGoal); }
public INode <T> Run(INode <T> start, T goal, int maxIterations = 100, bool earlyExit = true, bool clearNodes = true, bool debugPlan = false) { this.debugPlan = debugPlan; frontier.Clear(); stateToNode.Clear(); explored.Clear(); if (clearNodes) { ClearNodes(); createdNodes.Add(start); } frontier.Enqueue(start, start.GetCost()); DebugPlan(start, null); var iterations = 0; while ((frontier.Count > 0) && (iterations < maxIterations) && (frontier.Count + 1 < frontier.MaxSize)) { var node = frontier.Dequeue(); if (node.IsGoal(goal)) { ReGoapLogger.Log("[Astar] Success iterations: " + iterations); EndDebugPlan(node); return(node); } explored[node.GetState()] = node; foreach (var child in node.Expand()) { iterations++; if (clearNodes) { createdNodes.Add(child); } if (earlyExit && child.IsGoal(goal)) { ReGoapLogger.Log("[Astar] (early exit) Success iterations: " + iterations); EndDebugPlan(child); return(child); } var childCost = child.GetCost(); var state = child.GetState(); if (explored.ContainsKey(state)) { continue; } INode <T> similiarNode; stateToNode.TryGetValue(state, out similiarNode); if (similiarNode != null) { if (similiarNode.GetCost() > childCost) { frontier.Remove(similiarNode); } else { break; } } DebugPlan(child, node); //Utilities.ReGoapLogger.Log(string.Format(" Enqueue frontier: {0}, cost: {1}", child.Name, childCost)); frontier.Enqueue(child, childCost); stateToNode[state] = child; } } ReGoapLogger.LogWarning("[Astar] failed."); EndDebugPlan(null); return(null); }