Beispiel #1
0
        protected virtual void Awake()
        {
            enabled = false;

            effects       = ReGoapState.Instantiate();
            preconditions = ReGoapState.Instantiate();
        }
Beispiel #2
0
        protected virtual void Awake()
        {
            enabled = false;

            effects = ReGoapState <T, W> .Instantiate();

            preconditions = ReGoapState <T, W> .Instantiate();

            genericValues = new Dictionary <string, object>();
        }
Beispiel #3
0
        protected virtual void Awake()
        {
            state = ReGoapState <T, W> .Instantiate();

            sensors = GetComponents <IReGoapSensor <T, W> >();
            foreach (var sensor in sensors)
            {
                sensor.Init(this);
            }
        }
Beispiel #4
0
        private void Init(IGoapPlanner <T, W> planner, ReGoapState <T, W> newGoal, ReGoapNode <T, W> parent, IReGoapAction <T, W> action)
        {
            expandList.Clear();

            this.planner = planner;
            this.parent  = parent;
            this.action  = action;
            if (action != null)
            {
                actionSettings = action.GetSettings(planner.GetCurrentAgent(), newGoal);
            }

            if (parent != null)
            {
                state = parent.GetState().Clone();
                // g(node)
                g = parent.GetPathCost();
            }
            else
            {
                state = planner.GetCurrentAgent().GetMemory().GetWorldState().Clone();
            }

            var nextAction = parent == null ? null : parent.action;

            if (action != null)
            {
                // since in backward search we relax the problem all preconditions are valid but are added to the current goal
                var preconditions = action.GetPreconditions(newGoal, nextAction);
                goal = newGoal + preconditions;

                var effects = action.GetEffects(newGoal, nextAction);
                state.AddFromState(effects);
                g += action.GetCost(newGoal, nextAction);

                // removing current action effects from goal, no need to do with to the whole state
                //  since the state is the sum of all the previous actions's effects.
                goal.ReplaceWithMissingDifference(effects);

                // this is needed every step to make sure that any precondition is not already satisfied
                //  by the world state
                goal.ReplaceWithMissingDifference(planner.GetCurrentAgent().GetMemory().GetWorldState());
            }
            else
            {
                var diff = ReGoapState <T, W> .Instantiate();

                newGoal.MissingDifference(state, ref diff);
                goal = diff;
            }
            h = goal.Count;
            // f(node) = g(node) + h(node)
            cost = g + h * heuristicMultiplier;
        }
Beispiel #5
0
        private void Init(IGoapPlanner <T, W> planner, ReGoapState <T, W> newGoal, ReGoapNode <T, W> parent, IReGoapAction <T, W> action)
        {
            expandList.Clear();

            this.planner = planner;
            this.parent  = parent;
            this.action  = action;
            if (action != null)
            {
                actionSettings = action.GetSettings(planner.GetCurrentAgent(), newGoal);
            }

            if (parent != null)
            {
                state = parent.GetState().Clone();
                // g(node)
                g = parent.GetPathCost();
            }
            else
            {
                state = planner.GetCurrentAgent().GetMemory().GetWorldState().Clone();
            }

            var nextAction = parent == null ? null : parent.action;

            if (action != null)
            {
                // create a new instance of the goal based on the paren't goal
                goal = ReGoapState <T, W> .Instantiate(newGoal);

                var preconditions = action.GetPreconditions(goal, nextAction);
                var effects       = action.GetEffects(goal, nextAction);
                // adding the action's effects to the current node's state
                state.AddFromState(effects);
                // addding the action's cost to the node's total cost
                g += action.GetCost(goal, nextAction);

                // add all preconditions of the current action to the goal
                goal.AddFromState(preconditions);
                // removes from goal all the conditions that are now fullfiled in the node's state
                goal.ReplaceWithMissingDifference(state);
            }
            else
            {
                var diff = ReGoapState <T, W> .Instantiate();

                newGoal.MissingDifference(state, ref diff);
                goal = diff;
            }
            h = goal.Count;
            // f(node) = g(node) + h(node)
            cost = g + h * heuristicMultiplier;
        }
Beispiel #6
0
 public virtual List <ReGoapState <T, W> > GetSettings(GoapActionStackData <T, W> stackData)
 {
     if (stackData.settings != null)
     {
         return(new List <ReGoapState <T, W> > {
             stackData.settings
         });
     }
     else
     {
         return(new List <ReGoapState <T, W> > {
             ReGoapState <T, W> .Instantiate()
         });
     }
 }
Beispiel #7
0
        public static ReGoapTestGoal GetCustomGoal(GameObject gameObject, string name, Dictionary <string, object> goalState, int priority = 1)
        {
            var customGoal = gameObject.AddComponent <ReGoapTestGoal>();

            customGoal.Name = name;
            customGoal.SetPriority(priority);
            customGoal.Init();
            var goal = ReGoapState <string, object> .Instantiate();

            foreach (var pair in goalState)
            {
                goal.Set(pair.Key, pair.Value);
            }
            customGoal.SetGoalState(goal);
            return(customGoal);
        }
Beispiel #8
0
        public void TestReGoapStateMissingDifference()
        {
            var state = ReGoapState <string, object> .Instantiate();

            state.Set("var0", true);
            state.Set("var1", "string");
            state.Set("var2", 1);
            var otherState = ReGoapState <string, object> .Instantiate();

            otherState.Set("var1", "stringDifferent");
            otherState.Set("var2", 1);
            var differences = ReGoapState <string, object> .Instantiate();

            var count = state.MissingDifference(otherState, ref differences);

            Assert.That(count, Is.EqualTo(2));
            Assert.That(differences.Get("var0"), Is.EqualTo(true));
            Assert.That(differences.Get("var1"), Is.EqualTo("string"));
            Assert.That(differences.HasKey("var2"), Is.EqualTo(false));
        }
Beispiel #9
0
        protected virtual void Awake()
        {
            lastCalculationTime = -100;

            goals = new List <ReGoapGoal>(GetComponents <ReGoapGoal>());
            possibleGoalsDirty = true;

            actions = new List <ReGoapAction>(GetComponents <ReGoapAction>());
            for (int i = 0; i < actions.Count; ++i)
            {
                actions[i].SetAgent(this);
            }

            state   = ReGoapState.Instantiate();
            sensors = GetComponents <ReGoapSensor>();
            foreach (var sensor in sensors)
            {
                sensor.Init(this);
            }
        }
Beispiel #10
0
        public void TestReGoapStateAddOperator()
        {
            var state = ReGoapState <string, object> .Instantiate();

            state.Set("var0", true);
            state.SetStructValue("var1", StructValue.CreateIntArithmetic(10));
            state.SetStructValue("var2", StructValue.CreateFloatArithmetic(100f));
            var otherState = ReGoapState <string, object> .Instantiate();

            otherState.SetStructValue("var1", StructValue.CreateIntArithmetic(20)); // 2nd one replaces the first
            otherState.SetStructValue("var2", StructValue.CreateFloatArithmetic(-20f));
            otherState.Set("var3", 10.1f);
            Assert.That(state.Count, Is.EqualTo(3));
            state.AddFromState(otherState);
            Assert.That(otherState.Count, Is.EqualTo(3));
            Assert.That(state.Count, Is.EqualTo(4));
            Assert.That(state.Get("var0"), Is.EqualTo(true));
            Assert.That(state.Get("var1"), Is.EqualTo(30));
            Assert.That(state.Get("var2"), Is.EqualTo(80f));
            Assert.That(state.Get("var3"), Is.EqualTo(10.1f));
        }
Beispiel #11
0
        public void TestReGoapStateAddOperator()
        {
            var state = ReGoapState <string, object> .Instantiate();

            state.Set("var0", true);
            state.Set("var1", "string");
            state.Set("var2", 1);
            var otherState = ReGoapState <string, object> .Instantiate();

            otherState.Set("var2", "new2"); // 2nd one replaces the first
            otherState.Set("var3", true);
            otherState.Set("var4", 10.1f);
            Assert.That(state.Count, Is.EqualTo(3));
            state.AddFromState(otherState);
            Assert.That(otherState.Count, Is.EqualTo(3));
            Assert.That(state.Count, Is.EqualTo(5)); // var2 on first is replaced by var2 on second
            Assert.That(state.Get("var0"), Is.EqualTo(true));
            Assert.That(state.Get("var1"), Is.EqualTo("string"));
            Assert.That(state.Get("var2"), Is.EqualTo("new2"));
            Assert.That(state.Get("var3"), Is.EqualTo(true));
            Assert.That(state.Get("var4"), Is.EqualTo(10.1f));
        }
Beispiel #12
0
        public static ReGoapTestAction GetCustomAction(GameObject gameObject, string name, Dictionary <string, object> preconditionsBools,
                                                       Dictionary <string, object> effectsBools, int cost = 1)
        {
            var effects = ReGoapState <string, object> .Instantiate();

            var preconditions = ReGoapState <string, object> .Instantiate();

            var customAction = gameObject.AddComponent <ReGoapTestAction>();

            customAction.Name = name;
            customAction.Init();
            foreach (var pair in effectsBools)
            {
                _AddIntoReGoapState(effects, pair.Key, pair.Value);
            }
            customAction.SetEffects(effects);
            foreach (var pair in preconditionsBools)
            {
                _AddIntoReGoapState(preconditions, pair.Key, pair.Value);
            }
            customAction.SetPreconditions(preconditions);
            customAction.Cost = cost;
            return(customAction);
        }
    private void UpdateGoapNodes <T, W>(IReGoapAgent <T, W> agent)
    {
        if (nodes == null)
        {
            nodes = new List <ReGoapNodeEditor>();
        }
        if (agentHelper == null || agent == null || !agent.IsActive() || agent.GetMemory() == null)
        {
            return;
        }

        nodes.Clear();
        var width        = 300f;
        var height       = 70f;
        var nodePosition = new Vector2(0f, 60f);
        var nodeMiddleY  = new Vector2(0f, height * 0.5f);

        ReGoapNodeEditor?previousNode = null;

        foreach (var goal in agent.GetGoalsSet())
        {
            if (goal.GetGoalState() == null)
            {
                continue;
            }
            var text = string.Format("<b>GOAL</b> <i>{0}</i>\n", goal);
            foreach (var keyValue in goal.GetGoalState().GetValues())
            {
                text += string.Format("<b>'{0}'</b> = <i>'{1}'</i>", keyValue.Key, keyValue.Value);
            }
            var style = nodeStyle;
            if (agent.IsActive() && agent.GetCurrentGoal() == goal)
            {
                style = activeStyle;
            }
            var newNode = DrawGenericNode(text, width, height, style, ref nodePosition);
            if (previousNode.HasValue)
            {
                var startPosition = previousNode.Value.Rect.max - nodeMiddleY - new Vector2(10f, 0f);
                var endPosition   = newNode.Rect.min + nodeMiddleY + new Vector2(10f, 0f);
                Handles.DrawLine(startPosition, endPosition);
            }
            previousNode = newNode;
        }
        previousNode = null;

        nodePosition = new Vector2(0f, nodePosition.y + height + 10);
        height       = 66;
        var maxHeight = height;

        var emptyGoal = agent.InstantiateNewState();
        GoapActionStackData <T, W> stackData;

        stackData.agent        = agent;
        stackData.currentState = agent.GetMemory().GetWorldState();
        stackData.goalState    = emptyGoal;
        stackData.next         = null;
        stackData.settings     = ReGoapState <T, W> .Instantiate();

        foreach (var action in agent.GetActionsSet())
        {
            var curHeight = height;
            var text      = string.Format("<b>POSS.ACTION</b> <i>{0}</i>\n", action.GetName());
            text += "-<b>preconditions</b>-\n";
            var preconditionsDifferences = agent.InstantiateNewState();
            var preconditions            = action.GetPreconditions(stackData);
            if (preconditions == null)
            {
                continue;
            }
            preconditions.MissingDifference(stackData.currentState, ref preconditionsDifferences);
            foreach (var preconditionPair in preconditions.GetValues())
            {
                curHeight += 13;
                var color = "#004d00";
                if (preconditionsDifferences.GetValues().ContainsKey(preconditionPair.Key))
                {
                    color = "#800000";
                }
                text += string.Format("<color={2}>'<b>{0}</b>' = '<i>{1}</i>'</color>\n", preconditionPair.Key, preconditionPair.Value, color);
            }
            preconditionsDifferences.Recycle();

            text += "-<b>effects</b>-\n";
            foreach (var effectPair in action.GetEffects(stackData).GetValues())
            {
                curHeight += 13;
                text      += string.Format("'<b>{0}</b>' = '<i>{1}</i>'\n", effectPair.Key, effectPair.Value);
            }
            curHeight += 13;
            var proceduralCheck = action.CheckProceduralCondition(stackData);
            text += string.Format("<color={0}>-<b>proceduralCondition</b>: {1}</color>\n", proceduralCheck ? "#004d00" : "#800000", proceduralCheck);

            maxHeight = Mathf.Max(maxHeight, curHeight);

            nodeMiddleY = new Vector2(0f, curHeight * 0.5f);
            var newNode = DrawGenericNode(text, width, curHeight, possibleActionStyle, ref nodePosition);
            if (previousNode.HasValue)
            {
                var startPosition = previousNode.Value.Rect.max - nodeMiddleY - new Vector2(10f, 0f);
                var endPosition   = newNode.Rect.min + nodeMiddleY + new Vector2(10f, 0f);
                Handles.DrawLine(startPosition, endPosition);
            }
            previousNode = newNode;
        }
        previousNode = null;

        nodePosition.x  = 0;
        nodePosition.y += maxHeight + 10;
        height          = 40;
        nodeMiddleY     = new Vector2(0f, height * 0.5f);
        if (agent.GetCurrentGoal() != null)
        {
            foreach (var action in agent.GetStartingPlan().ToArray())
            {
                var style = actionNodeStyle;
                if (action.Action.IsActive())
                {
                    style = activeActionNodeStyle;
                }
                var text = string.Format("<b>ACTION</b> <i>{0}</i>\n", action.Action.GetName());

                var newNode = DrawGenericNode(text, width, height, style, ref nodePosition);
                if (previousNode.HasValue)
                {
                    var startPosition = previousNode.Value.Rect.max - nodeMiddleY - new Vector2(10f, 0f);
                    var endPosition   = newNode.Rect.min + nodeMiddleY + new Vector2(10f, 0f);
                    Handles.DrawLine(startPosition, endPosition);
                }
                previousNode = newNode;
            }
        }

        if (agent.GetMemory() != null)
        {
            nodePosition = new Vector2(0, nodePosition.y + height + 10);
            width        = 500;
            height       = 40;
            nodeMiddleY  = new Vector2(0f, height * 0.5f);
            var nodeText = "<b>WORLD STATE</b>\n";
            foreach (var pair in agent.GetMemory().GetWorldState().GetValues())
            {
                nodeText += string.Format("'<b>{0}</b>' = '<i>{1}</i>'\n", pair.Key, pair.Value);
                height   += 13;
            }
            DrawGenericNode(nodeText, width, height, worldStateStyle, ref nodePosition);
        }
    }
Beispiel #14
0
        private void Init(IGoapPlanner <T, W> planner, ReGoapState <T, W> newGoal, ReGoapNode <T, W> parent, IReGoapAction <T, W> action)
        {
            expandList.Clear();
            tmpKeys.Clear();

            this.planner = planner;
            this.parent  = parent;
            this.action  = action;
            if (action != null)
            {
                actionSettings = action.GetSettings(planner.GetCurrentAgent(), newGoal);
            }

            if (parent != null)
            {
                state = parent.GetState().Clone();
                // g(node)
                g = parent.GetPathCost();
            }
            else
            {
                state = planner.GetCurrentAgent().GetMemory().GetWorldState().Clone();
            }

            var nextAction = parent == null ? null : parent.action;

            if (action != null)
            {
                // create a new instance of the goal based on the paren't goal
                goal = ReGoapState <T, W> .Instantiate();

                var tmpGoal = ReGoapState <T, W> .Instantiate(newGoal);

                var preconditions = action.GetPreconditions(tmpGoal, nextAction);
                var effects       = action.GetEffects(tmpGoal, nextAction);
                // adding the action's effects to the current node's state
                state.AddFromState(effects);
                // addding the action's cost to the node's total cost
                g += action.GetCost(tmpGoal, nextAction);

                //// add all preconditions of the current action to the goal
                //tmpGoal.AddFromState(preconditions);
                //// removes from goal all the conditions that are now fulfilled in the node's state
                //tmpGoal.ReplaceWithMissingDifference(state);
                ////goal.ReplaceWithMissingDifference(effects);

                // collect all keys from goal & precondition, unique-ed
                foreach (var pr in tmpGoal.GetValues())
                {
                    var k = pr.Key;
                    if (!tmpKeys.Contains(k))
                    {
                        tmpKeys.Add(k);
                    }
                }
                foreach (var pr in preconditions.GetValues())
                {
                    var k = pr.Key;
                    if (!tmpKeys.Contains(k))
                    {
                        tmpKeys.Add(k);
                    }
                }

                // process each keys
                foreach (var k in tmpKeys)
                {
                    StructValue goalValue, effectValue, precondValue, stateValue, protoValue;
                    tmpGoal.GetValues().TryGetValue(k, out goalValue);
                    effects.GetValues().TryGetValue(k, out effectValue);
                    preconditions.GetValues().TryGetValue(k, out precondValue);
                    state.GetValues().TryGetValue(k, out stateValue);

                    StructValue.EValueType valueType;
                    _GetValueType(ref goalValue, ref effectValue, ref precondValue, ref stateValue, out valueType, out protoValue);
                    if (valueType == StructValue.EValueType.Arithmetic)
                    {
                        //_EnsureArithStructValueInited(ref goalValue, ref protoValue);
                        _EnsureArithStructValueInited(ref effectValue, ref protoValue);
                        _EnsureArithStructValueInited(ref precondValue, ref protoValue);
                        _EnsureArithStructValueInited(ref stateValue, ref protoValue);
                        if (!goalValue.Inited)
                        {
                            goalValue = StructValue.CopyCreate(ref stateValue, -(Convert.ToSingle(stateValue.v) - Convert.ToSingle(effectValue.v)));
                        }

                        float fGoal    = Convert.ToSingle(goalValue.v);
                        float fEffect  = Convert.ToSingle(effectValue.v);
                        float fPrecond = Convert.ToSingle(precondValue.v);
                        float fState   = Convert.ToSingle(stateValue.v);

                        float finalV = Math.Max(
                            fGoal - fEffect,
                            Math.Min(fPrecond, fPrecond - fState)
                            );

                        var sv = StructValue.CopyCreate(ref protoValue, finalV);

                        goal.SetStructValue(k, sv);
                    }
                    else if (valueType == StructValue.EValueType.Other)
                    {
                        //ReplaceWithMissingDifference
                        if (stateValue.Inited && goalValue.Inited && goalValue.IsFulfilledBy(stateValue))
                        {
                            goalValue.Invalidate();
                        }

                        // AddFromPrecond
                        // 1. if the precond is satisfied by the memory start state, then discard
                        // 2. else this newly added goal from precond, should not be removed due to fulfilled by curStateValue
                        if (precondValue.Inited)
                        {
                            bool        preCondfulfilledByMem = false;
                            var         startMemoryState      = planner.GetCurrentAgent().GetMemory().GetWorldState();
                            StructValue startMemoryValue;
                            if (startMemoryState.GetValues().TryGetValue(k, out startMemoryValue))
                            {
                                if (startMemoryValue.Inited && precondValue.IsFulfilledBy(startMemoryValue))
                                {
                                    preCondfulfilledByMem = true;
                                }
                            }

                            if (!preCondfulfilledByMem)
                            {
                                if (goalValue.Inited)
                                {
                                    goalValue = goalValue.MergeWith(precondValue);
                                }
                                else
                                {
                                    goalValue = precondValue;
                                }
                            }
                        }

                        if (goalValue.Inited)
                        {
                            goal.SetStructValue(k, goalValue);
                        }
                    }
                    else
                    {
                        UnityEngine.Debug.LogError("Unexpected StructValue type: " + valueType);
                    }
                }// foreach (var k in tmpKeys)

                tmpGoal.Recycle();
            }
            else
            {
                var diff = ReGoapState <T, W> .Instantiate();

                newGoal.MissingDifference(state, ref diff);
                goal = diff;
            }

            h = _CalculateH();

            // f(node) = g(node) + h(node)
            cost = g + h * planner.GetSettings().HeuristicMultiplier;
        }
Beispiel #15
0
        public void TestDynamicAction()
        {
            var gameObject = new GameObject();

            // settings these value to make sure that the planning chooses weaponA, since the pathing
            // weaponA -> ammoA -> enemy is actually cheaper, even if weaponC is very close to the enemy
            // without dynamic cost weaponC would always be chosen
            // we also add weaponB and ammoB to show the reconcileStartPosition logic
            // with this requirement in the goal and this action, we push as cost a goto to the player position
            // this effectively makes the plan: weaponB -> ammoB -> enemy more expensive, without reconciling with the starting position this plan would have been the best.
            var playerPosition  = Vector2.zero;
            var enemyPosition   = new Vector2(0, 100);
            var weaponAPosition = new Vector2(0, 50);
            var ammoAPosition   = new Vector2(0, 60);
            var weaponBPosition = new Vector2(0, 115);
            var ammoBPosition   = new Vector2(0, 115);
            var weaponCPosition = new Vector2(-5, 100);
            var weaponRange     = 20.0f;

            ReGoapTestsHelper.GetCustomAction(gameObject, "ShootEnemy",
                                              new Dictionary <string, object> {
                { "weaponReady", true }, { "isAt", enemyPosition }, { "inRange", weaponRange }
            },
                                              new Dictionary <string, object> {
                { "shootEnemy", true }
            }, 100);
            ReGoapTestsHelper.GetCustomAction(gameObject, "ReloadWeapon",
                                              new Dictionary <string, object> {
                { "hasWeapon", true }, { "hasAmmo", true }
            },
                                              new Dictionary <string, object> {
                { "weaponReady", true }
            }, 20);
            #region getWeapon
            var getWeapon = ReGoapTestsHelper.GetCustomAction(gameObject, "GetWeapon",
                                                              new Dictionary <string, object> {
            },
                                                              new Dictionary <string, object> {
                { "hasWeapon", true }
            }, 5);
            getWeapon.CustomPreconditionsGetter = (ref ReGoapState <string, object> preconditions, GoapActionStackData <string, object> stackData) =>
            {
                preconditions.Clear();
                if (stackData.settings.HasKey("weaponPosition"))
                {
                    preconditions.Set("isAt", (Vector2)stackData.settings.Get("weaponPosition"));
                }
            };
            getWeapon.CustomEffectsGetter = (ref ReGoapState <string, object> effects, GoapActionStackData <string, object> stackData) =>
            {
                effects.Clear();
                if (stackData.settings.HasKey("weaponPosition"))
                {
                    effects.Set("hasWeapon", true);
                }
            };
            getWeapon.CustomSettingsGetter = (GoapActionStackData <string, object> stackData) =>
            {
                var results = new List <ReGoapState <string, object> >();

                if (stackData.currentState.HasKey("weaponPositions") && stackData.currentState.HasKey("isAt"))
                {
                    var currentPosition = (Vector2)stackData.currentState.Get("isAt");

                    foreach (var objectPosition in (List <Vector2>)stackData.currentState.Get("weaponPositions"))
                    {
                        ReGoapState <string, object> settings = ReGoapState <string, object> .Instantiate();

                        settings.Set("weaponPosition", objectPosition);
                        results.Add(settings);
                    }
                }
                return(results);
            };
            #endregion
            #region getAmmo
            var getAmmo = ReGoapTestsHelper.GetCustomAction(gameObject, "GetAmmo",
                                                            new Dictionary <string, object> {
            },
                                                            new Dictionary <string, object> {
                { "hasAmmo", true }
            }, 3);

            getAmmo.CustomPreconditionsGetter = (ref ReGoapState <string, object> preconditions, GoapActionStackData <string, object> stackData) =>
            {
                preconditions.Clear();
                if (stackData.settings.HasKey("ammoPosition"))
                {
                    preconditions.Set("isAt", (Vector2)stackData.settings.Get("ammoPosition"));
                }
            };
            getAmmo.CustomEffectsGetter = (ref ReGoapState <string, object> effects, GoapActionStackData <string, object> stackData) =>
            {
                effects.Clear();
                if (stackData.settings.HasKey("ammoPosition"))
                {
                    effects.Set("hasAmmo", true);
                }
            };
            getAmmo.CustomSettingsGetter = (GoapActionStackData <string, object> stackData) =>
            {
                var results = new List <ReGoapState <string, object> >();

                if (stackData.currentState.HasKey("ammoPositions") && stackData.currentState.HasKey("isAt"))
                {
                    var currentPosition = (Vector2)stackData.currentState.Get("isAt");

                    foreach (var objectPosition in (List <Vector2>)stackData.currentState.Get("ammoPositions"))
                    {
                        ReGoapState <string, object> settings = ReGoapState <string, object> .Instantiate();

                        settings.Set("ammoPosition", objectPosition);
                        results.Add(settings);
                    }
                }
                return(results);
            };
            #endregion
            #region dynamicGoTo
            var dynamicGoTo = ReGoapTestsHelper.GetCustomAction(gameObject, "GoTo",
                                                                new Dictionary <string, object> {
            },
                                                                new Dictionary <string, object> {
            });
            dynamicGoTo.CustomCostGetter = (ref float cost, GoapActionStackData <string, object> stackData) =>
            {
                // base value to avoid free action
                cost = 1.0f;
                var inRange = 0.0f;
                if (stackData.settings.HasKey("inRange"))
                {
                    inRange = (float)stackData.settings.Get("inRange");
                }
                if (stackData.settings.HasKey("isAt") && stackData.currentState.HasKey("isAt"))
                {
                    var wantedPosition  = (Vector2)stackData.settings.Get("isAt");
                    var currentPosition = (Vector2)stackData.currentState.Get("isAt");
                    cost = (wantedPosition - currentPosition).magnitude - inRange;
                    if (cost < 0)
                    {
                        cost = 0;
                    }
                }
            };
            dynamicGoTo.CustomEffectsGetter = (ref ReGoapState <string, object> effects, GoapActionStackData <string, object> stackData) =>
            {
                effects.Clear();
                if (stackData.settings.HasKey("isAt"))
                {
                    var wantedPosition = (Vector2)stackData.settings.Get("isAt");
                    effects.Set("isAt", wantedPosition);
                }
                if (stackData.settings.HasKey("inRange"))
                {
                    var inRange = (float)stackData.settings.Get("inRange");
                    effects.Set("inRange", inRange);
                }
            };
            dynamicGoTo.CustomSettingsGetter = (GoapActionStackData <string, object> stackData) =>
            {
                var newSettings = ReGoapState <string, object> .Instantiate();

                Vector2 wantedPosition = Vector2.zero;
                float   inRange        = 0.0f;
                if (stackData.goalState.HasKey("isAt"))
                {
                    wantedPosition = (Vector2)stackData.goalState.Get("isAt");
                }
                if (stackData.goalState.HasKey("inRange"))
                {
                    inRange = (float)stackData.goalState.Get("inRange");
                }
                newSettings.Set("isAt", wantedPosition);
                newSettings.Set("inRange", inRange);
                return(new List <ReGoapState <string, object> > {
                    newSettings
                });
            };
            #endregion
            #region reconcileStartPosition
            var reconcileStartPosition = ReGoapTestsHelper.GetCustomAction(gameObject, "ReconcileStartPosition",
                                                                           new Dictionary <string, object> {
            },
                                                                           new Dictionary <string, object> {
            }, 1);
            reconcileStartPosition.CustomPreconditionsGetter = (ref ReGoapState <string, object> preconditions, GoapActionStackData <string, object> stackData) =>
            {
                preconditions.Clear();
                // this could be fetched from the world memory, in a custom action class
                preconditions.Set("isAt", playerPosition);
            };
            reconcileStartPosition.CustomEffectsGetter = (ref ReGoapState <string, object> effects, GoapActionStackData <string, object> stackData) =>
            {
                effects.Clear();
                // we want this action to work only if no other goal has to be archived
                if (stackData.goalState.HasKey("reconcileStartPosition") && stackData.goalState.Count == 1)
                {
                    effects.Set("reconcileStartPosition", true);
                }
            };
            #endregion

            var theGoal = ReGoapTestsHelper.GetCustomGoal(gameObject, "ShootEnemy",
                                                          new Dictionary <string, object> {
                { "shootEnemy", true }, { "reconcileStartPosition", true }
            });

            var memory = gameObject.AddComponent <ReGoapTestMemory>();
            memory.Init();
            memory.SetValue("enemyPosition", enemyPosition);
            memory.SetValue("ammoPositions", new List <Vector2> {
                ammoAPosition, ammoBPosition
            });
            memory.SetValue("weaponPositions", new List <Vector2> {
                weaponAPosition, weaponBPosition, weaponCPosition
            });

            var agent = gameObject.AddComponent <ReGoapTestAgent>();
            agent.Init();

            var plan = GetPlanner(dynamicActions: true).Plan(agent, null, null, null);
        }
 protected virtual void Awake()
 {
     goal = ReGoapState <T, W> .Instantiate();
 }
Beispiel #17
0
        public IReGoapGoal <T, W> Plan(IReGoapAgent <T, W> agent, IReGoapGoal <T, W> blacklistGoal = null, Queue <ReGoapActionState <T, W> > currentPlan = null, Action <IReGoapGoal <T, W> > callback = null)
        {
            if (ReGoapLogger.Level == ReGoapLogger.DebugLevel.Full)
            {
                ReGoapLogger.Log("[ReGoalPlanner] Starting planning calculation for agent: " + agent);
            }
            goapAgent   = agent;
            Calculated  = false;
            currentGoal = null;
            var possibleGoals = new List <IReGoapGoal <T, W> >();

            foreach (var goal in goapAgent.GetGoalsSet())
            {
                if (goal == blacklistGoal)
                {
                    continue;
                }
                goal.Precalculations(this);
                if (goal.IsGoalPossible())
                {
                    possibleGoals.Add(goal);
                }
            }
            possibleGoals.Sort((x, y) => x.GetPriority().CompareTo(y.GetPriority()));

            while (possibleGoals.Count > 0)
            {
                currentGoal = possibleGoals[possibleGoals.Count - 1];
                possibleGoals.RemoveAt(possibleGoals.Count - 1);
                var goalState = currentGoal.GetGoalState();

                // can't work with dynamic actions, of course
                if (!settings.UsingDynamicActions)
                {
                    var wantedGoalCheck = currentGoal.GetGoalState();
                    // we check if the goal can be archived through actions first, so we don't brute force it with A* if we can't
                    foreach (var action in goapAgent.GetActionsSet())
                    {
                        action.Precalculations(goapAgent, goalState);
                        if (!action.CheckProceduralCondition(goapAgent, wantedGoalCheck))
                        {
                            continue;
                        }
                        // check if the effects of all actions can archieve currentGoal
                        var previous = wantedGoalCheck;
                        wantedGoalCheck = ReGoapState <T, W> .Instantiate();

                        previous.MissingDifference(action.GetEffects(wantedGoalCheck), ref wantedGoalCheck);
                    }
                    // can't validate goal
                    if (wantedGoalCheck.Count > 0)
                    {
                        currentGoal = null;
                        continue;
                    }
                }

                //Utilities.ReGoapLogger.Log(string.Format("**** Goal: {0}, Expected State = ({1})", currentGoal.GetName(), goalState));

                goalState = goalState.Clone();
                var leaf = (ReGoapNode <T, W>)astar.Run(
                    ReGoapNode <T, W> .Instantiate(this, goalState, null, null), goalState, settings.MaxIterations, settings.PlanningEarlyExit, debugPlan: agent.debugPlan);
                if (leaf == null)
                {
                    currentGoal = null;
                    continue;
                }

                var result = leaf.CalculatePath();
                if (currentPlan != null && currentPlan == result)
                {
                    currentGoal = null;
                    break;
                }
                if (result.Count == 0)
                {
                    currentGoal = null;
                    continue;
                }
                currentGoal.SetPlan(result);
                break;
            }
            Calculated = true;

            if (callback != null)
            {
                callback(currentGoal);
            }
            if (currentGoal != null)
            {
                ReGoapLogger.Log(string.Format("[ReGoapPlanner] Calculated plan for goal '{0}', plan length: {1}", currentGoal, currentGoal.GetPlan().Count));
                if (ReGoapLogger.Level == ReGoapLogger.DebugLevel.Full)
                {
                    int i = 0;
                    foreach (var action in currentGoal.GetPlan())
                    {
                        ReGoapLogger.Log(string.Format("[ReGoapPlanner] {0}) {1}", i++, action.Action));
                    }
                }
            }
            else
            {
                ReGoapLogger.LogWarning("[ReGoapPlanner] Error while calculating plan.");
            }
            return(currentGoal);
        }
Beispiel #18
0
 public virtual ReGoapState <T, W> InstantiateNewState()
 {
     return(ReGoapState <T, W> .Instantiate());
 }
Beispiel #19
0
 protected virtual void Awake()
 {
     reGoapState = ReGoapState.Instantiate();
 }
Beispiel #20
0
        private void Init(IGoapPlanner <T, W> planner, ReGoapState <T, W> newGoal, ReGoapNode <T, W> parent, IReGoapAction <T, W> action, ReGoapState <T, W> settings)
        {
            expandList.Clear();

            this.planner = planner;
            this.parent  = parent;
            this.action  = action;
            if (settings != null)
            {
                this.actionSettings = settings.Clone();
            }

            if (parent != null)
            {
                state = parent.GetState().Clone();
                // g(node)
                g = parent.GetPathCost();
            }
            else
            {
                state = planner.GetCurrentAgent().GetMemory().GetWorldState().Clone();
            }

            var nextAction = parent == null ? null : parent.action;

            if (action != null)
            {
                // create a new instance of the goal based on the paren't goal
                goal = ReGoapState <T, W> .Instantiate(newGoal);

                GoapActionStackData <T, W> stackData;
                stackData.currentState = state;
                stackData.goalState    = goal;
                stackData.next         = action;
                stackData.agent        = planner.GetCurrentAgent();
                stackData.settings     = actionSettings;

                var preconditions = action.GetPreconditions(stackData);
                var effects       = action.GetEffects(stackData);
                // addding the action's cost to the node's total cost
                g += action.GetCost(stackData);

                // adding the action's effects to the current node's state
                state.AddFromState(effects);

                // removes from goal all the conditions that are now fullfiled in the action's effects
                goal.ReplaceWithMissingDifference(effects);
                // add all preconditions of the current action to the goal
                goal.AddFromState(preconditions);
            }
            else
            {
                goal = newGoal;
            }
            h = goal.Count;
            // f(node) = g(node) + h(node)
            cost = g + h * heuristicMultiplier;

            // additionally calculate the goal without any world effect to understand if we are done
            var diff = ReGoapState <T, W> .Instantiate();

            goal.MissingDifference(planner.GetCurrentAgent().GetMemory().GetWorldState(), ref diff);
            goalMergedWithWorld = diff;
        }
Beispiel #21
0
        private void Init(ReGoapAgent agent, ReGoapState newGoalState, ReGoapNode parent, ReGoapAction action)
        {
            expandList.Clear();

            ReGoapState goal = null;

            this.reGoapAgent = agent;
            this.parentNode  = parent;
            this.action      = action;
            if (action != null)
            {
                actionSettings = action.GetSettings(newGoalState);
            }

            if (parentNode != null)
            {
                agentReGoapState = parentNode.GetState().Clone();
                g = parentNode.GetPathCost();
            }
            else
            {
                ReGoapState reGoapState = agent.GetWorldState();
                agentReGoapState = reGoapState.Clone();
            }

            if (action != null)
            {
                // create a new instance of the goal based on the paren't goal
                goal = ReGoapState.Instantiate(newGoalState);

                var preconditions = action.GetPreconditions(goal);
                var effects       = action.GetEffects(goal);
                // adding the action's effects to the current node's state
                agentReGoapState.AddFromState(effects);
                // addding the action's cost to the node's total cost
                g += action.GetCost();
                // add all preconditions of the current action to the goal
                goal.AddFromState(preconditions);
                // removes from goal all the conditions that are now fullfiled in the node's state
                goal.ReplaceWithMissingDifference(agentReGoapState);
            }
            else
            {
                goal = newGoalState.MissingDifference(agentReGoapState);
            }
            h    = goal.Count;
            cost = g + h;

            //Expand(goal);

            expandList.Clear();

            List <ReGoapAction> actionsList = reGoapAgent.GetActionsSet();

            for (var index = actionsList.Count - 1; index >= 0; index--)
            {
                ReGoapAction possibleAction = actionsList[index];

                if (!possibleAction.CheckProceduralCondition())  // 执行条件不满足排除掉
                {
                    continue;
                }

                ReGoapState precond = possibleAction.GetPreconditions(goal);
                ReGoapState effects = possibleAction.GetEffects(goal);

                if (!ReGoapState.HasAny(effects, goal)) // any effect is the current goal
                {
                    continue;
                }

                if (!ReGoapState.HasAnyConflict(precond, goal))
                {
                    ReGoapNode reGoapNode = new ReGoapNode(reGoapAgent, goal, this, possibleAction);
                    expandList.Add(reGoapNode);
                }
            }
        }
Beispiel #22
0
 public virtual ReGoapState <T, W> GetPreconditions(GoapActionStackData <T, W> stackData)
 {
     return(ReGoapState <T, W> .Instantiate());
 }
Beispiel #23
0
        public IReGoapGoal <T, W> Plan(IReGoapAgent <T, W> agent, IReGoapGoal <T, W> blacklistGoal = null, Queue <ReGoapActionState <T, W> > currentPlan = null, Action <IReGoapGoal <T, W> > callback = null)
        {
            goapAgent   = agent;
            Calculated  = false;
            currentGoal = null;
            var possibleGoals = new List <IReGoapGoal <T, W> >();

            foreach (var goal in goapAgent.GetGoalsSet())
            {
                if (goal == blacklistGoal)
                {
                    continue;
                }
                goal.Precalculations(this);
                if (goal.IsGoalPossible())
                {
                    possibleGoals.Add(goal);
                }
            }
            possibleGoals.Sort((x, y) => x.GetPriority().CompareTo(y.GetPriority()));

            var currentState = agent.GetMemory().GetWorldState();

            while (possibleGoals.Count > 0)
            {
                currentGoal = possibleGoals[possibleGoals.Count - 1];
                possibleGoals.RemoveAt(possibleGoals.Count - 1);
                var goalState = currentGoal.GetGoalState();

                // can't work with dynamic actions, of course
                if (!settings.UsingDynamicActions)
                {
                    var wantedGoalCheck = currentGoal.GetGoalState();
                    GoapActionStackData <T, W> stackData;
                    stackData.agent        = goapAgent;
                    stackData.currentState = currentState;
                    stackData.goalState    = goalState;
                    stackData.next         = null;
                    stackData.settings     = null;
                    // we check if the goal can be archived through actions first, so we don't brute force it with A* if we can't
                    foreach (var action in goapAgent.GetActionsSet())
                    {
                        action.Precalculations(stackData);
                        if (!action.CheckProceduralCondition(stackData))
                        {
                            continue;
                        }
                        // check if the effects of all actions can archieve currentGoal
                        var previous = wantedGoalCheck;
                        wantedGoalCheck = ReGoapState <T, W> .Instantiate();

                        previous.MissingDifference(action.GetEffects(stackData), ref wantedGoalCheck);
                    }
                    // finally push the current world state
                    var current = wantedGoalCheck;
                    wantedGoalCheck = ReGoapState <T, W> .Instantiate();

                    current.MissingDifference(GetCurrentAgent().GetMemory().GetWorldState(), ref wantedGoalCheck);
                    // can't validate goal
                    if (wantedGoalCheck.Count > 0)
                    {
                        currentGoal = null;
                        continue;
                    }
                }

                goalState = goalState.Clone();
                var leaf = (ReGoapNode <T, W>)astar.Run(
                    ReGoapNode <T, W> .Instantiate(this, goalState, null, null, null), goalState, settings.MaxIterations, settings.PlanningEarlyExit);
                if (leaf == null)
                {
                    currentGoal = null;
                    continue;
                }

                var result = leaf.CalculatePath();
                if (currentPlan != null && currentPlan == result)
                {
                    currentGoal = null;
                    break;
                }
                if (result.Count == 0)
                {
                    currentGoal = null;
                    continue;
                }
                currentGoal.SetPlan(result);
                break;
            }
            Calculated = true;

            if (callback != null)
            {
                callback(currentGoal);
            }
            return(currentGoal);
        }