public RegionLinkQueueEntry(VehicleRegion from, VehicleRegionLink link, int cost, int estimatedPathCost) { this.from = from; this.link = link; this.cost = cost; this.estimatedPathCost = estimatedPathCost; }
public static void AddAllowedAdjacentRegions(LocalTargetInfo dest, TraverseParms traverseParams, Map map, List <VehicleRegion> regions) { GenAdj.GetAdjacentCorners(dest, out IntVec3 bl, out IntVec3 tl, out IntVec3 tr, out IntVec3 br); if (!dest.HasThing || (dest.Thing.def.size.x == 1 && dest.Thing.def.size.z == 1)) { IntVec3 cell = dest.Cell; for (int i = 0; i < 8; i++) { IntVec3 intVec = GenAdj.AdjacentCells[i] + cell; if (intVec.InBoundsShip(map) && !TouchPathEndModeUtility.IsAdjacentCornerAndNotAllowed(intVec, bl, tl, tr, br, map)) { VehicleRegion region = VehicleGridsUtility.GetRegion(intVec, map, RegionType.Set_Passable); if (region != null && region.Allows(traverseParams, true)) { regions.Add(region); } } } } else { List <IntVec3> list = GenAdjFast.AdjacentCells8Way(dest); for (int j = 0; j < list.Count; j++) { if (list[j].InBoundsShip(map) && !TouchPathEndModeUtility.IsAdjacentCornerAndNotAllowed(list[j], bl, tl, tr, br, map)) { VehicleRegion region2 = VehicleGridsUtility.GetRegion(list[j], map, RegionType.Set_Passable); if (region2 != null && region2.Allows(traverseParams, true)) { regions.Add(region2); } } } } }
private void DetermineStartRegions(IntVec3 start) { startingRegions.Clear(); if (pathGrid.WalkableFast(start)) { VehicleRegion validRegionAt = regionGrid.GetValidRegionAt(start); QueueNewOpenRegion(validRegionAt); startingRegions.Add(validRegionAt); } else { for (int i = 0; i < 8; i++) { IntVec3 c = start + GenAdj.AdjacentCells[i]; if (c.InBoundsShip(map)) { if (pathGrid.WalkableFast(c)) { VehicleRegion validRegionAt2 = regionGrid.GetValidRegionAt(c); if (!(validRegionAt2 is null) && validRegionAt2.reachedIndex != reachedIndex) { QueueNewOpenRegion(validRegionAt2); startingRegions.Add(validRegionAt2); } } } } } }
private void GetPreciseRegionLinkDistances(VehicleRegion region, CellRect destination, List <Pair <VehicleRegionLink, int> > outDistances) { outDistances.Clear(); tmpCellIndices.Clear(); if (destination.Width == 1 && destination.Height == 1) { tmpCellIndices.Add(map.cellIndices.CellToIndex(destination.CenterCell)); } else { foreach (IntVec3 cell in destination) { if (cell.InBoundsShip(map)) { tmpCellIndices.Add(map.cellIndices.CellToIndex(cell)); } } } Dijkstra <int> .Run(tmpCellIndices, (int x) => PreciseRegionLinkDistancesNeighborsGetter(x, region), preciseRegionLinkDistancesDistanceGetter, tmpDistances, null); foreach (VehicleRegionLink regionLink in region.links) { if (regionLink.GetOtherRegion(region).Allows(traverseParms, false)) { if (!tmpDistances.TryGetValue(map.cellIndices.CellToIndex(linkTargetCells[regionLink]), out float num)) { Log.ErrorOnce("Dijkstra couldn't reach one of the cells even though they are in the same region. There is most likely something wrong with the " + "neighbor nodes getter. Error occurred in ShipPathFinder of Vehicles", 1938471531); num = 100f; } outDistances.Add(new Pair <VehicleRegionLink, int>(regionLink, (int)num)); } } }
public bool CanReachUnfogged(IntVec3 c, TraverseParms traverseParms) { if (traverseParms.pawn != null) { if (!traverseParms.pawn.Spawned) { return(false); } if (traverseParms.pawn.Map != map) { Log.Error(string.Concat(new object[] { "Called CanReachUnfogged() with a pawn spawned not on this map. This means that we can't check his reachability here. Pawn's current map should have been used instead of this one. pawn=", traverseParms.pawn, " pawn.Map=", traverseParms.pawn.Map, " map=", map })); return(false); } } if (!c.InBoundsShip(map)) { return(false); } if (!c.Fogged(map)) { return(true); } VehicleRegion region = VehicleGridsUtility.GetRegion(c, map, RegionType.Set_Passable); if (region == null) { return(false); } bool entryCondition(VehicleRegion from, VehicleRegion r) => r.Allows(traverseParms, false); bool foundReg = false; bool regionProcessor(VehicleRegion r) { if (!r.AnyCell.Fogged(map)) { foundReg = true; return(true); } return(false); } WaterRegionTraverser.BreadthFirstTraverse(region, entryCondition, regionProcessor, 9999, RegionType.Set_Passable); return(foundReg); }
private void QueueNewOpenRegion(VehicleRegion region) { if (region is null) { Log.ErrorOnce("Tried to queue null region (Vehicles).", 881121); return; } if (region.reachedIndex == reachedIndex) { Log.ErrorOnce("VehicleRegion is already reached; you can't open it. VehicleRegion: " + region.ToString(), 719991); return; } openQueue.Enqueue(region); region.reachedIndex = reachedIndex; numRegionsOpened++; }
public void Init(CellRect end, TraverseParms traverseParms, int moveTicksCardinal, int moveTicksDiagonal, ByteGrid avoidGrid, Area allowedArea, bool drafted, List <int> disallowedCorners) { this.moveTicksCardinal = moveTicksCardinal; this.moveTicksDiagonal = moveTicksDiagonal; endCell = end.CenterCell; cachedRegion = null; cachedBestLink = null; cachedSecondBestLink = null; cachedBestLinkCost = 0; cachedSecondBestLinkCost = 0; cachedRegionIsDestination = false; regionGrid = map.GetCachedMapComponent <VehicleMapping>().VehicleRegionGrid.DirectGrid; destRegions.Clear(); if (end.Width == 1 && end.Height == 1) { VehicleRegion region = VehicleGridsUtility.GetRegion(endCell, map, RegionType.Set_Passable); if (region != null) { destRegions.Add(region); } } else { foreach (IntVec3 intVec in end) { if (intVec.InBoundsShip(map) && !disallowedCorners.Contains(map.cellIndices.CellToIndex(intVec))) { VehicleRegion region2 = VehicleGridsUtility.GetRegion(intVec, map, RegionType.Set_Passable); if (region2 != null) { if (region2.Allows(traverseParms, true)) { destRegions.Add(region2); } } } } } if (destRegions.Count == 0) { Log.Error("Couldn't find any destination regions. This shouldn't ever happen because we've checked reachability."); } vehicleRegionCostCalculator.Init(end, destRegions, traverseParms, moveTicksCardinal, moveTicksDiagonal, avoidGrid, allowedArea, drafted); }
public int GetRegionBestDistances(VehicleRegion region, out VehicleRegionLink bestLink, out VehicleRegionLink secondBestLink, out int secondBestCost) { int regionDistance = GetRegionDistance(region, out bestLink); secondBestLink = null; secondBestCost = int.MaxValue; foreach (VehicleRegionLink regionLink in region.links) { if (regionLink != bestLink && regionLink.GetOtherRegion(region).type.Passable()) { if (distances.TryGetValue(regionLink, out int num) && num < secondBestCost) { secondBestCost = num; secondBestLink = regionLink; } } } return(regionDistance); }
public int RegionMedianPathCost(VehicleRegion region) { if (minPathCosts.TryGetValue(region, out int result)) { return(result); } bool ignoreAllowedAreaCost = allowedArea != null && region.OverlapWith(allowedArea) != AreaOverlap.None; CellIndices cellIndices = map.cellIndices; Rand.PushState(); Rand.Seed = cellIndices.CellToIndex(region.extentsClose.CenterCell) * (region.links.Count + 1); for (int i = 0; i < SampleCount; i++) { pathCostSamples[i] = GetCellCostFast(cellIndices.CellToIndex(region.RandomCell), ignoreAllowedAreaCost); } Rand.PopState(); Array.Sort(pathCostSamples); int num = pathCostSamples[4]; minPathCosts[region] = num; return(num); }
private bool CheckRegionBasedReachability(TraverseParms traverseParms) { while (openQueue.Count > 0) { VehicleRegion region = openQueue.Dequeue(); foreach (VehicleRegionLink regionLink in region.links) { for (int i = 0; i < 2; i++) { VehicleRegion region2 = regionLink.regions[i]; if (!(region2 is null) && region2.reachedIndex != reachedIndex && region2.type.Passable()) { if (region2.Allows(traverseParms, false)) { if (destRegions.Contains(region2)) { foreach (VehicleRegion startRegion in startingRegions) { cache.AddCachedResult(startRegion.Room, region2.Room, traverseParms, true); } return(true); } QueueNewOpenRegion(region2); } } } } } foreach (VehicleRegion startRegion in startingRegions) { foreach (VehicleRegion destRegion in destRegions) { cache.AddCachedResult(startRegion.Room, destRegion.Room, traverseParms, false); } } return(false); }
public int GetPathCostFromDestToRegion(int cellIndex) { VehicleRegion region = regionGrid[cellIndex]; IntVec3 cell = map.cellIndices.IndexToCell(cellIndex); if (region != cachedRegion) { cachedRegionIsDestination = destRegions.Contains(region); if (cachedRegionIsDestination) { return(OctileDistanceToEnd(cell)); } cachedBestLinkCost = vehicleRegionCostCalculator.GetRegionBestDistances(region, out cachedBestLink, out cachedSecondBestLink, out cachedSecondBestLinkCost); cachedRegion = region; } else if (cachedRegionIsDestination) { return(OctileDistanceToEnd(cell)); } if (cachedBestLink != null) { int num = vehicleRegionCostCalculator.RegionLinkDistance(cell, cachedBestLink, 1); int num3; if (cachedSecondBestLink != null) { int num2 = vehicleRegionCostCalculator.RegionLinkDistance(cell, cachedSecondBestLink, 1); num3 = Mathf.Min(cachedSecondBestLinkCost + num2, cachedBestLinkCost + num); } else { num3 = cachedBestLinkCost + num; } return(num3 + OctileDistanceToEndEps(cell)); } return(10000); }
public bool CanReachShip(IntVec3 start, LocalTargetInfo dest, PathEndMode peMode, TraverseParms traverseParms) { if (working) { Log.ErrorOnce("Called CanReach() while working for Ships. This should never happen. Suppressing further errors.", 7312233); return(false); } if (!map.terrainGrid.TerrainAt(dest.Cell).IsWater) { return(false); } if (!(traverseParms.pawn is null)) { if (!traverseParms.pawn.Spawned) { return(false); } if (traverseParms.pawn.Map != map) { Log.Error(string.Concat(new object[] { "Called CanReach() with a ship spawned not on this map. This means that we can't check its reachability here. Pawn's" + "current map should have been used instead of this one. pawn=", traverseParms.pawn, " pawn.Map=", traverseParms.pawn.Map, " map=", map })); return(false); } } if (!dest.IsValid) { return(false); } if (dest.HasThing && dest.Thing.Map != map) { return(false); } if (!start.InBoundsShip(map) || !dest.Cell.InBoundsShip(map)) { return(false); } if ((peMode == PathEndMode.OnCell || peMode == PathEndMode.Touch || peMode == PathEndMode.ClosestTouch) && traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater) { VehicleRoom room = VehicleRegionAndRoomQuery.RoomAtFast(start, map, RegionType.Set_Passable); if (!(room is null) && room == VehicleRegionAndRoomQuery.RoomAtFast(dest.Cell, map, RegionType.Set_Passable)) { return(true); } } if (traverseParms.mode == TraverseMode.PassAllDestroyableThings) { TraverseParms traverseParms2 = traverseParms; traverseParms.mode = TraverseMode.PassDoors; if (CanReachShip(start, dest, peMode, traverseParms2)) { return(true); } } dest = (LocalTargetInfo)GenPathVehicles.ResolvePathMode(traverseParms.pawn, dest.ToTargetInfo(map), ref peMode); working = true; bool result; try { pathGrid = map.GetCachedMapComponent <VehicleMapping>().VehiclePathGrid; regionGrid = map.GetCachedMapComponent <VehicleMapping>().VehicleRegionGrid; reachedIndex += 1u; destRegions.Clear(); if (peMode == PathEndMode.OnCell) { VehicleRegion region = VehicleGridsUtility.GetRegion(dest.Cell, map, RegionType.Set_Passable); if (!(region is null) && region.Allows(traverseParms, true)) { destRegions.Add(region); } } else if (peMode == PathEndMode.Touch) { TouchPathEndModeUtilityVehicles.AddAllowedAdjacentRegions(dest, traverseParms, map, destRegions); } if (destRegions.Count == 0 && traverseParms.mode != TraverseMode.PassAllDestroyableThings && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater) { FinalizeCheck(); result = false; } else { destRegions.RemoveDuplicates(); openQueue.Clear(); numRegionsOpened = 0; DetermineStartRegions(start); if (openQueue.Count == 0 && traverseParms.mode != TraverseMode.PassAllDestroyableThings && traverseParms.mode != TraverseMode.PassAllDestroyableThingsNotWater) { FinalizeCheck(); result = false; } else { if (startingRegions.Any() && destRegions.Any() && CanUseCache(traverseParms.mode)) { BoolUnknown cachedResult = GetCachedResult(traverseParms); if (cachedResult == BoolUnknown.True) { FinalizeCheck(); return(true); } if (cachedResult == BoolUnknown.False) { FinalizeCheck(); return(false); } } if (traverseParms.mode == TraverseMode.PassAllDestroyableThings || traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater || traverseParms.mode == TraverseMode.NoPassClosedDoorsOrWater) { bool flag = CheckCellBasedReachability(start, dest, peMode, traverseParms); FinalizeCheck(); result = flag; } else { bool flag2 = CheckRegionBasedReachability(traverseParms); //bool flag2 = CheckCellBasedReachability(start, dest, peMode, traverseParms); //REDO? FinalizeCheck(); result = flag2; } } } } finally { working = false; } return(result); }
private bool CheckCellBasedReachability(IntVec3 start, LocalTargetInfo dest, PathEndMode peMode, TraverseParms traverseParms) { IntVec3 foundCell = IntVec3.Invalid; VehicleRegion[] directionRegionGrid = regionGrid.DirectGrid; VehiclePathGrid pathGrid = map.GetCachedMapComponent <VehicleMapping>().VehiclePathGrid; CellIndices cellIndices = map.cellIndices; map.floodFiller.FloodFill(start, delegate(IntVec3 c) { int num = cellIndices.CellToIndex(c); if ((traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater || traverseParms.mode == TraverseMode.NoPassClosedDoorsOrWater) && c.GetTerrain(map).IsWater) { return(false); } if (traverseParms.mode == TraverseMode.PassAllDestroyableThings || traverseParms.mode == TraverseMode.PassAllDestroyableThingsNotWater) { if (!pathGrid.WalkableFast(num)) { Building edifice = c.GetEdifice(map); if (edifice is null || !VehiclePathFinder.IsDestroyable(edifice)) { return(false); } } } else if (traverseParms.mode != TraverseMode.NoPassClosedDoorsOrWater) { Log.ErrorOnce("Do not use this method for non-cell based modes!", 938476762); if (!pathGrid.WalkableFast(num)) { return(false); } } VehicleRegion region = directionRegionGrid[num]; return(region is null || region.Allows(traverseParms, false)); }, delegate(IntVec3 c) { if (VehicleReachabilityImmediate.CanReachImmediateShip(c, dest, map, peMode, traverseParms.pawn)) { foundCell = c; return(true); } return(false); }, int.MaxValue, false, null); if (foundCell.IsValid) { if (CanUseCache(traverseParms.mode)) { VehicleRegion validRegionAt = regionGrid.GetValidRegionAt(foundCell); if (!(validRegionAt is null)) { foreach (VehicleRegion startRegion in startingRegions) { cache.AddCachedResult(startRegion.Room, validRegionAt.Room, traverseParms, true); } } } return(true); } if (CanUseCache(traverseParms.mode)) { foreach (VehicleRegion startRegion in startingRegions) { foreach (VehicleRegion destRegion in destRegions) { cache.AddCachedResult(startRegion.Room, destRegion.Room, traverseParms, false); } } } return(false); }
private IEnumerable <int> PreciseRegionLinkDistancesNeighborsGetter(int node, VehicleRegion region) { if (regionGrid[node] is null || regionGrid[node] != region) { return(null); } return(PathableNeighborIndices(node)); }
public int GetRegionDistance(VehicleRegion region, out VehicleRegionLink 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) { VehicleRegion otherRegion = regionLinkQueueEntry.Link.GetOtherRegion(regionLinkQueueEntry.From); if (!(otherRegion is null) && otherRegion.valid) { int num2 = 0; if (!(otherRegion.door is null)) { num2 = VehiclePathFinder.GetBuildingCost(otherRegion.door, traverseParms, traverseParms.pawn); if (num2 == int.MaxValue) { continue; } num2 += OctileDistance(1, 0); } int minPathCost = RegionMedianPathCost(otherRegion); foreach (VehicleRegionLink regionLink in otherRegion.links) { if (regionLink != regionLinkQueueEntry.Link && regionLink.GetOtherRegion(otherRegion).type.Passable()) { int num3 = (otherRegion.door is null) ? RegionLinkDistance(regionLinkQueueEntry.Link, regionLink, minPathCost) : num2; num3 = Math.Max(num3, 1); int num4 = num + num3; int estimatedPathCost = MinimumRegionLinkDistance(destinationCell, regionLink) + num4; if (distances.TryGetValue(regionLink, out int num5)) { if (num4 < num5) { distances[regionLink] = num4; queue.Push(new RegionLinkQueueEntry(otherRegion, regionLink, num4, estimatedPathCost)); } } else { distances.Add(regionLink, num4); queue.Push(new RegionLinkQueueEntry(otherRegion, regionLink, num4, estimatedPathCost)); } } } if (!regionMinLink.ContainsKey(otherRegion.id)) { regionMinLink.Add(otherRegion.id, regionLinkQueueEntry.Link); if (otherRegion == region) { minLink = regionLinkQueueEntry.Link; return(regionLinkQueueEntry.Cost); } } } } } return(10000); }