Finite State Machines for AI in Actionscript

Posted on 15 January 2007

A few months ago I said I'd post about the AI in Stick Sports Soccer. Here, at last, is the first such post looking at the code used to implement the Finite State Machines in this and other games I've developed.

Often finite state machines are implemented (in real projects and tutorials) as a mass of code in a single class, usually a giant switch statement hundreds or (in one instance I've seen) thousands of lines long. A simple switch statement is great for a simple agent with two or three states, but the more complex the agent gets, both in the number and complexity of the states, the more complex the code gets. Using a switch statement also offers very little opportunity to reuse code across different agents and different projects (other than by cutting and pasting).

The solution I've used in a number of projects is to implement each state as a separate class. The class will contain all the code necessary for entering, updating and exiting that state and nothing else. This way, the code for each state is separate and the agent code isn't cluttered by it.

In this solution, each state implements the State interface, which looks like this.

interface State
{
public function Enter():Void; // called on entering the state
public function Exit():Void; // called on leaving the state
public function Update( time:Number ):Void;
// called every frame while in the state
}

Each state implements Entry and Exit methods for one-off actions that the agent takes when entering and leaving the state, in addition to the Update method which is run repeatedly while in the state. The time paramater in the Update method is the duration of the frame we're executing.

A couple of states for a patrolling guard in a shoot 'em up might look like this.

The agent class is a lot more manageable without the state machine implementation and all the states inside it, and I have a single StateMachine class that can be used by all agents. I can even share states across agents too.

Finally, I add a number of features to the StateMachine class to allow chaining of states and returning to previous states.

Having used this solution for a couple of years I can't imagine returning to the mess of giant switch statements, even for the simplest projects. And I use the same state machine, agent base class and many of the states themselves across multiple projects, which speeds up development time.