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.

Coding > RNG with exact period

#5657 - sgeos - Mon May 05, 2003 4:58 am

Has anyone come across a method of generating an RNG with an exact period? I'm looking for a way to setup RNGs on the fly with function call something like the following:

next_state = rng(current_state, period);

states range from 0 to period - 1. I'm not sure if Knuth covers this. At any rate, I don't have my books with me.

There is a way to generate LCGs that meet all the above criteria except that the output isn't random. Take:

r = m + 1; /* Or any multiple of m, plus one */
c = 1;
next_state = (current_state * r + c) % m;

-Brendan

#5704 - slip - Tue May 06, 2003 3:00 pm

I don't know your answer to the above.... But if you are just after a random number between a certain range, you can use a TIMER and %.

For example.
to generate a number between 0 and 6 inclusive, that appears random. Take a value from a timer (or any other source for that matter) and %7 it...
% is modulus.

I use timer 2 for this. (no specific reason why)

u16 number = REG_TM2D%X;

where X is your range from 0 to X-1

Though I have not tried this but you could extend this method by dividing a number by say... 10. for example.

float number = (float)((REG_TM2D%10)/10.0f);

It may be a little messy but It would probably work. You could use 10 like I have above to give you a range between 0 and 1.

hope this helped
slip

#5729 - sgeos - Wed May 07, 2003 3:41 am

slip wrote:

to generate a number between 0 and 6 inclusive, that appears random. Take a value from a timer (or any other source for that matter) and %7 it...
% is modulus.


mod is not the best way of generating random numbers. It is fast, and I'll admit that it's probably good enough in most cases relating to games.

slip wrote:

Though I have not tried this but you could extend this method by dividing a number by say... 10. for example.

float number = (float)((REG_TM2D%10)/10.0f);


The GBA has no hardware support for floats. The current general purpose RNG I'm using looks like this:

Code:
unsigned long state;

int dice(int min, int max)
{
  state *= 69069;
  return min + ((max - min + 1) * (state >> (4 * sizeof(unsigned long)))) /
    (0x1 << (4 * sizeof(unsigned long)));
}


It returns a number between min and max, inclusive.

slip wrote:
I don't know your answer to the above.... But if you are just after a random number between a certain range, you can use a TIMER and %.


Acually, I'm after all the numbers from zero to (n - 1) in a random order. What I'm currently doing is something like this:

Code:
int array[N];
int ctr;

for (ctr = 0; ctr < N; ctr++)
  array[ctr] = ctr;
for (ctr = 0; ctr < N; ctr++)
  SWAP(array[ctr], array[dice(0, N - 1)]);


The advantage to this is that I can generate the list and use it as many times as I want to. The disadvantage is that I have a potentially large array hanging around. I'd rather just generate the list algorimically.

-Brendan