Log In  

I was looking at some of the tweet jam carts and noticed some of them use srand() in the loop, so srand() is called A LOT to generate whatever...

I took one of those carts and am firing rnd() when the user presses a button, hoping to get a new random number each button press...but that doesn't seem to be happening.

Without a lot of debugging otherwise, it seems like rnd() spits out the same number each time (ie, not so random)

I figure this is happening because srand() is running almost constantly in the tweet code. Just for shits, I took out the srand() and that solved the rnd() problem but then totally messes up the tweet jam cart.

So I guess I need to find a way to generate a random number that doesn't involved rnd()...? Or find something that avoid having to use srand() so then rnd() will work as expected...?

Just seems like rnd() and srand() is flakey...not sure what to do and/or try.

Any thoughts or insight is appreciated.

P#26113 2016-07-29 22:22 ( Edited 2016-08-03 16:03)

Most RNG is calculated by utilizing the system clock. So you get a new "seed" every second. The tricky part is that for the most variation, you'll usually want prime numbers, which involves adding an odd number like 7 or 13 to your intended outcome (I'd say "adding the seconds," but you don't want incremental differences).

function rand(min, max)
(datehrmin*sec \ (max - min)) + 13 + min

Basically, you'll want to make a really big number, and take the remainder of that number (that's what makes it randomized), make it prime by an odd-number addition, and then add your minimum value to the overall range.

Actual mileage may vary, depending on how you're using the output. If it's small enough of a range - which given the scope of PICO-8 projects, it likely is - you can get away with making smaller seed numbers. You might even NEED to, since variables (like score) are capped at 32000, IIRC.

I'm guessing that since it's an early build of PICO still, that either it isn't fully implemented or tested all that much? You're probably just better off using seconds and/or minutes as the seeds themselves. Maybe the date, if you're going for daily mix-ups.

P#26115 2016-07-29 22:57 ( Edited 2016-07-30 02:59)

Look at:
http://www.cplusplus.com/reference/cstdlib/srand/

The pico-8 docs says that srand takes a seed argument. My guess is that calling srand without an argument makes the argument NULL o zero and that makes the seed be the same all the time.

Calling rnd after setting the same seed will get you the same number. What you want to do is call srand once with a specific seed, and all subsequent calls to rnd will result in a consistently random sequence of numbers.

P#26117 2016-07-29 23:22 ( Edited 2016-07-30 03:22)

THAT'S good to know. Also, digging the Metroid love. It's the one thing I'm wishing 3DS had that it doesn't already.

P#26118 2016-07-29 23:26 ( Edited 2016-07-30 03:26)

They're calling srand(0) every frame so they get the same pattern every frame.

You can simply switch their seed with yours while you do your work with a long-term rnd() series and then switch back for their deterministic one:

-- your starting seed 
my_seed=0xabcd.0123   -- or time() or whatever

function update()
  -- use your most recent seed
  srand(my_seed) 
  -- use the next rnd() in your own series
  if(btnp()) print(rnd(10)) 
  -- use a full-range rnd() as your next seed
  my_seed=rnd(0xffff.ffff)

  -- the original code
  srand(0)
  their_code()
end

It's common in certain types of games for some systems to use their own seeds. For instance, if you need determinism for replays, then your update must use a seed that's different from your draw. Your draw may not occur as many times as your update, and if it skips frames inconsistently, it will change the rnd() series the update receives. Some games even give individual entities their own seeds+series. It just depends on what you need.

P#26130 2016-07-30 10:19 ( Edited 2016-07-30 14:22)

Hmmm...so even with all that info, I'm thinking I'll have to alter my game intentions a bit or just use backgrounds that don't use srand() in their routines. I don't see any way around it at this point, unless I re-engineer my game a bit (but even then not sure what I'd do differently).

Maybe once I get it done and out there, someone can smarter than I can find a way to remedy the issue.

P#26189 2016-07-30 23:35 ( Edited 2016-07-31 03:35)

When I use srand in a tweetjam carts, it's usualy to avoid storing values in arrays. For example if you want to put random stars on a black background and animate then, you should give them random position x and y and store them to use when drawing the next frame. To save character count, you can reset the seed at the begining of each frame, and calls to rnd() will give your the same values in the same order each frame.
So to solve your issue, you could just store random values in an array at the init of the game, and then use them instead of rnd in the tweetjam code. Then you can use rnd in the rest of the game like usual.

P#26311 2016-08-02 08:19 ( Edited 2016-08-02 12:19)

@NuSan - Okay, I kind of get what you're saying...

So when I make that array at init, am I just adding a bunch of rnd() numbers to that array? Like loop N times and add(list, rnd()) kind of thing?

So like in your tweetjam with the ball field, how would I remove srand() from the loop but still get the same result? Just store 500 random numbers in an array and then pull them out one at a time each interation?

P#26321 2016-08-02 09:53 ( Edited 2016-08-02 13:54)

Exactly, you would code something like that :

function _init()
 balls={}
 for i=1,500 do
  add(balls,rnd())
 end
end

function _draw()
 cls()
 for i=1,500 do
  p=9-i/50
  j=(p+sin(t)-t*9)%11+.1
  k=balls[i]-5+cos(t)
  circfill(k/j*50+64,80/j-20,9/j,p)
 end
 t+=.01
end

Of course if you want to use two rnd() per items (like x and y) you would store twice as many in the array.
If you need a very high number of random value, you could simply loop on a smaller array. For P.Craft I used the same 2D array of randoms values at a lot of place, with different 2D offset for each use. That way I could choose randomly between several ground tiles to mask repetition for example.

P#26347 2016-08-02 17:57 ( Edited 2016-08-02 21:57)

Awesome, that did work as expected. Thanks for the tip. You'll be able to see the results in my next game, woot!

Only thing different I had to do was retain the rnd(9) of the original cart when seeding the array, but no biggie at all.

P#26375 2016-08-03 10:10 ( Edited 2016-08-03 14:10)

Oh yeah, I forgot the 9 when filling the array. You can also store rnd() and multiply by 9 when you use the value. That way you can reuse those random value whith different multiplication at different place.

P#26380 2016-08-03 12:03 ( Edited 2016-08-03 16:03)

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-28 15:29:41 | 0.012s | Q:24