예제 #1
0
 // keep only missing differences in values
 public int ReplaceWithMissingDifference(GoapState <T, W> other, int stopAt = int.MaxValue, Func <KeyValuePair <T, W>, W, bool> predicate = null, bool test = false)
 {
     lock (values)
     {
         var count  = 0;
         var buffer = values;
         values = values == bufferA ? bufferB : bufferA;
         values.Clear();
         foreach (var pair in buffer)
         {
             W otherValue;
             other.values.TryGetValue(pair.Key, out otherValue);
             if (!Equals(pair.Value, otherValue) && (predicate == null || predicate(pair, otherValue)))
             {
                 count++;
                 values[pair.Key] = pair.Value;
                 if (count >= stopAt)
                 {
                     break;
                 }
             }
         }
         return(count);
     }
 }
예제 #2
0
 // write differences in "difference"
 public int MissingDifference(GoapState <T, W> other, ref GoapState <T, W> difference, int stopAt = int.MaxValue, Func <KeyValuePair <T, W>, W, bool> predicate = null, bool test = false)
 {
     lock (values)
     {
         var count = 0;
         foreach (var pair in values)
         {
             W otherValue;
             other.values.TryGetValue(pair.Key, out otherValue);
             if (!Equals(pair.Value, otherValue) && (predicate == null || predicate(pair, otherValue)))
             {
                 count++;
                 if (difference != null)
                 {
                     difference.values[pair.Key] = pair.Value;
                 }
                 if (count >= stopAt)
                 {
                     break;
                 }
             }
         }
         return(count);
     }
 }
예제 #3
0
 public void AddFromState(GoapState <T, W> b)
 {
     lock (values) lock (b.values)
         {
             foreach (var pair in b.values)
             {
                 values[pair.Key] = pair.Value;
             }
         }
 }
예제 #4
0
 private void Init(GoapState <T, W> old)
 {
     values.Clear();
     if (old != null)
     {
         lock (old.values)
         {
             foreach (var pair in old.values)
             {
                 values[pair.Key] = pair.Value;
             }
         }
     }
 }
예제 #5
0
        public static GoapState <T, W> Instantiate(GoapState <T, W> old = null)
        {
            GoapState <T, W> state;

            if (cachedStates == null)
            {
                cachedStates = new Stack <GoapState <T, W> >();
            }
            lock (cachedStates)
            {
                state = cachedStates.Count > 0 ? cachedStates.Pop() : new GoapState <T, W>();
            }
            state.Init(old);
            return(state);
        }
예제 #6
0
 public bool HasAny(GoapState <T, W> other)
 {
     lock (values) lock (other.values)
         {
             foreach (var pair in other.values)
             {
                 W thisValue;
                 values.TryGetValue(pair.Key, out thisValue);
                 if (Equals(thisValue, pair.Value))
                 {
                     return(true);
                 }
             }
             return(false);
         }
 }
예제 #7
0
 public int MissingDifference(GoapState <T, W> other, int stopAt = int.MaxValue)
 {
     lock (values)
     {
         var count = 0;
         foreach (var pair in values)
         {
             W otherValue;
             other.values.TryGetValue(pair.Key, out otherValue);
             if (!Equals(pair.Value, otherValue))
             {
                 count++;
                 if (count >= stopAt)
                 {
                     break;
                 }
             }
         }
         return(count);
     }
 }
예제 #8
0
        public bool HasAnyConflict(GoapState <T, W> other) // used only in backward for now
        {
            lock (values) lock (other.values)
                {
                    foreach (var pair in other.values)
                    {
                        var otherValue = pair.Value;

                        // not here, ignore this check
                        W thisValue;
                        if (!values.TryGetValue(pair.Key, out thisValue))
                        {
                            continue;
                        }
                        if (!Equals(otherValue, thisValue))
                        {
                            return(true);
                        }
                    }
                    return(false);
                }
        }
예제 #9
0
        // this method is more relaxed than the other, also accepts conflits that are fixed by "changes"
        public bool HasAnyConflict(GoapState <T, W> changes, GoapState <T, W> other)
        {
            lock (values) lock (other.values)
                {
                    foreach (var pair in other.values)
                    {
                        var otherValue = pair.Value;

                        // not here, ignore this check
                        W thisValue;
                        if (!values.TryGetValue(pair.Key, out thisValue))
                        {
                            continue;
                        }
                        W effectValue;
                        changes.values.TryGetValue(pair.Key, out effectValue);
                        if (!Equals(otherValue, thisValue) && !Equals(effectValue, thisValue))
                        {
                            return(true);
                        }
                    }
                    return(false);
                }
        }
예제 #10
0
        public IGoapGoal <T, W> Plan(IGoapAgent <T, W> agent, IGoapGoal <T, W> blacklistGoal = null, Queue <GoapActionState <T, W> > currentPlan = null, Action <IGoapGoal <T, W> > callback = null)
        {
            if (GoapLogger.Level == GoapLogger.DebugLevel.Full)
            {
                GoapLogger.Log("[ReGoalPlanner] Starting planning calculation for agent: " + agent);
            }
            goapAgent   = agent;
            Calculated  = false;
            currentGoal = null;
            var possibleGoals = new List <IGoapGoal <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 = GoapState <T, W> .Instantiate();

                        previous.MissingDifference(action.GetEffects(stackData), ref wantedGoalCheck);
                    }
                    // finally push the current world state
                    var current = wantedGoalCheck;
                    wantedGoalCheck = GoapState <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 = (GoapNode <T, W>)astar.Run(
                    GoapNode <T, W> .Instantiate(this, goalState, null, null, null), goalState, settings.MaxIterations, settings.PlanningEarlyExit, debugPlan: settings.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;

            callback?.Invoke(currentGoal);

            if (currentGoal != null)
            {
                GoapLogger.Log(string.Format("[ReGoapPlanner] Calculated plan for goal '{0}', plan length: {1}", currentGoal, currentGoal.GetPlan().Count));
                if (GoapLogger.Level == GoapLogger.DebugLevel.Full)
                {
                    int i = 0;
                    GoapActionStackData <T, W> stackData;
                    stackData.agent        = agent;
                    stackData.currentState = currentState;
                    stackData.goalState    = currentGoal.GetGoalState();
                    stackData.next         = null;
                    foreach (var action in currentGoal.GetPlan())
                    {
                        stackData.settings = action.Settings;
                        GoapLogger.Log(string.Format("[ReGoapPlanner] {0}) {1}", i++, action.Action.ToString(stackData)));
                    }
                }
            }
            else
            {
                GoapLogger.LogWarning("[ReGoapPlanner] Error while calculating plan.");
            }
            return(currentGoal);
        }