Exemple #1
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());
            }
        }
        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());
        }
 internal void PathFound()
 {
     Debug.Log($"Path found from {From} to {To}");
     OnPathCompleted?.Invoke(_path);
 }
Exemple #4
0
    public IEnumerator Run(T start,
                           Func <T, bool> isGoal,
                           Func <T, IEnumerable <WeightedNode <T> > > explode,
                           Func <T, float> getHeuristic)
    {
        var queue     = new PriorityQueue <T>();
        var distances = new Dictionary <T, float>();
        var parents   = new Dictionary <T, T>();
        var visited   = new HashSet <T>();

        distances[start] = 0;
        queue.Enqueue(new WeightedNode <T>(start, 0));

        var stopwatch = new Stopwatch();

        stopwatch.Start();

        while (!queue.IsEmpty)
        {
            var dequeued = queue.Dequeue();
            visited.Add(dequeued.Element);

            if (isGoal(dequeued.Element))
            {
                var path = CommonUtils.CreatePath(parents, dequeued.Element);
                OnPathCompleted?.Invoke(path);
                yield break;
            }

            var toEnqueue = explode(dequeued.Element);

            foreach (var transition in toEnqueue)
            {
                var neighbour = transition.Element;
                var neighbourToDequeuedDistance = transition.Weight;

                var startToNeighbourDistance =
                    distances.ContainsKey(neighbour) ? distances[neighbour] : float.MaxValue;
                var startToDequeuedDistance = distances[dequeued.Element];

                var newDistance = startToDequeuedDistance + neighbourToDequeuedDistance;

                if (!visited.Contains(neighbour) && startToNeighbourDistance > newDistance)
                {
                    distances[neighbour] = newDistance;
                    parents[neighbour]   = dequeued.Element;

                    queue.Enqueue(new WeightedNode <T>(neighbour, newDistance + getHeuristic(neighbour)));
                }

                if (stopwatch.ElapsedMilliseconds < 1f / 60f)
                {
                    yield return(null);

                    stopwatch.Restart();
                }
            }
        }

        OnCantCalculate?.Invoke();
    }