Code Monkey home page Code Monkey logo

luafsm's Introduction

A design pattern for doing finite state machines (FSMs) in Lua
==============================================================

Based on a very appreciated contribution of Luiz Henrique de Figueiredo
Original code from http://lua-users.org/wiki/FiniteStateMachine

The FSM is described with: old_state, event, new_state and action.
One easy way to do this in Lua would be to create a table in exactly 
the form above:

yourStateTransitionTable = { 
	{state1, event1, state2, action1},
	{state1, event2, state3, action2},
	...
}

The function FSM takes the simple syntax above and creates tables 
for (state, event) pairs with fields (action, new):

function FSM(yourStateTransitionTable)
  local stt = {}
  for _,v in ipairs(t) do
    local old, event, new, action = v[1], v[2], v[3], v[4]
    if stt[old] == nil then a[old] = {} end
    stt[old][event] = {new = new, action = action}
  end
  return stt
end

Note that this scheme works for states and events of any type: number, 
string, functions, tables, anything. Such is the power of associate arrays.

However, the double array stt[old][event] caused a problem for event = nil
Instead a single array is used, constructed as stt[state .. SEPARATOR .. event]
Where SEPARATOR is a constant and defined as '.'

Three special state transitions are added to the original code:
- any state but a specific event
- any event but a specific state
- unknown state-event combination to be used for exception handling

The any state and event are defined by the ANY constant, defined as '*' 
The unknown state-event is defined as the combination of ANY.ANY (*.*)

A default exception handler for unknown state-event combinations is 
provided and therefore a specification a your own exception handling is
optional.

After creating a new FSM, the initial state is set to the first defined 
state in your state transition table. With add(t) and delete(t), new state
transition can be added and removed later. 

A DEBUG-like method called silent is included to prevent wise-guy remarks
about things you shouldn't be doing. 

USAGE EXAMPLES:
------------------------------------------------------------------------------- 
FSM = require "fsm"

function action1() print("Performing action 1") end
function action2() print("Performing action 2") end

-- Define your state transitions here
local myStateTransitionTable = {
	{"state1", "event1", "state2", action1},
	{"state2", "event2", "state3", action2},
	{"*",      "event3", "state2", action1},  -- for any state
	{"*", 	   "*",	     "state2", action2}   -- exception handler
}

-- Create your finite state machine
fsm = FSM.new(myStateTransitionTable)

-- Use your finite state machine 
-- which starts by default with the first defined state
print("Current FSM state: " .. fsm:get())

-- Or you can set another state
fsm:set("state2")							
print("Current FSM state: " .. fsm:get())

-- Resond on "event" and last set "state"
fsm:fire("event2")
print("Current FSM state: " .. fsm:get())

Output:
-------
Current FSM state: state1
Current FSM state: state2
Performing action 2
Current FSM state: state3

REMARKS:
-------------------------------------------------------------------------------
Sub-states are not supported by additional methods to keep the code simple.
If you need sub-states, you can create them as 'state.substate' directly.

A specific remove method is not provided because I didn't need one (I think)
But feel free to implement one yourself :-)

One more thing, did I already mentioned that I am new to Lua?
Well, I learn a lot of other examples, so do not forget yours. 

CONCLUSION:
-------------------------------------------------------------------------------
A small amount of code is required to use the power of a Finite State Machine.

I wrote this code to implement generic graphical objects where the presentation 
and behaviour of the objects can be specified by using state-transition tables.
This resulted in less code (and less bugs), a higher modularity and above all a 
reduction of the complexity.

Finite state machines can be used to force (at least parts of) your code into 
deterministic behaviour. 

Have fun.

luafsm's People

Contributors

cornelisse avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.