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);
                 }
             }
         }
     }
 }
Beispiel #3
0
 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));
                }
            }
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
 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);
        }
Beispiel #10
0
 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);
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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);
 }