/// <summary>Starts pathfinding for the specified players/</summary>
        /// <param name="actionSet">The actionset of the current rule.</param>
        /// <param name="players">The players that will start pathfinding.</param>
        /// <param name="pathmapReference">A reference to the pathmap the players are pathfinding with.</param>
        /// <param name="parentArray">The parent array path.</param>
        /// <param name="attributeArray">The path attributes.</param>
        /// <param name="destination">The destination the players are navigating to.</param>
        public void Pathfind(ActionSet actionSet, Element players, Element pathmapReference, Element parentArray, Element attributeArray, Element destination)
        {
            // Set target's pathmap reference.
            actionSet.AddAction(PathmapReference.SetVariable(
                                    value: pathmapReference,
                                    targetPlayer: players
                                    ));

            // Set target's parent array.
            actionSet.AddAction(ParentArray.SetVariable(
                                    value: parentArray,
                                    targetPlayer: players
                                    ));

            // Set target's attribute array.
            actionSet.AddAction(AttributeArray.SetVariable(
                                    value: attributeArray,
                                    targetPlayer: players
                                    ));

            // Set target's destination.
            actionSet.AddAction(Destination.SetVariable(
                                    value: destination,
                                    targetPlayer: players
                                    ));

            // For each of the players, get the current.
            SetCurrent(actionSet, players);
        }
 /// <summary>Stops pathfinding for the specified players.</summary>
 /// <param name="actionSet">The actionset of the current rule.</param>
 /// <param name="players">The players to stop pathfinding for.</param>
 public void StopPathfinding(ActionSet actionSet, Element players) => actionSet.AddAction(ParentArray.SetVariable(value: new V_Null(), targetPlayer: players));
        public void Get()
        {
            IndexReference neighborIndex             = actionSet.VarCollection.Assign("Dijkstra: Neighbor Index", actionSet.IsGlobal, AssignExtended);
            IndexReference neighborDistance          = actionSet.VarCollection.Assign("Dijkstra: Distance", actionSet.IsGlobal, AssignExtended);
            IndexReference neighborSegmentAttributes = actionSet.VarCollection.Assign("Dijkstra: Neighbor Attributes", actionSet.IsGlobal, AssignExtended);

            InitializeVariables();

            actionSet.AddAction(While(Info.LoopCondition));

            // Invoke LoopStart
            Info.OnLoop();

            // Get neighboring indexes
            var connectedSegments = actionSet.VarCollection.Assign("Dijkstra: Connected Segments", actionSet.IsGlobal, AssignExtended);

            connectedSegments.Set(actionSet, GetConnectedSegments());

            // Loop through neighboring indexes
            ForeachBuilder forBuilder = new ForeachBuilder(actionSet, connectedSegments.GetVariable());

            // Invoke OnConnectLoop
            Info.OnConnectLoop();

            actionSet.AddAction(ArrayBuilder <Element> .Build(
                                    // Get the index from the segment data
                                    neighborIndex.SetVariable(
                                        FirstOf(Filter(
                                                    BothNodes(forBuilder.IndexValue),
                                                    Compare(ArrayElement(), Operator.NotEqual, Current.GetVariable())
                                                    ))
                                        ),

                                    // Get the distance between the current and the neighbor index.
                                    neighborDistance.SetVariable(
                                        DistanceBetween(
                                            nodes[neighborIndex.Get()],
                                            nodes[Current.Get()]
                                            ) + Distances.Get()[Current.Get()]
                                        )
                                    ));

            // Get the attributes from the current node to the neighbor node.
            actionSet.AddAction(neighborSegmentAttributes.SetVariable(Filter(attributes,
                                                                             And(
                                                                                 Compare(YOf(ArrayElement()), Operator.Equal, Current.Get()),
                                                                                 Compare(XOf(ArrayElement()), Operator.Equal, neighborIndex.Get())
                                                                                 )
                                                                             )));

            string ifComment =
                @"If the distance between this node and the neighbor node is lower than the node's current parent,
then the current node is closer and should be set as the neighbor's parent.
Alternatively, if the neighbor's distance is 0, that means it was not set so this should
be set as the parent regardless.

Additionally, make sure that any of the neighbor's attributes is in the attribute array.";

            // Set the current neighbor's distance if the new distance is less than what it is now.
            actionSet.AddAction(ifComment, If(And(
                                                  Or(
                                                      Not(Distances.Get()[neighborIndex.Get()]),
                                                      neighborDistance.Get() < Distances.Get()[neighborIndex.Get()]
                                                      ),
                                                  Or(
                                                      // There are no attributes.
                                                      Not(CountOf(neighborSegmentAttributes.Get())),
                                                      // There are attributes and the attribute array contains one of the attributes.
                                                      Any(
                                                          neighborSegmentAttributes.Get(),
                                                          Contains(Info.EnabledAttributes, ZOf(ArrayElement()))
                                                          )
                                                      )
                                                  )));

            actionSet.AddAction(
                "Set the neighbor's distance to be the distance between the current node and neighbor node.",
                Distances.SetVariable(neighborDistance.Get(), index: neighborIndex.Get())
                );
            actionSet.AddAction(
                @"Set the neighbor's parent ('parentArray[neighborIndex]') to be current. 1 is added to current because
0 means no parent was set yet (the first node will have current equal 0). This value will be subtracted
back by 1 when used.",
                ParentArray.SetVariable(Current.Get() + 1, index: neighborIndex.Get())
                );

            actionSet.AddAction(End());                                                                     // End the if.
            forBuilder.Finish();                                                                            // End the for.
            actionSet.AddAction(Unvisited.ModifyVariable(Operation.RemoveFromArrayByValue, Current.Get())); // Remove the current node from the unvisited array.
            Info.OnLoopEnd();                                                                               // External end loop logic.
            Current.Set(actionSet, LowestUnvisited());                                                      // Set current to the unvisited node with the lowest distance.
            actionSet.AddAction(End());                                                                     // End the while loop.
            Info.Finished();                                                                                // Done.

            // Reset variables.
            actionSet.AddAction(ArrayBuilder <Element> .Build(
                                    // Current.SetVariable(0),
                                    // Distances.SetVariable(0),
                                    // neighborIndex.SetVariable(0),
                                    // neighborDistance.SetVariable(0),
                                    // ParentArray.SetVariable(0)
                                    Current.SetVariable(0),
                                    Distances.SetVariable(0),
                                    connectedSegments.SetVariable(0),
                                    neighborIndex.SetVariable(0),
                                    neighborDistance.SetVariable(0),
                                    ParentArray.SetVariable(0)
                                    ));
        }