PCG Random Number Generator

for statistically good ( it passes test suit, and most importantly entrophy test) pseudo random number generator chances of repeating sequence depend only of length of sequence. And chance of producing the same sequence with different seeds should indistinguishable from chance of producing two matching sequences one right after another with one seed. (assuming length of sequences we are talking about are significantly less then period of generator)

In my case I want the universe to be generated exactly the same each time I run the app. So itā€™s important that all values are identical. Does that make sense? In this scenario, to get a nice random feel, donā€™t the seeds for each object need to be unique?

you can use one seed and generate objects in some fixed order, this should produce same result ( in regard to uniqueness )

Youā€™re right, of course!

Instead of focusing on each individual object, I can generate one seed per tile instead, then run a sequence to get all objects and sub-objects within that tile.

My initial idea was to be able to generate each item on the most granular level, but this method is much more straightforward. Thanks!

None. My intent was to change the sequence by using second number.

Random generator uses two 64 bit values for seed. One for state, one for sequence.
More info: pcg32_srandom_r

Currently Iā€™m using your int as state and your intā€™s size as sequence. Iā€™m not sure if it is possible to pass 64 bit int to C++ from Lua 5.1. To be on safe side I set them as 32bit.

In my mind, to make sure all objects are unique (to reduce the likelihood of two objects being exactly the same), I have to include the ā€œbreadcrumbā€ so each seed is unique.

I mean, the tile index (y*width+x) is unique. Do you need it to be more unique?

Please, not MORE complexity!

Well, this is the path youā€™ve chosen, to have this amount of complexity? :slight_smile:

To make the seed have as few collisions as possible, you should, create a hash of all the relevant input data. Each added bit that gets hashed will make it less likely to collide with other hashes. (assuming a good avalanche effect in the hash function)

Currently, we only have a the hash() that takes a string, but you can use it to concatenate values into a unique string, and then hash that, and youā€™ll have your seed value.
You can then use hash_to_hex() to create a string, which you can then use to create a numberā€¦ phew not very user friendly, but it might work.

1 Like

Oh great, then it makes complete sense adding it (regardless of my questionable use case!), since itā€™s part of the api.

Iā€™m rethinking my reasoning as we speak.

Most likely no, because Iā€™m now generating objects based on their cell parent, rather than on object level. Itā€™s much more straightforward, and more performant than I thought.

I never thought of that, thatā€™s really useful!

Just updated the extension. Now, you can seed the generator with state and sequence.

Also, I roughly tested with 64-bit values. Seems like it is working. But I havenā€™t got any experience of using and passing 64-bit int from lua to c++, so it may cause problems. If anyone has a knowledge about this, I wanted to hear it. It may be safe to use 32-bit integers. I believe @Mathias_Westerdahl has a better opinion about this.

 rnd.seed(init_state, init_seq )

init_state is the starting state for the RNG, you can pass any 64-bit value.
init_seq selects the output sequence for the RNG, you can pass any 64-bit value, although only the low 63 bits are significant.

Example is here

3 Likes

Fantastic! Gave it test run today itā€™s works beautifully. Thanks so much for doing this!

1 Like

glad it worked.
But you should consider to find a better way than seeding million of times. This is not a good approach.

1 Like

I seed three times now in total, I think thatā€™s ok! :slight_smile:

2 Likes

Hey! I am just getting started with defold and was having trouble with the math.random() functions. So after a little digging, I found this module. It looks great, but even after adding the zip file to my dependency list, I still cannot quite get the functions to work, even on a simple task like calling the rnd.number() function.

When I call the function, I get a script error: ā€œattempt to index global ā€˜rndā€™ (a nil value)ā€

Do you have any idea what I might have done wrong? Is there something I need to ā€œrequireā€ for it to work right?

Did you click Project > Fetch Libraries after adding the dependency?

1 Like

As a matter of fact, I did not. This is the first dependency Iā€™ve worked with, so I didnā€™t realize that was necessary. :sweat_smile:

Thank you!

4 Likes

I hope fetching the lib fixed this issue! This not a good design actually. People can simply forget to fetch.

math.random is more than enough for most of the time . What was your problem with it?

1 Like

Perhaps when changing the text of the libs in the game.project file the editor could detect the change and show a (! Fetch Libraries Needed) signal somewhere.

5 Likes

When I tried working with math.random, it would always give me the same string of values, always starting with the minimal value when I set a range. I know this is the intention of the function, and the popular way around it is to set the math.randomseed to be based on os.time and calling the function a few times to help with the randomness, but I was having issues getting that to work properly too.

Honestly, I know that the concept of entropy seed is probably overkill, especially when I have a range of less than 10, but I do think that your solution was easier than figuring out all the os.time stuff.

And yes, fetching the library definitely worked!

1 Like

Remember to only call math.randomseed() once when the application starts.

I have a small update.
rnd.double_range(min, max) added.
This one is not fast and consistent as rnd.double(). It is just a fake double but gets the job done for me

local n = rnd.double_range(1.25, 2.53)
5 Likes