PDA

View Full Version : Finite State Machines



cragwolf
27-01-2007, 11:01 AM
I understand that finite state machines (FSMs) are used very often in game AI, but I don't know much about them. Do you understand them, and have you used them in your game project? From reading this article (http://ai-depot.com/FiniteStateMachines/) I have a feeling that FSMs would be very amenable to object-oriented design, but I'm not entirely sure how to go about doing it. I would like to hear your thoughts on the subject.

tanffn
27-01-2007, 01:59 PM
I never quite understood why FSM enters the AI realm, nowadays too many topics fit into the AI category..

Anyway the idea of FSM is simply a case, which in each node you can have several options, for example an enemy in FPS:

Our object can be: [hurt, healthy, hiding, hunting]
Case object_state:
Hurt: do hiding.
Healthy: do hunting.
Hiding: do hiding until Healthy.
Hunting: do hunting until hurt.

Of course it should be a lot more complicated with several cases for each state in order to accomplish a believable “smart/real” enemy.

Robert Kosek
27-01-2007, 02:56 PM
One way to do it would be instead of using an enumerated type, use a straight integer with defined constants. So you could have a variable called state with a substate variable that defines the action. That way you don't have to mix enumerated types up.

In the case of a soldier:

const
STATE_HURT := 1;
STATE_HUNT := 2;
STATE_CAMP := 3;

SUB_SEEK_HEALTH := 1;
SUB_HEAL_SELF := 2;
SUB_FLEE := 3;

SUB_SEEK_TANGO := 1; // Tango is a callsign/slang for enemy
SUB_SEEK_AMMO := 2;
SUB_SEEK_COVER := 3;
SUB_FIRE_AT_WILL := 4; // 'cuz "weapons free" doesn't count when WILL is here. :P

SUB_WAIT := 1;
// Reuse SEEK_AMMO and SEEK_COVER; though both are required for a camper
SUB_HOLD_FIRE := 4; // In case a tank comes along


So then you do nested case statements to achieve the desired effects, and you may even have to create functions for each so that you can reuse parts of your code.

WILL
23-04-2007, 06:59 PM
Seeing as how the AI forums have been dead quiet lately, I figured I'd revive this thread.

One of the ideas of a FSM (Finate State Machine) is to have a setting and a series of behaviors attached to that specific setting. You'd of course have a series of these and they would make up the whole of your FSM.

An example of how a state machine can be used is my robots main 'modes' in Subject 33.

These are some enumerated types from my game for use in my TRobot object. (Sorry, I just like 'em! ;))

TRobotState = (rsSearch, rsEvade, rsAttack, rsScan);
TRobotCharacteristics = (rcAggressive, rcEvasive, rcTactical);

TRobotState is my main setting for each robot. Each robot can be considered an individual state machine. The robot will perform the following actions when set to one of these settings:

rsSearch -- Set when the robot doesn't have anymore leftover objectives and has no idea where any of the players are. He goes about his code to search for more humans to kill. (I use this as my default state because it's what the robot will find it's self doing most of the time.)

rsEvade -- Set when the robots feels it's time to back out and run. (Most likely for self-preservation.) The robot will follow it's code that tells it how to run and hide from the player or threat(s).

rsAttack -- Set when the robot sees the opportunity to attack a player. He then follows his code that tells him how he should attack the player.

rsScan -- This one was added as an aid to the rsSearch mode. Instead of moving about to look for the player, the robot will instead stay still and use his other scanning means to find the players. This includes ultrasound, infrared, movement, etc. Once done if no player is found he'll go back to rsSearch mode.


Notice how each mode the robots does a different set of tasks? These are the individual States which make up the whole agent. Change the state, change the set of tasks and behaviors.

Also you'll notice that with each state you have a different means of switching between the different states.

Example:

In search mode:
if it sees a player he'll go into attack mode.
if some time goes by or he reaches a new checkpoint it'll go into scan mode.


In attack mode:
if it sees shots fired at him, it may go into evade mode.
if it loses the player, it will go back into search mode.

In evade mode:
if it no longer sees the shots and some time goes by, he may go back into search mode to find the player again.

And so on... I think you get the general idea.

Hope this fills up any blanks. ;)