For testing purposes I'm creating random numbers with a given seed (i.e. not based on the current time).
Thus the whole program is deterministic.
If something happens, I'd like to be able to quickly restore a point "shortly before" the incident.
Therefore I need to be able to restore a System.Random
to a previous state.
Is there a way to extract a seed which I can use to recreate the random generator?
There is an alternative solution that (1) avoids the need to remember all previously generated numbers; (2) does not involve accessing the private fields of Random; (3) does not require serialization; (4) does not require looping back through Random as many times as it had been called; and (5) does not require creating a replacement for the built-in Random class.
The trick is to get state by generating a random number, and then reseeding the random number generator to this value. Then, in the future, one can always return to this state by reseeding the random number generator to this value. In other words, we "burn" a number in the random number sequence for the purpose of saving state and reseeding.
The implementation follows. Note that one would access the Generator property to actually generate numbers.
And here is a simple test:
This is what I came up:
Basically it extracts the private seed array. You just need to be careful to restore an "unshared" array.
System.Random
is not sealed and its methods are virtual, so you could create a class that counts the number of numbers generated to keep track of the state, something like:Example usage:
Output:
Store the amount of times the random number generator ran like
Xi Huan
wrote.Then simply loop to restore the old state.
Now just do
There is no way around this you have to loop to get back to where you left off.
In line with the answer given here, I wrote a small class to help with saving and restoring the state.
You can test this code in LINQPad.
I'm aware this question has already been answered, however, I wanted to provide my own implementation, which is currently in use for a game that I am creating. Essentially, I created my own Random class, using the code of .NET's Random.cs. Not only did I add more functionality, but I also added a way to save and load the current generator state into and from an array of just 59 indices. It is better to do it this way instead of how some other comments suggest to "Iterate x number of times to restore the state manually. This is a bad idea because in RNG heavy games your Random generator state could theoretically get into the billions of calls, meaning you would—according to them—need to iterate a billion times to restore the state of the last play session during each startup. Granted, this may still only take a second, tops, but it's still too dirty in my opinion, especially when you could simply extract the current state of the Random Generator and reload it when required, and only taking up 1 array (59 indices of memory).
This is just an idea, so take from my code what you will.
Here is the full source, which is much too large to post here:
GrimoireRandom.cs
And for anyone who just wants the implementation for the question, I will post it here.
My code is completely stand-alone, besides the DiceType enumeration, and the OpenTK Vector3 struct. Both of those functions can just be deleted and it will work for you.