// ========================================================= 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);
        }
示例#2
0
        // ========================================================= 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);
        }
示例#3
0
        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);
        }
示例#4
0
        // ========================================================= 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);
        }
示例#5
0
 public When_appending_a_step_and_no_builtin_steps_are_there()
 {
     When(() =>
     {
         Plan.Clear();
         Plan.Add <MyEquivalencyStep>();
     });
 }
示例#6
0
        // ========================================================= 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));
        }
示例#7
0
        // ========================================================= 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));
        }
示例#8
0
 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);
         }
     }
 }
示例#9
0
        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));
            }
        }
示例#10
0
    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);
        }
    }
示例#11
0
文件: TMPlan.cs 项目: x2v0/TM
 /// <summary>
 /// Clear plan loaded locally
 /// </summary>
 public void ClearPlan()
 {
     Plan.Clear();
     PlanResults.Clear();
 }
示例#12
0
        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);
        }