Skip to main content
gamedev.net
🔒 Locked

Random Number Generator

Started by programmer2 43 replies 2.8k views
Original Post
programmer2
programmer2
I''m making a basic adventure game, and am wondering how to make a random number generator for attacks, etc. in C++.
krad7
krad7
why dont you use the inbuild random number generator. rand() gives a random number between 0 and 32000 something i dont remember. and you might wanna srand(int seed) before using rand.

Slow and steady wins the race.
Slow and steady wins the race.
TekBoy
TekBoy
Yes, the standard C Runtime Library''s srand() and rand() functions are a good start. There are better PRNGs on the ''net which generate more than 15-bit values with more "randomness" and also are faster, but just experiment with rand() for now....
Homer Simpson
Homer Simpson
well... the rand() function that is in the stdlib don´t generate "true"( u´ll see that it is always the "same" numbers) so, u have to take the system time to use to generate real randomized numbers

#include // time()
#include <iostream.h>
#include <stdlib.h>
main(){
srand((unsigned)time(NULL));/*Uses the system time and use */
int rnum=0;

rnum=rand()%10; /*10 is the number of possibilities*/
cout<return 0;
}



sorry about my english i am brazilian


__________________
::Homer Simpson::
______::Homer Simpson::
DrPizza
DrPizza
(1) rand() is regularly shit
(2) STFW
(3) Mersenne Twister
char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;} /*** drpizza@battleaxe.net ***/
GoofProg
GoofProg
Any randomly generated number from a computer is NOT a complete random number. It mostly depends on the timing and that is what it uses as a seed to generate your pseudo-random generated numbers from.
The nightmare travels across the cosmos with his burning mane.  The trail of ash that is produced. ?Have a nice day!?
Hull
Hull
Modulo functions and time are excellent for simulating random numbers.

Get time in milliseconds (or microseconds with performance timer) and then use modulo to get the random range.

You can then keep the last value from your random function to
feed the next call, hence create a timebased fractal random value.

i.e.

  

float MyRandom()
{
static float tfrv = 0.0;

return tfrv = ((float)(( GetTimeInMsec() ) + (tfrv*1000000))%1000000)/1000000.0;

}



Just an idea.


[edited by - Hull on April 11, 2002 7:09:11 PM]
"Self awareness is the interaction between 3 different parts of your brain. The Cog, the Left and the Right side of you brain..."
DrPizza
DrPizza
quote:
Original post by GoofProg
Any randomly generated number from a computer is NOT a complete random number. It mostly depends on the timing and that is what it uses as a seed to generate your pseudo-random generated numbers from.

That simply isn't true. For a number of reasons.

The machine isn't deterministic; if it were to (let's say) generate a pseudorandom offsets into a disk using the current time as a seed, and then measure the time taken to read those offsets, it would give you back genuinely random answers, though that won't be very satisfactory if you want a lot of them.

However, to facilitate such things, Intel have begun including RNGs on their chipsets, which use thermal noise to generate random numbers, thereby introducing genuine randomness. This is the other main reason -- computers can sample their [random] environment and use them to generate random numbers.


[edited by - DrPizza on April 11, 2002 7:22:14 PM]
char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;} /*** drpizza@battleaxe.net ***/
Stoffel
Stoffel
Yay Beerhunter!
Oluseyi has an excellent point.
DrPizza: "rand() is regularly shit". How so? Its distribution is perfectly uniform and has a period of 2^32. That's pretty nice for many applications.

Oh, and computers are definitely NOT deterministic, because I can do something and it will work, and I can do the exact same thing later and it won't work.

[edited by - Stoffel on April 11, 2002 9:09:47 PM]
AdmiralBinary
AdmiralBinary
quote:
Original post by DrPizza
That simply isn''t true. For a number of reasons.

The machine isn''t deterministic; if it were to (let''s say) generate a pseudorandom offsets into a disk using the current time as a seed, and then measure the time taken to read those offsets, it would give you back genuinely random answers, though that won''t be very satisfactory if you want a lot of them.

However, to facilitate such things, Intel have begun including RNGs on their chipsets, which use thermal noise to generate random numbers, thereby introducing genuine randomness. This is the other main reason -- computers can sample their [random] environment and use them to generate random numbers.

This depends on how you define random. If you define random as "very difficult for the user to predict" (which seems to be the popular definition), then your method is simply "more random" than rand().

---------------

#define TRUE 0
#define FALSE 1
//MUAHAHAHAHAAAA!
DrPizza
DrPizza
quote:
Original post by Stoffel
How so? Its distribution is perfectly uniform and has a period of 2^32.

The VC++ rand(), for instance, only produces 15 random bits (i.e. RAND_MAX is 0x7fff), which isn''t enough for many applications, and has period 0x8000 0000 (that is, the sequence of numbers produced with srand(0) will be identical to the sequence of numbers produced with srand(0x80000000)) -- this is easily verifiable (read the source, or write a simple program to test it), which is why I can''t understand why you''d claim otherwise.

The bottom eight bits have period 2^24 (again, easily testable). This means that common (although unsafe, for this reason) practices such as saying: rand() % number to get numbers in the range [0, number) will seriously reduce the period; with smaller ranges, things get even worse (the bottom four bits have period 0x1ac50). The situation is significantly improved with the top 7 bits, which have a much longer period.

VC++''s rand() has significant issues that people need to be aware of. The bottom bits do not have a long period, and any code that concentrates on the bottom bits will be more predictable than it ought to be. VC++ isn''t unusual in having such a function, either. Other RNGs -- for instance, the Mersenne Twister -- have longer periods even with small numbers of bits. It''s fast, I''ll give it that -- one can test its entire result set in a few minutes on a new machine; the same can''t be said for the (far more complex) Mersenne Twister (which takes about 250 times longer).

quote:
That''s pretty nice for many applications.

Unless you need lots of random bits, in which case it''s pretty lousy.




quote:
This depends on how you define random. If you define random as "very difficult for the user to predict" (which seems to be the popular definition), then your method is simply "more random" than rand().

I don''t mean hard to predict. I mean impossible to predict -- described only by a probability distribution, with no deterministic relationship between results. Whilst you may be able to place a hard lower and upper bound (a seek time will never be more than 30 seconds, because at 30 seconds IDE times out, and never less than 0 seconds, because it''s impossible), you can never predict them -- particularly not with the nanosecond accuracy that that processor can use.

char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;} /*** drpizza@battleaxe.net ***/
intellibug
intellibug
i would recommend reading Knuth''s algorithm book series. there''s a HUGE chapter ( 150 pages i think) only about random number generation. after reading it you should know what to do. (in the end it comes out that you will simply use rand(), because it really just suffices for most applications like games :-) ). another nice text covering random numbers is in sedgewicks "algorithms in c" book, quite simple.

hope this helps..
Stoffel
Stoffel
quote:
Original post by DrPizza
The VC++ rand(), for instance, only produces 15 random bits (i.e. RAND_MAX is 0x7fff), which isn''t enough for many applications, and has period 0x8000 0000 (that is, the sequence of numbers produced with srand(0) will be identical to the sequence of numbers produced with srand(0x80000000)) -- this is easily verifiable (read the source, or write a simple program to test it), which is why I can''t understand why you''d claim otherwise.


Oops, I said 2^32 instead of 2^31. I guess I''m just a lying bastard.

quote:

The bottom eight bits have period 2^24 (again, easily testable). This means that common (although unsafe, for this reason) practices such as saying: rand() % number to get numbers in the range [0, number) will seriously reduce the period; with smaller ranges, things get even worse (the bottom four bits have period 0x1ac50). The situation is significantly improved with the top 7 bits, which have a much longer period.


And using modulo is the absolute wrong way to use rand (). Doing it the right way uses mostly the upper bits. Again, I fail to see how this makes rand "shit".

quote:

VC++''s rand() has significant issues that people need to be aware of. The bottom bits do not have a long period, and any code that concentrates on the bottom bits will be more predictable than it ought to be. VC++ isn''t unusual in having such a function, either. Other RNGs -- for instance, the Mersenne Twister -- have longer periods even with small numbers of bits. It''s fast, I''ll give it that -- one can test its entire result set in a few minutes on a new machine; the same can''t be said for the (far more complex) Mersenne Twister (which takes about 250 times longer).


So you''re saying for engineering and simulation applications, Mersenne Twister is more appropriate because it has a better distribution at the cost of efficiency. But for speed-critical applications, like, oh, I don''t know, games or something like that, rand () is the better choice. I agree with that.

intellibug
intellibug
"the same can''t be said for the (far more complex) Mersenne Twister (which takes about 250 times longer)."

i don''t understand that. the guys which did mersenne twister said it is up to four times faster than rand() (look on their homepage). i can''t remember the idea behind the mersenne-twister algorithm, but it just does a few bit operations to calc. a random number (and every 600-something times it recomputes the table, which is of course the slow part of the generator).
DrPizza
DrPizza
quote:
Original post by Stoffel
And using modulo is the absolute wrong way to use rand ().

That is entirely dependent on the RNG. The issue here is that with something like the Mersenne Twister, the period of even the bottom bits is very long. It is a particular failing of the stock VC++ rand() that makes mod so inappropriate.

quote:
Doing it the right way uses mostly the upper bits. Again, I fail to see how this makes rand "shit".

Good RNGs don''t require such special measures to be taken.

quote:
So you''re saying for engineering and simulation applications, Mersenne Twister is more appropriate because it has a better distribution at the cost of efficiency. But for speed-critical applications, like, oh, I don''t know, games or something like that, rand () is the better choice. I agree with that.

When appropriate measures are taken to get the longer period bits from rand(), its performance will tend to decrease; as long as you can stomach MT''s periodic "shuffling", its performance isn''t that bad (every few hundred it generates the next block of numbers).
char a[99999],*p=a;int main(int c,char**V){char*v=c>0?1[V]:(char*)V;if(c>=0)for(;*v&&93!=*v;){62==*v&&++p||60==*v&&--p||43==*v&&++*p||45==*v&&--*p||44==*v&&(*p=getchar())||46==*v&&putchar(*p)||91==*v&&(*p&&main(0,(char**)(--v+2))||(v=(char*)main(-1,(char**)++v)-1));++v;}else for(c=1;c;c+=(91==*v)-(93==*v),++v);return(int)v;} /*** drpizza@battleaxe.net ***/
Andrew Nguyen
Andrew Nguyen
Wait, is this a discussin on which random number generator implementation is the best or is it about a n00b who just needs a simple random number generator for a small adventure game?
---START GEEK CODE BLOCK---GCS/M/S dpu s:+ a---- C++ UL(+) P(++) L+(+) E--- W++ N+ o K w(--) !O !M !V PS- PE+Y+ PGP+ t 5 X-- R tv+ b+ DI+ D G e* h! r-- !x ---END GEEK CODE BLOCK---

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.