Minimizing the Pain of Lockstep Multiplayer
gamasutra.com
gamasutra.com
http://www.gamasutra.com/view/feature/131503/1500_archers_on...
http://dl.acm.org/citation.cfm?doid=1094855.1094861&preflayo... (sadly paywalled)
Essentialky if you model your world/simulation as objects and events/messages, and you can isolate input (user input, possibly clock ticks) - and you can order external inputs in a (distributed/consistent) log (a la apache kafka) - then you can have a simulation that runs in parallel and lock-step across many clients.
Have some threads waiting on input (controls, network), dispatch to pure functions running the simulation, stream render commands to a rendering component. You can even consider the RNG as one of the input streams to keep the core pure.
I'm not into game programming but this got me interested in implementing a toy RTS!
The happy medium for gameplay simulations is to write straight-line imperative code and minimize your use of subroutines and indirection - you want "static" synchronization that loops over data in big batches where execution flow reads easily. When it's kept simple like this, major desynchronization challenges come down to compilation behaviors and interactions with other modules(render, network, etc). The main loop gets big as a result, but factoring it out only makes it harder to follow, because the complexity is coming from the high number of sync points, not duplicated code.
This was from an RTS game circa 2000, can't remember which. They were p2p broadcast lockstep as the above, and UDP based. Since the bandwidth is so trivial (boils down to what 10 fingers and a mouse can do), they'd just repeat the last N messages in every packet as brute force forward error correction. Lose a packet? Just wait for the next one.