/// <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());
        }
        /// <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);
        }
예제 #3
0
        void GetNextNodeRule()
        {
            // The 'next' rule will set current to the next node index when the current node is reached.
            TranslateRule next = new TranslateRule(DeltinScript, "Pathfinder: Resolve Next", RuleEvent.OngoingPlayer);

            next.Conditions.Add(NodeReachedCondition(next.ActionSet));
            next.Conditions.Add(new Condition(ParentArray.Get(), Operator.NotEqual, Element.Null()));

            GetNextNode(next.ActionSet, EventPlayer());

            // Loop the next rule if the condition is true.
            next.ActionSet.AddAction(LoopIfConditionIsTrue());

            // Add rule
            DeltinScript.WorkshopRules.Add(next.GetRule());
        }
예제 #4
0
        public void GetNextNode(ActionSet actionSet, Element player)
        {
            if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock)
            {
                actionSet.AddAction(If(Compare(Current.Get(player), Operator.NotEqual, Num(-1))));
            }

            // Get last attribute.
            actionSet.AddAction(CurrentAttribute.SetVariable(GetCurrentSegmentAttribute(player), targetPlayer: player));

            if (TrackNextAttribute)
            {
                actionSet.AddAction(NextAttribute.SetVariable(GetNextSegmentAttribute(player), targetPlayer: player));
            }

            // Set current as the current's parent.
            actionSet.AddAction(Current.SetVariable(ParentArray.Get(player)[Current.Get(player)] - 1, targetPlayer: player));

            // Update stuck
            UpdateStuckDetector(actionSet, player);

            // Invoke OnNodeReached
            OnNodeReached?.Invoke(actionSet);

            if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock)
            {
                actionSet.AddAction(Else());
            }

            if (OnPathCompleted == null)
            {
                actionSet.AddAction(Part("Stop Throttle In Direction", player));
                StopPathfinding(actionSet, player);
            }
            else if (!OnPathCompleted.EmptyBlock)
            {
                OnPathCompleted.Invoke(actionSet);
            }

            if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock)
            {
                actionSet.AddAction(End());
            }
        }
        /// <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());
        }
        private void GetResolveRoutine()
        {
            // Create the rule that will get the closest node.
            TranslateRule getResolveRule = new TranslateRule(DeltinScript, "Pathfinder: Resolve Current", RuleEvent.OngoingPlayer);

            // The rule will activate when DoGetCurrent is set to true.
            getResolveRule.Conditions.Add(new Condition((Element)DoGetCurrent.GetVariable(), Operators.Equal, new V_True()));
            // Set the Current variable to the closest node.
            getResolveRule.ActionSet.AddAction(Current.SetVariable(ClosestNode(getResolveRule.ActionSet, PlayerPosition())));

            // If the OnPathStart hook is null, do the default which is throttling the player to the next node.
            if (OnPathStart == null)
            {
                // Start throttle to the current node.
                ThrottleEventPlayerToNextNode(getResolveRule.ActionSet);
            }
            // Otherwise, use the hook.
            else
            {
                OnPathStart.Invoke(getResolveRule.ActionSet);
            }

            // Update IsPathfindStuck data.
            UpdateStuckDetector(getResolveRule.ActionSet);

            // Reset DoGetCurrent to false.
            getResolveRule.ActionSet.AddAction(DoGetCurrent.SetVariable(new V_False()));

            // Add the rule.
            DeltinScript.WorkshopRules.Add(getResolveRule.GetRule());

            // Resolve the rule that increments the current node.

            // The 'next' rule will set current to the next node index when the current node is reached.
            TranslateRule next = new TranslateRule(DeltinScript, "Pathfinder: Resolve Next", RuleEvent.OngoingPlayer);

            next.Conditions.Add(NodeReachedCondition(next.ActionSet));
            next.Conditions.Add(new Condition(ParentArray.Get(), Operators.NotEqual, new V_Null()));

            if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock)
            {
                next.ActionSet.AddAction(Element.Part <A_If>(new V_Compare(Current.Get(), Operators.NotEqual, new V_Number(-1))));
            }

            // Get last attribute.
            next.ActionSet.AddAction(CurrentAttribute.SetVariable(NextSegmentAttribute(new V_EventPlayer())));

            // Set current as the current's parent.
            next.ActionSet.AddAction(Current.SetVariable(ParentArray.Get()[Current.Get()] - 1));

            // Update stuck
            UpdateStuckDetector(next.ActionSet);

            // Invoke OnNodeReached
            OnNodeReached?.Invoke(next.ActionSet);

            if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock)
            {
                next.ActionSet.AddAction(Element.Part <A_Else>());
            }

            if (OnPathCompleted == null)
            {
                next.ActionSet.AddAction(Element.Part <A_StopThrottleInDirection>(new V_EventPlayer()));
                StopPathfinding(next.ActionSet, new V_EventPlayer());
            }
            else if (!OnPathCompleted.EmptyBlock)
            {
                OnPathCompleted.Invoke(next.ActionSet);
            }

            if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock)
            {
                next.ActionSet.AddAction(Element.Part <A_End>());
            }

            // Add rule
            DeltinScript.WorkshopRules.Add(next.GetRule());
        }
 /// <summary>Gets the next pathfinding attribute.</summary>
 // public Element NextSegmentAttribute(Element player) => Element.TernaryConditional(
 //     Element.Part<V_And>(IsPathfinding(player), new V_Compare(Current.GetVariable(player), Operators.NotEqual, new V_Number(-1))),
 //     AttributeArray.Get(player)[Current.Get(player)],
 //     new V_Number(-1)
 // );
 public Element NextSegmentAttribute(Element player) => Element.Part <V_MappedArray>(Element.Part <V_FilteredArray>(
                                                                                         PathmapInstance.Attributes.Get()[PathmapReference.Get(player)],
                                                                                         Element.Part <V_And>(
                                                                                             new V_Compare(Element.Part <V_XOf>(Element.Part <V_ArrayElement>()), Operators.Equal, Current.Get(player)),
                                                                                             new V_Compare(Element.Part <V_YOf>(Element.Part <V_ArrayElement>()), Operators.Equal, ParentArray.Get()[Current.Get()] - 1)
                                                                                             )
                                                                                         ), Element.Part <V_ZOf>(Element.Part <V_ArrayElement>()));
 /// <summary>Determines if the target player is pathfinding.</summary>
 public Element IsPathfinding(Element player) => new V_Compare(ParentArray.GetVariable(player), Operators.NotEqual, new V_Null());
 /// <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));
예제 #10
0
 Element GetNextSegmentAttribute(Element player) => Element.Map(Element.Filter(
                                                                    PathmapInstance.Attributes.Get(_toWorkshop, PathmapReference.Get(player)),
                                                                    Element.And(
                                                                        Element.Compare(Element.XOf(Element.ArrayElement()), Operator.Equal, ParentArray.Get(player)[Current.Get(player)] - 1),
                                                                        Element.Compare(Element.YOf(Element.ArrayElement()), Operator.Equal, ParentArray.Get(player)[ParentArray.Get(player)[Current.Get(player)] - 1] - 1)
                                                                        )
                                                                    ), Element.ZOf(Element.ArrayElement()));
예제 #11
0
 /// <summary>Determines if the target player is pathfinding.</summary>
 public Element IsPathfinding(Element player) => Element.Compare(ParentArray.GetVariable(player), Operator.NotEqual, Element.Null());
예제 #12
0
 public Element NextPositionWithDestination(Element player    = null) => PositionAtOrDestination(ParentArray.Get(player)[Current.GetVariable(player)] - 1, player);
        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)
                                    ));
        }