Exemple #1
0
        public Element Get(ResolveInfoComponent resolveInfo, ActionSet actionSet, Element target)
        {
            ActionSet       = actionSet;
            ResolveInfo     = resolveInfo;
            Target          = target;
            PathmapInstance = actionSet.Translate.DeltinScript.Types.GetInstance <PathmapClass>();

            // Lookahead status
            IndexReference result = actionSet.VarCollection.Assign("Lookahead: Result", actionSet.IsGlobal, true);

            actionSet.AddAction(result.SetVariable(new V_False()));

            // The lookhead controller
            Look = actionSet.VarCollection.Assign("Pathfind: Lookahead", actionSet.IsGlobal, true);
            actionSet.AddAction(Look.SetVariable(resolveInfo.Current.Get(target)));

            // The loop
            actionSet.AddAction(Element.Part <A_While>(Element.Part <V_And>(
                                                           !result.Get(),
                                                           LoopCondition()
                                                           )));

            // Set the result.
            actionSet.AddAction(result.SetVariable(SetResult()));

            // End
            actionSet.AddAction(Look.SetVariable(Next));
            actionSet.AddAction(new A_End());
            return(result.Get());
        }
        /// <summary>Looks at a player's future segments.</summary>
        public Element IsTravelingToSegment(ActionSet actionSet, Element targetPlayer, Element segment)
        {
            IndexReference result = actionSet.VarCollection.Assign("Lookahead: Result", actionSet.IsGlobal, true);

            actionSet.AddAction(result.SetVariable(new V_False()));

            IndexReference look = actionSet.VarCollection.Assign("Pathfind: Lookahead", actionSet.IsGlobal, true);

            actionSet.AddAction(look.SetVariable(Current.Get(targetPlayer)));

            // Get the path.
            actionSet.AddAction(Element.Part <A_While>(Element.Part <V_And>(new V_Compare(
                                                                                ParentArray.Get(targetPlayer)[look.Get()] - 1,
                                                                                Operators.GreaterThanOrEqual,
                                                                                new V_Number(0)
                                                                                ), !result.Get())));

            Element currentNode = PathmapInstance.Nodes.Get()[PathmapReference.Get(targetPlayer)][look.Get()];
            Element nextNode    = PathmapInstance.Nodes.Get()[PathmapReference.Get(targetPlayer)][ParentArray.Get(targetPlayer)[look.Get()] - 1];

            actionSet.AddAction(result.SetVariable(new V_Compare(
                                                       segment,
                                                       Operators.Equal,
                                                       Element.Part <V_FirstOf>(PathmapInstance.SegmentsFromNodes(PathmapReference.Get(targetPlayer), look.Get(), ParentArray.Get(targetPlayer)[look.Get()] - 1))
                                                       )));

            actionSet.AddAction(look.SetVariable(ParentArray.Get(targetPlayer)[look.Get()] - 1));
            actionSet.AddAction(new A_End());

            return(result.Get());
        }
Exemple #3
0
        protected override void GetResult()
        {
            /*
             |  |
             +--+--+--+
             |
             */

            IndexReference newParentArray = actionSet.VarCollection.Assign("Pathfinder: New parent array", actionSet.IsGlobal, false);

            // Flip the parent array.
            IndexReference backTracker = actionSet.VarCollection.Assign("Pathfinder: Backtracker", actionSet.IsGlobal, assignExtended);

            actionSet.AddAction(backTracker.SetVariable(current.Get()));

            // Get the path.
            actionSet.AddAction(Element.Part <A_While>(new V_Compare(
                                                           backTracker.GetVariable(),
                                                           Operators.GreaterThanOrEqual,
                                                           new V_Number(0)
                                                           )));

            Element next = parentArray.Get()[backTracker.Get()] - 1;

            actionSet.AddAction(newParentArray.SetVariable(index: next, value: backTracker.Get() + 1));

            actionSet.AddAction(backTracker.SetVariable(next));
            actionSet.AddAction(A_Wait.MinimumWait); // TODO: Should there be a minwait here?
            actionSet.AddAction(new A_End());

            actionSet.AddAction(parentArray.SetVariable(newParentArray.Get()));

            resolveInfo.Pathfind(actionSet, player, pathmapObject, parentArray.Get(), parentAttributeInfo.Get(), Nodes[current.Get()]);
        }
        public Element Get(ResolveInfoComponent resolveInfo, ActionSet actionSet, Element target)
        {
            ActionSet       = actionSet;
            ResolveInfo     = resolveInfo;
            Target          = target;
            PathmapInstance = actionSet.DeltinScript.GetComponent <PathfinderTypesComponent>().Pathmap;

            // Lookahead status
            IndexReference result = actionSet.VarCollection.Assign("Lookahead: Result", actionSet.IsGlobal, true);

            actionSet.AddAction(result.SetVariable(Element.False()));

            // The lookhead controller
            Look = actionSet.VarCollection.Assign("Pathfind: Lookahead", actionSet.IsGlobal, true);
            actionSet.AddAction(Look.SetVariable(resolveInfo.Current.Get(target)));

            // The loop
            actionSet.AddAction(Element.While(Element.And(
                                                  !result.Get(),
                                                  LoopCondition()
                                                  )));

            // Set the result.
            actionSet.AddAction(result.SetVariable(SetResult()));

            // End
            actionSet.AddAction(Look.SetVariable(Next));
            actionSet.AddAction(Element.End());
            return(result.Get());
        }
        public SubroutineCatalogItem Initiate()
        {
            // Setup the subroutine element.
            Subroutine subroutine = _deltinScript.SubroutineCollection.NewSubroutine(_context.ElementName);

            // Create the rule.
            _subroutineRule = new TranslateRule(_deltinScript, subroutine, _context.RuleName, _context.VariableGlobalDefault);

            // Setup the return handler.
            _actionSet = _subroutineRule.ActionSet
                         .ContainVariableAssigner()
                         .SetThisTypeLinker(_context.TypeLinker)
                         .New(_context.Controller.Attributes.IsRecursive);

            // Create the function builder.
            var controller = _context.Controller;

            // Create the parameter handlers.
            _parameterHandler = controller.CreateParameterHandler(_actionSet, null);

            // If the subroutine is an object function inside a class, create a variable to store the class object.
            if (controller.Attributes.IsInstance)
            {
                _objectStore = _actionSet.VarCollection.Assign(_context.ObjectStackName, true, !controller.Attributes.IsRecursive);

                // Set the objectStore as an empty array if the subroutine is recursive.
                if (controller.Attributes.IsRecursive)
                {
                    // Initialize as empty array.
                    _actionSet.InitialSet().AddAction(_objectStore.SetVariable(Element.EmptyArray()));

                    // Add to assigner with the last of the objectStore stack being the object instance.
                    _context.ContainingType?.AddObjectVariablesToAssigner(_actionSet.ToWorkshop, Element.LastOf(_objectStore.GetVariable()), _actionSet.IndexAssigner);

                    // Set the actionSet.
                    _actionSet = _actionSet.New(Element.LastOf(_objectStore.Get())).PackThis().New(_objectStore.CreateChild(Element.CountOf(_objectStore.Get()) - 1));
                }
                else
                {
                    // Add to assigner with the objectStore being the object instance.
                    _context.ContainingType?.AddObjectVariablesToAssigner(_actionSet.ToWorkshop, _objectStore.GetVariable(), _actionSet.IndexAssigner);

                    // Set the actionSet.
                    _actionSet = _actionSet.New(_objectStore.Get()).PackThis().New(_objectStore);
                }
            }

            _functionBuilder = new WorkshopFunctionBuilder(_actionSet, controller);
            _functionBuilder.ModifySet(a => a.PackThis()); // TODO: is this required?
            _functionBuilder.SetupReturnHandler();
            _parameterHandler.AddParametersToAssigner(_actionSet.IndexAssigner);

            // Done.
            return(Result = new SubroutineCatalogItem(
                       subroutine: subroutine,
                       parameterHandler: _parameterHandler,
                       objectStack: _objectStore,
                       returnHandler: _functionBuilder.ReturnHandler));
        }
        public override void AddObjectVariablesToAssigner(IWorkshopTree reference, VarIndexAssigner assigner)
        {
            base.AddObjectVariablesToAssigner(reference, assigner);

            // Add hooks to assigner.
            AddHook(assigner, OnPathStartHook);
            AddHook(assigner, OnNodeReachedHook);
            AddHook(assigner, OnPathCompleted);
            AddHook(assigner, IsNodeReachedDeterminer);

            assigner.Add(NodesVar, Nodes.Get()[(Element)reference]);
            assigner.Add(SegmentsVar, Segments.Get()[(Element)reference]);
        }
        private Element FirstNullOrLength(ActionSet actionSet, Element array, string tempVariableName)
        {
            // Get the index of the first null node.
            IndexReference index = actionSet.VarCollection.Assign(tempVariableName, actionSet.IsGlobal, true);

            // Get the first null value.
            index.SetVariable(Element.Part <V_IndexOfArrayValue>(array, new V_Null()));

            // If the index is -1, use the count of the element.
            index.SetVariable(Element.TernaryConditional(new V_Compare(index.Get(), Operators.Equal, new V_Number(-1)), Element.Part <V_CountOf>(array), index.Get()));

            // Done
            return(index.Get());
        }
        // IComponent
        public void Init()
        {
            _waitAsyncQueue = DeltinScript.VarCollection.Assign("waitAsync_queue", true, false);
            DeltinScript.InitialGlobal.ActionSet.AddAction(_waitAsyncQueue.SetVariable(new V_EmptyArray()));

            // Rule creator.
            var rule = new TranslateRule(DeltinScript, "waitAsync", RuleEvent.OngoingGlobal);

            rule.Conditions.Add(new Condition(
                                    Element.Part <V_IsTrueForAny>(_waitAsyncQueue.Get(), ArrayElementTimeSurpassed(new V_ArrayElement()))
                                    ));

            // Get the affected item.
            var item = DeltinScript.VarCollection.Assign("waitAsync_item", true, false);

            rule.ActionSet.AddAction(item.SetVariable(Element.Part <V_FirstOf>(Element.Part <V_FilteredArray>(
                                                                                   Element.Part <V_MappedArray>(_waitAsyncQueue.Get(), new V_CurrentArrayIndex()),
                                                                                   ArrayElementTimeSurpassed(_waitAsyncQueue.Get()[new V_ArrayElement()])
                                                                                   ))));

            // Activate item lambda.
            DeltinScript.GetComponent <LambdaGroup>().Call(rule.ActionSet.New(Element.Part <V_LastOf>(_waitAsyncQueue.Get()[item.Get()])), new CallHandler());

            // Remove from queue.
            rule.ActionSet.AddAction(_waitAsyncQueue.ModifyVariable(Operation.RemoveFromArrayByIndex, item.Get()));

            // Loop if another item needs to execute on the same tick.
            rule.ActionSet.AddAction(Element.Part <A_LoopIfConditionIsTrue>());

            // Get the rule.
            DeltinScript.WorkshopRules.Add(rule.GetRule());
        }
Exemple #9
0
        private void SetInitialUnvisited()
        {
            // Create an array counting up to the number of values in the nodeArray array.
            // For example, if nodeArray has 6 variables unvisitedVar will be set to [0, 1, 2, 3, 4, 5].

            // Empty the unvisited array.
            actionSet.AddAction(unvisited.SetVariable(new V_EmptyArray()));

            IndexReference current = actionSet.VarCollection.Assign("unvisitedBuilder", actionSet.IsGlobal, assignExtended);

            actionSet.AddAction(current.SetVariable(0));

            // While current < the count of the node array.
            actionSet.AddAction(Element.Part <A_While>((Element)current.GetVariable() < Element.Part <V_CountOf>(Nodes)));

            // If there can be null nodes, make sure the node is not null.
            if (resolveInfo.PotentiallyNullNodes)
            {
                actionSet.AddAction(Element.Part <A_If>(new V_Compare(Nodes[current.Get()], Operators.NotEqual, new V_Null())));
            }

            actionSet.AddAction(unvisited.ModifyVariable(Operation.AppendToArray, (Element)current.GetVariable()));

            // End the if.
            if (resolveInfo.PotentiallyNullNodes)
            {
                actionSet.AddAction(new A_End());
            }

            actionSet.AddAction(current.ModifyVariable(Operation.Add, 1));

            // End the while.
            actionSet.AddAction(new A_End());
        }
        public Element Bake(Action <Element> progress)
        {
            if (_onLoop == null)
            {
                _bakeWait = ActionSet.VarCollection.Assign("bakeWait", ActionSet.IsGlobal, false);
                _bakeWait.Set(ActionSet, 0);
            }

            // Assign bakemap then set it to an empty array.
            _bakemap = ActionSet.VarCollection.Assign("bakemap", ActionSet.IsGlobal, false);
            _bakemap.Set(ActionSet, EmptyArray());

            // Loop through each node.
            _nodeLoop = new ForBuilder(ActionSet, "bakemapNode", NodeArrayLength);
            _builder  = new PathfindAlgorithmBuilder(this);
            progress(Progress);

            _nodeLoop.Init(); // Start the node loop.
            _builder.Get();   // Run pathfinder.
            _nodeLoop.End();  // End the node loop.

            // Create a new Bakemap class instance.
            var newBakemap = _bakemapClass.Instance.Create(ActionSet, ActionSet.Translate.DeltinScript.GetComponent <ClassData>());

            _bakemapClass.Pathmap.SetWithReference(ActionSet, newBakemap.Get(), _pathmapObject);
            _bakemapClass.NodeBake.SetWithReference(ActionSet, newBakemap.Get(), _bakemap.Get());
            return(newBakemap.Get());
        }
        // IComponent
        public void Init(DeltinScript deltinScript)
        {
            DeltinScript = deltinScript;

            _waitAsyncQueue = DeltinScript.VarCollection.Assign("waitAsync_queue", true, false);
            DeltinScript.InitialGlobal.ActionSet.AddAction(_waitAsyncQueue.SetVariable(Element.EmptyArray()));

            // Rule creator.
            var rule = new TranslateRule(DeltinScript, "waitAsync", RuleEvent.OngoingGlobal);

            rule.Conditions.Add(new Condition(
                                    Element.Any(_waitAsyncQueue.Get(), ArrayElementTimeSurpassed(Element.ArrayElement()))
                                    ));

            // Get the affected item.
            var item = DeltinScript.VarCollection.Assign("waitAsync_item", true, false);

            rule.ActionSet.AddAction(item.SetVariable(Element.FirstOf(Element.Filter(
                                                                          Element.Map(_waitAsyncQueue.Get(), Element.ArrayIndex()),
                                                                          ArrayElementTimeSurpassed(_waitAsyncQueue.Get()[Element.ArrayElement()])
                                                                          ))));

            // Activate item lambda.
            DeltinScript.WorkshopConverter.LambdaBuilder.Call(rule.ActionSet.New(Element.LastOf(_waitAsyncQueue.Get()[item.Get()])), new Functions.Builder.CallInfo(), null);

            // Remove from queue.
            rule.ActionSet.AddAction(_waitAsyncQueue.ModifyVariable(Operation.RemoveFromArrayByIndex, item.Get()));

            // Loop if another item needs to execute on the same tick.
            rule.ActionSet.AddAction(Element.LoopIfConditionIsTrue());

            // Get the rule.
            DeltinScript.WorkshopRules.Add(rule.GetRule());
        }
Exemple #12
0
        protected override void Assign()
        {
            // Get the PathResolveClass instance.
            PathResolveClass = actionSet.Translate.DeltinScript.Types.GetInstance <PathResolveClass>();
            PathResolveClass.WorkshopInit(actionSet.Translate.DeltinScript);

            // Create a new PathResolve class instance.
            ClassReference = PathResolveClass.Create(actionSet, actionSet.Translate.DeltinScript.GetComponent <ClassData>());

            // Save the pathmap.
            PathResolveClass.Pathmap.Set(actionSet, ClassReference.Get(), (Element)actionSet.CurrentObject);

            // Save the destination.
            PathResolveClass.Destination.Set(actionSet, ClassReference.Get(), Source);

            // Assign FinalNode
            if (Destination != null)
            {
                finalNode = actionSet.VarCollection.Assign("Final Node", actionSet.IsGlobal, assignExtended);
                finalNode.SetVariable(GetClosestNode(actionSet, Nodes, Destination));
            }
        }
 void IPathfinderInfo.OnLoop()
 {
     if (_onLoop == null)
     {
         ActionSet.AddAction(_bakeWait.ModifyVariable(Operation.Add, 1));
         ActionSet.AddAction(SkipIf(_bakeWait.Get() % 6, Num(1)));
         ActionSet.AddAction(Wait());
     }
     else
     {
         _onLoop.Invoke(ActionSet);
     }
 }
        /// <summary>Looks at a player's future nodes.</summary>
        public Element IsTravelingToAttribute(ActionSet actionSet, Element targetPlayer, Element attribute)
        {
            IndexReference result = actionSet.VarCollection.Assign("Lookahead: Result", actionSet.IsGlobal, true);

            actionSet.AddAction(result.SetVariable(new V_False()));

            IndexReference look = actionSet.VarCollection.Assign("Pathfind: Lookahead", actionSet.IsGlobal, true);

            actionSet.AddAction(look.SetVariable(Current.Get(targetPlayer)));

            // Get the path.
            actionSet.AddAction(Element.Part <A_While>(Element.Part <V_And>(new V_Compare(
                                                                                look.GetVariable(),
                                                                                Operators.GreaterThanOrEqual,
                                                                                new V_Number(0)
                                                                                ), !result.Get())));

            actionSet.AddAction(result.SetVariable(new V_Compare(attribute, Operators.Equal, AttributeArray.Get(targetPlayer)[look.Get()])));

            actionSet.AddAction(look.SetVariable(ParentArray.Get(targetPlayer)[look.Get()] - 1));
            actionSet.AddAction(new A_End());

            return(result.Get());
        }
Exemple #15
0
        public void Get()
        {
            var firstNode = GetClosestNode(actionSet, Nodes, Source);

            Assign();

            current   = actionSet.VarCollection.Assign("Dijkstra: Current", actionSet.IsGlobal, assignExtended);
            distances = actionSet.VarCollection.Assign("Dijkstra: Distances", actionSet.IsGlobal, false);
            unvisited = actionSet.VarCollection.Assign("Dijkstra: Unvisited", actionSet.IsGlobal, false);
            IndexReference connectedSegments = actionSet.VarCollection.Assign("Dijkstra: Connected Segments", actionSet.IsGlobal, assignExtended);
            IndexReference neighborIndex     = actionSet.VarCollection.Assign("Dijkstra: Neighbor Index", actionSet.IsGlobal, assignExtended);
            IndexReference neighborDistance  = actionSet.VarCollection.Assign("Dijkstra: Distance", actionSet.IsGlobal, assignExtended);

            parentArray = GetParentArray();
            if (useAttributes)
            {
                parentAttributeInfo = GetParentAttributeArray();
            }

            // Set the current variable as the first node.
            actionSet.AddAction(current.SetVariable(firstNode));
            SetInitialDistances(actionSet, distances, (Element)current.GetVariable());
            SetInitialUnvisited();

            actionSet.AddAction(Element.Part <A_While>(LoopCondition()));

            // Invoke LoopStart
            OnLoop.Invoke(actionSet);

            // Get neighboring indexes
            actionSet.AddAction(connectedSegments.SetVariable(GetConnectedSegments(
                                                                  (Element)current.GetVariable()
                                                                  )));

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

            // Invoke OnConnectLoop
            OnConnectLoop.Invoke(actionSet);

            actionSet.AddAction(ArrayBuilder <Element> .Build(
                                    // Get the index from the segment data
                                    neighborIndex.SetVariable(
                                        Element.Part <V_FirstOf>(Element.Part <V_FilteredArray>(
                                                                     BothNodes(forBuilder.IndexValue),
                                                                     new V_Compare(
                                                                         new V_ArrayElement(),
                                                                         Operators.NotEqual,
                                                                         current.GetVariable()
                                                                         )
                                                                     ))
                                        ),

                                    // Get the distance between the current and the neighbor index.
                                    neighborDistance.SetVariable(
                                        Element.Part <V_DistanceBetween>(
                                            Nodes[(Element)neighborIndex.GetVariable()],
                                            Nodes[(Element)current.GetVariable()]
                                            ) + ((Element)distances.GetVariable())[(Element)current.GetVariable()]
                                        )
                                    ));

            // Set the current neighbor's distance if the new distance is less than what it is now.
            actionSet.AddAction(Element.Part <A_If>(Element.Part <V_Or>(
                                                        new V_Compare(
                                                            ((Element)distances.GetVariable())[(Element)neighborIndex.GetVariable()],
                                                            Operators.Equal,
                                                            new V_Number(0)
                                                            ),
                                                        (Element)neighborDistance.GetVariable() < ((Element)distances.GetVariable())[(Element)neighborIndex.GetVariable()]
                                                        )));

            actionSet.AddAction(distances.SetVariable((Element)neighborDistance.GetVariable(), null, (Element)neighborIndex.GetVariable()));
            actionSet.AddAction(parentArray.SetVariable((Element)current.GetVariable() + 1, null, (Element)neighborIndex.GetVariable()));

            if (useAttributes)
            {
                if (!reverseAttributes)
                {
                    actionSet.AddAction(parentAttributeInfo.SetVariable(
                                            value: Element.TernaryConditional(
                                                new V_Compare(
                                                    current.GetVariable(),
                                                    Operators.Equal,
                                                    Node1(forBuilder.IndexValue)
                                                    ),
                                                Node2Attribute(forBuilder.IndexValue),
                                                Node1Attribute(forBuilder.IndexValue)
                                                ),
                                            index: neighborIndex.Get()
                                            ));
                }
                else
                {
                    actionSet.AddAction(parentAttributeInfo.SetVariable(
                                            value: Element.TernaryConditional(
                                                new V_Compare(
                                                    current.GetVariable(),
                                                    Operators.Equal,
                                                    Node1(forBuilder.IndexValue)
                                                    ),
                                                Node1Attribute(forBuilder.IndexValue),
                                                Node2Attribute(forBuilder.IndexValue)
                                                ),
                                            index: neighborIndex.Get()
                                            ));
                }
            }

            // End the if.
            actionSet.AddAction(new A_End());
            // End the for.
            forBuilder.Finish();

            // Remove the current node from the unvisited array.
            actionSet.AddAction(unvisited.ModifyVariable(Operation.RemoveFromArrayByValue, (Element)current.GetVariable()));
            EndLoop();
            actionSet.AddAction(current.SetVariable(LowestUnvisited(Nodes, (Element)distances.GetVariable(), (Element)unvisited.GetVariable())));

            actionSet.AddAction(new A_End());

            GetResult();

            actionSet.AddAction(ArrayBuilder <Element> .Build(
                                    current.SetVariable(0),
                                    distances.SetVariable(0),
                                    connectedSegments.SetVariable(0),
                                    neighborIndex.SetVariable(0),
                                    neighborDistance.SetVariable(0),
                                    parentArray.SetVariable(0),
                                    parentAttributeInfo.SetVariable(0)
                                    ));
        }
        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)
                                    ));
        }