Date detection implementation
The code below implements the date detection state machine outlined on the previous page. It is intended as an example of how to approach this rather than a complete solution. Detector style state machines in your own game will likely have different states and transitions according to your needs.
Defining the states
The first thing to do is to define the names of each of the states from
the state diagram so they can be used instead of state numbers in the
code.
This is kept as a define
so future versions of the game
can include additional states as needed.
# Date detection states. # define dateDetectStates = ( 'notSeen', # 0 'dateFirst', # 1 'dateSecond', # 2 'worried', # 3 'saySomething', # 4 )
Defining the class
This example uses the FsmTimer as a
base class so the code can work with state names rather than state numbers
and take advantage of its timer functionality.
An __init__
method is provided to initialise the base class
with the list of states.
Note: There's a syntactical difference between the way the base class is initialised between Ren'Py7/Python2 and Ren'Py8/Python3. Use the tabs below to select the appropriate code for your version.
classes/fsm/dateDetectFsm.rpy.rpy (cont.)init python: class DateDetectFsm(FsmTimer): """ State machine for detecting dates. """ # --------------------------------------------------------------------- # Constructor # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def __init__(self): """ Construct a date detecting FSM. """ super(DateDetectFsm, self).__init__('dateDetectStates') # Python 2
init python: class DateDetectFsm(FsmTimer): """ State machine for detecting dates. """ # --------------------------------------------------------------------- # Constructor # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def __init__(self): """ Construct a date detecting FSM. """ super().__init__('dateDetectStates') # Python 3
Timer transitions
There are three transitions which trigger when the timer reaches zero.
These are handled by overriding the timerTriggered
method of FsmTimer
.
Each reverts to an earlier state, and resets the timer to seven ticks.
To clear the timerTrig
flag the del
operation
is used.
This could be done whenever the timerTriggered
method is
called, but that might impact other additions to this state machine.
# --------------------------------------------------------------------- # Timer methods # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def timerTriggered(self): """ Back off detection state after timer has elapsed. Called when timer reaches zero. """ if self.stateName == 'dateFirst': self.stateName = 'notSeen' del self.timerTrig elif self.stateName == 'dateSecond': self.stateName = 'dateFirst' self.timer = 7 del self.timerTrig elif self.stateName == 'worried': self.stateName = 'dateSecond' self.timer = 7 del self.timerTrig
Inputs
There are three inputs to the state machine: date friend, date other, and said something.
Input: Date Friend
This method is invoked when the NPC is aware of the PC dating her friend. Whenever it transitions it resets the timer to seven ticks.
classes/fsm/dateDetectFsm.rpy.rpy (cont.)# --------------------------------------------------------------------- # Inputs # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def dateFriend(self): """ PC seen on date with friend. """ if self.stateName == 'notSeen': self.stateName = 'dateFirst' self.timer = 7 elif self.stateName == 'dateFirst': self.stateName = 'dateSecond' self.timer = 7 elif self.stateName == 'worried': self.stateName = 'saySomething' self.timer = 7
Input: Date Other
This method is invoked when the NPC is aware of the PC dating someone other than her friend. Whenever it transitions it resets the timer to seven ticks.
classes/fsm/dateDetectFsm.rpy.rpy (cont.)def dateOther(self): """ PC seen on a date with someone else. """ if self.stateName == 'dateSecond': self.stateName = 'worried' self.timer = 7
Input: Said Something
This method is invoked when the NPC said something to the player about the way they are treating their friend. Whenever it transitions it resets the timer to seven ticks.
classes/fsm/dateDetectFsm.rpy.rpy (cont.)def saidSomething(self): """ Said something to the PC. """ if self.stateName == 'saySomething': self.stateName = 'dateSecond' self.timer = 7
Outputs
There's just one output from this state machine that becomes
True
when the "correct" sequence of events has occurred.
Output: Say Something
This output is True
when the NPC is ready to talk to the
player about their behaviour.
It would be used to trigger some conditional dialogue between the two.
Alternatively it could be used to have the NPC talk to their friend,
potentially causing some other change.
# --------------------------------------------------------------------- # Outputs # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def saySomething(self): """ NPC ready to confront PC. """ return self.stateName == 'saySomething'