예제 #1
0
        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);
        }
예제 #2
0
        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));
        }
예제 #3
0
        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));
        }
예제 #4
0
        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);
        }
예제 #5
0
파일: Map.cs 프로젝트: wren11/ETDA
        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);
            }
        }
예제 #6
0
        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));
        }
예제 #7
0
        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));
        }
예제 #8
0
        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");
        }
예제 #9
0
        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;");
        }
예제 #10
0
        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");
        }
예제 #11
0
        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");
        }
예제 #12
0
        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}");
        }
예제 #13
0
        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}");
        }
예제 #14
0
        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));
        }
예제 #15
0
        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());
            }
        }
예제 #16
0
        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);
            }
        }
예제 #17
0
        /// <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());
        }
예제 #18
0
        /// <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());
        }
예제 #19
0
        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);
            }
        }
예제 #20
0
        // 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);
        }