Yellow-Dog-Man / Resonite-Issues

Issue repository for Resonite.
https://resonite.com
137 stars 2 forks source link

Seeded Random Values #2661

Open lxw404 opened 2 months ago

lxw404 commented 2 months ago

Is your feature request related to a problem? Please describe.

Right now Protoflux nodes for generating random numbers are not repeatable, which make them less useful for predictably generating random procedural structures.

Describe the solution you'd like

There should be a way to seed (initialize) the random number generator to get a predictable outcome from it, as well as perform single steps through its state machine to generate more random numbers from that initialized state.

Describe alternatives you've considered

The current only alternative is to use simplex noise and extract bits from that, however that is a very specific type of smoothed random which does not lend itself well at all for uniform sampling.

Additional Context

No response

Requesters

LuxKitty Baxter

shiftyscales commented 2 months ago

So you're effectively looking to create a pseudorandom number generator? Would you mind providing more context about your use case @lxw404? E.g. are there specific value types in particular you are interested?

What kind of mechanism are you envisioning for how the state of the nodes will be advanced? Per update? Per impulse? World Time? Something else entirely? In other words- by which metric do you wish for it to be "predictable"?

lxw404 commented 2 months ago

I'm actually not sure what best way this could be implemented in ProtoFlux, but importantly by "predictable" I mean every single random number from some node should have an exact sequence of outputs that is repeatable if you used the same initial state, regardless of machine or otherwise.

In (C++) for example, you build pseudo random number generators as a combination of a specific random number engine (which is the source of entropy for generating future random numbers), and a distribution function which alters that engine's state every time it is called. You can build as many engine-distribution combinations as you want, each one operating independently with their own states/initializations, but each time you want to get a random number, the state of the corresponding engine is modified by one step. By separating the source of entropy (engine) from the distribution, you can effectively generate many different predictable outputs from the same engine, and also completely control its state independent of other engines.

This might be a bit too far into the weeds though.

One of the most common uses for seeded random is for terrain/world/level generation. In these cases, you typically design an algorithm where everything generated by it can be exactly the same given some initial seed. The algorithms typically generate many random numbers in a deterministic fashion and use them accordingly. These can be literally any types, float, float2, float3, ColorX, int, etc, and can be as complex or simple as required for the generator.

A concrete example of this was in the past Creator Jam world "Cosmic Command". For this world, a game was built which generates a set of nodes in a 3D graph randomly with different players and unit numbers assigned to each one, however it was at that point impossible to reproduce certain "levels" that were generated by the graph algorithm and they were always completely unpredictable layouts. For a full game, it was desired to save the seed of "easy" and "hard" level layouts in order to give the players better choices on how they play.

For these use cases, it would need to be possible to set the exact initial state of some source of random bits, and then use that to "call" new random numbers. In ProtoFlux this just might have to be impulse-based, however I'm not totally sure how best to keep track of and update the source of random bits (random number engine). It's entirely possible that people would want to use an arbitrary number of separate random number "engines" in parallel as well to set different seeds and run the same generation process at the same time (for example each user getting a separate host controlled "seed", and they locally compute the results of the same generator function).

Frooxius commented 2 months ago

This is pretty common. Generally you just create instance of pseudorandomness generator with an explicit seed and then you sample it in exact same sequence.

It would work similarly with ProtoFlux - you create an instance and then provide it as input to the random sampling nodes.

My main concern will be that the random generator we use is a stable implementation, so we'll have to check that.