1. SMC – State Machine Compiler jeddli@gmail.com 아꿈사. 이동현
2. FSM? 상태기계를 이용하면 프로그램이 간단하고 이해하기 쉽다. C++ Code 수 많은 반복 코드와 노가다… 통제가 안될 정도로 커진다.
3. 좀 더 견고한 방법. – 상태 기계 언어 고전적인 의미의 상태 기계와 현실적인 의미의 상태 기계. 대부분의 게임 개발자는 느슨한 정의를 이용. 상태안의 상태. 다중 상태 변수. 상태 전이의 임의성. 상태 안에서 모든 게임 tick를 실행하는 코드. 기타 생각할 수 있는 모든 것.
10. 상태 기계 언어 기본 예제 BeginStateMachine State( STATE_Wander ) OnEnter // 상태시작점에대한C나C++ 코드 OnUpdate // 매틱(tick)마다실행되는C나C++ 코드 OnExit // 상태의뒷정리를위한C나C++ 코드 State( STATE_Attack ) OnEnter // 상태시작점에대한C나C++ 코드 EndStateMachine #define BeginStateMachine if(state < 0) { if (0) { #define EndStateMachinereturn (true); }} else { assert(0);br />return (false); } return (false); #define State(a) return (true);}}else if(a == state){if(0){ #define OnEvent(a) return (true);}else if(a == event){ #define OnEnterOnEvent(EVENT_Enter) #define OnUpdateOnEvent(EVENT_Update) #define OnExitOnEvent(EVENT_Exit)
11. 실제로 확장 해보면.. if( state < 0 ){ if( 0 ) { return ( true ); } }else if( STATE_Wander == state ) { if( 0 ){ return ( true ); }else if( EVENT_Enter== state ) { // 상태시작점에대한C++ 코드 return ( true ); }else if(EVENT_Update== state ) { // 매틱(tick)마다실행되는C++ 코드 return ( true ); }else if(EVENT_Wander== state ) { // 상태의뒷정리를위한C++ 코드 return ( true ); } }else if( STATE_Attack == state ) { if( 0 ){ return ( true ); }else if( EVENT_Enter == state ) { // 상태시작점에대한C++ 코드 return ( true ); } }else { assert(0); return( false ); } return false; BeginStateMachine State( STATE_Wander ) OnEnter // 상태시작점에대한C나C++ 코드 OnUpdate // 매틱(tick)마다실행되는C나C++ 코드 OnExit // 상태의뒷정리를위한C나C++ 코드 State( STATE_Attack ) OnEnter // 상태시작점에대한C나C++ 코드 EndStateMachine
12. 좀 더 나아가서.. AI 디자이너의 생산성 높이기. GUI 기반의 모델링. C++ 코더로의 변환 용이성.
13. CreatureMachine::CreatureMachine() { // add all variables to the variable list AddVariable("Health",VAR_INTEGER,&m_Health); AddVariable("EnemyLocation",VAR_POSITION,&m_Enemy; // now add conditions (may reference variables) AddCondition("InRange",LESSTHAN,"EnemyLocation",100); AddCondition("LowHealth",LESSTHAN,"Health", 50); // now add all the actions (may be referenced by the // states) AddAction("IdleAction"); AddAction("FightAction"); AddAction("FleeAction"); // now add all the states AddState("Idle","IdleAction"); AddState("Fight","FightAction"); AddState("Flee","FleeAction"); // now add all the transitions (may reference states // and variables) // transitions syntax : <condition-name> <start state> // <end state> AddTransition("In Range","Idle","Fight"); AddTransition("Low Health","Fight","Flee"); }; 다이어 그램의 코드화
14.
15. SMC – The State Map Compiler http://smc.sourceforge.net/SmcManual.htm “Your detailed state diagrams are only pictures. How are you going to translate your drawings into code? A transition matrix is cryptic while switch statements means your state machine logic is scattered all over your code. The state pattern looks like a great solution but that means writing and maintaining a class for each state - too much work.”
17. Adding a state machine to your class Download SMC - http://sourceforge.net/projects/smc/files/smc/6_0_0/smc_6_0_0.zip/download Include the SMC class definitions into your application. Include the state machine's source file. Instantiate the state machine's context object. If you want to execute the start state's entry actions call the state machine context's enterStartState method. This is not needed to set the start state as that is done when the state machine context is instantiated. enterStartState only executes the start state's entry actions (if any exist).
18. Make SMC file // This FSM works for the Task class only and only the Task // class may instantiate it. %class Task %package com.acme.supercron %fsmclassTaskFSM %access package %start TaskFSM::Suspended %map TaskFSM %% <snip> Running Exit { stopSliceTimer(); } { Suspend Suspended { suspendTask(); } Block Blocked { blockTask(); } Done Stopped { releaseResources(); } } <snip> } %% End State Transition Action { Suspend Suspended { suspendTask(); } Block Blocked { blockTask(); } Done Stopped { releaseResources(); } }
19. Transition Guards // State Idle { // Trans Run // Guard condition [ctxt.isProcessorAvailable() == true && ctxt.getConnection().isOpen() == true] // Next State Running // Actions { StopTimer("Idle"); DoWork(); } Run nil {RejectRequest();} }
20. Transition Arguments // State Idle { // Transition Run(msg: const Message&) // Guard condition [ctxt.isProcessorAvailable() == true && msg.isValid() == true] // Next State Running // Actions { StopTimer("Idle"); DoWork(msg); } Run(msg: const Message&) // Next State Actions nil {RejectRequest(msg);} }
22. Default Transitions What happens if a state receives a transition that is not defined in that state? Default { // Valid run request but transition occurred in an invalid // state. Send a reject reply to valid messages. Run(msg: const Message&) [ctxt.isProcessorAvailable() == true && msg.isValid() == true] nil { RejectRequest(msg); } // Ignore invalid messages are ignored when received in // an invalid state. Run(msg: const Message&) nil {} Shutdown ShuttingDown { StartShutdown(); } } Connecting { // We are now connected to the far-end. Now we can logon. Connected Connected { logon(); } // Any other transition at this point is an error. // Stop the connecting process and retry later. Default RetryConnection { stopConnecting(); } }
23. Transition Precedence Guarded transition Unguarded transition The Default state's guarded definition. The Default state's unguarded definition. The current state's guarded Default transition. The current state's unguarded Default transition. The Default state's guarded Default transition. The Default state's unguarded Default transition.
24. Compiling a .sm Prepare Java 1.6.0 or newer is properly installed and the "javac", "java" and "jar" executables are in your PATH environment variable. The standard Java Development Kit can be obtained for free from http://java.sun.com . The SMC_HOME environment variable contains the path to where SMC is installed. $ java -jar $SMC_HOME/bin/Smc.jar [-c | -c++ | -csharp | -graph | -groovy | -java | -lua | -objc | -perl | -php | -python | -ruby | -scala | -table | -tcl | -vb] <fsm_source_file>.sm