22
SMC – State Machine Compiler [email protected] 아아아 . 아아아

Smc–state machinecompiler

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Smc–state machinecompiler

SMC – State Machine [email protected]아꿈사 . 이동현

Page 2: Smc–state machinecompiler

FSM?

C++ Code

수 많은 반복 코드와 노가다…통제가 안될 정도로 커진다 .

상태기계를 이용하면 프로그램이 간단하고

이해하기 쉽다 .

Page 3: Smc–state machinecompiler

좀 더 견고한 방법 . – 상태 기계 언어• 고전적인 의미의 상태 기계와 현실적인 의미의 상태 기계 .• 대부분의 게임 개발자는 느슨한 정의를 이용 .• 상태안의 상태 .• 다중 상태 변수 .• 상태 전이의 임의성 .• 상태 안에서 모든 게임 tick 를 실행하는 코드 .• 기타 생각할 수 있는 모든 것 .

Page 4: Smc–state machinecompiler

코딩된 상태 기계void RunLogic( int* state ){ switch( *state ) { case 0: // 돌아다님 Wander(); if( SeeEnemy() ) { if( GetRandomChance() < 0.8 ) *state = 1; else *state = 2; } if( Dead() ) *state = 3; break; case 1: // 공격 Attack(); if( Dead() ) *state = 3; break;

case 2: // 도망 RunAway(); if( Dead() ) *state = 3; break;

case 3: // 죽음 SlowlyRot(); break; }}

합법적인 코드 그러나…

• 상태 변화가 잘 규제되지 않는다 .• 상태들이 int 형태이며 , 열거형이라면 더

견고하고 디버그 하기 쉬울 것이다 .• Break 키워드 하나만 지워도 찾기 어려운

버그들을 만들게 된다 .• 중복적인 논리가 다중 상태에 나타난다 .• 어떤 상태에 처음 들어갔는지를 알려줄 수 있는

방법이 없다 .• 상태 기계가 시간에 따라 어떻게 움직여 왔는지를

모티너하거나 기록으로 남길 (log) 방법이 없다 .

Page 5: Smc–state machinecompiler

상태 기계 언어• C++ 매크로의 활용 .• 언어의 일부분이므로 따로 파서등의 도구가 필요없다 .

• 핵심 키워드• BeginStateMachine• EndStateMachine• State• OnEnter• OnExit• OnUpdate

Page 6: Smc–state machinecompiler

상태 기계 언어 기본 예제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 EndStateMachine return (true); }} else { assert(0);\

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 OnEnter OnEvent(EVENT_Enter)#define OnUpdate OnEvent(EVENT_Update)#define OnExit OnEvent(EVENT_Exit)

Page 7: Smc–state machinecompiler

실제로 확장 해보면 ..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

Page 8: Smc–state machinecompiler

좀 더 나아가서 ..• AI 디자이너의 생산성 높이기 .• GUI 기반의 모델링 .• C++ 코더로의 변환 용이성 .

Page 9: Smc–state machinecompiler

CreatureMachine::CreatureMachine(){

// add all variables to the variable listAddVariable("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 statesAddState("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");

};

다이어 그램의 코드화

Page 10: Smc–state machinecompiler
Page 11: Smc–state machinecompiler

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.”

Page 12: Smc–state machinecompiler

SMC

Page 13: Smc–state machinecompiler

Adding a state machine to your class

1. Download SMC - http://sourceforge.net/projects/smc/files/smc/6_0_0/smc_6_0_0.zip/download

2. Include the SMC class definitions into your appli-cation.

3. Include the state machine's source file.4. Instantiate the state machine's context object.5. If you want to execute the start state's entry ac-

tions call the state machine context's enterStart-State method. This is not needed to set the start state as that is done when the state machine context is instantiated. enterStartState only exe-cutes the start state's entry actions (if any exist).

Page 14: Smc–state machinecompiler

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 %fsmclass TaskFSM %access package %start TaskFSM::Suspended %map TaskFSM %%

<snip> Running Exit { stopSliceTimer(); }{ Suspend Suspended { suspendTask(); } Block Blocked { blockTask(); } Done Stopped { releaseResources(); } } <snip> } %%

{ Suspend Suspended { suspendTask(); } Block Blocked { blockTask(); } Done Stopped { releaseResources(); } }

Transition End State Action

Page 15: Smc–state machinecompiler

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();} }

Page 16: Smc–state machinecompiler

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);} }

Page 17: Smc–state machinecompiler

Transition Arguments

void MainMap_CLOSED::PassiveOpen(TcpConnectionContext& context, unsigned short port){ TcpConnection& ctxt(context.getOwner());

CLOSED{ PassiveOpen(port: unsigned short) ServiceOpening { openServerSocket(port); }

Page 18: Smc–state machinecompiler

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(); }}

Page 19: Smc–state machinecompiler

Transition Precedence

1. Guarded transition 2. Unguarded transition 3. The Default state's guarded definition. 4. The Default state's unguarded definition. 5. The current state's guarded Default transition. 6. The current state's unguarded Default transition. 7. The Default state's guarded Default transition. 8. The Default state's unguarded Default transition.

Page 20: Smc–state machinecompiler

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

Page 21: Smc–state machinecompiler

Behind the Curtain

GOF’s State Pattern SMC Pattern

Page 22: Smc–state machinecompiler

Ex4

StopMap

State

Stoplight-State

StopMap_EastWestGreen

StopMap_EastWestYellow

StopMap_NorthSouthGreen

StopMap_NorthSouthYellow

StopMap_Default

StoplightCon-text

FSMCon-text

Stop-light

enterStartState