/// <summary> /// Uses Nearest Neighbor Simple TSP /// </summary> /// <returns></returns> internal static Queue <DungeonNode> GetSceneNearestNeighborRoute() { Stopwatch timer = new Stopwatch(); timer.Start(); Vector3 myPosition = ZetaDia.Me.Position; SceneSegmentation.Update(); if (!UnVisitedNodes.Any()) { return(default(Queue <DungeonNode>)); } List <DungeonNode> unsortedNodes = UnVisitedNodes.ToList(); List <DungeonNode> sortedNodes = new List <DungeonNode>(); var nearestNode = unsortedNodes .OrderBy(node => ZetaDia.Minimap.IsExplored(node.NavigableCenter, ZetaDia.Me.WorldDynamicId)) .ThenBy(node => node.NavigableCenter.Distance2DSqr(myPosition)) .First(); sortedNodes.Add(nearestNode); unsortedNodes.Remove(nearestNode); Dictionary <Vector2, bool> nodeExploredMap = unsortedNodes .ToDictionary(node => node.WorldTopLeft, node => ZetaDia.Minimap.IsExplored(node.NavigableCenter, ZetaDia.Me.WorldDynamicId)); // Enqueue closest node while (unsortedNodes.Any()) { var nextNode = unsortedNodes // Minimap Unvisited first .OrderBy(n => nodeExploredMap[n.WorldTopLeft]) .ThenBy(n => n.Center.DistanceSqr(sortedNodes.Last().Center)) .First(); sortedNodes.Add(nextNode); unsortedNodes.Remove(nextNode); } Queue <DungeonNode> route = new Queue <DungeonNode>(sortedNodes); Logger.Log("Generated new Scene Route with {0} nodes in {1}ms", route.Count, timer.ElapsedMilliseconds); return(route); }
internal static Queue <DungeonNode> GetWeightedNearestMinimapUnvisitedRoute() { Stopwatch timer = new Stopwatch(); timer.Start(); Vector3 myPosition = ZetaDia.Me.Position; Queue <DungeonNode> route = new Queue <DungeonNode>(); List <WeightedDungeonNode> weightedNodes = new List <WeightedDungeonNode>(); // We want to give a high weight to nodes which have unexplored nodes near it // A maximum weight will be given to a node with 4 directly connected unexplored (facing) nodes, and 4 corner-connected nodes // This is theoretically possible if we are standing IN this maximum-weighted unexplored node // Typically a node will have 1 or more directly connected nodes and 0 or more corner-connected nodes foreach (var unWeightedNode in UnVisitedNodes) { var weightedNode = new WeightedDungeonNode(unWeightedNode.WorldTopLeft, unWeightedNode.WorldBottomRight) { Weight = 0 }; // Grab unvisited nodes only, this is what we'll use for our Weighting int numNodesConnected = UnVisitedNodes.Count(node => node.GridCenter.DistanceSqr(weightedNode.GridCenter) <= (MaxCornerDistance * MaxCornerDistance)); weightedNode.Weight = numNodesConnected / MaxConnectedNodes; weightedNodes.Add(weightedNode); } foreach (var node in weightedNodes.OrderByDescending(n => (1 / n.NavigableCenter.Distance(myPosition)) * n.Weight)) { if (SetNodesExploredAutomatically && ZetaDia.Minimap.IsExplored(node.NavigableCenter, ZetaDia.CurrentWorldDynamicId)) { continue; } route.Enqueue(node); } Logger.Log("Generated new Weighted Nearest Minimap Unvisited Route with {0} nodes in {1}ms", route.Count, timer.ElapsedMilliseconds); return(route); }
internal static Queue <DungeonNode> GetSceneDirectionRoute() { if (Direction == Direction.Any) { Logger.Log("No Direction selected for Scene Route - using Scene TSP"); return(GetSceneNearestNeighborRoute()); } Stopwatch timer = new Stopwatch(); timer.Start(); Vector3 myPosition = ZetaDia.Me.Position; Queue <DungeonNode> route = new Queue <DungeonNode>(); /* * North = -X * South = +X * East = +Y * West = -Y * NorthEast = -X+Y * NorthWest = -X-Y * SouthEast = +X+Y * SouthWest = +X-Y */ switch (Direction) { case Direction.North: route = new Queue <DungeonNode>(UnVisitedNodes.OrderBy(node => node.GridCenter.X)); break; case Direction.South: route = new Queue <DungeonNode>(UnVisitedNodes.OrderByDescending(node => node.GridCenter.X)); break; case Direction.East: route = new Queue <DungeonNode>(UnVisitedNodes.OrderByDescending(node => node.GridCenter.Y)); break; case Direction.West: route = new Queue <DungeonNode>(UnVisitedNodes.OrderBy(node => node.GridCenter.Y)); break; case Direction.NorthEast: route = new Queue <DungeonNode>(UnVisitedNodes.OrderBy(node => (node.GridCenter.X - node.GridCenter.Y))); break; case Direction.NorthWest: route = new Queue <DungeonNode>(UnVisitedNodes.OrderBy(node => (node.GridCenter.X + node.GridCenter.Y))); break; case Direction.SouthEast: route = new Queue <DungeonNode>(UnVisitedNodes.OrderByDescending(node => (node.GridCenter.X + node.GridCenter.Y))); break; case Direction.SouthWest: route = new Queue <DungeonNode>(UnVisitedNodes.OrderByDescending(node => (node.GridCenter.X - node.GridCenter.Y))); break; } Logger.Log("Generated new Scene Direction Route with {0} nodes in {1}ms", route.Count, timer.ElapsedMilliseconds); return(route); }