Latest Trailer

Throw a wrench, change the galaxy.




Screenshots

Mostly nebulae.



Release date

No idea - sign up to be told when it's out



Platforms

Windows for sure, dunno about others



Testing

Get on the mailing list, I'll e-mail it when there's a way to do that



Team

Design, Code, Writing

Tom Francis

Art

John Roberts

Music

John Halpart

Site

Tom Francis
John Roberts

Adaptive Images by Matt Wilcox

Mailing List

We only mail you to invite you to closed alphas or tell you we released a game

 



Heat Signature Guards Patrol

Help Me Learn Finite State Machines For Guard AI In Heat Signature

I have long known that ‘Finite State Machines’ are a thing I should be using, but when I try to read up on them, the explanations are either hopelessly vague or incredibly specific to a language and situation I don’t understand.

I whined to Mike Cook about this, and he said something to the effect of, “When you read up about Finite State Machines, it sounds like they’re this one specific agreed-upon thing, but every time you talk to an actual programmer about them you’ll get a different version of what they are.”

But! I am determined to try them in Heat Signature, and I have just reached that point where there’s enough AI an animation stuff going on that I need some kind of system to manage it. So I’m going to explain how I plan to use one, and if you’re a programmer, perhaps you can warn me of any problems I’m making for myself.

If you’re not, or if you’re learning, maybe you’ll get something out of how hopelessly I’ve failed at this so far.

5005328528_867bd8e88a_o

How I Did It In Gunpoint

Guards did have a ‘State’ variable in Gunpoint, which I’d set to things like ‘Patrolling’ or ‘Preparing to fire’. But every time I wanted to change state, I’d have to check against all the possible states that should ignore this change. That was a pain, because every time I added a new state, lots of code in lots of different places needed to change.

Example: When a guard sees the player, he should go into the ‘Preparing to fire’ state. Oh, unless State = “Dead”. Then later, when I added a separate “Unconscious” state, I’d have to find all the places I made an exception for “Dead” and also add one for “Unconscious”.

I tried to alleviate this by having extra variables for broader concepts like “Mobility” – if the guard can’t move, I don’t care if it’s because he’s dead or unconscious or held down by the player, he shouldn’t run to investigate noises.

The problem was that I had to remember to add “Mobility = false” to all the different places that might set a guard’s state to “Dead” or “Unconscious”. And the more properties like that I added, the messier it got.

Heat Signature Guards Knocked Out

What I’m Planning For Heat Signature

Clearly, the problem boiled down to “Given our current state, can we change to new state X?” There will always be special case exceptions to that, so my attempt to boil things down into broader concepts like ‘Mobility’ would never be a full solution by itself. So I think for each state, there will have to be a list of states we can’t change to from there.

What would be helpful, though, was if there was only one such list for each state. Only one place in the code where we define those exceptions. It’ll still need maintaining and updating as the possible states and transitions change, but just the once. Then it would be much easier to maintain and the complexity wouldn’t increase when we called it from more and more different places in the code.

It could also set any useful broader variables like ‘Mobility’, and as long as it’s the only bit of code that ever changes state, we can be sure that those will always be set consistently for any given state we’re changing to. Every time we change to Dead, for example, it’ll always be this piece of code that runs it, so if it says ‘Mobility = false’, there’s no way we can ever die with our Mobility flag on, something our grandparents warned us against.

So specifically, I’m thinking of a function that says something like this:

ChangeEnemyState(NewState)

//See if we should change state

if State = “Sitting” {

    //No exceptions, always change regardless of new state
    State = NewState
    
} else if State = “Dead” {

    //No valid transitions, ignore
    
} else if State = “Unconscious” {
    
    if NewState = “Dead” {
        State = NewState
    }

}

//Set properties of new state (regardless of whether we changed)

if State = “Sitting” {
    
    Moving = false    //Not moving
    Mobility = true    //Can move if we need to
    Shootable = true
    
} else if State = “Dead” {

    Moving = false
    Mobility = false
    Shootable = false
    
} else if State = “Unconscious” {

    Moving = false
    Mobility = false
    Shootable = true
    
}

Does that make sense? Any problems I’m going to run into? Is that a Finite State Machine?

Edit: Thanks everyone! I have a much better idea of how they’re meant to work now. Lots of different implementations suggested, so I’ll pick the bits that make the most sense to me and that I already know how to do in Game Maker Language.

More

Rich Wilson: The way I've handled it in the past is to give each state its own update function. When you change states, you point the update to that new function. That way you can handle all of the transitions from the perspective of the current state only.

Your new ChangeState would just change the state variable and point the update function to the new state's update function. I don't know if gamemaker has function pointers, but there's probably something similar. Worst case you could do a switch statement in your update that executes the proper update function. (kinda gross)

Another thing to consider is code you might want to execute for each state during its init and shutdown, to clean up or set up any pertinent data for that state.

Chris Johnson: Perhaps this falls into the too-language-specific category (C++), but have you seen this chapter http://gameprogrammi... ...state.html in Bob Nystrom's 'Game Programming Patterns' (shortly to become a book)?


A comment on "Guards did have a ‘State’ variable in Gunpoint...But every time I wanted to change state, I’d have to check against all the possible states that should ignore this change". In a pure FSM implementation, all of the behaviour code is specific to a state, so the ProcessGuard function would look like

if (state="patrolling")
{// do all behaviour processing for patrolling state }
else if (state="dead")
{// do not much }
else if (state="pursuing")
{ // do code for when guard is pursuing }
etc.

The code for behaviour processing for each state might include code to change the current state, which will affect which part of the ProcessGuard function is executed in subsequent frames. This has the advantage that you don't have to check against potential states which ignore a change -- because the code is separated by state, you simply don't include that state transition in the code for the current state.

The disadvantage of this is that code in some states might be very similar, and so there is potential for a lot of duplication in the code that deals with each state. There are (at least two) solutions to this. One is to factor this common code out into separate functions, and then just call different sets of these functions in each state. Another option is to use a hierarchical state machine (see the Game Programming Patterns link above).

Adam: In my opinion, an easier way to implement it would be with a series of objects which contain the possible states they could change to.

Eg:

Sitting:
NextStates[Dead, Unconscious, Chasing, Firing]

Unconcious:
NextStates: [Dead]

Dead:
NextStates[]

Then you can throw state changes at your guards and see if that state is viable by checking if it's in the NextStates array. Plus you could put a function into the object that runs when the state is changed to this one.

No idea if this is the "right" way but it's what makes sense to me in my official capacity as "Some Guy"

Adam: Also, is there any way to put dividing lines between comments as I'm reading them all as one solid wall of text.

Sam: It is a finite state machine. Hooray!
But I would consider it a slightly messy finite state machine. Boo.

If being able to move (and shoot, etc) is to be tightly bound to what state someone is in, it would be tidier to explicitly make that the case. Rather than relying on always setting isAbleToMove false when transitioning in to a dead state. Having isAbleToMove as an independent variable leaves open the possibility for it being set without an associated change in state. You set someone as dead, then some far off function you forgot about sets isAbleToMove to true and you have an amusing bug.

I was going to suggest a possibly over engineered solution, but instead this is closer to your current plan and removes the risk of that kind of bug. You could also just have isAbleToMove marked as only able to be changed from within the Enemy class, but this solution makes it nice and clear that being able to move depends entirely on what state the enemy is in.

Create an Enum for all possible states. Look up isAbleToMove, isAbleToShoot, etc. by checking what the current state is, rather than by setting them when the state transitions. Otherwise keeping the same type of logic for checking if you can transition to a given state should be fine. But using an enum instead of a string is a better fit as you only ever want the state to be one of a few specific values, and not accidentally set to "hello world".

enum EnemyState {
Idle,
Alert,
KnockedOut,
Dead
}

class Enemy {
EnemyState state = Idle;

public bool isAbleToMove() {
if (state == Idle || state == Alert) {
return true;
} else {
return false;
}
}

}

(My personally preferred way would be to use a class instead of an enum, so you can have all the information about what it means to be in a state of Dead within the class definition of Dead. As it is we're defining that along with what it means to be Alert, KnockedOut, or Idle within Enemy, which is less tidy to me.)

Martin: That is actually a state machine! Everyone's first state machine looks like that. After you've done that a few times and ended up with a bit of a mess, you will add a level abstraction to it, but hey, one step at a time. :-)

Cory Sponseller: You're already getting lots of implementation suggestions, so I'll just go ahead and say that it looks like you do indeed have a finite state machine. You've got some pre-defined states and only one of them can be the active one.

I'm learning this stuff myself, and I guess I'd just advise not overthinking it. I spent a lot of time worrying, "oh god, FSMs sound complicated, am I doing this right?" and kinda gave up. Later on, I found that I had created an FSM without realizing it, and, huh, they're really pretty simple after all.

Sam: Just realised this is being made in GML not C#, I think? In which case you probably don't have enums. In any case, having as much as possible refer back to an entity's state rather than a bunch of fiddly little variables is a good plan.

As other posters have suggested, the next level of finite state loveliness is to pull much of the logic in to the states themselves.

You could have a Dead class that extends EnemyState, providing functions that check if a given state is valid to transition in to, and values defining if the enemy can move and shoot while in this state.

What's particularly nice is each EnemyState class will have begin() and end() functions that are called during state transitions. It can handle things like calling for the correct animation to be displayed, triggering alarms, or whatever else should happen. "Tidiness" comes in here too, as now you can have everything about what it means to be Dead all within a class definition rather than sprinkled around other parts of the game logic.

You can end up with the Enemy class being tiny, and passing on almost all logic to the current state. So every EnemyState class could have a onPlayerEntersView() function, which for the Idle state might trigger a state change to have them start chasing (or fleeing), while the same function on the Dead state would do nothing. That design is great for avoiding the kind of bug that has enemy corpses turning to face players when they make a loud noise.

Alan: People above have described the basic FSM; I don't think I can add anything to that.

If you're looking for complex behavior, a traditional FSM can be unwieldy. You might want to look at http://alumni.media.... ...f_fear.pdf My recollection is that a similar idea is at the heart of L4D's dialog system, but I can't review the video at the moment. http://gdcvault.com/... ...og-through

Andrew: Immediate answer to your questions: Yes. Some. Yes.

Because you're packing all the state transition behaviour into one big method, you'll find it grows very large and unwieldy as the game grows in complexity, but with GML's limited polymorphism I'm not sure there's a huge amount you can do about that.

You might find it easier to simply store all valid transitions in a long, 2D array. You create the array at the start, then when you want to make a state change you scan through the array to see if the transition you're asking for exists - if so, make the transition, else return. E.g.

validTransitions[0,0] = "Sitting"
validTransitions[0,1] = "Dead"

validTransitions[1,0] = "Sitting"
validTransitions[1,1] = "Unconscious"

validTransitions[2,0] = "Unconscious"
validTransitions[2,1] = "Dead"

(Or even better, load all this from a file, and store the file in an easy-to-read/edit format)

You'll note that there are no transitions in the list that start with the "Dead" state, so any attempt to change from this state will be ignored. It's a little limiting in that you don't get the catch-all behaviour of "Sitting" allowing any transition, but you can easily add that with a special "AnyState" value or similar.

So your state change code might look like:

for(i = 0;i < array_length_1d(validTransitions);i++)
{
if State = validTransitions[i,0] And
(NewState = validTransitions[i,1] Or validTransitions[i,1] = "AnyState")
{
State = NewState
}
}

The best part of this is that you can have different arrays for different enemies, and so give each one variations in behaviour without having to write multiple update methods.

[Part 1 of x]

Jeff W: GameMaker finally added enums, actually, Sam. Only as recently as this past July, but they are there.

David: I find that the best way to handle state machines is in an object oriented manner.

You have a base State class, and then every other state inherits from State or a child of State.

This allows you to have a state like 'Alive' under which all your alive sub-states, err, live. Each child state can override behavior defined in its ancestors if necessary, or leave it alone.

What's really great is that if you make states into objects, the NPC using it doesn't have to know anything about the particular state its in. You can just ask the state if you can do a certain thing and it'll tell you.

This is a very hard explanation to do without diagrams. I hope someone can do better then me :)

Andrew: To store all the other data that goes along with the states (again, because GML doesn't seem to have a full data structure/class model) you can store a second array, with each state listed against the behaviours (e.g. Mobile, Shootable, Moving) that it supports.
To do this efficiently, we're better switching to numerical values with names, rather than using strings for everything. Start by defining your behaviours:

Mobile_Flag = 1
Shootable_Flag = 2
Moving_Flag = 4

Then create your array of behaviours, by state:

stateBehaviours[0,0] = "Sitting"
stateBehaviours[0,1] = Mobile_Flag | Shootable_Flag

stateBehaviours[1,0] = "Dead"
stateBehaviours[1,1] = 0

stateBehaviours[2,0] = "Sitting"
stateBehaviours[2,1] = Shootable_Flag

We're storing the set of behaviours as Flags - binary values, ORed together to form a number that represents the full set. You extract the behaviours for a given state by:

for(i = 0;i 0
Shootable = (stateBehaviours[i,0] & Shootable_Flag) > 0
Moving = (stateBehaviours[i,0] & Moving_Flag) > 0
}
}

Andrew: As my last code snippet contains greater-than and less-than symbols, the comments system has removed chunks - lets see if this works better:

for(i = 0;i < array_length_1d(stateBehaviours);i++)

{
if State = stateBehaviours[i,0]
{
Mobile = (stateBehaviours[i,0] & Mobile_Flag) > 0
Shootable = (stateBehaviours[i,0] & Shootable_Flag) > 0
Moving = (stateBehaviours[i,0] & Moving_Flag) > 0
}
}

Andrew: Ugh, and now I've spotted a typo - one last try:

for(i = 0;i < array_length_1d(stateBehaviours);i++)

{
if State = stateBehaviours[i,0]
{
Mobile = (stateBehaviours[i,1] & Mobile_Flag) > 0
Shootable = (stateBehaviours[i,1] & Shootable_Flag) > 0
Moving = (stateBehaviours[i,1] & Moving_Flag) > 0
}
}

Victor: Your description is very close to what I know about finite state machines but the concept here is mostly mathematical, I think. Definitions from theoretical standpoint are probably all overcomlicated, so I hope I remembered correct what it should mean. It's simple really.
You have some finite set of states, the current state and mathematical function that based on current state and input gives you next state of the machine.
I must say I learned this year ago and haven't used FSM yet, so I can miss some bits.
So, basically FSM is a math thing for a lot of stuff.

The Cheshire Cat: In the broadest view, a finite state machine is just a list of states and what input they'll accept, and what to do for each input (usually, change to another state). Rather than approaching it from the direction of a function "Change state" that checks your current state and sees if the new state is a valid transition, inputs should be passed to the character like "heard noise" or "got shot", and the current state should then be used to determine how to react to those inputs.

David's object oriented approach above is probably the easiest way to do it, since using polymorphism will handle this kind of thing in a very natural way, but if that isn't an option (I know GM isn't very good with OO stuff, but I'm not sure what you're using for this), you can still kind of simulate it by setting up your functions like:

heardNoise(noiseSource){

if state="patrolling"
{
goInvestigate(noiseSource)
}
else
{
//don't react to it
}
}

The key here is that you only need to write in behaviours for states where the input actually matters - notice I didn't specify what to do if the guard is dead or shooting at the player or whatever - if they're dead they shouldn't do anything at all, and if they're shooting at the player, they have more important concerns than a noise in the distance. Both cases are handled by the catch-all "else" at the end, though, which should be used in all actions to represent states where that input shouldn't result in any change in the state of the enemy. This approach also means that you don't have to have all the "meta state" variables like "Mobile", because states where the enemy is immobile like dead or unconscious simply won't be given actions in your movement function. In general the point of state machines is to try to limit the amount of variables you have tracking things like whether the enemy can move or is shootable because the state itself should already represent those behaviours. There are some things you probably want to track independent of state, like enemy health or ammo, but you can easily make use of those just by setting up statements like:

function playerSpotted()
{
if state="alive"
{
if ammo>0
{
shootPlayer()
}
else
{
runAway()
}
}
else
{
//do nothing
}
}

Where you're essentially treating variables like ammo as secondary inputs to your state machine.

mctribble: As you've probably noticed from other answers, you're starting to get into territory where you will wish you had a more powerful programming language than GML.

That having been said, you DO have a state machine. And it WILL work as intended. You might be able to clean it up a bit, but I honestly wouldn't worry about it too much unless that starts to get unwieldy or you happen to want to try it just to see if you can.

If you do want to clean up a bit, the main thing I would suggest is that if you can find a way to put all the AI logic into the states themselves, you can almost entirely avoid "special case" logic. For example, when you go to have the bot do something you check what state you are in and call the appropriate function for that state (normally called update()) and then it will do whatever happens to make sense for that state, and nothing else.

Normally I would suggest classes for that, but I don't think GML has them. Delegates are nice too, but I don't think GML has an equivalent for that either. You'll probably just have to use a switch statement to figure out which update() to call.

if you still find yourself changing a lot of variables around, then you can also give each state it's own init() function which would set variables to whatever you need for that state, so you only have to change it in one place. You can also give each one an exit() function if states need to clean up after themselves.

And if you need a clean way to define which states can change to which other states, the 2D array solution Andrew posted above works pretty well.

Otto Robba: You already have a finite state machine, as other pointed out. You can always refine the code as you go (which is what I find myself doing).

If I needed to create one today though, I'd probably go with 'isSomething' object properties thar are checked.

For example:

if (enemy.hearsPlayer) {
if (enemy.isSleeping) {
enemy.wakeUp();
} else if (enemy.isAwake) {
enemy.checkNoise();
}
}


It can get a bit long but it is clear & readable - just be careful with your side-effects (and be sure to set things to false when the character is killed, we probably don't want dead enemies to keep patrolling).

I find it easier to think of logic when using pen and paper, I solve the problem and then I have to "translate" the solution to code.

Flynn: Personally, I wouldn't do

ChangeEnemyState(newState) { }

I'd do

SomethingHappensToEnemy(event) { }, because an enemy should decided it's own state, based on what happens to it.

I'd end up with something along the lines of

SomethingHappensToEnemy(event) {
if (event = GotShot) {
if (state != Dead) {
state = Dead;
}
}

if (event = PlayerEnteredVisualRange) {
if (state == Patrolling) {
state = ChasingPlayer;
RaiseTheAlarm;
}
}

if (event = AlarmWasRaised) {
if (state == Patrolling) {
state = ChasingPlayer;
}
}
}

Jeremy: A few of suggestions:

1. Make sure you consider every possible transition. The problem with code of the form "if state == X then handle event A, B, C" is that its very easy to overlook some event/state combinations.

I find it useful to make a NxN array (spreadsheet, for example) for N states, and fill in all the events that can cause each state transition, where "empty" means its not a valid transition. For example:

from-> LIVE DEAD SHOOTING
to v
LIVE - resurrected fired
DEAD killed - killed
SHOOTING target - -

Depending on how it ends up looking (very sparse, long rows/cols of one event transitioning into one state - event KILLED -> state=DEAD - etc), you may decide to implement it as a decision tree predicated on states ("if state == A then { if event == X then state = C } ..."), or events ("if event = X then { if state == A then state = C }"), or do it in a completely table driven way.

2. Avoid representing the state in more than one way. Rather than setting a separate "immobile" flag for DEAD and STUNNED states, have a predicate function "isImmobile(state) { return state == DEAD or state == STUNNED }". That way you can't get your flags out of sync with the canonical state.

3. Related to 2, avoid encoding your state in more than one variable. If you do, it's easy to accidentally explode your state space without noticing or accounting for it. If you have "state" with N values, and "otherstate" with M values, and you have to take both into account when determining what to do, you effectively have NxM states, and again, its easy to overlook some transitions. Its much better to explicitly enumerate all the distinct states and handle them all, even if you end up with a whole bunch of states called X and X_WITH_Y. If you *do* end up with too many states, then you can reconsider whether you actually need them all, and either live with it or simplify.

It's particularly easy to do this by adding a handful of bools to represent various aspects of "otherstate" - after a while you end up with 3 or 4 and you either have 8-16x more states than you expect, or not every combination of flags is possible and it would be better explicitly enumerate the possible combinations.

Martin ?erný: I guess that the issues you describe are basically the reason why FSMs are being replaced in many games by behavior trees, which spare you the necessity to think of all possible transitions and make the behaviors goal-directed.

AiGameDev has some nice intro into behavior trees (free after registration) and you may also find example implementation to download.
http://aigamedev.com... ...ior-trees/
http://aigamedev.com... ...ration-bt/

But both with FSMs or behavior trees, remember that that the key to avoid craziness lies in enforcing a init - work - done lifecycle for your behaviors (states/tree nodes/...).

The logic is that "init" is executed when the behavior starts. If init fails, the whole behavior fails.
"Work" is called to perform the actual stuff. Work is never executed if init failed.
"Done" serves as a cleanup and is guaranteed to be executed before the character switches to any other behavior. The only exception is that "done" is not executed, if "init" failed.

So for a sitting behavior, you have:
init: perform a sitting animation
work: show idle sitting animation
done: perform stand-up animation

This way most of your transitions are implicit - simply perform first "done" of the old behavior and then "init" of your new behavior.

Miguel: I think there's a point nobody mentioned, excuse me if I missed it.

Usually FSMs transition between states based on events. With this, I mean that you should not think of having a function ChangeState(NewState) but rather as ChangeState(Event).

Doing it the first way, the code outside the FSM needs to know about the agent states and the coupling is increased. Doing it the second way, the code outside only needs to 'fire' events, to which the state machine will react according to the outward transitions defined for the current state.

Also, +1 to the suggestion of having entry, update and exit function at each state.

Implementation-wise, I'd go with somthing like each state having a set of function entry, update and exit pointers (or whichever GML allows) and a list of its possible transitions, with each transition containing the event that triggers it and the state it switches to. This way, the code managing the FSM would be like:

update(current_state, event)
for transition in current state
if transition.event == event
current_state.exit()
current_state = transition.next_state
current_state.enter()
current_state.update()
return current_state

Finally, there are LOTS of potential pitfalls with FSMs, and maybe using some dedicated implementation can help you with avoiding some of them. I've been using rfsm (Lua based) for a while for robotics applications and find it very nice indeed.

Miguel: Identation was messed up in the little code snippet I pasted. Should read a bit like:

update(current_state, event)
..for transition in current state
....if transition.event == event
......current_state.exit()
......current_state = transition.next_state
......current_state.enter()
..current_state.update()
..return current_state

Tony Sæle: Hi! Long time user of Game Maker here.

The first you'll want to know about is the switch statement.
http://docs.yoyogame... ...witch.html
It looks like this:

switch (State) {
case 'Sitting':
/*stuff for sitting*/
break; // <- This is important or you get a fall through
case 'Dead':
/* stuff for being dead */
break;
/*and so on*/
default:
/* probably raise an error because the game has encountered a state you didn't want it to */
}

You may also be interested in script_execute()

For instance, when you create a unit, you can do something like this:
StepScript = scrPatrollingScript

and then in the unit's step event:
script_execute(StepScript)

The reason this is fantastic is that you can do this when changing states:
StepScript = scrBeingDeadScript

Essentially allowing you to change out the unit's step event depending on their state. I find it the most elegant way of handling state machines.

Lovepreet: I usually have a state variable which I give a number to. Each number will represent a different state for the AI. Then in each state I will have scripts that only the AI can do in them states. So this is a basic implementation of how I normally do it:

switch (state) {
case 0 : // dead
scrDead(); // AI dead script
break;
case 1 : // idle
scrIdle(); // AI idle script
scrGetPlayerLocation(); // check how far player is, and change state depending on what state the AI is
break;
case 2 :
scrPatrol(); // AI patrol script
scrGetPlayerLocation(); // check how far player is, and change state depending on what state the AI is
break;
case 3 : // Check noise
scrNoiseCheck(); // AI noise check script
scrGetPlayerLocation(); // check how far player is, and change state depending on what state the AI is
case 4 : // shoot
scrGetPlayerLocation(); // check how far player is, and change state depending on what state the AI is
scrShoot(); // AI shoot script
break;
case 90 : // debug
scrDebug(); // debug script for testing stuff out
break;
}

Hope you found that useful.

st33d: The multiple states thing I tend to handle with Bitwise operations. There's a Game Maker primer here that goes into it a bit more:

http://gmc.yoyogames... ...pic=473795

But what you get with a bitwise flag instead of a boolean flag is the lovely flexible ability to combine tests for different states.

So say I want to test something whilst running and sitting:

RUNNING = 1 << 0;
SITTING = 1 << 1;
STANDING = 1 << 2;

st33d: And somehow I tab-posted. Fucking marvellous. Anyway.

Those are equal to 1, 2 and 4. Which nicely stand for these binary numbers:

001
010
100

It's like 3 separate switches. But we can stack them together:

test = RUNNING | SITTING;

which basically makes:

011

Great! Now everything is much easier to read. How about if I have a lot of stuff stacked together in one variable and I want to find one thing in there? We use the & operator:

if((test & RUNNING) != 0){
// do it
}

Consider line 311: https://github.com/st33d/Ending/blob/master/src/com/robotacid/engine/LevelData.as

I've tested for a bunch of properties in each direction there. But with a lot less if/else that if it was all in separate states.

There may be a better solution than a state machine. But your problem of having to test for a lot of confusing states can be compressed into a much more readable space that you can keep all in your head.

Jeremy: @Miguel - Yes absolutely! I'd meant to emphasize the state vs event distinction. I think its implicit in a lot of these discussions but its worth making a point of it.

Tom Francis: Thanks everyone! I have a much better idea of how they're meant to work now. Lots of different implementations suggested, so I'll pick the bits that make the most sense to me and that I already know how to do in Game Maker Language.

Stephen Davey: Just adding to the mix here. My work is primarily in Unity3d, so I follow the enum-switch approach in C#.

enum States {
Idle,
Run,
Jump,
Falling,
AttackTarget, //attacking whatever the "target" variable is set to
Unconscious,
Dead
}
States state = States.Falling; //pre-define some relatively safe initial state, from which the actor can quickly recover to a more desirable state

//this method is called when the actor is created, before the first Update()
void Start() {
. . //this function is explained later, but fits your idea of a method for setting state
. . SetStateUnchecked(state); //ensures state is set up before its behaviour code executes
}

//called once per frame, to update the actor's state
void Update() {
switch () {
. . case (States.Idle):
. . . . DoIdleState();
. . . . break;
. . case (States.Run):
. . . . DoRunState();
. . . . break;
. . //etc, for each state
. . //optionally: catch errant state values, if your chosen setup doesn't implicitly prevent invalid states
. . default:
. . . . state = States.Falling; //default to some safe catch-all state, or perhaps throw an error if debugging
. . . . break;
. . }
}

//example state handler, only ever called from Update()
void DoIdleState() {
. . //Ordered steps for state handling:
. . //1) Update actor based on this state.
. . //2) Detect change in state. Usually I pack checks into functions to
. . //. . keep them more manageable. To set the new state from within
. . //. . the FSM, I use a SetStateUnchecked() method, explained below.
}

There's also the possibility that an actor's state will be set by an external source, especially during testing. For simplicity's sake, in that case I add one or two wrapper functions for setting state.

//External scripts should generally use this method to set state.
public void SetStateChecked(State newState) {
. . if (state==newState) return; //we're already in the given state, early out
. . SetStateUnchecked(newState);
}

//Doesn't check if state is the same as before. Good for debugging
//by resetting current state and watching some behaviour play out.
//The reason the FSM owning this method uses this instead of
//SetStateChecked() is because you can be fairly sure you're not
//setting the new state to the old state, if using the design pattern described.
public void SetStateUnchecked(State newState) {
. . switch (state) {
. . . . //Each case() statement should handle cleanup of the old state
. . . . //Answering your question "", this would also be where you
. . . . //would check if you can change state.
. . }
. .
. . //now we've handled cleanup of the old state, set the new state
. . state = newState;
. .
. . switch (state) {
. . . . //each case() statement should handle setup for the new state, if needed
. . }
}

For broader concepts like mobility (I'd guess I'd call that a meta-state?), your idea of tracking them with boolean variables seems workable for FSMs with a handful of meta-states. An alternative I use is having boolean functions for each meta-state I want to check. This comes with a marginal overhead of evaluating a conditional statement every time you call them. But unless it's bottlenecking your performance, that overhead doesn't matter - not that it's at all likely to be a bottleneck unless you have tons of FSMs checking meta-state simultaneously!

The benefit of using boolean functions is simplicity of editing set values of / adding extra / removing unwanted meta-states. With boolean functions, you're not editing [number of states] lines of code to update one meta-state. You need only change one part of an OR-ed list of states. For FSMs with many states, it's a bit less error prone.

For some examples:

public bool IsInMobileState() {
. . return state == States.Idle || state == States.Run || state == States.Jump || state == States.Falling;
. . //Or alternatively, in this specific example, the State enum might
. . //more easily have mobile states added to it if instead you use:
. . //return state != States.Dead && state != States.Unconscious;
}

public bool IsInAirborneState() {
. . return state == States.Falling || state == States.Jump;
}

When I'm like @Flynn (above) and want to make an FSM determine its own state based on what happens to it, I tend to make methods that other scripts can call to indirectly attempt to set state. This logic stands outside of my strict enum-switch design pattern for the FSM, and somewhat embodies a meta-state that the FSM wouldn't know it was in without being told about it by calling the event-handling function. For a couple of examples:

public void OnWasPunchedByPlayer(Actor player, float damage) {
. . if (state==States.Dead) {
. . . . //show on-screen messages to egg the player on to upwards of 999 punches
. . . . punchCounter = punchCounter + 1;
. . }
. . else {
. . . . health = health - damage;
. . . . if (health<0) {
. . . . . . health = 0;
. . . . . . SetStateUnchecked(States.Dead);
. . . . }
. . . . else if (IsInMobileState()) {
. . . . . . target = player; //set the target this actor's going after
. . . . . . SetStateChecked(States.AttackTarget); //we haven't checked if we're currently attacking
. . . . }
. . }
}

public void OnWasRevived() {
. . //Create a revive particle effect + sound, or whatever.
. . //Place to somewhere just above the ground, to avoid any nasty
. . //on-spawn geometry intersection weirdness.
. . SetStateChecked(States.Falling);
}

Stephen Davey: Heh, I spent so long writing that that I didn't notice you'd wrapped up with a reply.

Tom Francis: Haha, thanks anyhow! I will still read and absorb.

Joshua: What if something that happens to the enemy effects them based on the state?
An example: when you get shot, you are made unconcious if you are not dead, or made dead if are already unconcious.
Your NewState variable is like what another function proposes for the next state will be, but if there can be more than one state it can change to, you have a problem.

Taha Nasir: It astounds me how this game is possible in GM! As a scrub programmer who is using GML, this is really helpful!

lyxar: To put it simply, a finite state machine simply is an "automaton" that is in one state at a given time, and it "loops" through this state until it decides to switch to another state.

Imagine programming without functions - only having GOTO. To get any kind of organization into your program, you'd probably divide it up into different states/modes - similiar to how early games were based on "screens" (each "screen" was pretty much its own program).

So yeah, finite state machine really just means a set of loops, and then switching back-and-forth between those loops. That is all - it's that generic.

The various issues you had before, are all about implementation details - they don't really have something to do with you understanding FSM, but rather with you having experience in how to solve problems via FSMs (implementation).

In my personal opinion, FSMs on their own are too limiting in their functionality. I always end up additional features - handlers/events (so, basically a plugin-architecture for states), or even a statestack to ensure that all functional programmers will be mindf*cked *g*.

lyxar: Sorry for double-posting - one more addition:
For any halfway complex AI, you will need something akin to a "tasklist" - basically a list of priorities for making decisions. This list would be specific to the AI-type, and it would often be this list, that actually decides about switching.

So, in this setup, it mostly isn't the states that do the switching - the typical AI loop would look like this:

1. Execute tasklist checks. If neccessary, switch state.
2. Execute current state - if requested, switch state.
3. Goto #1

So, all the checks you've come to hate so much, would basically be stored in an AI-specific "global state* that always gets executed before the normal state.

foo: ... This is really just an issue of doing good modelling. First, you need to distinguish between the physical state of an actor and their current action. For instance, being "dead" is a different "type" of state than "seeking cover".

You should also avoid redundancy, that means only storing in a variable what needs to be a variable, and implement anything that can be deduced from other variables as function. For instance, you can have an isMoving() function that returns false immediately if the actor is dead.

Brad: It's not so much “When you read up about Finite State Machines, it sounds like they’re this one specific agreed-upon thing, but every time you talk to an actual programmer about them you’ll get a different version of what they are" but rather "It's the sort of simple concept that gets covered in a semester programming _theory_ course, and then people spend twenty years arguing about how best to implement." D: Especially since each language or programming method is likely to make a different approach look more elegant or nicer than other mechanically equivalent approaches.

In my opinion, the most important thing when dealing with a finite state machine is writing out your diagram or documentation of how the machine is supposed to transition from one state to the other.

If you're making changes, update your diagram/documentation, then go through your code to make sure it implements your new diagram properly. Because finite state machines are all about compacting detailed and complicated transitions together, you don't want to try to keep the whole thing just in your head.

Chris: Hi I'm a CompSci student who just did a module on automata and state machines. Here are the notes if you want to have a look http://cgi.csc.liv.a... ...te1up2.pdf

Jeremy: In GameMaker I use enums for my state machines. It is a tiny bit extra to type but I feel it is much cleaner and easier to remember vs typing "patrolling" all the time.

enum GC_ENEMY_STATE
{
idle = 0,
patrolling = 1,
chasing = 2
}

globalvar GC_ENEMY_CURRENT_STATE;


// Set a state
GC_ENEMY_CURRENT_STATE = GC_ENEMY_STATE.idle;

// Test a state
if(GC_ENEMY_CURRENT_STATE == GC_ENEMY_STATE.patrolling)
{
// Patrol code
}

The enum doesn't have to be a integer either you can use a string and its fine.

enum GC_ENEMY_STATE
{
idle = "idle",
patrolling = "patrolling",
chasing = "chasing"
}

Ryan: Create a base state object that has properties on it, such as canMove or whatever. One of the properties should be nextStates which lists which other states this one can move into. Create subclasses to this with modified properties for that state. Assign one of these to each of your units or whatever, and write supporting code to enforce the nextStates etc.

I have no idea if this is a "state machine" or what, but it seems like a solid way to organize your states.

Pavel: Did you consider using Behaviour Tree(BT)? It is actuially pretty easy to understand(not so easy to implement, but you always can use other framework). BT workd perfect to maintain "states hell" and "transition pain" =)
Acctually I had recommended you to use BT in Gunpoint(I wrote you email about it long long time ago), but it looks like you missed it:-) But anyway, BT is still cool, and if you start Ai system from scratch it is good chance to try it.
P.S.
We use BT in our game, and it works perfectly.
P.P.S.
Sorry for my english.

JustAStateChange: If you look at games that handle modding every block of code that dictates behavior is placed in one file per object controlled. And the object will look to states listed (and hard coded as functions) to see what that thing needs to do.

For instance


Object name :


= true



# else where in another file

class set_as_animal:

{
on_these_states

do_do_these_things
}


# your functions someplace else


class Death

{

if object% #if anything declared as a type of object,

then

do_this_animation%_% # do this animation type

set hp_value% 0 #all you need now is a public float value somewhere for what happens when any objects health reaches 0, this can be anything in your game you deemed as an "Object"
}

yeah i guess I cant escape putting in else ifs because the code needs to disable stuff,

like if dead, become disabled and do nothing else, and then get deleted or transition into dead_type for self and transform other life state in same position to deleted state.

but im no programmer i just have read alot of modder files for games. and what makes stuff easiest is if your in-game objects have very few custom variables and simply call all their functions from public lists that can then be further individualized down the end of the code instead of at the front.

Tomasz Kaye: In case you need to do this kind of thing in unity in the future, I like the Statekit approach a lot: https://github.com/prime31/StateKit

Damien: Quicker solution: port everything to Unity and buy Playmaker: problem solved. You're welcome.

Richard Newman: Hi,

I dont know if this is late to the party - and i'm just a beginner myself, but - i think you could just use an Array for this?

so "sleeping" could have as many separate variables as you want, then the same for "pursuing" or "dead"

sorry if i dont explain this well but basically an array can hold a load of variables in a table format with several variables attached to a single Array ID...

here is a link to the GM tutorial - i hope i'm not being to low-brow here!

http://docs.yoyogame... ...rrays.html

Matt: // scr_state_movement
// Handles all steering behaviors, based on state, of calling enemy object

switch(current_state) {
// IDLE - Self-explanatory
case State.IDLE:
debug_state = 'idle';
break;

// WNDR
case State.WNDR:
debug_state = 'wander';
//
break;

// PRSU - Player sighted, move closer
case State.PRSU:
debug_state = 'pursue';
steering = vect_add(steering, sb_pursuit(obj_player, 1));
break;

// HOLD - Player sighted, has moved close enough
case State.HOLD:
debug_state = 'hold';
//
break;

// FLBK - Player has moved too close, fall back
case State.FLBK:
debug_state = 'fall back';
steering = vect_add(steering, sb_flee(obj_player.x, obj_player.y, 1));
break;

// SRCH - Lost sight of player, searching
case State.SRCH:
debug_state = 'search';
steering = vect_add(steering, sb_seek_arrive(last_sighted_x, last_sighted_y, 150, 1));
break;

// RTRN - Gives up on finding player, return to last patrol point
case State.RTRN:
debug_state = 'return';
steering = vect_add(steering, sb_seek_arrive(xstart, ystart, 150, 1));
break;

// HIDE - Health is low, GTFO of here!!
case State.HIDE:
debug_state = 'hide';
//
break;
}

if (moving) {
//Avoid solid objects
steering = vect_add(steering, sb_avoid(obj_solid, 100, 64, 1));

//Limit steering by max_force
steering = vect_truncate(steering, max_force);

// Limit velocity to max_speed
velocity = vect_truncate(vect_add(velocity, steering),max_speed);

//Add velocity to position
position = vect_add(position, velocity);
}

// Update position
x = position[1];
y = position[2];

This has greatly simplified the code and made it much easier to read a debug. Not sure how old this article is, but hope this helps.

- Matt