Log In  

There's currently no way to get the existing random seed, since srand() doesn't return anything.

Test/demo:

Cart #yudodekegi-0 | 2020-03-29 | Code ▽ | Embed ▽ | No License
2

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.

Thanks! :)

P#74306 2020-03-29 13:02 ( Edited 2020-03-29 14:03)

1

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.

P#74308 2020-03-29 14:43

@samhocevar Is that true? I was getting some inconsistent results with seeded randoms earlier, but couldn't produce a minimal reproducing example. That could explain the inconsistencies.

P#74309 2020-03-29 14:49

@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
P#74312 2020-03-29 18:03 ( Edited 2020-03-30 12:06)

@samhocevar

How do you know it's a 64-bit seed?

Anyway, I guess srand() could start taking an optional second value for a full 64 bits and likewise return a tuple of the internal seed.

But yeah, memory-mapping it would probably be good.

P#74321 2020-03-30 02:10 ( Edited 2020-03-30 02:10)

@Felice you can find the PRNG algorithm by searching for -1095947846 (0xbead29ba) in any HTML export. You’ll see it uses two 32-bit numbers as its state (the a and b variables in my above code).

P#74328 2020-03-30 12:06

@samhocevar

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.

That... sucks.

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.

P#74352 2020-03-31 06:05 ( Edited 2020-03-31 06:51)

I agree, sucks if this is the case. We need @zep in here!

P#74358 2020-03-31 12:53
5

@Felice, @samhocevar agreed, this should be mapped to RAM. I've added the 8 bytes at 0x5f44

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)
P#74386 2020-04-01 12:49 ( Edited 2020-04-01 12:52)
1

@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.

P#74391 2020-04-01 15:56 ( Edited 2020-04-01 15:56)
1

@zep

Thank you! That's awesome! :)

Thanks also to Sam for suggesting the memory-mapping solution. I think that was probably the ideal fix, given the circumstances. :)

P#74394 2020-04-01 18:51

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-28 19:42:29 | 0.035s | Q:32