예제 #1
0
    /// <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());
    }
예제 #2
0
    /// <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);
    }
예제 #3
0
    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());
        }
    }
예제 #4
0
    /// <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);
    }
예제 #5
0
    /// <summary>
    /// Finds the optimal between the source and the destination router using the metric hop count.
    /// </summary>
    /// <returns>The optimal path as a list.</returns>
    /// <param name="source">Source.</param>
    /// <param name="destination">Destination.</param>
    protected List <GameObject> findOptimalHopCountPath(GameObject source, GameObject destination)
    {
        if (isLogEnabled)
        {
            Debug.Log("Finding best path!");
        }

        prioQueue = new PriorityQueue <RouterScript>();
        RouterScript current = source.GetComponent <RouterScript>();

        current.SetPriority(0);

        Dictionary <RouterScript, RouterScript> parentRelationship = new Dictionary <RouterScript, RouterScript>();

        List <RouterScript> closed   = new List <RouterScript>();
        List <RouterScript> children = new List <RouterScript>();

        if (isLogEnabled)
        {
            Debug.Log("Starting findOptimalHopCountPath from " + current.name + " to " + destination.name);
        }

        while (current.gameObject != destination)
        {
            if (!closed.Contains(current)) // Don't need to check this node again.
            {
                children = ExpandNode(current);
                foreach (RouterScript tmp in children)
                {
                    // Check whether the router has already been handled. If this is the case,
                    // we don't need to add them to the priority queue again.
                    if (closed.Contains(tmp))
                    {
                        continue;
                    }

                    // Increase the priority. One more hop.
                    tmp.SetPriority(current.GetPriority() + 1);

                    // Store parent (predecessor router of current router) for child.
                    // Only do this if no router has already been defined as the predecessor router.
                    if (parentRelationship.ContainsKey(tmp))
                    {
                        // do nothing.
                        if (isLogEnabled)
                        {
                            Debug.Log("There is already a predecessor for the router " + tmp.name + "defined.");
                        }
                    }
                    else
                    {
                        parentRelationship.Add(tmp, current);

                        if (isLogEnabled)
                        {
                            Debug.Log("Setting predecessor for router: " + tmp.name + ", the predecessor is: " + current.name);
                        }
                    }

                    if (isLogEnabled)
                    {
                        Debug.Log("Adding to prioQueue: router: " + tmp.name + " | with priority: " + tmp.GetPriority());
                    }

                    prioQueue.Enqueue(tmp);
                }

                // Mark router as handled.
                closed.Add(current);
            }

            if (isLogEnabled)
            {
                Debug.Log("Handling of router: " + current.name + " is done. Taking the next one.");
            }

            // Continue with node that has the lowest priority at that time.
            current = prioQueue.PullHighest();
        }


        // Calculate optimal path.
        List <GameObject> optimalPath = new List <GameObject>();

        optimalPath.Insert(0, current.gameObject);

        while (parentRelationship[current].gameObject != source)
        {
            current = parentRelationship[current];
            optimalPath.Insert(0, current.gameObject);
        }
        optimalPath.Insert(0, source);

        if (isLogEnabled)
        {
            string logString = "Optimal Path: ";
            foreach (GameObject go in optimalPath)
            {
                logString += go.GetComponent <RouterScript>().GetRouterName() + " -> ";
            }
            Debug.Log(logString.Substring(0, logString.Length - 3));
        }

        return(optimalPath);
    }