Finite State Machine

Started by
6 comments, last by mintfresh 20 years, 3 months ago
Hi I''m writing a game, that features numerous animals that will "live" in an enviroment. I have decided on using a finite state machine to model the animals behaviour. Looking around I have come across lots on the theory of a finite state machine and feel that I understand how they work and have designed the states of my animals. However, although I have found a few code examples, I am not really sure how to go about implementing my own. I am using C++, and would probably like to go for an object orientated approach, as the rest of the code will be. So basically what I''m looking for, is either basic examples, or just an explanation of the general approach to take, e.g. what objects would be need, and what would need to be handled by them. Thanks
Advertisement
They way I roll a FA is just to have a large enum in the beginning which has all the states, then a large switch statement that takes you to the correct bubble, then I do my logic in that bubble and break out of the switch statement.

Its messy though, anyone have a more elegant solution?

~~~~~
"One Reality is worth one thousand dreams"
Download and play Slime King I.
~~~~~Screaming Statue Software. | OpenGL FontLibWhy does Data talk to the computer? Surely he's Wi-Fi enabled... - phaseburn
Get the Games Programming Gems books 1 & 2 (I think, might be 1 & 3).

One shows fuzzy state machines and one shows finite state machines with a clean approach.

~Graham

----
while (your_engine >= my_engine)
my_engine++;
Thanks for the information. I was thinking of buying a book, so I got Game programming gems 2, as a review on amazon said it covers finite state machines.

If anyone else has any other ideas then that would be useful.

Thanks again.
quote:Original post by dede
They way I roll a FA is just to have a large enum in the beginning which has all the states, then a large switch statement that takes you to the correct bubble, then I do my logic in that bubble and break out of the switch statement.

Its messy though, anyone have a more elegant solution?

~~~~~
"One Reality is worth one thousand dreams"
Download and play Slime King I.


Yeah that''s the way I do it too.

Though, the really OO way to do it would be to have an abstract State class, and each of the states are derived classes.

But yeah, enum and switch statements work great for me. I make sure to include the following things to make it cleaner:

- a function setState(int state) to change the state, which includes two switch statements: one switch on the previous state to do any end-of-state logic, and a switch on the new state to do beginning-of-state logic
- a function finishState() which is called at times where you know you want to end this state, but not sure where to go next (so this function ends up calling setState)
- a variable m_ticksInState, which counts the number of game ticks you have been in this state. So this variable is set to 0 by setState(). I use this variable *all* the time, in the most random places
Fine. OO way. Here is some Java code, adjust syntax as needed. This version implements a pattern called "Run and return successor".

class MachineState {  // Each subclass of MachineState represents a state that the   // machine can be in. The base class represents a ''terminal''   // state - in your context I guess that would mean the animal  // is dead?  private Animal parent;  public MachineState(Animal parent) { this.parent = parent; }  public MachineState act(Object[] input) {    // use whatever inputs are appropriate (presumably things that    // the animal senses in its environment.    // In the logic here, make parent.foo() calls depending on    // the input values. (I.e. override this method for each    // subclass)    return this;    // there is no action during, and no escape from, the terminal state.  }}class BornState extends MachineState {  // the initial state. Fill in as needed.  // Similarly for other subclasses.}class HuntingState extends MachineState {  // etc.}// etc.class Animal {  // ...  private MachineState currentAction;  public Animal() {    currentAction = new BornState(this);  }  // in C++, you''ll probably need a destructor to free up the   // state when the animal dies. Be careful :)    // Called by the simulator main loop.  public void act() { currentAction.act(senseEnvironment()); }  private Object[] senseEnvironment() {    // fill in as needed  }  // Now we add callbacks (need to be accessible by the   // machine states; you could use packaging in Java, or the  // ''friend'' mechanism in C++, but I''ll just show them as public)  // which let the MachineStates tell the Animal what to do.  public void murder(Animal enemy) {    enemy.currentAction = new MachineState(); // terminal state, remember  }  public void eat(Food f) {    // etc.  }  // etc.
Just want to say thanks alot for the code, looks easy to understand, especailly since you put it into the context of my program. Should give me enough to get started, will look at it in detail and try to implement somthing. Will post again if I run into any more problems.

Again, thank you very much for your help.
The "Quake" way of doing it is to have (a pointer to) a "think" function that gets called every time the entity is updated. So a state change would look like:

this->think = dog_HumpPlayersLeg;
this->nextthink = current_time + 0.1;

The think function contains everything that the entity needs when it''s in that state (such as rules for deciding when to switch to another state). The nextthink timer determines when the entity needs to be updated. For example, an idling AI might only check its environment once a second or so, while in combat it would "think" more rapidly.

This topic is closed to new replies.

Advertisement