There's currently no way to get the existing random seed, since srand() doesn't return anything.
Could it return the existing seed so we can temporarily change to a sub-system's ongoing seed, then restore it? Like this, for instance:
function handle_ai(ai) local old_seed=srand(ai.seed) ⋮ (stuff) ⋮ srand(old_seed) end
It's minor, since you can always keep your seeds in shadow values from the outset and manually set them each time, but it'd still be handy.
Unfortunately the PRNG state is 64-bit and is not mapped into RAM, while the API only lets you provide a 32-bit seed. So in order to reset the state to what it was previously you’d need to call srand() but also call rnd() as many times as it had been called previously.
I personally would love to see this solved by having the PRNG state mapped to RAM.
@Xii sure it’s true :-) here’s a full software reimplementation if you’re interested; rnd2() and srand2() should behave exactly like their system counterparts (edit: except for negative numbers):
do local a,b = 0,0 local function _() b = a + rotl(b,16) a += b end function rnd2(x) _() x = x or 1 if x == 0 then return 0 end local b,n = b,x while x>0 and b<0 do -- hack: simulate unsigned modulo while n + n > 0 do n += n end b -= n end return b % x end function srand2(x) a = x or 0xdead.beef b = bxor(a, 0xbead.29ba) for n=1,32 do _() end end end
Huh, okay. That means it's absolutely impossible to use rnd() with more than one parallel stream of numbers in the same app.
Like, srand() serves no purpose other than making ONE call to establish determinism for ALL code in an entire run.
Hmm, but maybe I'm spoiled by the system we used in one engine I worked on, which admittedly didn't provide ideal RNG, but was simplified so that the seed and the state were the same thing. It probably had lousy periodicity and distribution, but it was quite fast.
So, it's possible to back up and restore the seed with: memcpy(0x4300,0x5f44,8), memcpy(0x5f44, 0x4300, 8)
Not exactly a solution for the same problem, but when I need a separate but variable number of random values without interrupting the sequence, I just use:
temp = rnd(0x8000) srand(temp) -- if you want the same seed twice for i=1,var_num do something_else(rnd(0x8000)) end srand(temp)
@zep great news, thanks!
Note that this allows the user to break the PRNG by setting all the bits to zero, causing rnd() to return zero forever. Also anything with too little entropy will take a few iterations before showing the randomness properties again.
[Please log in to post a comment]