public void GotoSameTileTest() { network = new SamplePathNetwork(dataA); IPathNode start = network.GetNode(0, 0); IPathNode goal = network.GetNode(0, 0); Path <SampleNode> p = solver.FindPath(start, goal, network); Assert.AreEqual(PathStatus.ALREADY_THERE, p.status); }
public Path <PointTileNode> FindPath(WorldCoordinate pStart, WorldCoordinate pEnd) { TileNode start = GetRoom(pStart.roomName).GetTile(pStart.localPosition); TileNode end = GetRoom(pEnd.roomName).GetTile(pEnd.localPosition); return(_pathSolver.FindPath(start, end, this)); }
public void FindPath_ThrowsIfGraphNotBuilt() { var solver = new PathSolver <Point, PathTestOption>(_testMap); PathResult <Point> pathResult = null; Assert.ThrowsException <PathfindingException>(() => pathResult = solver.FindPath(_startPt, _reachableEndPt, PathTestOption.Normal)); }
public void FindPathManyRooms() { Room[] rooms = LoadFromFile(); PrintWorld(rooms, Path <TileNode> .EMPTY); TileNode start = null, goal = null; foreach (Room r in rooms) { GameTypes.IntPoint localStart = r.WorldToLocalPoint(new GameTypes.IntPoint(-8, 1)); GameTypes.IntPoint localGoal = r.WorldToLocalPoint(new GameTypes.IntPoint(17, 6)); if (r.GetTileType(localStart) == TileType.FLOOR) { start = r.GetTile(localStart); } if (r.GetTileType(localGoal) == TileType.FLOOR) { goal = r.GetTile(localGoal); } } Assert.NotNull(start); Assert.NotNull(goal); PathSolver <TileNode> solver = new PathSolver <TileNode>(); MultiRoomNetwork roomNetwork = new MultiRoomNetwork(rooms); var foundPath = solver.FindPath(start, goal, roomNetwork); Assert.AreEqual(PathStatus.FOUND_GOAL, foundPath.status); PrintWorld(rooms, foundPath); }
public List <PathSolver.PathFinderNode> Search(Position Start, Position End) { try { lock (_mapObjects) { if (Grid.GetLength(0) == 0 || Grid.GetLength(1) == 0) { return(null); } if (!Client.MapLoaded) { return(null); } nodes = new PathSolver.PathNode[Width, Height]; for (short y = 0; y < Height; y++) { for (short x = 0; x < Width; x++) { nodes[x, y] = new PathSolver.PathNode() { HasReactor = false, IsBlock = this[x, y] == 1, Steps = 0, IsDoor = false }; } } foreach (var obj in MapObjects) { if (obj.Type == MapObjectType.Monster || obj.Type == MapObjectType.Aisling || obj.Type == MapObjectType.NPC) { nodes[obj.ServerPosition.X, obj.ServerPosition.Y].IsBlock = true; } } SetPassable(Start); SetPassable(End); nodes[Start.X, Start.Y].IsBlock = false; nodes[End.X, End.Y].IsBlock = false; var usingpath = PathSolver.FindPath(ref nodes, Start, End); return(usingpath); } } catch { return(null); } }
public void FindPath_ThrowsIfEmptyDestinationList() { var solver = new PathSolver <Point, PathTestOption>(_testMap); solver.BuildAdjacencyGraph(_startPt); PathResult <Point> pathResult = null; var destList = new List <Point>(); Assert.ThrowsException <PathfindingException>(() => pathResult = solver.FindPath(_startPt, destList, PathTestOption.Normal)); }
public void FindPath_ThrowsIfDestNodeNotInGraph() { var solver = new PathSolver <Point, PathTestOption>(_testMap); solver.BuildAdjacencyGraph(_startPt); PathResult <Point> pathResult = null; var ptOutsideOfGraph = new Point(-1, -1); Assert.ThrowsException <PathfindingException>(() => pathResult = solver.FindPath(_startPt, ptOutsideOfGraph, PathTestOption.Normal)); }
public void FindPath_ZeroLengthPathToSelf() { var solver = new PathSolver <Point, PathTestOption>(_testMap); solver.BuildAdjacencyGraph(new Point[] { _startPt, _reachableEndPt, _unreachableEndPt }); var solution = solver.FindPath(_startPt, _startPt, PathTestOption.Normal); Assert.IsTrue(solution.PathCost == 0); Assert.IsNotNull(solution.Path); Assert.IsTrue(solution.Path.Count == 0); StringAssert.Contains(solution.PerformanceSummary(), "Zero-length path"); }
public void PerformanceSummary_HasInfo() { var solver = new PathSolver <Point, PathTestOption>(_testMap); solver.BuildAdjacencyGraph(new Point[] { _startPt, _reachableEndPt, _unreachableEndPt }); var solution = solver.FindPath(_startPt, _reachableEndPt, PathTestOption.Normal); var summary = solver.PerformanceSummary(); Assert.IsNotNull(summary); StringAssert.Contains(summary, "pathCount=1;"); }
public void FindPath_NoPathToUnreachable() { // In this case, _startPt and _unreachableEndPt are disconnected in the adjacency graph. var solver = new PathSolver <Point, PathTestOption>(_testMap); solver.BuildAdjacencyGraph(new Point[] { _startPt, _reachableEndPt, _unreachableEndPt }); var solution = solver.FindPath(_startPt, _unreachableEndPt, PathTestOption.Normal); Assert.IsTrue(solution.PathCost == double.PositiveInfinity); Assert.IsNull(solution.Path); StringAssert.Contains(solution.PerformanceSummary(), "Path not found"); }
public void FindPath_NoPathIfAllInfiniteCosts() { // In this case, the start and end points are connected in the adjacency graph, but all possible paths // have an infinite cost. PathSolver treats that as unreachable. var solver = new PathSolver <Point, PathTestOption>(_testMap); solver.BuildAdjacencyGraph(new Point[] { _startPt, _reachableEndPt, _unreachableEndPt }); var solution = solver.FindPath(_startPt, _reachableEndPt, PathTestOption.InfiniteCost); Assert.IsTrue(solution.PathCost == double.PositiveInfinity); Assert.IsNull(solution.Path); StringAssert.Contains(solution.PerformanceSummary(), "Path not found"); }
public void FindPath_GoodPathToReachable() { var solver = new PathSolver <Point, PathTestOption>(_testMap); solver.BuildAdjacencyGraph(new Point[] { _startPt, _reachableEndPt, _unreachableEndPt }); var solution = solver.FindPath(_startPt, _reachableEndPt, PathTestOption.Normal); Assert.IsTrue(solution.PathCost >= _testMap.EstimatedCost(_startPt, _reachableEndPt, PathTestOption.Normal)); Assert.IsNotNull(solution.Path); Assert.IsTrue(solution.Path.Count > 0); Assert.IsTrue(solution.Path[solution.Path.Count - 1] == _reachableEndPt); Assert.IsFalse(solution.Path.Contains(_startPt)); Assert.IsTrue(solution.NodesReprocessedCount == 0); StringAssert.Contains(solution.PerformanceSummary(), $"Path from {_startPt}"); }
public void FindPath_GoodPathEvenWithOverestimate() { // If we give PathSolver a bad estimate, we should still get a path, but it won't always be optimal. // NodesReprocessedCount can only be > 0 in this case. var solver = new PathSolver <Point, PathTestOption>(_testMap); solver.BuildAdjacencyGraph(new Point[] { _startPt, _reachableEndPt, _unreachableEndPt }); var solution = solver.FindPath(_startPt, _reachableEndPt, PathTestOption.OverEstimateRemainingDistance); Assert.IsNotNull(solution.Path); Assert.IsTrue(solution.Path.Count > 0); Assert.IsTrue(solution.Path[solution.Path.Count - 1] == _reachableEndPt); Assert.IsFalse(solution.Path.Contains(_startPt)); Assert.IsTrue(solution.NodesReprocessedCount > 0); StringAssert.Contains(solution.PerformanceSummary(), $"Path from {_startPt}"); }
public void ClearAdjacencyGraph_InvalidatesOldNodes() { var solver = new PathSolver <Point, PathTestOption>(_testMap); // Build a graph based on all three points. solver.BuildAdjacencyGraph(new Point[] { _startPt, _reachableEndPt, _unreachableEndPt }); // Clear the graph, and then rebuild it with just one point. solver.ClearAdjacencyGraph(); solver.BuildAdjacencyGraph(_startPt); // Try to find a path to _unreachableEndPt. PathSolver should complain that it doesn't know about that point. PathResult <Point> pathResult = null; Assert.ThrowsException <PathfindingException>(() => pathResult = solver.FindPath(_startPt, _unreachableEndPt, PathTestOption.Normal)); }
private static void Demo() { // Create a tile map. In this case we're doing it from hard-coded strings, but it // would be trivial to get it from a file instead. var map = new Map(_demoMapStrings); // Create an instace of an IPathGraph. This is a class that the caller provides // that answers which tiles are adjacent to which, and what the cost is to move from // one to the next. var tileGraph = new TileGraph(map); // Create a PathSolver instance. The first type parameter here is Point2D. It's whatever // we're using to identify nodes (tile in this case). The second one - int here - is a dummy // type since we don't care about callerData/passthrough values in this example. var solver = new PathSolver <Point2D, int>(tileGraph); var allImportantPoints = _demoGoalPts.Concat(_demoStartPts); // Pre-build the PathSolver's data structures. We're telling it to build a graph of all of the points // reachable from the ones we give it here. solver.BuildAdjacencyGraph(allImportantPoints); // Create a path and draw the map for each point in _demoStartPts. foreach (var startPt in _demoStartPts) { // Find the shortest path from startPt to any of points listed in _interestingGoals. Of course, // you could just give it one ending point. The third parameter, 0 here, is unused in this example. var pathResult = solver.FindPath(startPt, _demoGoalPts, 0); // Write the map out as a grid characters, with a couple extra bits: // O is the starting point for our path. // X is one of the ending points for our path. // . is a tile we moved through on the path. var startPtsArray = new Point2D[] { startPt }; var mapStrings = map.RowStrings(pathResult.Path, startPtsArray, _demoGoalPts); Console.WriteLine(); foreach (var mapRow in mapStrings) { Console.WriteLine(mapRow); } // Write performance info. Console.WriteLine(pathResult.PerformanceSummary()); } }
public List <PathSolver.PathFinderNode> Search(Position Start, Position End) { lock (_mapObjects) { if (Grid.GetLength(0) == 0 || Grid.GetLength(1) == 0) { return(null); } if (!Client.MapLoaded) { return(null); } var usingpath = PathSolver.FindPath(Grid, Start, End); return(usingpath); } }
/// <summary> /// Plot a path between the given stars for a particular ship type, and write that path out to the console. /// </summary> private static void WritePath(StarMap map, PathSolver <string, ShipCharacteristics> solver, string fromStar, string toStar, ShipCharacteristics ship) { // Find the best path between our stars. The third parameter here, ship, gets passed through // to StarMap's Cost and EstimatedCost methods. var pathInfo = solver.FindPath(fromStar, toStar, ship); if (pathInfo.Path == null) { Console.WriteLine($"{ship.ShipClass}: no path found from {fromStar} to {toStar}"); return; } // Write out a string indicating each step in the path and its cost. var buff = new System.Text.StringBuilder(); buff.Append(ship.ShipClass).Append(": ").Append(fromStar); string currentStar = fromStar; int i = 0; while (i < pathInfo.Path.Count) { string nextStar = pathInfo.Path[i]; var cost = map.Cost(currentStar, nextStar, ship); buff.AppendFormat(" -({0:N1})-> ", cost); buff.Append(nextStar); i += 1; currentStar = nextStar; } Console.WriteLine(buff.ToString()); // Write out debug/performance stats. Console.WriteLine(" " + pathInfo.PerformanceSummary()); }
/// <summary> /// Search for a whole lot of paths using a large map. /// </summary> private static void Benchmark() { // Build the necessary pieces (as above in Demo()). var map = new Map(_benchmarkMapStrings); var tileGraph = new TileGraph(map); var solver = new PathSolver <Point2D, int>(tileGraph); // Init the solver's graph. (This step is included in solver.LifetimeSolutionTimeMS, by the way.) solver.BuildAdjacencyGraph(_benchmarkPts); // Solve a path for every combination of 1 starting point and 2 destination points. (So if P is the number of // points, then we're solving P*(P-1)*(P-2)/2 paths.) for (var startIdx = 0; startIdx < _benchmarkPts.Length; ++startIdx) { var startPt = _benchmarkPts[startIdx]; for (var endIdx1 = 0; endIdx1 < _benchmarkPts.Length; ++endIdx1) { if (endIdx1 == startIdx) { continue; } for (var endIdx2 = endIdx1 + 1; endIdx2 < _benchmarkPts.Length; ++endIdx2) { if (endIdx2 == startIdx) { continue; } var endPts = new[] { _benchmarkPts[endIdx1], _benchmarkPts[endIdx2] }; var pathResult = solver.FindPath(startPt, endPts, 0); } } } // Write out a summary of the PathSolver's lifetime statistics. Console.WriteLine(solver.PerformanceSummary()); }
public void BasicUsage() { { RelayTwo relay = new RelayTwo(); relay.CreateTable(Room.TABLE_NAME); RoomRunner roomRunner = new RoomRunner(relay); foreach (string s in roomRunner.Preload()) { ; } Room r1 = roomRunner.CreateRoom <Room>("r1"); Room r2 = roomRunner.CreateRoom <Room>("r2"); PointTileNode door1 = null; PointTileNode door2 = null; for (int i = 0; i < 100; i++) { int x = i % 10; int y = i / 10; if (x == 9 && y == 9) { door1 = new PointTileNode(new IntPoint(9, 9), r1); r1.AddTile(door1); } else { r1.AddTile(new PointTileNode(new IntPoint(x, y), r1)); } } for (int i = 0; i < 100; i++) { int x = i % 10; int y = i / 10; if (x == 0 && y == 0) { door2 = new PointTileNode(new IntPoint(0, 0), r2); r2.AddTile(door2); } else { r2.AddTile(new PointTileNode(new IntPoint(x, y), r2)); } } r1.worldPosition = new IntPoint(50, 0); door1.teleportTarget = door2; door2.teleportTarget = door1; relay.SaveAll("room_test.json"); } { RelayTwo relay = new RelayTwo("room_test.json"); RoomRunner roomRunner = new RoomRunner(relay); foreach (string s in roomRunner.Preload()) { ; } Room r1 = roomRunner.GetRoom("r1"); Room r2 = roomRunner.GetRoom("r2"); r1.GetTile(9, 9).teleportTarget = r2.GetTile(0, 0); r2.worldPosition = new IntPoint(0, 0); PointTileNode start = r1.GetTile(new IntPoint(0, 5)); PointTileNode goal = r2.GetTile(new IntPoint(9, 5)); D.isNull(start); D.isNull(goal); PathSolver <PointTileNode> pathSolver = new PathSolver <PointTileNode>(); Path <PointTileNode> path = pathSolver.FindPath(start, goal, roomRunner); Assert.AreEqual(PathStatus.FOUND_GOAL, path.status); Console.WriteLine("path resolved using " + path.pathSearchTestCount + " node tests"); Console.WriteLine("path tile count " + path.nodes.Length); } }
// Returns true if the character should start walking again private bool TilePathfindToTargetPositionInRoom() { #if PROFILE Stopwatch sw = new Stopwatch(); sw.Start(); #endif _tilePath = Path.EMPTY; _startTileNode = _character.tile; if (_startTileNode == null) { TryToFindAlternativeStartingTile(); if (_startTileNode != null) { //D.Log (_character + " has no start tile, will set his pos to alternative start tile " + _startTileNode); _character.StartAction("", null, 0f, 0f); _character.position = _startTileNode.position; } else { //D.Log (_character + " has no start tile but didn't find alternative start tile"); } } Room finalRoom = _roomRunner.GetRoom(_character.finalTargetPosition.roomName); if (_character.room == finalRoom) { if (_character.finalTargetTing != null) { // Try to go to the closest interaction point instead of straight to the actual ting position // (which will lead to an error) #if LOG s_logger.Log(_character + " with timetable " + _character.timetable + " will tilepathfind to closest interaction point of " + _character.finalTargetTing + " at position " + _character.finalTargetTing.position); #endif bool ignoreCharacters = (_character.finalTargetTing is Door || _character.finalTargetTing is Portal); IntPoint closestInteractionPoint; if (_character.finalTargetTing.interactionPointsTryTheseFirst != null && GetClosestInteractionPoint(_roomRunner, finalRoom, _character.tile, _character.finalTargetTing.interactionPointsTryTheseFirst, out closestInteractionPoint, _character, ignoreCharacters)) { _character.finalTargetPosition = new WorldCoordinate(_character.finalTargetPosition.roomName, closestInteractionPoint); #if LOG s_logger.Log("Found a closest target position for " + _character.name + ": " + _character.finalTargetPosition); #endif } else if (GetClosestInteractionPoint(_roomRunner, finalRoom, _character.tile, _character.finalTargetTing.interactionPoints, out closestInteractionPoint, _character, ignoreCharacters)) { _character.finalTargetPosition = new WorldCoordinate(_character.finalTargetPosition.roomName, closestInteractionPoint); #if LOG s_logger.Log("Found a closest target position B for " + _character.name + ": " + _character.finalTargetPosition); #endif } else { //Console.WriteLine(_character.name + " can't find closest target position for ting " + _character.finalTargetTing + " at pos " + _character.finalTargetTing.position); _character.CancelWalking(); _character.timetableTimer = Randomizer.GetValue(5.0f, 10.0f); // how long to wait? (used to be 0) return(false); } } // The target in the room should be the same as the final target position _character.targetPositionInRoom = _character.finalTargetPosition; } else { // In this case the target position in the room should be already set by MimanPathfinding } _goalTileNode = _character.room.GetTile(_character.targetPositionInRoom.localPosition); if (_goalTileNode == null) { TryToFindAlternativeGoalTile(); } if (_goalTileNode == null) { #if LOG s_logger.Log("Tilepathfinding for " + _character.name + " failed, can't find a goal tile node"); #endif return(false); } if (_startTileNode.group > -1 && _goalTileNode.group > -1 && _startTileNode.group != _goalTileNode.group) { _character.CancelWalking(); _character.timetableTimer = Randomizer.GetValue(5.0f, 10.0f); // how long to wait? (used to be 0) #if LOG s_logger.Log("Tilepathfinding for " + _character.name + " failed, startTileNode at " + _startTileNode.position + " has group " + _startTileNode.group + " while _goalTileNode at " + _goalTileNode.position + " has group " + _goalTileNode.group); #endif return(false); } /* * if(_character.HasRecentlyMadeAFailedPathFindingSearch(_startTileNode, _goalTileNode)) { * _character.logger.Log(_character.name + " will not pathfind; has recently made a failed path finding search between " + _character.tile + " and " + _goalTileNode); * _character.CancelWalking(); * return false; * } */ #if LOG s_logger.Log(_character.name + " will pathfind from " + _character.tile + " to " + _goalTileNode); #endif _character.room.Reset(); _tilePath = _tilePathSolver.FindPath(_startTileNode, _goalTileNode, _roomRunner, false); foreach (var tilePathNode in _tilePath.nodes) { Fence fence = tilePathNode.GetOccupantOfType <Fence>(); if (fence != null) { //s_logger.Log("There is a Fence on the path of " + _character + ", will interact with that instead"); _character.CancelWalking(); _character.WalkToTingAndInteract(fence); return(false); } } #if LOG s_logger.Log("Tile path solve from " + _startTileNode + " to " + _goalTileNode + ": " + _tilePath.status); // + ", PATH NODES " + _tilePath); #endif #if PROFILE sw.Stop(); if (sw.Elapsed.TotalSeconds > 0.001f) { D.Log("TilePathFinding for " + _character + " from " + _startTileNode + " to " + _goalTileNode + " took " + sw.Elapsed.TotalSeconds + " s."); } #endif if (_tilePath.status == PathStatus.DESTINATION_UNREACHABLE) { #if LOG s_logger.Log("The destination was unreachable so we'll register it and cancel walking"); #endif //_character.RegisterFailedPathFindingSearch(_startTileNode, _goalTileNode); #if LOG s_logger.Log(_character.name + ": The destination " + _goalTileNode.position + " was unreachable from " + _startTileNode.position); #endif //_character.CancelWalking(); return(false); } else if (_tilePath.status == PathStatus.ALREADY_THERE) { #if LOG s_logger.Log("Already there, analyze tile"); #endif AnalyzeNewTile(); return(false); } else if (_tilePath.status == PathStatus.FOUND_GOAL) { #if LOG s_logger.Log("Found goal at " + _goalTileNode); s_logger.Log("Path for " + _character + ": " + string.Join(", ", _tilePath.nodes.Select(t => t.ToString()).ToArray())); #endif return(true); } else { #if LOG s_logger.Log("This case should really not happen"); #endif } return(false); }