finite state machines finite state machines
play

Finite State Machines Finite State Machines Often AI as agents: - PowerPoint PPT Presentation

3/24/2016 Finite State Machines Finite State Machines Often AI as agents: sense , think , then act But many different rules for agents Ex: sensing, thinking and acting when fighting , running , exploring Can be difficult to


  1. 3/24/2016 Finite State Machines Finite State Machines • Often AI as agents: sense , think , then act • But many different rules for agents – Ex: sensing, thinking and acting when fighting , running , exploring … – Can be difficult to keep rules consistent! • Try Finite State Machine https://en.wikipedia.org/wiki/Finite-state_machine#/media/File:Turnstile_state_machine_colored.svg – Probably most common game AI software pattern – Natural correspondence between states and behaviors • Abstract model of computation – Easy: to diagram, program, debug • Formally: (Detailed game example – General to any problem – Set of states next slide) – See AI Depot – FSM: http://ai-depot.com/FiniteStateMachines/ – A starting state • For each situation, choose appropriate state – An input vocabulary – Number of rules for each state is small – A transition function that maps inputs and current state to next state Finite State Machines – Example (1 of 2) Finite State Machines – Example (1 of 2) Game where raid Egyptian Tomb Game where raid Egyptian Tomb • • Mummies! Behavior Mummies! Behavior Wander • • – Spend all of eternity w andering in – Spend all of eternity w andering in tomb tomb No sense Sense – When player is close, s earch – When player is close, s earch – When see player, c hase – When see player, c hase FSM? Make separate states Make separate states • • Seek – Define behavior in each state – Define behavior in each state • Wander – move slowly, randomly • Wander – move slowly, randomly Can’t see • Search – move faster, in lines • Search – move faster, in lines See • Chasing – direct to player • Chasing – direct to player Define transitions (suitable for code) Define transitions (suitable for code) • • Attack – Close is 100 meters (smell/sense) – Visible is line of sight 1

  2. 3/24/2016 Finite State Machines – Example (2 of 2) Outline Start • Can be extended easily • Introduction (done) • Ex: Add magical scarab (amulet) Wander • When player gets scarab, • Common AI Techniques (done) Mummy is afraid. Cowers. No Sense Sense • Behavior • Promising AI Techniques (done) No – Stay still (tremble animation) Ankh • Pathfinding (A*) (done) • Transition Seek Cower – When player gets scarab Ankh • Finite State Machines Can’t See – When timer expires See • Could also have sub-states – Game example (next) – Same transitions, but different Attack • Summary actions • i.e., range attack versus melee attack class State { Pyramid! private: string state_type; // Name of state. public: State(); // Set name of state. void setType(std::string new_type); State.h // Get name of state. std::string getType() const; // Invoked when state first entered. virtual void Enter(Object *p_obj); Must define Derived class // Invoked every game loop step. redefines virtual void Execute(Object *p_obj)=0; // Invoked when state exited. virtual void Exit(Object *p_obj); Dragonfly }; Solve the maze to escape the mummy guardians! 2

  3. 3/24/2016 class StateMachine { StateMachine Update(), ChangeState() private: Object *p_owner; // Owner of this state machine. State *p_state; // Current state. State *p_previous_state; // Previous state. void StateMachine::Update() { State *p_global_state; // Global state (reachable from any state). StateMachine.h // Execute global state. public: StateMachine(); if (p_global_state) p_global_state -> Execute(p_owner); // Set owner of state machine. void setOwner(Object *p_new_owner); // Execute local state. // Get owner of state machine. if (p_state) Object *getOwner() const; p_state -> Execute(p_owner); // Set current state. void setState(State *p_new_state); } // Get current state. State *getState() const; void StateMachine::changeState(State *p_new_state) { // Set previous state. Called to update void setPreviousState(State *p_new_state); FSM. Usually // Call exit on old state. // Get previous state. if (p_state) p_state -> Exit(p_owner); State *getPreviousState() const; every step // Set global state. void setGlobalState(State *p_new_state); // Keep track of previous state. // Get global state. p_previous_state = p_state; State *getGlobalState() const; // Update state machine (calling Execute() for current state). // Change to new state. void Update(); Called when p_state = p_new_state; // Change current state. void changeState(State *p_new_state); state changes // Revert to previous state. // Call enter on new state. void revertToPrevious(); if (p_state) p_state -> Enter(p_owner); Dragonfly }; } Dragonfly StateWander.h Pyramid StateWander Enter() Pyramid class StateWander : public State { // Change sprite to "wander" Mummy. void StateWander::Enter(Object *p_obj) { private: LogManager &log_manager = LogManager::getInstance(); StateWander(); // Private since singleton. StateWander(StateWander const&); // Don't allow copy. // Set wander sprite (white mummy). void operator=(StateWander const&); // Don't allow assignment. ResourceManager &resource_manager = ResourceManager::getInstance(); public: Sprite *p_sprite = resource_manager.getSprite("mummy-white"); // Get the singleton instance of the state. if (!p_sprite) { static StateWander *getInstance(); log_manager.writeLog("Warning! ‘mummy-white' not found"); return; } void Enter(Object *p_obj); Note: has no Exit() p_obj -> setSprite(p_sprite); void Execute(Object *p_obj); log_manager.writeLog("StateWander::Enter(): Set mummy-white"); }; } Also need: StateSearch , StateChase and StateCower 3

  4. 3/24/2016 Pyramid Pyramid class Mummy : public Object { // Wander around pyramid. void StateWander::Execute(Object *p_obj) { Used for slowing down StateWander Execute() private: movement, thinking int move_countdown; // This state deals with a Mummy, so cast Object *. int think_countdown; Mummy *p_mummy = dynamic_cast <Mummy *> p_obj; enum direction_type direction; StateMachine machine; // Controls behavior. // Move. Mummy.h if (!doMove(p_mummy, 1, false)) public: return; Defined in Hero ~Mummy(); Mummy(); Used by states for // If Hero has ankh, enter cower state. int eventHandler(Event *e); if (Hero::getInstance() -> hasAnkh()) { transitions bool senseHero(); StateMachine *p_machine = p_mummy->getMachine(); int seeHero(); p_machine -> changeState(StateCower::getInstance()); void setMoveCountdown(int new_move_countdown); return; int getMoveCountdown(); } void setThinkCountdown(int new_think_countdown); Defined in Mummy int getThinkCountdown(); // If can sense Hero, enter seek state. void setDirection(enum direction_type new_direction); if (p_mummy -> senseHero()) { enum direction_type getDirection(); StateMachine *p_machine = p_mummy->getMachine(); p_machine -> changeState(StateSeek::getInstance()); // Return pointer to Mummy's finite state machine. return; StateMachine *getMachine(); } }; } The Mummy State Transitions Code Flow for State Machine • Initially: // Return true if Hero is within sensing distance. // Constructor. bool Mummy::senseHero() { – Define states as classes derived from State (e.g., Mummy::Mummy() { WorldManager &world_manager = WorldManager::getInstance(); // Set up state machine. Starts in “wander” state. StateWander) machine.setOwner(this); // If Hero is within box, then can sense. machine.setState(StateWander::getInstance()); // First, setup box. – Setup StateMachine (e.g., set starting state) machine.changeState(StateWander::getInstance()); df::Box sense_box; … df::Position p(getPosition().getX()-SENSE_XRANGE/2, • In Game � Step event } getPosition().getY()-SENSE_YRANGE/2); sense_box.setCorner(p); sense_box.setHorizontal(SENSE_XRANGE); – Get state from state machine sense_box.setVertical(SENSE_YRANGE); // Handle event. // Return 0 if ignored, else 1 – Call StateMachine Update() // Then, see if Hero within box. int Mummy::eventHandler(const Event *p_e) { df::ObjectList objs_in_box = if (p_e->getType() == df::STEP_EVENT) { world_manager.objectsInBox(sense_box); – StateMachine Update() calls State Execute() of derived machine.Update(); // Update state machine. df::ObjectListIterator oi(&objs_in_box); return 1; class for (oi.first(); !oi.isDone(); oi.next()) { } df::Object *p_temp = i.currentObject(); … if (p_temp -> getType() == "Hero") • e.g., StateWander calls Mummy senseHero() return true; // Senses Hero! } – If so, tell state machine to change state } return false; // Doesn’t sense Hero. – Otherwise, execute state action (e.g., Mummy wanders) } 4

  5. 3/24/2016 Finite State Machines Summary Pros Cons Simplicity � low entry level Predictability � can make for • • Simplicity � quick to design, easy-to-exploit opponent • implement and execute Complexity � Large FSMs Predictability � allows for easy • • difficult to manage and testing maintain ("spaghetti-factor“) Well-proven technique with lots of • examples Inflexibility � All states, • Flexibility � many ways to • transitions and conditions implement need to be known up front Easy to transfer from abstract • representation to coded and be well defined implementation Inflexibility � conditions for • Low processor overhead � only • transitions are rigid the code for current state needs to run, well suited to games Easy to tell reachability of state • 5

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend