A Finite-State-Machine (or automaton) is a structure used to make state-based programming (see http://en.wikipedia.org/wiki/Finite-state_machine). SPADE supports this structure by means of the FSM behaviour.
The FSM behaviour is one of the most advanced possibilities for developing your agents. This type of behaviour allows you to create a FSM where each of its States is an embedded behaviour of any of the basic types (OneShot, Periodic, TimeOut...) or a custom behaviour type defined by the user (by inheriting from any of the provided behaviour types). One of these States will be the First State, the starting point of the FSM. Another will be the Last State, the ending point.
To change from one State to another, you should define a Transition. Each transition connects two States in one direction only, from an origin behaviour to a target behaviour, and it is triggered by the exit code of the origin behaviour. The exit code of each origin behaviour must be stored in its self._exitcode variable at the end of its execution. Once a behaviour has finished, the FSM behaviour will check this variable and make the right transition for its value. This flow will continue until the Final State is reached.
After declaring all the behaviours, in order to define an FSM (in the _setup() method of an agent) you must first associate a code to represent each behaviour that will become a state in the FSM. Then, you must use the registerFirstState() method to associate an instance of the initial behaviour with its code. Following, you can use the registerState() method to associate every instance of the behaviours that form the States of the FSM with their codes. After that, you must use the registerLastState() to associate an instance of the last behaviour to its code. Finally, you may use the registerTransition() method to create the transitions that link the behaviours with their exit codes.
And that's it! You have created a complex FSM behaviour. A complete agent class using one of these beauties is shown next:
class MyAgent(spade.Agent.Agent): class StateOne(spade.Behaviour.OneShotBehaviour): def _process(self): print "This is State One..." self.myAgent.counter = self.myAgent.counter + 1 if self.myAgent.counter > 2: self._exitcode = self.myAgent.TRANSITION_TO_TWO else: self._exitcode = self.myAgent.TRANSITION_DEFAULT class StateTwo(spade.Behaviour.OneShotBehaviour): def _process(self): print "This is State Two..." self.myAgent.counter = self.myAgent.counter + 1 if self.myAgent.counter > 5: self._exitcode = self.myAgent.TRANSITION_TO_THREE else: self._exitcode = self.myAgent.TRANSITION_DEFAULT class StateThree(spade.Behaviour.OneShotBehaviour): def _process(self): print "This is State Three..." self.myAgent.counter = self.myAgent.counter + 1 if self.myAgent.counter > 8: self._exitcode = self.myAgent.TRANSITION_TO_FOUR else: self._exitcode = self.myAgent.TRANSITION_DEFAULT class StateFour(spade.Behaviour.OneShotBehaviour): def _process(self): print "This is State Four..." self.myAgent.counter = self.myAgent.counter + 1 if self.myAgent.counter > 11: print "Counter ", self.myAgent.counter print "Bye Bye" self.myAgent._kill() else: self._exitcode = self.myAgent.TRANSITION_DEFAULT def _setup(self): time.sleep(2) print "FSMAgent starting . . ." self.counter = 0 self.STATE_ONE_CODE = 1 self.STATE_TWO_CODE = 2 self.STATE_THREE_CODE = 3 self.STATE_FOUR_CODE = 4 self.TRANSITION_DEFAULT = 0 self.TRANSITION_TO_ONE = 10 self.TRANSITION_TO_TWO = 20 self.TRANSITION_TO_THREE = 30 self.TRANSITION_TO_FOUR = 40 b = spade.Behaviour.FSMBehaviour() b.registerFirstState(self.StateOne(), self.STATE_ONE_CODE) b.registerState(self.StateTwo(), self.STATE_TWO_CODE) b.registerState(self.StateThree(), self.STATE_THREE_CODE) b.registerLastState(self.StateFour(), self.STATE_FOUR_CODE) b.registerTransition(self.STATE_ONE_CODE, self.STATE_ONE_CODE, self.TRANSITION_DEFAULT) b.registerTransition(self.STATE_ONE_CODE, self.STATE_TWO_CODE, self.TRANSITION_TO_TWO) b.registerTransition(self.STATE_TWO_CODE, self.STATE_TWO_CODE, self.TRANSITION_DEFAULT) b.registerTransition(self.STATE_TWO_CODE, self.STATE_THREE_CODE, self.TRANSITION_TO_THREE) b.registerTransition(self.STATE_THREE_CODE, self.STATE_THREE_CODE, self.TRANSITION_DEFAULT) b.registerTransition(self.STATE_THREE_CODE, self.STATE_FOUR_CODE, self.TRANSITION_TO_FOUR) self.addBehaviour(b, None)