public NodeData( ExplorationNode node, Dictionary<ExplorationEdge, uint> edgeToId) { this.NodeId = node.Id; this.State = new StateData(node.State); this.PageRank = node.PageRank; this.InversePageRank = node.InversePageRank; this.MinCutIn = this.EncodeMinCuts(node.GetMinCutsIn()); this.MinCutOut = this.EncodeMinCuts(node.GetMinCutsOut()); IList<ExplorationEdge> incoming = node.IncomingExploration; this.Incoming = new uint[incoming.Count]; for (int i = 0; i < incoming.Count; i++) this.Incoming[i] = edgeToId[incoming[i]]; IList<ExplorationEdge> outgoing = node.OutgoingExploration; this.Outgoing = new uint[outgoing.Count]; for (int i = 0; i < outgoing.Count; i++) this.Outgoing[i] = edgeToId[outgoing[i]]; IList<ExplorationEdge[]> paths = node.GetPathsOut(); this.Paths = new uint[paths.Count][]; for (int i = 0; i < paths.Count; i++) { ExplorationEdge[] path = paths[i]; this.Paths[i] = new uint[path.Length]; for (int j = 0; j < path.Length; j++) this.Paths[i][j] = edgeToId[path[j]]; } }
/// <summary> /// Picks far away nodes with a thin bottleneck /// </summary> public static double Score_SkinnyPipe( ExplorationNode current, ExplorationNode candidate) { int length = current.GetPathOut(candidate.Id).Length; int minCutOut = current.GetMinCutOut(candidate.Id); return (double)minCutOut / (double)length; }
private static void Task_ProcessPair( ExplorationNode source, ExplorationNode dest) { IList<ExplorationEdge> edges = ParallelGraphUtil.AStarPath(source, dest); if (edges != null) source.SetPathOut(dest.Id, edges.ToArray()); }
public Candidate( ExplorationEdge[] path, ExplorationNode goal, double score) { this.Goal = goal; this.Path = path; this.Score = score; }
public Candidate( ExplorationEdge edge, ExplorationNode goal, double score) { this.Goal = goal; this.Edge = edge; this.Score = score; }
private static double ScoreNodeSkinnyPipe( ExplorationNode current, ExplorationNode candidate) { int length = current.GetPathOut(candidate.Id).Length; int minCutOut = current.GetMinCutOut(candidate.Id); double modifier = ScorePath(current.GetPathOut(candidate.Id)); return ((double)minCutOut / (double)length) / modifier; }
private static ExplorationNode Decode(NodeData data) { ExplorationNode newNode = new ExplorationNode(data.State.Decode()); newNode.Id = data.NodeId; newNode.PageRank = data.PageRank; newNode.InversePageRank = data.InversePageRank; StoreMinCuts(newNode, data.MinCutIn, newNode.SetMinCutIn); StoreMinCuts(newNode, data.MinCutOut, newNode.SetMinCutOut); return newNode; }
public ExplorationEdge( ExplorationNode source, ExplorationNode target, params TransitionEvent[] transitions) { this.Source = source; this.Target = target; this.Events = transitions; #if !PARALLEL this.Saturated = false; #endif }
private static void StoreMinCuts( ExplorationNode node, uint[] minCuts, Action<uint, int> assign) { for (int i = 0; i < minCuts.Length >> 1; i++) { int index = i << 1; uint id = minCuts[index]; int value = (int)minCuts[index + 1]; assign(id, value); } }
public void CandidateSelected(int index) { if (this.candidates != null) { Candidate selected = this.candidates[index]; this.current = selected.Path[0].Target; this.lastGoal = selected.Goal; this.candidates = null; } else { Console.WriteLine("WARNING: Ignoring TakeCandidate()"); } }
private void PopulateAdjacent( Func<ExplorationNode, ExplorationNode, double> scorer, bool descending = false) { if (this.currentNode == null) if (this.Explorer.IsDone == true) this.currentNode = Explorer.StateSpace.Nodes[0]; if (this.currentNode != null) { List<Candidate> picked = new List<Candidate>(); foreach (ExplorationEdge edge in this.currentNode.OutgoingExploration) { ExplorationNode goal = edge.Target; picked.Add(new Candidate(edge, goal, 1.0)); } this.candidates.Clear(); this.candidates.AddRange(picked); Debug.Log("On state " + this.currentNode.Id); } }
private void Populate( Func<ExplorationNode, ExplorationNode, double> scorer, bool descending = false) { if (this.currentNode == null) if (this.Explorer.IsDone == true) this.currentNode = Explorer.StateSpace.Nodes[0]; if (this.currentNode != null) { List<Candidate> candidates = new List<Candidate>(); foreach (ExplorationNode node in this.Explorer.StateSpace.Nodes) { if (this.currentNode == node) continue; // Make sure it's reachable ExplorationEdge[] path = this.currentNode.GetPathOut(node.Id); if (path != null) { // Add it as a candidate if the score is high enough double score = scorer(this.currentNode, node); ExplorationEdge edge = path[0]; ExplorationNode goal = path.Last().Target; candidates.Add(new Candidate(edge, goal, score)); } } // Sort the candidates by score candidates.Sort((c1, c2) => c1.Score.CompareTo(c2.Score)); if (descending == true) candidates.Reverse(); HashSet<ExplorationNode> seenNexts = new HashSet<ExplorationNode>(); HashSet<ExplorationNode> seenGoals = new HashSet<ExplorationNode>(); // A list of candidates that we've picked to display List<Candidate> picked = new List<Candidate>(); // Add the next step of the previous goal, if we had one if (this.previousGoal != null && this.previousGoal != this.currentNode && this.currentNode.GetPathOut(this.previousGoal.Id) != null) { // Get the path to the previous goal ExplorationEdge[] path = this.currentNode.GetPathOut(this.previousGoal.Id); // Make sure it's still reachable if (path != null) { // If so, add it as a picked candidate picked.Add( new Candidate(path[0], this.previousGoal, -1)); seenNexts.Add(path[0].Target); seenGoals.Add(this.previousGoal); } } // Pick the top N foreach (Candidate candidate in candidates) { ExplorationNode next = candidate.Edge.Target; ExplorationNode goal = candidate.Goal; // If this is a novel direction to go, add it bool seenGoal = seenGoals.Contains(goal); bool seenNext = seenNexts.Contains(next); if (seenGoal == false && seenNext == false) { picked.Add(candidate); seenNexts.Add(next); seenGoals.Add(goal); } if (picked.Count >= this.Recommendations) break; } this.candidates.Clear(); this.candidates.AddRange(picked); Debug.Log("On state " + this.currentNode.Id); } }
/// <summary> /// Checks the second transition in a 2-transition jump and sees if we can /// perform the collapse (there's no overlap, etc.) /// </summary> /// <param name="beginning">The first expanded node (beginning, middle, /// end)</param> /// <param name="jump1">The first edge (beginning-middle)</param> /// <param name="jump1Events">The events in the first edge</param> /// <param name="involvedInFirst">The objects involved in jump1</param> /// <param name="edgesToAdd">(out) A list in which we write the edges to /// add to the graph</param> private static void AnalyzeEndpoints( ExplorationNode beginning, ExplorationEdge jump1, IEnumerable<TransitionEvent> jump1Events, HashSet<uint> involvedInFirst, IList<ExplorationEdge> edgesToAdd) { // Get all of the final endpoint jumps (middle-end) foreach (ExplorationEdge jump2 in jump1.Target.Outgoing) { ExplorationNode end = jump2.Target; List<TransitionEvent> jump2Events = new List<TransitionEvent>(jump2.Events); // All the objects in jump2 HashSet<uint> involvedSecond = new HashSet<uint>(); GetInvolved(jump2Events).ForEach( (uint id) => { DebugUtil.Assert(involvedSecond.Contains(id) == false); involvedSecond.Add(id); }); // There's no overlap if (involvedInFirst.Overlaps(involvedSecond) == false) { List<TransitionEvent> combined = new List<TransitionEvent>(); combined.AddRange( jump1Events.Convert(s => new TransitionEvent(s))); combined.AddRange( jump2Events.Convert(s => new TransitionEvent(s))); edgesToAdd.Add( new ExplorationEdge(beginning, end, combined.ToArray())); } } }
/// <summary> /// Explores the state space resulting from the initial world state /// and produces a list of nodes in a graph /// </summary> /// <param name="initial">The initial world state</param> /// <param name="stateSpaceToFill">The list of nodes we add to</param> /// <returns>true if finished, false otherwise</returns> private static IEnumerable ExploreStateSpace( WorldState initial, EventDescriptor[] evtDescs, List<ExplorationNode> stateSpaceToFill) { List<ExplorationNode> openList = new List<ExplorationNode>(); Dictionary<WorldState, ExplorationNode> seen = new Dictionary<WorldState, ExplorationNode>(); uint i = 0; ExplorationNode firstNode = new ExplorationNode(initial); firstNode.Id = i; openList.Add(firstNode); seen.Add(initial, firstNode); while (openList.Count > 0) { // Pop the node off the open list ExplorationNode curNode = openList[0]; openList.RemoveAt(0); Rules.ClearCache(); AddExpansionsToLists(evtDescs, openList, seen, curNode); curNode.Id = i++; stateSpaceToFill.Add(curNode); yield return false; } yield break; }
/// <summary> /// Picks nodes with a low pagerank /// </summary> public static double Score_LowInvPagerank( ExplorationNode current, ExplorationNode candidate) { return candidate.InversePageRank; }
/// <summary> /// Picks nodes with a high pagerank /// </summary> public static double Score_HighPagerank( ExplorationNode current, ExplorationNode candidate) { return 1.0 / candidate.PageRank; }
private void CreateGrid() { if (GridCreated) return; Cells = new List<WorldSceneCell>(); foreach (var navCell in Scene.Mesh.Zone.NavZoneDef.NavCells) { //if (navCell.Flags.HasFlag(NavCellFlags.AllowWalk)) //{ Cells.Add(new WorldSceneCell(navCell, Min)); //} } if (SubScene != null) { foreach (var navCell in SubScene.Scene.Mesh.Zone.NavZoneDef.NavCells) { //if (navCell.Flags.HasFlag(NavCellFlags.AllowWalk)) //{ Cells.Add(new WorldSceneCell(navCell, SubScene.Min)); //} } if (SubScene.SubScene != null) { foreach (var navCell in SubScene.SubScene.Scene.Mesh.Zone.NavZoneDef.NavCells) { //if (navCell.Flags.HasFlag(NavCellFlags.AllowWalk)) //{ Cells.Add(new WorldSceneCell(navCell, SubScene.SubScene.Min)); //} } } } var navBoxSize = ExplorationData.ExplorationNodeBoxSize; var searchBeginning = navBoxSize / 2; //var cellCount = _boxSize / navBoxSize; //var maxCellsCount = cellCount * cellCount; for (var x = Min.X + searchBeginning; x <= Max.X; x = x + navBoxSize) { for (var y = Min.Y + searchBeginning; y <= Max.Y; y = y + navBoxSize) { var navNode = new ExplorationNode(new Vector2(x, y), _boxSize, _boxTolerance, this); Nodes.Add(navNode); } } //var width = (int)(Max.X - Min.X); //var height = (int)(Max.Y - Min.Y); //var gridSizeX = width / _boxSize; //var gridSizeY = height / _boxSize; ////var grid = new Node[gridSizeX, gridSizeY]; //for (var x = 0; x < gridSizeX; x++) //{ // for (var y = 0; y < gridSizeY; y++) // { // var center = Min + new Vector2(x * _boxSize + _boxSize / 2, y * _boxSize + _boxSize / 2); // Nodes.Add(new ExplorationNode(center, _boxSize, _boxTolerance, this)); // } //} GridCreated = true; }
public Recommender(ExplorationSpace space) { this.space = space; this.current = space.Nodes[0]; this.busyObjects = new HashSet<uint>(); }
public static List<ExplorationNode> GetExplorationNodesInRadius(ExplorationNode centerNode, float radius) { var gridDistance = Instance.ToGridDistance(radius); var neighbors = centerNode.GetNeighbors(gridDistance, true); return neighbors.Where(n => n.Center.DistanceSqr(centerNode.NavigableCenter2D) < radius * radius).ToList(); }
public static IEnumerable<Candidate> GetCandidates( ExplorationSpace space, ExplorationNode start, ExplorationNode lastGoal, HashSet<uint> busyObjects) { return GetCandidates( space, start, lastGoal, busyObjects, DEFAULT_SCORER, DEFAULT_RECOMMENDATIONS, DEFAULT_DESCENDING); }
/// <summary> /// Expands all of the transitions and adds the resulting world states /// to the list of nodes during exploration /// </summary> /// <param name="openList">The list of nodes we haven't explored /// yet</param> /// <param name="seen">The list of nodes we've seen</param> /// <param name="curNode">The current node from the open list</param> private static void AddExpansionsToLists( EventDescriptor[] evtDescs, List<ExplorationNode> openList, Dictionary<WorldState, ExplorationNode> seen, ExplorationNode curNode) { // Find all of the event signatures foreach (EventDescriptor evtDesc in evtDescs) { IEnumerable<Tuple<WorldState, uint[]>> expansions = GetExpansions(curNode.State, evtDesc); // Get all of the expansions foreach (Tuple<WorldState, uint[]> expansion in expansions) { WorldState expansionState = expansion.Item1; ExplorationNode expansionNode; // If we haven't seen the world state if (seen.TryGetValue(expansionState, out expansionNode) == false) { expansionNode = new ExplorationNode(expansionState); openList.Add(expansionNode); seen.Add(expansionState, expansionNode); } DebugUtil.Assert(expansionNode != null); TransitionEvent transition = new TransitionEvent(evtDesc, expansion.Item2); ExplorationEdge edge = new ExplorationEdge( curNode, expansionNode, transition); curNode.AddOutgoing(edge); expansionNode.AddIncoming(edge); } } }
public static IEnumerable<Candidate> GetCandidates( ExplorationSpace space, ExplorationNode start, Scorer scorer) { return GetCandidates( space, start, null, null, scorer, DEFAULT_RECOMMENDATIONS, DEFAULT_DESCENDING); }
//private readonly WaitTimer _newNodePickTimer = new WaitTimer(TimeSpan.FromSeconds(60)); private async Task<bool> Exploring() { if (_currentDestination == null || _currentDestination.IsVisited)// || _newNodePickTimer.IsFinished) { //_newNodePickTimer.Stop(); //_currentDestination = ExplorationHelpers.NearestWeightedUnvisitedNodeLocation(_levelAreaIds); if (_currentDestination != null) { _currentDestination.IsCurrentDestination = false; } _currentDestination = ExplorationHelpers.NearestWeightedUnvisitedNode(_levelAreaIds); if (_currentDestination != null) _currentDestination.IsCurrentDestination = true; //_newNodePickTimer.Reset(); } if (_currentDestination != null) { if (await NavigationCoroutine.MoveTo(_currentDestination.NavigableCenter, 3)) { _currentDestination.IsVisited = true; _currentDestination.IsCurrentDestination = false; _currentDestination = null; } return false; } State = States.Completed; return false; }
public static IEnumerable<Candidate> GetCandidates( ExplorationSpace space, ExplorationNode start, int numRecommendations) { return GetCandidates( space, start, null, null, DEFAULT_SCORER, numRecommendations, DEFAULT_DESCENDING); }
public static IEnumerable<Candidate> GetCandidates( ExplorationSpace space, ExplorationNode start, ExplorationNode lastGoal, HashSet<uint> busyObjects, Scorer scorer, int numRecommendations, bool descending) { if (busyObjects == null) busyObjects = new HashSet<uint>(); List<Candidate> candidates = new List<Candidate>(); foreach (ExplorationNode node in space.Nodes) { if (start == node) continue; // Make sure it's reachable ExplorationEdge[] path = start.GetPathOut(node.Id); if (path != null) { // Add it as a candidate if the score is high enough double score = scorer(start, node); ExplorationEdge edge = path[0]; ExplorationNode goal = path.Last().Target; double sentimentScore = SentimentScore(score, path); candidates.Add(new Candidate(path, goal, sentimentScore)); } } // Sort the candidates by score candidates.Sort((c1, c2) => c1.Score.CompareTo(c2.Score)); if (descending == true) candidates.Reverse(); // Add the previous goal to the front if we still have a path to it if (lastGoal != null) { ExplorationEdge[] oldPath = start.GetPathOut(lastGoal.Id); if (oldPath != null) candidates.Insert(0, new Candidate(oldPath, lastGoal, 0.0)); } HashSet<ExplorationNode> seenGoals = new HashSet<ExplorationNode>(); HashSet<ExplorationEdge> seenEdges = new HashSet<ExplorationEdge>(); // Pick the top N int count = 0; foreach (Candidate candidate in candidates) { ExplorationNode goal = candidate.Goal; if (candidate.Path.Length == 0) continue; ExplorationEdge edge = candidate.Path[0]; // Nix this event if it uses an object that's currently in use // TODO: Assumes only one event per edge TransitionEvent evt = edge.Events[0]; foreach (uint id in evt.Participants) if (busyObjects.Contains(id) == true) goto skipCandidate; // If this is a novel direction to go, add it bool seenGoal = seenGoals.Contains(goal); bool seenEdge = seenEdges.Contains(edge); if (seenGoal == false && seenEdge == false) { seenGoals.Add(goal); seenEdges.Add(edge); count++; yield return candidate; } if (count >= numRecommendations) break; skipCandidate : continue; } }
/// <summary> /// Picks far away nodes /// </summary> public static double Score_Distance( ExplorationNode current, ExplorationNode candidate) { return 1.0 / current.GetPathOut(candidate.Id).Length; }
public void OnButtonClick(int which) { DebugUtil.Assert(this.candidates.Count > which); Candidate candidate = this.candidates[which]; DebugUtil.Assert(candidate != null); // TODO: Only taking the first event TransitionEvent evt = candidate.Edge.Events[0]; DebugUtil.Assert(evt != null); this.DeselectAll(evt); EventSignature sig = (EventSignature)evt.Descriptor; SmartEvent instance = sig.Create(this.GetParameters(evt)); string output = evt.Descriptor.Name; foreach (object parameter in this.GetParameters(evt)) { SmartObject obj = (SmartObject)parameter; output += " " + obj.gameObject.name; } Debug.LogWarning("Executing: " + output); instance.StartEvent(1.0f); this.previousGoal = candidate.Goal; this.Depopulate(); this.currentEvent = instance; this.currentEdge = candidate.Edge; }
//private readonly WaitTimer _newNodePickTimer = new WaitTimer(TimeSpan.FromSeconds(60)); private async Task <bool> Exploring() { if (_useIgnoreRegions) { ExplorationHelpers.UpdateIgnoreRegions(); } if (_currentDestination == null || _currentDestination.IsVisited)// || _newNodePickTimer.IsFinished) { //_newNodePickTimer.Stop(); //_currentDestination = ExplorationHelpers.NearestWeightedUnvisitedNodeLocation(_levelAreaIds); if (_explorationDataMaxWaitUntil != DateTime.MinValue && DateTime.UtcNow > _explorationDataMaxWaitUntil) { Core.Logger.Debug($"[Exploration] Timeout waiting for exploration data"); State = States.Completed; return(false); } if (!ExplorationGrid.Instance.WalkableNodes.Any()) { if (_explorationDataMaxWaitUntil == DateTime.MinValue) { _explorationDataMaxWaitUntil = DateTime.UtcNow + TimeSpan.FromSeconds(15); } Core.Scenes.Update(); await Coroutine.Sleep(1000); Core.Logger.Debug($"[Exploration] Patiently waiting for exploration data"); return(false); } _explorationDataMaxWaitUntil = DateTime.MinValue; if (_currentDestination != null) { _currentDestination.IsCurrentDestination = false; } var destination = ExplorationHelpers.NearestWeightedUnvisitedNode(_levelAreaIds); if (destination == null) { Core.Logger.Debug($"[Exploration] No more unvisited nodes to explore, so we're done."); State = States.Completed; return(false); } if (_currentDestination != destination) { Core.Logger.Debug($"[Exploration] Destination Changed from {_currentDestination?.NavigableCenter} to {destination.NavigableCenter}"); _currentDestination = destination; } if (_currentDestination != null) { Core.Logger.Debug($"[Exploration] Current Destination {_currentDestination?.NavigableCenter}, CanRayWalk={CanRayWalkDestination} MyPosition={AdvDia.MyPosition}"); _currentDestination.IsCurrentDestination = true; } //_newNodePickTimer.Reset(); } if (_currentDestination != null) { if (await NavigationCoroutine.MoveTo(_currentDestination.NavigableCenter, 15)) { if (NavigationCoroutine.LastResult == CoroutineResult.Failure && (NavigationCoroutine.LastMoveResult == MoveResult.Failed || NavigationCoroutine.LastMoveResult == MoveResult.PathGenerationFailed)) { _currentDestination.FailedNavigationAttempts++; var canClientPathTo = await AdvDia.Navigator.CanFullyClientPathTo(_currentDestination.NavigableCenter); if (_currentDestination.FailedNavigationAttempts >= 10 && !canClientPathTo) { Core.Logger.Debug($"[Exploration] Unable to client path to {_currentDestination.NavigableCenter} and failed {_currentDestination.FailedNavigationAttempts} times; Ignoring Node."); _currentDestination.IsVisited = true; _currentDestination.IsIgnored = true; _currentDestination.IsCurrentDestination = false; _currentDestination = null; _failedNavigationAttempts++; } else if (!CanRayWalkDestination && _currentDestination.Distance < 25f && _currentDestination.FailedNavigationAttempts >= 3 || _currentDestination.FailedNavigationAttempts >= 15) { Core.Logger.Debug($"[Exploration] Failed to Navigate to {_currentDestination.NavigableCenter} {_currentDestination.FailedNavigationAttempts} times; Ignoring Node."); _currentDestination.IsVisited = true; _currentDestination.IsIgnored = true; _currentDestination.IsCurrentDestination = false; _currentDestination = null; _failedNavigationAttempts++; } } else { Core.Logger.Debug($"[Exploration] Destination Reached!"); _currentDestination.FailedNavigationAttempts = 0; _currentDestination.IsVisited = true; _currentDestination.IsCurrentDestination = false; _currentDestination = null; } if (_failedNavigationAttempts > 25) { if (_allowReExplore) { Core.Logger.Debug($"[Exploration] Exploration Resetting"); Core.Scenes.Reset(); Navigator.Clear(); _failedNavigationAttempts = 0; } else { Core.Logger.Debug($"[Exploration] too many failed navigation attempts, aborting."); State = States.Completed; return(false); } } } return(false); } Core.Logger.Debug($"[Exploration] We found no explore destination, so we're done."); Core.Scenes.Reset(); Navigator.Clear(); State = States.Completed; return(false); }
private void Advance() { DebugUtil.Assert(this.currentNode == this.currentEdge.Source); this.currentNode = this.currentEdge.Target; }
/// <summary> /// Picks nodes with a low average min-cut out /// </summary> public static double Score_TrapNodes( ExplorationNode current, ExplorationNode candidate) { return (double)candidate.AverageMinCutOut(); }
private async Task <bool> Exploring() { if (_useIgnoreRegions) { ExplorationHelpers.UpdateIgnoreRegions(); } if (_currentDestination == null || _currentDestination.IsVisited) { if (_explorationDataMaxWaitUntil != DateTime.MinValue && DateTime.UtcNow > _explorationDataMaxWaitUntil) { Core.Logger.Debug($"[Exploration] Timeout waiting for exploration data"); State = States.Completed; return(false); } if (!ExplorationGrid.Instance.WalkableNodes.Any()) { if (_explorationDataMaxWaitUntil == DateTime.MinValue) { _explorationDataMaxWaitUntil = DateTime.UtcNow + TimeSpan.FromSeconds(15); } Core.Scenes.Update(); await Coroutine.Sleep(1000); Core.Logger.Debug($"[Exploration] Patiently waiting for exploration data"); return(false); } _explorationDataMaxWaitUntil = DateTime.MinValue; if (_currentDestination != null) { _currentDestination.IsCurrentDestination = false; } var destination = ExplorationHelpers.NearestWeightedUnvisitedNode(_levelAreaIds); // Ignore marking nodes as Visited for bounties. if (destination != null && ZetaDia.Storage.Quests.ActiveBounty == null) { WorldScene destScene = destination.Scene; Vector3 destinationPos = destination.NavigableCenter; var exitPositions = destScene.ExitPositions; var connectedScenes = destScene.ConnectedScenes(); var unconnectedExits = exitPositions.Where(ep => connectedScenes.FirstOrDefault(cs => cs.Direction == ep.Key) == null); if (destinationPos.Distance(ExplorationHelpers.PriorityPosition) >= 15) { if (!unconnectedExits.Any(ep => destinationPos.Distance(ep.Value) <= 15) && ZetaDia.Minimap.IsExplored(destinationPos, AdvDia.CurrentWorldDynamicId)) { destination.IsVisited = true; destination.IsKnown = true; return(false); } } } if (destination == null) { Core.Logger.Debug($"[Exploration] No more unvisited nodes to explore, so we're done."); State = States.Completed; return(false); } if (_currentDestination != destination) { Core.Logger.Debug($"[Exploration] Destination Changed from {_currentDestination?.NavigableCenter} to {destination.NavigableCenter}"); _currentDestination = destination; } if (_currentDestination != null) { Core.Logger.Debug($"[Exploration] Current Destination {_currentDestination?.NavigableCenter}, CanRayWalk={CanRayWalkDestination} MyPosition={AdvDia.MyPosition}"); _currentDestination.IsCurrentDestination = true; } //_newNodePickTimer.Reset(); } if (_currentDestination != null) { if (await NavigationCoroutine.MoveTo(_currentDestination.NavigableCenter, 15)) { if (NavigationCoroutine.LastResult == CoroutineResult.Failure && (NavigationCoroutine.LastMoveResult == MoveResult.Failed || NavigationCoroutine.LastMoveResult == MoveResult.PathGenerationFailed)) { _currentDestination.FailedNavigationAttempts++; var canClientPathTo = await AdvDia.Navigator.CanFullyClientPathTo(_currentDestination.NavigableCenter); if (_currentDestination.FailedNavigationAttempts >= 10 && !canClientPathTo) { Core.Logger.Debug($"[Exploration] Unable to client path to {_currentDestination.NavigableCenter} and failed {_currentDestination.FailedNavigationAttempts} times; Ignoring Node."); _currentDestination.IsVisited = true; _currentDestination.IsIgnored = true; _currentDestination.IsCurrentDestination = false; _currentDestination = null; _failedNavigationAttempts++; } else if (!CanRayWalkDestination && _currentDestination.Distance < 25f && _currentDestination.FailedNavigationAttempts >= 3 || _currentDestination.FailedNavigationAttempts >= 15) { Core.Logger.Debug($"[Exploration] Failed to Navigate to {_currentDestination.NavigableCenter} {_currentDestination.FailedNavigationAttempts} times; Ignoring Node."); _currentDestination.IsVisited = true; _currentDestination.IsIgnored = true; _currentDestination.IsCurrentDestination = false; _currentDestination = null; _failedNavigationAttempts++; } } else { Core.Logger.Debug($"[Exploration] Destination Reached!"); _currentDestination.FailedNavigationAttempts = 0; _currentDestination.IsVisited = true; _currentDestination.IsCurrentDestination = false; _currentDestination = null; } if (_failedNavigationAttempts > 25) { if (_allowReExplore) { Core.Logger.Debug($"[Exploration] Exploration Resetting"); Core.Scenes.Reset(); Navigator.Clear(); _failedNavigationAttempts = 0; } else { Core.Logger.Debug($"[Exploration] too many failed navigation attempts, aborting."); State = States.Completed; return(false); } } } return(false); } Core.Logger.Debug($"[Exploration] We found no explore destination, so we're done."); Core.Scenes.Reset(); Navigator.Clear(); State = States.Completed; return(false); }
private static void AssignEdgesToNode( Dictionary<uint, ExplorationEdge> idToEdge, NodeData data, ExplorationNode node) { // Add the incoming and outgoing nodes, in order foreach (uint id in data.Incoming) node.AddIncoming(idToEdge[id]); foreach (uint id in data.Outgoing) node.AddOutgoing(idToEdge[id]); List<ExplorationEdge> edges = new List<ExplorationEdge>(); // Convert the path to path edges for each target for (int tIdx = 0; tIdx < data.Paths.Length; tIdx++) { uint[] pathIds = data.Paths[tIdx]; ExplorationEdge[] pathEdges = pathIds.Convert((id) => idToEdge[id]).ToArray(); ExplorationNode target = pathEdges.Last().Target; node.SetPathOut(target.Id, pathEdges); } }