6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern...

25
6.5 Implementing a State Machine Language

Transcript of 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern...

Page 1: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

6.5 Implementing a State Machine Language

Page 2: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

State Machine in game AI

The most used software pattern Simple to program Easy to comprehend Easy to debug Completely general to any problem Might not always provide the best solution

But few can deny that they get the job done with minimal risk to the project

Page 3: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

State Machine in game AI

Disadvantage of state machine No consistent structure Development cycle churns on Poor structure

This article presents Robust way to structure your state machine with a simple

language Make programming games much easier

Page 4: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Game Developer-Style State Machine

void RunLogic (int *state) {

switch(*state){

case 0: //Wander

Wander();

if(SeeEnemy()){

if(GetRandomChance() <0.8) *state =1;

else *state =2;

}

if(Dead()) *state =3;

break;

case 1: //Attack

Attack();

if(Dead()) *state =3;

break;

case 2: //RunAway

RunAway();

if(Dead()) *state =3;

break;

case 3: //Dead

SlowlyRot();

break;

}

}

Page 5: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Game Developer-Style State Machine Serious weaknesses

The state changes are poorly regulated States are of type int and would be more robust and debugg

able as enums The omission of a single break keyword would couse hard-to

-find bugs Redundant logic appears in multiple states No way to tell that a state has been entered for the first time No way to monitor or log how the state machine has behave

d over time

What is a poor game programmer to do? Provide some structure

Page 6: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

A State Machine Language Be created with the help of macros

Have six keyword BeginStateMachine EndStateMachine State OnEnter OnExit OnUpdate

Page 7: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

The State Machine Language Example structure of the State Machine Language

BeginStateMachine

State(STATE_Wander)

OnEnter

// C or C++ code for state entry

OnUpdate

// C or C++ code executed every tick

OnExit

// C or C++ code for state clean-up

State(STATE_Attack)

OnEnter

// C or C++ code for state entry

EndStateMachine

Page 8: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Actual Implementation The six macro keywords

#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 9: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Using macro

Nice properties Expand in a building-block fashion

Handled event Provide an easy way to monitor how the state machine is

Can't mess up the state machine by forgetting something like a break keyword.

Easier to read

Page 10: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Support functionvoid StateMachine::Process(StateMachineEvent event){

States(event, m_currentState);

int safetyCount = 10;

while (m_stateChange && (-safetyCount >=0)) {

assert ( safetyCount > 0 && "States are flip-flopping.");

m_stateChange = false;

//Let the last state clean-up

States(EVENT_Exit, m_currentState);

//Set the new state

m_currentState = m_nextState;

//Let the new state initialize

States(EVENT_Entr, m_currentState);

}

}

Page 11: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Integrating this Solution How is it actually integrated within a game?

class Robot: public StateMachine{public: Robot(void){}; ~Robot(void){};private: virtual bool States(StateMachineEvent event, int state); // Put private robot specific variables here

};bool Robot::States (StateMachineEvent event, int state){

BeginStateMachine // Put any number of states and event responses. // Refer to the code on the CD for more examples.EndStateMachine

}

Page 12: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Conclusion State Machine Language provides

Simple enforced structure Excellent readability Natural to debug Full power of C/C++ within the state machine Easy to add code for entering or exiting a state State changes are more formal and protected Error checking for flip-flopping state changes No need to spend months developing a custom language

Page 13: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

6.6 Enhancing a State Machine Language through Messaging

Page 14: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

The Concept of Messages Message

A number of enumerated type

Communicate with messages between game objects

The technique of messages Event-driven behavior

enum MSG_Name { MSG_Attacked, MSG_Damaged, MSG_Healed, MSG_Poisoned };

Page 15: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Messages as Letters

class MSG_Object

{

public:

MSG_Name m_Name; // Message name(enumeration)

float m_Data; // Extra data for the message

objectID m_Sender; // Object tht sent the message

objectID m_Receiver; // Object that will get the message

float m_DeliveryTime; // Time at which to send the message

};

Page 16: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Messages as Events

Incorporate messages into the State Machine Language

A message event

BeginStateMachine

State(STATE_Wander)

OnMsg(MSG_Attacked)

SetState(STATE_RunAway);

State(STATE_RunAway)

OnEnter

//run away

EndStateMachine

Page 17: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Message Timers When a game object sends a message to itself to create an

internal event

BeginStateMachine

State(STATE_Wander)

OnMsg(MSG_Attacked)

SendDelayedMsgToMe(0.5, MSG_TimeOut);

OnMsg(MSG_TimeOut)

SetState(STATE_RunAway);

State(STATE_RunAway)

OnEnter

//run away

EndStateMachine

Page 18: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Scoping Messages Scoping

Something is only valid within a certain context

Scoping messages By defining a scope for messages Won't be misinterpreted in the wrong context The extraneous queued timeout messages are ignored

Page 19: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Scoping Messages

BeginStateMachine

State(STATE_Wander)

OnMsg(MSG_Attacked)

SendDelayedMsgToMe(0.5, MSG_TimeOut, SCOPE_TO_THIS_STATE);

OnMsg(MSG_TimeOut)

SetState(STATE_RunAway);

State(STATE_RunAway)

OnEnter

SendDelayedMsgToMe(7.0, MSG_TimeOut);

OnMsg(MSG_TimeOut)

SetState(STATE_Wander);

EndStateMachine

Page 20: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Redundant Message Policy Redundant Messages

Multiple delayed messages All basically the same messages Accumulate in the message router

Standard rules for redundant messages1. Ignore the new message

2. Replace the old message with the new one

3. Store the new message, letting redundant messages accumulate

The best policy is #1

Page 21: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Global Event ResponsesBeginStateMachine

OnMsg(MSG_Dead) // Global response -Triggered regardless of state SetState(STATE_Dead);

State(STATE_Wander)OnEnter

//Wander State(STATE_RunAway) OnEnter //Run away State(STATE_Dead) OnEnter //Die OnMsg(MSG_Dead) //Ignore msg - this overrids the global responseEndStateMachine

Page 22: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Recording Behavior for Debugging The need for good debugging of state machines is critical To monitor and record every event

That's handled and not handled by each state machine

Embed logging function Calls within the macro keywords themselves

#define BeginStateMachine if(state < 0){char statename[64]= "STATE_Global"; if(0){

#define State(a) return(true);}}else if(a == state) \

{char statename[64] =#a; if(0){

#define OnMsg(a) return(true);}else if(EVENT_Message == \

event && msg && a == msg->GetMsgName()){ \

g_debuflog.LogStateMachineEvent( \

m_Owner->GetID(),msg,statename,#a,true);

Page 23: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Partial listing of the main function// Create game objectGameObject myGameObject (g_database.GetNewObjectID());g_database.Store(myGameObject);

//Give the game object a state machinemyGameObject.SetStateMachine (new Robot(&myGameObject));myGameObject.GetStateMachine()>Initialized();

//Game Loopwhile(1){

g_time.MarkTimeThisTick();myGameObject.GetStateMachine()->Update();g_msgroute.DeliverDelayedMessages();

}

Page 24: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Summary

Make games easier and more robust to code State machines

Easy to read Easy to debug Easy to build and prototype A way to communicate with other game objects Global event responses to reduce redundant code A way to set event timers Allow transparent monitoring and logging of all events

Page 25: 6.5 Implementing a State Machine Language. State Machine in game AI The most used software pattern Simple to program Easy to comprehend Easy to debug.

Summary Allow execution of special code when first entered Allow execution of special code when exited

Conclusion For simplicity For maintainability For robustness For ease of debugging