public void RemoveClosed(GOAPNode node)
 {
     if (this.numClosed > 0)
     {
         this.closed[this.lastFoundClosed] = this.closed[this.numClosed - 1];
     }
     this.numClosed--;
 }
 public void RemoveOpened(GOAPNode node)
 {
     if (this.numOpened > 0)
     {
         this.opened[this.lastFoundOpened] = this.opened[this.numOpened - 1];
     }
     this.numOpened--;
 }
 public GOAPNode FindClosed(GOAPNode node)
 {
     for (var i = 0; i < this.numClosed; i++)
     {
         long care = node.WorldState.DontCare ^ -1L;
         if ((node.WorldState.Values & care) == (this.closed[i].WorldState.Values & care))
         {
             this.lastFoundClosed = i;
             return(this.closed[i]);
         }
     }
     return(null);
 }
Exemple #4
0
        /// <summary>
        /// internal function to reconstruct the plan by tracing from last node to initial node
        /// </summary>
        /// <returns>The plan.</returns>
        private static Stack <GOAPAction> ReconstructPlan(GOAPNode goalNode, List <GOAPNode> selectedNodes)
        {
            var totalActionsInPlan = goalNode.Depth - 1;
            var plan = new Stack <GOAPAction>(totalActionsInPlan);

            var curnode = goalNode;

            for (var i = 0; i <= totalActionsInPlan - 1; i++)
            {
                // optionally add the node to the List if we have been passed one
                selectedNodes?.Add(curnode.Clone());
                plan.Push(curnode.Action);
                curnode = curnode.Parent;
            }

            // our nodes went from the goal back to the start so reverse them
            selectedNodes?.Reverse();

            return(plan);
        }
 internal List<GOAPNode> GetPossibleTransitions( WorldState fr )
 {
     var result = new List<GOAPNode>();
     for( var i = 0; i < this.viableActions.Count; ++i )
     {
         // see if precondition is met
         var pre = this.preConditions[i];
         var care = ( pre.DontCare ^ -1L );
         bool met = ( ( pre.Values & care ) == ( fr.Values & care ) );
         if( met )
         {
             var node = new GOAPNode
             {
                 Action = this.viableActions[i],
                 CostSoFar = this.viableActions[i].Cost,
                 WorldState = this.ApplyPostConditions(this, i, fr)
             };
             result.Add( node );
         }
     }
     return result;
 }
Exemple #6
0
        /* from: http://theory.stanford.edu/~amitp/GameProgramming/ImplementationNotes.html
         * OPEN = priority queue containing START
         * CLOSED = empty set
         * while lowest rank in OPEN is not the GOAL:
         * current = remove lowest rank item from OPEN
         * add current to CLOSED
         * for neighbors of current:
         *  cost = g(current) + movementcost(current, neighbor)
         *  if neighbor in OPEN and cost less than g(neighbor):
         *    remove neighbor from OPEN, because new path is better
         *  if neighbor in CLOSED and cost less than g(neighbor): **
         *    remove neighbor from CLOSED
         *  if neighbor not in OPEN and neighbor not in CLOSED:
         *    set g(neighbor) to cost
         *    add neighbor to OPEN
         *    set priority queue rank to g(neighbor) + h(neighbor)
         *    set neighbor's parent to current
         */

        /// <summary>
        /// Make a plan of actions that will reach desired world state
        /// </summary>
        /// <param name="ap">Ap.</param>
        /// <param name="start">Start.</param>
        /// <param name="goal">Goal.</param>
        /// <param name="selectedNodes">Storage.</param>
        public static Stack <GOAPAction> Plan(ActionPlanner ap, WorldState start, WorldState goal, List <GOAPNode> selectedNodes = null)
        {
            Storage.Clear();

            var currentNode = new GOAPNode();

            currentNode.WorldState                = start;
            currentNode.ParentWorldState          = start;
            currentNode.CostSoFar                 = 0;                                                 // g
            currentNode.HeuristicCost             = CalculateHeuristic(start, goal);                   // h
            currentNode.CostSoFarAndHeuristicCost = currentNode.CostSoFar + currentNode.HeuristicCost; // f
            currentNode.Depth = 1;

            Storage.AddToOpenList(currentNode);

            while (true)
            {
                // nothing left open so we failed to find a path
                if (!Storage.HasOpened())
                {
                    Storage.Clear();
                    return(null);
                }

                currentNode = Storage.RemoveCheapestOpenNode();

                Storage.AddToClosedList(currentNode);

                // all done. we reached our goal
                if (goal.Equals(currentNode.WorldState))
                {
                    var plan = ReconstructPlan(currentNode, selectedNodes);
                    Storage.Clear();
                    return(plan);
                }

                var neighbors = ap.GetPossibleTransitions(currentNode.WorldState);
                for (var i = 0; i < neighbors.Count; i++)
                {
                    var cur    = neighbors[i];
                    var opened = Storage.FindOpened(cur);
                    var closed = Storage.FindClosed(cur);
                    var cost   = currentNode.CostSoFar + cur.CostSoFar;

                    // if neighbor in OPEN and cost less than g(neighbor):
                    if (opened != null && cost < opened.CostSoFar)
                    {
                        // remove neighbor from OPEN, because new path is better
                        Storage.RemoveOpened(opened);
                        opened = null;
                    }

                    // if neighbor in CLOSED and cost less than g(neighbor):
                    if (closed != null && cost < closed.CostSoFar)
                    {
                        // remove neighbor from CLOSED
                        Storage.RemoveClosed(closed);
                    }

                    // if neighbor not in OPEN and neighbor not in CLOSED:
                    if (opened == null && closed == null)
                    {
                        var nb = new GOAPNode
                        {
                            WorldState       = cur.WorldState,
                            CostSoFar        = cost,
                            HeuristicCost    = CalculateHeuristic(cur.WorldState, goal),
                            Action           = cur.Action,
                            ParentWorldState = currentNode.WorldState,
                            Parent           = currentNode,
                            Depth            = currentNode.Depth + 1
                        };
                        nb.CostSoFarAndHeuristicCost = nb.CostSoFar + nb.HeuristicCost;
                        Storage.AddToOpenList(nb);
                    }
                }
            }
        }
 public void AddToOpenList(GOAPNode node)
 {
     this.opened[this.numOpened++] = node;
 }
 public bool IsClosed(GOAPNode node)
 {
     return(Array.IndexOf(this.closed, node) > -1);
 }
 public bool IsOpen(GOAPNode node)
 {
     return(Array.IndexOf(this.opened, node) > -1);
 }
 public void AddToClosedList(GOAPNode node)
 {
     this.closed[this.numClosed++] = node;
 }