3

So I'm working on a roguelike, and planning to represent the monsters using a finite state machine

          spot PC
wander------------------->move
  ^   ^                    |
  |      \                 |
  |         \ killed PC    |
  |evaded       \          | close
  |                 \      |
  |         hurt        \  V
 flee<-------------------attack

However, I wanted to be able to change the monsters FSM, as the monster is modified. For example, in the game, it is possible the monster may have a health potion. In that case, the FSM should look like this:

wander------------------->move
                            |
                            |
                            |
                            | close
            used potion     |
       ,-----------------V  V
 use potion              attack
       ^-------------------'
              hurt

And then, once the potion is used up, return to the previous FSM. My thought is that I should change the FSM at the time the potion is given to the monster, so potion.give(monster) modifies the FSM at that time, and potion.use() unmodifies it. But I'm not sure how to implement this? How can the potion object know what states it should bind to, or transition back to?

One possible thought was to have the FSM state transition binding be a stack. So picking up a potion adds use potion to the attack['hurt'] transition stack.

Is there a best practice, or can someone link to an example of how to modify a FSM at runtime?

  • 1
    That really depends on your implementation of the FSM. How is the FSM designed (class structure) and choices for the next state made? – user40980 Nov 16 '14 at 4:41
  • I highly recommend that you get a copy of Programming Game AI by Example. Very nice book for beginners to mid-level AI programmers. – glampert Nov 16 '14 at 16:22
  • Also, be sure to visit gamedev.stackexchange.com – glampert Nov 16 '14 at 16:23
2

Lets assume we have a class that looks something like this:

class State {
  String description;
  List triggerStateTuple;
  Action onEnter;
}

Then you've got a list of (Trigger, State) tuples which you walk the list, select one, move to the next state and invoke the onEnter.

One approach to this is to avoid trying to do the 'this is getting inserted or removed' and instead build up the huge state table of all possible events with a more complex Trigger. Instead of working off of 'all items in the list are valid' it would instead have to do a 'check if this can be triggered'. The advantage here is that you build it once and its done rather than having to rebuild it on the fly.

That rebuild on the fly is where it is likely getting tricky for you. You need to know where to put the trigger (what states is it valid in?). What happens after the potion is drunk? Well, you would need to remove it from all the associated states. This gets rather messy too. The logic gets more complex... what happens if you have two health potions and your monster drinks one - gotta make sure you don't remove both of the triggers.

As you can see, this can get complex. When an item is added (or removed) from the inventory, it needs to add (or remove) itself from the different states that it can hook into. One could see modifying the tuple to also contain the object (for easy removal from the state).

When an object is added to the inventory, the list of states that it can hook into is pulled from the object and then all the states with a matching description have the trigger added. This involves some choreography of events. You're going to likely want a 'use' state that the object can link to that then when the action is triggered, invokes the action back in the object.

Though, I will also point out that 'use' isn't really a state. It's a one off event that doesn't change the state from 'attack'.


When reading through this, this becomes something that feels more like a rules engine than a simple FSM. The logic is getting more complex and you can start to suffer with difficulties debugging it. Instead, you might want to look at an embedded rules engine of some sort and then coding against that.

In Java, the rules engines are things that you can find looking for JSR 94. Other systems have their own ways to implement rules engines (DTRules has its own DSL). Some approaches are straight up implementations of prolog.


The approach that nethack has for the 'can a monster use this' is in Muse.c which is a huge, hard coded decision tree.

So... your alternatives:

  • Lots of hooks and book keeping on the finite state machine
  • A large, hard coded FSM (build it all out up front)
  • Using a rules engine or rules oriented language
  • A large, hard coded rules engine (nethack)
3

One way you could implement this:

          spot PC
wander------------------->move
  ^   ^                    |
  |      \                 |
  |         \ killed PC    |
  |evaded       \          | close
  |                 \      |
  |  hurt and no potion \  V
 flee<-------------------attack
                         ^ |
                         | |
             potion used | | hurt and have potion
                         | |
                         | v
                      use potion

Although you probably would want to separate between strategy and tactics. Strategy can be modelled as a state machine, while the tactical parts of the monster can be modelled with a rules table as described in another answer. The monster strategy is basically the monster's "mood", either the monster is in a "fight" mood or "flight" mood. A monster may switch to "fight" mood when he's healthy or just recovered, while they can get into "flight" mood when they're low on health or when they encounter an opponent far above their own level. When the monster's strategy changes, then the rules table also changes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.