260 likes | 265 Views
State Driven Agents. CIS 479/579 Bruce R. Maxim UM-Dearborn. Buckland Software. The executables and source code available http://www.wordware.com/files/ai The Boost library is available from http://www.boost.org/
E N D
State Driven Agents CIS 479/579 Bruce R. Maxim UM-Dearborn
Buckland Software • The executables and source code available http://www.wordware.com/files/ai The Boost library is available from http://www.boost.org/ • The Visual C++ environment need to be configured to compile the source code by setting the appropriate paths
Paths • Include file paths C:\boost C:\AI_Source\Common C:\AI_Source\Common\lua-5.0\include C:\AI_Source\Common\laubind • Source file paths C:\AI_Source\Common C:\AI_Source\Common\lua-5.0 C:\AI_Source\Common\laubind • Library file paths C:\AI_Source\Common\lua-5.0\lib
FSM Agent Advantages • Quick design and simple to code • Easy to debug • Low computational overhead • Intuitive so they make sense to domain experts • Flexible, easy for programmers to tweak to modify behaviors
FSM State Examples • Pacman ghosts • evade, chase • Quake bots • find armor, find health, seek cover, run away • FIFA soccer players • strike, dribble, chase ball, mark player • NPC’s in real time strategy games • move to position, patrol, follow path
Switch Implementation - 1 • Define an enumerated type with the state names enum StateType(RunAway, Patrol, Attack); • Then define method that manages the transitions void Agent::Update(StateType CurrentState) { switch (CurrentState) { case Runaway: EvadeEnemy( ); if (Safe( )) ChangeState(Patrol); break; …
Switch Implementation - 2 • This works OK for simple FSM’s • Becomes overly complicated for FSM’s with lots of states and transitions • Requires recompilation if states are changed • Not easy to have simultaneous behaviors implemented (run and shoot) without defining lots of states
State Transition Table - 2 • Agent queries table as needed • Table can stored in file and edited without recompiling the program • Each state can be modeled as a separate objects or functions called by the agent • Fairly easy to extend and modify
State Design Pattern - 1 • The state transition rules can be embedded in the states themselves • All states share a common interface using a pure virtual class class State { public: virtual void Execute(Troll* troll) = 0; }
State Design Pattern - 2 class Troll { State* m_pCurrentState; public: void Update() { m_pCurrentState->Execute(this); } void ChangeState(const State* pNewState) { delete m_pCurrentState; m_pCurrentState = pNewState; } }
State Design Pattern - 3 class State_Runaway : public State { public: void Execute(Troll* troll) { if (troll->isSafe()) troll->ChangeState(new State_Sleep()); else troll->MoveAwayFromEnemy(); } }
State Design Pattern - 4 class State_Sleep : public State { public: void Execute(Troll* troll) { if (troll->isThreatned()) troll->ChangeState(new State_RunAway()); else troll->Snore(); } }
West World Miner States EnterMineDigForGold pockets full thirsty not thirsty not wealthy VisitBankDepositGold QuenchThirstSaloon rested wealthy enough GoHomeSleep
Classes • All West World inhabitants are derived from the base class BaseGameEntity • Each entity will be assigned a unique identifier • The Miner class is an example of one such class • The State class is the base abstract class and each of the four Miner states needs its own class definition
Reusable Classes • The State base class and the Miner owned classes would be more easily reused if were templates • Creating a StateMachine class with ways of tracking the Miner’s current, previous, and global states gives the FSM a crude memory to allow more complex (context sensitive) behaviors
Adding New NPC • Elsa only visits two states VisitBathroom (1 chance in 10) or DoHouseWork • This makes use of the template version of the State class and required the definition of a new global state WifeGlobalState to deal with the bathroom visits • This requires adding classes MinersWife and MinersWifeOwnedStates
Adding NPC Communication • Good games make use of event driven architectures • When events occur they are broadcast to other game objects who are programmed to react to the event or ignore it • Intelligent game agents can send messages to each other to allow cooperative behaviors
Telegram Structure struct Telegram { //the entity that sent this telegram int Sender; //the entity that is to receive this telegram int Receiver; //the message itself. These are all enumerated in the file //"MessageTypes.h" int Msg; //If a delay is necessary this field is stamped with the time //the message should be dispatched. double DispatchTime; //any additional information that may accompany the message void* ExtraInfo; // constructors not shown here }
Message Types #include <string> enum message_type { Msg_HiHoneyImHome, Msg_StewReady, }; inline std::string MsgToStr(int msg) { switch (msg) { case 1: return "HiHoneyImHome"; case 2: return "StewReady"; default: return "Not recognized!"; } }
Elsa’s New States CookStew 1 chance in 10 Previous state Delayed message to self “Stew Ready” VisitBathroom 1 chance in 10 Receive “honey I’m home” previous state DoHouseWork
Message Management • Creation, dispatch, and management of telegrams is handled by the class MessageDispatcher • The method DispatchMessage is used by every agent to send a message to entity with a known ID • The database of ID’s are managed by the class EntityManager
Use Priority Queue • Telegrams with delays are store in a priority queue ordered by their Time Stamp data • Telegrams without delays (e.g. “I just shot you with my crossbow”) are sent right away • The front queue message is removed long with any unprocessed expired telegrams
FSM Changes • The BaseEntity class needs to be modified (add HandleMessage) so that any derived class can receive messages • The State class needs to be modified so that BaseEntity states can choose to accept and handle messages (add OnMessage method) • The StateMachine class needs its own version of HandleMessage
Elsa Cooks Dinner • Miner enters shack and sends “honey I’m home” message • Elsa receives “honey I’m home” and changes state to CookStew • Elsa puts Stew in oven and sends delayed message “Stew ready” • Elsa receives “Stew ready”, takes out stew, and sends Miner “Dinner ready” message • Miner receives “Dinner ready” and changes state to EatStew
What happens? • In between messages the NPC’s are free to respond to all state appropriate inputs • This may means that the Miner has left the building before receiving the “Dinner ready” message • Sometimes you need two FSM’s working in parallel (one for character movement and one for character’s weapon) • Sometimes you need nested state machines (aka hierarchical FSM’s)