Example #1
0
        /// <summary>
        /// We first traverse to the root, then apply tasks from there to get them in the right order
        /// such that the last task on the queue is the task of our leaf node that we started with.
        /// </summary>
        /// <param name="node"></param>
        private void GeneratePlan(IContext ctx, GOAPNode node)
        {
            if (node != null && node.Task != null)
            {
                GeneratePlan(ctx, node.Parent);

                node.Task.ApplyEffects(ctx);
                Plan.Enqueue(node.Task);
            }
        }
Example #2
0
        private void FreeNode(IContext ctx, GOAPNode node)
        {
            var nextNode = node.Parent;

            ctx.Factory.Free(ref node);
            if (nextNode != null)
            {
                FreeNode(ctx, nextNode);
            }
        }
Example #3
0
        private GOAPNode GetCheapestLeaf(List <GOAPNode> leaves)
        {
            GOAPNode cheapestLeaf = null;

            foreach (var leaf in leaves)
            {
                if (cheapestLeaf != null)
                {
                    if (leaf.RunningCost < cheapestLeaf.RunningCost)
                    {
                        cheapestLeaf = leaf;
                    }
                }
                else
                {
                    cheapestLeaf = leaf;
                }
            }

            return(cheapestLeaf);
        }
Example #4
0
        private bool TryBuildGraph(IContext ctx, GOAPNode parent, List <GOAPNode> leaves, List <ITask> openSubtasks)
        {
            var foundLeaf = false;

            for (var taskIndex = 0; taskIndex < openSubtasks.Count; taskIndex++)
            {
                var task = openSubtasks[taskIndex];
                if (task.IsValid(ctx) == false)
                {
                    continue;
                }

                if (task is IGOAPTask goapTask)
                {
                    // Due to branching permutations of state, and multiple possible solutions
                    // to the goal, where we want to end up with the shortest path, we need to
                    // reset the state stack for every task we operate on.
                    var oldStackDepth = ctx.GetWorldStateChangeDepth(ctx.Factory);

                    goapTask.ApplyEffects(ctx);

                    var node = ctx.Factory.Create <GOAPNode>();
                    {
                        node.Parent      = parent;
                        node.RunningCost = parent.RunningCost + goapTask.Cost(ctx);
                        node.Task        = goapTask;
                    }

                    if (ValidatesGoal(ctx))
                    {
                        leaves.Add(node);
                        foundLeaf = true;
                    }
                    else
                    {
                        var subset = GetSubset(ctx, task, openSubtasks);
                        if (TryBuildGraph(ctx, node, leaves, subset))
                        {
                            foundLeaf = true;
                        }
                        else
                        {
                            // If we failed to find a valid branch for this node,
                            // then it will no longer be referenced after this point.
                            // Otherwise its still used as a parent reference in the
                            // leaves list, and we can't return it to the factory yet.
                            ctx.Factory.Free(ref node);
                        }
                        ctx.Factory.FreeList(ref subset);
                    }

                    // Because of the branching permutations of state with GOAP,
                    // we must always reset the state stack back to the state it
                    // was in previous to the changes applied by this particular
                    // permutation.
                    ctx.TrimToStackDepth(oldStackDepth);
                }
            }

            return(foundLeaf);
        }