Beispiel #1
0
        public static void Run(
            IEnumerable <IntVec3> startingNodes,
            Func <IntVec3, IEnumerable <IntVec3> > neighborsGetter,
            Func <IntVec3, IntVec3, float> distanceGetter,
            List <KeyValuePair <IntVec3, float> > outDistances,
            Dictionary <IntVec3, IntVec3> outParents = null)
        {
            outDistances.Clear();
            //distances.Clear();
            Dictionary <IntVec3, float> distances = new Dictionary <IntVec3, float>();
            //queue.Clear();
            FastPriorityQueue <KeyValuePair <IntVec3, float> > queue = new FastPriorityQueue <KeyValuePair <IntVec3, float> >((IComparer <KeyValuePair <IntVec3, float> >) new DistanceComparer());

            outParents?.Clear();
            if (startingNodes is IList <IntVec3> objList)
            {
                for (int index = 0; index < objList.Count; ++index)
                {
                    IntVec3 key;
                    try
                    {
                        key = objList[index];
                    } catch (ArgumentOutOfRangeException)
                    {
                        break;
                    }
                    if (!distances.ContainsKey(key))
                    {
                        distances.Add(key, 0.0f);
                        queue.Push(new KeyValuePair <IntVec3, float>(key, 0.0f));
                    }
                }
            }
            else
            {
                foreach (IntVec3 startingNode in startingNodes)
                {
                    if (!distances.ContainsKey(startingNode))
                    {
                        distances.Add(startingNode, 0.0f);
                        queue.Push(new KeyValuePair <IntVec3, float>(startingNode, 0.0f));
                    }
                }
            }
            while (queue.Count > 0)
            {
                KeyValuePair <IntVec3, float> node = queue.Pop();
                {
                    IntVec3 nodeKey = node.Key;
                    // NEED TO FIX HACK (contains key)
                    if (distances.ContainsKey(nodeKey))
                    {
                        float distance = distances[nodeKey];
                        if ((double)node.Value == (double)distance)
                        {
                            IEnumerable <IntVec3> objs = neighborsGetter(node.Key);
                            if (objs != null)
                            {
                                if (objs is IList <IntVec3> objList2)
                                {
                                    for (int index = 0; index < objList2.Count; ++index)
                                    {
                                        HandleNeighbor2(distances, queue, objList2[index], distance, node, distanceGetter, outParents);
                                    }
                                }
                                else
                                {
                                    foreach (IntVec3 n in objs)
                                    {
                                        HandleNeighbor2(distances, queue, n, distance, node, distanceGetter, outParents);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            foreach (KeyValuePair <IntVec3, float> distance in distances)
            {
                outDistances.Add(distance);
            }
            distances.Clear();
        }
Beispiel #2
0
        public WorldPath FindPath(int startTile, int destTile, Caravan caravan, Func <float, bool> terminator = null)
        {
            if (startTile < 0)
            {
                Log.Error("Tried to FindPath with invalid start tile " + startTile + ", caravan= " + caravan);
                return(WorldPath.NotFound);
            }
            if (destTile < 0)
            {
                Log.Error("Tried to FindPath with invalid dest tile " + destTile + ", caravan= " + caravan);
                return(WorldPath.NotFound);
            }
            if (caravan != null)
            {
                if (!caravan.CanReach(destTile))
                {
                    return(WorldPath.NotFound);
                }
            }
            else if (!Find.WorldReachability.CanReach(startTile, destTile))
            {
                return(WorldPath.NotFound);
            }
            World      world = Find.World;
            WorldGrid  grid  = world.grid;
            List <int> tileIDToNeighbors_offsets = grid.tileIDToNeighbors_offsets;
            List <int> tileIDToNeighbors_values  = grid.tileIDToNeighbors_values;
            Vector3    normalized = grid.GetTileCenter(destTile).normalized;

            float[] movementDifficulty = world.pathGrid.movementDifficulty;
            int     num  = 0;
            int     num2 = caravan?.TicksPerMove ?? 3300;
            int     num3 = CalculateHeuristicStrength(startTile, destTile);

            statusOpenValue   += 2;
            statusClosedValue += 2;
            if (statusClosedValue >= 65435)
            {
                ResetStatuses();
            }
            calcGrid[startTile].knownCost     = 0;
            calcGrid[startTile].heuristicCost = 0;
            calcGrid[startTile].costNodeCost  = 0;
            calcGrid[startTile].parentTile    = startTile;
            calcGrid[startTile].status        = statusOpenValue;
            openList.Clear();
            openList.Push(new CostNode(startTile, 0));
            while (true)
            {
                if (openList.Count <= 0)
                {
                    Log.Warning(caravan + " pathing from " + startTile + " to " + destTile + " ran out of tiles to process.");
                    return(WorldPath.NotFound);
                }
                CostNode costNode = openList.Pop();
                if (costNode.cost != calcGrid[costNode.tile].costNodeCost)
                {
                    continue;
                }
                int tile = costNode.tile;
                if (calcGrid[tile].status == statusClosedValue)
                {
                    continue;
                }
                if (tile == destTile)
                {
                    return(FinalizedPath(tile));
                }
                if (num > 500000)
                {
                    Log.Warning(caravan + " pathing from " + startTile + " to " + destTile + " hit search limit of " + 500000 + " tiles.");
                    return(WorldPath.NotFound);
                }
                int num4 = (tile + 1 < tileIDToNeighbors_offsets.Count) ? tileIDToNeighbors_offsets[tile + 1] : tileIDToNeighbors_values.Count;
                for (int i = tileIDToNeighbors_offsets[tile]; i < num4; i++)
                {
                    int num5 = tileIDToNeighbors_values[i];
                    if (calcGrid[num5].status == statusClosedValue || world.Impassable(num5))
                    {
                        continue;
                    }
                    int    num6   = (int)((float)num2 * movementDifficulty[num5] * grid.GetRoadMovementDifficultyMultiplier(tile, num5)) + calcGrid[tile].knownCost;
                    ushort status = calcGrid[num5].status;
                    if ((status != statusClosedValue && status != statusOpenValue) || calcGrid[num5].knownCost > num6)
                    {
                        Vector3 tileCenter = grid.GetTileCenter(num5);
                        if (status != statusClosedValue && status != statusOpenValue)
                        {
                            float num7 = grid.ApproxDistanceInTiles(GenMath.SphericalDistance(tileCenter.normalized, normalized));
                            calcGrid[num5].heuristicCost = Mathf.RoundToInt((float)num2 * num7 * (float)num3 * 0.5f);
                        }
                        int num8 = num6 + calcGrid[num5].heuristicCost;
                        calcGrid[num5].parentTile   = tile;
                        calcGrid[num5].knownCost    = num6;
                        calcGrid[num5].status       = statusOpenValue;
                        calcGrid[num5].costNodeCost = num8;
                        openList.Push(new CostNode(num5, num8));
                    }
                }
                num++;
                calcGrid[tile].status = statusClosedValue;
                if (terminator != null && terminator(calcGrid[tile].costNodeCost))
                {
                    break;
                }
            }
            return(WorldPath.NotFound);
        }
        //public static FastPriorityQueue<CostNode2> openList = new FastPriorityQueue<CostNode2>(new CostNodeComparer2());
        //public static PathFinderNodeFast[] calcGrid = new PathFinderNodeFast[40000];
        //public static ushort statusOpenValue = 1;
        //public static ushort statusClosedValue = 2;
        public static bool FindPath(PathFinder __instance, ref PawnPath __result, IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell)
        {
            FastPriorityQueue <CostNode2> openList = getOpenList();
            ushort statusOpenValue   = getOpenValue();
            ushort statusClosedValue = getClosedValue();

            PathFinderNodeFast[]        calcGrid             = getCalcGrid(__instance);
            RegionCostCalculatorWrapper regionCostCalculator = getRegionCostCalculatorWrapper(__instance);

            if (DebugSettings.pathThroughWalls)
            {
                traverseParms.mode = TraverseMode.PassAllDestroyableThings;
            }

            Pawn pawn = traverseParms.pawn;

            if (pawn != null && pawn.Map != mapField(__instance))
            {
                Log.Error(string.Concat("Tried to FindPath for pawn which is spawned in another map. His map PathFinder should have been used, not this one. pawn=", pawn, " pawn.Map=", pawn.Map, " map=", mapField(__instance)));
                __result = PawnPath.NotFound;
                return(false);
            }

            if (!start.IsValid)
            {
                Log.Error(string.Concat("Tried to FindPath with invalid start ", start, ", pawn= ", pawn));
                __result = PawnPath.NotFound;
                return(false);
            }

            if (!dest.IsValid)
            {
                Log.Error(string.Concat("Tried to FindPath with invalid dest ", dest, ", pawn= ", pawn));
                __result = PawnPath.NotFound;
                return(false);
            }

            if (traverseParms.mode == TraverseMode.ByPawn)
            {
                if (!pawn.CanReach(dest, peMode, Danger.Deadly, traverseParms.canBash, traverseParms.mode))
                {
                    __result = PawnPath.NotFound;
                    return(false);
                }
            }
            else if (!mapField(__instance).reachability.CanReach(start, dest, peMode, traverseParms))
            {
                __result = PawnPath.NotFound;
                return(false);
            }

            PfProfilerBeginSample(string.Concat("FindPath for ", pawn, " from ", start, " to ", dest, dest.HasThing ? (" at " + dest.Cell) : ""));
            cellIndicesField(__instance)   = mapField(__instance).cellIndices;
            pathGridField(__instance)      = mapField(__instance).pathGrid;
            edificeGridField(__instance)   = mapField(__instance).edificeGrid.InnerArray;
            blueprintGridField(__instance) = mapField(__instance).blueprintGrid.InnerArray;
            int      x               = dest.Cell.x;
            int      z               = dest.Cell.z;
            int      curIndex        = cellIndicesField(__instance).CellToIndex(start);
            int      num             = cellIndicesField(__instance).CellToIndex(dest.Cell);
            ByteGrid byteGrid        = pawn?.GetAvoidGrid();
            bool     flag            = traverseParms.mode == TraverseMode.PassAllDestroyableThings || traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag2           = traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag3           = !flag;
            CellRect destinationRect = CalculateDestinationRect(dest, peMode);
            bool     flag4           = destinationRect.Width == 1 && destinationRect.Height == 1;

            int[]        array       = mapField(__instance).pathGrid.pathGrid;
            TerrainDef[] topGrid     = mapField(__instance).terrainGrid.topGrid;
            EdificeGrid  edificeGrid = mapField(__instance).edificeGrid;
            int          num2        = 0;
            int          num3        = 0;
            Area         allowedArea = GetAllowedArea(pawn);
            bool         flag5       = pawn != null && PawnUtility.ShouldCollideWithPawns(pawn);
            bool         flag6       = !flag && start.GetRegion(mapField(__instance)) != null && flag2;
            bool         flag7       = !flag || !flag3;
            bool         flag8       = false;
            bool         flag9       = pawn?.Drafted ?? false;
            int          num4        = (pawn?.IsColonist ?? false) ? 100000 : 2000;
            int          num5        = 0;
            int          num6        = 0;
            float        num7        = DetermineHeuristicStrength(pawn, start, dest);
            int          num8;
            int          num9;

            if (pawn != null)
            {
                num8 = pawn.TicksPerMoveCardinal;
                num9 = pawn.TicksPerMoveDiagonal;
            }
            else
            {
                num8 = 13;
                num9 = 18;
            }

            CalculateAndAddDisallowedCorners2(disallowedCornerIndicesField(__instance), mapField(__instance), peMode, destinationRect);
            InitStatusesAndPushStartNode3(ref curIndex, start, cellIndicesField(__instance), calcGrid, ref statusOpenValue, ref statusClosedValue);
            openList.Clear();
            openList.Push(new CostNode2(curIndex, 0));
            while (true)
            {
                PfProfilerBeginSample("Open cell");
                if (openList.Count <= 0)
                {
                    string text  = (pawn != null && pawn.CurJob != null) ? pawn.CurJob.ToString() : "null";
                    string text2 = (pawn != null && pawn.Faction != null) ? pawn.Faction.ToString() : "null";
                    Log.Warning(string.Concat(pawn, " pathing from ", start, " to ", dest, " ran out of cells to process.\nJob:", text, "\nFaction: ", text2));
                    DebugDrawRichData();
                    PfProfilerEndSample();
                    PfProfilerEndSample();
                    __result = PawnPath.NotFound;
                    return(false);
                }

                num5 += openList.Count;
                num6++;
                CostNode2 costNode = openList.Pop();
                curIndex = costNode.index;
                if (costNode.cost != calcGrid[curIndex].costNodeCost)
                {
                    PfProfilerEndSample();
                    continue;
                }

                if (calcGrid[curIndex].status == statusClosedValue)
                {
                    PfProfilerEndSample();
                    continue;
                }

                IntVec3 c  = cellIndicesField(__instance).IndexToCell(curIndex);
                int     x2 = c.x;
                int     z2 = c.z;
                if (flag4)
                {
                    if (curIndex == num)
                    {
                        PfProfilerEndSample();
                        PawnPath result = FinalizedPath2(curIndex, flag8, cellIndicesField(__instance), calcGrid);
                        PfProfilerEndSample();
                        __result = result;
                        return(false);
                    }
                }
                else if (destinationRect.Contains(c) && !disallowedCornerIndicesField(__instance).Contains(curIndex))
                {
                    PfProfilerEndSample();
                    PawnPath result2 = FinalizedPath2(curIndex, flag8, cellIndicesField(__instance), calcGrid);
                    PfProfilerEndSample();
                    __result = result2;
                    return(false);
                }

                if (num2 > 160000)
                {
                    break;
                }

                PfProfilerEndSample();
                PfProfilerBeginSample("Neighbor consideration");
                for (int i = 0; i < 8; i++)
                {
                    uint num10 = (uint)(x2 + Directions[i]);
                    uint num11 = (uint)(z2 + Directions[i + 8]);
                    if (num10 >= mapSizeXField(__instance) || num11 >= mapSizeZField(__instance))
                    {
                        continue;
                    }

                    int num12 = (int)num10;
                    int num13 = (int)num11;
                    int num14 = cellIndicesField(__instance).CellToIndex(num12, num13);
                    if (calcGrid[num14].status == statusClosedValue && !flag8)
                    {
                        continue;
                    }

                    int  num15  = 0;
                    bool flag10 = false;
                    if (!flag2 && new IntVec3(num12, 0, num13).GetTerrain(mapField(__instance)).HasTag("Water"))
                    {
                        continue;
                    }

                    if (!pathGridField(__instance).WalkableFast(num14))
                    {
                        if (!flag)
                        {
                            continue;
                        }

                        flag10 = true;
                        num15 += 70;
                        Building building = edificeGrid[num14];
                        if (building == null || !PathFinder.IsDestroyable(building))
                        {
                            continue;
                        }

                        num15 += (int)(building.HitPoints * 0.2f);
                    }

                    switch (i)
                    {
                    case 4:
                        if (PathFinder.BlocksDiagonalMovement(curIndex - mapSizeXField(__instance), mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (PathFinder.BlocksDiagonalMovement(curIndex + 1, mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        break;

                    case 5:
                        if (PathFinder.BlocksDiagonalMovement(curIndex + mapSizeXField(__instance), mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (PathFinder.BlocksDiagonalMovement(curIndex + 1, mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        break;

                    case 6:
                        if (PathFinder.BlocksDiagonalMovement(curIndex + mapSizeXField(__instance), mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (PathFinder.BlocksDiagonalMovement(curIndex - 1, mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        break;

                    case 7:
                        if (PathFinder.BlocksDiagonalMovement(curIndex - mapSizeXField(__instance), mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        if (PathFinder.BlocksDiagonalMovement(curIndex - 1, mapField(__instance)))
                        {
                            if (flag7)
                            {
                                continue;
                            }

                            num15 += 70;
                        }

                        break;
                    }

                    int num16 = (i > 3) ? num9 : num8;
                    num16 += num15;
                    if (!flag10)
                    {
                        num16 += array[num14];
                        num16  = ((!flag9) ? (num16 + topGrid[num14].extraNonDraftedPerceivedPathCost) : (num16 + topGrid[num14].extraDraftedPerceivedPathCost));
                    }

                    if (byteGrid != null)
                    {
                        num16 += byteGrid[num14] * 8;
                    }

                    if (allowedArea != null && !allowedArea[num14])
                    {
                        num16 += 600;
                    }

                    if (flag5 && PawnUtility.AnyPawnBlockingPathAt(new IntVec3(num12, 0, num13), pawn, actAsIfHadCollideWithPawnsJob: false, collideOnlyWithStandingPawns: false, forPathFinder: true))
                    {
                        num16 += 175;
                    }

                    Building building2 = edificeGridField(__instance)[num14];
                    if (building2 != null)
                    {
                        PfProfilerBeginSample("Edifices");
                        int buildingCost = PathFinder.GetBuildingCost(building2, traverseParms, pawn);
                        if (buildingCost == int.MaxValue)
                        {
                            PfProfilerEndSample();
                            continue;
                        }

                        num16 += buildingCost;
                        PfProfilerEndSample();
                    }

                    List <Blueprint> list = blueprintGridField(__instance)[num14];
                    if (list != null)
                    {
                        PfProfilerBeginSample("Blueprints");
                        int num17 = 0;
                        for (int j = 0; j < list.Count; j++)
                        {
                            num17 = Mathf.Max(num17, PathFinder.GetBlueprintCost(list[j], pawn));
                        }

                        if (num17 == int.MaxValue)
                        {
                            PfProfilerEndSample();
                            continue;
                        }

                        num16 += num17;
                        PfProfilerEndSample();
                    }

                    int    num18  = num16 + calcGrid[curIndex].knownCost;
                    ushort status = calcGrid[num14].status;
                    if (status == statusClosedValue || status == statusOpenValue)
                    {
                        int num19 = 0;
                        if (status == statusClosedValue)
                        {
                            num19 = num8;
                        }

                        if (calcGrid[num14].knownCost <= num18 + num19)
                        {
                            continue;
                        }
                    }

                    if (flag8)
                    {
                        calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)regionCostCalculator.GetPathCostFromDestToRegion(num14) * RegionHeuristicWeightByNodesOpened.Evaluate(num3));
                        if (calcGrid[num14].heuristicCost < 0)
                        {
                            Log.ErrorOnce(string.Concat("Heuristic cost overflow for ", pawn.ToStringSafe(), " pathing from ", start, " to ", dest, "."), pawn.GetHashCode() ^ 0xB8DC389);
                            calcGrid[num14].heuristicCost = 0;
                        }
                    }
                    else if (status != statusClosedValue && status != statusOpenValue)
                    {
                        int dx    = Math.Abs(num12 - x);
                        int dz    = Math.Abs(num13 - z);
                        int num20 = GenMath.OctileDistance(dx, dz, num8, num9);
                        calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)num20 * num7);
                    }

                    int num21 = num18 + calcGrid[num14].heuristicCost;
                    if (num21 < 0)
                    {
                        Log.ErrorOnce(string.Concat("Node cost overflow for ", pawn.ToStringSafe(), " pathing from ", start, " to ", dest, "."), pawn.GetHashCode() ^ 0x53CB9DE);
                        num21 = 0;
                    }

                    calcGrid[num14].parentIndex  = curIndex;
                    calcGrid[num14].knownCost    = num18;
                    calcGrid[num14].status       = statusOpenValue;
                    calcGrid[num14].costNodeCost = num21;
                    num3++;
                    openList.Push(new CostNode2(num14, num21));
                }

                PfProfilerEndSample();
                num2++;
                calcGrid[curIndex].status = statusClosedValue;
                if (num3 >= num4 && flag6 && !flag8)
                {
                    flag8 = true;
                    regionCostCalculator.Init(destinationRect, traverseParms, num8, num9, byteGrid, allowedArea, flag9, disallowedCornerIndicesField(__instance));
                    InitStatusesAndPushStartNode3(ref curIndex, start, cellIndicesField(__instance), calcGrid, ref statusOpenValue, ref statusClosedValue);
                    openList.Clear();
                    openList.Push(new CostNode2(curIndex, 0));
                    num3 = 0;
                    num2 = 0;
                }
            }

            Log.Warning(string.Concat(pawn, " pathing from ", start, " to ", dest, " hit search limit of ", 160000, " cells."));
            DebugDrawRichData();
            PfProfilerEndSample();
            PfProfilerEndSample();
            __result = PawnPath.NotFound;
            return(false);
        }
        public int GetRegionDistance(Region region, out RegionLink minLink)
        {
            if (regionMinLink.TryGetValue(region.id, out minLink))
            {
                return(distances[minLink]);
            }

            while (queue.Count != 0)
            {
                var vertex = queue.Pop();
                nodes_popped++;
                int knownBest = distances[vertex.Link];
                if (vertex.Cost == knownBest)
                {
                    var destRegion = GetLinkOtherRegion(vertex.FromRegion, vertex.Link);

                    //I've never encountered this during testing, but users reported issues resolved by this check.
                    if (destRegion?.valid != true)
                    {
                        continue;
                    }

                    int portalCost = 0;
                    if (destRegion.portal != null)
                    {
                        //Not using Region.Allows because it is not entirely consistent with the pathfinder logic,
                        //resulting in errors when a door is within range of 22 turrets (avoidGrid=255)
                        portalCost = NewPathFinder.GetPathCostForBuilding(destRegion.portal, traverseParms);
                        if (portalCost < 0)
                        {
                            continue;
                        }
                        portalCost = portalCost + OctileDistance(1, 0);
                    }

                    var minPathCost = RegionMedianPathCost(destRegion);
                    foreach (var current2 in destRegion.links)
                    {
                        if (current2 == vertex.Link)
                        {
                            continue;
                        }
                        var addedCost = destRegion.portal != null ? portalCost : RegionLinkDistance(vertex.Link, current2, minPathCost);
                        addedCost = Math.Max(addedCost, 1);                         //Handle mods with negative path costs
                        int newCost  = knownBest + addedCost;
                        int pathCost = MinimumRegionLinkDistance(targetCell, current2) + newCost;
                        int oldCost;
                        if (distances.TryGetValue(current2, out oldCost))
                        {
                            if (newCost < oldCost)
                            {
                                distances[current2] = newCost;
                                queue.Push(new RegionLinkQueueEntry(destRegion, current2, newCost, pathCost));
                            }
                        }
                        else
                        {
                            distances.Add(current2, newCost);
                            queue.Push(new RegionLinkQueueEntry(destRegion, current2, newCost, pathCost));
                        }
                    }
                    //if this is the first vertex popped for the region, we've found the shortest path to that region
                    if (!regionMinLink.ContainsKey(destRegion.id))
                    {
                        //if (DebugViewSettings.drawPaths && !NewPathFinder.disableDebugFlash)
                        //{
                        //	//NewPathFinder.disableDebugFlash = true;
                        //	//var tempPath = debugPathfinder?.FindPathInner(this.rootCell, new LocalTargetInfo(RegionLinkCenter(vertex.Link)), this.traverseParms, Verse.AI.PathEndMode.OnCell);
                        //	//NewPathFinder.disableDebugFlash = false;
                        //	//var actualCost = tempPath.TotalCost;
                        //	//tempPath.Dispose();
                        //	if (regionMinLink.TryGetValue(vertex.FromRegion.id, out minLink))
                        //		NewPathFinder.DebugLine(this.map, RegionLinkCenter(vertex.Link), RegionLinkCenter(minLink));
                        //	NewPathFinder.DebugFlash(this.map, RegionLinkCenter(vertex.Link), knownBest / 1500f, $"{knownBest}\n{nodes_popped}" /*+ "\n(" + actualCost + ")"*/);
                        //	//if (actualCost < knownBest) { Log.Warning(vertex.Link + " has actual cost " + actualCost + "with heuristic " + knownBest); }
                        //}
                        regionMinLink[destRegion.id] = vertex.Link;
                        if (destRegion.id == region.id)
                        {
                            minLink = vertex.Link;
                            return(vertex.Cost);
                        }
                    }
                }
            }

            return(100000);
        }
Beispiel #5
0
        public PawnPath FindPath(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell)
        {
            if (DebugSettings.pathThroughWalls)
            {
                traverseParms.mode = TraverseMode.PassAllDestroyableThings;
            }
            Pawn pawn = traverseParms.pawn;

            if (pawn != null && pawn.Map != map)
            {
                Log.Warning(String.Format("Map object was rebuilt, but new pather was not assigned to new map (new {0}) (old {1})", pawn.Map.uniqueID, map.uniqueID));
                Log.Error("Tried to FindPath for pawn which is spawned in another map. His map PathFinder should have been used, not this one. pawn=" + pawn + " pawn.Map=" + pawn.Map + " map=" + map);
                return(PawnPath.NotFound);
            }
            if (!start.IsValid)
            {
                Log.Error("Tried to FindPath with invalid start " + start + ", pawn= " + pawn);
                return(PawnPath.NotFound);
            }
            if (!dest.IsValid)
            {
                Log.Error("Tried to FindPath with invalid dest " + dest + ", pawn= " + pawn);
                return(PawnPath.NotFound);
            }
            if (traverseParms.mode == TraverseMode.ByPawn)
            {
                if (!pawn.CanReach(dest, peMode, Danger.Deadly, traverseParms.canBash, traverseParms.mode))
                {
                    return(PawnPath.NotFound);
                }
            }
            else if (!map.reachability.CanReach(start, dest, peMode, traverseParms))
            {
                return(PawnPath.NotFound);
            }
            PfProfilerBeginSample("FindPath for " + pawn + " from " + start + " to " + dest + (dest.HasThing ? (" at " + dest.Cell) : ""));
            cellIndices      = map.cellIndices;
            pathGrid         = map.pathGrid;
            this.edificeGrid = map.edificeGrid.InnerArray;
            blueprintGrid    = map.blueprintGrid.InnerArray;
            int      x        = dest.Cell.x;
            int      z        = dest.Cell.z;
            int      curIndex = cellIndices.CellToIndex(start);
            int      num      = cellIndices.CellToIndex(dest.Cell);
            ByteGrid byteGrid = pawn?.GetAvoidGrid();
            bool     flag     = traverseParms.mode == TraverseMode.PassAllDestroyableThings || traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag2    = traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag3    = !flag;
            CellRect cellRect = CalculateDestinationRect(dest, peMode);
            bool     flag4    = cellRect.Width == 1 && cellRect.Height == 1;

            int[]        array       = map.pathGrid.pathGrid;
            TerrainDef[] topGrid     = map.terrainGrid.topGrid;
            EdificeGrid  edificeGrid = map.edificeGrid;
            int          num2        = 0;
            int          num3        = 0;
            Area         allowedArea = GetAllowedArea(pawn);
            bool         flag5       = pawn != null && PawnUtility.ShouldCollideWithPawns(pawn);
            bool         flag6       = (!flag && start.GetRegion(map) != null) & flag2;
            bool         flag7       = !flag || !flag3;
            bool         flag8       = false;
            bool         flag9       = pawn?.Drafted ?? false;
            int          num4        = (pawn?.IsColonist ?? false) ? 100000 : 2000;
            int          num5        = 0;
            int          num6        = 0;
            float        num7        = DetermineHeuristicStrength(pawn, start, dest);
            // BEGIN CHANGED SECTION
            // In case pawn is null
            int num8 = 13;
            int num9 = 18;
            Dictionary <TerrainDef, int>  pawnTerrainCacheCardinal    = new Dictionary <TerrainDef, int>();
            Dictionary <TerrainDef, int>  pawnTerrainCacheDiagonal    = new Dictionary <TerrainDef, int>();
            Dictionary <TerrainDef, bool> pawnSpecialMovementCache    = new Dictionary <TerrainDef, bool>();
            Dictionary <TerrainDef, bool> pawnImpassibleMovementCache = new Dictionary <TerrainDef, bool>();
            Dictionary <TerrainDef, int>  pawnTerrainMovementCache    = new Dictionary <TerrainDef, int>();

            // END CHANGED SECTION
            CalculateAndAddDisallowedCorners(traverseParms, peMode, cellRect);
            InitStatusesAndPushStartNode(ref curIndex, start);
            while (true)
            {
                PfProfilerBeginSample("Open cell");
                if (openList.Count <= 0)
                {
                    string text  = (pawn != null && pawn.CurJob != null) ? pawn.CurJob.ToString() : "null";
                    string text2 = (pawn != null && pawn.Faction != null) ? pawn.Faction.ToString() : "null";
                    Log.Warning(pawn + " pathing from " + start + " to " + dest + " ran out of cells to process.\nJob:" + text + "\nFaction: " + text2);
                    DebugDrawRichData();
                    PfProfilerEndSample();
                    PfProfilerEndSample();
                    return(PawnPath.NotFound);
                }
                num5 += openList.Count;
                num6++;
                CostNode costNode = openList.Pop();
                curIndex = costNode.index;
                if (costNode.cost != calcGrid[curIndex].costNodeCost)
                {
                    PfProfilerEndSample();
                    continue;
                }
                if (calcGrid[curIndex].status == statusClosedValue)
                {
                    PfProfilerEndSample();
                    continue;
                }
                IntVec3 c  = cellIndices.IndexToCell(curIndex);
                int     x2 = c.x;
                int     z2 = c.z;
                if (flag4)
                {
                    if (curIndex == num)
                    {
                        PfProfilerEndSample();
                        PawnPath result = FinalizedPath(curIndex, flag8);
                        PfProfilerEndSample();
                        return(result);
                    }
                }
                else if (cellRect.Contains(c) && !disallowedCornerIndices.Contains(curIndex))
                {
                    PfProfilerEndSample();
                    PawnPath result2 = FinalizedPath(curIndex, flag8);
                    PfProfilerEndSample();
                    return(result2);
                }
                if (num2 > 160000)
                {
                    break;
                }
                PfProfilerEndSample();
                PfProfilerBeginSample("Neighbor consideration");
                for (int i = 0; i < 8; i++)
                {
                    uint num10 = (uint)(x2 + Directions[i]);
                    uint num11 = (uint)(z2 + Directions[i + 8]);
                    if (num10 >= mapSizeX || num11 >= mapSizeZ)
                    {
                        continue;
                    }
                    int num12 = (int)num10;
                    int num13 = (int)num11;
                    int num14 = cellIndices.CellToIndex(num12, num13);
                    if (calcGrid[num14].status == statusClosedValue && !flag8)
                    {
                        continue;
                    }
                    // BEGIN CHANGED SECTION
                    IntVec3    targetCell    = new IntVec3(num12, 0, num13);
                    TerrainDef targetTerrain = topGrid[num14];
                    if (pawn != null)
                    {
                        // Use cache of terrain movement indicators to avoid a lot of repeated computation
                        if (!pawnImpassibleMovementCache.TryGetValue(targetTerrain, out bool impassible))
                        {
                            impassible = pawn.kindDef.UnreachableTerrainCheck(targetTerrain);
                            pawnImpassibleMovementCache[targetTerrain] = impassible;
                        }
                        if (impassible)
                        {
                            // Skip this cell for pathing calculations
                            calcGrid[num14].status = statusClosedValue;
                            continue;
                        }

                        // Overwrite directional move costs
                        if (!pawnTerrainCacheCardinal.TryGetValue(targetTerrain, out num8))
                        {
                            num8 = pawn.TerrainAwareTicksPerMoveCardinal(targetTerrain);
                            pawnTerrainCacheCardinal[targetTerrain] = num8;
                        }
                        if (!pawnTerrainCacheDiagonal.TryGetValue(targetTerrain, out num9))
                        {
                            num9 = pawn.TerrainAwareTicksPerMoveDiagonal(targetTerrain);
                            pawnTerrainCacheDiagonal[targetTerrain] = num9;
                        }
                    }
                    // END CHANGED SECTION
                    int  num15  = 0;
                    bool flag10 = false;
                    //if (!flag2 && new IntVec3(num12, 0, num13).GetTerrain(map).HasTag("Water"))
                    if (!flag2 && targetTerrain.HasTag("Water"))
                    {
                        continue;
                    }
                    if (!pathGrid.WalkableFast(num14))
                    {
                        if (!flag)
                        {
                            continue;
                        }
                        flag10 = true;
                        num15 += 70;
                        Building building = edificeGrid[num14];
                        if (building == null || !IsDestroyable(building))
                        {
                            continue;
                        }
                        num15 += (int)((float)building.HitPoints * 0.2f);
                    }
                    switch (i)
                    {
                    case 4:
                        if (BlocksDiagonalMovement(curIndex - mapSizeX))
                        {
                            if (flag7)
                            {
                                continue;
                            }
                            num15 += 70;
                        }
                        if (BlocksDiagonalMovement(curIndex + 1))
                        {
                            if (flag7)
                            {
                                continue;
                            }
                            num15 += 70;
                        }
                        break;

                    case 5:
                        if (BlocksDiagonalMovement(curIndex + mapSizeX))
                        {
                            if (flag7)
                            {
                                continue;
                            }
                            num15 += 70;
                        }
                        if (BlocksDiagonalMovement(curIndex + 1))
                        {
                            if (flag7)
                            {
                                continue;
                            }
                            num15 += 70;
                        }
                        break;

                    case 6:
                        if (BlocksDiagonalMovement(curIndex + mapSizeX))
                        {
                            if (flag7)
                            {
                                continue;
                            }
                            num15 += 70;
                        }
                        if (BlocksDiagonalMovement(curIndex - 1))
                        {
                            if (flag7)
                            {
                                continue;
                            }
                            num15 += 70;
                        }
                        break;

                    case 7:
                        if (BlocksDiagonalMovement(curIndex - mapSizeX))
                        {
                            if (flag7)
                            {
                                continue;
                            }
                            num15 += 70;
                        }
                        if (BlocksDiagonalMovement(curIndex - 1))
                        {
                            if (flag7)
                            {
                                continue;
                            }
                            num15 += 70;
                        }
                        break;
                    }
                    int num16 = (i > 3) ? num9 : num8;
                    num16 += num15;
                    if (!flag10)
                    {
                        // BEGIN CHANGED SECTION
                        //num16 += array[num14];
                        //num16 = ((!flag9) ? (num16 + topGrid[num14].extraNonDraftedPerceivedPathCost) : (num16 + topGrid[num14].extraDraftedPerceivedPathCost));
                        if (pawn == null)
                        {
                            num16 += array[num14];
                            if (flag9)
                            {
                                num16 += targetTerrain.extraDraftedPerceivedPathCost;
                            }
                            else
                            {
                                num16 += targetTerrain.extraNonDraftedPerceivedPathCost;
                            }
                        }
                        else
                        {
                            // Use cache of terrain perceived cost instead of fixed pathCost grid to avoid a lot of repeated computation while maintaining accuracy
                            if (!pawnTerrainMovementCache.TryGetValue(targetTerrain, out int terrainMoveCost))
                            {
                                terrainMoveCost = pawn.TerrainMoveCost(targetTerrain);
                                pawnTerrainMovementCache[targetTerrain] = terrainMoveCost;
                            }
                            // This was really really expensive, so we opted to mod this pre-calced value
                            //num16 += pathGrid.TerrainCalculatedCostAt(map, pawn, targetCell, true, IntVec3.Invalid, terrainMoveCost);
                            num16 += pathGrid.ApplyTerrainModToCalculatedCost(targetTerrain, array[num14], terrainMoveCost);
                            // Use cache of terrain movement indicators to avoid a lot of repeated computation
                            if (!pawnSpecialMovementCache.TryGetValue(targetTerrain, out bool specialMovement))
                            {
                                specialMovement = pawn.TerrainMoveStat(targetTerrain) != StatDefOf.MoveSpeed;
                                pawnSpecialMovementCache[targetTerrain] = specialMovement;
                            }
                            // Skip applying the PerceivedPathCost hack if we've got a specialized speed stat for this terrain
                            if (!specialMovement)
                            {
                                if (flag9)
                                {
                                    num16 += targetTerrain.extraDraftedPerceivedPathCost;
                                }
                                else
                                {
                                    num16 += targetTerrain.extraNonDraftedPerceivedPathCost;
                                }
                            }
                        }
                        // END CHANGED SECTION
                    }
                    if (byteGrid != null)
                    {
                        num16 += byteGrid[num14] * 8;
                    }
                    if (allowedArea != null && !allowedArea[num14])
                    {
                        num16 += 600;
                    }
                    //new IntVec3(num12, 0, num13) -> targetCell
                    if (flag5 && PawnUtility.AnyPawnBlockingPathAt(targetCell, pawn, actAsIfHadCollideWithPawnsJob: false, collideOnlyWithStandingPawns: false, forPathFinder: true))
                    {
                        num16 += 175;
                    }
                    Building building2 = this.edificeGrid[num14];
                    if (building2 != null)
                    {
                        PfProfilerBeginSample("Edifices");
                        int buildingCost = GetBuildingCost(building2, traverseParms, pawn);
                        if (buildingCost == int.MaxValue)
                        {
                            PfProfilerEndSample();
                            continue;
                        }
                        num16 += buildingCost;
                        PfProfilerEndSample();
                    }
                    List <Blueprint> list = blueprintGrid[num14];
                    if (list != null)
                    {
                        PfProfilerBeginSample("Blueprints");
                        int num17 = 0;
                        for (int j = 0; j < list.Count; j++)
                        {
                            num17 = Mathf.Max(num17, GetBlueprintCost(list[j], pawn));
                        }
                        if (num17 == int.MaxValue)
                        {
                            PfProfilerEndSample();
                            continue;
                        }
                        num16 += num17;
                        PfProfilerEndSample();
                    }
                    int    num18  = num16 + calcGrid[curIndex].knownCost;
                    ushort status = calcGrid[num14].status;
                    if (status == statusClosedValue || status == statusOpenValue)
                    {
                        int num19 = 0;
                        if (status == statusClosedValue)
                        {
                            num19 = num8;
                        }
                        if (calcGrid[num14].knownCost <= num18 + num19)
                        {
                            continue;
                        }
                    }
                    if (flag8)
                    {
                        calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)regionCostCalculator.GetPathCostFromDestToRegion(num14) * RegionHeuristicWeightByNodesOpened.Evaluate(num3));
                        if (calcGrid[num14].heuristicCost < 0)
                        {
                            Log.ErrorOnce("Heuristic cost overflow for " + pawn.ToStringSafe() + " pathing from " + start + " to " + dest + ".", pawn.GetHashCode() ^ 0xB8DC389);
                            calcGrid[num14].heuristicCost = 0;
                        }
                    }
                    else if (status != statusClosedValue && status != statusOpenValue)
                    {
                        int dx    = Math.Abs(num12 - x);
                        int dz    = Math.Abs(num13 - z);
                        int num20 = GenMath.OctileDistance(dx, dz, num8, num9);
                        calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)num20 * num7);
                    }
                    int num21 = num18 + calcGrid[num14].heuristicCost;
                    if (num21 < 0)
                    {
                        Log.ErrorOnce("Node cost overflow for " + pawn.ToStringSafe() + " pathing from " + start + " to " + dest + ".", pawn.GetHashCode() ^ 0x53CB9DE);
                        num21 = 0;
                    }
                    calcGrid[num14].parentIndex  = curIndex;
                    calcGrid[num14].knownCost    = num18;
                    calcGrid[num14].status       = statusOpenValue;
                    calcGrid[num14].costNodeCost = num21;
                    num3++;
                    openList.Push(new CostNode(num14, num21));
                }
                PfProfilerEndSample();
                num2++;
                calcGrid[curIndex].status = statusClosedValue;
                if (num3 >= num4 && flag6 && !flag8)
                {
                    flag8 = true;
                    regionCostCalculator.Init(cellRect, traverseParms, num8, num9, byteGrid, allowedArea, flag9, disallowedCornerIndices);
                    InitStatusesAndPushStartNode(ref curIndex, start);
                    num3 = 0;
                    num2 = 0;
                }
            }
            Log.Warning(pawn + " pathing from " + start + " to " + dest + " hit search limit of " + 160000 + " cells.");
            DebugDrawRichData();
            PfProfilerEndSample();
            PfProfilerEndSample();
            return(PawnPath.NotFound);
        }
Beispiel #6
0
        public static void Run(IEnumerable <T> startingNodes, Func <T, IEnumerable <T> > neighborsGetter, Func <T, T, float> distanceGetter, List <KeyValuePair <T, float> > outDistances, Dictionary <T, T> outParents = null)
        {
            outDistances.Clear();
            distances.Clear();
            queue.Clear();
            outParents?.Clear();
            IList <T> list = startingNodes as IList <T>;

            if (list != null)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    T key = list[i];
                    if (!distances.ContainsKey(key))
                    {
                        distances.Add(key, 0f);
                        queue.Push(new KeyValuePair <T, float>(key, 0f));
                    }
                }
            }
            else
            {
                foreach (T startingNode in startingNodes)
                {
                    if (!distances.ContainsKey(startingNode))
                    {
                        distances.Add(startingNode, 0f);
                        queue.Push(new KeyValuePair <T, float>(startingNode, 0f));
                    }
                }
            }

            while (queue.Count != 0)
            {
                KeyValuePair <T, float> node = queue.Pop();
                float num = distances[node.Key];
                if (node.Value != num)
                {
                    continue;
                }

                IEnumerable <T> enumerable = neighborsGetter(node.Key);
                if (enumerable == null)
                {
                    continue;
                }

                IList <T> list2 = enumerable as IList <T>;
                if (list2 != null)
                {
                    for (int j = 0; j < list2.Count; j++)
                    {
                        HandleNeighbor(list2[j], num, node, distanceGetter, outParents);
                    }

                    continue;
                }

                foreach (T item in enumerable)
                {
                    HandleNeighbor(item, num, node, distanceGetter, outParents);
                }
            }

            foreach (KeyValuePair <T, float> distance in distances)
            {
                outDistances.Add(distance);
            }

            distances.Clear();
        }
Beispiel #7
0
 public int GetRegionDistance(Region region, out RegionLink minLink)
 {
     if (regionMinLink.TryGetValue(region.id, out minLink))
     {
         return(distances[minLink]);
     }
     while (queue.Count != 0)
     {
         RegionLinkQueueEntry regionLinkQueueEntry = queue.Pop();
         int num = distances[regionLinkQueueEntry.Link];
         if (regionLinkQueueEntry.Cost != num)
         {
             continue;
         }
         Region otherRegion = regionLinkQueueEntry.Link.GetOtherRegion(regionLinkQueueEntry.From);
         if (otherRegion == null || !otherRegion.valid)
         {
             continue;
         }
         int num2 = 0;
         if (otherRegion.door != null)
         {
             num2 = PathFinder.GetBuildingCost(otherRegion.door, traverseParms, traverseParms.pawn);
             if (num2 == int.MaxValue)
             {
                 continue;
             }
             num2 += OctileDistance(1, 0);
         }
         int minPathCost = RegionMedianPathCost(otherRegion);
         for (int i = 0; i < otherRegion.links.Count; i++)
         {
             RegionLink regionLink = otherRegion.links[i];
             if (regionLink == regionLinkQueueEntry.Link || !regionLink.GetOtherRegion(otherRegion).type.Passable())
             {
                 continue;
             }
             int val = (otherRegion.door != null) ? num2 : RegionLinkDistance(regionLinkQueueEntry.Link, regionLink, minPathCost);
             val = Math.Max(val, 1);
             int num3 = num + val;
             int estimatedPathCost = MinimumRegionLinkDistance(destinationCell, regionLink) + num3;
             if (distances.TryGetValue(regionLink, out int value))
             {
                 if (num3 < value)
                 {
                     distances[regionLink] = num3;
                     queue.Push(new RegionLinkQueueEntry(otherRegion, regionLink, num3, estimatedPathCost));
                 }
             }
             else
             {
                 distances.Add(regionLink, num3);
                 queue.Push(new RegionLinkQueueEntry(otherRegion, regionLink, num3, estimatedPathCost));
             }
         }
         if (!regionMinLink.ContainsKey(otherRegion.id))
         {
             regionMinLink.Add(otherRegion.id, regionLinkQueueEntry.Link);
             if (otherRegion == region)
             {
                 minLink = regionLinkQueueEntry.Link;
                 return(regionLinkQueueEntry.Cost);
             }
         }
     }
     return(10000);
 }
Beispiel #8
0
        public PawnPath FindPath(IntVec3 start, LocalTargetInfo dest, TraverseParms traverseParms, PathEndMode peMode = PathEndMode.OnCell)
        {
            if (DebugSettings.pathThroughWalls)
            {
                traverseParms.mode = TraverseMode.PassAllDestroyableThings;
            }
            Pawn pawn = traverseParms.pawn;

            if (pawn != null && pawn.Map != map)
            {
                Log.Error("Tried to FindPath for pawn which is spawned in another map. His map PathFinder should have been used, not this one. pawn=" + pawn + " pawn.Map=" + pawn.Map + " map=" + map);
                return(PawnPath.NotFound);
            }
            if (!start.IsValid)
            {
                Log.Error("Tried to FindPath with invalid start " + start + ", pawn= " + pawn);
                return(PawnPath.NotFound);
            }
            if (!dest.IsValid)
            {
                Log.Error("Tried to FindPath with invalid dest " + dest + ", pawn= " + pawn);
                return(PawnPath.NotFound);
            }
            if (traverseParms.mode == TraverseMode.ByPawn)
            {
                if (!pawn.CanReach(dest, peMode, Danger.Deadly, traverseParms.canBash, traverseParms.mode))
                {
                    return(PawnPath.NotFound);
                }
            }
            else if (!map.reachability.CanReach(start, dest, peMode, traverseParms))
            {
                return(PawnPath.NotFound);
            }
            PfProfilerBeginSample("FindPath for " + pawn + " from " + start + " to " + dest + ((!dest.HasThing) ? string.Empty : (" at " + dest.Cell)));
            cellIndices      = map.cellIndices;
            pathGrid         = map.pathGrid;
            this.edificeGrid = map.edificeGrid.InnerArray;
            blueprintGrid    = map.blueprintGrid.InnerArray;
            IntVec3  cell     = dest.Cell;
            int      x        = cell.x;
            IntVec3  cell2    = dest.Cell;
            int      z        = cell2.z;
            int      curIndex = cellIndices.CellToIndex(start);
            int      num      = cellIndices.CellToIndex(dest.Cell);
            ByteGrid byteGrid = pawn?.GetAvoidGrid();
            bool     flag     = traverseParms.mode == TraverseMode.PassAllDestroyableThings || traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag2    = traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater;
            bool     flag3    = !flag;
            CellRect cellRect = CalculateDestinationRect(dest, peMode);
            bool     flag4    = cellRect.Width == 1 && cellRect.Height == 1;

            int[]        array       = map.pathGrid.pathGrid;
            TerrainDef[] topGrid     = map.terrainGrid.topGrid;
            EdificeGrid  edificeGrid = map.edificeGrid;
            int          num2        = 0;
            int          num3        = 0;
            Area         allowedArea = GetAllowedArea(pawn);
            bool         flag5       = pawn != null && PawnUtility.ShouldCollideWithPawns(pawn);
            bool         flag6       = true && DebugViewSettings.drawPaths;
            bool         flag7       = !flag && start.GetRegion(map) != null && flag2;
            bool         flag8       = !flag || !flag3;
            bool         flag9       = false;
            bool         flag10      = pawn?.Drafted ?? false;
            int          num4        = (!(pawn?.IsColonist ?? false)) ? 2000 : 100000;
            int          num5        = 0;
            int          num6        = 0;
            float        num7        = DetermineHeuristicStrength(pawn, start, dest);
            int          num8;
            int          num9;

            if (pawn != null)
            {
                num8 = pawn.TicksPerMoveCardinal;
                num9 = pawn.TicksPerMoveDiagonal;
            }
            else
            {
                num8 = 13;
                num9 = 18;
            }
            CalculateAndAddDisallowedCorners(traverseParms, peMode, cellRect);
            InitStatusesAndPushStartNode(ref curIndex, start);
            while (true)
            {
                PfProfilerBeginSample("Open cell");
                if (openList.Count <= 0)
                {
                    string text  = (pawn == null || pawn.CurJob == null) ? "null" : pawn.CurJob.ToString();
                    string text2 = (pawn == null || pawn.Faction == null) ? "null" : pawn.Faction.ToString();
                    Log.Warning(pawn + " pathing from " + start + " to " + dest + " ran out of cells to process.\nJob:" + text + "\nFaction: " + text2);
                    DebugDrawRichData();
                    PfProfilerEndSample();
                    return(PawnPath.NotFound);
                }
                num5 += openList.Count;
                num6++;
                CostNode costNode = openList.Pop();
                curIndex = costNode.index;
                if (costNode.cost != calcGrid[curIndex].costNodeCost)
                {
                    PfProfilerEndSample();
                }
                else if (calcGrid[curIndex].status == statusClosedValue)
                {
                    PfProfilerEndSample();
                }
                else
                {
                    IntVec3 c  = cellIndices.IndexToCell(curIndex);
                    int     x2 = c.x;
                    int     z2 = c.z;
                    if (flag6)
                    {
                        DebugFlash(c, (float)calcGrid[curIndex].knownCost / 1500f, calcGrid[curIndex].knownCost.ToString());
                    }
                    if (flag4)
                    {
                        if (curIndex == num)
                        {
                            PfProfilerEndSample();
                            PawnPath result = FinalizedPath(curIndex, flag9);
                            PfProfilerEndSample();
                            return(result);
                        }
                    }
                    else if (cellRect.Contains(c) && !disallowedCornerIndices.Contains(curIndex))
                    {
                        PfProfilerEndSample();
                        PawnPath result2 = FinalizedPath(curIndex, flag9);
                        PfProfilerEndSample();
                        return(result2);
                    }
                    if (num2 > 160000)
                    {
                        break;
                    }
                    PfProfilerEndSample();
                    PfProfilerBeginSample("Neighbor consideration");
                    for (int i = 0; i < 8; i++)
                    {
                        uint num10 = (uint)(x2 + Directions[i]);
                        uint num11 = (uint)(z2 + Directions[i + 8]);
                        if (num10 < mapSizeX && num11 < mapSizeZ)
                        {
                            int num12 = (int)num10;
                            int num13 = (int)num11;
                            int num14 = cellIndices.CellToIndex(num12, num13);
                            if (calcGrid[num14].status != statusClosedValue || flag9)
                            {
                                int  num15  = 0;
                                bool flag11 = false;
                                if (flag2 || !new IntVec3(num12, 0, num13).GetTerrain(map).HasTag("Water"))
                                {
                                    if (!pathGrid.WalkableFast(num14))
                                    {
                                        if (!flag)
                                        {
                                            if (flag6)
                                            {
                                                DebugFlash(new IntVec3(num12, 0, num13), 0.22f, "walk");
                                            }
                                            continue;
                                        }
                                        flag11 = true;
                                        num15 += 70;
                                        Building building = edificeGrid[num14];
                                        if (building == null || !IsDestroyable(building))
                                        {
                                            continue;
                                        }
                                        num15 += (int)((float)building.HitPoints * 0.2f);
                                    }
                                    switch (i)
                                    {
                                    case 4:
                                        if (BlocksDiagonalMovement(curIndex - mapSizeX))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        if (BlocksDiagonalMovement(curIndex + 1))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        goto default;

                                    case 5:
                                        if (BlocksDiagonalMovement(curIndex + mapSizeX))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        if (BlocksDiagonalMovement(curIndex + 1))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2 + 1, 0, z2), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        goto default;

                                    case 6:
                                        if (BlocksDiagonalMovement(curIndex + mapSizeX))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2, 0, z2 + 1), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        if (BlocksDiagonalMovement(curIndex - 1))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        goto default;

                                    case 7:
                                        if (BlocksDiagonalMovement(curIndex - mapSizeX))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2, 0, z2 - 1), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        if (BlocksDiagonalMovement(curIndex - 1))
                                        {
                                            if (flag8)
                                            {
                                                if (flag6)
                                                {
                                                    DebugFlash(new IntVec3(x2 - 1, 0, z2), 0.9f, "corn");
                                                }
                                                break;
                                            }
                                            num15 += 70;
                                        }
                                        goto default;

                                    default:
                                    {
                                        int num16 = (i <= 3) ? num8 : num9;
                                        num16 += num15;
                                        if (!flag11)
                                        {
                                            num16 += array[num14];
                                            num16  = ((!flag10) ? (num16 + topGrid[num14].extraNonDraftedPerceivedPathCost) : (num16 + topGrid[num14].extraDraftedPerceivedPathCost));
                                        }
                                        if (byteGrid != null)
                                        {
                                            num16 += byteGrid[num14] * 8;
                                        }
                                        if (allowedArea != null && !allowedArea[num14])
                                        {
                                            num16 += 600;
                                        }
                                        if (flag5 && PawnUtility.AnyPawnBlockingPathAt(new IntVec3(num12, 0, num13), pawn, actAsIfHadCollideWithPawnsJob: false, collideOnlyWithStandingPawns: false, forPathFinder: true))
                                        {
                                            num16 += 175;
                                        }
                                        Building building2 = this.edificeGrid[num14];
                                        if (building2 != null)
                                        {
                                            PfProfilerBeginSample("Edifices");
                                            int buildingCost = GetBuildingCost(building2, traverseParms, pawn);
                                            if (buildingCost == 2147483647)
                                            {
                                                PfProfilerEndSample();
                                                break;
                                            }
                                            num16 += buildingCost;
                                            PfProfilerEndSample();
                                        }
                                        List <Blueprint> list = blueprintGrid[num14];
                                        if (list != null)
                                        {
                                            PfProfilerBeginSample("Blueprints");
                                            int num17 = 0;
                                            for (int j = 0; j < list.Count; j++)
                                            {
                                                num17 = Mathf.Max(num17, GetBlueprintCost(list[j], pawn));
                                            }
                                            if (num17 == 2147483647)
                                            {
                                                PfProfilerEndSample();
                                                break;
                                            }
                                            num16 += num17;
                                            PfProfilerEndSample();
                                        }
                                        int    num18  = num16 + calcGrid[curIndex].knownCost;
                                        ushort status = calcGrid[num14].status;
                                        if (status == statusClosedValue || status == statusOpenValue)
                                        {
                                            int num19 = 0;
                                            if (status == statusClosedValue)
                                            {
                                                num19 = num8;
                                            }
                                            if (calcGrid[num14].knownCost <= num18 + num19)
                                            {
                                                break;
                                            }
                                        }
                                        if (flag9)
                                        {
                                            calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)regionCostCalculator.GetPathCostFromDestToRegion(num14) * RegionHeuristicWeightByNodesOpened.Evaluate((float)num3));
                                            if (calcGrid[num14].heuristicCost < 0)
                                            {
                                                Log.ErrorOnce("Heuristic cost overflow for " + pawn.ToStringSafe() + " pathing from " + start + " to " + dest + ".", pawn.GetHashCode() ^ 0xB8DC389);
                                                calcGrid[num14].heuristicCost = 0;
                                            }
                                        }
                                        else if (status != statusClosedValue && status != statusOpenValue)
                                        {
                                            int dx    = Math.Abs(num12 - x);
                                            int dz    = Math.Abs(num13 - z);
                                            int num20 = GenMath.OctileDistance(dx, dz, num8, num9);
                                            calcGrid[num14].heuristicCost = Mathf.RoundToInt((float)num20 * num7);
                                        }
                                        int num21 = num18 + calcGrid[num14].heuristicCost;
                                        if (num21 < 0)
                                        {
                                            Log.ErrorOnce("Node cost overflow for " + pawn.ToStringSafe() + " pathing from " + start + " to " + dest + ".", pawn.GetHashCode() ^ 0x53CB9DE);
                                            num21 = 0;
                                        }
                                        calcGrid[num14].parentIndex  = curIndex;
                                        calcGrid[num14].knownCost    = num18;
                                        calcGrid[num14].status       = statusOpenValue;
                                        calcGrid[num14].costNodeCost = num21;
                                        num3++;
                                        openList.Push(new CostNode(num14, num21));
                                        break;
                                    }
                                    }
                                }
                            }
                        }
                    }
                    PfProfilerEndSample();
                    num2++;
                    calcGrid[curIndex].status = statusClosedValue;
                    if (num3 >= num4 && flag7 && !flag9)
                    {
                        flag9 = true;
                        regionCostCalculator.Init(cellRect, traverseParms, num8, num9, byteGrid, allowedArea, flag10, disallowedCornerIndices);
                        InitStatusesAndPushStartNode(ref curIndex, start);
                        num3 = 0;
                        num2 = 0;
                    }
                }
            }
            Log.Warning(pawn + " pathing from " + start + " to " + dest + " hit search limit of " + 160000 + " cells.");
            DebugDrawRichData();
            PfProfilerEndSample();
            return(PawnPath.NotFound);
        }