gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > How to generate lots of random numbers?

#141879 - Jeremysr - Mon Oct 01, 2007 3:47 am

I'm making a puzzle game which has lots of tiles and each tile has numbers on it. When I generate a puzzle, most of the numbers have to be random numbers (between 0 and 9) and after that I randomize the position of the tiles multiple times.

My question is how can I make all these numbers completely random? rand() seems to work pretty good but it generates the exact same puzzle each time.

#141880 - Lazy1 - Mon Oct 01, 2007 4:25 am

You need to seed the random number generator first before calling rand.

Code:

srand( sometime );
...
...
blah = rand();
bleh = rand();


Normally it would be seeded with the time but you can use any number.
Keep in mind though if you use the same number to seed it will generate the same numbers.

Since by default time() is unavailable on the DS you'll need to find another way of seeding the RNG.

#141883 - DragonMinded - Mon Oct 01, 2007 6:39 am

A good way of truly randomizing is to capture some data from the microphone on startup, and use that to seed.
_________________
Enter the mind of the dragon.

http://dragonminded.blogspot.com

Seriously guys, how hard is it to simply TRY something yourself?

#141885 - a128 - Mon Oct 01, 2007 8:44 am

http://en.wikipedia.org/wiki/Mersenne_twister

Use this one.....using different seeds with srand() does not produce a better random generator :-)

#141899 - tepples - Mon Oct 01, 2007 12:40 pm

Lazy1 wrote:
Since by default time() is unavailable on the DS you'll need to find another way of seeding the RNG.

This is fixable. Isn't there some way to grab the current time from the ARM7?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#141900 - Lick - Mon Oct 01, 2007 12:55 pm

DragonMinded has a time() implementation in DSO I believe, and I also wrote one (NDSX_time). I'm not sure if either of these work with the latest libnds.
_________________
http://licklick.wordpress.com

#141901 - Jesse - Mon Oct 01, 2007 12:59 pm

tepples wrote:
Lazy1 wrote:
Since by default time() is unavailable on the DS you'll need to find another way of seeding the RNG.

This is fixable. Isn't there some way to grab the current time from the ARM7?

With the CVS version of libnds this works nicely:
srand(IPC->time.rtc.seconds);
Of course, you may want to take more than the seconds into account, if you want more than 60 different setups. :)
_________________
http://www.collectingsmiles.com/colors & http://www.collectingsmiles.com/hyena

#141903 - freemaan - Mon Oct 01, 2007 2:09 pm

You can use the WiFi register 0x044 (W_RANDOM) too to get a 11 bit random number.

#141907 - HyperHacker - Mon Oct 01, 2007 2:33 pm

Lazy1 wrote:
You need to seed the random number generator first before calling rand.

Code:

srand( sometime );
...
...
blah = rand();
bleh = rand();


Normally it would be seeded with the time but you can use any number.
Keep in mind though if you use the same number to seed it will generate the same numbers.

Since by default time() is unavailable on the DS you'll need to find another way of seeding the RNG.
Games on consoles without a real-time clock tended to do it by counting how many VBlanks until the player does something such as pushing Start at the title screen. This has the potential gotcha, though, that if the player always just mashes Start during startup to skip the title as fast as possible, they're likely to get the same few seeds over and over.
_________________
I'm a PSP hacker now, but I still <3 DS.

#141912 - Lick - Mon Oct 01, 2007 4:02 pm

freemaan wrote:
You can use the WiFi register 0x044 (W_RANDOM) too to get a 11 bit random number.


Hey that's a good one. I hope I'll remember it when I need it. Any idea about its randomness though?
_________________
http://licklick.wordpress.com

#141913 - Mighty Max - Mon Oct 01, 2007 4:39 pm

It's less random as proper use of rand()

nocash gbatek wrote:

044h - W_RANDOM - Random Generator (R)

0-10 Random
11-15 Not used (zero)

The random generator is updated at 33MHz rate, as such:

X = (X AND 1) XOR (X ROL 1) ;(rotation within 11bit range)

The random sequence goes through 5FDh different values before it restarts.
When reading from the random register, the old latched value is returned to the CPU, and the new current random value is then latched, so reads always return the older value, timed from the previous read.
Occassionally, about once every some thousand reads, the latching appears to occur 4 cycles earlier than normally, so the value on the next read will be 4 cycles older than expected.
The random register has ACTIVE mirrors.

_________________
GBAMP Multiboot

#141939 - Jeremysr - Tue Oct 02, 2007 12:21 am

I didn't realize that you only have to seed the number generator once, and then it seems to generate good random numbers... I thought I had to seed it each time I want to generate a new number. I counted vblanks during the splash screen to get the seed and it seems to work good :)

If I can figure it out though, I'll try to use a combination of vblank counts and microphone volume. Thanks everyone

#141956 - mml - Tue Oct 02, 2007 11:41 am

Jeremysr wrote:
I didn't realize that you only have to seed the number generator once, and then it seems to generate good random numbers...


To explain it in simple terms: rand() will always generate the same (very long) sequence of numbers. When you "seed" it, you're setting where in this long sequence to start from. If you don't seed it, you'll always start at the start (and always get the same numbers in the same order). If you seed it with the same number each time you start up, you'll start from a different position than if you hadn't seeded, but will still always get the same numbers in the same order, relative to the seed. (This can be useful during debugging because you can predict the numbers that will be generated, and compare what it does with those numbers against what you expected it to do with them.) In typical usage though, you would want to seed it with a different number each time your program starts, in order to get a sequence of numbers that feels random enough.

In the PC world it's traditional to pick a seed using time(), which will give back the number of seconds since the start of 1970. Most of the time this is a "random enough" starting point (if you start the app twice in the same second you'll get the same sequence of numbers, but for most apps this is pretty unlikely).

I guess on the DS you might try grabbing a number from the W_RANDOM register described above, and using that to seed rand.

#141995 - Mighty Max - Tue Oct 02, 2007 9:47 pm

mml wrote:
Most of the time this is a "random enough" starting point (if you start the app twice in the same second you'll get the same sequence of numbers, but for most apps this is pretty unlikely).


"Most of the time"?

Puzzle games get easy solvable, by "guessing" the seed. There even was an online poker with $ involved suffering from this problem in 2001 iirc, allowing an attacker to know all cards after the first few were known.

For everything even remotely security related, seeding with time only is a no-go.
_________________
GBAMP Multiboot

#142027 - mml - Wed Oct 03, 2007 11:32 am

For anything remotely security related, you shouldn't be using rand() to begin with. Most of the time you do use rand(), seeding with the time is fine.