-
-
Save igaray/9bfae6fa73a481d30397 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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("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