Archived

This topic is now archived and is closed to further replies.

Predictable Randomization

This topic is 5553 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I''ve upgraded to Visual C++.NET from an ancient copy of Borland''s Turbo C. I wrote a function that used the "rand" function to generate random numbers from X-Y, but for any given set of X & Y, the function returns the same random variable over and over again, even if I seed the random number generator with the system time!! For goodness sakes, someone help me out here! How do I generate random numbers that are actually random? In case you need to know, the function uses the 0-32767 number returned, converts it to a double, rescales it by multiplying it by Y-X+1 and dividing it by 32767, rounds it off, and adds X. (At least I think this is how I wrote it; I''m not typing this post on my own computer.) Is there a simpler system function, perhaps?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster

double num = (double)rand() / (double) RAND_MAX;
int r = (num *((double)Y-X+1)) + X;
return r

Share this post


Link to post
Share on other sites
rand isn''t broken. Either you''re re-seeding the same value between each call, or your function to manipulate the number is aliasing everything to the same values. Post some code.

Share this post


Link to post
Share on other sites
As a fairly recent (started learning C two years ago, C++ this month) convert to Visual C++, I may not know what I''m doing, but this seems like a fairly clear-cut case of poor documentation to me.

Here''s the function:


#include <math.h>
#include <stdlib.h>
#include <time.h>

int trueRand(int start, int finish)
{
srand( (unsigned)time( NULL ) );
double scaleConversion=RAND_MAX/(1+finish-start);
int tmpRandom=rand();
tmpRandom=((tmpRandom+start)/scaleConversion)+start-1;
return tmpRandom;
}

Share this post


Link to post
Share on other sites
quote:
Original post by DuranStrife
As a fairly recent (started learning C two years ago, C++ this month) convert to Visual C++, I may not know what I''m doing, but this seems like a fairly clear-cut case of poor documentation to me.

The MSDN docs I own say this:

"The srand function sets the starting point for generating a series of pseudorandom integers."

Note the term ''series'', which implies that you call srand once for every X calls of rand. It may not be explicit what you need to do in your situation, but sometimes you do need to call srand several times, so it can hardly say "you must only call srand once".




[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]

Share this post


Link to post
Share on other sites
quote:
Original post by Kylotan
The MSDN docs I own say this:

"The srand function sets the starting point for generating a series of pseudorandom integers."

Note the term ''series'', which implies that you call srand once for every X calls of rand.


I don''t see how A implies B here.

The docs merely explains what rand does: returns a pseudorandom series, meaning that from any starting seed the random numbers generated will be the same as subsequent calls to rand starting from the same seed. This doesn''t imply that you need to re-seed it every X calls. It wouldn''t hurt your randomness unless you seed it to the same value each time, but it would incur unnecessary overhead.

quote:

It may not be explicit what you need to do in your situation, but sometimes you do need to call srand several times, so it can hardly say "you must only call srand once".



The only times I can think you''d want to call srand are:
- beginning of the program.
- beginning of a "replay" or some function where you want to synchronize the pseudo-random sequence to a prior value.
- beginning of a "match" in a multiplayer game where it''s important that random events are generated in the same way on each player''s computer.

Share this post


Link to post
Share on other sites
quote:
Original post by Stoffel
This doesn''t imply that you need to re-seed it every X calls.

What I said was unclear. I didn''t mean that you need to re-seed it every X calls, I meant that there is a 1 to many relationship between srand and rand calls, as opposed to the 1 to 1 relationship that so many new programmers mistakenly use.

quote:
The only times I can think you''d want to call srand are:
- beginning of the program.
- beginning of a "replay" or some function where you want to synchronize the pseudo-random sequence to a prior value.
- beginning of a "match" in a multiplayer game where it''s important that random events are generated in the same way on each player''s computer.

I use it to get reproducable ''random'' number sequences, meaning that someone with a 1% lockpicking skill on my RPG can''t just try 100 times (or thereabouts) and be sure to succeed.



[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]

Share this post


Link to post
Share on other sites
quote:
Original post by Kylotan
I use it to get reproducable ''random'' number sequences, meaning that someone with a 1% lockpicking skill on my RPG can''t just try 100 times (or thereabouts) and be sure to succeed.

Very nice, hadn''t thought of that application. That''s pretty ingenious.

Share this post


Link to post
Share on other sites
Note that if a player has 1% lockpicking chance, it can mean three things:

1°/ If he finds a door, and tries to lockpick it 100 times and be sure to get it open.

2°/ If he finds 100 doors, he will be able to open only one of them.

3°/ You skipped the wrong mathematics course.

Cheating on the player will get the player angry, even if he doesn''t know it. Instead of preventing the player from opening the door JUST because you don''t want him to open the door, prevent him by telling him his lockpick is broken.

Moreover, if he cannot open a door just by lockpicking it 100 times, then his lockpicking chance is less than 1%. If you tell him it IS 1%, you''re just feeding the player false information. And if you''re not USING that percentage anyway, why do you show it? Wouldn''t it be easier and less rude to the player to use fuzzy values (for instance Lockpicking LVL 3)?

This is just the way I''m being frustrated when playing Diablo2: having 95% chances hitting some monster, and having 20-30 misses in a row against it...

Not so cheerful, ToohrVyk.

Share this post


Link to post
Share on other sites
quote:
Original post by ToohrVyk
Note that if a player has 1% lockpicking chance, it can mean three things:

1°/ If he finds a door, and tries to lockpick it 100 times and be sure to get it open.


If I flip a coin twice, am I guaranteed to get heads once? If I roll a six-sided die six times, am I guaranteed a four?

Read the first chapter of any introductory stats textbook.


Don''t listen to me. I''ve had too much coffee.

Share this post


Link to post
Share on other sites
The function srand shouldn't act this way, since the system time is constantly changing, but moving the srand call to the beginning of main did indeed fix my problem. Many thanks to Beer Hunter!!

Oh, and by the way, the principle Beer Hunter showed comes greatly in handy in pen & paper roleplaying games that list default encounter chances per hour for certain terrain types. Just take the chance of NOT being attacked in a given hour, ^24 it, and subtract from 100 to get the % chance of being attacked at least once in a 24-hour period. Understanding this concept of probability also comes greatly in handy when creating balanced statistics rules for a computer RPG.

[edited by - DuranStrife on September 13, 2002 9:19:27 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Remember, the system time isn''t "constantly" changing, it ticks at about once every 55ms.

Even on a slow machine you could call that function hundreds of times before the system timer "ticks" again.

And if you call srand before every call to rand you are limiting the non-repeating length of the random sequence to the maximum size of the parameter to srand (an unsigned int IIRC). rand can produce longer non-repeating sequences than that if srand is only called once.

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
And if you call srand before every call to rand you are limiting the non-repeating length of the random sequence to the maximum size of the parameter to srand (an unsigned int IIRC). rand can produce longer non-repeating sequences than that if srand is only called once.

Please ignore this insane statement.

Share this post


Link to post
Share on other sites
quote:
Original post by Kylotan
I use it to get reproducable ''random'' number sequences, meaning that someone with a 1% lockpicking skill on my RPG can''t just try 100 times (or thereabouts) and be sure to succeed.

I don''t get it. Wouldn''t you get the same results with any random number generator? What''s the use of srand there? To get ''reproducable'' numbers? Why would you want that?

Cédric

Share this post


Link to post
Share on other sites
quote:
Original post by Kylotan
I use it to get reproducable ''random'' number sequences, meaning that someone with a 1% lockpicking skill on my RPG can''t just try 100 times (or thereabouts) and be sure to succeed.

quote:
Original post by cedricl
I don''t get it. Wouldn''t you get the same results with any random number generator? What''s the use of srand there? To get ''reproducable'' numbers? Why would you want that?


I am in the same boat as cedric. Can you please give a little more explanation?

Share this post


Link to post
Share on other sites
In most D&D house rules I know of, if you fail at picking a lock or disarming a trap, you can''t try again. Using the method Kylotan describes, you can implement this easily without having to track which traps or doors a player has tried already, as long as each object has a unique ID. Each time an attempt is made, the RNG is seeded with the object''s unique ID. This assures that the same RN will be generated for each try.

Using this method, if a poor thief with 1% lockpick skill was presented with 100 doors, the odds are that he''d only be able to pick 1 of the locks. No matter how many times he tries, he will never be able to open any of the other doors. Likewise, if a thief has a 90% lockpicking skill, odds are that around 10 of the doors simply will not open for him.

Share this post


Link to post
Share on other sites
quote:
Original post by ToohrVyk
Note that if a player has 1% lockpicking chance, it can mean three things:

or
4: you misread what I said: I said lockpicking SKILL, not CHANCE. In other words, the player has learned lockpicking 1%. Not that they automatically have 1% chance of success on any lock. The best they can manage is 100% learning for a skill. These are very different concepts.

Edit - and indeed, Stoffel's explanation works if you really want the percentage to be a percentage chance - it's a percentage chance of being skilled enough to open a given door at all, not a percentage chance of being able to open a given door on each attempt.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files | My stuff ]

[edited by - Kylotan on September 15, 2002 3:38:03 PM]

Share this post


Link to post
Share on other sites
I just called the srand once outside the trueRand function. It solves the problem.

I think the problem is srand() always get the same seed from time(NULL). FYI, time(NULL) gives the number of secs from Jan 1st 1970 and it always generate the same number sequence for rand() to get(within the same sec) and rand() always get the 1st number and subsequent rand() will get the consecutive generated numbers but you always re-seed it, so rand() always get the same 1st number.

Share this post


Link to post
Share on other sites