2
\$\begingroup\$

Sorry if this is such a simple thing, but for some reason I can't get my head around it.

Imagine you have a world, that you have "seeded" with a value. You base all your randomisations off this value - perhaps you made mountains, monsters, or any other such thing.

Then the user saves her game, and then picks up where she left off a few days later.

We can store the seed we started with easily enough. But, it will reset to the beginning. What I would actually like is to "start off where we left off". Therefore, with persistence, do I need to be storing the iterations that we applied on said random number generator? When loading the saved game, do we go through the iterations to arrive at the place we should be?

An alternate would be to initialise a world using a random seed, and then throw it away when we save, so that any subsequent load, has a new random number generator.

Thoughts and ideas welcome :)

Edit

To reiterate from the comment I made below, my first thought was to wrap all access to the Random class, and track the number of iterations. This could be saved alongside the seed. When loading, one would re-initialise the class, and then loop through the iterations (effectively throwing away the result) to arrive at the point you'd have been at originally.

Also, added c# tag.

\$\endgroup\$
  • \$\begingroup\$ So your intention is to make sure that the user can save and load the game, and, from the loaded state, it will continue in the same way as if it had not been saved and loaded? It might be possible to serialize/persist the actual random number generator (it must have an associated internal state). Maybe some info about the language/RNG that you are using may be helpful here... \$\endgroup\$ – Marco13 Sep 7 '14 at 15:13
  • \$\begingroup\$ @Marco13, exactly! I am using C#. If my random generator gave me "1, 2, 3" after 3 calls, and then I saved it. when I loaded, I should get 4 on the next call (all things considered). My first idea was to store the "iterations" (and wrap all calls to the random generator through them), meaning I'd get the desired result - but wondered if there was a way to save the "state" of the random generator itself. \$\endgroup\$ – Moo-Juice Sep 7 '14 at 15:17
  • \$\begingroup\$ I'm not familiar with C#, but could imagine that it has a built-in serialization mechanism (like java.util.Random) that meets your requirements. Let's see what the experts say ;-) (Related, but did not read/understand it completely: stackoverflow.com/questions/7589388/… ) \$\endgroup\$ – Marco13 Sep 7 '14 at 15:30
  • \$\begingroup\$ Why can't you just serialize all the data (mountains, etc.)? That's really what you're after. \$\endgroup\$ – ashes999 Sep 7 '14 at 15:36
  • \$\begingroup\$ @ashes999, that was an example. In my case, I am generating a pool of people (randomly), and would like that pool to "continue" after the player saves the game rather than reseeding. Obviously, the existing "pool" is persisted. \$\endgroup\$ – Moo-Juice Sep 7 '14 at 15:40
3
\$\begingroup\$

The correct way to do this is to implement your own random number generator, such as the Mersene Twister. The reason you should implement your own is this:

The output of Random is not guaranteed to be the same between different invocations of your program!

(Even though it should be the same when running on the identical versions of the .NET Framework.)

When you implement your own, you simply need to serialize the current state of your random number generator (assuming your goal is to have the "generated in the future" sequence of numbers match). Note that the Random class in C# is serializable, should you wish to risk using it.

If you want to get the same sequence of random numbers, from the start, then simply store the initial seed (again, on your own implementation is safer).

\$\endgroup\$
0
\$\begingroup\$

If the players cannot modify the world, you may be able to just save your seed, and rebuild the world later.

If they can modify the world, it will be very tricky to rebuild the world (especially if their modifications depends of the RNG at the moment they take the action).

If your world is highly procedural (you generate a lot of data) and modifiable you may try to save both the seed and a "delta" of the differences between the generated world and the "actual" world.

One way to do that (not the most efficient but it should work) would be:

  • Save the seed
  • Recreate the original world in another part of your memory (from the creation seed)
  • Iterate through your world objects/actors/etc and if they have changed, store the new value

Re-loading will be almost the same:

  • Read the seed
  • Recreate the original world
  • Read all modified objects and overwrite their "original" version

Depending of the specific details of your game, you can probably optimize this further.

Just a bit of warning: If your procedural process is using floating numbers AND you want the saved games to be useable on another computer than the one which saved it, it will likely not work the way you're expecting it unless you take extra precautions (see this article about the issue if you plan to do it: http://gafferongames.com/networking-for-game-programmers/floating-point-determinism/)

\$\endgroup\$
0
\$\begingroup\$

You could reseed the terrain generation per chunk dependent on both the global seed and the coordinates of where you are generating.

Enemy RNG can be independent from this global seed.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.