Subscribe

DSL-FSM.. that kinda sounds like some wierd internet sub-culture. It stands for domain specific language - finite state machine. I proposed both topics as presentation material for the austin-ruby group that I meet with once a month. Steven Harms the organizer recommended both/either so I combined it into one piece of code as it actually works pretty well that way.

The DSL that I’m using is pretty small right now, which lends itself to easier understanding and explanation.

Ruby code tarball can be downloaded here.

A FSM is defined in a ruby script file without any class definition using the following rules:

  1. All attributes are specified in a method named ’setup’. Setup takes an argument hash which may contain arguments that can be used to setup a FSM entity.
  2. All states are specified by defining top level methods with the name ‘while<statename>’. These methods are called in a tick update while that state is active.
  3. All transitions are initiated by saying start :statename
For example the creature FSM is has a method:
def whileidle
target_nearest

start :chasing if @target

end
All FSM entity templates can be loaded in the world using world.load(’template-name’). The world is currently driven by a simple script named ’simulate.rb’ which allows you to single step the world simulation and watch all the state machines make their choices. There are some debugging tools available. You can list all active entities and dump the world grid.

World#load uses the Object#instance_eval method to evaluate the contents of the FSM definition in terms of a FSM base instance. The FSM class defines some methods that can be called within the FSM definition to control state transitions and to access common methods.

Practically speak this is a very simple way to enable easy extension of a system. It provides an easier path to refactor the individual state machines and lowers the barrier to entry for writing state machine code. Additionally, it would be nice to include certain types of behavior from modules so that state machine authors could have easy access to some of the methods currently defined in creature FSM. This would include methods like target_nearest.  You could also mix in native C modules to get access to things like a path finding grid.

Ideas for playing with the code:

  1. Make creatures pick up the ‘ammo’ entities
  2. Make creatures compete for the ‘fark’ entities
  3. Add a new term to the FSM for state transitions. The method names should be named ‘whenchangingfrom<statename>, whenchangingto<statename>, whenchangingfrom<statename>to_<statename>’ and should be executed when those state change patterns are matched.
  4. Allow entities to die
Some Notes:

A great article about some of the different types of DSL creation and the mindset from one of the coders at 37signals:

http://weblog.jamisbuck.org/2006/4/20/writing-domain-specific-languages

Careful of using missing_method, it bit me in the arse a number of times:

http://redhanded.hobix.com/inspect/theBestOfMethod_missing.html

It’s really hard to track down bugs related to methodmissing, any code you write inside an object implementing this needs to be carefully checked. It can also lead to blowing your stack when an error in methodmissing recalls method_missing.. and on and on.

This little gem is nice to keep in your back pocket when trying to raise a descriptive exception:

http://blog.nicksieger.com/articles/2006/09/06/rubys-exception-hierarchy

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Technorati
  • Reddit
  • Digg
  • del.icio.us
  • StumbleUpon
  • DZone
  • ThisNext

Related posts:

8 Responses to “Implementing a Finite State Machine with a Ruby Domain Specific Language”

  1. on 17 Jan 2008 at 5:55 pm v01d

    Hi, I thought of doing a ‘fsm’ module for Ruby, based on your idea to design it as a DSL. Just letting you know, since I don’t want to think I ripped your idea if you see the code on rubyforge or something. I had a non-DSL version at http://trac.v01d.com.ar/fsm . I’ll upload the DSL version there, if you’re interested.

  2. on 17 Jan 2008 at 6:31 pm proj

    That’s great! I would love to see what you come up with. I had a lot of ideas on how I could enhance the features of the FSM within the DSL framework I initially provided. If you’re interested in hosting it on rubyforge and would like to have an extra contributor let me know.

  3. on 17 Jan 2008 at 7:07 pm v01d

    Hi again, I just uploaded this version to svn, and updated the wiki at http://trac.v01d.com.ar

  4. on 17 Jan 2008 at 8:21 pm proj

    I’m getting:

    Forbidden
      You don't have permission to access / on this server.
    
  5. on 17 Jan 2008 at 10:49 pm v01d

    Sorry, I just fixed it. The direct URL for the project is http://trac.v01d.com.ar/fsm (/ lists all my trac projects).

  6. on 18 Jan 2008 at 2:30 am proj

    I think I might need anonymous read access. I tried:

    svn list http://svn.v01d.com.ar/fsm/trunk

    It asks me for my credentials.

  7. on 18 Jan 2008 at 8:01 pm v01d

    Anonymous access is enabled, try leaving user and password blank, if it asks. In any case, you should be able to browse the sources using the “Browse Source” on http://trac.v01d.com.ar/fsm. Also, at the bottom of that page, there’s a tgz file of the last version.

  8. on 18 Jan 2008 at 8:02 pm v01d

    OH, didn’t notice you were using http, the svn address is svn://. But, as I said, it is not necessary to access using the svn command if you just want to look at the code.

Trackback URI | Comments RSS

Leave a Reply