Exemple #1
0
		public override void UpdateRecursiveG (Path path, PathNode pathNode, PathHandler handler) {
			UpdateG (path,pathNode);
			
			handler.PushNode (pathNode);
			
			for (var i=0;i<connections.Length;i++) {
				var other = connections[i];
				var otherPN = handler.GetPathNode (other);
				if (otherPN.parent == pathNode && otherPN.pathID == handler.PathID) {
					other.UpdateRecursiveG (path, otherPN,handler);
				}
			}
		}
Exemple #2
0
		public override void Reset () {
			base.Reset();

			searchLength = 5000;
			spread = 5000;

			uniform = true;
			aimStrength = 0.0f;
			chosenNodeR = null;
			maxGScoreNodeR = null;
			maxGScore = 0;
			aim = Vector3.zero;

			nodesEvaluatedRep = 0;
		}
Exemple #3
0
 public override void Open(Path path, PathNode pathNode, PathHandler handler)
 {
     if (this.connections == null)
     {
         return;
     }
     for (int i = 0; i < this.connections.Length; i++)
     {
         GraphNode graphNode = this.connections[i];
         if (path.CanTraverse(graphNode))
         {
             PathNode pathNode2 = handler.GetPathNode(graphNode);
             if (pathNode2.pathID != handler.PathID)
             {
                 pathNode2.node = graphNode;
                 pathNode2.parent = pathNode;
                 pathNode2.pathID = handler.PathID;
                 pathNode2.cost = this.connectionCosts[i];
                 pathNode2.H = path.CalculateHScore(graphNode);
                 graphNode.UpdateG(path, pathNode2);
                 handler.PushNode(pathNode2);
             }
             else
             {
                 uint num = this.connectionCosts[i];
                 if (pathNode.G + num + path.GetTraversalCost(graphNode) < pathNode2.G)
                 {
                     pathNode2.cost = num;
                     pathNode2.parent = pathNode;
                     graphNode.UpdateRecursiveG(path, pathNode2, handler);
                 }
                 else if (pathNode2.G + num + path.GetTraversalCost(this) < pathNode.G && graphNode.ContainsConnection(this))
                 {
                     pathNode.parent = pathNode2;
                     pathNode.cost = num;
                     this.UpdateRecursiveG(path, pathNode, handler);
                 }
             }
         }
     }
 }
Exemple #4
0
 public Tuple(uint F, PathNode node)
 {
     this.F    = F;
     this.node = node;
 }
Exemple #5
0
		public override void UpdateRecursiveG (Path path, PathNode pathNode, PathHandler handler) {
			var gg = GetGridGraph (GraphIndex);
			var neighbourOffsets = gg.neighbourOffsets;
			var nodes = gg.nodes;
			
			UpdateG (path,pathNode);
			handler.PushNode (pathNode);
			
			var pid = handler.PathID;
			
			for (var i=0;i<8;i++) {				
				if (GetConnectionInternal(i)) {
					var other = nodes[nodeInGridIndex + neighbourOffsets[i]];
					var otherPN = handler.GetPathNode (other);
					if (otherPN.parent == pathNode && otherPN.pathID == pid) other.UpdateRecursiveG (path, otherPN,handler);
				}
			}
			
		}
Exemple #6
0
		public override void Open (Path path, PathNode pathNode, PathHandler handler) {
			throw new System.NotImplementedException();
		}
		public override void UpdateRecursiveG (Path path, PathNode pathNode, PathHandler handler) {
			//BaseUpdateAllG (nodeR, nodeRunData);

			handler.PushNode (pathNode);
			UpdateG (path, pathNode);

			LayerGridGraph graph = GetGridGraph (GraphIndex);
			int[] neighbourOffsets = graph.neighbourOffsets;
			LevelGridNode[] nodes = graph.nodes;
			int index = NodeInGridIndex;

			for (int i=0;i<4;i++) {
				int conn = GetConnectionValue(i);//(gridConnections >> i*4) & 0xF;
				if (conn != LevelGridNode.NoConnection) {

					LevelGridNode other = nodes[index+neighbourOffsets[i] + graph.lastScannedWidth*graph.lastScannedDepth*conn];
					PathNode otherPN = handler.GetPathNode (other);

					if (otherPN != null && otherPN.parent == pathNode && otherPN.pathID == handler.PathID) {
						other.UpdateRecursiveG (path, otherPN,handler);
					}
				}
			}
		}
Exemple #8
0
		public override void UpdateRecursiveG (Path path, PathNode pathNode, PathHandler handler) {
			UpdateG(path, pathNode);

			handler.PushNode(pathNode);

			if (connections == null) return;

			for (int i = 0; i < connections.Length; i++) {
				GraphNode other = connections[i];
				PathNode otherPN = handler.GetPathNode(other);
				if (otherPN.parent == pathNode && otherPN.pathID == handler.PathID) other.UpdateRecursiveG(path, otherPN, handler);
			}
		}
Exemple #9
0
		/** Open the node */
		public abstract void Open (Path path, PathNode pathNode, PathHandler handler);
Exemple #10
0
 /// <summary>Has the ending condition been fulfilled.</summary>
 /// <param name="node">The current node.</param>
 public abstract bool TargetFound(PathNode node);
		/** Reset all values to their default values.
		 * All inheriting path types must implement this function, resetting ALL their variables to enable recycling of paths.
		 * Call this base function in inheriting types with base.Reset ();
		 */
		public override void Reset () {
			base.Reset ();

			startNode = null;
			endNode = null;
			startHint = null;
			endHint = null;
			originalStartPoint = Vector3.zero;
			originalEndPoint = Vector3.zero;
			startPoint = Vector3.zero;
			endPoint = Vector3.zero;
			calculatePartial = false;
			partialBestTarget = null;
			startIntPoint = new Int3();
			hTarget = new Int3();
			endNodeCosts = null;

#if !ASTAR_NO_GRID_GRAPH
			gridSpecialCaseNode = null;
#endif
		}
        /// <summary>
        /// Calculates the path until completed or until the time has passed targetTick.
        /// Usually a check is only done every 500 nodes if the time has passed targetTick.
        /// Time/Ticks are got from System.DateTime.UtcNow.Ticks.
        ///
        /// Basic outline of what the function does for the standard path (Pathfinding.ABPath).
        /// <code>
        /// while the end has not been found and no error has occurred
        /// check if we have reached the end
        /// if so, exit and return the path
        ///
        /// open the current node, i.e loop through its neighbours, mark them as visited and put them on a heap
        ///
        /// check if there are still nodes left to process (or have we searched the whole graph)
        /// if there are none, flag error and exit
        ///
        /// pop the next node of the heap and set it as current
        ///
        /// check if the function has exceeded the time limit
        /// if so, return and wait for the function to get called again
        /// </code>
        /// </summary>
        protected override void CalculateStep(long targetTick)
        {
            int counter = 0;

            // Continue to search as long as we haven't encountered an error and we haven't found the target
            while (CompleteState == PathCompleteState.NotCalculated)
            {
                searchedNodes++;

                // Close the current node, if the current node is the target node then the path is finished
                if (currentR.flag1)
                {
                    // We found a target point
                    // Mark that node as the end point
                    CompleteWith(currentR.node);
                    break;
                }

                if (currentR.H < partialBestTarget.H)
                {
                    partialBestTarget = currentR;
                }

                AstarProfiler.StartFastProfile(4);

                // Loop through all walkable neighbours of the node and add them to the open list.
                currentR.node.Open(this, currentR, pathHandler);

                AstarProfiler.EndFastProfile(4);

                // Any nodes left to search?
                if (pathHandler.heap.isEmpty)
                {
                    if (calculatePartial && partialBestTarget != null)
                    {
                        CompleteState = PathCompleteState.Partial;
                        Trace(partialBestTarget);
                    }
                    else
                    {
                        FailWithError("Searched whole area but could not find target");
                    }

                    return;
                }

                // Select the node with the lowest F score and remove it from the open list
                AstarProfiler.StartFastProfile(7);
                currentR = pathHandler.heap.Remove();
                AstarProfiler.EndFastProfile(7);

                // Check for time every 500 nodes, roughly every 0.5 ms usually
                if (counter > 500)
                {
                    // Have we exceded the maxFrameTime, if so we should wait one frame before continuing the search since we don't want the game to lag
                    if (System.DateTime.UtcNow.Ticks >= targetTick)
                    {
                        // Return instead of yield'ing, a separate function handles the yield (CalculatePaths)
                        return;
                    }

                    counter = 0;

                    // Mostly for development
                    if (searchedNodes > 1000000)
                    {
                        throw new System.Exception("Probable infinite loop. Over 1,000,000 nodes searched");
                    }
                }

                counter++;
            }

            AstarProfiler.StartProfile("Trace");

            if (CompleteState == PathCompleteState.Complete)
            {
                Trace(currentR);
            }
            else if (calculatePartial && partialBestTarget != null)
            {
                CompleteState = PathCompleteState.Partial;
                Trace(partialBestTarget);
            }

            AstarProfiler.EndProfile();
        }
Exemple #13
0
        public override void Open(Path path, PathNode pathNode, PathHandler handler)
        {
            GridGraph gg = GetGridGraph(GraphIndex);

            ushort pid = handler.PathID;

#if ASTAR_JPS
            if (gg.useJumpPointSearch && !path.FloodingPath)
            {
                JPSOpen(path, pathNode, handler);
            }
            else
#endif
            {
                int[]      neighbourOffsets = gg.neighbourOffsets;
                uint[]     neighbourCosts   = gg.neighbourCosts;
                GridNode[] nodes            = gg.nodes;
                var        index            = NodeInGridIndex;

                for (int i = 0; i < 8; i++)
                {
                    if (HasConnectionInDirection(i))
                    {
                        GridNode other = nodes[index + neighbourOffsets[i]];
                        if (!path.CanTraverse(other))
                        {
                            continue;
                        }

                        PathNode otherPN = handler.GetPathNode(other);

                        uint tmpCost = neighbourCosts[i];

                        // Check if the other node has not yet been visited by this path
                        if (otherPN.pathID != pid)
                        {
                            otherPN.parent = pathNode;
                            otherPN.pathID = pid;

                            otherPN.cost = tmpCost;

                            otherPN.H = path.CalculateHScore(other);
                            otherPN.UpdateG(path);

                            handler.heap.Add(otherPN);
                        }
                        else
                        {
                            // Sorry for the huge number of #ifs

                            //If not we can test if the path from the current node to this one is a better one then the one already used

#if ASTAR_NO_TRAVERSAL_COST
                            if (pathNode.G + tmpCost < otherPN.G)
#else
                            if (pathNode.G + tmpCost + path.GetTraversalCost(other) < otherPN.G)
#endif
                            {
                                //Debug.Log ("Path better from " + NodeIndex + " to " + otherPN.node.NodeIndex + " " + (pathNode.G+tmpCost+path.GetTraversalCost(other)) + " < " + otherPN.G);
                                otherPN.cost = tmpCost;

                                otherPN.parent = pathNode;

                                other.UpdateRecursiveG(path, otherPN, handler);
                            }
                        }
                    }
                }
            }

#if !ASTAR_GRID_NO_CUSTOM_CONNECTIONS
            base.Open(path, pathNode, handler);
#endif
        }
Exemple #14
0
        public override void CalculateStep(long targetTick)
        {
            for (int i = 0; base.CompleteState == PathCompleteState.NotCalculated; i++)
            {
                base.searchedNodes++;
                if (base.currentR.G >= this.searchLength)
                {
                    if (base.currentR.G <= (this.searchLength + this.spread))
                    {
                        this.nodesEvaluatedRep++;
                        if (this.rnd.NextDouble() <= (1f / ((float)this.nodesEvaluatedRep)))
                        {
                            this.chosenNodeR = base.currentR;
                        }
                        goto Label_00E6;
                    }
                    if (this.chosenNodeR == null)
                    {
                        this.chosenNodeR = base.currentR;
                    }
                    base.CompleteState = PathCompleteState.Complete;
                    break;
                }
                if (base.currentR.G > this.maxGScore)
                {
                    this.maxGScore      = (int)base.currentR.G;
                    this.maxGScoreNodeR = base.currentR;
                }
Label_00E6:
                base.currentR.node.Open(this, base.currentR, base.pathHandler);
                if (base.pathHandler.heap.isEmpty)
                {
                    if (this.chosenNodeR != null)
                    {
                        base.CompleteState = PathCompleteState.Complete;
                    }
                    else if (this.maxGScoreNodeR != null)
                    {
                        this.chosenNodeR   = this.maxGScoreNodeR;
                        base.CompleteState = PathCompleteState.Complete;
                    }
                    else
                    {
                        base.Error();
                    }
                    break;
                }
                base.currentR = base.pathHandler.heap.Remove();
                if (i > 500)
                {
                    if (DateTime.UtcNow.Ticks >= targetTick)
                    {
                        return;
                    }
                    i = 0;
                    if (base.searchedNodes > 0xf4240)
                    {
                        throw new Exception("Probable infinite loop. Over 1,000,000 nodes searched");
                    }
                }
            }
            if (base.CompleteState == PathCompleteState.Complete)
            {
                this.Trace(this.chosenNodeR);
            }
        }
		internal override string DebugString (PathLog logMode) {
			if (logMode == PathLog.None || (!error && logMode == PathLog.OnlyErrors)) {
				return "";
			}

			System.Text.StringBuilder text = pathHandler.DebugStringBuilder;
			text.Length = 0;

			DebugStringPrefix(logMode, text);

			if (!error) {
				text.Append("\nShortest path was ");
				text.Append(chosenTarget == -1 ? "undefined" : nodePaths[chosenTarget].Count.ToString());
				text.Append(" nodes long");

				if (logMode == PathLog.Heavy) {
					text.Append("\nPaths (").Append(targetsFound.Length).Append("):");
					for (int i = 0; i < targetsFound.Length; i++) {
						text.Append("\n\n	Path ").Append(i).Append(" Found: ").Append(targetsFound[i]);

						if (nodePaths[i] != null) {
							text.Append("\n		Length: ");
							text.Append(nodePaths[i].Count);

							GraphNode node = nodePaths[i][nodePaths[i].Count-1];

							if (node != null) {
								PathNode nodeR = pathHandler.GetPathNode(endNode);
								if (nodeR != null) {
									text.Append("\n		End Node");
									text.Append("\n			G: ");
									text.Append(nodeR.G);
									text.Append("\n			H: ");
									text.Append(nodeR.H);
									text.Append("\n			F: ");
									text.Append(nodeR.F);
									text.Append("\n			Point: ");
									text.Append(((Vector3)endPoint).ToString());
									text.Append("\n			Graph: ");
									text.Append(endNode.GraphIndex);
								} else {
									text.Append("\n		End Node: Null");
								}
							}
						}
					}

					text.Append("\nStart Node");
					text.Append("\n	Point: ");
					text.Append(((Vector3)endPoint).ToString());
					text.Append("\n	Graph: ");
					text.Append(startNode.GraphIndex);
					text.Append("\nBinary Heap size at completion: ");
					text.AppendLine(pathHandler.heap == null ? "Null" : (pathHandler.heap.numberOfItems-2).ToString());  // -2 because numberOfItems includes the next item to be added and item zero is not used
				}
			}

			DebugStringSuffix(logMode, text);

			return text.ToString();
		}
Exemple #16
0
        /** Internal method to initialize node data */
        public void InitializeNode(GraphNode node)
        {
            //Get the index of the node
            int ind = node.NodeIndex;

            int bucketNumber = ind >> BucketSizeLog2;
            int bucketIndex  = ind & BucketIndexMask;

            if (bucketNumber >= nodes.Length)
            {
                // A resize is required
                // At least increase the size to:
                // Current size * 1.5
                // Current size + 2 or
                // bucketNumber+1

                var newNodes = new PathNode[System.Math.Max(System.Math.Max(nodes.Length * 3 / 2, bucketNumber + 1), nodes.Length + 2)][];
                for (int i = 0; i < nodes.Length; i++)
                {
                    newNodes[i] = nodes[i];
                }

                var newBucketNew = new bool[newNodes.Length];
                for (int i = 0; i < nodes.Length; i++)
                {
                    newBucketNew[i] = bucketNew[i];
                }

                var newBucketCreated = new bool[newNodes.Length];
                for (int i = 0; i < nodes.Length; i++)
                {
                    newBucketCreated[i] = bucketCreated[i];
                }

                nodes         = newNodes;
                bucketNew     = newBucketNew;
                bucketCreated = newBucketCreated;
            }

            if (nodes[bucketNumber] == null)
            {
                PathNode[] ns;

                if (bucketCache.Count > 0)
                {
                    ns = bucketCache.Pop();
                }
                else
                {
                    ns = new PathNode[BucketSize];
                    for (int i = 0; i < BucketSize; i++)
                    {
                        ns[i] = new PathNode();
                    }
                }
                nodes[bucketNumber] = ns;

                if (!bucketCreated[bucketNumber])
                {
                    bucketNew[bucketNumber]     = true;
                    bucketCreated[bucketNumber] = true;
                }
                filledBuckets++;
            }

            PathNode pn = nodes[bucketNumber][bucketIndex];

            pn.node = node;
        }
Exemple #17
0
		/** Reset all values to their default values.
		 * 
		 * \note All inheriting path types (e.g ConstantPath, RandomPath, etc.) which declare their own variables need to
		 * override this function, resetting ALL their variables to enable recycling of paths.
		 * If this is not done, trying to use that path type for pooling might result in weird behaviour.
		 * The best way is to reset to default values the variables declared in the extended path type and then
		 * call this base function in inheriting types with base.Reset ().
		 * 
		 * \warning This function should not be called manually.
		  */
		public virtual void Reset () {
				
			if (ReferenceEquals (AstarPath.active, null))
				throw new NullReferenceException ("No AstarPath object found in the scene. " +
					"Make sure there is one or do not create paths in Awake");
			
			hasBeenReset = true;
			state = (int)PathState.Created;
			releasedNotSilent = false;
			
			pathHandler = null;
			callback = null;
			_errorLog = "";
			pathCompleteState = PathCompleteState.NotCalculated;
			
			path = ListPool<GraphNode>.Claim();
			vectorPath = ListPool<Vector3>.Claim();
			
			currentR = null;
			
			duration = 0;
			searchIterations = 0;
			searchedNodes = 0;
			//calltime
			
			nnConstraint = PathNNConstraint.Default;
			next = null;
			
			radius = 0;
			walkabilityMask = -1;
			height = 0;
			turnRadius = 0;
			speed = 0;
			
			//heuristic = (Heuristic)0;
			//heuristicScale = 1F;
			heuristic = AstarPath.active.heuristic;
			heuristicScale = AstarPath.active.heuristicScale;
			
			pathID = 0;
			enabledTags = -1;
			tagPenalties = null;

			callTime = DateTime.UtcNow;
			pathID = AstarPath.active.GetNextPathID ();
			
			hTarget = Int3.zero;
			hTargetNode = null;
		}
Exemple #18
0
 /// <summary>Has the ending condition been fulfilled.</summary>
 /// <param name="node">The current node.
 /// This is per default the same as asking if node == p.endNode</param>
 public override bool TargetFound(PathNode node)
 {
     return(node.node == abPath.endNode);
 }
Exemple #19
0
		/** Has the ending condition been fulfilled.
		 * \param node The current node.
		 * This is per default the same as asking if \a node == \a p.endNode */
		public virtual bool TargetFound (PathNode node) {
			return true;//node.node == p.endNode;
		}
Exemple #20
0
 public override bool TargetFound(PathNode node)
 {
     return(((Vector3)node.node.position - abPath.originalEndPoint).sqrMagnitude <= maxDistance * maxDistance);
 }
		/** Calculates the path until completed or until the time has passed \a targetTick.
		 * Usually a check is only done every 500 nodes if the time has passed \a targetTick.
		 * Time/Ticks are got from System.DateTime.UtcNow.Ticks.
		 *
		 * Basic outline of what the function does for the standard path (Pathfinding.ABPath).
\code
while the end has not been found and no error has ocurred
	check if we have reached the end
		if so, exit and return the path

	open the current node, i.e loop through its neighbours, mark them as visited and put them on a heap

	check if there are still nodes left to process (or have we searched the whole graph)
		if there are none, flag error and exit

	pop the next node of the heap and set it as current

	check if the function has exceeded the time limit
		if so, return and wait for the function to get called again
\endcode
		 */
		public override void CalculateStep (long targetTick) {

			int counter = 0;

			// Continue to search while there hasn't ocurred an error and the end hasn't been found
			while (CompleteState == PathCompleteState.NotCalculated) {

				searchedNodes++;

				// Close the current node, if the current node is the target node then the path is finished
				if (currentR.flag1) {
					// We found a target point
					// Mark that node as the end point
					CompleteWith(currentR.node);
					break;
				}

				if (currentR.H < partialBestTarget.H) {
					partialBestTarget = currentR;
				}

				AstarProfiler.StartFastProfile (4);

				// Loop through all walkable neighbours of the node and add them to the open list.
				currentR.node.Open (this, currentR, pathHandler);

				AstarProfiler.EndFastProfile (4);

				// Any nodes left to search?
				if (pathHandler.HeapEmpty()) {
					Error ();
					LogError ("Searched whole area but could not find target");
					return;
				}

				// Select the node with the lowest F score and remove it from the open list
				AstarProfiler.StartFastProfile (7);
				currentR = pathHandler.PopNode ();
				AstarProfiler.EndFastProfile (7);

				// Check for time every 500 nodes, roughly every 0.5 ms usually
				if (counter > 500) {

					// Have we exceded the maxFrameTime, if so we should wait one frame before continuing the search since we don't want the game to lag
					if (System.DateTime.UtcNow.Ticks >= targetTick) {
						// Return instead of yield'ing, a separate function handles the yield (CalculatePaths)
						return;
					}
					counter = 0;

					// Mostly for development
					if (searchedNodes > 1000000) {
						throw new System.Exception ("Probable infinite loop. Over 1,000,000 nodes searched");
					}
				}

				counter++;
			}

			AstarProfiler.StartProfile ("Trace");

			if (CompleteState == PathCompleteState.Complete) {
				Trace (currentR);
			} else if (calculatePartial && partialBestTarget != null) {
				CompleteState = PathCompleteState.Partial;
				Trace (partialBestTarget);
			}

			AstarProfiler.EndProfile ();
		}
Exemple #22
0
        public override void Open(Path path, PathNode pathNode, PathHandler handler)
        {
            GridGraph gg = GetGridGraph(GraphIndex);

            ushort pid = handler.PathID;

#if ASTAR_JPS
            if (gg.useJumpPointSearch && !path.FloodingPath)
            {
                JPSOpen(path, pathNode, handler);
            }
            else
#endif
            {
                int[]      neighbourOffsets = gg.neighbourOffsets;
                uint[]     neighbourCosts   = gg.neighbourCosts;
                GridNode[] nodes            = gg.nodes;

                for (int i = 0; i < 8; i++)
                {
                    if (GetConnectionInternal(i))
                    {
                        GridNode other = nodes[nodeInGridIndex + neighbourOffsets[i]];
                        if (!path.CanTraverse(other))
                        {
                            continue;
                        }

                        PathNode otherPN = handler.GetPathNode(other);

#if ASTAR_CONSTANT_PENALTY
                        uint tmpCost = neighbourCosts[i];
#else
                        // Multiply the connection cost with 1 + the average of the traversal costs for the two nodes
                        uint tmpCost = (neighbourCosts[i] * (256 + path.GetTraversalCost(this) + path.GetTraversalCost(other))) / 128;
#endif

                        if (otherPN.pathID != pid)
                        {
                            otherPN.parent = pathNode;
                            otherPN.pathID = pid;

                            otherPN.cost = tmpCost;

                            otherPN.H = path.CalculateHScore(other);
                            other.UpdateG(path, otherPN);

                            //Debug.Log ("G " + otherPN.G + " F " + otherPN.F);
                            handler.PushNode(otherPN);
                            //Debug.DrawRay ((Vector3)otherPN.node.Position, Vector3.up,Color.blue);
                        }
                        else
                        {
                            // Sorry for the huge number of #ifs

                            //If not we can test if the path from the current node to this one is a better one then the one already used

#if ASTAR_CONSTANT_PENALTY
                            if (pathNode.G + tmpCost + path.GetTraversalCost(other) < otherPN.G)
#else
                            if (pathNode.G + tmpCost < otherPN.G)
#endif
                            {
                                //Debug.Log ("Path better from " + NodeIndex + " to " + otherPN.node.NodeIndex + " " + (pathNode.G+tmpCost+path.GetTraversalCost(other)) + " < " + otherPN.G);
                                otherPN.cost = tmpCost;

                                otherPN.parent = pathNode;

                                other.UpdateRecursiveG(path, otherPN, handler);

                                //Or if the path from this node ("other") to the current ("current") is better
                            }
#if ASTAR_CONSTANT_PENALTY
                            else if (otherPN.G + tmpCost + path.GetTraversalCost(this) < pathNode.G)
#else
                            else if (otherPN.G + tmpCost < pathNode.G)
#endif
                            {
                                //Debug.Log ("Path better from " + otherPN.node.NodeIndex + " to " + NodeIndex + " " + (otherPN.G+tmpCost+path.GetTraversalCost (this)) + " < " + pathNode.G);
                                pathNode.parent = otherPN;
                                pathNode.cost   = tmpCost;

                                UpdateRecursiveG(path, pathNode, handler);
                            }
                        }
                    }
                }
            }

#if ASTAR_GRID_CUSTOM_CONNECTIONS
            if (connections != null)
            {
                for (int i = 0; i < connections.Length; i++)
                {
                    GraphNode other = connections[i];
                    if (!path.CanTraverse(other))
                    {
                        continue;
                    }

                    PathNode otherPN = handler.GetPathNode(other);

#if ASTAR_CONSTANT_PENALTY
                    uint tmpCost = connectionCosts[i];
#else
                    uint tmpCost = (connectionCosts[i] * (256 + path.GetTraversalCost(this) + path.GetTraversalCost(other))) / 128;
#endif

                    if (otherPN.pathID != pid)
                    {
                        otherPN.parent = pathNode;
                        otherPN.pathID = pid;

                        otherPN.cost = tmpCost;

                        otherPN.H = path.CalculateHScore(other);
                        other.UpdateG(path, otherPN);

                        //Debug.Log ("G " + otherPN.G + " F " + otherPN.F);
                        handler.PushNode(otherPN);
                        //Debug.DrawRay ((Vector3)otherPN.node.Position, Vector3.up,Color.blue);
                    }
                    else
                    {
                        // Sorry for the huge number of #ifs

                        //If not we can test if the path from the current node to this one is a better one then the one already used

#if ASTAR_CONSTANT_PENALTY
                        if (pathNode.G + tmpCost + path.GetTraversalCost(other) < otherPN.G)
#else
                        if (pathNode.G + tmpCost < otherPN.G)
#endif
                        {
                            //Debug.Log ("Path better from " + NodeIndex + " to " + otherPN.node.NodeIndex + " " + (pathNode.G+tmpCost+path.GetTraversalCost(other)) + " < " + otherPN.G);
                            otherPN.cost = tmpCost;

                            otherPN.parent = pathNode;

                            other.UpdateRecursiveG(path, otherPN, handler);

                            //Or if the path from this node ("other") to the current ("current") is better
                        }
#if ASTAR_CONSTANT_PENALTY
                        else if (otherPN.G + tmpCost + path.GetTraversalCost(this) < pathNode.G && other.ContainsConnection(this))
#else
                        else if (otherPN.G + tmpCost < pathNode.G && other.ContainsConnection(this))
#endif
                        {
                            //Debug.Log ("Path better from " + otherPN.node.NodeIndex + " to " + NodeIndex + " " + (otherPN.G+tmpCost+path.GetTraversalCost (this)) + " < " + pathNode.G);
                            pathNode.parent = otherPN;
                            pathNode.cost   = tmpCost;

                            UpdateRecursiveG(path, pathNode, handler);
                        }
                    }
                }
            }
#endif
        }
Exemple #23
0
		public void UpdateG (Path path, PathNode pathNode) {
#if ASTAR_NO_TRAVERSAL_COST
			pathNode.G = pathNode.parent.G + pathNode.cost;
#else
			pathNode.G = pathNode.parent.G + pathNode.cost + path.GetTraversalCost(this);
#endif
		}
Exemple #24
0
        public override void Open(Path path, PathNode pathNode, PathHandler handler)
        {
            if (connections == null)
            {
                return;
            }

            // Flag2 indicates if this node needs special treatment
            // with regard to connection costs
            bool flag2 = pathNode.flag2;

            // Loop through all connections
            for (int i = connections.Length - 1; i >= 0; i--)
            {
                GraphNode other = connections[i];

                // Make sure we can traverse the neighbour
                if (path.CanTraverse(other))
                {
                    PathNode pathOther = handler.GetPathNode(other);

                    // Fast path out, worth it for triangle mesh nodes since they usually have degree 2 or 3
                    if (pathOther == pathNode.parent)
                    {
                        continue;
                    }

                    uint cost = connectionCosts[i];

                    if (flag2 || pathOther.flag2)
                    {
                        // Get special connection cost from the path
                        // This is used by the start and end nodes
                        cost = path.GetConnectionSpecialCost(this, other, cost);
                    }

                    // Test if we have seen the other node before
                    if (pathOther.pathID != handler.PathID)
                    {
                        // We have not seen the other node before
                        // So the path from the start through this node to the other node
                        // must be the shortest one so far

                        // Might not be assigned
                        pathOther.node = other;

                        pathOther.parent = pathNode;
                        pathOther.pathID = handler.PathID;

                        pathOther.cost = cost;

                        pathOther.H = path.CalculateHScore(other);
                        other.UpdateG(path, pathOther);

                        handler.PushNode(pathOther);
                    }
                    else
                    {
                        // If not we can test if the path from this node to the other one is a better one than the one already used
                        if (pathNode.G + cost + path.GetTraversalCost(other) < pathOther.G)
                        {
                            pathOther.cost   = cost;
                            pathOther.parent = pathNode;

                            other.UpdateRecursiveG(path, pathOther, handler);
                        }
                        else if (pathOther.G + cost + path.GetTraversalCost(this) < pathNode.G && other.ContainsConnection(this))
                        {
                            // Or if the path from the other node to this one is better

                            pathNode.parent = pathOther;
                            pathNode.cost   = cost;

                            UpdateRecursiveG(path, pathNode, handler);
                        }
                    }
                }
            }
        }
        public override void Open(Path path, PathNode pathNode, PathHandler handler)
        {
            GridGraph gg = GetGridGraph(GraphIndex);

            int[]      neighbourOffsets = gg.neighbourOffsets;
            uint[]     neighbourCosts   = gg.neighbourCosts;
            GridNode[] nodes            = gg.nodes;
            ushort     pid = handler.PathID;

            for (int i = 0; i < 8; i++)
            {
                if (GetConnectionInternal(i))
                {
                    GridNode other = nodes[nodeInGridIndex + neighbourOffsets[i]];
                    if (!path.CanTraverse(other))
                    {
                        continue;
                    }

                    PathNode otherPN = handler.GetPathNode(other);

                    if (otherPN.pathID != pid)
                    {
                        otherPN.parent = pathNode;
                        otherPN.pathID = pid;

                        otherPN.cost = neighbourCosts[i];

                        otherPN.H = path.CalculateHScore(other);
                        other.UpdateG(path, otherPN);

                        //Debug.Log ("G " + otherPN.G + " F " + otherPN.F);
                        handler.PushNode(otherPN);
                        //Debug.DrawRay ((Vector3)otherPN.node.Position, Vector3.up,Color.blue);
                    }
                    else
                    {
                        //If not we can test if the path from the current node to this one is a better one then the one already used
                        uint tmpCost = neighbourCosts[i];

                        if (pathNode.G + tmpCost + path.GetTraversalCost(other) < otherPN.G)
                        {
                            //Debug.Log ("Path better from " + NodeIndex + " to " + otherPN.node.NodeIndex + " " + (pathNode.G+tmpCost+path.GetTraversalCost(other)) + " < " + otherPN.G);
                            otherPN.cost = tmpCost;

                            otherPN.parent = pathNode;

                            other.UpdateRecursiveG(path, otherPN, handler);

                            //Or if the path from this node ("other") to the current ("current") is better
                        }
                        else if (otherPN.G + tmpCost + path.GetTraversalCost(this) < pathNode.G)
                        {
                            //Debug.Log ("Path better from " + otherPN.node.NodeIndex + " to " + NodeIndex + " " + (otherPN.G+tmpCost+path.GetTraversalCost (this)) + " < " + pathNode.G);
                            pathNode.parent = otherPN;
                            pathNode.cost   = tmpCost;

                            UpdateRecursiveG(path, pathNode, handler);
                        }
                    }
                }
            }
        }
Exemple #26
0
 public override void Open(Path path, PathNode pathNode, PathHandler handler)
 {
     throw new System.NotImplementedException();
 }
Exemple #27
0
		/** Opens a node using Jump Point Search.
		 * \see http://en.wikipedia.org/wiki/Jump_point_search
		 */
		public void JPSOpen (Path path, PathNode pathNode, PathHandler handler) {
			GridGraph gg = GetGridGraph(GraphIndex);

			int[] neighbourOffsets = gg.neighbourOffsets;
			GridNode[] nodes = gg.nodes;
			ushort pid = handler.PathID;

			int noncyclic = gridFlags & 0xFF;
			int cyclic = 0;
			for (int i = 0; i < 8; i++) cyclic |= ((noncyclic >> i)&0x1) << JPSCyclic[i];

			var parent = pathNode.parent != null ? pathNode.parent.node as GridNode : null;
			int parentDir = -1;

			if (parent != null) {
				int diff = parent != null ? parent.nodeInGridIndex - nodeInGridIndex : 0;

				int x2 = nodeInGridIndex % gg.width;
				int x1 = parent.nodeInGridIndex % gg.width;
				if (diff < 0) {
					if (x1 == x2) {
						parentDir = 0;
					} else if (x1 < x2) {
						parentDir = 7;
					} else {
						parentDir = 4;
					}
				} else {
					if (x1 == x2) {
						parentDir = 1;
					} else if (x1 < x2) {
						parentDir = 6;
					} else {
						parentDir = 5;
					}
				}
			}
			int cyclicParentDir = 0;
			// Check for -1

			int forced = 0;
			if (parentDir != -1) {
				cyclicParentDir = JPSCyclic[parentDir];
				// Loop around to be able to assume -X is where we came from
				cyclic = ((cyclic >> cyclicParentDir) | ((cyclic << 8) >> cyclicParentDir)) & 0xFF;
			} else {
				forced = 0xFF;
				//parentDir = 0;
			}

			bool diagonal = parentDir >= 4;
			int natural;

			if (diagonal) {
				for (int i = 0; i < 8; i++) if (((cyclic >> i)&1) == 0) forced |= JPSForcedDiagonal[i];

				natural = JPSNaturalDiagonalNeighbours;
			} else {
				for (int i = 0; i < 8; i++) if (((cyclic >> i)&1) == 0) forced |= JPSForced[i];

				natural = JPSNaturalStraightNeighbours;
			}

			// Don't force nodes we cannot reach anyway
			forced &= cyclic;
			natural &= cyclic;

			int nb = forced | natural;


			/*if ( ((Vector3)position - new Vector3(0.5f,0,3.5f)).magnitude < 0.5f ) {
			 *  Debug.Log (noncyclic + " " + parentDir + " " + cyclicParentDir);
			 *  Debug.Log (System.Convert.ToString (cyclic, 2)+"\n"+System.Convert.ToString (noncyclic, 2)+"\n"+System.Convert.ToString (natural, 2)+"\n"+System.Convert.ToString (forced, 2));
			 * }*/

			for (int i = 0; i < 8; i++) {
				if (((nb >> i)&1) != 0) {
					int oi = JPSInverseCyclic[(i + cyclicParentDir) % 8];
					GridNode other = nodes[nodeInGridIndex + neighbourOffsets[oi]];

#if ASTARDEBUG
					if (((forced >> i)&1) != 0) {
						Debug.DrawLine((Vector3)position, Vector3.Lerp((Vector3)other.position, (Vector3)position, 0.6f), Color.red);
					}
					if (((natural >> i)&1) != 0) {
						Debug.DrawLine((Vector3)position + Vector3.up*0.2f, Vector3.Lerp((Vector3)other.position, (Vector3)position, 0.6f) + Vector3.up*0.2f, Color.green);
					}
#endif

					if (oi < 4) {
						other = JPSJumpStraight(other, path, handler, JPSInverseCyclic[(i + 4 + cyclicParentDir) % 8]);
					} else {
						other = other.JPSJumpDiagonal(path, handler, JPSInverseCyclic[(i + 4 + cyclicParentDir) % 8]);
					}

					if (other != null) {
						//Debug.DrawLine ( (Vector3)position + Vector3.up*0.0f, (Vector3)other.position + Vector3.up*0.3f, Color.cyan);
						//Debug.DrawRay ( (Vector3)other.position, Vector3.up, Color.cyan);
						//GridNode other = nodes[nodeInGridIndex + neighbourOffsets[i]];
						//if (!path.CanTraverse (other)) continue;

						PathNode otherPN = handler.GetPathNode(other);

						if (otherPN.pathID != pid) {
							otherPN.parent = pathNode;
							otherPN.pathID = pid;

							otherPN.cost = (uint)(other.position - position).costMagnitude;//neighbourCosts[i];

							otherPN.H = path.CalculateHScore(other);
							other.UpdateG(path, otherPN);

							//Debug.Log ("G " + otherPN.G + " F " + otherPN.F);
							handler.PushNode(otherPN);
							//Debug.DrawRay ((Vector3)otherPN.node.Position, Vector3.up,Color.blue);
						} else {
							//If not we can test if the path from the current node to this one is a better one then the one already used
							uint tmpCost = (uint)(other.position - position).costMagnitude;//neighbourCosts[i];

							if (pathNode.G+tmpCost+path.GetTraversalCost(other) < otherPN.G) {
								//Debug.Log ("Path better from " + NodeIndex + " to " + otherPN.node.NodeIndex + " " + (pathNode.G+tmpCost+path.GetTraversalCost(other)) + " < " + otherPN.G);
								otherPN.cost = tmpCost;

								otherPN.parent = pathNode;

								other.UpdateRecursiveG(path, otherPN, handler);

								//Or if the path from this node ("other") to the current ("current") is better
							} else if (otherPN.G+tmpCost+path.GetTraversalCost(this) < pathNode.G) {
								//Debug.Log ("Path better from " + otherPN.node.NodeIndex + " to " + NodeIndex + " " + (otherPN.G+tmpCost+path.GetTraversalCost (this)) + " < " + pathNode.G);
								pathNode.parent = otherPN;
								pathNode.cost = tmpCost;

								UpdateRecursiveG(path, pathNode, handler);
							}
						}
					}
				}

#if ASTARDEBUG
				if (i == 0 && parentDir != -1 && this.nodeInGridIndex > 10) {
					int oi = JPSInverseCyclic[(i + cyclicParentDir) % 8];

					if (nodeInGridIndex + neighbourOffsets[oi] < 0 || nodeInGridIndex + neighbourOffsets[oi] >= nodes.Length) {
						//Debug.LogError ("ERR: " + (nodeInGridIndex + neighbourOffsets[oi]) + " " + cyclicParentDir + " " + parentDir + " Reverted " + oi);
						//Debug.DrawRay ((Vector3)position, Vector3.up, Color.red);
					} else {
						GridNode other = nodes[nodeInGridIndex + neighbourOffsets[oi]];
						Debug.DrawLine((Vector3)position - Vector3.up*0.2f, Vector3.Lerp((Vector3)other.position, (Vector3)position, 0.6f) - Vector3.up*0.2f, Color.blue);
					}
				}
#endif
			}
		}
Exemple #28
0
        /** Opens a node using Jump Point Search.
         * \see http://en.wikipedia.org/wiki/Jump_point_search
         */
        public void JPSOpen(Path path, PathNode pathNode, PathHandler handler)
        {
            GridGraph gg = GetGridGraph(GraphIndex);

            int[]      neighbourOffsets = gg.neighbourOffsets;
            GridNode[] nodes            = gg.nodes;
            ushort     pid = handler.PathID;

            int noncyclic = gridFlags & 0xFF;
            int cyclic    = 0;

            for (int i = 0; i < 8; i++)
            {
                cyclic |= ((noncyclic >> i) & 0x1) << JPSCyclic[i];
            }

            var parent    = pathNode.parent != null ? pathNode.parent.node as GridNode : null;
            int parentDir = -1;

            if (parent != null)
            {
                int diff = parent != null ? parent.nodeInGridIndex - nodeInGridIndex : 0;

                int x2 = nodeInGridIndex % gg.width;
                int x1 = parent.nodeInGridIndex % gg.width;
                if (diff < 0)
                {
                    if (x1 == x2)
                    {
                        parentDir = 0;
                    }
                    else if (x1 < x2)
                    {
                        parentDir = 7;
                    }
                    else
                    {
                        parentDir = 4;
                    }
                }
                else
                {
                    if (x1 == x2)
                    {
                        parentDir = 1;
                    }
                    else if (x1 < x2)
                    {
                        parentDir = 6;
                    }
                    else
                    {
                        parentDir = 5;
                    }
                }
            }
            int cyclicParentDir = 0;
            // Check for -1

            int forced = 0;

            if (parentDir != -1)
            {
                cyclicParentDir = JPSCyclic[parentDir];
                // Loop around to be able to assume -X is where we came from
                cyclic = ((cyclic >> cyclicParentDir) | ((cyclic << 8) >> cyclicParentDir)) & 0xFF;
            }
            else
            {
                forced = 0xFF;
                //parentDir = 0;
            }

            bool diagonal = parentDir >= 4;
            int  natural;

            if (diagonal)
            {
                for (int i = 0; i < 8; i++)
                {
                    if (((cyclic >> i) & 1) == 0)
                    {
                        forced |= JPSForcedDiagonal[i];
                    }
                }

                natural = JPSNaturalDiagonalNeighbours;
            }
            else
            {
                for (int i = 0; i < 8; i++)
                {
                    if (((cyclic >> i) & 1) == 0)
                    {
                        forced |= JPSForced[i];
                    }
                }

                natural = JPSNaturalStraightNeighbours;
            }

            // Don't force nodes we cannot reach anyway
            forced  &= cyclic;
            natural &= cyclic;

            int nb = forced | natural;


            /*if ( ((Vector3)position - new Vector3(0.5f,0,3.5f)).magnitude < 0.5f ) {
             *  Debug.Log (noncyclic + " " + parentDir + " " + cyclicParentDir);
             *  Debug.Log (System.Convert.ToString (cyclic, 2)+"\n"+System.Convert.ToString (noncyclic, 2)+"\n"+System.Convert.ToString (natural, 2)+"\n"+System.Convert.ToString (forced, 2));
             * }*/

            for (int i = 0; i < 8; i++)
            {
                if (((nb >> i) & 1) != 0)
                {
                    int      oi    = JPSInverseCyclic[(i + cyclicParentDir) % 8];
                    GridNode other = nodes[nodeInGridIndex + neighbourOffsets[oi]];

#if ASTARDEBUG
                    if (((forced >> i) & 1) != 0)
                    {
                        Debug.DrawLine((Vector3)position, Vector3.Lerp((Vector3)other.position, (Vector3)position, 0.6f), Color.red);
                    }
                    if (((natural >> i) & 1) != 0)
                    {
                        Debug.DrawLine((Vector3)position + Vector3.up * 0.2f, Vector3.Lerp((Vector3)other.position, (Vector3)position, 0.6f) + Vector3.up * 0.2f, Color.green);
                    }
#endif

                    if (oi < 4)
                    {
                        other = JPSJumpStraight(other, path, handler, JPSInverseCyclic[(i + 4 + cyclicParentDir) % 8]);
                    }
                    else
                    {
                        other = other.JPSJumpDiagonal(path, handler, JPSInverseCyclic[(i + 4 + cyclicParentDir) % 8]);
                    }

                    if (other != null)
                    {
                        //Debug.DrawLine ( (Vector3)position + Vector3.up*0.0f, (Vector3)other.position + Vector3.up*0.3f, Color.cyan);
                        //Debug.DrawRay ( (Vector3)other.position, Vector3.up, Color.cyan);
                        //GridNode other = nodes[nodeInGridIndex + neighbourOffsets[i]];
                        //if (!path.CanTraverse (other)) continue;

                        PathNode otherPN = handler.GetPathNode(other);

                        if (otherPN.pathID != pid)
                        {
                            otherPN.parent = pathNode;
                            otherPN.pathID = pid;

                            otherPN.cost = (uint)(other.position - position).costMagnitude;                            //neighbourCosts[i];

                            otherPN.H = path.CalculateHScore(other);
                            other.UpdateG(path, otherPN);

                            //Debug.Log ("G " + otherPN.G + " F " + otherPN.F);
                            handler.heap.Add(otherPN);
                            //Debug.DrawRay ((Vector3)otherPN.node.Position, Vector3.up,Color.blue);
                        }
                        else
                        {
                            //If not we can test if the path from the current node to this one is a better one then the one already used
                            uint tmpCost = (uint)(other.position - position).costMagnitude;                            //neighbourCosts[i];

                            if (pathNode.G + tmpCost + path.GetTraversalCost(other) < otherPN.G)
                            {
                                //Debug.Log ("Path better from " + NodeIndex + " to " + otherPN.node.NodeIndex + " " + (pathNode.G+tmpCost+path.GetTraversalCost(other)) + " < " + otherPN.G);
                                otherPN.cost = tmpCost;

                                otherPN.parent = pathNode;

                                other.UpdateRecursiveG(path, otherPN, handler);

                                //Or if the path from this node ("other") to the current ("current") is better
                            }
                            else if (otherPN.G + tmpCost + path.GetTraversalCost(this) < pathNode.G)
                            {
                                //Debug.Log ("Path better from " + otherPN.node.NodeIndex + " to " + NodeIndex + " " + (otherPN.G+tmpCost+path.GetTraversalCost (this)) + " < " + pathNode.G);
                                pathNode.parent = otherPN;
                                pathNode.cost   = tmpCost;

                                UpdateRecursiveG(path, pathNode, handler);
                            }
                        }
                    }
                }

#if ASTARDEBUG
                if (i == 0 && parentDir != -1 && this.nodeInGridIndex > 10)
                {
                    int oi = JPSInverseCyclic[(i + cyclicParentDir) % 8];

                    if (nodeInGridIndex + neighbourOffsets[oi] < 0 || nodeInGridIndex + neighbourOffsets[oi] >= nodes.Length)
                    {
                        //Debug.LogError ("ERR: " + (nodeInGridIndex + neighbourOffsets[oi]) + " " + cyclicParentDir + " " + parentDir + " Reverted " + oi);
                        //Debug.DrawRay ((Vector3)position, Vector3.up, Color.red);
                    }
                    else
                    {
                        GridNode other = nodes[nodeInGridIndex + neighbourOffsets[oi]];
                        Debug.DrawLine((Vector3)position - Vector3.up * 0.2f, Vector3.Lerp((Vector3)other.position, (Vector3)position, 0.6f) - Vector3.up * 0.2f, Color.blue);
                    }
                }
#endif
            }
        }
Exemple #29
0
 public override void Open(Path path, PathNode pathNode, PathHandler handler)
 {
     GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex);
     ushort pathID = handler.PathID;
     int[] neighbourOffsets = gridGraph.neighbourOffsets;
     uint[] neighbourCosts = gridGraph.neighbourCosts;
     GridNode[] nodes = gridGraph.nodes;
     for (int i = 0; i < 8; i++)
     {
         if (this.GetConnectionInternal(i))
         {
             GridNode gridNode = nodes[this.nodeInGridIndex + neighbourOffsets[i]];
             if (path.CanTraverse(gridNode))
             {
                 PathNode pathNode2 = handler.GetPathNode(gridNode);
                 uint num = neighbourCosts[i];
                 if (pathNode2.pathID != pathID)
                 {
                     pathNode2.parent = pathNode;
                     pathNode2.pathID = pathID;
                     pathNode2.cost = num;
                     pathNode2.H = path.CalculateHScore(gridNode);
                     gridNode.UpdateG(path, pathNode2);
                     handler.PushNode(pathNode2);
                 }
                 else if (pathNode.G + num + path.GetTraversalCost(gridNode) < pathNode2.G)
                 {
                     pathNode2.cost = num;
                     pathNode2.parent = pathNode;
                     gridNode.UpdateRecursiveG(path, pathNode2, handler);
                 }
                 else if (pathNode2.G + num + path.GetTraversalCost(this) < pathNode.G)
                 {
                     pathNode.parent = pathNode2;
                     pathNode.cost = num;
                     this.UpdateRecursiveG(path, pathNode, handler);
                 }
             }
         }
     }
     if (this.connections != null)
     {
         for (int j = 0; j < this.connections.Length; j++)
         {
             GraphNode graphNode = this.connections[j];
             if (path.CanTraverse(graphNode))
             {
                 PathNode pathNode3 = handler.GetPathNode(graphNode);
                 uint num2 = this.connectionCosts[j];
                 if (pathNode3.pathID != pathID)
                 {
                     pathNode3.parent = pathNode;
                     pathNode3.pathID = pathID;
                     pathNode3.cost = num2;
                     pathNode3.H = path.CalculateHScore(graphNode);
                     graphNode.UpdateG(path, pathNode3);
                     handler.PushNode(pathNode3);
                 }
                 else if (pathNode.G + num2 + path.GetTraversalCost(graphNode) < pathNode3.G)
                 {
                     pathNode3.cost = num2;
                     pathNode3.parent = pathNode;
                     graphNode.UpdateRecursiveG(path, pathNode3, handler);
                 }
                 else if (pathNode3.G + num2 + path.GetTraversalCost(this) < pathNode.G && graphNode.ContainsConnection(this))
                 {
                     pathNode.parent = pathNode3;
                     pathNode.cost = num2;
                     this.UpdateRecursiveG(path, pathNode, handler);
                 }
             }
         }
     }
 }
Exemple #30
0
        public override void Open(Path path, PathNode pathNode, PathHandler handler)
        {
            GridGraph gg = GetGridGraph(GraphIndex);

            ushort pid = handler.PathID;

#if ASTAR_JPS
            if (gg.useJumpPointSearch && !path.FloodingPath)
            {
                JPSOpen(path, pathNode, handler);
            }
            else
#endif
            {
                int[]      neighbourOffsets = gg.neighbourOffsets;
                uint[]     neighbourCosts   = gg.neighbourCosts;
                GridNode[] nodes            = gg.nodes;

                for (int i = 0; i < 8; i++)
                {
                    if (GetConnectionInternal(i))
                    {
                        GridNode other = nodes[nodeInGridIndex + neighbourOffsets[i]];
                        if (!path.CanTraverse(other))
                        {
                            continue;
                        }

                        PathNode otherPN = handler.GetPathNode(other);

                        uint tmpCost = neighbourCosts[i];

                        if (otherPN.pathID != pid)
                        {
                            otherPN.parent = pathNode;
                            otherPN.pathID = pid;

                            otherPN.cost = tmpCost;

                            otherPN.H = path.CalculateHScore(other);
                            other.UpdateG(path, otherPN);

                            //Debug.Log ("G " + otherPN.G + " F " + otherPN.F);
                            handler.heap.Add(otherPN);
                            //Debug.DrawRay ((Vector3)otherPN.node.Position, Vector3.up,Color.blue);
                        }
                        else
                        {
                            // Sorry for the huge number of #ifs

                            //If not we can test if the path from the current node to this one is a better one then the one already used

#if ASTAR_NO_TRAVERSAL_COST
                            if (pathNode.G + tmpCost < otherPN.G)
#else
                            if (pathNode.G + tmpCost + path.GetTraversalCost(other) < otherPN.G)
#endif
                            {
                                //Debug.Log ("Path better from " + NodeIndex + " to " + otherPN.node.NodeIndex + " " + (pathNode.G+tmpCost+path.GetTraversalCost(other)) + " < " + otherPN.G);
                                otherPN.cost = tmpCost;

                                otherPN.parent = pathNode;

                                other.UpdateRecursiveG(path, otherPN, handler);

                                //Or if the path from this node ("other") to the current ("current") is better
                            }
#if ASTAR_NO_TRAVERSAL_COST
                            else if (otherPN.G + tmpCost < pathNode.G)
#else
                            else if (otherPN.G + tmpCost + path.GetTraversalCost(this) < pathNode.G)
#endif
                            {
                                //Debug.Log ("Path better from " + otherPN.node.NodeIndex + " to " + NodeIndex + " " + (otherPN.G+tmpCost+path.GetTraversalCost (this)) + " < " + pathNode.G);
                                pathNode.parent = otherPN;
                                pathNode.cost   = tmpCost;

                                UpdateRecursiveG(path, pathNode, handler);
                            }
                        }
                    }
                }
            }

#if !ASTAR_GRID_NO_CUSTOM_CONNECTIONS
            base.Open(path, pathNode, handler);
#endif
        }
Exemple #31
0
 // Token: 0x06000756 RID: 1878 RVA: 0x00047AF6 File Offset: 0x00045EF6
 public override bool TargetFound(PathNode node)
 {
     return((ulong)node.G >= (ulong)((long)this.maxGScore));
 }
Exemple #32
0
 public void UpdateG(Path path, PathNode pathNode)
 {
     pathNode.G = pathNode.parent.G + pathNode.cost + path.GetTraversalCost(this);
 }
Exemple #33
0
		public override void Open (Path path, PathNode pathNode, PathHandler handler) {

			var gg = GetGridGraph (GraphIndex);

			var pid = handler.PathID;

			{
				var neighbourOffsets = gg.neighbourOffsets;
				var neighbourCosts = gg.neighbourCosts;
				var nodes = gg.nodes;
				 
				for (var i=0;i<8;i++) {
					if (GetConnectionInternal(i)) {
						
						var other = nodes[nodeInGridIndex + neighbourOffsets[i]];
						if (!path.CanTraverse (other)) continue;
						
						var otherPN = handler.GetPathNode (other);

						// Multiply the connection cost with 1 + the average of the traversal costs for the two nodes
						var tmpCost = (neighbourCosts[i] * (256 + path.GetTraversalCost(this) + path.GetTraversalCost(other)))/128;

						if (otherPN.pathID != pid) {
							otherPN.parent = pathNode;
							otherPN.pathID = pid;

							otherPN.cost = tmpCost;

							otherPN.H = path.CalculateHScore (other);
							other.UpdateG (path, otherPN);
							
							//Debug.Log ("G " + otherPN.G + " F " + otherPN.F);
							handler.PushNode (otherPN);
							//Debug.DrawRay ((Vector3)otherPN.node.Position, Vector3.up,Color.blue);
						} else {

							// Sorry for the huge number of #ifs

							//If not we can test if the path from the current node to this one is a better one then the one already used

							if (pathNode.G+tmpCost < otherPN.G)
							{
								//Debug.Log ("Path better from " + NodeIndex + " to " + otherPN.node.NodeIndex + " " + (pathNode.G+tmpCost+path.GetTraversalCost(other)) + " < " + otherPN.G);
								otherPN.cost = tmpCost;
								
								otherPN.parent = pathNode;
								
								other.UpdateRecursiveG (path,otherPN, handler);
								
							//Or if the path from this node ("other") to the current ("current") is better
							}
							else if (otherPN.G+tmpCost < pathNode.G)
							{

								//Debug.Log ("Path better from " + otherPN.node.NodeIndex + " to " + NodeIndex + " " + (otherPN.G+tmpCost+path.GetTraversalCost (this)) + " < " + pathNode.G);
								pathNode.parent = otherPN;
								pathNode.cost = tmpCost;
								
								UpdateRecursiveG(path, pathNode, handler);
							}
						}
					}
				}
			}

		}
 /** Open the node */
 public abstract void Open(Path path, PathNode pathNode, PathHandler handler);
Exemple #35
0
		/** Traces the calculated path from the end node to the start.
		 * This will build an array (#path) of the nodes this path will pass through and also set the #vectorPath array to the #path arrays positions.
		 * Assumes the #vectorPath and #path are empty and not null (which will be the case for a correctly initialized path).
		 */
		protected virtual void Trace (PathNode from) {
			
			var count = 0;
			
			var c = from;
			while (c != null) {
				c = c.parent;
				count++;
				if (count > 1024) {
					Debug.LogWarning ("Inifinity loop? >1024 node path. Remove this message if you really have that long paths (Path.cs, Trace function)");
					break;
				}
			}
			
			//Ensure capacities for lists
			AstarProfiler.StartProfile ("Check List Capacities");
			
			if (path.Capacity < count) path.Capacity = count;
			if (vectorPath.Capacity < count) vectorPath.Capacity = count;
			
			AstarProfiler.EndProfile ();
			
			c = from;
			
			for (var i = 0;i<count;i++) {
				path.Add (c.node);
				c = c.parent;
			}
			
			var half = count/2;
			for (var i=0;i<half;i++) {
				var tmp = path[i];
				path[i] = path[count-i-1];
				path[count - i - 1] = tmp;
			}
			
			for (var i=0;i<count;i++) {
				vectorPath.Add ((Vector3)path[i].position);
			}
		}
        public override void Open(Path path, PathNode pathNode, PathHandler handler)
        {
            if (connections == null)
            {
                return;
            }

            for (int i = 0; i < connections.Length; i++)
            {
                GraphNode other = connections[i];

                if (path.CanTraverse(other))
                {
                    PathNode pathOther = handler.GetPathNode(other);

                    if (pathOther.pathID != handler.PathID)
                    {
                        //Might not be assigned
                        pathOther.node = other;

                        pathOther.parent = pathNode;
                        pathOther.pathID = handler.PathID;

                        pathOther.cost = connectionCosts[i];

                        pathOther.H = path.CalculateHScore(other);
                        other.UpdateG(path, pathOther);

                        handler.PushNode(pathOther);
                    }
                    else
                    {
                        //If not we can test if the path from this node to the other one is a better one then the one already used
                        uint tmpCost = connectionCosts[i];

                        if (pathNode.G + tmpCost + path.GetTraversalCost(other) < pathOther.G)
                        {
                            pathOther.cost   = tmpCost;
                            pathOther.parent = pathNode;

                            //other.UpdateAllG (pathOther,handler);
                            other.UpdateRecursiveG(path, pathOther, handler);

                            //handler.PushNode (pathOther);
                        }
                        else if (pathOther.G + tmpCost + path.GetTraversalCost(this) < pathNode.G && other.ContainsConnection(this))
                        {
                            //Or if the path from the other node to this one is better

                            pathNode.parent = pathOther;
                            pathNode.cost   = tmpCost;

                            //UpdateAllG (pathNode,handler);

                            UpdateRecursiveG(path, pathNode, handler);

                            //handler.PushNode (pathNode);
                        }
                    }
                }
            }
        }
Exemple #37
0
		/** Has the ending condition been fulfilled.
		 * \param node The current node.
		 * This is per default the same as asking if \a node == \a p.endNode */
		public override bool TargetFound (PathNode node) {
			return node.node == abPath.endNode;
		}
Exemple #38
0
        public override void Open(Path path, PathNode pathNode, PathHandler handler)
        {
            if (connections == null)
            {
                return;
            }

            var flag2 = pathNode.flag2;

            for (var i = connections.Length - 1; i >= 0; i--)
            {
                var other = connections[i];

                if (path.CanTraverse(other))
                {
                    var pathOther = handler.GetPathNode(other);

                    //Fast path out, worth it for triangle mesh nodes since they usually have degree 2 or 3
                    if (pathOther == pathNode.parent)
                    {
                        continue;
                    }

                    var cost = connectionCosts[i];

                    if (flag2 || pathOther.flag2)
                    {
                        cost = path.GetConnectionSpecialCost(this, other, cost);
                    }

                    if (pathOther.pathID != handler.PathID)
                    {
                        //Might not be assigned
                        pathOther.node = other;

                        pathOther.parent = pathNode;
                        pathOther.pathID = handler.PathID;

                        pathOther.cost = cost;

                        pathOther.H = path.CalculateHScore(other);
                        other.UpdateG(path, pathOther);

                        handler.PushNode(pathOther);
                    }
                    else
                    {
                        //If not we can test if the path from this node to the other one is a better one than the one already used
                        if (pathNode.G + cost + path.GetTraversalCost(other) < pathOther.G)
                        {
                            pathOther.cost   = cost;
                            pathOther.parent = pathNode;

                            other.UpdateRecursiveG(path, pathOther, handler);
                            //handler.PushNode (pathOther);
                        }
                        else if (pathOther.G + cost + path.GetTraversalCost(this) < pathNode.G && other.ContainsConnection(this))
                        {
                            //Or if the path from the other node to this one is better

                            pathNode.parent = pathOther;
                            pathNode.cost   = cost;

                            UpdateRecursiveG(path, pathNode, handler);

                            //handler.PushNode (pathNode);
                        }
                    }
                }
            }
        }
		public override void Initialize () {

			// Mark nodes to enable special connection costs for start and end nodes
			// See GetConnectionSpecialCost
			if (startNode != null) pathHandler.GetPathNode (startNode).flag2 = true;
			if (endNode != null) pathHandler.GetPathNode (endNode).flag2 = true;

			// Zero out the properties on the start node
			PathNode startRNode = pathHandler.GetPathNode (startNode);
			startRNode.node = startNode;
			startRNode.pathID = pathHandler.PathID;
			startRNode.parent = null;
			startRNode.cost = 0;
			startRNode.G = GetTraversalCost (startNode);
			startRNode.H = CalculateHScore (startNode);

			// Check if the start node is the target and complete the path if that is the case
			CompletePathIfStartIsValidTarget ();
			if (CompleteState == PathCompleteState.Complete) return;

			// Open the start node and puts its neighbours in the open list
			startNode.Open (this,startRNode,pathHandler);

			searchedNodes++;

			partialBestTarget = startRNode;

			// Any nodes left to search?
			if (pathHandler.HeapEmpty ()) {
				if (calculatePartial) {
					CompleteState = PathCompleteState.Partial;
					Trace (partialBestTarget);
				} else {
					Error ();
					LogError ("No open points, the start node didn't open any nodes");
					return;
				}
			}

			// Pop the first node off the open list
			currentR = pathHandler.PopNode ();
		}
Exemple #40
0
        public void RecalculateCosts()
        {
            if (pivots == null)
            {
                RecalculatePivots();
            }
            if (mode == HeuristicOptimizationMode.None)
            {
                return;
            }

            pivotCount = 0;

            for (int i = 0; i < pivots.Length; i++)
            {
                if (pivots[i] != null && (pivots[i].Destroyed || !pivots[i].Walkable))
                {
                    throw new System.Exception("Invalid pivot nodes (destroyed or unwalkable)");
                }
            }

            if (mode != HeuristicOptimizationMode.RandomSpreadOut)
            {
                for (int i = 0; i < pivots.Length; i++)
                {
                    if (pivots[i] == null)
                    {
                        throw new System.Exception("Invalid pivot nodes (null)");
                    }
                }
            }

            Debug.Log("Recalculating costs...");
            pivotCount = pivots.Length;

            System.Action <int> startCostCalculation = null;

            int            numComplete = 0;
            OnPathDelegate onComplete  = (Path path) => {
                numComplete++;
                if (numComplete == pivotCount)
                {
                    // Last completed path
                    ApplyGridGraphEndpointSpecialCase();
                }
            };

            startCostCalculation = (int pivotIndex) => {
                GraphNode pivot = pivots[pivotIndex];

                FloodPath floodPath = null;
                floodPath = FloodPath.Construct(pivot, onComplete);
                floodPath.immediateCallback = (Path _p) => {
                    // Handle path pooling
                    _p.Claim(this);

                    // When paths are calculated on navmesh based graphs
                    // the costs are slightly modified to match the actual target and start points
                    // instead of the node centers
                    // so we have to remove the cost for the first and last connection
                    // in each path
                    var  meshNode   = pivot as MeshNode;
                    uint costOffset = 0;
                    if (meshNode != null && meshNode.connections != null)
                    {
                        for (int i = 0; i < meshNode.connections.Length; i++)
                        {
                            costOffset = System.Math.Max(costOffset, meshNode.connections[i].cost);
                        }
                    }


                    var graphs = AstarPath.active.graphs;
                    // Process graphs in reverse order to raise probability that we encounter large NodeIndex values quicker
                    // to avoid resizing the internal array too often
                    for (int j = graphs.Length - 1; j >= 0; j--)
                    {
                        graphs[j].GetNodes(node => {
                            int idx = node.NodeIndex * pivotCount + pivotIndex;
                            EnsureCapacity(idx);
                            PathNode pn = ((IPathInternals)floodPath).PathHandler.GetPathNode(node);
                            if (costOffset > 0)
                            {
                                costs[idx] = pn.pathID == floodPath.pathID && pn.parent != null ? System.Math.Max(pn.parent.G - costOffset, 0) : 0;
                            }
                            else
                            {
                                costs[idx] = pn.pathID == floodPath.pathID ? pn.G : 0;
                            }
                        });
                    }

                    if (mode == HeuristicOptimizationMode.RandomSpreadOut && pivotIndex < pivots.Length - 1)
                    {
                        // If the next pivot is null
                        // then find the node which is furthest away from the earlier
                        // pivot points
                        if (pivots[pivotIndex + 1] == null)
                        {
                            int  best      = -1;
                            uint bestScore = 0;

                            // Actual number of nodes
                            int totCount = maxNodeIndex / pivotCount;

                            // Loop through all nodes
                            for (int j = 1; j < totCount; j++)
                            {
                                // Find the minimum distance from the node to all existing pivot points
                                uint mx = 1 << 30;
                                for (int p = 0; p <= pivotIndex; p++)
                                {
                                    mx = System.Math.Min(mx, costs[j * pivotCount + p]);
                                }

                                // Pick the node which has the largest minimum distance to the existing pivot points
                                // (i.e pick the one furthest away from the existing ones)
                                GraphNode node = ((IPathInternals)floodPath).PathHandler.GetPathNode(j).node;
                                if ((mx > bestScore || best == -1) && node != null && !node.Destroyed && node.Walkable)
                                {
                                    best      = j;
                                    bestScore = mx;
                                }
                            }

                            if (best == -1)
                            {
                                Debug.LogError("Failed generating random pivot points for heuristic optimizations");
                                return;
                            }

                            pivots[pivotIndex + 1] = ((IPathInternals)floodPath).PathHandler.GetPathNode(best).node;
                        }

                        // Start next path
                        startCostCalculation(pivotIndex + 1);
                    }

                    // Handle path pooling
                    _p.Release(this);
                };

                AstarPath.StartPath(floodPath, true);
            };

            if (mode != HeuristicOptimizationMode.RandomSpreadOut)
            {
                // All calculated in parallel
                for (int i = 0; i < pivots.Length; i++)
                {
                    startCostCalculation(i);
                }
            }
            else
            {
                // Recursive and serial
                startCostCalculation(0);
            }

            dirty = false;
        }
Exemple #41
0
		public override void Open (Path path, PathNode pathNode, PathHandler handler) {
			if (connections == null) return;
			
			for (var i=0;i<connections.Length;i++) {
				var other = connections[i];
				
				if (path.CanTraverse (other)) {
					
					var pathOther = handler.GetPathNode (other);
					
					if (pathOther.pathID != handler.PathID) {
						//Might not be assigned
						pathOther.node = other;
						
						pathOther.parent = pathNode;
						pathOther.pathID = handler.PathID;
						
						pathOther.cost = connectionCosts[i];
						
						pathOther.H = path.CalculateHScore (other);
						other.UpdateG (path, pathOther);
						
						handler.PushNode (pathOther);
					} else {
						//If not we can test if the path from this node to the other one is a better one then the one already used
						var tmpCost = connectionCosts[i];
						
						if (pathNode.G + tmpCost + path.GetTraversalCost(other) < pathOther.G) {
							
							pathOther.cost = tmpCost;
							pathOther.parent = pathNode;
							
							//other.UpdateAllG (pathOther,handler);
							other.UpdateRecursiveG (path,pathOther, handler);
							
							//handler.PushNode (pathOther);
						}
						else if (pathOther.G+tmpCost+path.GetTraversalCost(this) < pathNode.G && other.ContainsConnection (this)) {
							//Or if the path from the other node to this one is better
							
							pathNode.parent = pathOther;
							pathNode.cost = tmpCost;
							
							//UpdateAllG (pathNode,handler);
							
							UpdateRecursiveG(path, pathNode, handler);
							
							//handler.PushNode (pathNode);
						}
					}
				}
			}
		}
 // Token: 0x06002C91 RID: 11409 RVA: 0x001CA04B File Offset: 0x001C824B
 public Tuple(uint f, PathNode node)
 {
     this.F    = f;
     this.node = node;
 }
Exemple #43
0
		public override void Open (Path path, PathNode pathNode, PathHandler handler) {
			if (connections == null) return;

			// Flag2 indicates if this node needs special treatment
			// with regard to connection costs
			bool flag2 = pathNode.flag2;

			// Loop through all connections
			for (int i = connections.Length-1; i >= 0; i--) {
				GraphNode other = connections[i];

				// Make sure we can traverse the neighbour
				if (path.CanTraverse(other)) {
					PathNode pathOther = handler.GetPathNode(other);

					// Fast path out, worth it for triangle mesh nodes since they usually have degree 2 or 3
					if (pathOther == pathNode.parent) {
						continue;
					}

					uint cost = connectionCosts[i];

					if (flag2 || pathOther.flag2) {
						// Get special connection cost from the path
						// This is used by the start and end nodes
						cost = path.GetConnectionSpecialCost(this, other, cost);
					}

					// Test if we have seen the other node before
					if (pathOther.pathID != handler.PathID) {
						// We have not seen the other node before
						// So the path from the start through this node to the other node
						// must be the shortest one so far

						// Might not be assigned
						pathOther.node = other;

						pathOther.parent = pathNode;
						pathOther.pathID = handler.PathID;

						pathOther.cost = cost;

						pathOther.H = path.CalculateHScore(other);
						other.UpdateG(path, pathOther);

						handler.PushNode(pathOther);
					} else {
						// If not we can test if the path from this node to the other one is a better one than the one already used
						if (pathNode.G + cost + path.GetTraversalCost(other) < pathOther.G) {
							pathOther.cost = cost;
							pathOther.parent = pathNode;

							other.UpdateRecursiveG(path, pathOther, handler);
						} else if (pathOther.G+cost+path.GetTraversalCost(this) < pathNode.G && other.ContainsConnection(this)) {
							// Or if the path from the other node to this one is better

							pathNode.parent = pathOther;
							pathNode.cost = cost;

							UpdateRecursiveG(path, pathNode, handler);
						}
					}
				}
			}
		}
Exemple #44
0
 public override void UpdateRecursiveG(Path path, PathNode pathNode, PathHandler handler)
 {
     base.UpdateG(path, pathNode);
     handler.PushNode(pathNode);
     for (int i = 0; i < this.connections.Length; i++)
     {
         GraphNode graphNode = this.connections[i];
         PathNode pathNode2 = handler.GetPathNode(graphNode);
         if (pathNode2.parent == pathNode && pathNode2.pathID == handler.PathID)
         {
             graphNode.UpdateRecursiveG(path, pathNode2, handler);
         }
     }
 }
Exemple #45
0
		public virtual void UpdateRecursiveG (Path path, PathNode pathNode, PathHandler handler) {
			//Simple but slow default implementation
			UpdateG(path, pathNode);

			handler.PushNode(pathNode);

			GetConnections(delegate(GraphNode other) {
				PathNode otherPN = handler.GetPathNode(other);
				if (otherPN.parent == pathNode && otherPN.pathID == handler.PathID) other.UpdateRecursiveG(path, otherPN, handler);
			});
		}
Exemple #46
0
 protected virtual void Trace(PathNode from)
 {
     int num = 0;
     PathNode pathNode = from;
     while (pathNode != null)
     {
         pathNode = pathNode.parent;
         num++;
         if (num > 2048)
         {
             UnityEngine.Debug.LogWarning("Infinite loop? >2048 node path. Remove this message if you really have that long paths (Path.cs, Trace method)");
             break;
         }
     }
     if (this.path.Capacity < num)
     {
         this.path.Capacity = num;
     }
     if (this.vectorPath.Capacity < num)
     {
         this.vectorPath.Capacity = num;
     }
     pathNode = from;
     for (int i = 0; i < num; i++)
     {
         this.path.Add(pathNode.node);
         pathNode = pathNode.parent;
     }
     int num2 = num / 2;
     for (int j = 0; j < num2; j++)
     {
         GraphNode value = this.path[j];
         this.path[j] = this.path[num - j - 1];
         this.path[num - j - 1] = value;
     }
     for (int k = 0; k < num; k++)
     {
         this.vectorPath.Add((Vector3)this.path[k].position);
     }
 }
        public override void Initialize()
        {
            // Mark nodes to enable special connection costs for start and end nodes
            // See GetConnectionSpecialCost
            if (startNode != null)
            {
                pathHandler.GetPathNode(startNode).flag2 = true;
            }
            if (endNode != null)
            {
                pathHandler.GetPathNode(endNode).flag2 = true;
            }

            if (hasEndPoint && startNode == endNode)
            {
                PathNode endNodeR = pathHandler.GetPathNode(endNode);
                endNodeR.node   = endNode;
                endNodeR.parent = null;
                endNodeR.H      = 0;
                endNodeR.G      = 0;
                Trace(endNodeR);
                CompleteState = PathCompleteState.Complete;
                return;
            }

            //Adjust the costs for the end node

            /*if (hasEndPoint && recalcStartEndCosts) {
             *      endNodeCosts = endNode.InitialOpen (open,hTarget,(Int3)endPoint,this,false);
             *      callback += ResetCosts; /* \todo Might interfere with other paths since other paths might be calculated before #callback is called *
             * }*/

            PathNode startRNode = pathHandler.GetPathNode(startNode);

            startRNode.node   = startNode;
            startRNode.pathID = pathHandler.PathID;
            startRNode.parent = null;
            startRNode.cost   = 0;
            startRNode.G      = GetTraversalCost(startNode);
            startRNode.H      = CalculateHScore(startNode);

            /*if (recalcStartEndCosts) {
             *      startNode.InitialOpen (open,hTarget,startIntPoint,this,true);
             * } else {*/
            startNode.Open(this, startRNode, pathHandler);
            //}

            searchedNodes++;

            partialBestTarget = startRNode;

            //any nodes left to search?
            if (pathHandler.HeapEmpty())
            {
                if (calculatePartial)
                {
                    CompleteState = PathCompleteState.Partial;
                    Trace(partialBestTarget);
                }
                else
                {
                    Error();
                    LogError("No open points, the start node didn't open any nodes");
                    return;
                }
            }

            currentR = pathHandler.PopNode();
        }
Exemple #48
0
        public void RecalculateCosts()
        {
            if (pivots == null)
            {
                RecalculatePivots();
            }
            if (mode == HeuristicOptimizationMode.None)
            {
                return;
            }

            pivotCount = 0;

            for (int i = 0; i < pivots.Length; i++)
            {
                if (pivots[i] != null && (pivots[i].Destroyed || !pivots[i].Walkable))
                {
                    throw new System.Exception("Invalid pivot nodes (destroyed or unwalkable)");
                }
            }

            if (mode != HeuristicOptimizationMode.RandomSpreadOut)
            {
                for (int i = 0; i < pivots.Length; i++)
                {
                    if (pivots[i] == null)
                    {
                        throw new System.Exception("Invalid pivot nodes (null)");
                    }
                }
            }

            UnityEngine.Debug.Log("Recalculating costs...");
            pivotCount = pivots.Length;

            System.Action <int> startCostCalculation = null;

            startCostCalculation = delegate(int k) {
                GraphNode pivot = pivots[k];

                FloodPath fp = null;
                fp = FloodPath.Construct(pivot);
                fp.immediateCallback = delegate(Path _p) {
                    // Handle path pooling
                    _p.Claim(this);

                    // When paths are calculated on navmesh based graphs
                    // the costs are slightly modified to match the actual target and start points
                    // instead of the node centers
                    // so we have to remove the cost for the first and last connection
                    // in each path
                    MeshNode mn         = pivot as MeshNode;
                    uint     costOffset = 0;
                    if (mn != null && mn.connectionCosts != null)
                    {
                        for (int i = 0; i < mn.connectionCosts.Length; i++)
                        {
                            costOffset = System.Math.Max(costOffset, mn.connectionCosts[i]);
                        }
                    }


                    var graphs = AstarPath.active.graphs;
                    // Process graphs in reverse order to raise probability that we encounter large NodeIndex values quicker
                    // to avoid resizing the internal array too often
                    for (int j = graphs.Length - 1; j >= 0; j--)
                    {
                        graphs[j].GetNodes(delegate(GraphNode node) {
                            int idx = node.NodeIndex * pivotCount + k;
                            EnsureCapacity(idx);
                            PathNode pn = fp.pathHandler.GetPathNode(node);
                            if (costOffset > 0)
                            {
                                costs[idx] = pn.pathID == fp.pathID && pn.parent != null ? System.Math.Max(pn.parent.G - costOffset, 0) : 0;
                            }
                            else
                            {
                                costs[idx] = pn.pathID == fp.pathID ? pn.G : 0;
                            }
                            return(true);
                        });
                    }

                    if (mode == HeuristicOptimizationMode.RandomSpreadOut && k < pivots.Length - 1)
                    {
                        int  best      = -1;
                        uint bestScore = 0;

                        // Actual number of nodes
                        int totCount = maxNodeIndex / pivotCount;

                        // Loop through all nodes
                        for (int j = 1; j < totCount; j++)
                        {
                            // Find the minimum distance from the node to all existing pivot points
                            uint mx = 1 << 30;
                            for (int p = 0; p <= k; p++)
                            {
                                mx = System.Math.Min(mx, costs[j * pivotCount + p]);
                            }

                            // Pick the node which has the largest minimum distance to the existing pivot points
                            // (i.e pick the one furthest away from the existing ones)
                            GraphNode node = fp.pathHandler.GetPathNode(j).node;
                            if ((mx > bestScore || best == -1) && node != null && !node.Destroyed && node.Walkable)
                            {
                                best      = j;
                                bestScore = mx;
                            }
                        }

                        if (best == -1)
                        {
                            Debug.LogError("Failed generating random pivot points for heuristic optimizations");
                            return;
                        }

                        pivots[k + 1] = fp.pathHandler.GetPathNode(best).node;

                        Debug.Log("Found node at " + pivots[k + 1].position + " with score " + bestScore);

                        startCostCalculation(k + 1);
                    }

                    // Handle path pooling
                    _p.Release(this);
                };

                AstarPath.StartPath(fp, true);
            };

            if (mode != HeuristicOptimizationMode.RandomSpreadOut)
            {
                // All calculated in paralell
                for (int i = 0; i < pivots.Length; i++)
                {
                    startCostCalculation(i);
                }
            }
            else
            {
                // Recursive and serial
                startCostCalculation(0);
            }


            dirty = false;
        }
Exemple #49
0
 public virtual void Reset()
 {
     if (object.ReferenceEquals(AstarPath.active, null))
     {
         throw new NullReferenceException("No AstarPath object found in the scene. Make sure there is one or do not create paths in Awake");
     }
     this.hasBeenReset = true;
     this.state = PathState.Created;
     this.releasedNotSilent = false;
     this.pathHandler = null;
     this.callback = null;
     this._errorLog = string.Empty;
     this.pathCompleteState = PathCompleteState.NotCalculated;
     this.path = ListPool<GraphNode>.Claim();
     this.vectorPath = ListPool<Vector3>.Claim();
     this.currentR = null;
     this.duration = 0f;
     this.searchIterations = 0;
     this.searchedNodes = 0;
     this.nnConstraint = PathNNConstraint.Default;
     this.next = null;
     this.heuristic = AstarPath.active.heuristic;
     this.heuristicScale = AstarPath.active.heuristicScale;
     this.enabledTags = -1;
     this.tagPenalties = null;
     this.callTime = DateTime.UtcNow;
     this.pathID = AstarPath.active.GetNextPathID();
     this.hTarget = Int3.zero;
     this.hTargetNode = null;
 }
        /** Calculates the path until completed or until the time has passed \a targetTick.
         * Usually a check is only done every 500 nodes if the time has passed \a targetTick.
         * Time/Ticks are got from System.DateTime.UtcNow.Ticks.
         *
         * Basic outline of what the function does for the standard path (Pathfinding.ABPath).
         * \code
         * while the end has not been found and no error has ocurred
         * check if we have reached the end
         * if so, exit and return the path
         *
         * open the current node, i.e loop through its neighbours, mark them as visited and put them on a heap
         *
         * check if there are still nodes left to process (or have we searched the whole graph)
         * if there are none, flag error and exit
         *
         * pop the next node of the heap and set it as current
         *
         * check if the function has exceeded the time limit
         * if so, return and wait for the function to get called again
         * \endcode
         */
        public override void CalculateStep(long targetTick)
        {
            int counter = 0;

            //Continue to search while there hasn't ocurred an error and the end hasn't been found
            while (CompleteState == PathCompleteState.NotCalculated)
            {
                searchedNodes++;

                //Close the current node, if the current node is the target node then the path is finished
                if (currentR.node == endNode)
                {
                    CompleteState = PathCompleteState.Complete;
                    break;
                }

                if (currentR.H < partialBestTarget.H)
                {
                    partialBestTarget = currentR;
                }

                AstarProfiler.StartFastProfile(4);
                //Debug.DrawRay ((Vector3)currentR.node.Position, Vector3.up*2,Color.red);

                //Loop through all walkable neighbours of the node and add them to the open list.
                currentR.node.Open(this, currentR, pathHandler);

                AstarProfiler.EndFastProfile(4);

                //any nodes left to search?
                if (pathHandler.HeapEmpty())
                {
                    Error();
                    LogError("No open points, whole area searched");
                    return;
                }


                //Select the node with the lowest F score and remove it from the open list
                AstarProfiler.StartFastProfile(7);
                currentR = pathHandler.PopNode();
                AstarProfiler.EndFastProfile(7);

                //Check for time every 500 nodes, roughly every 0.5 ms usually
                if (counter > 500)
                {
                    //Have we exceded the maxFrameTime, if so we should wait one frame before continuing the search since we don't want the game to lag
                    if (System.DateTime.UtcNow.Ticks >= targetTick)
                    {
                        //Return instead of yield'ing, a separate function handles the yield (CalculatePaths)
                        return;
                    }
                    counter = 0;

                    if (searchedNodes > 1000000)
                    {
                        throw new System.Exception("Probable infinite loop. Over 1,000,000 nodes searched");
                    }
                }

                counter++;
            }


            AstarProfiler.StartProfile("Trace");

            if (CompleteState == PathCompleteState.Complete)
            {
                Trace(currentR);
            }
            else if (calculatePartial && partialBestTarget != null)
            {
                CompleteState = PathCompleteState.Partial;
                Trace(partialBestTarget);
            }

            AstarProfiler.EndProfile();
        }
		public override bool TargetFound (PathNode node) {
			return node.G >= maxGScore;
		}
        /* String builder used for all debug logging */
        //public static System.Text.StringBuilder debugStringBuilder = new System.Text.StringBuilder ();

        /** Returns a debug string for this path.
         */
        public override string DebugString(PathLog logMode)
        {
            if (logMode == PathLog.None || (!error && logMode == PathLog.OnlyErrors))
            {
                return("");
            }

            //debugStringBuilder.Length = 0;

            System.Text.StringBuilder text = new System.Text.StringBuilder();

            text.Append(error ? "Path Failed : " : "Path Completed : ");
            text.Append("Computation Time ");

            text.Append((duration).ToString(logMode == PathLog.Heavy ? "0.000" : "0.00"));
            text.Append(" ms Searched Nodes ");
            text.Append(searchedNodes);

            if (!error)
            {
                text.Append(" Path Length ");
                text.Append(path == null ? "Null" : path.Count.ToString());

                if (logMode == PathLog.Heavy)
                {
                    text.Append("\nSearch Iterations " + searchIterations);

                    if (hasEndPoint && endNode != null)
                    {
                        PathNode nodeR = pathHandler.GetPathNode(endNode);
                        text.Append("\nEnd Node\n	G: ");
                        text.Append(nodeR.G);
                        text.Append("\n	H: ");
                        text.Append(nodeR.H);
                        text.Append("\n	F: ");
                        text.Append(nodeR.F);
                        text.Append("\n	Point: ");
                        text.Append(((Vector3)endPoint).ToString());
                        text.Append("\n	Graph: ");
                        text.Append(endNode.GraphIndex);
                    }

                    text.Append("\nStart Node");
                    text.Append("\n	Point: ");
                    text.Append(((Vector3)startPoint).ToString());
                    text.Append("\n	Graph: ");
                    if (startNode != null)
                    {
                        text.Append(startNode.GraphIndex);
                    }
                    else
                    {
                        text.Append("< null startNode >");
                    }
                    //text.Append ("\nBinary Heap size at completion: ");
                    //text.Append (pathHandler.open == null ? "Null" : (pathHandler.open.numberOfItems-2).ToString ());// -2 because numberOfItems includes the next item to be added and item zero is not used
                }

                /*"\nEnd node\n	G = "+p.endNode.g+"\n	H = "+p.endNode.H+"\n	F = "+p.endNode.f+"\n	Point	"+p.endPoint
                 +"\nStart Point = "+p.startPoint+"\n"+"Start Node graph: "+p.startNode.graphIndex+" End Node graph: "+p.endNode.graphIndex+
                 * "\nBinary Heap size at completion: "+(p.open == null ? "Null" : p.open.numberOfItems.ToString ())*/
            }

            if (error)
            {
                text.Append("\nError: ");
                text.Append(errorLog);
            }

            if (logMode == PathLog.Heavy && !AstarPath.IsUsingMultithreading)
            {
                text.Append("\nCallback references ");
                if (callback != null)
                {
                    text.Append(callback.Target.GetType().FullName).AppendLine();
                }
                else
                {
                    text.AppendLine("NULL");
                }
            }

            text.Append("\nPath Number ");
            text.Append(pathID);

            return(text.ToString());
        }
Exemple #53
0
		public override void UpdateRecursiveG (Path path, PathNode pathNode, PathHandler handler) {
			GridGraph gg = GetGridGraph(GraphIndex);

			int[] neighbourOffsets = gg.neighbourOffsets;
			GridNode[] nodes = gg.nodes;

			UpdateG(path, pathNode);
			handler.PushNode(pathNode);

			ushort pid = handler.PathID;

			for (int i = 0; i < 8; i++) {
				if (GetConnectionInternal(i)) {
					GridNode other = nodes[nodeInGridIndex + neighbourOffsets[i]];
					PathNode otherPN = handler.GetPathNode(other);
					if (otherPN.parent == pathNode && otherPN.pathID == pid) other.UpdateRecursiveG(path, otherPN, handler);
				}
			}

#if !ASTAR_GRID_NO_CUSTOM_CONNECTIONS
			if (connections != null) for (int i = 0; i < connections.Length; i++) {
					GraphNode other = connections[i];
					PathNode otherPN = handler.GetPathNode(other);
					if (otherPN.parent == pathNode && otherPN.pathID == pid) other.UpdateRecursiveG(path, otherPN, handler);
				}
#endif
		}
 public override bool TargetFound(PathNode node)
 {
     return(node.G >= this.maxGScore);
 }
Exemple #55
0
		public override void Open (Path path, PathNode pathNode, PathHandler handler) {
			GridGraph gg = GetGridGraph(GraphIndex);

			ushort pid = handler.PathID;

#if ASTAR_JPS
			if (gg.useJumpPointSearch && !path.FloodingPath) {
				JPSOpen(path, pathNode, handler);
			} else
#endif
			{
				int[] neighbourOffsets = gg.neighbourOffsets;
				uint[] neighbourCosts = gg.neighbourCosts;
				GridNode[] nodes = gg.nodes;

				for (int i = 0; i < 8; i++) {
					if (GetConnectionInternal(i)) {
						GridNode other = nodes[nodeInGridIndex + neighbourOffsets[i]];
						if (!path.CanTraverse(other)) continue;

						PathNode otherPN = handler.GetPathNode(other);

						uint tmpCost = neighbourCosts[i];

						if (otherPN.pathID != pid) {
							otherPN.parent = pathNode;
							otherPN.pathID = pid;

							otherPN.cost = tmpCost;

							otherPN.H = path.CalculateHScore(other);
							other.UpdateG(path, otherPN);

							//Debug.Log ("G " + otherPN.G + " F " + otherPN.F);
							handler.PushNode(otherPN);
							//Debug.DrawRay ((Vector3)otherPN.node.Position, Vector3.up,Color.blue);
						} else {
							// Sorry for the huge number of #ifs

							//If not we can test if the path from the current node to this one is a better one then the one already used

#if ASTAR_NO_TRAVERSAL_COST
							if (pathNode.G+tmpCost < otherPN.G)
#else
							if (pathNode.G+tmpCost+path.GetTraversalCost(other) < otherPN.G)
#endif
							{
								//Debug.Log ("Path better from " + NodeIndex + " to " + otherPN.node.NodeIndex + " " + (pathNode.G+tmpCost+path.GetTraversalCost(other)) + " < " + otherPN.G);
								otherPN.cost = tmpCost;

								otherPN.parent = pathNode;

								other.UpdateRecursiveG(path, otherPN, handler);

								//Or if the path from this node ("other") to the current ("current") is better
							}
#if ASTAR_NO_TRAVERSAL_COST
							else if (otherPN.G+tmpCost < pathNode.G)
#else
							else if (otherPN.G+tmpCost+path.GetTraversalCost(this) < pathNode.G)
#endif
							{
								//Debug.Log ("Path better from " + otherPN.node.NodeIndex + " to " + NodeIndex + " " + (otherPN.G+tmpCost+path.GetTraversalCost (this)) + " < " + pathNode.G);
								pathNode.parent = otherPN;
								pathNode.cost = tmpCost;

								UpdateRecursiveG(path, pathNode, handler);
							}
						}
					}
				}
			}

#if !ASTAR_GRID_NO_CUSTOM_CONNECTIONS
			if (connections != null) for (int i = 0; i < connections.Length; i++) {
					GraphNode other = connections[i];
					if (!path.CanTraverse(other)) continue;

					PathNode otherPN = handler.GetPathNode(other);

					uint tmpCost = connectionCosts[i];

					if (otherPN.pathID != pid) {
						otherPN.parent = pathNode;
						otherPN.pathID = pid;

						otherPN.cost = tmpCost;

						otherPN.H = path.CalculateHScore(other);
						other.UpdateG(path, otherPN);

						//Debug.Log ("G " + otherPN.G + " F " + otherPN.F);
						handler.PushNode(otherPN);
						//Debug.DrawRay ((Vector3)otherPN.node.Position, Vector3.up,Color.blue);
					} else {
						// Sorry for the huge number of #ifs

						//If not we can test if the path from the current node to this one is a better one then the one already used

#if ASTAR_NO_TRAVERSAL_COST
						if (pathNode.G+tmpCost < otherPN.G)
#else
						if (pathNode.G+tmpCost+path.GetTraversalCost(other) < otherPN.G)
#endif
						{
							//Debug.Log ("Path better from " + NodeIndex + " to " + otherPN.node.NodeIndex + " " + (pathNode.G+tmpCost+path.GetTraversalCost(other)) + " < " + otherPN.G);
							otherPN.cost = tmpCost;

							otherPN.parent = pathNode;

							other.UpdateRecursiveG(path, otherPN, handler);

							//Or if the path from this node ("other") to the current ("current") is better
						}
#if ASTAR_NO_TRAVERSAL_COST
						else if (otherPN.G+tmpCost < pathNode.G && other.ContainsConnection(this))
#else
						else if (otherPN.G+tmpCost+path.GetTraversalCost(this) < pathNode.G && other.ContainsConnection(this))
#endif
						{
							//Debug.Log ("Path better from " + otherPN.node.NodeIndex + " to " + NodeIndex + " " + (otherPN.G+tmpCost+path.GetTraversalCost (this)) + " < " + pathNode.G);
							pathNode.parent = otherPN;
							pathNode.cost = tmpCost;

							UpdateRecursiveG(path, pathNode, handler);
						}
					}
				}
#endif
		}
Exemple #56
0
 public void PushNode(PathNode node)
 {
     this.heap.Add(node);
 }
		public override void Open (Path path, PathNode pathNode, PathHandler handler) {

			//BaseOpen (nodeRunData, nodeR, targetPosition, path);

			LayerGridGraph graph = GetGridGraph(GraphIndex);
			int[] neighbourOffsets = graph.neighbourOffsets;
			uint[] neighbourCosts = graph.neighbourCosts;
			LevelGridNode[] nodes = graph.nodes;

			int index = NodeInGridIndex;//indices & 0xFFFFFF;

			for (int i=0;i<4;i++) {
				int conn = GetConnectionValue(i);//(gridConnections >> i*4) & 0xF;
				if (conn != LevelGridNode.NoConnection) {

					GraphNode other = nodes[index+neighbourOffsets[i] + graph.lastScannedWidth*graph.lastScannedDepth*conn];

					if (!path.CanTraverse (other)) {
						continue;
					}

					PathNode otherPN = handler.GetPathNode (other);

					if (otherPN.pathID != handler.PathID) {
						otherPN.parent = pathNode;
						otherPN.pathID = handler.PathID;

						otherPN.cost = neighbourCosts[i];

						otherPN.H = path.CalculateHScore (other);
						other.UpdateG (path, otherPN);

						handler.PushNode (otherPN);

					} else {
						//If not we can test if the path from the current node to this one is a better one then the one already used
						uint tmpCost = neighbourCosts[i];

#if ASTAR_NO_TRAVERSAL_COST
						if (pathNode.G + tmpCost < otherPN.G)
#else
						if (pathNode.G + tmpCost + path.GetTraversalCost(other) < otherPN.G)
#endif
						{
							otherPN.cost = tmpCost;

							otherPN.parent = pathNode;

							other.UpdateRecursiveG (path,otherPN, handler);

						}
						//Or if the path from this node ("other") to the current ("current") is better
#if ASTAR_NO_TRAVERSAL_COST
						else if (otherPN.G+tmpCost < pathNode.G)
#else
						else if (otherPN.G+tmpCost+path.GetTraversalCost(this) < pathNode.G)
#endif
						{
							pathNode.parent = otherPN;
							pathNode.cost = tmpCost;

							UpdateRecursiveG(path, pathNode, handler);
						}
					}
				}
			}
		}
        /* Color to use for gizmos.
         * Returns a color to be used for the specified node with the current debug settings (editor only)
         */
        public virtual Color NodeColor(GraphNode node, PathHandler data)
        {
            Color c      = AstarColor.NodeConnection;
            bool  colSet = false;

            if (node == null)
            {
                return(AstarColor.NodeConnection);
            }

            switch (AstarPath.active.debugMode)
            {
            case GraphDebugMode.Areas:
                c      = AstarColor.GetAreaColor(node.Area);
                colSet = true;
                break;

            case GraphDebugMode.Penalty:
                c      = Color.Lerp(AstarColor.ConnectionLowLerp, AstarColor.ConnectionHighLerp, (float)node.Penalty / (float)AstarPath.active.debugRoof);
                colSet = true;
                break;

            case GraphDebugMode.Tags:
                c      = AstarMath.IntToColor((int)node.Tag, 0.5F);
                colSet = true;
                break;

                /* Wasn't really usefull
                 * case GraphDebugMode.Position:
                 *      float r = Mathf.PingPong (node.position.x/10000F,1F) + Mathf.PingPong (node.position.x/300000F,1F);
                 *      float g = Mathf.PingPong (node.position.y/10000F,1F) + Mathf.PingPong (node.position.y/200000F,1F);
                 *      float b = Mathf.PingPong (node.position.z/10000F,1F) + Mathf.PingPong (node.position.z/100000F,1F);
                 *
                 *
                 *      c = new Color (r,g,b);
                 *      break;
                 */
            }

            if (!colSet)
            {
                if (data == null)
                {
                    return(AstarColor.NodeConnection);
                }

                PathNode nodeR = data.GetPathNode(node);

                switch (AstarPath.active.debugMode)
                {
                case GraphDebugMode.G:
                    //c = Mathfx.IntToColor (node.g,0.5F);
                    c = Color.Lerp(AstarColor.ConnectionLowLerp, AstarColor.ConnectionHighLerp, (float)nodeR.G / (float)AstarPath.active.debugRoof);
                    break;

                case GraphDebugMode.H:
                    c = Color.Lerp(AstarColor.ConnectionLowLerp, AstarColor.ConnectionHighLerp, (float)nodeR.H / (float)AstarPath.active.debugRoof);
                    break;

                case GraphDebugMode.F:
                    c = Color.Lerp(AstarColor.ConnectionLowLerp, AstarColor.ConnectionHighLerp, (float)nodeR.F / (float)AstarPath.active.debugRoof);
                    break;
                }
            }
            c.a *= 0.5F;
            return(c);
        }
Exemple #59
0
 public override void UpdateRecursiveG(Path path, PathNode pathNode, PathHandler handler)
 {
     GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex);
     int[] neighbourOffsets = gridGraph.neighbourOffsets;
     GridNode[] nodes = gridGraph.nodes;
     base.UpdateG(path, pathNode);
     handler.PushNode(pathNode);
     ushort pathID = handler.PathID;
     for (int i = 0; i < 8; i++)
     {
         if (this.GetConnectionInternal(i))
         {
             GridNode gridNode = nodes[this.nodeInGridIndex + neighbourOffsets[i]];
             PathNode pathNode2 = handler.GetPathNode(gridNode);
             if (pathNode2.parent == pathNode && pathNode2.pathID == pathID)
             {
                 gridNode.UpdateRecursiveG(path, pathNode2, handler);
             }
         }
     }
     if (this.connections != null)
     {
         for (int j = 0; j < this.connections.Length; j++)
         {
             GraphNode graphNode = this.connections[j];
             PathNode pathNode3 = handler.GetPathNode(graphNode);
             if (pathNode3.parent == pathNode && pathNode3.pathID == pathID)
             {
                 graphNode.UpdateRecursiveG(path, pathNode3, handler);
             }
         }
     }
 }
Exemple #60
0
        /** Returns the node with the lowest F score from the heap */
        public PathNode Remove()
        {
            numberOfItems--;
            PathNode returnItem = binaryHeap[0].node;

            binaryHeap[0] = binaryHeap[numberOfItems];

            int swapItem = 0, parent;

            do
            {
                if (D == 0)
                {
                    parent = swapItem;
                    int p2 = parent * D;
                    if (p2 + 1 <= numberOfItems)
                    {
                        // Both children exist
                        if (binaryHeap[parent].F > binaryHeap[p2].F)
                        {
                            swapItem = p2;                            //2 * parent;
                        }
                        if (binaryHeap[swapItem].F > binaryHeap[p2 + 1].F)
                        {
                            swapItem = p2 + 1;
                        }
                    }
                    else if ((p2) <= numberOfItems)
                    {
                        // Only one child exists
                        if (binaryHeap[parent].F > binaryHeap[p2].F)
                        {
                            swapItem = p2;
                        }
                    }
                }
                else
                {
                    parent = swapItem;
                    uint swapF = binaryHeap[swapItem].F;
                    int  pd    = parent * D + 1;

                    if (D >= 1 && pd + 0 <= numberOfItems && (binaryHeap[pd + 0].F < swapF || (SortGScores && binaryHeap[pd + 0].F == swapF && binaryHeap[pd + 0].node.G < binaryHeap[swapItem].node.G)))
                    {
                        swapF    = binaryHeap[pd + 0].F;
                        swapItem = pd + 0;
                    }

                    if (D >= 2 && pd + 1 <= numberOfItems && (binaryHeap[pd + 1].F < swapF || (SortGScores && binaryHeap[pd + 1].F == swapF && binaryHeap[pd + 1].node.G < binaryHeap[swapItem].node.G)))
                    {
                        swapF    = binaryHeap[pd + 1].F;
                        swapItem = pd + 1;
                    }

                    if (D >= 3 && pd + 2 <= numberOfItems && (binaryHeap[pd + 2].F < swapF || (SortGScores && binaryHeap[pd + 2].F == swapF && binaryHeap[pd + 2].node.G < binaryHeap[swapItem].node.G)))
                    {
                        swapF    = binaryHeap[pd + 2].F;
                        swapItem = pd + 2;
                    }

                    if (D >= 4 && pd + 3 <= numberOfItems && (binaryHeap[pd + 3].F < swapF || (SortGScores && binaryHeap[pd + 3].F == swapF && binaryHeap[pd + 3].node.G < binaryHeap[swapItem].node.G)))
                    {
                        swapF    = binaryHeap[pd + 3].F;
                        swapItem = pd + 3;
                    }

                    if (D >= 5 && pd + 4 <= numberOfItems && binaryHeap[pd + 4].F < swapF)
                    {
                        swapF    = binaryHeap[pd + 4].F;
                        swapItem = pd + 4;
                    }

                    if (D >= 6 && pd + 5 <= numberOfItems && binaryHeap[pd + 5].F < swapF)
                    {
                        swapF    = binaryHeap[pd + 5].F;
                        swapItem = pd + 5;
                    }

                    if (D >= 7 && pd + 6 <= numberOfItems && binaryHeap[pd + 6].F < swapF)
                    {
                        swapF    = binaryHeap[pd + 6].F;
                        swapItem = pd + 6;
                    }

                    if (D >= 8 && pd + 7 <= numberOfItems && binaryHeap[pd + 7].F < swapF)
                    {
                        swapF    = binaryHeap[pd + 7].F;
                        swapItem = pd + 7;
                    }

                    if (D >= 9 && pd + 8 <= numberOfItems && binaryHeap[pd + 8].F < swapF)
                    {
                        swapF    = binaryHeap[pd + 8].F;
                        swapItem = pd + 8;
                    }
                }

                // One if the parent's children are smaller or equal, swap them
                if (parent != swapItem)
                {
                    var tmpIndex = binaryHeap[parent];
                    binaryHeap[parent]   = binaryHeap[swapItem];
                    binaryHeap[swapItem] = tmpIndex;
                }
                else
                {
                    break;
                }
            } while (true);

            //Validate ();

            return(returnItem);
        }