private CellRefNode ProfilingDequeue(Priority_Queue.FastPriorityQueue <CellRefNode> queue) { ProfilerStart("Dequeue"); CellRefNode node = queue.Dequeue(); ProfilerEnd("Dequeue"); return(node); }
/// <summary> /// Converts a CellRef to a CellRefNode. Caches nodes to ensure Contains() and similar methods function /// properly on the priority queue. /// </summary> /// <returns>The node.</returns> /// <param name="cellRef">Cell reference.</param> private CellRefNode GetNode(CellRef cellRef) { if (!cellRefNodeCache.ContainsKey(cellRef)) { cellRefNodeCache[cellRef] = new CellRefNode(cellRef); } return(cellRefNodeCache[cellRef]); }
/// <summary> /// Converts a CellRef to a CellRefNode. Caches nodes to ensure Contains() and similar methods function /// properly on the priority queue. /// </summary> /// <returns>The node.</returns> /// <param name="cellRef">Cell reference.</param> private CellRefNode GetNode(CellRef cellRef, Direction direction) { if (!cellRefNodeCache.ContainsKey(cellRef)) { cellRefNodeCache[cellRef] = new CellRefNode(cellRef); } cellRefNodeCache[cellRef].enterDirection = direction; return(cellRefNodeCache[cellRef]); }
public override PawnPath FindPath() { ProfilerStart("Total Time"); // Prime the closed and open sets closedSet[startCell] = new CellNode { knownCost = 0, heuristicCost = ProfilingHeuristic(startCell), parent = null }; ProfilerCount("Closed - Total"); if (pathfindData.CellIsInDestination(startCell)) { ProfilerListStats(); DebugDrawFinalPath(); //TODO //debugVisualizer.RegisterReplay(debugReplay); return(FinalizedPath(startCell)); } foreach (Direction direction in DirectionUtils.AllDirections) { CellRef neighbor = direction.From(startCell); if (neighbor.InBounds()) { MoveData moveData = new MoveData(neighbor, direction); if (!ProfilingMoveIsValid(moveData)) { continue; } int moveCost = ProfilingCalcMoveCost(moveData); int heuristic = ProfilingHeuristic(neighbor); ProfilerCount("Open - New"); ProfilerCount("Open - Total"); closedSet[neighbor] = new CellNode { knownCost = moveCost, heuristicCost = heuristic, parent = startCell }; ProfilingEnqueue(openSet, GetNode(direction.From(startCell), direction), moveCost + heuristic); } } // Main A* Loop int closedNodes = 0; while (openSet.Count > 0) { CellRefNode current = ProfilingDequeue(openSet); debugReplay.DrawCell(current); debugReplay.NextFrame(); ProfilerCount("Closed - Total"); // Check if we've reached our goal if (pathfindData.CellIsInDestination(current)) { ProfilerListStats(); DebugDrawFinalPath();//TODO //debugVisualizer.RegisterReplay(debugReplay); return(FinalizedPath(current)); } // Check if we hit the searchLimit if (closedNodes > SearchLimit) { Log.Warning(string.Format("[Trailblazer] {0} pathing from {1} to {2} hit search limit of {3} cells.", pathfindData.traverseParms.pawn, startCell, destCell, SearchLimit)); ProfilerListStats(); DebugDrawFinalPath(); //TODO //debugVisualizer.RegisterReplay(debugReplay); return(PawnPath.NotFound); } foreach (Direction direction in DirectionUtils.AllBut(current.enterDirection.Opposite())) { CellRef neighbor = direction.From(current); if (neighbor.InBounds()) { //debugReplay.DrawLine(current, neighbor); //debugReplay.NextFrame(); ProfilerCount("Moves - Total"); MoveData moveData = new MoveData(neighbor, direction); if (!ProfilingMoveIsValid(moveData)) { ProfilerCount("Moves - Invalid"); continue; } ProfilerCount("Moves - Valid"); int neighborNewCost = closedSet[current].knownCost + ProfilingCalcMoveCost(moveData); if (!closedSet.ContainsKey(neighbor) || closedSet[neighbor].knownCost > neighborNewCost) { if (!closedSet.ContainsKey(neighbor)) { closedSet[neighbor] = new CellNode { heuristicCost = ProfilingHeuristic(neighbor) }; ProfilerCount("Open - New"); } else { ProfilerCount("Open - Reopened"); } closedSet[neighbor].knownCost = neighborNewCost; closedSet[neighbor].parent = current; ProfilingEnqueue(openSet, GetNode(neighbor, direction), closedSet[neighbor].TotalCost); ProfilerCount("Open - Total"); ProfilerMax("Open Set Max", openSet.Count); } else { ProfilerCount("Rescanned Nodes"); } } } closedNodes++; } Pawn pawn = pathfindData.traverseParms.pawn; string currentJob = pawn?.CurJob?.ToString() ?? "null"; string faction = pawn?.Faction?.ToString() ?? "null"; Log.Warning(string.Format("[Trailblazer] {0} pathing from {1} to {2} ran out of cells to process.\n" + "Job: {3}\nFaction: {4}", pawn, startCell, destCell, currentJob, faction)); ProfilerListStats(); DebugDrawFinalPath();//TODO //debugVisualizer.RegisterReplay(debugReplay); return(PawnPath.NotFound); }
private void ProfilingEnqueue(Priority_Queue.FastPriorityQueue <CellRefNode> queue, CellRefNode node, int priority) { ProfilerStart("Enqueue"); if (queue.Contains(node)) { queue.UpdatePriority(node, priority); } else { queue.Enqueue(node, priority); } ProfilerEnd("Enqueue"); }
/// <summary> /// Initiates or resumes RRA* pathfinding to the given target. /// This variant of RRA* paths on the same grid as the main A* pather but only uses a subset of rules /// </summary> /// <returns>The region link closest to the target cell</returns> /// <param name="targetCell">Target cell.</param> private void ReverseResumableAStar(CellRef targetCell) { ProfilerStart("RRA"); ProfilerStart("RRA Reprioritize"); // Rebuild the open set based on the new target CellRefNode[] cachedNodes = rraOpenSet.ToArray(); // Cache the nodes because we'll be messing with the queue foreach (CellRefNode cell in cachedNodes) { rraOpenSet.UpdatePriority(cell, rraClosedSet[cell] + RRAHeuristic(cell, targetCell)); } ProfilerEnd("RRA Reprioritize"); int closedNodes = 0; while (rraOpenSet.Count > 0) { CellRef current = rraOpenSet.Dequeue(); debugReplay.DrawCell(current); ProfilerCount("RRA Closed"); // Check if we've reached our goal if (current.Equals(targetCell)) { ProfilerEnd("RRA"); return; } if (closedNodes > SearchLimit) { Log.Error("[Trailblazer] RRA* Heuristic closed too many cells, aborting"); ProfilerEnd("RRA"); return; } foreach (Direction direction in DirectionUtils.AllDirections) { IntVec3 neighborCell = direction.From(current); CellRef neighbor = map.GetCellRef(neighborCell); ProfilerStart("RRA Bounds Check"); bool inBounds = neighborCell.InBounds(map); ProfilerEnd("RRA Bounds Check"); if (inBounds) { MoveData moveData = new MoveData(neighbor, direction); ProfilerStart("RRA Move Check"); bool passable = rraPathfinderGrid.MoveIsValid(moveData); ProfilerEnd("RRA Move Check"); if (!passable) { continue; } ProfilerStart("RRA Move Cost"); int newCost = rraClosedSet[current] + rraPathfinderGrid.MoveCost(moveData); ProfilerEnd("RRA Move Cost"); if (!rraClosedSet.ContainsKey(neighbor) || newCost < rraClosedSet[neighbor]) { if (rraClosedSet.ContainsKey(neighbor)) { ProfilerCount("RRA Reopened"); } else { ProfilerCount("RRA New Open"); } rraClosedSet[neighbor] = newCost; int estimatedCost = newCost + RRAHeuristic(neighbor, targetCell); ProfilerStart("RRA Enqueue"); CellRefNode neighborNode = GetNode(neighbor); if (rraOpenSet.Contains(neighborNode)) { rraOpenSet.UpdatePriority(neighborNode, estimatedCost); } else { rraOpenSet.Enqueue(neighborNode, estimatedCost); } ProfilerEnd("RRA Enqueue"); } else { ProfilerCount("RRA Rescanned"); } } } debugReplay.NextFrame(); closedNodes++; } Log.Error("[Trailblazer] RRA heuristic failed to reach target cell " + targetCell); ProfilerEnd("RRA"); }