Building an Engine with Reproducible Behavior

Started by
10 comments, last by PaulCunningham 19 years, 11 months ago
According to this article... Instant Replay : Building a Game Engine with Reproducible Behavior ...to get truly deterministic behaviour I will have to use fixed point datatypes for my game state. Does anybody know of any good resources for implementing fixed point data types in C++. Ease of use is probably of more concern than raw speed. Or links to source for this kind of engine. I''ve looked at Cube and Q3 (confusing) thus far and will try and track Unreal down tomorrow. I think I''d also like to be able to fast forward or rewind the demos or maybe a system similar to DVD chapters. So decent serialising game object links would also be appreciated. This feature is not my main concern though as it will probably be left ''til v3 of the engine. Many thanks. PS - my first attempt at demo recording and playback (before reading the article) failed miserably - check it out on my Defender clone Alien Abduction. Attract mode should activate after 7 seconds and replay some demos - you''ll notice they differ each time. PPS - I''m using SDL and Vis Studio 2003 if that makes any difference (but will look to release on other systems later) Cheers, Paul Cunningham Pumpkin Games
Cheers,Paul CunninghamPumpkin Games
Advertisement
just a thought, but it almost looks like you are storing
the state information for how the player moves, but
not how everything else does.

if that is not the case, then are you remembering to
store the random seed? because that could also be it
you need to have a way to generate the same random
numbers so everything that is generated randomly
is generated exactly the same way.

just some thoughts...
quote:Original post by PaulCunningham ...to get truly deterministic behaviour I will have to use fixed point datatypes for my game state.


I don''t see how fractional values are represented affecs the determinism. The quakes all use floats, and their demos repeat deterministically.

If you apply the same aglorithms to the same and complete data, then there should not be a problem.
What prejudices have you rooted out today?
There are a few problems:

1) Getting the same results on the same machine, over and over again.

2) Getting the same results, on different machines, running the same software.

3) Getting the same results, on different machines, running different software.

Case 1) is the case of game replays. It does NOT matter whether you use float or fixed, as long as ALL inputs are the same. This includes things like the floating point control word. DirectX will change the floating point control word when you call it, unless you create your device with D3DCREATE_FPUPRESERVE. Other drivers/dlls have been known to do the same, except they have no flag to change this behavior. Thus, test and set on your own. (Only set if necessary, because setting may cause very long stalls; hundreds of cycles)

Case 2) is the case of a networked peer-to-peer game, all running the same software (say, on Windows). The difference here is almost the same as in case 1), except you have have different CPUs, and thus different CPU speeds; different graphics cards, different DLL versions, etc. Make sure you install all DLLs you depend on, and make sure you work around any FPU bugs. Also make sure to use a consistent precision across machines. Typically, you''ll want to set to 64 bit (rather than 80) to make Athlons and P-IV work as similar as possible.

Case 3) is when your servers run Linux (different compiler) or your app also runs on the Mac. This is Really Frickin Hard to get right 100% of the time. Here, it MIGHT make sense to try with fixed point math, to avoid pulling hair. Compilers that generate different instruction order may indeed cause truncation/rounding of operations to change between machines. In this case, you pretty much need to be baselining (i e, arrange to get a known good snapshot to the other machines every so often).
enum Bool { True, False, FileNotFound };
quote:Original post by KulSeran
just a thought, but it almost looks like you are storing the state information for how the player moves, but not how everything else does.

if that is not the case, then are you remembering to store the random seed? because that could also be it you need to have a way to generate the same random numbers so everything that is generated randomly is generated exactly the same way.

just some thoughts...


I''m storing player INPUT and then re-applying that. I have my own random number generator and I save the seed in the demo and reset on playback. The problem is the engine wasn''t really designed with demo playback in mind and it was just tagged on so it''s never going to work in that game - I know where the problem is and I might go back and fix it when I get it working in this new engine.

quote:Original post by Eccentrix
I don''t see how fractional values are represented affecs the determinism. The quakes all use floats, and their demos repeat deterministically.


Calculations using fixed point math will be consistent across all systems - floating point calculations may not - even with IEEE compliant FPUs (according to the article - I do not have the systems to perform my own investigations).

If you look at the source to Quake2 you''ll find that he specifically states in code that certain data structures need to be fixed point (he uses 12:3) - the stuff that keeps track of player positions, orientations, etc.

quote:Original post by Eccentrix
If you apply the same aglorithms to the same and complete data, then there should not be a problem.


As above - the problem is the data can get mangled due to inconistencies with the different FPUs.


hplus0603: spot on!

My intention is to release on any platform that SDL supports and have demos available for download / upload from my site.

I''m not proficient with compiler settings and different architectures so I thought fixed point was the safest option in my case.

You got any links I can research?


Cheers,Paul CunninghamPumpkin Games
To get accurate replay you have to store info about time delta between all frames plus all inputs speacially if your game or simulation uses time delta b/w frames. For long recordings you can setup a multithreaded system which writes info as big packets.
3D Side-Scroller game demo Project-X2 "playable"Lashkar: A 3D Game & Simulation Project demo @ lashkar.berlios.de
quote:Original post by DirectXXX
To get accurate replay you have to store info about time delta between all frames.


My ''physics'' system is seperate from my ''render'' system and is set to update at a constant rate so this is not true in my case. If frames take longer to draw on replay, more imputs get applied.

Cheers,Paul CunninghamPumpkin Games
quote:Original post by PaulCunningham
If frames take longer to draw on replay, more imputs get applied.

I didnt understand what your mean. Did you store inputs data per frame or with respect to time. and are you going to apply these inputs per frame or with respect to time.
3D Side-Scroller game demo Project-X2 "playable"Lashkar: A 3D Game & Simulation Project demo @ lashkar.berlios.de
On the new system I store player input every x milliseconds (x is a constant and is currently set to 10)

In the main loop I simply work out the last frame time in milliseconds (SDL_GetTicks) and apply appropriate number of inputs.

e.g.

9 milliseconds passed - no input to apply
10 - 1 input
20 - 2 inputs
etc

...then I render. Physics is decoupled from frame rate. If a frame takes longer then more inputs get applied.

Cheers,Paul CunninghamPumpkin Games
personally i think that storing/applying inputs with respect time isnt good idea. You should store inputs and aplpy to each frame. If memory gets short than pack that data to disk in other thread. Using this method no matter how fast or slow a machine is you will get exactly the same replay.
3D Side-Scroller game demo Project-X2 "playable"Lashkar: A 3D Game & Simulation Project demo @ lashkar.berlios.de

This topic is closed to new replies.

Advertisement