Loading...
Logo
Processing Forum

Detecting Seed After the Fact?

in General Discussion  •  Other  •  1 year ago  
This question is related to, but different from what is discussed here.

If random() or noise() are not called in conjunction with randomSeed() or noiseSeed(), is there still a seed value at work behind the scenes? One that gets changed with each call? Or is the seedless process somehow completely different from the seeded one?

More to the point, if I'm playing with a non-seeded random or noisy sketch, I expect to get different results each time. But if I happen across a result that is particularly interesting, is there any way reproduce that result after the fact? That is, could some code be added which tracks how a random or noisy function got its start?

I do realize I could set a seed value from the get-go (even a randomized seed value), and print that to the console, so I'd know what seed had produced a given result. I was just wondering if there were any way to excavate the seed or genesis or ur-condition of random or noise without an explicitly specified seed. TIA.

Replies(5)

See the source. The information you want is in:

Random internalRandom;
Random perlinRandom;

When no seed is set manually, a seed is set automatically.

Unfortunately these are not public, so they can't be accessed from PDE sketches.

You might be able to get to them if you extend PApplet in Eclipse.

It seems easier to just set a seed manually as you said, so you can keep track of interesting seeds.

Since the solution I mentioned is trivial to implement, that's the way I'll go. But thanks to your answer, and reviewing the Processing source code, and following a few other breadcrumbs, I've come away with a better understanding of the process and initial seed states in particular. Thanks hugely for the reply!
Could you just store the values created during execution  each frame, and store them in a file? 
This could be done, but it's the initial seed state that's the crucial one. With that as a known, the rest follows deterministically. At least that's my understanding at this point.
Just to follow up on this a bit for future reference:

It's easy to pass a seed value to a variable, change it, track it, and restore it. The following pseudo-code snippets are working well for me:

Copy code
  1. // Global declarations.
  2. int noiseSeedVal = int(random(// someValue));     // Create a different seed each runtime.
  3. //  int noiseSeedVal = // someValue;                    // Or use this line instead to reproduce the same pattern.
  4. int noiseSeedValStore = noiseSeedVal;            // Storage variable for reset to initial value.

  5. void setup() {
  6. // Cool setup-y stuff.
  7. println("Initial Noise Seed Value:  " + noiseSeedVal);      // This line prints once to the console.
  8. }

  9. void draw() {
  10.   noiseSeed(noiseSeedVal);                    // Works in setup() or global, but needs to be in draw for runtime changes.
  11. // Cool draw-y stuff.
  12. }

  13. /* ========= UI =========== */

  14. // Increment/decrement seed value for new result (could randomize instead).
  15. // Print on demand the new seed value to the console.
  16. void keyPressed() {
  17.   if (key == '=' || key == '+') noiseSeedVal += 1; 
  18.   if (key == '-' || key == '_') noiseSeedVal -= 1;
  19.   if (key == '?')  println("Current Noise Seed Value:  " + noiseSeedVal);
  20. }

You can also set a mouse or key event for

  noiseSeedVal = noiseSeedValStore;

to restore the value to its initial conditions.

The upshot of all this is that you can set a seed randomly or specifically, and have its value discoverable and available for later retrieval if you want to reuse it for a specific desirable output. You can manually experiment with different values during runtime, or automate seed changes inside draw(). The new values are also available for inspection, but need not clutter up the console with new values every frame.

Maybe someone will find this useful.