/// <summary> /// Handles the event which is fired if the player has reached the target point. /// </summary> private void ReachedTargetPoint() { // Special case: Path Discovery. if (performsPathDiscovery && originRouter != null) { if (isLogEnabled) { Debug.Log("DijkstraMovementManager: PathDiscovery: Need to move player back to origin router."); } performsPathDiscovery = false; movementScript.ControlPuddleSpawning(false); // Move player back to origin router. movementScript.MovePlayer(originRouter); originRouter = null; } else { SpriteRenderer sr = player.GetComponentInChildren <SpriteRenderer>(); sr.color = Color.white; // Update the routing table. routingTableUI.UpdateRoutingTableUI(); // Show the path costs. if (currentPath != null && currentPath.IsDiscovered() == true) { currentPath.DisplayPathCosts(); // Display path costs also for the way back. dijkstraManager.GetInversePath(currentPath).DisplayPathCosts(); //writeFileLog } // If it is a valid discovery move, check if the current working router is completely handled now. if (currentStatus == DijkstraStatus.VALID_HOP_DISCOVERY || currentStatus == DijkstraStatus.VALID_HOP) { bool isHandled = dijkstraManager.IsCurrentWorkingRouterHandledCompletely(); if (isHandled) { dijkstraManager.GetCurrentPlayerPosition().GetComponent <RouterScript>().HighlightRouter(); if (soundManager != null) { soundManager.PlaySound(SoundManager.SoundType.RunComplete); } } } } }
/// <summary> /// Checks whether the current working router is completely handled, i.e. all paths from /// or to this router have been discovered by the player. /// </summary> /// <returns>Returns true, if all paths from or to the current working router are discovered. Returns false, if there /// are still undiscovered paths.</returns> public bool IsCurrentWorkingRouterHandledCompletely() { bool handledCompletely = true; for (int i = 0; i < graphRepresentation2.GetLength(1); i++) { PathScript path = graphRepresentation2[routerScriptCurrentPlayerPosition.GetRouterIndex(), i]; // extract a path from or to the current working router. if (path != null) { if (!path.IsDiscovered()) { handledCompletely = false; // There is still an undiscovered path, so the working router isn't handled completely so far. } } } return(handledCompletely); }
/// <summary> /// Checks whether the attempted hop by the player is a valid hop which fulfills the conditions of the dijkstra algorithm. /// First, it is checked whether the path is connecting the router on which the player is currently located and an adjacent router. /// If not, it is an invalid hop. Second, it is checked whether the path is already discovered. If not, it is a valid hop, but a /// hop in discovery mode. If the path it is not discovered and there are still undiscovered paths connected to the router on which the player is /// located, it is an invalid hop due to undiscovered neighbors. Third, if the target router of this path has already been handled, the user /// can move back to this router, so its a valid hop. Finally, if non of the cases mentioned before has applied, the player wants to perform an /// actual movement towards an router which should be handled by the dijkstra algorithm next. It is checked whether the target router determined by /// the path is actually a router that the dijkstra algorithm would handle next. If it is, it is a valid hop, otherwise it is an invalid hop concerning /// the dijkstra algorithm. /// </summary> /// <param name="path">The path between the two routers which should be passed in this hop.</param> /// <returns>The result of the dijkstra path check.</returns> public DijkstraStatus IsValidHop(PathScript path) { RouterScript from; RouterScript to; DijkstraMove dijkstraMove = new DijkstraMove(); // Get path script. //PathScript currentPath = graphRepresentation2[from.GetRouterIndex(), to.GetRouterIndex()]; PathScript currentPath = path; if (currentPath == null) { // Invalid hop, no path found between these routers. return(DijkstraStatus.HOP_UNREACHABLE); } // Check on which of the routers the player is located. if (path.from.GetComponent <RouterScript>() == routerScriptCurrentPlayerPosition) { to = path.to.GetComponent <RouterScript>(); from = path.from.GetComponent <RouterScript>(); } else if (bidirectional && path.to.GetComponent <RouterScript>() == routerScriptCurrentPlayerPosition) { to = path.from.GetComponent <RouterScript>(); from = path.to.GetComponent <RouterScript>(); } else { dijkstraMove.Source = routerScriptCurrentPlayerPosition; dijkstraMove.Destination = currentPath.from.GetComponent <RouterScript>(); dijkstraMove.Status = DijkstraStatus.HOP_UNREACHABLE; listOfMoves.Add(dijkstraMove); // Invalid hop if player is not located on one of these routers. return(DijkstraStatus.HOP_UNREACHABLE); } // Store the routers in the DijkstraMove object. dijkstraMove.Source = from; dijkstraMove.Destination = to; // Check if player is in error recovery mode. if (errorRecovery) { dijkstraMove.Status = DijkstraStatus.ERROR_RECOVERY; listOfMoves.Add(dijkstraMove); return(DijkstraStatus.ERROR_RECOVERY); } // Check whether the path is already discovered. if (!currentPath.IsDiscovered()) { dijkstraMove.Status = DijkstraStatus.VALID_HOP_DISCOVERY; listOfMoves.Add(dijkstraMove); // It is a valid hop. It is a path discovery move. return(DijkstraStatus.VALID_HOP_DISCOVERY); } // Check if all paths to the adjacent routers have already been discovered. for (int i = 0; i < graphRepresentation2.GetLength(1); i++) { PathScript pathToNeighbor = graphRepresentation2[from.GetRouterIndex(), i]; if (pathToNeighbor != null && !pathToNeighbor.IsDiscovered()) { dijkstraMove.Status = DijkstraStatus.UNDISCOVERED_PATHS; listOfMoves.Add(dijkstraMove); // Not a valid move. The player needs to perform path discovery on all paths of this router first. return(DijkstraStatus.UNDISCOVERED_PATHS); } } // Check if the router has already been handled by the dijkstra algorithm. // If the router has already been handled, the player can perform a hop to this router. // Perform this check after the 'all paths discovered' check to make sure the player has handled the current working router completely before moving back to a already handled router. if (!priorityQueue.IsContained(to)) { dijkstraMove.Status = DijkstraStatus.NOP; listOfMoves.Add(dijkstraMove); // Valid hop. return(DijkstraStatus.NOP); } // Check if the hop conforms to the hop which will be performed by the Dijkstra algorithm. // To do this, get the next hop from the priority queue, i.e. the router with the currently shortest distance. if (priorityQueue.Peek() == to) { dijkstraMove.Status = DijkstraStatus.VALID_HOP; listOfMoves.Add(dijkstraMove); // All conditions are met. It is a valid move. return(DijkstraStatus.VALID_HOP); } else { // It is still possible that there is another router which has the same distance and is thus a valid next hop. bool isValidHop = false; // To check this, we need to remove the elements before this router from the queue and later put them back in. RouterScript headOfQueue = priorityQueue.PullHighest(); // Check the following routers. Stop if they have a higher priority than the original head. List <RouterScript> nextRouterCandidates = new List <RouterScript>(); while (priorityQueue.Count() > 0 && priorityQueue.Peek().GetPriority() == headOfQueue.GetPriority()) { RouterScript candidateRouter = priorityQueue.PullHighest(); nextRouterCandidates.Add(candidateRouter); if (candidateRouter == to) { isValidHop = true; break; } } // Store the candidate routers and the original headOfQueue back into the priority queue. priorityQueue.Enqueue(headOfQueue); for (int i = 0; i < nextRouterCandidates.Count; i++) { priorityQueue.Enqueue(nextRouterCandidates[i]); } // Break if it isn't a valid hop. if (!isValidHop) { dijkstraMove.Status = DijkstraStatus.WRONG_HOP; listOfMoves.Add(dijkstraMove); return(DijkstraStatus.WRONG_HOP); } } dijkstraMove.Status = DijkstraStatus.VALID_HOP; listOfMoves.Add(dijkstraMove); // All conditions are met. It is a valid move. return(DijkstraStatus.VALID_HOP); }