public void Test_request_transition_with_a_nested_fsm() { var nested = new StateMachine(); fsm.AddState("A", recorder.Track(nested)); fsm.AddState("B", recorder.TrackedState); nested.AddState("A.X", recorder.TrackedState); fsm.Init(); fsm.OnLogic(); recorder.Expect .Enter("A") .Enter("A.X") .Logic("A") .Logic("A.X") .All(); fsm.RequestStateChange("B"); recorder.Expect .Exit("A") .Exit("A.X") .Enter("B") .All(); fsm.OnLogic(); recorder.Expect .Logic("B") .All(); }
public void TestStartupEvents() { fsm.AddState("A", recorder.Track(new State())); recorder.Expect.Empty(); fsm.Init(); recorder.Expect.Enter("A").All(); Assert.AreEqual("A", fsm.ActiveStateName); fsm.OnLogic(); recorder.Expect.Logic("A").All(); }
public void Test_example_scene() { // Advanced test that checks multiple different components working together. // This is the hierarchical state machine example from the README // that controls the beheviour of an Enemy Spy unit in a space game. // ExtractIntel state StateMachine extractIntel = new StateMachine(); extractIntel.AddState("CollectData", recorder.TrackedState); extractIntel.AddState("SendData", recorder.TrackedState); bool shouldCollectData = true; extractIntel.SetStartState("CollectData"); extractIntel.AddTransition("CollectData", "SendData", t => !shouldCollectData); extractIntel.AddTransition("SendData", "CollectData", t => shouldCollectData); // States fsm.AddState("FleeFromPlayer", recorder.TrackedState); fsm.AddState("FollowPlayer", recorder.TrackedState); fsm.AddState("ExtractIntel", recorder.Track(extractIntel)); // Transitions bool isInPlayerScanningRange = false; bool isPlayerInOwnScanningRange = false; fsm.AddTransition( "ExtractIntel", "FollowPlayer", t => !isPlayerInOwnScanningRange ); fsm.AddTransition( "FollowPlayer", "ExtractIntel", t => isPlayerInOwnScanningRange ); fsm.AddTransition( "ExtractIntel", "FleeFromPlayer", t => isInPlayerScanningRange ); fsm.AddTransition( "FleeFromPlayer", "ExtractIntel", t => !isInPlayerScanningRange ); // Start fsm.SetStartState("FollowPlayer"); fsm.Init(); recorder.Expect.Enter("FollowPlayer").All(); // Follow the player for one frame fsm.OnLogic(); recorder.Expect.Logic("FollowPlayer").All(); // Player gets in scanning range => Start collecting data isPlayerInOwnScanningRange = true; fsm.OnLogic(); recorder.Expect .Exit("FollowPlayer") .Enter("ExtractIntel") .Enter("CollectData") .Logic("ExtractIntel") .Logic("CollectData") .All(); fsm.OnLogic(); recorder.Expect .Logic("ExtractIntel") .Logic("CollectData") .All(); // In the ExtractIntel state: Send the data shouldCollectData = false; fsm.OnLogic(); recorder.Expect .Logic("ExtractIntel") .Exit("CollectData") .Enter("SendData") .Logic("SendData") .All(); fsm.OnLogic(); recorder.Expect .Logic("ExtractIntel") .Logic("SendData") .All(); // In the ExtractIntel state: Collect data shouldCollectData = true; fsm.OnLogic(); recorder.Expect .Logic("ExtractIntel") .Exit("SendData") .Enter("CollectData") .Logic("CollectData") .All(); // Collect data is interrupted by the player who can now see the Spy Enemy on the edge // of the radar. isInPlayerScanningRange = true; fsm.OnLogic(); recorder.Expect .Exit("ExtractIntel") .Exit("CollectData") .Enter("FleeFromPlayer") .Logic("FleeFromPlayer") .All(); fsm.OnLogic(); recorder.Expect.Logic("FleeFromPlayer").All(); }