// ========================================================= DECOMPOSITION /// <summary> /// In an Invert Status decomposition, we invert success/failure. /// Note that Rejected is still returned as Rejected. /// Note that Partial is still returned as Partial (it doesn't really make sense to use with this selector). /// </summary> /// <param name="ctx"></param> /// <returns></returns> protected override DecompositionStatus OnDecompose(IContext ctx, int startIndex, out Queue <ITask> result) { Plan.Clear(); for (var taskIndex = startIndex; taskIndex < Subtasks.Count; taskIndex++) { var task = Subtasks[taskIndex]; var status = OnDecomposeTask(ctx, task, taskIndex, null, out result); switch (status) { case DecompositionStatus.Succeeded: return(DecompositionStatus.Failed); // We treat this as a selector and will try until we decompose successfully case DecompositionStatus.Failed: continue; } // Rejected or Partial is not inverted. return(status); } // If we failed to find a valid decomposition, we revert to Success. result = Plan; return(DecompositionStatus.Succeeded); }
// ========================================================= DECOMPOSITION protected override DecompositionStatus OnDecompose(IContext ctx, int startIndex, out Queue <ITask> result) { Plan.Clear(); var leaves = ctx.Factory.CreateList <GOAPNode>(); var start = ctx.Factory.Create <GOAPNode>(); { start.Parent = null; start.RunningCost = 0f; start.Task = null; } if (TryBuildGraph(ctx, start, leaves, Subtasks)) { GeneratePlan(ctx, GetCheapestLeaf(leaves)); } foreach (var leaf in leaves) { FreeNode(ctx, leaf); } ctx.Factory.FreeList(ref leaves); result = Plan; return(result.Count == 0 ? DecompositionStatus.Failed : DecompositionStatus.Succeeded); }
private bool BuildPlan(Room room) { Plan.Clear(); HashSet <Room> explored = new HashSet <Room>(); Queue <GraphNode> frontier = new Queue <GraphNode>(); GraphNode node = new GraphNode(room, null, AgentAction.NONE); frontier.Enqueue(node); do { if (!frontier.TryDequeue(out node)) { return(false); } List <GraphNode> newNodes = DiscoverSurroundingNodes(node); explored.Add(node.Room); newNodes.RemoveAll(n => explored.Contains(n.Room)); foreach (GraphNode newNode in newNodes) { frontier.Enqueue(newNode); } } while(!node.Room.IsDirty); Plan.Push(AgentAction.CLEAN); while (node.Parent != null) { Plan.Push(node.Action); node = node.Parent; } return(true); }
// ========================================================= DECOMPOSITION /// <summary> /// In an Always Succeed decomposition, we always return success. This allows it to be used /// as an "optional" branch during decomposition, without invalidating a Sequence. /// Note that this selector makes sense only in a Sequence. /// </summary> /// <param name="ctx"></param> /// <returns></returns> protected override DecompositionStatus OnDecompose(IContext ctx, int startIndex, out Queue <ITask> result) { Plan.Clear(); result = null; for (var taskIndex = startIndex; taskIndex < Subtasks.Count; taskIndex++) { var task = Subtasks[taskIndex]; var status = OnDecomposeTask(ctx, task, taskIndex, null, out result); // Even though we always return success, we still treat this as a selector. if (status == DecompositionStatus.Failed) { continue; } break; } if (result == null) { result = Plan; } return(DecompositionStatus.Succeeded); }
public When_appending_a_step_and_no_builtin_steps_are_there() { When(() => { Plan.Clear(); Plan.Add <MyEquivalencyStep>(); }); }
// ========================================================= DECOMPOSITION /// <summary> /// In a Random Selector decomposition, we simply select a sub-task randomly, and stick with it for the duration of the /// plan as if it was the only sub-task. /// So if the sub-task fail to decompose, that means the entire Selector failed to decompose (we don't try to decompose /// any other sub-tasks). /// Because of the nature of the Random Selector, we don't do any MTR tracking for it, since it doesn't do any real /// branching. /// </summary> /// <param name="ctx"></param> /// <returns></returns> protected override DecompositionStatus OnDecompose(IContext ctx, int startIndex, out Queue <ITask> result) { Plan.Clear(); var taskIndex = _random.Next(startIndex, Subtasks.Count); var task = Subtasks[taskIndex]; return(OnDecomposeTask(ctx, task, taskIndex, null, out result)); }
// ========================================================= DECOMPOSITION /// <summary> /// In a Utility Selector decomposition, we select a single sub-task based on utility theory. /// If the sub-task fail to decompose, that means the entire Selector failed to decompose (we don't try to decompose /// any other sub-tasks). /// Because of the nature of the Utility Selector, we don't do any MTR tracking for it, since it doesn't do any real /// branching. /// </summary> /// <param name="ctx"></param> /// <returns></returns> protected override DecompositionStatus OnDecompose(IContext ctx, int startIndex, out Queue <ITask> result) { Plan.Clear(); var task = FindBestTask(ctx, startIndex, out var taskIndex); if (task == null) { result = Plan; return(DecompositionStatus.Failed); } return(OnDecomposeTask(ctx, task, taskIndex, null, out result)); }
public void Reset() { foreach (var t in wf.Tasks) { t.ScheduledInstance = null; } Plan.Clear(); Wrappers = TaskScheduler.GenerateWrappers(wf); Estimations = TaskScheduler.MakeOverallEstimations(wf, Wrappers); if (!IgnoreNonUrgentTasks) { var additions = new Dictionary <int, List <ActiveEstimatedTask> >(); for (var i = 0; i < Estimations.Count; i++) { var ests = Estimations[i]; var busyEsts = ests.Where(e => { var busyNodes = e.Estimation.NodesTimings.Where(n => n.LaunchedTask != null).ToArray(); if (!busyNodes.Any()) { return(false); } var maxUrgentTime = busyNodes.Max(n => n.LaunchedTask.IsUrgent ? n.LaunchedTask.Estimation.Result.Time : 0); return(busyNodes.Any(n => !n.LaunchedTask.IsUrgent && n.LaunchedTask.Estimation.Result.Time > maxUrgentTime)); }); foreach (var e in busyEsts.ToArray()) { additions.GetOrCreateValue(i, () => new List <ActiveEstimatedTask>()).Add(new ActiveEstimatedTask(e) { IgnoreNonUrgent = false }); } } foreach (var p in additions) { (Estimations[p.Key] as List <ActiveEstimatedTask>).AddRange(p.Value); } } }
protected override DecompositionStatus OnDecompose(IContext ctx, int startIndex, out Queue <ITask> result) { Plan.Clear(); if (IsValidWorldStateIndex(ctx) == false) { result = Plan; return(DecompositionStatus.Failed); } var repetitions = ctx.GetState((int)WorldStateIndex); switch (_type) { case RepetitionType.Interleaved: default: return(DecomposeInterleaved(ctx, startIndex, repetitions, out result)); case RepetitionType.Blockwise: return(DecomposeBlockwise(ctx, startIndex, repetitions, out result)); } }
public void OnUpdate() { if (!brain.stopPlanning) { stateSystemAnimator.ResetInterrupt(this); this.Memory.Items.ToString(); bool needToReplanBySystem = UpdateSensorsSystemsNGoalPriorities(); bool replanned = false; bool actionChanged = false; if (needToReplanBySystem || planPending || Plan == null || Plan.Count == 0) { if (Plan == null || Plan.Count == 0) { Replan(); replanned = true; lastPlanTime = Time.time; } else if (Plan != null && Plan.Peek().IsInterruptableBySystems(this)) { if (Time.time - lastPlanTime > brain.minPlanInterval || planPending) { lastPlanTime = Time.time; replanned = true; // deactivate then replan next update if (Plan.Peek().IsActivated) { Plan.Peek().DeActivate(this); } currentState.ExitState(this); Plan.Clear(); stateSystemAnimator.InterruptAnimation(this); } } planPending = false; } if (!replanned && Plan != null && Plan.Count > 0) // if replanned, wait for ExitState on this update (to completely leave action) { if (!Plan.Peek().IsActivated) // action activation { actionChanged = true; if (Plan.Peek().CanActivate(this)) { #if UNITY_EDITOR if (brain.actionDebug) { brain.ShowDebugMessage("Activated Action" + Plan.Peek()); } #endif Plan.Peek().Activate(this); Plan.Peek().LastUsedAt = Time.time; Plan.Peek().IsActivated = true; currentState = allStates.Find(x => x.StateType == Plan.Peek().correspondingState); currentState.EnterState(this); stateSystemAnimator.InterruptAnimation(this); } else // can't activate this action { Plan.Clear(); currentState.ExitState(this); } } else if (Plan.Peek().IsActivated) { if (Plan.Peek().IsStillValid(this)) { Plan.Peek().OnUpdate(this); if (Plan.Peek().IsCompleted(this)) { #if UNITY_EDITOR if (brain.actionDebug) { brain.ShowDebugMessage("Completed Action" + Plan.Peek()); } #endif actionChanged = true; Plan.Peek().IsActivated = false; Plan.Peek().GeneralPostEffects(this); currentState.ExitState(this); stateSystemAnimator.InterruptAnimation(this); /*if (Plan.Peek().repeatType == EnumTypes.ActionType.Repetitive) * { * } * else */ if (Plan.Peek().repeatType == ET.ActionType.Once) { Plan.Dequeue(); } } } else { #if UNITY_EDITOR if (brain.actionDebug) { brain.ShowDebugMessage("Deactivated Action 'Not Valid' " + Plan.Peek()); } #endif actionChanged = true; Plan.Peek().IsActivated = false; Plan.Peek().DeActivate(this); Plan.Clear(); currentState.ExitState(this); stateSystemAnimator.InterruptAnimation(this); } } } if (!replanned && !actionChanged) { currentState.Update(this); } } else // Debug sensors-systems { UpdateSensorsSystemsNGoalPriorities(); currentState = allStates.Find(x => x.StateType == ET.StateType.Idle);; currentState.Update(this); } }
/// <summary> /// Clear plan loaded locally /// </summary> public void ClearPlan() { Plan.Clear(); PlanResults.Clear(); }
bool _CreatePlan(Domain domain, List <StateVariable> worldState, Plan plan) { plan.Clear(); if (history == null) { history = new Stack <PlannerState>(); } if (taskQueue == null) { taskQueue = new List <Task>(); } if (states == null) { states = new List <StateVariable>(); } states.Clear(); taskQueue.Clear(); history.Clear(); taskQueue.Add(domain.root); states.AddRange(worldState); while (taskQueue.Count > 0) { var task = taskQueue[0]; taskQueue.RemoveAt(0); if (task is CompoundTask) { var compoundTask = task as CompoundTask; var method = compoundTask.FindSatisfiedMethod(states); if (method != null) { SaveHistory(taskQueue, plan, states); foreach (var i in method.tasks) { taskQueue.Add(domain.tasks[i.name]); } } else { if (!RestoreHistory(taskQueue, plan, states)) { return(false); } } } else { var primitiveTask = task as PrimitiveTask; if (primitiveTask.ConditionsAreValid(states)) { primitiveTask.ApplyEffects(states); plan.Add(primitiveTask); } else { if (!RestoreHistory(taskQueue, plan, states)) { return(false); } } } } return(true); }