Make sure that you've implemented the simulation in such a way that the simulation's "state" is a function. That is, a function of time.
Given an initial state at time T0
, you should be able to construct the simulation frame at time Tn
for any n
. For example, an initial stationary state and no events (yet) might equal the identity function, so Tn == Tn+1
.
Given some pilot action event at time Ta
, you should be able to construct a frame Ta+n
for any n
. So you think of events as modifying a function that takes a time value as argument and returns the frame of the simulation for that time.
I would implement the history of events as a Zipper of (time, function) pairs representing the control state of the simulation. The "current" state would be in focus, with a list of future states on the right, and past states on the left. Like so:
([past], present, [future])
Every time the simulation state changes, record a new state function in the future
. Running the simulation then becomes a matter of taking functions out of the future
list and passing the current time into them. Running it backwards is exactly the same except that you take events out of the past
list instead.
So if you're at time Tn
and you want to rewind to time Tn-1
, look into the past
list for the latest state whose time
attribute is less than n-1
. Pass n-1
into its function
attribute, and you have the state of simulation at time Tn-1
.
I've implemented a Zipper datastructure in Java, here.