• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
MarkS

Why is it "bad" to call srand multiple times?

25 posts in this topic

I keep reading this, but never an explanation. Being curious, I took a look at Visual Studio's code for rand and srand and all srand does is set a global variable. rand performs a typical pseudo-random number algorithm based on the global variable.

 

While I don't see any need to call srand multiple times, save for using the same seed to repeat the random values, I cannot see the harm. Why is it "bad"?

0

Share this post


Link to post
Share on other sites
What argument are you going to call it with next time? And why? If you want to make your rand sequence more random, throw away random numbers by calling rand() while waiting for something to happen you have no control over (such as a keypress).
0

Share this post


Link to post
Share on other sites
<blockquote class="ipsBlockquote" data-author="MarkS" data-cid="5014813"><p>I keep reading this, but never an explanation. Being curious, I took a look at Visual Studio's code for rand and srand and all srand does is set a global variable. rand performs a typical&nbsp;pseudo-random number algorithm based on the global variable.<br />&nbsp;<br />While I don't see any need to call srand multiple times, save for using the same seed to repeat the random values, I cannot see the harm. Why is it "bad"?</p></blockquote><br />because you normally pass a fairly low resolution timer value to srand, so if you do srand , rand, srand rand and both srand calls get passed the same value you will also get the same result from the rand calls. (which makes it very non random)
0

Share this post


Link to post
Share on other sites
What argument are you going to call it with next time? And why?

No idea. I'm not asking this because I plan on doing this or am currently doing this. I just want an explanation to go along with the statement.

0

Share this post


Link to post
Share on other sites
It's not necessarily calling srand multiple times, it's beginners repeatedly calling [tt]srand[/tt] with [tt]time(0)[/tt] and making a "rand isn't random" thread on gamedev:
for ( int i = 1; i <= 10; i=i+1 )
{
    srand( time(0) );
    int val = rand()%10 + 1;
    cout << val << endl;
}
Edited by fastcall22
1

Share this post


Link to post
Share on other sites
Well, you can't call it with the return value from rand(), since it will be the same. And if you already seeded it with a timer, seeding it again soon afterwards is likely to be predictable too. Only call srand with a known value if you need to repeat a random sequence again.

EDIT: Which is incredibly useful e.g. for rerunning simulations or doing a replay playback when you only store keypresses. Edited by Paradigm Shifter
0

Share this post


Link to post
Share on other sites

I don't know the context in which you heard that re-using srand is bad, but if you understand that you don't have to re-seed all the time (usually never) then I think you probably understand what's going on and can do what you like.

Edited by Khatharr
0

Share this post


Link to post
Share on other sites
I keep reading this, but never an explanation. Being curious, I took a look at Visual Studio's code for rand and srand and all srand does is set a global variable. rand performs a typical pseudo-random number algorithm based on the global variable.

 

because you just don't need to do that, its like checking variable twice just to make sure its value is consistent. just do

// time() returns the time as the number of seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).
srand(time()); // well not sure time() is present in MSVC
1

Share this post


Link to post
Share on other sites
Calling srand() multiple times is not "bad". If you need to call it multiple times then call it multiple times. There are many scenarios in which you would. You may for instance randomly generate game levels and want to save the seed that you used to randomly generate the levels as part of the game save file. In that case, you would call srand() every time you load a level.

The problem is that if you see someone calling srand() multiple times and that person is a beginner, generally speaking, they're doing so because they don't know what they are doing, so you see people saying, "Don't do that". That's all.
2

Share this post


Link to post
Share on other sites

Thanks, everyone.

 

Some of this I knew and some I didn't. However, every time a newbie would post code calling srand multiple times, they would be chastised, but rarely with explanation. This has the tendency to leave a new programmer in a state of confusion and with the feeling that they violated some unwritten rule. Hopefully this thread will be linked to in future cases.

0

Share this post


Link to post
Share on other sites

I did, didn't I? laugh.png

I've been in that mood today, having to twice cancelled from posting fully-written very colorful and sarcastic responses to... less than helpful users, on another forum. dry.png

At least the above slightly sarcastic response wasn't directed at a specific individual. wink.png

0

Share this post


Link to post
Share on other sites
At least the above slightly sarcastic response wasn't directed at a specific individual. wink.png

 

It does sound suspiciously familiar... unsure.png sleep.png

0

Share this post


Link to post
Share on other sites

[quote name='Servant of the Lord' timestamp='1356642050' post='5014852']Don't use rand(), it's inaccurate after the 2 billionth number is generated, and certain values are more likely to come up with an 0.003% higher probability than others. Instead, forget about completing your stupid little project, and go look up real fake psuedonumericallyperfectrandom number generators that college students study in compute science class.
[/quote]

I feel hurt because this is actually very relevant to my work sad.png nah no offense taken, it's true that for beginners it's best to just explain to them how to use those basic PRNG's, and then they can look up more about them if they're interested. In general, using rand() is perfectly fine for basically everything unless you're running a gambling site, ultra high precision probabilistic algorithm, cryptographic infrastructure, or other highly specialized tasks. Nothing like information overload to put somebody off programming.

0

Share this post


Link to post
Share on other sites

Don't use rand(), it's inaccurate after the 2 billionth number is generated, and certain values are more likely to come up with an 0.003% higher probability than others. Instead, forget about completing your stupid little project, and go look up real fake psuedonumericallyperfectrandom number generators that college students study in compute science class.

 

In general, using rand() is perfectly fine for basically everything unless you're running a gambling site, ultra high precision probabilistic algorithm, cryptographic infrastructure, or other highly specialized tasks. Nothing like information overload to put somebody off programming.

 

Using rand() is perfectly fine *if* you only need a uniform distribution. There are a lot of times where this isn't the case (for example, generating white noise, where you want a gaussian distribution). In those cases you'll need some kind of random number generator. I'd recommend the boost::random library, which lets you specify any distribution you want. 

 

Also, if you want a "truly random" number and you're on linux, call srand() once with a number read from /dev/rand or /dev/urand. These files provide about as close to a truly random number as you can get. Your sequence will still be predictable *if* you know the seed, but with a truly random seed, your numbers are also less predictable (i.e. "more" random). 

 

If you're wondering why you can't just read from /dev/rand or /dev/urand all the time when you need a random number, technically you *can,* you just *shouldn't,* since it depletes the random-ness of the numbers in the file, and can affect other programs running on the machine that need random numbers, like ssh. 

0

Share this post


Link to post
Share on other sites
Also, if you want a "truly random" number and you're on linux, call srand() once with a number read from /dev/rand or /dev/urand. These files provide about as close to a truly random number as you can get. Your sequence will still be predictable *if* you know the seed, but with a truly random seed, your numbers are also less predictable (i.e. "more" random).

There are a couple of things that are not right in that. First, the devices are /dev/random and /dev/urandom. Second, depending on the rand() implementation, it might be easy to recover the seed after observing a relatively short sequence of generated numbers. So you should keep incorporating entropy into the sequence every so often. /dev/random will block if you try to read from it and the pool of entropy is depleted, while /dev/urandom will always return a number without blocking, and a high-quality PRNG will be used if there is no more entropy. I believe /dev/urandom is random enough for every purpose I can think of.
1

Share this post


Link to post
Share on other sites
Using rand() is perfectly fine *if* you only need a uniform distribution. There are a lot of times where this isn't the case (for example, generating white noise, where you want a gaussian distribution). In those cases you'll need some kind of random number generator. I'd recommend the boost::random library, which lets you specify any distribution you want. 

 

Not true. The default LCG included in most rand() implementations does not produce a uniform distribution. Look up "random numbers fall mainly in the planes" from G. Marsaglia. Mersenne Twister does a much better job, though, so if you can use that easily without changing much code, I'd definitely recommend it. It's just that usually, this is good enough for most applications which don't require a perfectly uniform distribution, even a rough approximation usually suffices.

 

Also you can derive any statistical distribution from a uniform distribution - or any other distribution, for that matter - via inverse transform sampling (essentially, invert the cumulative distribution function). For an example with a normal distribution, check out the Box-Muller transform, or the Ziggurat algorithm.

 

 

 

Also, if you want a "truly random" number and you're on linux, call srand() once with a number read from /dev/rand or /dev/urand. These files provide about as close to a truly random number as you can get. Your sequence will still be predictable *if* you know the seed, but with a truly random seed, your numbers are also less predictable (i.e. "more" random).

Again, no. Even if your seed is highly unpredictable, the default LCG will not produce a proper uniform sequence. In fact, it doesn't even matter what your seed is, since a good LCG is a proper permutation - you'll just be starting at a different place in the cycle. A similar argument holds for Mersenne Twister, though it's not a permutation iirc. At least in the context of a game, if you're talking cryptography it's obviously different.

 

 

 

If you're wondering why you can't just read from /dev/rand or /dev/urand all the time when you need a random number, technically you *can,* you just *shouldn't,* since it depletes the random-ness of the numbers in the file, and can affect other programs running on the machine that need random numbers, like ssh. 

This really depends how much entropy you need. There are methods to stretch a single 128-bit value into an effectively infinite bitstream which is computationally indistinguishable from a truly uniformly random bitstream, but this is really going off-topic and overkill in this context. I don't wanna be "that guy" SOTL was talking about mellow.png

Edited by Bacterius
0

Share this post


Link to post
Share on other sites
In response to Bacterius's post I want to say that the rand() implementation you get in Linux (i.e., GLIBC's implementation) these days is much much better than a simple LCG.
1

Share this post


Link to post
Share on other sites
In response to Bacterius's post I want to say that the rand() implementation you get in Linux (i.e., GLIBC's implementation) these days is much much better than a simple LCG.

That's good to know. Better be safe than sorry though. I liked the C++11 way of having multiple standard PRNG's with a common interface so you could choose which one you wanted (I think there was the LCG, a MT, a couple lagged generators and a few other simple ones) and could easily change with a simple token replace.

0

Share this post


Link to post
Share on other sites

In general, using rand() is perfectly fine for basically everything unless you're running a gambling site, ultra high precision probabilistic algorithm, cryptographic infrastructure, or other highly specialized tasks. Nothing like information overload to put somebody off programming.

 
Using rand() is perfectly fine *if* you only need....

 

I completely agree that rand() is less-than perfect in many many situations. If the rand() implementation varies from compiler to compiler (which I think was the case was the C++98 standard, but I might be mistaken here), then that's yet another reason why you'll need your own implementation, so (for example) generated map seeds can be shared over the internet with users using your game compiled with different compilers on different operating systems.

 

My only point (directed at the OP's 'why such a simple response'), was that rand() works perfectly fine for a console game or a tetris/asteroids clone, and that anyone not understanding when and why to call srand() more than once, is also not needing anything better than rand(), and probably wouldn't understand how something like a Mersenne Twister implementation works.

 

Thankfully, C++11 has new better psuedo-random number generators (such as built-in standardized mersenne twister, among others), though because their usage is all templatey and classy, which is great for intermediate and advanced C++ users, a beginner will probably still use rand().

 

Discussion among more experienced developers (like in this thread) about the nitpicky implementation details is of immense value and very educational to people who didn't go through college (like myself). It just overwhelms people still trying to understand the difference between references and pointers, and possibly drives them away from programming because "it's too confusing".

Edited by Servant of the Lord
0

Share this post


Link to post
Share on other sites

One thing I didn't see anybody here mention (unless I skipped something) is that calling srand with the same value to get the same sequence is not portable. Sure, if you run it on the same implementation, you'll get the same sequence, but the algorithm used by rand is completely implementation defined, and switching to a different implementation of the standard library is bound to give you a different sequence.

 

Calling srand more than once is theoretically fine but you need to be aware of how it works. It's very unlikely you'll have any serious reasons to do it, and if it's to get the same sequence as in the above case, you probably want to use either your own RNG or a RNG library which guarantees the algorithm will stay the same always.

 

EDIT: just realized a part of the post above says this =/ But yes, that pretty much renders calling srand again mostly useless.

Edited by Sik_the_hedgehog
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0