Ejemplo n.º 1
0
/**
 * Runs a generic AStar search
 * The search can look through action nodes or pathfinding nodes and find a path from the start to the Goal
 * @param the ai module,needed to generate neighbours
 */

    public void RunAStar(Agent ai)
    {
        float     g, h, f;    //The g,h and f values needed for the formula f = g + h
        int       numberOfNeighbours = 0;
        short     neighbour;
        AStarNode neighbourNode;

        CurrentNode = Map.CreateANode(End);
        //Add the first node to the open list
        Storage.AddToOpenList(CurrentNode, Map);

        h             = Goal.GetHeuristicDistance(ai, CurrentNode, true);
        CurrentNode.G = 0.0f;
        CurrentNode.H = h;
        CurrentNode.F = h;

        //if (ai.debugGOAP) Debug.Log(Time.timeSinceLevelLoad + " RunAStar " + CurrentNode.NodeID);

        /**
         * We come to the main body of A*, we continue until a solution is found
         */
        while (true)
        {
            //Get the node with the lowest f from the front of the Storage
            CurrentNode = Storage.RemoveCheapestOpenNode(Map);

            //Add the node to the closed list
            if (CurrentNode != null)
            {
                Storage.AddToClosedList(CurrentNode, Map);
            }
            else
            {
                break;
            }

            //Check whether we've reached our Goal
            //The abstract Goal handles the different Goal conditions for nav and planning
            if (Goal.IsAStarFinished(CurrentNode))
            {
                break;                //We've finished, break out
            }

            /**
             * Next job is to get the neighbours of the current node
             * Iterate over them calculate their f,g,h and add to the open list if required
             */

            numberOfNeighbours = Map.GetNumAStarNeighbours(CurrentNode);

            for (short i = 0; i < numberOfNeighbours; i++)
            {
                neighbour = Map.GetAStarNeighbour(CurrentNode, i);
                if (neighbour == -1)                                            //If neighbour is invalid quit
                {
                    break;
                }

                AStarNode.E_AStarFlags flags = Map.GetAStarFlags(neighbour);
                //check whether the node is flagged as open
                if (flags == AStarNode.E_AStarFlags.Open)
                {
                    neighbourNode = Storage.FindInOpenList(neighbour);
                }
                else if (flags == AStarNode.E_AStarFlags.Closed)
                {
                    /**
                     * Get node from the closed list
                     * If the new f for this node is better than previously then remove the node from the closed list
                     * If it is greater than previously then skip this neighbour
                     */
                    neighbourNode = Storage.FindInClosedList(neighbour);
                }
                else if (Goal.IsAStarNodePassable(neighbour))
                {
                    neighbourNode = Map.CreateANode(neighbour);
                }
                else
                {
                    continue;
                }

                //If out best path so far is through the neighbour
                //then theres no need to re-assess
                if (neighbourNode == null || CurrentNode.Parent == neighbourNode)
                {
                    continue;
                }

                /**
                 * Get the new g,h and f for this neighbour node
                 */
                g = CurrentNode.G + (Goal.GetActualCost(CurrentNode, neighbourNode));
                h = Goal.GetHeuristicDistance(ai, neighbourNode, false);

                f = g + h;

                /**
                 * Now need to check if the new f is more expensive to get to this
                 * neighbor node from the current node than from its previous parent.
                 */
                if (f >= neighbourNode.F)
                {
                    continue;
                }


                neighbourNode.F = f;
                neighbourNode.G = g;
                neighbourNode.H = h;

                if (flags == AStarNode.E_AStarFlags.Closed)
                {
                    Storage.RemoveFromClosedList(neighbourNode.NodeID, Map);
                }


                // Finally add the neighbour to the open list
                Storage.AddToOpenList(neighbourNode, Map);

                neighbourNode.Parent = CurrentNode;
            }
        }
    }
Ejemplo n.º 2
0
    /**
     * Adds the specified node to the open list.
     * The list is sorted so the node must be inserted in order
     * @param the node to add
     */
    public void AddToOpenList(AStarNode node, AStarMap map)
    {
        AStarNode currNode     = headOfOpenList;
        AStarNode PreviousNode = null;
        AStarNode NextNode     = null;

        if (map.GetAStarFlags(node.NodeID) == AStarNode.E_AStarFlags.Open)
        {
            return;
        }

        if (currNode == null)
        {
            headOfOpenList = node;
            openSize       = 1;
            map.SetAStarFlags(node.NodeID, AStarNode.E_AStarFlags.Open);
            node.Flag = AStarNode.E_AStarFlags.Open;
        }
        else
        {
            bool inserted = false;
            while (!inserted)
            {
                NextNode     = currNode.Next;
                PreviousNode = currNode.Previous;

                //New node has a higher value than what is already in the open list
                if (currNode.F > node.F)
                {                       //If no Previous node then we have the start node
                    if (PreviousNode == null)
                    {
                        currNode.Previous = node;
                        node.Next         = currNode;
                        node.Previous     = null;
                        headOfOpenList    = node;
                        node.Flag         = AStarNode.E_AStarFlags.Open;
                        map.SetAStarFlags(node.NodeID, AStarNode.E_AStarFlags.Open);
                        inserted = true;
                        openSize++;
                    }
                    else
                    {
                        PreviousNode.Next = node;
                        node.Previous     = PreviousNode;
                        node.Next         = currNode;
                        currNode.Previous = node;
                        map.SetAStarFlags(node.NodeID, AStarNode.E_AStarFlags.Open);
                        node.Flag = AStarNode.E_AStarFlags.Open;
                        inserted  = true;
                        openSize++;
                    }
                }
                else if (currNode.F == node.F)
                {                       //Check if the current node has a higher precendence than existing
                    if (map.CompareNodes(currNode, node))
                    {                   //Can insert node in before the current node
                        if (PreviousNode != null)
                        {
                            PreviousNode.Next = node;
                            currNode.Previous = node;
                            node.Previous     = PreviousNode;
                            node.Next         = currNode;
                            map.SetAStarFlags(node.NodeID, AStarNode.E_AStarFlags.Open);
                            node.Flag = AStarNode.E_AStarFlags.Open;
                            inserted  = true;
                            openSize++;
                        }
                        else if (PreviousNode == null)
                        {
                            node.Previous     = null;
                            node.Next         = currNode;
                            currNode.Previous = node;
                            map.SetAStarFlags(node.NodeID, AStarNode.E_AStarFlags.Open);
                            node.Flag = AStarNode.E_AStarFlags.Open;
                            inserted  = true;
                            openSize++;
                            headOfOpenList = node;
                        }
                    }
                    else
                    {
                        if (NextNode == null)
                        {
                            currNode.Next = node;
                            node.Previous = currNode;
                            node.Next     = null;
                            map.SetAStarFlags(node.NodeID, AStarNode.E_AStarFlags.Open);
                            node.Flag = AStarNode.E_AStarFlags.Open;
                            inserted  = true;
                            openSize++;
                        }
                        else
                        {
                            currNode = NextNode;
                        }
                    }
                }
                else
                {
                    if (NextNode == null)
                    {
                        currNode.Next = node;
                        node.Previous = currNode;
                        node.Next     = null;
                        map.SetAStarFlags(node.NodeID, AStarNode.E_AStarFlags.Open);
                        node.Flag = AStarNode.E_AStarFlags.Open;
                        inserted  = true;
                        openSize++;
                    }
                    else
                    {
                        currNode = NextNode;
                    }
                }
            }
        }
    }