Page 1 of 1

Using the global random number generator inside on_chunk_generated

Posted: Sat Aug 21, 2021 5:33 pm
by BicycleEater
I have a mod which really wants to change things beyond the currently loaded chunks, but instantly loading a huge number of chunks is expensive and unnecessary. What I would really like to do is to do all the changes when each chunk loads, however my mod also uses a lot of rng in the big change-the-world scripts.

My question is this:
If you use the global random number generator during an on_chunk_generated script, will this cause desyncs, and is this a bad practice.

I ask because I would guess that the chunk generation order isn't the same every time (as it depends on player actions, and maybe even load time) so the random numbers generated may be different. This may cause desyncs if the order is not guaranteed across different instances of the game (e.g. client and server).
Even if the order is guaranteed, it may be bad practice, as it makes the outcome of the game dependant on the order of chunk loading, so it may introduce future issues. It may also mean that a save which is loaded back doesn't result in the same events, as the random number generator is in a different state.

Re: Using the global random number generator inside on_chunk_generated

Posted: Sat Aug 21, 2021 6:17 pm
by DaveMcW
You can combine the coordinates of the chunk with the map seed, to create your own tick-independent random number generator.

The x and y multipliers are random primes I found on the internet, the important part is that they are large and prime.

Code: Select all

local x = event.position.x
local y = event.position.y
local map_seed = event.surface.map_gen_settings.seed

local new_seed = (x * 374761393 + y * 668265263 + map_seed) % 4294967296
local rng = game.create_random_generator(new_seed)

local rand1 = rng(1, 100)
local rand2 = rng(1, 100)
...

Re: Using the global random number generator inside on_chunk_generated

Posted: Sat Aug 21, 2021 7:39 pm
by PFQNiet
Using `math.random()` is just fine.

Re: Using the global random number generator inside on_chunk_generated

Posted: Sun Aug 22, 2021 9:37 am
by orzelek
DaveMcW wrote:
Sat Aug 21, 2021 6:17 pm
You can combine the coordinates of the chunk with the map seed, to create your own tick-independent random number generator.

The x and y multipliers are random primes I found on the internet, the important part is that they are large and prime.

Code: Select all

local x = event.position.x
local y = event.position.y
local map_seed = event.surface.map_gen_settings.seed

local new_seed = (x * 374761393 + y * 668265263 + map_seed) % 4294967296
local rng = game.create_random_generator(new_seed)

local rand1 = rng(1, 100)
local rand2 = rng(1, 100)
...
This looks better then what RSO does now - it has something similar but not using prime numbers.
I might upgrade it to get better overall randomness.

Re: Using the global random number generator inside on_chunk_generated

Posted: Sun Aug 22, 2021 9:36 pm
by eradicator
Just because nobody has explicitly answered @OPs questions: Most of your answers are in the doc.
https://lua-api.factorio.com/latest/Libraries.html
BicycleEater wrote:
Sat Aug 21, 2021 5:33 pm
will this cause desyncs
No, math.random is safe. However math.randomseed is a no-op, see the doc above.
BicycleEater wrote:
Sat Aug 21, 2021 5:33 pm
and is this a bad practice.
I'd personally say it's fine, however if you want a map-seed stable randomness that doesn't depend on exploration order then a chunk-seeded LuaRandomGenerator for each chunk is a good idea, as the posters above have already explained.
DaveMcW wrote:
Sat Aug 21, 2021 6:17 pm
the important part is that they are large and prime.

Not a mathematician myself, but if LuaRandomGenerator is a proper PRNG then isn't the randomness of the seed irrelevant as long as the seed function produces a unique seed above 341 for each (x,y)?
[Edit: See post below.]

Re: Using the global random number generator inside on_chunk_generated

Posted: Sun Aug 22, 2021 9:43 pm
by DaveMcW
eradicator wrote:
Sun Aug 22, 2021 9:36 pm
if LuaRandomGenerator is a proper PRNG
:lol: :lol: :lol: :lol:

The documentation specifically says, "Seeds that are close together will produce similar results."

Re: Using the global random number generator inside on_chunk_generated

Posted: Mon Aug 23, 2021 3:43 pm
by eradicator
DaveMcW wrote:
Sun Aug 22, 2021 9:43 pm
The documentation specifically says, "Seeds that are close together will produce similar results."
Ah, dang. I remembered the 341 thing, but not the sentence before that :P.

Re: Using the global random number generator inside on_chunk_generated

Posted: Mon Aug 23, 2021 7:10 pm
by BicycleEater
eradicator wrote:
Sun Aug 22, 2021 9:36 pm
No, math.random is safe. However math.randomseed is a no-op, see the doc above.
OK, thanks, that clears things up.
The thing I was scared of was that the chunk loading could be done 'as and when', rather than in lock-step, meaning that client and server could differ in exact ordering, I kind of figured it wouldn't be a thing, but you never know.

I'll still use a chunk specific rng though, as it seems like a nice thing to do - that way you can't explore differently and change how the world works.