/// <summary> /// Performs a hop within error recovery mode. It is checked whether this hop /// brings the player back to the last valid router. If the player returns to the /// last valid router, the error recovery mode will be disabled. Otherwise, /// the player remains in error recovery mode. /// </summary> /// <param name="path">The path along which the player performs the hop.</param> /// <returns>The current status of the error recovery.</returns> public ErrorRecoveryStatus PerformErrorRecoveryHop(PathScript path) { RouterScript from = path.from.GetComponent <RouterScript>(); RouterScript to = path.to.GetComponent <RouterScript>(); // Check if player returns to the last valid hop. if (lastValidRouter == to || (bidirectional && lastValidRouter == from)) { lastValidRouter = null; // Error recovery finished. errorRecovery = false; if (isLogEnabled) { Debug.Log("Left error recovery mode."); } } // Update the current player position according to the performed hop. UpdateCurrentPlayerPosition(path); // Check if still in error recovery mode. if (errorRecovery) { return(ErrorRecoveryStatus.ERROR_NOT_RECOVERED); } return(ErrorRecoveryStatus.ERROR_RECOVERED); }
void GameManagerInterface.Start(GameTuple startAndEndPoint) { recreateGraphRepresentation(); base.InitializeRun(startAndEndPoint); RouterScript currentRouter = activeRouter.GetComponent <RouterScript>(); currentRouter.SetPriority(0); neighboursOfActiveRouter = ExpandNode(currentRouter); prioQueue = new PriorityQueue <RouterScript>(); for (int i = 0; i < neighboursOfActiveRouter.Count; i++) { PathScript pathToNeighbor = graphRepresentation2[currentRouter.GetRouterIndex(), neighboursOfActiveRouter[i].GetRouterIndex()]; neighboursOfActiveRouter[i].SetPriority(pathToNeighbor.GetPathCosts()); prioQueue.Enqueue(neighboursOfActiveRouter[i]); if (isLogEnabled) { Debug.Log(string.Format("Added router {0} to prio queue with path costs {1}.", neighboursOfActiveRouter[i], pathToNeighbor.GetPathCosts())); } } }
/// <summary> /// A helper method that sorts the entries of the array of RouterScript instances according /// to the current priority of their corresponding router. The entries are /// sorted ascendingly. /// </summary> /// <param name="routers">The array of RouterScript instances that should be sorted.</param> /// <returns>A sorted version of the array that was passed as a parameter.</returns> private RouterScript[] sortRouterArrayByPriority(RouterScript[] routers) { bool isSorted = false; while (!isSorted) { // Assume it is sorted. isSorted = true; // Check if all elements are sorted. for (int i = 0; i < routers.Length - 1; i++) { // Sort by priority ascendingly. if (routers[i].GetPriority() > routers[i + 1].GetPriority()) { // Not sorted yet. isSorted = false; // Swap elements. RouterScript tmp = routers[i]; routers[i] = routers[i + 1]; routers[i + 1] = tmp; } } } return(routers); }
/// <summary> /// Equivalent to neighborPaths in the GreedyManager, returns all children/neighbors of this router. /// </summary> /// <returns>The neighbors/children of the current working router</returns> /// <param name="current">Current Working router</param> public List <RouterScript> ExpandNode(RouterScript current) { List <RouterScript> neighbors = new List <RouterScript>(); List <PathScript> neighborPaths = new List <PathScript>(); int currentRouterIndex = current.GetRouterIndex(); //Extract paths from graph representation. for (int i = 0; i < graphRepresentation2.GetLength(1); i++) { if (graphRepresentation2[currentRouterIndex, i] != null) { neighborPaths.Add(graphRepresentation2[currentRouterIndex, i]); } } foreach (PathScript p in neighborPaths) { RouterScript from = p.from.GetComponent <RouterScript>(); RouterScript to = p.to.GetComponent <RouterScript>(); if (current == from) { neighbors.Add(to); } } return(neighbors); }
/// <summary> /// Displays the destination router on top of the beer bottle. /// </summary> public void displayDestinationRouter() { SpriteRenderer spriteRenderer = transform.GetComponentInChildren <SpriteRenderer>(); // Get the Text Mesh. The TextMesh is contained in the first child of the router game object. TextMesh textField = null; foreach (TextMesh m in GetComponentsInChildren <TextMesh>()) { if (m.name == "PathDestinationText") { textField = m; } } if (textField != null) { textField.transform.localScale = new Vector3(0.1f, 0.1f, 1.0f); // Set the rendering order and the sorting order of the TextMesh. MeshRenderer textFieldRenderer = textField.transform.GetComponent <MeshRenderer>(); textFieldRenderer.sortingLayerID = spriteRenderer.sortingLayerID; textFieldRenderer.sortingOrder = spriteRenderer.sortingOrder + 2; // Set sorting order +2 compared to the sprite renderer. // Set the position and text of the TextMesh. Vector3 routerPosition = transform.position; routerPosition.x = routerPosition.x + offsetX; routerPosition.y = routerPosition.y + offsetY; textField.transform.position = routerPosition; RouterScript toScript = to.GetComponent <RouterScript>(); textField.text = toScript.routerName; } }
private void UpdateGreedyHeuristics(RouterScript source, RouterScript destination) { foreach (RouterScript tmp in listOfRouterScripts) { int heuristic = CalcStraightLineHeuristic(tmp, destination); tmp.SetGreedyHeuristicValue(heuristic); } }
/// <summary> /// Finds the greedy path between source and destination. /// </summary> /// <param name="source">Source.</param> /// <param name="destination">Destination.</param> private List <RouterScript> FindPath(RouterScript source, RouterScript destination) { if (isLogEnabled) { Debug.Log("Finding best greedy path!"); } prioQueue = new PriorityQueue <RouterScript>(); RouterScript current = source; List <RouterScript> closed = new List <RouterScript>(); List <RouterScript> children = new List <RouterScript>(); if (isLogEnabled) { Debug.Log("Starting Greedy from " + current.name + " to " + destination.name); } UpdateGreedyHeuristics(source, destination); while (current != destination) { if (!closed.Contains(current)) { children = ExpandNode(current); foreach (RouterScript tmp in children) { if (isLogEnabled) { Debug.Log("Current Child: " + tmp.name + " | heuristic: " + tmp.GetGreedyHeuristicValue()); } tmp.SetPriority(tmp.GetGreedyHeuristicValue()); prioQueue.Enqueue(tmp); } closed.Add(current); } if (isLogEnabled) { Debug.Log("Finished with: " + current.name); } //Check if more than one solution exists. current = prioQueue.PullHighest(); } string path = ""; foreach (RouterScript tmp in closed) { path += tmp.name + "|" + CalcStraightLineHeuristic(tmp, destination) + " >> "; } path += current.name + "|0"; if (isLogEnabled) { Debug.Log("Path=" + path); } closed.Add(destination); return(closed); }
/// <summary> /// Returns the predecessor router of the target router on the shortest path from the starting /// router to the target router. /// </summary> /// <param name="targetRouter">The router whose predecessor on the shortest path should be extracted.</param> /// <returns>The RouterScript instance from the predecessor router or null if there is no valid predecessor for the target router.</returns> public RouterScript GetPredecessorRouterOnShortestPath(RouterScript targetRouter) { // Check if router has a valid predecessor. if (predecessorRouter.ContainsKey(targetRouter)) { return(predecessorRouter[targetRouter]); } return(null); }
/// <summary> /// Determines whether this router instance is already handled in the current run. /// </summary> /// <returns><c>true</c> if this router instance is already handled in the current run; otherwise, <c>false</c>.</returns> /// <param name="router">The router instance.</param> public bool IsRouterAlreadyHandled(RouterScript router) { // The routers in current path have already been visited and no shorter path // can be found for this routers. if (currentPath != null && !currentPath.Contains(router)) { return(false); } return(true); }
/// <summary> /// Performs the path discovery on the specified path. The path costs of this path /// are determined and it is checked whether the target router can be reached with /// less path costs using this path. If the target router can be reached with less /// path costs via this path, the distance (priority) of the router is adjusted and /// the previous router on this path stored in the predecessorRouter data structure. /// Finally, the path is set to discovered. /// </summary> /// <param name="path">The path for which the path discovery is performed.</param> public void PerformPathDiscovery(PathScript path) { RouterScript from = path.from.GetComponent <RouterScript>(); RouterScript to = path.to.GetComponent <RouterScript>(); RouterScript previousRouter = null; RouterScript discoveredRouter = null; // Check which router will be discovered. if (from == routerScriptCurrentPlayerPosition) { // Player discovers 'to' router. discoveredRouter = to; previousRouter = routerScriptCurrentPlayerPosition; } else if (bidirectional && to == routerScriptCurrentPlayerPosition) { // Player discovers 'from' router. discoveredRouter = from; previousRouter = routerScriptCurrentPlayerPosition; } // Update the current distance if we have found a shorter path to the discovered router. // This only needs to be done when the discovered router has not already been handled by the dijkstra algorithm. if (priorityQueue.IsContained(discoveredRouter)) { // Path costs to the discovered router are the path cost to the previous router + the path costs of this path. int pathCost = previousRouter.GetPriority() + graphRepresentation2[previousRouter.GetRouterIndex(), discoveredRouter.GetRouterIndex()].GetPathCosts(); // Are the new path costs lower than the currently stored lowest path costs. if (pathCost < discoveredRouter.GetPriority()) { // Update the path costs of the router. priorityQueue.DecreasePriority(discoveredRouter, pathCost); // Set the new predecessor for this router. predecessorRouter[discoveredRouter] = previousRouter; } } // Set path to discovered. graphRepresentation2[previousRouter.GetRouterIndex(), discoveredRouter.GetRouterIndex()].SetDiscovered(true); //graphRepresentation2[previousRouter.GetRouterIndex(), discoveredRouter.GetRouterIndex()].DisplayPathCosts(); // If there is a path back with the same costs, discover this path as well. PathScript backPath = graphRepresentation2[discoveredRouter.GetRouterIndex(), previousRouter.GetRouterIndex()]; if (backPath != null && backPath.GetPathCosts() == path.GetPathCosts()) { backPath.SetDiscovered(true); //backPath.DisplayPathCosts(); } // Test: Output the current priority queue. // Debug.Log(priorityQueue.ToString()); }
/// <summary> /// Determines whether this hop is a valid uniform cost hop for the specified targetRouter. /// </summary> /// <returns><c>true</c> if this instance is a valid uniform cost hop for the specified targetRouter; otherwise, <c>false</c>.</returns> /// <param name="targetRouter">Target router.</param> private bool IsValidUniformCostHop(RouterScript targetRouter) { if (!prioQueue.IsContained(targetRouter)) { // Valid hop. return(true); } // Is the target the first element in the priority queue? if (prioQueue.Peek() == targetRouter) { return(true); } else { // Target is not the first element in the priority Queue. // But it is still a valid hop if there are more elements with // the same costs. 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 = prioQueue.PullHighest(); // Check the following routers. Stop if they have a higher priority than the original head. List <RouterScript> nextRouterCandidates = new List <RouterScript>(); while (prioQueue.Count() > 0 && prioQueue.Peek().GetPriority() == headOfQueue.GetPriority()) { RouterScript candidateRouter = prioQueue.PullHighest(); nextRouterCandidates.Add(candidateRouter); if (candidateRouter == targetRouter) { isValidHop = true; break; } } // Store the candidate routers and the original headOfQueue back into the priority queue. prioQueue.Enqueue(headOfQueue); for (int i = 0; i < nextRouterCandidates.Count; i++) { prioQueue.Enqueue(nextRouterCandidates[i]); } if (!isValidHop) { return(false); } } return(true); }
/// <summary> /// Performs a hop which is considered invalid due to the dijkstra algorithm. /// Starts the error recovery which lasts until the player returns to the last valid hop. /// </summary> /// <param name="path">The path along which the player performs the hop.</param> public void PerformWrongHop(PathScript path) { if (isLogEnabled) { Debug.Log("Started error recovery mode."); } // Start the error recovery. errorRecovery = true; // Store the last valid router to that the player needs to return. // Last valid position is the router on which the player is located before the wrong hop. lastValidRouter = routerScriptCurrentPlayerPosition; // Update the current player position. UpdateCurrentPlayerPosition(path); }
/// <summary> /// Indicates whether the specified router is already marked as handled in the current dijkstra run. /// </summary> /// <param name="router">The RouterScript instance of the router that should be checked.</param> /// <returns>Returns true, if the router is already handled, false otherwise.</returns> public bool IsRouterAlreadyHandled(RouterScript router) { if (router != null && priorityQueue != null) { if (priorityQueue.IsContained(router)) { // Not yet handled as it is still in the priority queue. return(false); } else { return(true); } } return(false); }
/// <summary> /// Gets the path between the provided nodes. /// </summary> /// <returns>The path between the nodes.</returns> /// <param name="from">From.</param> /// <param name="to">To.</param> public PathScript GetPathBetweenNodes(RouterScript from, RouterScript to) { PathScript path = graphRepresentation2[ from.GetRouterIndex(), to.GetRouterIndex() ]; if (path == null) { path = graphRepresentation2[ to.GetRouterIndex(), from.GetRouterIndex() ]; } return(path); }
/// <summary> /// A helper method that updates the current player position depending on the specified /// path. The method takes into account whether bidirectional movements are allowed. /// </summary> /// <param name="path">The path on which the player performs the hop.</param> private void UpdateCurrentPlayerPosition(PathScript path) { RouterScript from = path.from.GetComponent <RouterScript>(); RouterScript to = path.to.GetComponent <RouterScript>(); // Check to which router the player moves. if (from == routerScriptCurrentPlayerPosition) { // Player performs hop to router "to". routerScriptCurrentPlayerPosition = to; } else if (bidirectional && to == routerScriptCurrentPlayerPosition) { // Player performs hop to router "from". routerScriptCurrentPlayerPosition = from; } }
/// <summary> /// Starts the Dijkstra algorithm. Performs the required initialization and fills the priority queue. /// Sets the player's position to the starting router. /// </summary> /// <param name="startingRouter">The starting router of the algorithm.</param> public void StartDijkstraAlgorithm(RouterScript startingRouter) { if (isLogEnabled) { Debug.Log("StartDijkstraAlgorithm() called."); } // Create the priority queue. priorityQueue = new PriorityQueue <RouterScript>(); // Initialize Dijkstra algorithm by storing nodes in priority queue. for (int i = 0; i < listOfRouterScripts.Length; i++) { RouterScript router = listOfRouterScripts[i]; if (router == startingRouter) { if (isLogEnabled) { Debug.Log("router instance id: " + router.GetInstanceID() + " and starting router instance id " + startingRouter.GetInstanceID()); } // Set the current shortest path of the starting router to 0. router.SetPriority(0); predecessorRouter[router] = router; // The predecessor of the starting router is the router itself. // Set this router as the current player position and as the current working router. routerScriptCurrentPlayerPosition = router; currentWorkingRouter = router; } else { // For all other routers, set the current distance to the max int value. Debug.Log("Router=" + router + " i=" + i + " list of routers size=" + listOfRouterScripts.Length); router.SetPriority(int.MaxValue); // Add the router to the priority queue. priorityQueue.Enqueue(router); } } if (isLogEnabled) { Debug.Log("Finished StartDijkstraAlgorithm()."); } }
/// <summary> /// Performs a hop along the path to the target router. The target router will be the next /// router that is handled by the dijkstra algorithm. The target router is removed from the /// priority queue which marks it as processed. For this router no shorter path can be found. /// </summary> /// <param name="path"> The path on which the hop is performed. The path determines the previous router /// and the target router.</param> public void PerformHop(PathScript path) { // Update the current player position. UpdateCurrentPlayerPosition(path); // Update the current working router. currentWorkingRouter = routerScriptCurrentPlayerPosition; // The chosen router is now getting processed by the dijkstra algorithm and cannot get a shorter path afterwards. // Take it out of the priority queue. if (priorityQueue.IsContained(routerScriptCurrentPlayerPosition)) { if (priorityQueue.Peek() == routerScriptCurrentPlayerPosition) { // It is the first element, so pull it from the queue. priorityQueue.PullHighest(); } else { // Another router with the same distance is currently in front of the target router. // Remove those routers before the target router, but put them back into the queue afterwards. List <RouterScript> routerCache = new List <RouterScript>(); while (priorityQueue.Count() > 0) { if (priorityQueue.Peek() != routerScriptCurrentPlayerPosition) { routerCache.Add(priorityQueue.PullHighest()); } else { // Found the target router. Remove it from the queue and abort the loop. priorityQueue.PullHighest(); break; } } // Put cached routers back into priority queue. for (int i = 0; i < routerCache.Count; i++) { priorityQueue.Enqueue(routerCache[i]); } } } }
/// <summary> /// Create entries for the routers that have been handeld already by the dijkstra algorithm /// in the current run. The entries are concatenated to a string. /// </summary> /// <param name="routers">The list of all routers that are involved in the current dijkstra run.</param> /// <returns>A string containing the routing table entries of the already handled routers.</returns> private string createHandledRouterRoutingTableEntries(RouterScript[] routers) { System.Text.StringBuilder s = new System.Text.StringBuilder(); for (int i = 0; i < routers.Length; i++) { // Check whether the router is already handled. if (dijkstraManager.IsRouterAlreadyHandled(routers[i])) { string currentRouter = string.Empty; // Request predecessor. RouterScript predecessorRouter = dijkstraManager.GetPredecessorRouterOnShortestPath(routers[i]); if (predecessorRouter != null) { // Add entry to the routing table. currentRouter = string.Format("Tisch {0}: ({1},{2})" + System.Environment.NewLine, routers[i].GetRouterName(), routers[i].GetPriority(), predecessorRouter.GetRouterName()); } // Is the router the current working router? if (routers[i] == dijkstraManager.GetCurrentWorkingRouter().GetComponent <RouterScript>()) { currentRouter = colorizeString(currentRouter, currentWorkingRouterColor); } s.Append(currentRouter); } } string output = s.ToString(); output = colorizeString(output, handledRouterColor); if (isDebugging) { Debug.Log(" In handled routers: " + output); } return(output); }
/// <summary> /// Determines whether this instance is valid greedy hop for the specified hopTarget. /// </summary> /// <returns><c>true</c> if this instance is valid greedy hop for the specified hopTarget; otherwise, <c>false</c>.</returns> /// <param name="hopTarget">Hop target.</param> private bool IsValidGreedyHop(RouterScript hopTarget) { foreach (RouterScript router in neighboursOfActiveRouter) { if (hopTarget.gameObject == router.gameObject) { continue; } if (currentPath.Contains(router)) { continue; } if (router.GetGreedyHeuristicValue() < hopTarget.GetGreedyHeuristicValue()) { return(false); } } return(true); }
// Use this for initialization. void Start() { if (isLogEnabled) { Debug.Log("Start initializing graph datastructure."); } // Fill graph representation array with information taken from the nodes and edges for (int i = 0; i < listOfPathScripts.Length; i++) { RouterScript from = listOfPathScripts[i].from.GetComponent <RouterScript>(); RouterScript to = listOfPathScripts[i].to.GetComponent <RouterScript>(); graphRepresentation2[from.GetRouterIndex(), to.GetRouterIndex()] = listOfPathScripts[i]; } if (isLogEnabled) { Debug.Log("Finished initializing graph datastructure."); } }
/// <summary> /// Create entries for the routers that have not been handeld by the dijkstra algorithm so far /// in the current run. The entries are concatenated to a string. /// </summary> /// <param name="routers">The list of all routers that are involved in the current dijkstra run.</param> /// <returns>A string containing the routing table entries of the not yet handled routers.</returns> private string createUnhandledRouterRoutingTableEntries(RouterScript[] routers) { System.Text.StringBuilder s = new System.Text.StringBuilder(); for (int i = 0; i < routers.Length; i++) { // Check whether the router is already handled. if (!dijkstraManager.IsRouterAlreadyHandled(routers[i])) { // Request predecessor. RouterScript predecessorRouter = dijkstraManager.GetPredecessorRouterOnShortestPath(routers[i]); if (predecessorRouter != null) { // Add entry to the routing table. s.Append(string.Format("Tisch {0}: ({1},{2})" + System.Environment.NewLine, routers[i].GetRouterName(), routers[i].GetPriority(), predecessorRouter.GetRouterName())); } else { // Add entry to the routing table without predecessor. s.Append(string.Format("Tisch {0}: (inf,-)" + System.Environment.NewLine, routers[i].GetRouterName())); } } } string output = s.ToString(); output = colorizeString(output, unhandledRouterColor); if (isDebugging) { Debug.Log(" In unhandled routers: " + output.Substring(1, output.Length - 1)); } return(output); }
/// <summary> /// Recreates the graph representation. Takes blocked routers into account. /// </summary> public void recreateGraphRepresentation() { graphRepresentation2 = new PathScript[listOfNodes.Length, listOfNodes.Length]; // Nodex x Nodes // Fill graph representation array with information taken from the nodes and edges. // Take blocked routers into the account. for (int i = 0; i < listOfPathScripts.Length; i++) { RouterScript from = listOfPathScripts[i].from.GetComponent <RouterScript>(); RouterScript to = listOfPathScripts[i].to.GetComponent <RouterScript>(); if (!from.Disabled && !to.Disabled) { // Include only active paths. graphRepresentation2[from.GetRouterIndex(), to.GetRouterIndex()] = listOfPathScripts[i]; } else { listOfPathScripts[i].Disabled = true; } } }
/// <summary> /// Searches all routers in the priority queue which currently have the shortest distance and /// are a suitable candidate for the next working router in the Dijkstra algorithm. /// </summary> /// <returns>A string which contains the names of the candidate routers.</returns> public string GetNextRouterSuggestionAsString() { if (priorityQueue.Count() == 0) { return(string.Empty); } System.Text.StringBuilder sb = new System.Text.StringBuilder(); RouterScript headOfQueue = priorityQueue.PullHighest(); sb.Append(headOfQueue.GetRouterName() + ", "); // Check if the next element in the priority queue also has the same distance. if (headOfQueue.GetCurrentDistance() == priorityQueue.Peek().GetCurrentDistance()) { // Retrieve all routers that have the same current distance. List <RouterScript> routerCache = new List <RouterScript>(); while (headOfQueue.GetCurrentDistance() == priorityQueue.Peek().GetCurrentDistance()) { sb.Append(priorityQueue.Peek().GetRouterName() + ", "); routerCache.Add(priorityQueue.PullHighest()); } // Put the routers back in. foreach (RouterScript router in routerCache) { priorityQueue.Enqueue(router); } } // Remove the last comma. sb.Remove(sb.Length - 2, 2); // Put head of priority queue back. priorityQueue.Enqueue(headOfQueue); return(sb.ToString()); }
/// <summary> /// Removes the router from the priority queue. /// </summary> /// <param name="routerScript">Router script.</param> protected void RemoveRouterFromPrioQueue(RouterScript routerScript) { if (prioQueue.IsContained(routerScript)) { if (prioQueue.Peek() == routerScript) { // It is the first element, so pull it from the queue. prioQueue.PullHighest(); } else { // Another router with the same distance is currently in front of the target router. // Remove those routers before the target router, but put them back into the queue afterwards. List <RouterScript> routerCache = new List <RouterScript>(); while (prioQueue.Count() > 0) { if (prioQueue.Peek() != routerScript) { routerCache.Add(prioQueue.PullHighest()); } else { // Found the target router. Remove it from the queue and abort the loop. prioQueue.PullHighest(); break; } } // Put cached routers back into priority queue. for (int i = 0; i < routerCache.Count; i++) { prioQueue.Enqueue(routerCache[i]); } } } }
void GameManagerInterface.SetCurrentPlayerPosition(RouterScript playerPos) { activeRouter = playerPos.gameObject; }
protected void Initialize() { if (isLogEnabled) { Debug.Log("Awake the GameManager."); } // Extract scripts from nodes and edges listOfNodes = GameObject.FindGameObjectsWithTag("Node"); listOfEdges = GameObject.FindGameObjectsWithTag("Path"); // Initialize graph datastructure. //graphRepresentation = new int[listOfNodes.Length,listOfNodes.Length]; // Nodes x Nodes graphRepresentation2 = new PathScript[listOfNodes.Length, listOfNodes.Length]; // Nodex x Nodes // Keep track of the predecessor router for each router on the shortest path. //predecessorRouter = new Dictionary<RouterScript, RouterScript> (); if (isLogEnabled) { Debug.Log("Start extracting scripts in GameManager."); } // listOfRouterScripts = new RouterScript[listOfNodes.Length]; // listOfPathScripts = new PathScript[listOfEdges.Length]; // Extract scripts from nodes and edges listOfNodes = GameObject.FindGameObjectsWithTag("Node"); listOfEdges = GameObject.FindGameObjectsWithTag("Path"); // Initialize graph datastructure. //graphRepresentation = new int[listOfNodes.Length,listOfNodes.Length]; // Nodes x Nodes graphRepresentation2 = new PathScript[listOfNodes.Length, listOfNodes.Length]; // Nodex x Nodes listOfRouterScripts = new RouterScript[listOfNodes.Length]; listOfPathScripts = new PathScript[listOfEdges.Length]; for (int i = 0; i < listOfNodes.Length; i++) { listOfRouterScripts[i] = listOfNodes[i].GetComponent <RouterScript>(); } for (int i = 0; i < listOfEdges.Length; i++) { listOfPathScripts[i] = listOfEdges[i].GetComponent <PathScript>(); } // Check router names. checkIntegrityOfRouterNames(); if (isLogEnabled) { Debug.Log("Finished extracting scripts in GameManager."); Debug.Log("Finished Awake method of the GameManager."); } if (isLogEnabled) { Debug.Log("Start initializing graph datastructure."); } // Fill graph representation array with information taken from the nodes and edges for (int i = 0; i < listOfPathScripts.Length; i++) { RouterScript from = listOfPathScripts[i].from.GetComponent <RouterScript>(); RouterScript to = listOfPathScripts[i].to.GetComponent <RouterScript>(); graphRepresentation2[from.GetRouterIndex(), to.GetRouterIndex()] = listOfPathScripts[i]; } if (isLogEnabled) { Debug.Log("Finished initializing graph datastructure."); } }
void GameManagerInterface.PerformHop(PathScript path) { GameObject hopTarget = null; //to=active --> goto from if (path.to.gameObject == activeRouter.gameObject) { hopTarget = path.from.gameObject; } else //from=active --> goto to if (path.from.gameObject == activeRouter.gameObject) { hopTarget = path.to.gameObject; } // Update the active router and the neighbours of the active router. activeRouter = hopTarget; currentPath.Add(hopTarget.GetComponent <RouterScript>()); neighboursOfActiveRouter = ExpandNode(activeRouter.GetComponent <RouterScript>()); // Remove the hop target from the priortiy queue. RemoveRouterFromPrioQueue(hopTarget.GetComponent <RouterScript>()); for (int i = 0; i < neighboursOfActiveRouter.Count; i++) { RouterScript neighborRouter = neighboursOfActiveRouter[i].GetComponent <RouterScript>(); // Path costs to the target router are the path cost to the currently active router + the path costs of this path. int pathCost = activeRouter.GetComponent <RouterScript>().GetPriority() + graphRepresentation2[ activeRouter.GetComponent <RouterScript>().GetRouterIndex(), neighborRouter.GetRouterIndex() ].GetPathCosts(); if (currentPath.Contains(neighborRouter)) { continue; } if (prioQueue.IsContained(neighborRouter)) { if (pathCost < neighborRouter.GetPriority()) { // Update the path costs of the router. prioQueue.DecreasePriority(neighborRouter, pathCost); if (isLogEnabled) { Debug.Log(string.Format("Updated path costs of router {0}, new path costs are {1}.", neighborRouter.GetRouterName(), neighborRouter.GetPriority())); } } } else { neighborRouter.SetPriority(pathCost); if (isLogEnabled) { Debug.Log(string.Format("Inserted neighbor into prio queue. Neighbor is {0}, path costs are {1}.", neighborRouter.GetRouterName(), pathCost)); } // Insert neighbor into priority queue. prioQueue.Enqueue(neighborRouter); } } if (isLogEnabled) { Debug.Log("Prio Queue after hop: " + prioQueue.ToString()); } }
/// <summary> /// Calculates the straight line heuristic. /// </summary> /// <returns>The straight line heuristic.</returns> /// <param name="source">Source.</param> /// <param name="destination">Destination.</param> private int CalcStraightLineHeuristic(RouterScript source, RouterScript destination) { return((int)Vector3.Distance(source.transform.position, destination.transform.position)); }
public void SetCurrentPlayerPosition(RouterScript playerPos) { activeRouter = playerPos.gameObject; }
/// <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); }