/**
  * Sets all variables of the HelperNode.
  */
 public void Initialize(int id, int state, int distance, HelperNodeController predecessor)
 {
     Id          = id;
     State       = state;
     Distance    = distance;
     Predecessor = predecessor;
 }
 // Checks whether to add the node to the queue or not
 private bool DecideToAddNewNode(HelperNodeController nodeController)
 {
     if (nodeController.Distance < allDistances[nodeController.Id, nodeController.State])
     {
         // Update smallest known distance
         allDistances[nodeController.Id, nodeController.State] = nodeController.Distance;
         return(true);
     }
     return(false);
 }
    // Calculates the path between start and target
    private void CalculatePathBetweenStartAndEndNode(HelperNodeController endHelperNode)
    {
        ShortestPath = new List <NodeController>();
        List <NodeController> pathHelperList    = new List <NodeController>();
        HelperNodeController  currentHelperNode = endHelperNode;

        while (currentHelperNode != null)
        {
            pathHelperList.Add(MainScript.AllNodes[currentHelperNode.Id]);
            currentHelperNode = currentHelperNode.Predecessor;
        }

        for (int i = pathHelperList.Count - 1; i >= 0; i--)
        {
            ShortestPath.Add(pathHelperList[i]);
        }
    }
    // Performs the modified dijkstra algorithm and calls the method to fill the shortestPathBetweenStartAndEndNode list.
    public void CalculateModifiedDijkstraAlgorithm()
    {
        HelperNodeController endHelperNode = null;

        // Add the start node with state = 0 and distance = 0 to the SimplePriorityQueue
        GameObject           helpObject = Instantiate(helperNodePrefab);
        HelperNodeController help       = helpObject.GetComponent <HelperNodeController>();

        help.Initialize(startNode.Id, initialState, 0, null);
        prioQueue.Enqueue(help, 0);
        garbage.Add(helpObject);
        allDistances[startNode.Id, initialState] = 0;

        while (prioQueue.Count != 0)
        {
            // Retrieve the node with the smallest distance
            HelperNodeController currentHelperNode = prioQueue.Dequeue();

            // Skip the node if it was treated yet
            if (currentHelperNode.Distance != allDistances[currentHelperNode.Id, currentHelperNode.State])
            {
                continue;
            }

            NodeController currentNode = MainScript.AllNodes[currentHelperNode.Id];

            // End node test
            if (currentHelperNode.Id == endNode.Id)
            {
                endHelperNode = currentHelperNode;
                break;
            }

            // Perform the state change of the current node
            int newState = currentNode.ChangeState(currentHelperNode.State);

            // Handle all outgoing edges of the current node
            foreach (EdgeController edge in currentNode.OutgoingEdges)
            {
                // Calculate the new distance of the end node of the edge
                int newDistance = currentHelperNode.Distance + edge.GetCostForState(newState);

                // Create the new node and add it if allowed
                GameObject           newNodeObject = Instantiate(helperNodePrefab);
                HelperNodeController newNode       = newNodeObject.GetComponent <HelperNodeController>();
                garbage.Add(newNodeObject);

                // Check which node is the target node
                if (edge.Node1.Id != currentNode.Id)
                {
                    newNode.Initialize(edge.Node1.Id, newState, newDistance, currentHelperNode);
                }
                else
                {
                    newNode.Initialize(edge.Node0.Id, newState, newDistance, currentHelperNode);
                }

                if (DecideToAddNewNode(newNode))
                {
                    prioQueue.Enqueue(newNode, newDistance);
                }
            }
        }

        // Calculate the distance and path of the result
        if (endHelperNode != null)
        {
            ShortestDistance = endHelperNode.Distance;
            CalculatePathBetweenStartAndEndNode(endHelperNode);
        }

        // Destroy garbage
        foreach (GameObject obj in garbage)
        {
            Destroy(obj);
        }
    }