Skip to content

Instantly share code, notes, and snippets.

@igaray
Created November 22, 2014 17:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save igaray/9bfae6fa73a481d30397 to your computer and use it in GitHub Desktop.
Save igaray/9bfae6fa73a481d30397 to your computer and use it in GitHub Desktop.
class FiniteStateMachine:
def __init__(self, cs=None, tt={}, tf={}, sf={}, oe={}, ox={}):
self.ps = None # previous state
self.cs = cs # current state
self.tt = tt # transition table
self.tf = tf # transition functions
self.sf = sf # state functions
self.oe = oe # on entry functions
self.ox = ox # on exit functions
def transition(self, event):
"""
The fsm will only transition if the transition is valid, i. e. the
(state, event) pair is in the transition table.
On firing the transition, the fsm will execute, in order:
- the previous state's on_exit function
- the transition function
- the next state's on_entry function
- the state's function
"""
if (self.cs, event) in self.tt:
# print
print("current state: ", EngineState.to_str(self.cs))
print("event: ", EngineEvent.to_str(event))
print("next state: ", EngineState.to_str(self.tt[(self.cs, event)]))
# on exit function
if self.cs in self.ox:
self.ox[self.cs]()
# go to next state
self.ps = self.cs
self.cs = self.tt[(self.cs, event)]
# transition function
if event in self.tf:
self.tf[event]()
# on entry function
if self.cs in self.oe:
self.oe[self.cs]()
# state function
if self.cs in self.sf:
self.sf[self.cs]()
else:
print("Bad transition: {0}".format( (self.cs, event) ))
sys.exit()
class EngineState:
INIT = 0
HALT = 1
SHOWING_MENU = 2
GENERATING_WORLD = 3
STARTING_SIM = 4
LOADING_SIM = 5
STOPPING_SIM = 6
MOVING_UNITS = 7
RUNNING_LOCALS = 8
ENDING_TURN = 9
RUNNING = 10
PAUSED = 11
SHOWING_LOCAL = 12
def to_str(state):
if state == EngineState.INIT: return "INIT"
elif state == EngineState.HALT: return "HALT"
elif state == EngineState.SHOWING_MENU: return "SHOWING_MENU"
elif state == EngineState.GENERATING_WORLD: return "GENERATING_WORLD"
elif state == EngineState.STARTING_SIM: return "STARTING_SIM"
elif state == EngineState.LOADING_SIM: return "LOADING_SIM"
elif state == EngineState.STOPPING_SIM: return "STOPPING_SIM"
elif state == EngineState.MOVING_UNITS: return "MOVING_UNITS"
elif state == EngineState.RUNNING_LOCALS: return "RUNNING_LOCALS"
elif state == EngineState.ENDING_TURN: return "ENDING_TURN"
elif state == EngineState.RUNNING: return "RUNNING"
elif state == EngineState.PAUSED: return "PAUSED"
elif state == EngineState.SHOWING_LOCAL: return "SHOWING_LOCAL"
class EngineEvent:
INIT = 0
HALT = 1
GENERATE = 2
ACCEPT = 3
REJECT = 4
SHOW_MENU = 5
START_SIM = 6
LOAD_SIM = 7
STOP_SIM = 8
START_TURN = 9
RUN_LOCALS = 10
END_TURN = 11
OK = 12
RUN = 13
PAUSE = 14
RUN_LOCAL = 15
STOP_LOCAL = 16
STEP = 17
def to_str(event):
if event == EngineEvent.INIT: return("INIT")
elif event == EngineEvent.HALT: return("HALT")
elif event == EngineEvent.GENERATE: return("GENERATE")
elif event == EngineEvent.ACCEPT: return("ACCEPT")
elif event == EngineEvent.REJECT: return("REJECT")
elif event == EngineEvent.SHOW_MENU: return("SHOW_MENU")
elif event == EngineEvent.START_SIM: return("START_SIM")
elif event == EngineEvent.LOAD_SIM: return("LOAD_SIM")
elif event == EngineEvent.STOP_SIM: return("STOP_SIM")
elif event == EngineEvent.START_TURN: return("START_TURN")
elif event == EngineEvent.RUN_LOCALS: return("RUN_LOCALS")
elif event == EngineEvent.END_TURN: return("END_TURN")
elif event == EngineEvent.OK: return("OK")
elif event == EngineEvent.RUN: return("RUN")
elif event == EngineEvent.PAUSE: return("PAUSE")
elif event == EngineEvent.RUN_LOCAL: return("RUN_LOCAL")
elif event == EngineEvent.STOP_LOCAL: return("STOP_LOCAL")
elif event == EngineEvent.STEP: return("STEP")
class Engine:
def engine_init(self):
print("engine_init")
def engine_halt(self):
print("engine_halt")
self.quit = True
def __init__(self):
print("engine_initialize: enter")
cs = EngineState.INIT
tt = {
(EngineState.INIT, EngineEvent.INIT) : EngineState.SHOWING_MENU,
(EngineState.SHOWING_MENU, EngineEvent.GENERATE) : EngineState.GENERATING_WORLD,
(EngineState.SHOWING_MENU, EngineEvent.START_SIM) : EngineState.STARTING_SIM,
(EngineState.SHOWING_MENU, EngineEvent.LOAD_SIM) : EngineState.LOADING_SIM,
(EngineState.SHOWING_MENU, EngineEvent.HALT) : EngineState.HALT,
(EngineState.GENERATING_WORLD, EngineEvent.ACCEPT) : EngineState.SHOWING_MENU,
(EngineState.GENERATING_WORLD, EngineEvent.REJECT) : EngineState.SHOWING_MENU,
(EngineState.STARTING_SIM, EngineEvent.OK) : EngineState.MOVING_UNITS,
(EngineState.LOADING_SIM, EngineEvent.START_TURN) : EngineState.MOVING_UNITS,
(EngineState.STOPPING_SIM, EngineEvent.START_TURN) : EngineState.HALT,
(EngineState.STOPPING_SIM, EngineEvent.SHOW_MENU) : EngineState.SHOWING_MENU,
(EngineState.MOVING_UNITS, EngineEvent.RUN_LOCALS) : EngineState.RUNNING_LOCALS,
(EngineState.RUNNING_LOCALS, EngineEvent.END_TURN) : EngineState.ENDING_TURN,
(EngineState.RUNNING_LOCALS, EngineEvent.RUN_LOCAL) : EngineState.PAUSED,
(EngineState.ENDING_TURN, EngineEvent.START_TURN) : EngineState.MOVING_UNITS,
(EngineState.ENDING_TURN, EngineEvent.STOP_SIM) : EngineState.STOPPING_SIM,
(EngineState.RUNNING, EngineEvent.PAUSE) : EngineState.PAUSED,
(EngineState.PAUSED, EngineEvent.RUN) : EngineState.RUNNING,
(EngineState.PAUSED, EngineEvent.STEP) : EngineState.PAUSED,
(EngineState.PAUSED, EngineEvent.STOP_LOCAL) : EngineState.RUNNING_LOCALS
}
tf = {
EngineEvent.INIT : self.engine_init,
EngineEvent.HALT : self.engine_halt
}
self.fsm = FiniteStateMachine(cs, tt, tf)
self.quit = False
def engine_main_loop(engine):
while not engine.quit:
event = get_event()
engine.transition(event)
def engine_main():
print("engine_main: enter")
engine = Engine()
engine_main_loop(engine)
print("engine_main: exit")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment