private Point?GetExploreDestination() { //todo, clean up later var potentiallyReachable = FloodFill.ScanToArray(Player.Position, point => !point.IsMapEdge() && (!Map.Seen[point] || TileDefinition.IsPassable(TileTypeAt(point)))); var dm2 = new DijkstraMap(p => (Map.Seen[p] || p.IsMapEdge())? -1 : 1) //todo, seen==blocked? { IsSource = p => (Map.Seen[p] || p.IsMapEdge()) }; dm2.Scan(); //CharacterScreens.PrintDijkstraTest(dm2); foreach (Point p in Map.GetAllPoints(false)) { if (dm2[p] == DijkstraMap.Unexplored || dm2[p] == DijkstraMap.Blocked) { continue; } dm2[p] = -(dm2[p] * dm2[p]); } dm2.RescanWithCurrentValues(); //CharacterScreens.PrintDijkstraTest(dm2); var dm = new DijkstraMap(p => (!Map.Seen[p] || !TileDefinition.IsPassable(TileTypeAt(p)))? -1 : 1) { IsSource = p => !Map.Seen[p] && potentiallyReachable[p], GetSourceValue = p => - (dm2[p]) }; dm.Scan(); //CharacterScreens.PrintDijkstraTest(dm2); //CharacterScreens.PrintDijkstraTest(dm); List <Point> playerPath = dm.GetDownhillPath(Player.Position, true, earlyStopCondition: p => !Map.Seen[p]); if (playerPath.Count == 0) { return(null); } else { return(playerPath[playerPath.Count - 1]); } }
private List <Point> GetPathToNearbyReachable(Point potentialDestination, DijkstraMap playerMovementMap, ref PointArray <bool> knownReachable, ref DijkstraMap distanceToKnownReachable) { Point destination = potentialDestination; // First, figure out whether the destination cell is known-reachable: if (knownReachable == null) { knownReachable = FloodFill.ScanToArray(Player.Position, CellIsKnownPassable); } PointArray <bool> knownReachable2 = knownReachable; // Can't use a ref parameter inside a lambda, but using a 2nd variable works. if (!knownReachable[destination]) { // If not, then find the nearest known reachable spaces: if (distanceToKnownReachable == null) { distanceToKnownReachable = new DijkstraMap(point => 1) { IsSource = point => knownReachable2[point] }; distanceToKnownReachable.Scan(); } if (distanceToKnownReachable[destination] > 1) // If distance is 1, then we can reach it anyway { destination = destination.EnumeratePointsAtChebyshevDistance(distanceToKnownReachable[destination], true, false) // We know the distance already, so check only those cells... .Where(nearby => nearby.ExistsBetweenMapEdges() && knownReachable2[nearby]) // ...make sure only reachable ones are considered... .WhereLeast(nearby => destination.GetHalfStepMetricDistance(nearby)) // ...get the nearest ones to the targeted point... .WhereLeast(nearby => Player.Position.GetHalfStepMetricDistance(nearby))[0]; // ...and finally get whichever one of those is closest to the player. } } if (destination == Player.Position) { return(new List <Point>()); } List <Point> path = playerMovementMap.GetDownhillPath(destination, preferCardinalDirections: true, includePathSource: true, includePathDestination: false, ignorePathSourceCost: true); path.Reverse(); return(path); }
private void ChooseAutoexploreAction(PlayerTurnEvent e) { var potentiallyReachable = FloodFill.ScanToArray(Player.Position, point => !point.IsMapEdge() && (!Map.Seen[point] || TileDefinition.IsPassable(TileTypeAt(point)))); var distanceToKnown = new DijkstraMap(p => (Map.Seen[p] || p.IsMapEdge())? -1 : 1) { IsSource = p => (Map.Seen[p] || p.IsMapEdge()) }; distanceToKnown.Scan(); foreach (Point p in Map.GetAllPoints(false)) { if (distanceToKnown[p] == DijkstraMap.Unexplored || distanceToKnown[p] == DijkstraMap.Blocked) { continue; } distanceToKnown[p] = -(distanceToKnown[p] * distanceToKnown[p]); } distanceToKnown.RescanWithCurrentValues(); var exploreMap = new DijkstraMap(p => (!Map.Seen[p] || !TileDefinition.IsPassable(TileTypeAt(p)))? -1 : 1) // todo, needs items, shrines, etc. eventually { IsSource = p => !Map.Seen[p] && potentiallyReachable[p], GetSourceValue = p => - (distanceToKnown[p]) }; exploreMap.Scan(); List <Point> playerPath = exploreMap.GetDownhillPath(Player.Position, true, earlyStopCondition: p => true); if (playerPath.Count == 0) { return; } else { e.ChosenAction = new WalkAction(Player, playerPath[0]); } }