protected virtual void Awake() { state = new BGoapState(); sensors = GetComponents <IReGoapSensor>(); foreach (var sensor in sensors) { sensor.Init(this); } availableSoList = new SmartObject[0]; }
public bool ValueEqualsUntyped(IStateVarKey thisKey, IStateVarKey otherKey, BGoapState otherState) { Type thisKeyType = thisKey.GetType(); Type otherKeyType = otherKey.GetType(); if (!thisKeyType.IsGenericType || !otherKeyType.IsGenericType || thisKeyType.GetGenericArguments()[0] != otherKeyType.GetGenericArguments()[0]) { throw new ArgumentException("underlying type is different for " + thisKey + " and " + otherKey); } return((bool)typeof(BGoapState).GetMethod("ValueEquals").MakeGenericMethod(thisKeyType.GetGenericArguments()[0]).Invoke(this, new object[] { thisKey, otherKey, otherState })); }
public override void UpdateSensor() { this.GetMemory().SetAvailableSoList(GameObject.FindObjectsOfType <SmartObject>()); this.GetMemory().SetAvailableItemList(GameObject.FindObjectsOfType <InGameItem>()); BGoapState worldState = GetMemory().GetWorldState(); worldState.Set(WorldStates.STATE_POSITION, transform.position); foreach (RPGSmartObjectSimpleState so in GameObject.FindObjectsOfType <RPGSmartObjectSimpleState>()) { worldState.Set(so.GetIndicatingWorldState(), so.isStateOn); } }
protected override IEnumerable <BGoapState> GetPossibleGenericVariableCombinations(IReGoapAgent goapAgent) { foreach (SmartObject so in (goapAgent.GetMemory() as GoapMemory).GetAvailableSoList()) { if (so is RPGSOTable) { BGoapState resultState = new BGoapState(); resultState.Set(table, so); yield return(resultState); } } }
public virtual IEnumerator Run(IReGoapAction previous, IReGoapAction next, IReGoapActionSettings settings, BGoapState goalState, Action <IReGoapAction> done, Action <IReGoapAction> fail) { interruptWhenPossible = false; enabled = true; doneCallback = done; failCallback = fail; previousAction = previous; nextAction = next; yield return(null); }
//TODO: check for value type public void SetFromKeyUntyped(IStateVarKey thisKey, IStateVarKey otherKey, BGoapState otherState) { values[thisKey] = otherState.values[otherKey]; Type thisKeyType = thisKey.GetType(); Type otherKeyType = otherKey.GetType(); if (!thisKeyType.IsGenericType || !otherKeyType.IsGenericType || thisKeyType.GetGenericArguments()[0] != otherKeyType.GetGenericArguments()[0]) { throw new ArgumentException("underlying type is different for " + thisKey + " and " + otherKey); } typeof(BGoapState).GetMethod("SetFromKey").MakeGenericMethod(thisKeyType.GetGenericArguments()[0]).Invoke(this, new object[] { thisKey, otherKey, otherState }); }
public override sealed BGoapState GetPreconditions(BGoapState goalState, IReGoapActionSettings settings, IReGoapAction next = null) { BGoapState variablePreconditions = GetPreconditionsFromGoal(goalState, settings as Settings); if (variablePreconditions == null || variablePreconditions.IsEmpty()) { return(staticPreconditions); } else { return(staticPreconditions.Union(variablePreconditions)); } }
/// <summary> /// Adds two extended states together. returns new extended states. respects WorldStateLogic /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public float Distance(BGoapState from) { float distance = 0; foreach (var pair in values) { if (from.HasKey(pair.Key)) { distance += pair.Key.Distance(from.values[pair.Key], values[pair.Key]); } else { distance += pair.Key.Distance(pair.Key.GetDefaultValue(), values[pair.Key]); } } return(distance); }
/// <summary> /// Creates a new Effects set based on parametrized world states /// </summary> /// <param name="goalState"></param> /// <returns></returns> protected BGoapState ExtractEffectsFromGoal(BGoapState goalState) { BGoapState newState = new BGoapState(staticEffects); foreach (IStateVarKey state in parametrizedEffectsWithDefaults) { if (goalState.HasKey(state)) { newState.SetFrom(state, goalState); } else { newState.SetFrom(state, parametrizedEffectsWithDefaults); } } return(newState); }
/// <summary> /// Tests if this state has at least one value that fulfills goal's variable /// </summary> /// <param name="goal"></param> /// <returns></returns> public bool DoesFullfillGoal(BGoapState goal) { lock (values) lock (goal.values) { foreach (var pair in values) { if (goal.HasKey(pair.Key)) { if (pair.Key.Logic.Satisfies(pair.Value, goal.values[pair.Key])) //if variable gets canceled out, it means that it fulfilled goal { return(true); } } } return(false); } }
public override bool LockInValues(BGoapState lockedInValues, BGoapState goalState) { if (goalState.HasKey(key)) { //set locked in values if (lockedInValues.HasKey(variableAsParameter)) { if (lockedInValues.ValueEquals(variableAsParameter, key, goalState)) { //clash on variable value return(false); } } else { lockedInValues.SetFromKey(variableAsParameter, key, goalState); } } return(true); //we are fixed, nothing to lock in }
public void _3_Difference() { BGoapState eff = new BGoapState(); BGoapState goal = new BGoapState(); BGoapState difference; eff.Set(wsEqual, 4); goal.Set(wsEqual, 4); difference = goal.Difference(eff, false); Assert.IsFalse(difference.HasKey(wsEqual), "subtracting two identical EQUAL values"); eff.Clear(); eff.Set(wsEqual, 5); Assert.Throws <ArgumentException>(() => goal.Difference(eff, false), "subtracting two different EQUAL values"); eff.Clear(); goal.Clear(); goal.Set(wsAtLeast, 10); eff.Set(wsAtLeast, 5); difference = goal.Difference(eff, false); Assert.AreEqual(10, difference.Get(wsAtLeast), "At least, 10 \\ 5"); eff.Set(wsAtLeast, 15); difference = goal.Difference(eff, false); Assert.IsFalse(difference.HasKey(wsAtLeast), "At least, 10 \\ 5"); goal.Clear(); eff.Clear(); goal.Set(wsAtMost, 10); eff.Set(wsAtMost, 5); difference = goal.Difference(eff, false); Assert.IsFalse(difference.HasKey(wsAtMost), "At most, 10 \\ 5"); eff.Set(wsAtMost, 15); difference = goal.Difference(eff, false); Assert.AreEqual(10, difference.Get(wsAtMost), "At most, 10 \\ 5"); }
/// <summary> /// Tests for conflict with action that has given preconditions and effects. A conflict arises when effect sets an incompatible value, OR precondition sets an incompatible value and effect doesn't change it. /// If there is no conflict, then "this.Difference(effect) + precond" returns a valid state /// </summary> /// <param name="precond"></param> /// <param name="effects"></param> /// <returns></returns> public bool HasConflict(BGoapState precond, BGoapState effects) { //check effects foreach (var key in values.Keys) { if (effects.HasKey(key)) { if (key.Logic.IsConflict(values[key], effects.values[key])) { return(true); } } else if (precond.HasKey(key)) //only check precond, if this value was not changed { if (key.Logic.IsConflict(values[key], precond.values[key])) { return(true); } } } return(false); }
protected override IEnumerable <BGoapState> GetPossibleVariableCombinations(BGoapState lockInValues, IReGoapAgent goapAgent, BGoapState genericAssignments) { if (lockInValues.HasKey(itemVariable) && lockInValues.Get(itemVariable) == null) //this should be handled by place/drop item { yield break; } if (lockInValues.HasKey(itemVariable) && lockInValues.HasKey(itemTypeVariable)) //both item type and specific item are locked in { if (lockInValues.Get(itemVariable).sourceItem == lockInValues.Get(itemTypeVariable)) //check that this combination is valid { BGoapState assignment = new BGoapState(); assignment.Set(locationVariable, lockInValues.Get(itemVariable).positionCache); yield return(assignment); } } else if (lockInValues.HasKey(itemVariable) && lockInValues.Get(itemVariable) != null) //specific item locked in, fill in it's values { BGoapState assignment = new BGoapState(); assignment.Set(itemTypeVariable, lockInValues.Get(itemVariable).sourceItem); assignment.Set(locationVariable, lockInValues.Get(itemVariable).positionCache); yield return(assignment); } else if (lockInValues.HasKey(itemTypeVariable)) //item type locked in, fill in all possible items { DBItem requiredItemType = lockInValues.Get(itemTypeVariable); foreach (InGameItem item in (goapAgent.GetMemory() as GoapMemory).GetAvailableItemList()) { if (item.sourceItem == requiredItemType) { BGoapState assignment = new BGoapState(); assignment.Set(itemVariable, item); assignment.Set(locationVariable, item.positionCache); yield return(assignment); } } } yield break; }
/// <summary> /// A ∪ B // for each variable v in both A and B, resulting set contains v( A) + v( B) // for each value in either A or B, resulting set contains either v( A) or v( B) respectively /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public BGoapState Union(BGoapState b) { BGoapState result; lock ( values) { result = new BGoapState(this); } lock (b.values) { foreach (var pair in b.values) { if (values.ContainsKey(pair.Key)) //value is contained in both a and b { result.values[pair.Key] = pair.Key.Logic.Add(values[pair.Key], b.values[pair.Key]); // use this key's logic to combine the two values } else { result.values[pair.Key] = pair.Value; //value was only in b } } return(result); } }
/// <summary> /// Calculates set difference between this state and the other. /// A ∖ B /// for each variable v in both A and B, resulting set contains v( A) if ¬(v( A)-v( B)) (if v( A)-v( B), then the resulting set doesn't contain v at all) /// for each variable v only in A, resulting set contains v( A) /// </summary> /// <param name="doUseDefaults">whether to use key defaults or not</param> /// <param name="other"></param> /// <returns></returns> public BGoapState Difference(BGoapState other, bool doUseDefaults) { BGoapState result = new BGoapState(); lock (values) lock (other.values) { foreach (var key in values.Keys) { if (other.HasKey(key)) //value exists { if (!key.Logic.Satisfies(other.values[key], values[key])) { result.values.Add(key, values[key]); } } else if (!(doUseDefaults && key.Logic.Satisfies(key.GetDefaultValue(), values[key]))) { result.values.Add(key, values[key]); } } } return(result); }
/* * private IEnumerable<IReGoapActionSettings> GenerateAllPossibleActions(IReGoapAgent goapAgent, BGoapState goalState, BGoapState genericsAssignement) { * * //this is not a real state, just a container for variables * BGoapState lockedInValues = new BGoapState(); * * BGoapState effects = staticEffects.Clone() as BGoapState; * List<IStateVarKey> freeEffects = new List<IStateVarKey>(); * //set effects * foreach (IStateVarKey iteratorKey in parametrizedEffects.Keys) * { * IStateVarKey key;// if key is a template, use it's appropriate child instead * if (iteratorKey is IGenericStateVarKeyTemplate) //appropriate child is such, that has generic argument in accordance with genericsAssignement * key = (iteratorKey as IGenericStateVarKeyTemplate).MakeGenericInstance(genericsAssignement.Get(genericParameters[iteratorKey])); * else * key = iteratorKey; * * IStateVarKey variableKey = parametrizedEffects[iteratorKey]; * if (goalState.HasKey(key)) * { * //set locked in values * if (lockedInValues.HasKey(variableKey)) * { * if (lockedInValues.ValueEqualsUntyped(variableKey, key, goalState)) * { //clash on variable value * continue; * } * } * else * { * lockedInValues.SetFromKeyUntyped(variableKey, key, goalState); * } * effects.SetFrom(key, goalState); * } * else * { * freeEffects.Add(key); * } * } * * BGoapState preconditions = staticPreconditions.Clone() as BGoapState; * * List<IStateVarKey> freePreconditions = new List<IStateVarKey>(); * foreach (IStateVarKey iteratorKey in parametrizedPreconditions.Keys) * { * IStateVarKey key;// if key is a template, use it's appropriate child instead * if (iteratorKey is IGenericStateVarKeyTemplate) //appropriate child is such, that has generic argument in accordance with genericsAssignement * key = (iteratorKey as IGenericStateVarKeyTemplate).MakeGenericInstance(genericsAssignement.Get(genericParameters[iteratorKey])); * else * key = iteratorKey; * * IStateVarKey variableKey = parametrizedPreconditions[iteratorKey]; * if (lockedInValues.HasKey(variableKey)) * { * preconditions.SetFromKeyUntyped(key, variableKey, lockedInValues); * } * else * { * freePreconditions.Add(key); * } * } * * if (freeEffects.Count + freePreconditions.Count > 0) //some variables need to be searched * { * foreach (BGoapState assignment in GetPossibleVariableCombinations(lockedInValues, goapAgent)) * { * BGoapState finalEffects = effects.Clone() as BGoapState; * BGoapState finalPreconditions = preconditions.Clone() as BGoapState; * foreach (IStateVarKey key in freeEffects) * { * IStateVarKey variableKey = parametrizedEffects[key]; * finalEffects.SetFromKeyUntyped(key, variableKey, assignment); * } * foreach (IStateVarKey key in freePreconditions) * { * IStateVarKey variableKey = parametrizedPreconditions[key]; * finalPreconditions.SetFromKeyUntyped(key, variableKey, assignment); * } * yield return new PrototypeActionSettings { effects = finalEffects, preconditions = finalPreconditions, agent = goapAgent }; * } * } * else * { //all variables locked in * yield return new PrototypeActionSettings { effects = effects, preconditions = preconditions, agent = goapAgent }; * } * * } */ public override IEnumerable <IReGoapActionSettings> MultiPrecalculations(IReGoapAgent goapAgent, BGoapState goalState) { foreach (BGoapState genericAssignments in GetPossibleGenericVariableCombinations(goapAgent)) { /// generate all possible generic assignemnts GoapStateEntry[] processedEffects = effects.Select(x => x.GenNongenericVersion(genericAssignments)).ToArray(); GoapStateEntry[] processedPreconditions = preconditions.Select(x => x.GenNongenericVersion(genericAssignments)).ToArray(); //lock in values that are in goal BGoapState lockedInValues = new BGoapState(); foreach (GoapStateEntry effect in processedEffects) { effect.LockInValues(lockedInValues, goalState); } //generate all actions available for given locked values foreach (BGoapState assignments in GetPossibleVariableCombinations(lockedInValues, goapAgent, genericAssignments)) { BGoapState combined = new BGoapState(assignments).Union(lockedInValues); //union should work here, as lockedInValues and assignemets should be mutually exclusive BGoapState generatedPreconditions = new BGoapState(); BGoapState generatedEffects = new BGoapState(); foreach (GoapStateEntry entry in processedPreconditions) { entry.AddSelfToState(generatedPreconditions, combined); } foreach (GoapStateEntry entry in processedEffects) { entry.AddSelfToState(generatedEffects, combined); } yield return(new PrototypeActionSettings { effects = generatedEffects, preconditions = generatedPreconditions, genericAssignments = genericAssignments, agent = goapAgent }); } } }
public void _4_ChainOperations() { BGoapState goal = new BGoapState(); goal.Set(wsEqual, 10); goal.Set(wsAtLeast, 25); goal.Set(wsAtMost, 4); BGoapState eff4 = new BGoapState(); eff4.Set(wsAtLeast, 20); eff4.Set(wsAtMost, 2); var preEff4 = goal.Difference(eff4, false); BGoapState eff3 = new BGoapState(); eff3.Set(wsEqual, 10); var preEff3 = preEff4.Difference(eff3, false); BGoapState eff2 = new BGoapState(); eff2.Set(wsAtLeast, 40); eff2.Set(wsAtMost, 15); var preEff2 = preEff3.Difference(eff2, false); Assert.IsFalse(preEff2.HasKey(wsAtMost), "initial set contains wsAtMost"); Assert.IsFalse(preEff2.HasKey(wsAtLeast), "initial set contains wsAtLeast"); Assert.IsFalse(preEff2.HasKey(wsEqual), "initial set contains wsEqual"); var reconstructedGoal = preEff2.Union(eff2).Union(eff3).Union(eff4); Assert.AreEqual(10, reconstructedGoal.Get(wsEqual), "reconstructed goal EQUAL test"); Assert.IsTrue(reconstructedGoal.Get(wsAtLeast) >= 25, "reconstructed goal AT_LEAST test"); Assert.IsTrue(reconstructedGoal.Get(wsAtMost) <= 4, "reconstructed goal AT_MOST test"); }
public object Clone() { var clone = new BGoapState(this); return(clone); }
public abstract IEnumerator Run(IReGoapAction previousAction, IReGoapAction nextAction, IReGoapActionSettings settings, BGoapState goalState, Action <IReGoapAction> done, Action <IReGoapAction> fail);
public void SetEffects(BGoapState effects) { this.effects = effects; }
public void SetPreconditions(BGoapState preconditions) { this.preconditions = preconditions; }
public abstract bool CheckProceduralCondition(IReGoapAgent goapAgent, IReGoapActionSettings settings, BGoapState goalState, IReGoapAction nextAction = null);
protected override IEnumerable <BGoapState> GetPossibleVariableCombinations(BGoapState lockInValues, IReGoapAgent goapAgent, BGoapState genericAssignments) { BGoapState assignment = new BGoapState(); assignment.Set(locationVariable, genericAssignments.Get(table).positionCache); yield return(assignment); }
public bool ValueEquals <T>(AStateVarKey <T> thisKey, AStateVarKey <T> otherKey, BGoapState otherState) { return(HasKey(thisKey) && otherState.HasKey(otherKey) && values[thisKey] == otherState.values[otherKey]); }
protected override void InitializePreconditionsAndEffects(BGoapState staticEffects, ref BGoapState parametrizedEffects, BGoapState staticPreconditions) { parametrizedEffects.Set(WorldStates.STATE_FLOAT_SATURATION, 0); //we know nothing about current saturation, so we can't promise anything parametrizedEffects.Set(WorldStateMinItemCategory.GetStateForItem(foodCategory), 0); //probably not required, set default to 0 }
public void SetFromKey <T>(AStateVarKey <T> thisKey, AStateVarKey <T> otherKey, BGoapState otherState) { values[thisKey] = otherState.values[otherKey]; }
public override sealed IEnumerator Run(IReGoapAction previousAction, IReGoapAction nextAction, IReGoapActionSettings settingsParam, BGoapState goalState, Action <IReGoapAction> done, Action <IReGoapAction> fail) { Settings settings = settingsParam as Settings; IEnumerator <SimpleActionExecutionControlElements> progress = Execute(settings, () => { fail(this); }); while (progress.MoveNext()) { if (settings.interruptNextChanceYouHave && progress.Current != SimpleActionExecutionControlElements.CANNOT_INTERRUPT) { done(this); yield break; } if (progress.Current == SimpleActionExecutionControlElements.WAIT_NEXT_FRAME) { yield return(new WaitForFixedUpdate()); } yield return(progress.Current); } done(this); }
public void SetFrom(IStateVarKey state, BGoapState otherState) { values[state] = otherState.values[state]; }
public BGoapState(BGoapState old) { lock (old.values) values = new Dictionary <IStateVarKey, object>(old.values); }