Computers are deterministic machines. This means that if you give them the same input, and perform the same operations, you'll get the same output every time. With respect to the desk example, everyone gets the same pieces, follows the same instructions, and so builds the same desk.
Again, using the context of games, if everyone gets the same assets and algorithms to put them together, we will all get the same game and experience. Sometimes, this is the goal. However, in our case, we want to create game systems that are unpredictable and dynamic. Therefore, we need to introduce an element of randomness to procedural generation.
Pseudorandom number generation
Random number generation is simply the process of picking a number at random. This is pretty straightforward for us, but it is a much tougher task for a computer. In fact, it's impossible for a computer to generate a truly random number without special hardware. You'll understand why this is so in a moment.
The next best thing is pseudorandom number generation. The word pseudo literally means not genuine. Therefore, pseudorandom number generation can be thought of as a fake random number generation. The numbers appear to be random but are actually the result of complex equations and algorithms that could in fact be calculated in advance.
Bear in mind that not all pseudorandom number generators are built equally. For applications such as trivial simulations and games, fairly linear algorithms can be used and are perfectly suitable. However, pseudorandom number generation is also used in applications such as cryptography, and will use much more complex algorithms so that the outcome cannot be determined via patterns created from earlier outputs.
The pseudorandom number generators that we use as developers fall firmly into the first category and are perfectly suitable. Luckily for us, C++ offers a number of ways in which trivial pseudorandom numbers can be generated. Throughout the course of this book, we will use std::rand()
and std::srand()
, both of which standard C++ functions that are included in <cstdlib>
library.
Tip
Learning how to read and extract information from documentation is a skill that I feel is often overlooked. With a multitude of great forums at hand it's easy to go straight to Google for a solution to your problem, but first, always read the documentation. http://www.cplusplus.com is a great C++ reference, and SFML is fully documented at http://www.sfml-dev.org/documentation/.
Why computers can't generate truly random numbers
We now know that computers can't generate random numbers, and that we generate pseudorandom numbers instead. Let's have a look at why this is so.
The reason behind this is the same as the reason why two computers will reach the same output given the same input and operation; computers are deterministic. Everything that a computer produces is the result of an algorithm or equation. They are nothing more than highly sophisticated calculators. Therefore, you can't ask them to act unpredictably.
True random numbers can be generated, but you need to utilize systems outside the machine. For example, at https://www.random.org/
you can generate truly random numbers using atmospheric noise. There are other systems that are akin to this, but unless you are generating random numbers for something important such as security purposes, trivial pseudorandom number generation will suffice.
Generating random numbers in C++
Let's start coding by writing a small program to generate some pseudorandom numbers. To do this, we will use the std::rand()
function. It generates a pseudorandom integer in the range between 0
to RAND_MAX
. The RAND_MAX
variable is a constant defined in <cstdlib>
. Its value will vary depending on the library that you are using. On a standard library implementation, it's guaranteed to be at least 32767.
Tip
If you're already familiar with this topic, feel free to skip ahead to the sub-chapter named Seeds.
You can download the code for this program from the Packt website at http://www.packtpub.com/support. It will be present in the Examples
folder, and the project name is random_numbers
:
Tip
Downloading the example code
You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
This is a very simple console application that makes a call to std::rand()
every time we press the Enter key. This returns us the pseudorandom number, and we pass it to std::cout
to display it. That's how easy it is!
Generating random numbers within a range
The previous code generated numbers between 0
and RAND_MAX
. That's great, but we'll usually want more control over this in order to generate numbers within a certain range. To do this, we are going to use the modulo operator.
Tip
In C++, the modulo operator is the % symbol. This varies between languages, but is generally either % or Mod.
The modulo operator returns the remainder of the division between two numbers. So, 9 mod 2 is 1, as 2 goes into 9 four times with 1 left over. We can use this to create a range for the pseudorandom number generation. Let's generate a number between 0 and 249.
To do this, we need to make the following change:
Run the program a few times now, and you'll see that all the results are limited to the range that we just defined. So now we can generate a number between 0 and n, but what if we don't want our range to start from 0? To do this, we need to make one more change to the line that generates a number:
Remember that the number we used in the mod calculation will generate a number between 0 and n-1, and the number we add afterwards will increase the range by that amount. So here, we generate a number between 0 and 200 and then increase the range by 50 to get a number between 50 and 250.
Tip
If you're not fully comfortable with the math behind what we're doing here, head over to Khan Academy. It's a fantastic resource for learning and has lots of great mathematics-related material.
Run the program and note the first five numbers that are generated. In my case, they are 91, 226, 153, 219, and 124. Now, run it again. You'll notice that something strange happens; we received the exact same numbers.
They were generated in a pseudorandom manner, right? Maybe it was just a fluke. Let's run it again and see what we get. You will get the same result again. To understand what's happening here, we need to take a look at seeds.