Different FSM patterns - your experience?
Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit
Author of the book, Behavioral Mathematics for Game AI
Blogs I write:
IA News - What's happening at IA | IA on AI - AI news and notes | Post-Play'em - Observations on AI of games I play
"Reducing the world to mathematical equations!"
From my own experiences, the different approaches have paralleled my OO programming development. I used to build agents that did not explicitly implement a FSM to manage their logic. The logic was just built into the agent design. There was typically an interface layer (sensors and actuators) and an internal agent function that produced the mapping from sensors to actions. The FSM was implicit in that agent function. This worked reasonably well for single agents and robots I was playing with, but as soon as I moved toward multi-agent simulations and game environments, I found myself duplicating work between agents.
Once I'd started reading some of the Game AI literature I came around to the idea of explicitly designing the FSM class to handle the logic processing. Eventually I took up the state design pattern that is quite prevalent today and encoded states as classes. However, I've come to find problems with that recently. You can't do it in infinite state spaces (for obvious reasons), so if your domain is continuous and not easily discretised, you end up either going back to implicit FSM design, or you take a different tack; encoding agent behaviours as 'states' and then determing the outcome of behaviours depending on the current domain state. This becomes most useful when the outcomes of the agents behaviour depend on the external environment state. I've subsequently noticed that many examples in the game AI literature actually do this.
At the moment I'm tackling a generic behavioural machine class that incorporates parameterised behaviours. An example of the use of such a machine would be in high level behavioural description of an aircraft. You can define behaviours like turn, climb, descend, land, takeoff, etc., which given parameters become commands. The parameters change the execution of the behaviour depending on factors internal and external to the agent.
My final conclusion? I tend to favour the state-as-class design pattern. It's easier to handle things like logging, easier to manage the extension of the state space and ultimately I believe it makes you think more clearly about state flow logic, because you can separate out the logic of flow control.
Cheers,
Timkin
Handling Complexity in the Halo 2 AI
I recommend a read of the book it is really good. The FSM section of the book is available online.
http://www.ai-junkie.com/architecture/state_driven/tut_state1.html
In my opinion, for smaller FSMs where the states have more differences than commonalities, there's little reason to go with the OO approach. The "game state" FSM of an application is a good example of this. Most of the time with AI, though, this pattern emerges accidentally, as a boolean variable or two grow into a more complicated state space. So I do think this idiom is overused.
In situations where there are "things about" the state, the OO approach really comes into its own. As an example, I use a state machine to maintain the current action of a character. In addition to doing whatever it needs to do, I can determine under what circumstances the action can be interrupted, and other useful properties. Doing this without classes would require parallel switch statements, which are an absolute pain in the ass to maintain.
Overall it's a nice system, but the above problems had me re-thinking using it, and either replacing or modifying it to consolidate the desirability calculations as part of a more persistent goal class, which turns out is what the Halo2 article is about and more. Additionally, I'm doing low level states that are run simultaneously with high level states, which is part of the FSM design as well, so another bonus over the goal approach. For example, there is a low level FollowPath function that is responsible for moving the agent along a path. I prefer this method greatly over a queue of tens or hundreds of Goto goals, whose seperation into different class instances really serves little purpose imo.
Quote: Original post by DrEvil
I prefer this method greatly over a queue of tens or hundreds of Goto goals, whose seperation into different class instances really serves little purpose imo.
I don't think any sane person would actually implement a long sequence of waypoints on a path as instances of a 'waypoint class', or at least they wouldn't once they had more than a few waypoints along a path. Of course, there is a natural mapping between that and a path following behaviour through the specification of a path class that can respond to agent queries about coordinate locations along the path (which the agent may steer toward, or move through, etc).
One thing I'd like to hear feedback on (so long as it doesn't hijack the thread from IFs original intent) is this prevalence of state machines as 'behavioural machines'. I read through the Gamasutra article linked above and noted that the Halo 2 HFSM was another example of this design pattern. This, at least to me, appears to be a perversion of the classic FSM, but one that is quite relevant and useful in game AI design, which is often concerned with designing actors that instantiate gameplay requirements. Do others find it useful to work/think/design in this behaviour space and if so, why? If you do, how are you positioned with regards to the original question in this thread: do you prefer to encode such behaviours within the agent, or in a separated machine+logic idiom?
There's no real getting around it. If you are lucky, you have some intuition about your problem domain and you can pick the style that suits it best.
I'm not a Gamasutra member, so I can't read the link. While the theory of FSM's is interesting, I really doubt game AI programmers use them for this reason. Really, people use FSMs because they allow you to specify behavior using a simple causal framework. It encapsulates the if-then-else decision making process that everybody is familiar with.
However, I had also used Steve Rabin's FSM class from Game AI Wisdom (it was also in a Gems book). He has a very easy way of setting up a sequence of FSM states using what are (behind the scenes) actually macros. It makes it very easy to identify your states and have logic for "on enter" "on update" and "on exit". It's easy to read and program. But... it means that all your transition and action logic is in that one function (and it gets lengthy when you have a lot of states) or for readability you have to split it out to other functions that are called from inside that State function. Now you have started to scatter what was once a very streamlined collection of stuff. *shrug*
Again, benefits to both...
Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit
Author of the book, Behavioral Mathematics for Game AI
Blogs I write:
IA News - What's happening at IA | IA on AI - AI news and notes | Post-Play'em - Observations on AI of games I play
"Reducing the world to mathematical equations!"