public void Throw_An_Exception_If_User_Tries_To_Iterate_Over_Behaviours_With_A_Null_Delegate() { var fsm = new HierarchicalStateMachine <int, int>(); Assert.Throws <ArgumentNullException>(() => fsm.ForeachBehaviour(null)); Assert.Throws <ArgumentNullException>(() => fsm.ForeachBehaviourOn(1, null)); }
public void Remove_Behaviours_From_Behavioural_States() { var fsm = new HierarchicalStateMachine <int, int>(); var stateBehaviour1 = Substitute.For <IStateBehaviour>(); var stateBehaviour2 = Substitute.For <IStateBehaviour>(); fsm.AddWithBehaviours(1, stateBehaviour1, stateBehaviour2); fsm.RemoveBehaviourFrom(1, stateBehaviour1); Assert.IsTrue(fsm.BehaviourCount() == 1); Assert.IsTrue(fsm.BehaviourCountOf(1) == 1); Assert.IsFalse(fsm.ContainsBehaviour(stateBehaviour1)); Assert.IsFalse(fsm.ContainsBehaviourOn(1, stateBehaviour1)); Assert.IsTrue(fsm.ContainsBehaviour(stateBehaviour2)); Assert.IsTrue(fsm.ContainsBehaviourOn(1, stateBehaviour2)); fsm.RemoveBehaviourFrom(1, stateBehaviour2); Assert.IsTrue(fsm.BehaviourCount() == 0); Assert.IsTrue(fsm.BehaviourCountOf(1) == 0); Assert.IsFalse(fsm.ContainsBehaviour(stateBehaviour2)); Assert.IsFalse(fsm.ContainsBehaviourOn(1, stateBehaviour2)); }
public void Enter_Update_And_Exit_Behaviours() { var fsm = new HierarchicalStateMachine <int, int>(); var stateBehaviour1 = Substitute.For <IStateBehaviour>(); var stateBehaviour2 = Substitute.For <IStateBehaviour>(); fsm.AddWithBehaviours(1, stateBehaviour1, stateBehaviour2); fsm.InitialState = 1; fsm.Start(); stateBehaviour1.Received(1).OnEnter(); stateBehaviour2.Received(1).OnEnter(); fsm.Update(); stateBehaviour1.Received(1).OnUpdate(); stateBehaviour2.Received(1).OnUpdate(); fsm.Stop(); stateBehaviour1.Received(1).OnExit(); stateBehaviour2.Received(1).OnExit(); }
private void BuildBehaviouralStates <TState, TTrigger>(HierarchicalStateMachine <TState, TTrigger> stateMachine) { var states = stateMachine.GetStates(); if (states != null) { for (int i = 0; i < states.Length; i++) { var stateObject = stateMachine.GetStateById(states[i]); if (stateObject is ScriptableBehaviouralState behaviouralState) { var serializedBehaviours = behaviouralState.GetSerializedBehaviours(); foreach (ScriptableStateBehaviour behaviour in serializedBehaviours) { var currentBehaviour = behaviour; if (currentBehaviour.InstantiateThis) { currentBehaviour = Instantiate(behaviour); } behaviouralState.AddBehaviour(currentBehaviour); stateMachine.SubscribeEventHandlerTo(states[i], currentBehaviour); } } } } }
public void Throw_An_Exception_If_User_Asks_If_Contains_Behaviour_With_A_Null_Behaviour() { var fsm = new HierarchicalStateMachine <int, int>(); Assert.Throws <ArgumentNullException>(() => fsm.ContainsBehaviour(null)); Assert.Throws <ArgumentNullException>(() => fsm.ContainsBehaviourOn(1, null)); }
private void AddTransitionsAndGuardConditions <TState, TTrigger>(HierarchicalStateMachine <TState, TTrigger> stateMachine) { if (_transitions.Count > 0) { for (int i = 0; i < _transitions.Count; i++) { var current = _transitions[i]; TState stateFrom = (TState)current.StateFrom; TState stateTo = (TState)current.StateTo; TTrigger trigger = (TTrigger)current.Trigger; var transition = new Transition <TState, TTrigger>(stateFrom, trigger, stateTo); stateMachine.AddTransition(transition); for (int j = 0; j < current.GuardConditions.Length; j++) { IGuardCondition guardCondition; if (current.GuardConditions[j].InstantiateThis) { guardCondition = Instantiate(current.GuardConditions[j]); } else { guardCondition = current.GuardConditions[j]; } stateMachine.AddGuardConditionTo(transition, guardCondition); } } } }
private void ShowMachineData <TState, TTrigger>(HierarchicalStateMachine <TState, TTrigger> stateMachine) { var states = stateMachine.GetStates(); Debug.Log("State count: " + stateMachine.StateCount); Debug.Log("Initial State: " + stateMachine.InitialState); if (states != null) { foreach (var state in states) { Debug.Log(state); var eventHandlers = stateMachine.GetEventHandlersOf(state); if (eventHandlers != null) { Debug.Log("State " + state + " contains " + eventHandlers.Length + " event handlers"); } var childs = stateMachine.GetImmediateChildsOf(state); if (childs != null) { foreach (var child in childs) { Debug.Log("Child state: " + child); } Debug.Log("Initial Child: " + stateMachine.GetInitialStateOf(state)); } } var transitions = stateMachine.GetTransitions(); if (transitions != null) { foreach (var transition in transitions) { Debug.Log("Transition: " + transition.StateFrom + " -> " + transition.Trigger + " -> " + transition.StateTo); var guardConditions = stateMachine.GetGuardConditionsOf(transition); if (guardConditions != null) { Debug.Log("Guard conditions count: " + guardConditions.Length); } else { Debug.Log("Guard conditions count: " + 0); } } } } }
public void Return_Behaviour_Of_Specific_Type_From_Specific_State() { var fsm = new HierarchicalStateMachine <int, int>(); var stateBehaviour = new TestStateBehaviour(); fsm.AddWithBehaviours(1, stateBehaviour); Assert.AreEqual(stateBehaviour, fsm.GetBehaviourOf <TestStateBehaviour, int, int>(1)); }
private HierarchicalStateMachine <TState, TTrigger> Build <TState, TTrigger>() { var stateMachine = new HierarchicalStateMachine <TState, TTrigger>(); AddStates(stateMachine); BuildBehaviouralStates(stateMachine); AddTransitionsAndGuardConditions(stateMachine); SetParentConnections(stateMachine); return(stateMachine); }
public void Do_Nothing_If_User_Tries_To_Add_The_Same_Behaviour_On_The_Same_State_Twice() { var fsm = new HierarchicalStateMachine <int, int>(); var stateBehaviour1 = Substitute.For <IStateBehaviour>(); fsm.AddWithBehaviours(1); fsm.AddBehaviourTo(1, stateBehaviour1); Assert.DoesNotThrow(() => fsm.AddBehaviourTo(1, stateBehaviour1)); Assert.IsTrue(fsm.BehaviourCount() == 1); }
public void Add_Behaviour_To_Behavioural_States() { var fsm = new HierarchicalStateMachine <int, int>(); var stateBehaviour1 = Substitute.For <IStateBehaviour>(); fsm.AddWithBehaviours(1); fsm.AddBehaviourTo(1, stateBehaviour1); Assert.IsTrue(fsm.ContainsBehaviour(stateBehaviour1)); }
public void Throw_An_Exception_If_User_Tries_To_Add_A_Null_Behaviour() { var fsm = new HierarchicalStateMachine <int, int>(); var stateBehaviour1 = Substitute.For <IStateBehaviour>(); Assert.Throws <ArgumentNullException>(() => fsm.AddWithBehaviours(1, stateBehaviour1, null)); fsm.AddWithBehaviours(1); Assert.Throws <ArgumentNullException>(() => fsm.AddBehaviourTo(1, null)); Assert.Throws <ArgumentNullException>(() => fsm.AddBehavioursTo(1, stateBehaviour1, null)); }
public void Return_Behaviours_Of_Specific_Type_From_Specific_Behavioural_State() { var fsm = new HierarchicalStateMachine <int, int>(); var stateBehaviour1 = new TestStateBehaviour(); var stateBehaviour2 = new TestStateBehaviour(); var stateBehaviour3 = Substitute.For <IStateBehaviour>(); fsm.AddWithBehaviours(1, stateBehaviour1, stateBehaviour2, stateBehaviour3); var behaviors = fsm.GetBehavioursOf <TestStateBehaviour, int, int>(1); Assert.IsTrue(behaviors.Length == 2); Assert.IsTrue(behaviors.Contains(stateBehaviour1)); Assert.IsTrue(behaviors.Contains(stateBehaviour2)); }
private void SetParentConnections <TState, TTrigger>(HierarchicalStateMachine <TState, TTrigger> stateMachine) { if (_parentConnections.Count > 0) { for (int i = 0; i < _parentConnections.Count; i++) { var current = _parentConnections[i]; var parentId = (TState)current.ParentStateId; var initialChildId = (TState)current.InitialChildId; var childs = Array.ConvertAll(current.GetChilds(), objectId => (TState)objectId); for (int j = 0; j < childs.Length; j++) { stateMachine.AddChildTo(parentId, childs[j]); } stateMachine.SetInitialStateTo(parentId, initialChildId); } } }
public void Add_Behavioural_States() { var fsm = new HierarchicalStateMachine <int, int>(); var behaviouralState1 = fsm.AddWithBehaviours(1); Assert.IsTrue(fsm.ContainsState(1)); Assert.IsTrue(fsm.GetStateById(1) == behaviouralState1); IStateBehaviour stateBehaviour1 = Substitute.For <IStateBehaviour>(); IStateBehaviour stateBehaviour2 = Substitute.For <IStateBehaviour>(); var behaviouralState2 = fsm.AddWithBehaviours(2, stateBehaviour1, stateBehaviour2); Assert.IsTrue(fsm.ContainsState(2)); Assert.IsTrue(fsm.GetStateById(2) == behaviouralState2); Assert.IsTrue(fsm.ContainsBehaviour(stateBehaviour1)); Assert.IsTrue(fsm.ContainsBehaviour(stateBehaviour2)); Assert.IsTrue(fsm.BehaviourCount() == 2); Assert.IsTrue(fsm.BehaviourCountOf(2) == 2); }
public void Iterate_Over_All_Behaviours() { var fsm = new HierarchicalStateMachine <int, int>(); var stateBehaviour1 = Substitute.For <IStateBehaviour>(); var stateBehaviour2 = Substitute.For <IStateBehaviour>(); fsm.AddWithBehaviours(1, stateBehaviour1, stateBehaviour2); var behaviours = new List <IStateBehaviour>(); behaviours.Add(stateBehaviour1); behaviours.Add(stateBehaviour2); fsm.ForeachBehaviour(behaviour => { behaviours.Remove(behaviour); return(false); }); Assert.IsTrue(behaviours.Count == 0); }
private void AddStates <TState, TTrigger>(HierarchicalStateMachine <TState, TTrigger> stateMachine) { if (_states.Count > 0) { for (int i = 0; i < _states.Count; i++) { var current = _states[i]; TState stateId = (TState)current.StateId; IState stateObject; if (current.StateObject != null) { if (current.StateObject.InstantiateThis) { stateObject = Instantiate(current.StateObject); } else { stateObject = current.StateObject; } } else { stateObject = new EmptyState(); } stateMachine.AddState(stateId, stateObject); if (stateObject is IStateEventHandler eventHandler) { stateMachine.SubscribeEventHandlerTo(stateId, eventHandler); } } stateMachine.InitialState = (TState)InitialStateId; } }
public void Throw_An_Exception_If_User_Tries_To_Remove_A_Null_Behaviour() { var fsm = new HierarchicalStateMachine <int, int>(); Assert.Throws <ArgumentNullException>(() => fsm.RemoveBehaviourFrom(1, null)); }
private void InitializeHsm() { // start by creating the states // fleer var stateFlock = new State("Flock"); var stateEvade = new State("Evade"); var stateHide = new State("Hide"); // chaser var stateWander = new State("Wander"); var statePursue = new State("Pursue"); _fleer = new HierarchicalStateMachine(stateFlock, "Fleer"); _fleer.States = new HashSet <IState> { stateFlock, stateEvade, stateHide }; // // FLOCK STATE // stateFlock.Parent = _fleer; // cache for performance var go = gameObject; // flock actions stateFlock.EntryActions = new HashSet <IAction> { new FlockEntryAction(go) }; stateFlock.ActiveActions = new HashSet <IAction> { new EmptyAction() }; stateFlock.ExitActions = new HashSet <IAction> { new FlockExitAction(go) }; var trFlockToHide = new Transition( 0, new HashSet <IAction> { new EmptyAction() }, stateHide, "Flock to Hide", new List <ICondition> { new HidingSpotNearby(), new ChaserNearby() }, go); var trFlockToEvade = new Transition( 0, new HashSet <IAction> { new EmptyAction() }, stateEvade, "Flock to Evade", new List <ICondition> { new NoHidingSpot(), new ChaserNearby() }, go); // flock transitions (from flock to somewhere) stateFlock.Transitions = new HashSet <ITransition> { trFlockToHide, trFlockToEvade }; // // HIDE STATE // stateHide.Parent = _fleer; // hide state actions // for hiding, we need to know from who we are hiding from, so the active action will be to find the closest one. stateHide.EntryActions = new HashSet <IAction> { new HideEntryAction(go) }; stateHide.ActiveActions = new HashSet <IAction> { new HideActiveAction(go) }; stateHide.ExitActions = new HashSet <IAction> { new HideExitAction(go) }; var trHideToFlock = new Transition( 0, new HashSet <IAction> { new EmptyAction() }, stateFlock, "Hide to Flock", new List <ICondition> { new NoChaserNearby() }, go); var trHideToEvade = new Transition( 0, new HashSet <IAction> { new EmptyAction() }, stateHide, "Hide to Evade", new List <ICondition> { new ChaserNearby(), new NoHidingSpot() }, go); // hide state transitions stateHide.Transitions = new HashSet <ITransition> { trHideToEvade, trHideToFlock }; // // EVADE STATE // stateEvade.Parent = _fleer; // for hiding, we need to know from how we are hiding from, so the active action will be to find the closest one. stateEvade.EntryActions = new HashSet <IAction> { new EvadeEntryAction(go) }; stateEvade.ActiveActions = new HashSet <IAction> { new HideActiveAction(go) }; stateEvade.ExitActions = new HashSet <IAction> { new EvadeExitActions(go) }; var trEvadeToFlock = new Transition( 0, new HashSet <IAction> { new EmptyAction() }, stateFlock, "Evade to Flock", new List <ICondition> { new NoChaserNearby() }, go); var trEvadeToHide = new Transition( 0, new HashSet <IAction> { new EmptyAction() }, stateHide, "Evade to Hide", new List <ICondition> { new ChaserNearby(), new HidingSpotNearby() }, go); stateEvade.Transitions = new HashSet <ITransition> { trEvadeToHide, trEvadeToFlock }; // evade state actions // for evading, we need to know from how we are hiding from, so the active action will be to find the closest one. _chaser = new HierarchicalStateMachine(stateWander, "Chaser"); }
/// <summary> /// Initializes the <see cref="HierarchicalStateMachine"/> for this <see cref="GoapAgent"/>. It has 3 states: Planning, Moving or Acting. Every state can transition to every other state. Check the conditions to see what triggers transitions: <see cref="NeedToMoveCondition"/>, <see cref="NeedNewPlanCondition"/> and <see cref="ReadyToPerformActionCondition"/>. /// </summary> private void InitializeHsm() { //print("initializing hsm"); // create the states var statePlanning = new State("Planning") { ActiveActions = new HashSet <IAction> { new PlanAction(_planner, _dataProvider, this) }, ExitActions = new HashSet <IAction>() // no exit actions }; var stateMoving = new State("Moving") { ActiveActions = new HashSet <IAction> { new MoveToAction(this, _dataProvider) }, ExitActions = new HashSet <IAction>() // no exit actions }; var stateActing = new State("Acting") { ActiveActions = new HashSet <IAction> { new PerformActionAction(this, _dataProvider) }, ExitActions = new HashSet <IAction>() // no exit actions }; // create the state machine and add the states to it _hsm = new HierarchicalStateMachine(statePlanning, "goap hsm") { States = new HashSet <IState> { statePlanning, stateMoving, stateActing }, ActiveActions = new HashSet <IAction>(), // no active actions EntryActions = new HashSet <IAction>(), // no entry actions ExitActions = new HashSet <IAction>() // no exit actions }; // inform the states which is the state machine they belong to statePlanning.Parent = _hsm; stateMoving.Parent = _hsm; stateActing.Parent = _hsm; // initialize the transtion conditions var needToMoveCondition = new NeedToMoveCondition(); var needNewPlanCondition = new NeedNewPlanCondition(); var readyToActCondition = new ReadyToPerformActionCondition(); // define the conditions var transPlanToMoveTo = new Transition( 0, // should always be zero for a single layer state machine new HashSet <IAction>(), stateMoving, "transPlanToMoveTo", new List <ICondition> { needToMoveCondition }, this); var transPlanToAct = new Transition( 0, new HashSet <IAction>(), stateActing, "transPlanToAct", new List <ICondition> { readyToActCondition }, this); var transMoveToAct = new Transition( 0, new HashSet <IAction>(), stateActing, "transMoveToAct", new List <ICondition> { readyToActCondition }, this); var transActToMove = new Transition( 0, new HashSet <IAction>(), stateMoving, "transActToMove", new List <ICondition> { needToMoveCondition }, this); var transActToPlan = new Transition( 0, new HashSet <IAction>(), statePlanning, "transActToPlan", new List <ICondition> { needNewPlanCondition }, this); var transMoveToPlan = new Transition( 0, new HashSet <IAction>(), statePlanning, "transMoveToPlan", new List <ICondition> { needNewPlanCondition }, this); // add the conditions to each state statePlanning.Transitions = new HashSet <ITransition> { transPlanToMoveTo, transPlanToAct }; stateMoving.Transitions = new HashSet <ITransition> { transMoveToPlan, transMoveToAct }; stateActing.Transitions = new HashSet <ITransition> { transActToMove, transActToPlan }; }
void AttachLionHFSM() { // hunt deer sub macine state //////////////////////////// State wanderState = new State("wander deer", new WanderAction()); State hideState = new State("hide deer", new SetTargetToClosestBush(), new GoToBushAction(), new emptyAction()); State waitState = new State("wait for deer", new emptyAction(), new WaitInBushAction(false), new emptyVisibleAction()); State pounceState = new State("pounce deer", new SetLionTargetToDeerAction(), new PounceAction(), new emptyAction()); pounceState.entryActions.Add(new emptyVisibleAction()); State eatState = new State("eat", new KillDeerAction(), new EatAction(), new emptyAction()); State napState = new State("nap", new NapAction()); State creepState = new State("creep deer", new CreepDeerAction()); State chaseState = new State("chase deer", new ChaseDeerAction()); Transition arriveAtBush = new Transition(new ReachedBush(), waitState, -1); Transition waitToPounce = new Transition(new AndCondition(new TimerCondition(200), new DeerInRangeCondition(RangeToPounce)), pounceState, -1); Transition pounceToKill = new Transition(new ReachedDeerTarget(KillRange), eatState, -1); Transition pounceToWander = new Transition(new ReachedPounceTarget(30), wanderState, -1); Transition pounceMissToWander = new Transition(new NotCondition(new ReachedPounceTarget(200)), wanderState, -1); Transition wanderToNap = new Transition(new RandomTimerCondition(new TimeSpan(), 600), napState, -1); Transition napToWander = new Transition(new RandomTimerCondition(new TimeSpan(), 600), wanderState, -1); Transition napToCreep = new Transition(new LionHungerGreaterThanCondition(800), creepState, -1); Transition wanderToCreep = new Transition(new LionHungerGreaterThanCondition(800), creepState, -1); Transition creepToHide = new Transition(new LionHungerGreaterThanCondition(1300), hideState, -1); Transition creepToPounce = new Transition(new DeerInRangeCondition(RangeToPounce), pounceState, -1); Transition waitToChase = new Transition(new LionHungerGreaterThanCondition(1800), chaseState, -1); Transition chaseToPounce = new Transition(new DeerInRangeCondition(RangeToPounce), pounceState, -1); Transition eatToWander = new Transition(new RandomTimerCondition(new TimeSpan(), 200), wanderState, -1); hideState.addTransition(arriveAtBush); waitState.addTransition(waitToPounce, waitToChase); pounceState.addTransition(pounceToWander, pounceToKill, pounceMissToWander); wanderState.addTransition(wanderToNap, wanderToCreep); napState.addTransition(napToWander, napToCreep); eatState.addTransition(eatToWander); creepState.addTransition(waitToChase, creepToPounce, creepToHide); chaseState.addTransition(chaseToPounce); SubMachineState HuntDeerSubMachineState = new SubMachineState(game, wanderState, hideState, waitState, pounceState, wanderState, eatState, chaseState, creepState, napState); // HUNT HUNTER SUBMACHINE STATE ///////////////////////////////////////////////// State creepHunter = new State("creepHunter", new CreepHunterAction()); State chaseHunter = new State("chaseHunter", new ChaseHunterAction()); State pounceHunter = new State("pouncePlayer", new SetLionTargetToHunterAction(), new PounceAction(), new emptyVisibleAction()); State goToBushState = new State("hideFromPlayer", new SetTargetToClosestBush(), new GoToBushAction(), new emptyAction()); State hideInBush = new State("hide", new emptyAction(), new WaitInBushAction(true), new emptyVisibleAction()); State hurtHunterState = new State("bite!", new BiteHunterAction(), new NapAction(), new emptyAction()); Transition creepToChaseH = new Transition(new DistanceToHunter(200), chaseHunter, -1); Transition creepToPounceH = new Transition(new DistanceToHunter(150), pounceHunter, -1); Transition creepToBushH = new Transition(new NotCondition(new DistanceToHunter(300)), goToBushState, -1); creepHunter.addTransition(creepToPounce, creepToChaseH, creepToBushH); Transition chaseToPounceH = new Transition(new DistanceToHunter(150), pounceHunter, -1); chaseHunter.addTransition(chaseToPounceH); Transition pounceToHurtHunter = new Transition(new DistanceToHunter(40), hurtHunterState, -1); Transition pounceToCreepHunter = new Transition(new ReachedPounceTarget(40), creepHunter, -1); pounceHunter.addTransition(pounceToHurtHunter, pounceToCreepHunter); Transition hurtHunterToCreep = new Transition(new TimerCondition(50), creepHunter, -1); hurtHunterState.addTransition(hurtHunterToCreep); Transition bushToChase = new Transition(new DistanceToHunter(200), chaseHunter, -1); Transition goToBushToHide = new Transition(new ReachedBush(), hideInBush, -1); goToBushState.addTransition(bushToChase, goToBushToHide); Transition hideToPounce = new Transition(new DistanceToHunter(RangeToPounce), pounceHunter, -1); Transition hideToCreep = new Transition(new TimerCondition(400), chaseHunter, -1); hideInBush.addTransition(hideToPounce, hideToCreep); SubMachineState HuntHunterSubMachine = new SubMachineState(game, creepHunter, creepHunter, chaseHunter, pounceHunter, hurtHunterState, goToBushState, hideInBush); HuntHunterSubMachine.name = "hunt Hunter"; //top level machine Transition huntDeerToHuntHunter = new Transition(new OrCondition(new OrCondition( new AndCondition(new DistanceToHunter(300), new AndCondition(new NotCondition(new LionHealthCondition(4)), new LionHungerGreaterThanCondition(2500))), new DeerCount(0)), new AndCondition(new ThreatLevel(75f), new DistanceToHunter(299))), HuntHunterSubMachine, 0); HuntDeerSubMachineState.addTransition(huntDeerToHuntHunter); State fleeFromHunterState = new State("flee hunter", new FleeFromHunterAction()); State fleeWanderState = new State("wandering", new WanderAction()); Transition fleeFFHtoWander = new Transition(new NotCondition(new DistanceToHunter(300)), fleeWanderState, -1); Transition fleeWandertoFFH = new Transition(new DistanceToHunter(300), fleeFromHunterState, -1); fleeFromHunterState.addTransition(fleeFFHtoWander); fleeWanderState.addTransition(fleeWandertoFFH); Transition fleeHunterToHuntDeer = new Transition(new AndCondition(new NotCondition(new DistanceToHunter(200)), new NotCondition(new DeerCount(0))), HuntDeerSubMachineState, 0); Transition fleeHuntertoHuntHunter = new Transition(new LionHungerGreaterThanCondition(3000), HuntHunterSubMachine, 0); fleeHuntertoHuntHunter.addActions(new LionDesperateAction()); SubMachineState fleeHunterSubMachine = new SubMachineState(game, fleeFromHunterState, fleeFromHunterState, fleeWanderState); fleeHunterSubMachine.name = "fleeHunter"; fleeHunterSubMachine.addTransition(fleeHunterToHuntDeer, fleeHuntertoHuntHunter); Transition huntHunterToHuntDeer = new Transition(new OrCondition(new PlayerHealthCondition(0), ( new AndCondition(new NotCondition(new DeerCount(0)), new NotCondition(new DistanceToHunter(300))))), HuntDeerSubMachineState, 0); Transition huntHunterToFleeHunter = new Transition(new AndCondition(new NotCondition(new LionDesperateCondition()), new OrCondition(new PlayerHealthCondition(0), new LionHealthCondition(5))), fleeHunterSubMachine, 0); HuntHunterSubMachine.addTransition(huntHunterToHuntDeer, huntHunterToFleeHunter); Transition huntDeerToFleeHunter = new Transition(new AndCondition( new DistanceToHunter(200), new LionHealthCondition(5)), fleeHunterSubMachine, 0); HuntDeerSubMachineState.addTransition(huntDeerToFleeHunter); //finalize machine and attach to lion. PHEW this.hfsm = new HierarchicalStateMachine(game, HuntDeerSubMachineState, fleeHunterSubMachine, HuntHunterSubMachine); }