private void FinishedReset(DijkstraNode current, DijkstraNode prev)
        {
            if (hitTarget(current))
            {
                foreach (var tentative in _tentative)
                {
                    tentative.Reset();
                }
                _tentative.Clear();

                if (_cont && _visualise && prev != null)
                {
                    if (_text)
                    {
                        Say("A route to the target was found. The algorithm is finished");
                    }
                    current.Reset();
                }
            }
            else
            {
                if (_cont && _visualise && prev != null)
                {
                    if (_text)
                    {
                        Say("There are no more nodes in the tentative list. The algorithm is finished");
                    }
                    prev.Reset();
                }
            }
        }
        /// <summary>
        /// Check a neighbour of the current node to see if it needs to be added to the tentative list
        /// or the shortest route to it needs to be updated.
        /// </summary>
        /// <param name="neighbour">The neighbour to check.</param>
        /// <param name="current">The current node.</param>
        /// <param name="dist">The distance from the root to the current node.</param>
        /// <param name="link">The link between current and neighbour.</param>
        private void checkNeighbour(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link)
        {
            float newDistance = dist + link.Weight;

            try {
                //If the new route from root to neighbour is shorter than the old route or there was no old route
                //set the current node as the first step towards the root from neighbour
                if (_cont && !_tentative.Contains(neighbour))
                {
                    _tentative.AddFirst(neighbour);
                    neighbour.SetDistanceFromRoot(ID, newDistance, current, link);
                }
                else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID))
                {
                    neighbour.SetDistanceFromRoot(ID, newDistance, current, link);
                }
            } catch (KeyNotFoundException e) {
                //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop
                _cont = false;
                if (_visualise)
                {
                    VisualisedNode = null;
                }
                Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " +
                             current.Name + " (root = " + Name + ")");
            }

            //Incase another thread has modified the distance
            if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID))
            {
                neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link);
            }
        }
        /// <summary>
        /// Once the algorithm has finished use the information it has stored to update the routing table.
        /// </summary>
        private void UpdateRoutingTable()
        {
            IKeyTable <IMLink> oldTable = ForwardingTable;

            foreach (DijkstraNode target in _confirmed)
            {
                if (target.ID != ID)
                {
                    //Work backwards along the route, starting at the target, until the first hop is found
                    DijkstraNode prev = target;
                    while (prev != null && !Equals(prev.GetPrev(ID)))
                    {
                        prev = prev.GetPrev(ID);
                    }

                    if (prev != null && Links.ContainsKey(prev.ID))
                    {
                        IMLink l = Links[prev.ID];
                        SetRoute(Algorithm, target.ID, l, target.GetDistanceFromRoot(ID));
                        oldTable.Remove(target.ID);
                    }
                }
            }
            //Trigger events for any nodes that can no longer be routed to
            foreach (IMNodeInternal n in KnownNodes)
            {
                if (oldTable.ContainsKey(n.ID))
                {
                    RemoveRoute(Algorithm, n.ID);
                }
            }
        }
        //public override event ForwardingTableChangeDelegate OnRouteChange;

        public override void Stop()
        {
            if (_visualise && Equals(VisualisedNode))
            {
                ResetAlgorithm();
                _visualise     = false;
                _text          = false;
                VisualisedNode = null;
                RunAlgorithm(Name + " visualisation stopped. Re-running algorithm silently.", null, false);
            }
        }
 /// <summary>
 /// Check whether the target to be routed to has been found.
 /// </summary>
 /// <param name="current">The current node.</param>
 /// <returns>True if the current node is the target node.</returns>
 private bool hitTarget(DijkstraNode current)
 {
     if (!_cont || _target == null)
     {
         return(false);
     }
     if (_cont && _text && _visualise && current.ID == _target.ID)
     {
         Say("Found the shortest route to target " + _target.Name);
     }
     return(current.ID == _target.ID);
 }
 /// <summary>
 /// The main loop which is the body of the algorithm.
 /// Loops through every neighbour of the current node checking to see if they:
 /// A. Have been visited before
 /// B. Have been visited before but are now a shorter route
 /// </summary>
 /// <param name="current">The node currently being checked.</param>
 /// <param name="prev">The previous node that was checked.</param>
 /// <returns>The last node to be checked.</returns>
 private void MainLoop(DijkstraNode current, DijkstraNode prev)
 {
     while (_cont && current != null && !hitTarget(current))
     {
         //If necessary display text and wait
         if (_cont && _text && _visualise)
         {
             current.Say("4. Iterating through neighbours excluding neighbours in Confirmed");
             Pause();
         }
         //Get the current distance to the target
         float dist = current.GetDistanceFromRoot(ID);
         foreach (var n in current.Neighbours)
         {
             IMLink link = current.Links[n.ID];
             if (_visualise)
             {
                 _links.AddFirst(link);
             }
             var neighbour = this.GetAlgNode <DijkstraNode>(n.ID);
             if (_cont && !_confirmed.Contains(neighbour))
             {
                 if (_visualise && _text)
                 {
                     VisualiseCheckNeighbourText(neighbour, current, dist, link);
                 }
                 else if (_visualise)
                 {
                     VisualiseCheckNeighbour(neighbour, current, dist, link);
                 }
                 checkNeighbour(neighbour, current, dist, link);
             }
             if (!_cont)
             {
                 break;
             }
         }
         //Store the old previous node
         prev = current;
         if (_cont && _text && _visualise)
         {
             Say("Finished iterating through current's (" + current.Name +
                 "'s) neighbours, getting next current from tentative list");
             Pause();
         }
         //Get the next node to be checked (the one which has the shortest path to it)
         current = getNext(current);
     }
     FinishedReset(current, prev);
 }
        /// <summary>
        /// Visualise the process of choosing the next node. Will output text about what is going on if necessary.
        /// </summary>
        /// <param name="next">The next node to be current.</param>
        /// <param name="prev">The node that was previously current.</param>
        private void VisualiseChooseNext(DijkstraNode next, DijkstraNode prev)
        {
            if (_cont && !next.Equals(this))
            {
                if (_cont && _text)
                {
                    Say("8. There are nodes in the tentative list. Finding the node in tentative with the smallest cost");
                    Pause();
                }
                Pause(3f);
                if (_cont && _text)
                {
                    Say("9. new current = " + next.Name + " with cost " + next.GetDistanceFromRoot(ID));
                    Pause();
                    Say("10. Adding link between ct (" + prev.Name + ") and new current (" + next.Name + ") to the shortest path");
                    Pause();
                }
            }

            prev.Reset();

            IMLink confirmedLink = next.GetWIPRoute(ID);

            if (_cont && confirmedLink != null)
            {
                Pause(6f);
                confirmedLink.Colour = Color.Red;
            }

            if (_cont && _text)
            {
                Say((next.Equals(this) ? "2a" : "11a") + ". Adding " +
                    (next.Equals(this) ? "root" : "new current") + " (" + next.Name + ") to Confirmed");
                Pause();
                Say((next.Equals(this) ? "2b" : "11b") + ". Setting current to " +
                    (next.Equals(this) ? "root" : "new current") + " (" + next.Name + ")");
            }

            next.Reset();
            next.Selected = currentGlow;
            next.Colour   = Color.White;

            if (_cont && _text && !next.Equals(this))
            {
                Pause();
                Say("11c. Going to step 4");
                Pause();
            }
        }
        /// <summary>
        /// Get the next node to be checked. Next node is the node in the tentative list which is closest to the root.
        /// </summary>
        /// <param name="prev">The node that was previously checked.</param>
        /// <returns>The new current node.</returns>
        private DijkstraNode getNext(DijkstraNode prev)
        {
            if (_cont && _tentative.Count > 0)
            {
                DijkstraNode next = _tentative.OrderBy(node => node.GetDistanceFromRoot(ID)).First();
                if (!_cont)
                {
                    return(null);
                }
                _tentative.Remove(next);
                _confirmed.AddLast(next);

                if (_cont && _visualise)
                {
                    VisualiseChooseNext(next, prev);
                }
                return(next);
            }
            return(null);
        }
        public override void VisualiseAlgorithm(UUID to, Parameters parameters)
        {
            if (Equals(VisualisedNode))
            {
                ResetAlgorithm();
                _visualise     = false;
                VisualisedNode = null;
                return;
            }
            else if (VisualisedNode != null)
            {
                VisualisedNode.Stop();
            }

            IMNodeInternal target = KnownNodes.ContainsKey(to) ? KnownNodes[to] : null;

            _text          = Dijkstra.AlwaysPrint || (Dijkstra.EverPrint && parameters != null && parameters.Get <bool>("Text"));
            VisualisedNode = this;

            RunAlgorithm("Visualise Dijkstra's Algorithm", target, true);
        }
        internal void SetDistanceFromRoot(UUID root, float value, DijkstraNode prevNode, IMLink link)
        {
            //if (prevNode != null/* && !Links.ContainsKey(prevNode.ID)*/)
            //    return;

            lock (_distances) {
                if (_distances.ContainsKey(root))
                {
                    _distances[root] = value;
                    _prev[root]      = prevNode;
                }
                else
                {
                    _distances.Add(root, value);
                    _prev.Add(root, prevNode);
                }
            }
            if (prevNode != null)
            {
                SetWIPRoute(root, link);
            }
        }
        private void RunAlgorithm(IMNodeInternal to)
        {
            lock (_runLock) {
                Init(to);

                if (_visualise)
                {
                    Logger.Debug("Dijkstra visualising routing from " + Name);
                }

                if (_cont && _text && _visualise)
                {
                    Say("Starting Algorithm");
                    Say("1. Initialising Confirmed and Tentative lists");
                }

                DijkstraNode current = getNext(this);
                DijkstraNode prev    = current;

                if (_cont && _text && _visualise)
                {
                    Pause();
                    Say("3. Cost for root (" + Node.Name + ") = 0");
                    Pause();
                }

                MainLoop(current, prev);

                //If the algorithm didn't finish prematurely
                if (_cont)
                {
                    UpdateRoutingTable();
                }
                algorithmFinished();
            }
        }
        /// <summary>
        /// Visualises the process of checking a neighbour node.
        /// </summary>
        /// <param name="neighbour">The neighbour to check.</param>
        /// <param name="current">The current node.</param>
        /// <param name="dist">The distance from the root to the current node.</param>
        /// <param name="link">The link between current and neighbour.</param>
        private void VisualiseCheckNeighbour(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link)
        {
            if (!_visualise)
            {
                return;
            }

            if (_cont)
            {
                Pause(4f);
                link.Colour = Color.Blue;
                Pause(6);
            }

            try {
                if (_cont && !_tentative.Contains(neighbour))
                {
                    neighbour.Selected = tentativeGlow;
                    Pause(6);
                }
            } catch (KeyNotFoundException e) {
                //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop
                _cont = false;
                if (_visualise)
                {
                    VisualisedNode = null;
                }
                Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " +
                             current.Name + " (root = " + Name + ")");
            }

            if (_cont)
            {
                link.Colour = Color.White;
            }
        }
 /// <summary>
 /// Check whether the target to be routed to has been found.
 /// </summary>
 /// <param name="current">The current node.</param>
 /// <returns>True if the current node is the target node.</returns>
 private bool hitTarget(DijkstraNode current)
 {
     if (!_cont || _target == null)
         return false;
     if (_cont && _text && _visualise && current.ID == _target.ID)
         Say("Found the shortest route to target " + _target.Name);
     return current.ID == _target.ID;
 }
        /// <summary>
        /// Get the next node to be checked. Next node is the node in the tentative list which is closest to the root.
        /// </summary>
        /// <param name="prev">The node that was previously checked.</param>
        /// <returns>The new current node.</returns>
        private DijkstraNode getNext(DijkstraNode prev)
        {
            if (_cont && _tentative.Count > 0) {
                DijkstraNode next = _tentative.OrderBy(node => node.GetDistanceFromRoot(ID)).First();
                if (!_cont)
                    return null;
                _tentative.Remove(next);
                _confirmed.AddLast(next);

                if (_cont && _visualise)
                    VisualiseChooseNext(next, prev);
                return next;
            }
            return null;
        }
        private void FinishedReset(DijkstraNode current, DijkstraNode prev)
        {
            if (hitTarget(current)) {
                foreach (var tentative in _tentative)
                    tentative.Reset();
                _tentative.Clear();

                if (_cont && _visualise && prev != null) {
                    if (_text)
                        Say("A route to the target was found. The algorithm is finished");
                    current.Reset();
                }
            } else {
                if (_cont && _visualise && prev != null) {
                    if (_text)
                        Say("There are no more nodes in the tentative list. The algorithm is finished");
                    prev.Reset();
                }
            }
        }
        /// <summary>
        /// Check a neighbour of the current node to see if it needs to be added to the tentative list
        /// or the shortest route to it needs to be updated.
        /// </summary>
        /// <param name="neighbour">The neighbour to check.</param>
        /// <param name="current">The current node.</param>
        /// <param name="dist">The distance from the root to the current node.</param>
        /// <param name="link">The link between current and neighbour.</param>
        private void checkNeighbour(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link)
        {
            float newDistance = dist + link.Weight;

            try {
                //If the new route from root to neighbour is shorter than the old route or there was no old route
                //set the current node as the first step towards the root from neighbour
                if (_cont && !_tentative.Contains(neighbour)) {
                    _tentative.AddFirst(neighbour);
                    neighbour.SetDistanceFromRoot(ID, newDistance, current, link);
                } else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID))
                    neighbour.SetDistanceFromRoot(ID, newDistance, current, link);
            } catch (KeyNotFoundException e) {
                //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop
                _cont = false;
                if (_visualise)
                    VisualisedNode = null;
                Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " +
                         current.Name + " (root = " + Name + ")");
            }

            //Incase another thread has modified the distance
            if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID))
                neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link);
        }
        internal void SetDistanceFromRoot(UUID root, float value, DijkstraNode prevNode, IMLink link)
        {
            //if (prevNode != null/* && !Links.ContainsKey(prevNode.ID)*/)
            //    return;

            lock (_distances) {
                if (_distances.ContainsKey(root)) {
                    _distances[root] = value;
                    _prev[root] = prevNode;
                } else {
                    _distances.Add(root, value);
                    _prev.Add(root, prevNode);
                }
            }
            if (prevNode != null)
                SetWIPRoute(root, link);
        }
        /// <summary>
        /// Visualises the process of checking a neighbour node and prints out text explaining what is happening.
        /// </summary>
        /// <param name="neighbour">The neighbour to check.</param>
        /// <param name="current">The current node.</param>
        /// <param name="dist">The distance from the root to the current node.</param>
        /// <param name="link">The link between current and neighbour.</param>
        private void VisualiseCheckNeighbourText(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link)
        {
            if (!_visualise && !_text)
                return;

            float newDistance = dist + link.Weight;

            if (_cont) {
                //if (_cont && _text)
                //    current.Say("Examining neighbour " + neighbour.Name);
                Pause(4f);
                link.Colour = Color.Blue;
                if (_cont && _text) {
                    Pause();
                    current.Say("5. Test cost to " + neighbour.Name + " = " + dist + " + " + link.Weight + " = " +
                                  newDistance);
                    Pause();
                }
                Pause(4f);
            }

            try {
                if (_cont && !_tentative.Contains(neighbour)) {
                    if (_cont && _text)
                        current.Say(neighbour.Name + " is not in tentative list");

                    _tentative.AddFirst(neighbour);
                    neighbour.SetDistanceFromRoot(ID, newDistance, current, link);

                    if (_cont) {
                        Pause(4f);
                        neighbour.Selected = tentativeGlow;
                        if (_cont && _text) {
                            current.Say("6a. Adding " + neighbour.Name + " to the tentative list");
                            Pause();
                            current.Say("6b. " + neighbour.Name + ".cost = test cost (" + newDistance + ")");
                        }
                    }
                }
                    //If the new route from root to neighbour is shorter than the old route or there was no old route
                    //set the current node as the first step towards the root from neighbour
                else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID)) {
                    neighbour.SetDistanceFromRoot(ID, newDistance, current, link);

                    if (_cont && _text) {
                        current.Say(neighbour.Name + ".cost (" + neighbour.GetDistanceFromRoot(ID) + ") > test cost (" +
                                      newDistance + ")");
                        Pause();
                        current.Say("7. " + neighbour.Name + ".cost = test cost (" + newDistance + ")");
                        Pause();
                    }
                }
            } catch (KeyNotFoundException e) {
                //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop
                _cont = false;
                if (_visualise)
                    VisualisedNode = null;
                Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " +
                         current.Name + " (root = " + Name + ")");
            }

            if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID))
                neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link);

            if (_cont) {
                Pause(4f);
                link.Colour = Color.White;
                Pause(6f);
            }
        }
        /// <summary>
        /// Visualises the process of checking a neighbour node and prints out text explaining what is happening.
        /// </summary>
        /// <param name="neighbour">The neighbour to check.</param>
        /// <param name="current">The current node.</param>
        /// <param name="dist">The distance from the root to the current node.</param>
        /// <param name="link">The link between current and neighbour.</param>
        private void VisualiseCheckNeighbourText(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link)
        {
            if (!_visualise && !_text)
            {
                return;
            }

            float newDistance = dist + link.Weight;

            if (_cont)
            {
                //if (_cont && _text)
                //    current.Say("Examining neighbour " + neighbour.Name);
                Pause(4f);
                link.Colour = Color.Blue;
                if (_cont && _text)
                {
                    Pause();
                    current.Say("5. Test cost to " + neighbour.Name + " = " + dist + " + " + link.Weight + " = " +
                                newDistance);
                    Pause();
                }
                Pause(4f);
            }

            try {
                if (_cont && !_tentative.Contains(neighbour))
                {
                    if (_cont && _text)
                    {
                        current.Say(neighbour.Name + " is not in tentative list");
                    }

                    _tentative.AddFirst(neighbour);
                    neighbour.SetDistanceFromRoot(ID, newDistance, current, link);

                    if (_cont)
                    {
                        Pause(4f);
                        neighbour.Selected = tentativeGlow;
                        if (_cont && _text)
                        {
                            current.Say("6a. Adding " + neighbour.Name + " to the tentative list");
                            Pause();
                            current.Say("6b. " + neighbour.Name + ".cost = test cost (" + newDistance + ")");
                        }
                    }
                }
                //If the new route from root to neighbour is shorter than the old route or there was no old route
                //set the current node as the first step towards the root from neighbour
                else if (_cont && newDistance <= neighbour.GetDistanceFromRoot(ID))
                {
                    neighbour.SetDistanceFromRoot(ID, newDistance, current, link);

                    if (_cont && _text)
                    {
                        current.Say(neighbour.Name + ".cost (" + neighbour.GetDistanceFromRoot(ID) + ") > test cost (" +
                                    newDistance + ")");
                        Pause();
                        current.Say("7. " + neighbour.Name + ".cost = test cost (" + newDistance + ")");
                        Pause();
                    }
                }
            } catch (KeyNotFoundException e) {
                //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop
                _cont = false;
                if (_visualise)
                {
                    VisualisedNode = null;
                }
                Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " +
                             current.Name + " (root = " + Name + ")");
            }

            if (_cont && newDistance < neighbour.GetDistanceFromRoot(ID))
            {
                neighbour.SetDistanceFromRoot(ID, newDistance, neighbour, link);
            }

            if (_cont)
            {
                Pause(4f);
                link.Colour = Color.White;
                Pause(6f);
            }
        }
 /// <summary>
 /// The main loop which is the body of the algorithm.
 /// Loops through every neighbour of the current node checking to see if they:
 /// A. Have been visited before
 /// B. Have been visited before but are now a shorter route
 /// </summary>
 /// <param name="current">The node currently being checked.</param>
 /// <param name="prev">The previous node that was checked.</param>
 /// <returns>The last node to be checked.</returns>
 private void MainLoop(DijkstraNode current, DijkstraNode prev)
 {
     while (_cont && current != null && !hitTarget(current)) {
         //If necessary display text and wait
         if (_cont && _text && _visualise) {
             current.Say("4. Iterating through neighbours excluding neighbours in Confirmed");
             Pause();
         }
         //Get the current distance to the target
         float dist = current.GetDistanceFromRoot(ID);
         foreach (var n in current.Neighbours) {
             IMLink link = current.Links[n.ID];
             if (_visualise)
                 _links.AddFirst(link);
             var neighbour = this.GetAlgNode<DijkstraNode>(n.ID);
             if (_cont && !_confirmed.Contains(neighbour)) {
                 if (_visualise && _text)
                     VisualiseCheckNeighbourText(neighbour, current, dist, link);
                 else if (_visualise)
                     VisualiseCheckNeighbour(neighbour, current, dist, link);
                 checkNeighbour(neighbour, current, dist, link);
             }
             if (!_cont)
                 break;
         }
         //Store the old previous node
         prev = current;
         if (_cont && _text && _visualise) {
             Say("Finished iterating through current's (" + current.Name +
                       "'s) neighbours, getting next current from tentative list");
             Pause();
         }
         //Get the next node to be checked (the one which has the shortest path to it)
         current = getNext(current);
     }
     FinishedReset(current, prev);
 }
        /// <summary>
        /// Visualises the process of checking a neighbour node.
        /// </summary>
        /// <param name="neighbour">The neighbour to check.</param>
        /// <param name="current">The current node.</param>
        /// <param name="dist">The distance from the root to the current node.</param>
        /// <param name="link">The link between current and neighbour.</param>
        private void VisualiseCheckNeighbour(DijkstraNode neighbour, DijkstraNode current, float dist, IMLink link)
        {
            if (!_visualise)
                return;

            if (_cont) {
                Pause(4f);
                link.Colour = Color.Blue;
                Pause(6);
            }

            try {
                if (_cont && !_tentative.Contains(neighbour)) {
                    neighbour.Selected = tentativeGlow;
                    Pause(6);
                }
            } catch (KeyNotFoundException e) {
                //If the AddLink being checked is no Keyer in the list of links the algorithm needs to stop
                _cont = false;
                if (_visualise)
                    VisualisedNode = null;
                Logger.Debug("Trying to work with a neighbour (" + neighbour.Name + ") which is not actually connected to " +
                         current.Name + " (root = " + Name + ")");
            }

            if (_cont)
                link.Colour = Color.White;
        }
 //public override event ForwardingTableChangeDelegate OnRouteChange;
 public override void Stop()
 {
     if (_visualise && Equals(VisualisedNode)) {
         ResetAlgorithm();
         _visualise = false;
         _text = false;
         VisualisedNode = null;
         RunAlgorithm(Name + " visualisation stopped. Re-running algorithm silently.", null, false);
     }
 }
        /// <summary>
        /// Visualise the process of choosing the next node. Will output text about what is going on if necessary.
        /// </summary>
        /// <param name="next">The next node to be current.</param>
        /// <param name="prev">The node that was previously current.</param>
        private void VisualiseChooseNext(DijkstraNode next, DijkstraNode prev)
        {
            if (_cont && !next.Equals(this)) {
                if (_cont && _text) {
                    Say("8. There are nodes in the tentative list. Finding the node in tentative with the smallest cost");
                    Pause();
                }
                Pause(3f);
                if (_cont && _text) {
                    Say("9. new current = " + next.Name + " with cost " + next.GetDistanceFromRoot(ID));
                    Pause();
                    Say("10. Adding link between ct (" + prev.Name + ") and new current (" + next.Name + ") to the shortest path");
                    Pause();
                }
            }

            prev.Reset();

            IMLink confirmedLink = next.GetWIPRoute(ID);
            if (_cont && confirmedLink != null) {
                Pause(6f);
                confirmedLink.Colour = Color.Red;
            }

            if (_cont && _text) {
                Say((next.Equals(this) ? "2a" : "11a") + ". Adding " +
                          (next.Equals(this) ? "root" : "new current") + " (" + next.Name + ") to Confirmed");
                Pause();
                Say((next.Equals(this) ? "2b" : "11b") + ". Setting current to " +
                          (next.Equals(this) ? "root" : "new current") + " (" + next.Name + ")");
            }

            next.Reset();
            next.Selected = currentGlow;
            next.Colour = Color.White;

            if (_cont && _text && !next.Equals(this)) {
                Pause();
                Say("11c. Going to step 4");
                Pause();
            }
        }
        public override void VisualiseAlgorithm(UUID to, Parameters parameters)
        {
            if (Equals(VisualisedNode)) {
                ResetAlgorithm();
                _visualise = false;
                VisualisedNode = null;
                return;
            }
            else if (VisualisedNode != null)
                VisualisedNode.Stop();

            IMNodeInternal target = KnownNodes.ContainsKey(to) ? KnownNodes[to] : null;

            _text = Dijkstra.AlwaysPrint || (Dijkstra.EverPrint && parameters != null && parameters.Get<bool>("Text"));
            VisualisedNode = this;

            RunAlgorithm("Visualise Dijkstra's Algorithm", target, true);
        }