Finite State Machines

Transcription

Finite State Machines
Founda'ons of Game AI Level 8 – Finite State Machines Dr Alexiei Dingli The Theory •  Set of states •  Input vocabulary •  Transi'onal func'on T (State given Input) •  Denotes the change of an object over 'me In Prac'ce •  A state represents a behavior •  T defines how to transi'on to another state •  Accep'ng states represent the end for a FSM •  Input to the FSM con'nues as long as the game con'nues •  Can be easily represented using a graph In Games •  The NPC AI is a sequence of mental states •  World events can force a change in state •  The model used is easy to grasp (even for non-­‐programmers) E.g. Leaf carrying ant E.g. Leaf carrying ant E.g. Leaf carrying ant The FSM class public class FSM { private var ac'veState :Func'on; // points to the currently ac've state func'on public func0on FSM() { } public func0on setState(state :Func'on) :void { ac'veState = state; } public func0on update() :void { if (ac'veState != null) { ac'veState(); } } } The Ant Class public class Ant { public var posi'on :Vector3D; public var velocity :Vector3D; public var brain :FSM; public func0on Ant(posX :Number, posY :Number) { posi'on = new Vector3D(posX, posY); velocity = new Vector3D( -­‐1, -­‐1); brain = new FSM(); // Tell the brain to start looking for the leaf. brain.setState(findLeaf); } Finding the leaf public func0on findLeaf() :void { // Move the ant towards the leaf. velocity = new Vector3D(Game.instance.leaf.x -­‐ posi'on.x, Game.instance.leaf.y -­‐ posi'on.y); if (distance(Game.instance.leaf, this) <= 10) { // The ant is extremelly close to the leaf, it's 'me // to go home. brain.setState(goHome); } if (distance(Game.mouse, this) <= MOUSE_THREAT_RADIUS) { // Mouse cursor is threatening us. Let's run away! // It will make the brain start calling runAway() from // now on. brain.setState(runAway); } } Going back home public func0on goHome() :void { // Move the ant towards home velocity = new Vector3D(Game.instance.home.x -­‐ posi'on.x, Game.instance.home.y -­‐ posi'on.y); if (distance(Game.instance.home, this) <= 10) { // The ant is home, let's find the leaf again. brain.setState(findLeaf); } } Running away public func0on runAway() :void { // Move the ant away from the mouse cursor velocity = new Vector3D(posi'on.x -­‐ Game.mouse.x, posi'on.y -­‐ Game.mouse.y); // Is the mouse cursor s'll close? if (distance(Game.mouse, this) > MOUSE_THREAT_RADIUS) { // No, the mouse cursor has gone away. Let's go back looking for the leaf. brain.setState(findLeaf); } } Exercise •  Modify the code to add the transi'on from goHome to runAway E.g. Improved leaf carrying ant Stack based FSM •  Uses a stack to control states •  Top of stack = ac've state •  Transi'ons work by pushing and popping states 3 possibili'es public class StackFSM { private var stack :Array; public func0on StackFSM() { this.stack = new Array(); } public func0on update() :void { var currentStateFunc'on :Func'on = getCurrentState(); if (currentStateFunc'on != null) { currentStateFunc'on(); } } public func0on popState() :Func'on { return stack.pop(); } public func0on pushState(state :Func'on) :void { if (getCurrentState() != state) { stack.push(state); } } public func0on getCurrentState() :Func'on { return stack.length > 0 ? stack[stack.length -­‐ 1] : null; } } The Stack FSM Exercise: More complex Ant •  Descrip0on of Ant AI –  First, the ants will move randomly in their environment in an ajempt to locate a piece of food. Once an ant finds a piece of food, it will return to its home posi'on. When it arrives home, it will drop its food and then start a new search for water rather than food. The thirsty ants will roam randomly in search of water. Once an ant finds water, it will resume its search for more food. –  Returning food to the home posi'on will result in a new ant emerging from the home posi'on. The ant popula'on will con'nue to grow so long as more food is returned to the home posi'on. Of course, the ants will encounter obstacles along the way. In addi'on to the randomly placed food will be randomly placed poison. Naturally, the poison has a fatal effect on the ants. •  Can you summarize the behavior in an FSM? PacMan State Machine Timer <= 0
PacMan eats a
Power Pill
Timer <= 0
Collision with
GhostBox
Fall 2012
Collision with
PacMan
20
Actions of States
Roam;
If PacMan gets close,
PathTo (PacMan)
Timer—
Move back-and-forth
Timer--;
PathAwayFrom
(PacMan)
PathTo (GhostBox)
Coding the States Example: Cleaning Robot AI •  Single FSM operates with no problems •  However, the robot can run low on power and requires recharging •  Alarm mechanism: Interrup'ng the normal behavior to respond to something else important Example: Cleaning Robot AI •  Adding “Get Power” state to accommodate the alarm mechanism is not difficult à but number of states increase about x2 •  What if we have a “Hide” alarm that is another alarm behavior? Example: Cleaning Robot AI •  So, rather than combining all the logic into a single FSM, we can separate into several FSMs, arranged in a hierarchy •  Higher levels of hierarchy can respond to alarm behaviors Hierarchical State Machine •  Higher level: Operates the alarm behavior (to get power) •  Lower level (within the Clean Up mother state): Operates the cleaning up behavior Hierarchical State Machine •  H* state: “History state” that indicates which sub-­‐state (in lower level) should be entered (ini'ally) or resumed (if just returned from the higher level) Hierarchical State Machine •  It is possible to implement both FSMs separately, but a lot of switching between the two is required à implementa'on inefficiency •  Nested hierarchy: We are in more than one state at a 'me (on different levels), just keep track of mul'ple levels of states Cross Hierarchical Transi'on •  If the robot has no objects to collect (of found nothing useful), makes sense to go back to charging bay rather than was'ng power •  Transi'on from lower level state to a higher level state – Lower level FSM is reset, with no history record Hierarchical FSMs •  Expand a state into its own sub-­‐FSM •  Some events move you around the same level in the hierarchy, some move you up a level •  When entering a state, have to choose a state for it’s child in the hierarchy –  Set a default, and always go to that –  Random choice –  Depends on the nature of the behavior FSM Processing •  Polling –  Simple and easy to debug –  Inefficient since FSMs are always evaluated •  Event Driven Model –  FSM registers which events it is interested in –  Requires complex Observer model in engine –  Hard to balance granularity of event model •  Mul0threaded –  Each FSM assigned its own thread –  Requires thread-­‐safe communica'on –  Conceptually elegant –  Difficult to debug More FSM Extensions •  Fuzzy State Machines –  Degrees of truth allow mul'ple FSM’s to contribute to character ac'ons •  Mul0ple FSM’s –  High level FSM coordinates several smaller FSM’s •  Polymorphic FSM’s –  Allows common behavior to be shared –  Soldier -­‐> German -­‐> Machine Gunner Debugging FSMs •  Offline Debugging –  Logging –  Verbosity Levels •  Online Debugging –  Graphical representa'on is modified based on AI state –  Command line to modify AI behavior on the fly Weaknesses of FSMs 1.  Rigid modeling of behaviors –  Each character can only have one state at a 'me – straighsorward but limited 2.  Complex transi'on condi'ons can affect efficiency –  …if many condi'ons need to be checked 3.  Behaviors are determinis'c –  Designer pre-­‐determines the ac'ons and behaviors of the character, unlikely for it to respond out side what it was designed to Addressing them… 1.  Rigid modeling of behaviors –  Modeling mul'ple states in a nested hierarchy might help to construct more complex behaviors 2.  Complex transi'on condi'ons can affect efficiency –  Use decision trees in the transi'ons 3.  Behaviors are determinis'c –  Apply fuzzy logic to the transi'ons Exercise •  A Tamagotchi is a small virtual creature that lives on a computer. It starts as a 'ny egg and awer a few minutes it “hatches”. The user must feed the Tamagotchi, play with it, provide medicine when it is sick, turn the “light” in the unit on and off when it is 'me for the Tamagotchi to wake up or go to bed, clean its living quarters, discipline it, and check its status (age, weight, discipline, hunger, and happiness). The Tamagotchi can also call its owner when it needs assistance. The degree to which the owner uses (or abuses) each func'on has an influence on its welfare and development. The development of a Tamagotchi is a simple affair, progressing through four stages: “baby”, “child, “teenager”, and “adult”. A few weeks awer the Tamagotchi becomes an “adult”, it dies. •  Create the FSM of the Tamagotchi. Ques'ons? Case Study: Robocode •  Install Robocode •  Click on robocode.command •  Bajle > New > Select the AI > Start Bajle Case Study: Robocode •  How do we defend, search and ajack? Defend Search Ajack Case Study: Robocode •  First determine what states are needed –  Ajack, Evade, Search, etc •  Code up the FSM transi'on func'on •  Setup debugging –  Verbosity levels are a must Defense and Firing Power •  Enable your bot to dodge incoming fire •  Every 20 ‘'cks’ reverse direc'on •  Adds a circle strafe •  Selects a bullet power based on our distance away from the target void doMovement()
{
if (getTime()%20 == 0)
{
direction *= -1;
setAhead(direction*300);
}
setTurnRightRadians(target.bearing + (PI/2));
}
void doFirePower()
{
firePower = 400/target.distance;
}
Searching •  Reducing the scanner arc allows you to fire faster •  If a target has not been seen recently, spin •  Scan where the target is •  Wobble to make sure to find the target void doScanner() {
double radarOffset;
if(getTime() - target.ctime > 4)
radarOffset = 360;
else
radarOffset = getRadarHeadingRadians() absbearing(getX(),getY(),target.x,target.y);
if( radarOffset < 0 )
radarOffset -= PI/8;
else
radarOffset += PI/8;
setTurnRadarLeftRadians(NormaliseBearing(radarO
ffset));
}
Exercise •  Use the Robot > Editor to implement your own FSM based robot •  Hint: Look at MyFirstRobot or MyFirstJuniorRobot