private void FloodFillAt(int tile) { World world = Find.World; if (world.Impassable(tile)) { this.fields[tile] = this.impassableFieldID; return; } Find.WorldFloodFiller.FloodFill(tile, (int x) => !world.Impassable(x), delegate(int x) { this.fields[x] = this.nextFieldID; }, 2147483647, null); this.nextFieldID++; }
private void FloodFillAt(int tile) { World world = Find.World; if (world.Impassable(tile)) { fields[tile] = impassableFieldID; return; } Find.WorldFloodFiller.FloodFill(tile, (int x) => !world.Impassable(x), delegate(int x) { fields[x] = nextFieldID; }); nextFieldID++; }
private void FloodFillAt(int tile) { World world = Find.World; if (world.Impassable(tile)) { this.fields[tile] = this.impassableFieldID; } else { Find.WorldFloodFiller.FloodFill(tile, (int x) => !world.Impassable(x), delegate(int x) { this.fields[x] = this.nextFieldID; }, int.MaxValue, null); this.nextFieldID++; } }
public static bool CanReach(int startTile, int destTile) { //all reachability for a war object should be verified prior to creating it //this might cause bugs during return path or repathing //does "WorldReachability" work better? //return true; int[] fields = new int[Verse.Find.WorldGrid.TilesCount]; int nextFieldID = 1; int impassableFieldID = nextFieldID; int minValidFieldID = nextFieldID; nextFieldID++; if (startTile < 0 || startTile >= fields.Length || destTile < 0 || destTile >= fields.Length) { return(false); } if (fields[startTile] == impassableFieldID || fields[destTile] == impassableFieldID) { return(false); } if ((fields[startTile] >= minValidFieldID) || (fields[destTile] >= minValidFieldID)) { return(fields[startTile] == fields[destTile]); } RimWorld.Planet.World world = Verse.Find.World; if (world.Impassable(startTile)) { fields[startTile] = impassableFieldID; } else { Verse.Find.WorldFloodFiller.FloodFill(startTile, (int x) => !world.Impassable(x), delegate(int x) { fields[x] = nextFieldID; }); nextFieldID++; } if (fields[startTile] == impassableFieldID) { return(false); } return(fields[startTile] == fields[destTile]); }
public int FindMostReasonableAdjacentTileForDisplayedPathCost(int fromTile) { Tile tile = tiles[fromTile]; float num = 1f; int num2 = -1; List <Tile.RoadLink> roads = tile.Roads; if (roads != null) { for (int i = 0; i < roads.Count; i++) { Tile.RoadLink roadLink = roads[i]; float movementCostMultiplier = roadLink.road.movementCostMultiplier; if (movementCostMultiplier < num) { World world = Find.World; Tile.RoadLink roadLink2 = roads[i]; if (!world.Impassable(roadLink2.neighbor)) { num = movementCostMultiplier; Tile.RoadLink roadLink3 = roads[i]; num2 = roadLink3.neighbor; } } } } if (num2 != -1) { return(num2); } tmpNeighbors.Clear(); GetTileNeighbors(fromTile, tmpNeighbors); for (int j = 0; j < tmpNeighbors.Count; j++) { if (!Find.World.Impassable(tmpNeighbors[j])) { return(tmpNeighbors[j]); } } return(fromTile); }
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 void FloodPathsWithCost(List <int> startTiles, Func <int, int, int> costFunc, Func <int, bool> impassable = null, Func <int, float, bool> terminator = null) { if (startTiles.Count < 1 || startTiles.Contains(-1)) { Log.Error("Tried to FindPath with invalid start tiles"); return; } World world = Find.World; WorldGrid grid = world.grid; List <int> tileIDToNeighbors_offsets = grid.tileIDToNeighbors_offsets; List <int> tileIDToNeighbors_values = grid.tileIDToNeighbors_values; if (impassable == null) { impassable = ((int tid) => world.Impassable(tid)); } statusOpenValue += 2; statusClosedValue += 2; if (statusClosedValue >= 65435) { ResetStatuses(); } openList.Clear(); foreach (int startTile in startTiles) { calcGrid[startTile].knownCost = 0; calcGrid[startTile].costNodeCost = 0; calcGrid[startTile].parentTile = startTile; calcGrid[startTile].status = statusOpenValue; openList.Push(new CostNode(startTile, 0)); } while (openList.Count > 0) { CostNode costNode = openList.Pop(); if (costNode.cost != calcGrid[costNode.tile].costNodeCost) { continue; } int tile = costNode.tile; if (calcGrid[tile].status == statusClosedValue) { continue; } int num = (tile + 1 < tileIDToNeighbors_offsets.Count) ? tileIDToNeighbors_offsets[tile + 1] : tileIDToNeighbors_values.Count; for (int i = tileIDToNeighbors_offsets[tile]; i < num; i++) { int num2 = tileIDToNeighbors_values[i]; if (calcGrid[num2].status != statusClosedValue && !impassable(num2)) { int num3 = costFunc(tile, num2) + calcGrid[tile].knownCost; ushort status = calcGrid[num2].status; if ((status != statusClosedValue && status != statusOpenValue) || calcGrid[num2].knownCost > num3) { int num4 = num3; calcGrid[num2].parentTile = tile; calcGrid[num2].knownCost = num3; calcGrid[num2].status = statusOpenValue; calcGrid[num2].costNodeCost = num4; openList.Push(new CostNode(num2, num4)); } } } calcGrid[tile].status = statusClosedValue; if (terminator != null && terminator(tile, calcGrid[tile].costNodeCost)) { break; } } }
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; int[] pathGrid = world.pathGrid.pathGrid; int num = 0; int num2 = (caravan == null) ? 2500 : caravan.TicksPerMove; int num3 = this.CalculateHeuristicStrength(startTile, destTile); this.statusOpenValue += 2; this.statusClosedValue += 2; if (this.statusClosedValue >= 65435) { this.ResetStatuses(); } this.calcGrid[startTile].knownCost = 0; this.calcGrid[startTile].heuristicCost = 0; this.calcGrid[startTile].costNodeCost = 0; this.calcGrid[startTile].parentTile = startTile; this.calcGrid[startTile].status = this.statusOpenValue; this.openList.Clear(); this.openList.Push(new CostNode(startTile, 0)); while (true) { if (this.openList.Count <= 0) { Log.Warning(caravan + " pathing from " + startTile + " to " + destTile + " ran out of tiles to process."); return(WorldPath.NotFound); } CostNode costNode = this.openList.Pop(); if (costNode.cost == this.calcGrid[costNode.tile].costNodeCost) { int tile = costNode.tile; if (this.calcGrid[tile].status != this.statusClosedValue) { if (DebugViewSettings.drawPaths) { Find.WorldDebugDrawer.FlashTile(tile, (float)((float)this.calcGrid[tile].knownCost / 375000.0), this.calcGrid[tile].knownCost.ToString(), 50); } if (tile == destTile) { return(this.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_values.Count : tileIDToNeighbors_offsets[tile + 1]; for (int i = tileIDToNeighbors_offsets[tile]; i < num4; i++) { int num5 = tileIDToNeighbors_values[i]; int num7; ushort status; if (this.calcGrid[num5].status != this.statusClosedValue && !world.Impassable(num5)) { int num6 = num2; num6 += pathGrid[num5]; num6 = (int)((float)num6 * grid.GetRoadMovementMultiplierFast(tile, num5)); num7 = num6 + this.calcGrid[tile].knownCost; status = this.calcGrid[num5].status; if (status != this.statusClosedValue && status != this.statusOpenValue) { goto IL_041e; } if (this.calcGrid[num5].knownCost > num7) { goto IL_041e; } } continue; IL_041e: Vector3 tileCenter = grid.GetTileCenter(num5); if (status != this.statusClosedValue && status != this.statusOpenValue) { float num8 = grid.ApproxDistanceInTiles(GenMath.SphericalDistance(tileCenter.normalized, normalized)); this.calcGrid[num5].heuristicCost = Mathf.RoundToInt((float)((float)num2 * num8 * (float)num3 * 0.5)); } int num9 = num7 + this.calcGrid[num5].heuristicCost; this.calcGrid[num5].parentTile = tile; this.calcGrid[num5].knownCost = num7; this.calcGrid[num5].status = this.statusOpenValue; this.calcGrid[num5].costNodeCost = num9; this.openList.Push(new CostNode(num5, num9)); } num++; this.calcGrid[tile].status = this.statusClosedValue; if (terminator != null && terminator((float)this.calcGrid[tile].costNodeCost)) { break; } } } } return(WorldPath.NotFound); }
public void FloodPathsWithCost(List <int> startTiles, Func <int, int, int> costFunc, Func <int, bool> impassable = null, Func <int, float, bool> terminator = null) { if (startTiles.Count < 1 || startTiles.Contains(-1)) { Log.Error("Tried to FindPath with invalid start tiles"); } else { World world = Find.World; WorldGrid grid = world.grid; List <int> tileIDToNeighbors_offsets = grid.tileIDToNeighbors_offsets; List <int> tileIDToNeighbors_values = grid.tileIDToNeighbors_values; if (impassable == null) { impassable = ((int tid) => world.Impassable(tid)); } this.statusOpenValue += 2; this.statusClosedValue += 2; if (this.statusClosedValue >= 65435) { this.ResetStatuses(); } this.openList.Clear(); foreach (int startTile in startTiles) { this.calcGrid[startTile].knownCost = 0; this.calcGrid[startTile].costNodeCost = 0; this.calcGrid[startTile].parentTile = startTile; this.calcGrid[startTile].status = this.statusOpenValue; this.openList.Push(new CostNode(startTile, 0)); } while (this.openList.Count > 0) { CostNode costNode = this.openList.Pop(); if (costNode.cost == this.calcGrid[costNode.tile].costNodeCost) { int tile = costNode.tile; if (this.calcGrid[tile].status != this.statusClosedValue) { int num = (tile + 1 >= tileIDToNeighbors_offsets.Count) ? tileIDToNeighbors_values.Count : tileIDToNeighbors_offsets[tile + 1]; for (int i = tileIDToNeighbors_offsets[tile]; i < num; i++) { int num2 = tileIDToNeighbors_values[i]; int num4; if (this.calcGrid[num2].status != this.statusClosedValue && !impassable(num2)) { int num3 = costFunc(tile, num2); num4 = num3 + this.calcGrid[tile].knownCost; ushort status = this.calcGrid[num2].status; if (status != this.statusClosedValue && status != this.statusOpenValue) { goto IL_0282; } if (this.calcGrid[num2].knownCost > num4) { goto IL_0282; } } continue; IL_0282: int num5 = num4; this.calcGrid[num2].parentTile = tile; this.calcGrid[num2].knownCost = num4; this.calcGrid[num2].status = this.statusOpenValue; this.calcGrid[num2].costNodeCost = num5; this.openList.Push(new CostNode(num2, num5)); } this.calcGrid[tile].status = this.statusClosedValue; if (terminator != null && terminator(tile, (float)this.calcGrid[tile].costNodeCost)) { break; } } } } } }
public WorldPath FindPath(int startTile, int destTile, Caravan caravan, Func <float, bool> terminator = null) { WorldPath notFound; if (startTile < 0) { Log.Error(string.Concat(new object[] { "Tried to FindPath with invalid start tile ", startTile, ", caravan= ", caravan }), false); notFound = WorldPath.NotFound; } else if (destTile < 0) { Log.Error(string.Concat(new object[] { "Tried to FindPath with invalid dest tile ", destTile, ", caravan= ", caravan }), false); notFound = WorldPath.NotFound; } else { 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 == null) ? 3500 : caravan.TicksPerMove; int num3 = this.CalculateHeuristicStrength(startTile, destTile); this.statusOpenValue += 2; this.statusClosedValue += 2; if (this.statusClosedValue >= 65435) { this.ResetStatuses(); } this.calcGrid[startTile].knownCost = 0; this.calcGrid[startTile].heuristicCost = 0; this.calcGrid[startTile].costNodeCost = 0; this.calcGrid[startTile].parentTile = startTile; this.calcGrid[startTile].status = this.statusOpenValue; this.openList.Clear(); this.openList.Push(new WorldPathFinder.CostNode(startTile, 0)); while (this.openList.Count > 0) { WorldPathFinder.CostNode costNode = this.openList.Pop(); if (costNode.cost == this.calcGrid[costNode.tile].costNodeCost) { int tile = costNode.tile; if (this.calcGrid[tile].status != this.statusClosedValue) { if (DebugViewSettings.drawPaths) { Find.WorldDebugDrawer.FlashTile(tile, (float)this.calcGrid[tile].knownCost / 375000f, this.calcGrid[tile].knownCost.ToString(), 50); } if (tile == destTile) { return(this.FinalizedPath(tile)); } if (num > 500000) { Log.Warning(string.Concat(new object[] { caravan, " pathing from ", startTile, " to ", destTile, " hit search limit of ", 500000, " tiles." }), false); return(WorldPath.NotFound); } int num4 = (tile + 1 >= tileIDToNeighbors_offsets.Count) ? tileIDToNeighbors_values.Count : tileIDToNeighbors_offsets[tile + 1]; for (int i = tileIDToNeighbors_offsets[tile]; i < num4; i++) { int num5 = tileIDToNeighbors_values[i]; if (this.calcGrid[num5].status != this.statusClosedValue) { if (!world.Impassable(num5)) { int num6 = (int)((float)num2 * movementDifficulty[num5] * grid.GetRoadMovementDifficultyMultiplier(tile, num5, null)); int num7 = num6 + this.calcGrid[tile].knownCost; ushort status = this.calcGrid[num5].status; if ((status != this.statusClosedValue && status != this.statusOpenValue) || this.calcGrid[num5].knownCost > num7) { Vector3 tileCenter = grid.GetTileCenter(num5); if (status != this.statusClosedValue && status != this.statusOpenValue) { float num8 = grid.ApproxDistanceInTiles(GenMath.SphericalDistance(tileCenter.normalized, normalized)); this.calcGrid[num5].heuristicCost = Mathf.RoundToInt((float)num2 * num8 * (float)num3 * 0.5f); } int num9 = num7 + this.calcGrid[num5].heuristicCost; this.calcGrid[num5].parentTile = tile; this.calcGrid[num5].knownCost = num7; this.calcGrid[num5].status = this.statusOpenValue; this.calcGrid[num5].costNodeCost = num9; this.openList.Push(new WorldPathFinder.CostNode(num5, num9)); } } } } num++; this.calcGrid[tile].status = this.statusClosedValue; if (terminator != null && terminator((float)this.calcGrid[tile].costNodeCost)) { return(WorldPath.NotFound); } } } } Log.Warning(string.Concat(new object[] { caravan, " pathing from ", startTile, " to ", destTile, " ran out of tiles to process." }), false); notFound = WorldPath.NotFound; } return(notFound); }