Example #1
0
        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));
        }
Example #2
0
        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));
        }
Example #3
0
        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);
                        }
                    }
                }
            }
        }
Example #5
0
        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);
                        }
                    }
                }
            }
        }
Example #8
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);
        }
Example #10
0
        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);
        }
Example #11
0
        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));
        }
Example #12
0
        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));
        }
Example #13
0
        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);
                }
            }
        }
Example #15
0
        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);
        }
Example #16
0
        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;
            }
        }
Example #18
0
        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));
        }
Example #19
0
        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");
        }
Example #20
0
        /// <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
            };
        }
Example #21
0
        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);
        }