Avatar image for gkhan
Posted by gkhan (1052 posts) -

Hi! My name is gkhan, and I'm a game developer with a background in mathematics, which means that there are few things that I love more in the world than randomness in games. It's a subject that I find endlessly fascinating and that I love reading and thinking about. Throughout the years I've gathered some stories about how games use (and misuse) randomness, and I thought I would share some of them. Most people would find this subject super-boring, but you guys all seem to be as crazily into games as I am, so I figured I'd write a blog post about it. I hope some of you will find this interesting!

To be clear: this article is specifically about randomness in games, so I'm going to leave out a lot of stuff. Randomness in cryptography, for instance, is a huge and complicated subject that wont be covered here.

Random and Pseudo-random

(this section is about how computers technically generate random numbers. Feel free to skip it if you're not interested, and you'll get to the fun parts about the Doom and Pitfall!)

Randomness is a surprisingly tricky subject for computers to handle, because computers are entirely deterministic machines. If you feed a computer program the same input, it will always produce the same output, every time. This is good because it means that you can always rely on your code to do what you want it to do, but when you need random numbers (and you very often do in games), it poses a problem.

How then do you solve it? The basic answer is two-fold: collect some small piece of randomness from "outside" the machine, and use what is known as a Pseudo-Random Number Generator to generate your random numbers. The small piece of randomness from outside the machine (properly known as "entropy") can be anything that the computer can't predict. The easiest thing to use (and by far the most common in non-cryptographic applications) is the current time. The code simply asks the computer what time it is, which is something that will be different every time you run the game. Some gaming machines (like the NES) didn't have internal clocks, so a common trick then is to use user input. You could, for instance, use the value "How many frames of the game had passed before the user pressed the 'start' button?".

That little piece of randomness is then used as a "seed" for your Pseudo-Random Number Generator ("PRNG"). A PRNG is basically just a mathematical formula that takes your seed value and uses it to start pumping out numbers that "look" random. They aren't actually really random, because the formula will always produce the same sequence given the same seed, but the numbers sort-of look random enough. There are some very complicated PRNGs out there, but I thought I'd give a quick example of a really simple (though a very common) PRNG, the Linear Congruential Generator. A random number generator of that type uses a formula that looks like this:

<next number> = (1103515245 * <previous number> + 12345) mod 2^31

("mod" here means that you take the first number, divide it by the second, and then take the remainder of that division).

So, if your seed number is 42, then your next number in the sequence is 1250496027. After that, you get 1116302264, and after that you get 1000676753, and on and on and on. Keep applying that formula and you have your steady stream of pseudo-random numbers.

(this formula, by the way, with those particular numbers, is the formula that glibc, a very common standard C library, which means that that particular formula is probably the most common PRNG in the world)

Why Doom has the worst pseudo-random number generator EVER

So much lost potential!
So much lost potential!

Doom is a technical masterpiece, and should be counted among the greatest achievements in the history of game development. It did, however, have an amazingly bad random random number generator, so bad, in fact, that it even affected gameplay. How did Doom's random number generator work? Well, instead of having a nice formula like the one in the previous section, it just had a list of 256 random numbers. That's it. Literally just a list of numbers. When a new random number was needed, it simply looked at the next value in the list, and used that. When it got to the end, it started from the beginning. If you're curious about what the list of numbers was, it's part of the Doom source code released in 1997 and can be seen here (it starts on line 32).

Now, some might argue "this is good enough, and the player will never know the difference", but the badness of the number generator actually affected gameplay. One of the most notable examples: it nerfs the BFG9000. The BFG heavily uses random numbers to calculate the damage, and it could hypothetically do up to 4280 damage. However, that will never happen in Doom, because there's literally no place on the random number generator table where that amount of damage can be inflicted.

Now, it's true that "max damage" BFG shot would be very unlikely even if it Doom had a proper PRNG, but even so, the fact that the PRNG is so poor means that the "window" of potential damage the BFG can do is much more narrow than the designers intended.

John Carmack, you are a brilliant developer giant among men, but you dropped the ball on this one!

Why No Man's Sky is just a gussied-up version of Pitfall

Another one of the great technical masterpieces in gaming history is Pitfall! for the Atari 2600, and unlike Doom it uses random numbers in an ingenious way.

If you're an expert Pitfall player, you might have noticed that the number of screens in the game is exactly 256 and no two are exactly alike. If you know your games, you might suspect that that number is no coincidence, and you'd be right.

Here, the random number generator decided to be a dick and put in crocodiles instead of the swinging vine
Here, the random number generator decided to be a dick and put in crocodiles instead of the swinging vine

256 is, of course, equal to 2^8, which is the number of possible values that can be stored in a single byte. A byte consists of eight "bits" that are either 0 or 1, and in Pitfall, each screen can be described by 8 bits. For instance, if a certain bit is 1 instead of 0, it might mean that there is water in the level. Another one might mean that there's an enterance to the lower world, or what enemies are on screen. That makes for exactly 256 different possible screens.

Since there are 256 possible screens in Pitfall, and you want to include all of them, the next decision you have to make is what order they come in. The easiest way to do that is to simply store the sequence of 256 screens as 256 numbers (much like how Doom did it, come to think of it), but that wasn't a possibility on the 2600. The reason for that is memory on the carts was extremely limited, and the entire game of Pitfall needed to be stored in just 4 kilobytes. A sequence of 256 one-byte numbers takes 256 bytes to store, which is equal (exactly) to a quarter of a kilobyte, a full 1/16th of the entire space on the cartrige! There was absolutely no way that was going to be possible, so David Crane, the programmer behind Pitfall, had to come up with a better way.

His solution was to basically use a random number generator to generate the sequence of screens. Instead of laying them out manually and storing the sequence on the cartridge, he instead just stored the formula for it. Since every cart had the same formula, it would always generate the same screens in the same order, but the order would look random enough for the world to be interesting. In this way, he was able to lower the amount of space the world map needed from 256 bytes to around 50 bytes, a huge savings.

(note for programming nerds: Pitfall doesn't use a classic random number generator like one of the ones I described above, it technically used a Linear Feedback Shift Register implemented as a polynomial counter. But the idea is more or less the same.)

This is just a prettier version of Pitfall, DON'T BELIEVE THE HYPE!
This is just a prettier version of Pitfall, DON'T BELIEVE THE HYPE!

Interestingly, this concept is incredibly similar to how No Man's Sky supposedly works. No Man's Sky isn't composed of screens, it's composed of planets, but just like each Pitfall screen is defined by an 8-bit number, each No Man's Sky Planet is defined by a 64-bit number, generated by a random number generator. And just like Pitfall had its random world "hard-coded" on the cartridge, No Man's Sky will have it's universe hard-coded on the disc, so that everyone is playing in the same "random" world. From a technical perspective, the concepts behind both games are remarkably similar, even though (of course) there's a massive difference in scale.

Breaking random number generators, for fun and profit

Random number generators can really screw you over when playing, so wouldn't it be nice to have a way to manipulate them so they always give you what you want? Every hit would be a critical, every drop legendary, and every romance attempt successful!

Unfortunately, it is almost impossible for regular humans to do, because it requires a detailed knowledge of the internal memory state of the game, and players don't have that. You know who does, though? Tool-assisted speed-runners, that's who!

A major component of a lot of tool-assisted speedruns is what's known as "luck manipulation", basically breaking the random number generator so that it always does what you want. A great example of this is this tool-assisted speedrun of the NES game Dragon Warrior:

Notice that from around 39 seconds into the video, the player embarks on a journey across the world, but he never runs into random encounters unless he wants to. And when he does, every hit is a critical, and every spell succeeds perfectly.

How does he do that? While I'm not privy to the exact technical details, what I think is going on is this: the game uses a random number generator that cycles (i.e. generates a new number) every frame. That number is used to determine how random events that frame are going to go (i.e. whether or not entering a tile triggers an encounter, or whether or not a hit is a critical). So, what the player does is that he always chooses his actions on frames where the random number generator works in his favor. That is, if combat would be triggered when entering a tile on a certain frame, simply wait a single frame for the random number generator to cycle, and do it the next frame instead.

It's interesting to note that the programmers could have mitigated this technique if they wished by only cycling the random number generator when necessary. That is, don't cycle the PRNG on every frame, only on every frame where the character enters a new tile. That way you couldn't avoid the curse of randomness in this simple way.

You'll miss. Every time. Reloading doesn't help. You're just screwed.
You'll miss. Every time. Reloading doesn't help. You're just screwed.

This might seem extreme (since only TAS-runners can exploit this, why would you care?), but it actually does solve a different way that players can manipulate the PRNG: save-scumming. XCOM: Enemy Unknown does a version of this by saving the state of the PRNG in the save file and only cycling it when a new random number is needed. That means that if you save just before taking an important shot and miss, reloading and trying again will not work. The random number generator will just spit out the same number again. What you have to do is force it to cycle, which in XCOM probably means making a move with a different character first. However, given the nature of XCOM, even that is a limited technique because of how limited the number of possible actions is each turn.

Links to interesting stuff

If you want to read more on this subject, here are some stuff that I like:

This thing became way longer than I expected, if any of you made it down here, I'm really grateful. I was thinking I might write some other stuff about game development concepts in history if you guys like this and are interested. For instance, an obvious part of randomness in games is procedural generation (how does Minecraft generate those nice-looking worlds?) and I was thinking about explaining how you actually do that practically.

If you have any questions about any of this stuff or any comments, I'd be happy to hear them. Cheers!

Avatar image for notnert427
#1 Posted by notnert427 (2158 posts) -

Interesting stuff. Thanks for the write-up, duder!

Avatar image for onarum
#2 Posted by onarum (3212 posts) -

That was a great read man, really interesting stuff, really weird the rather simplistic approach carmack used on doom, I'd think he'd opt for a far more exotic solution, perhaps just because it was cheaper on the processing department, I mean CPUs at the time weren't exactly powerhouses.

And yes I'm hugely interested in procedural generation so yes please!

Avatar image for cmblasko
#3 Posted by cmblasko (2917 posts) -

Great post, thanks!

Avatar image for mithical
#4 Edited by mithical (423 posts) -

More great examples of RNG manipulation in Tool-Assisted Speedrunning are the Shining Force runs by DarkKobold. This run of SF2 has since been improved by the same author but the RNG manipulation is only discussed in the comments there, with details about 7 Lua scripts the author created to manage the RNG.

Avatar image for driadon
#5 Posted by Driadon (3253 posts) -

This is fantastic! I'd love to hear about procedural generation, as I'm very young and inexperienced in the subject, but much like you love the concept of computers generating randomness and using it.

Avatar image for baal_sagoth
#6 Posted by Baal_Sagoth (1602 posts) -

Great, interesting post! And very well written since that was a pretty painless read even for someone that isn't exactly the most glorious mathematician around. Needless to say, I'd really like you to continue to explore similar subjects in future.

The part about Doom's Big Fucking Gun was really new to me even just as a piece of gaming history. Very fascinating stuff.

Avatar image for devil240z
#7 Posted by Devil240Z (5704 posts) -

But I liked pitfall...

Avatar image for gkhan
#8 Posted by gkhan (1052 posts) -

@driadon: @cmblasko: @notnert427:Thanks! I thought it turned out pretty well :)

@onarum said:

That was a great read man, really interesting stuff, really weird the rather simplistic approach carmack used on doom, I'd think he'd opt for a far more exotic solution, perhaps just because it was cheaper on the processing department, I mean CPUs at the time weren't exactly powerhouses.

And yes I'm hugely interested in procedural generation so yes please!

I've thought a bit of why exactly Doom chose to use this approach, and I don't think CPU limitations is the reason. Good PRNG's (or at least "good enough" PRNG's) can be implemented that use very little processing power. The example I provided, the Linear Congruential Generator, is an example of that: in order to generate a new number you only have to do two arithmetic operations: one addition and one multiplication (the "mod" operation can be implemented using something called bit-masking if the modulus is an even power of two, which is the reason 2^31 was chosen in this case. Bit masking is much faster than arithmetic). Two arithmetic operations is nothing for a computer, even a computer in the 90's. The computational cost is totally trivial. It's true that Doom's version is a tiny bit faster, but it's only faster by two or three CPU cycles. Given that you don't necessarily need to calculate very many random numbers inside a single frame, the computational cost makes no difference what-so-ever.

Another way to put it is this: if David Crane could implement a decent random number generator for a machine made in 1977 (the Atari 2600), the Doom guys could easily have done the same thing on a machine made in the 90's.

No, I think the reason is simply that programmers back then had much less general awareness of what "good" random number generation looks like and why it's a good idea to use a good PRNG. The Doom dudes are brilliant programmers, but they weren't number theorists. They used the first solution that came to mind and since it more or less works, they didn't worry about it after that. I would bet money that none of them even realized that their random number generator affected the damage output of the BFG, because it is a very subtle effect.

But I liked pitfall...

Pitfall Harry is made up of 4 colors. FOUR COLORS!
Pitfall Harry is made up of 4 colors. FOUR COLORS!

Pitfall is amazing :) It's also a minor miracle of programming that it even runs on a 2600, that device is insanely underpowered for a game like that. The developers had to break the machine in all sorts of ways to even get it to run. For instance: the 2600 only had support for single-colored sprites, but look at Pitfall Harry. He's a multicolored sprite. How did they do that?

Well, basically: magic. A CRT monitor draws the screen line by line from left to right with a cathode beam, which means that when the beam reaches the right edge, it has to travel back to the left side of the screen. During that time, you can squeeze in a few extra instructions, so what Pitfall does is that it changes the palette of the sprite while the beam is traveling to the left side of the screen. That's why every line of the Harry sprite is the same color. I cannot put in to words how clever that is, it's absolutely brilliant.

Getting Pitfall to run on a 2600 is sort-of like getting Crysis to run on a PS2. It's just insane that it was even possible.

Avatar image for devil240z
#9 Posted by Devil240Z (5704 posts) -

@gkhan: And I guess I'm saying, I think I will like NMS too. nothing about that game is new or whatever. Its like many other space games but with all the procedural stuff it has on top of that. Those other games were just empty planets with space ships near them. NMS is that with something extra. Its doing things that have never been done before regardless of if people will call it repetitive or bland or variations of the same thing slightly changed by random variables.

Maybe I"m one of the few people with realistic expectations for no mans sky.

Avatar image for frybird
#10 Edited by Frybird (253 posts) -

Cool Read, especially since i always failed to put the pieces together on how the scale of random-yet-persistent planets on NMS is gonna work.

I'd like to add (even if most may know already) that 256 (or 255) Levels is incredibly common in Games of the 80ies because of the reason stated above, although many (arcade) games did not really plan to have players getting through 255 Levels and just programmed the game to continue "endlessly", which results in games like Pacman, (EDIT: originally counted Donkey Kong, but thats not a 256 case, should actually read what i link) Galaga or Dig Dug just breaking themselves in what is mostly and famously referred to as "Kill Screens"

Avatar image for tobbrobb
#11 Posted by TobbRobb (6576 posts) -

Interesting blog! I love stuff like this. The underlying workings of video games are super interesting, and randomness is absolutely not an exception.

Online
Avatar image for flashflood_29
#12 Edited by FlashFlood_29 (4401 posts) -

That was a fun read! Thank you! A lot of great information there.

Avatar image for amyggen
#13 Edited by AMyggen (7738 posts) -

Fantastic blog post, really interesting stuff.

Avatar image for knifeyspoony
#14 Posted by KnifeySpoony (1252 posts) -

Thanks for the great write up. Really interesting info and it made No Many's Sky make more sense. Hope to see more posts like this.

Avatar image for caska
#15 Posted by caska (263 posts) -

This was really cool to read, thanks! I'd love to read more of this type of stuff!

It's always great to see how games are made and you've explained a small facet of this process perfectly.

Avatar image for excitable_misunderstood_genius
#16 Posted by Excitable_Misunderstood_Genius (346 posts) -

Good writeup, it's still pretty surprising how many people don't have a solid grasp on the distinction between random and pseudorandom even when they are constantly using systems that have to rely on pseudorandom number generation.

Avatar image for anjinm
#17 Posted by AnjinM (151 posts) -

This blog post was a real treat. I look forward to whatever else you might want to share in the future!

Avatar image for charlie_victor_bravo
#18 Posted by charlie_victor_bravo (1712 posts) -

Interesting read. There are options for true random (enough in practice and in most theory) numbers but require special hardware. Imagine if an RPG would have hardware requirement of TRNG-card.

I remember that Golden Sun had PRNG that relied on player movement on the over world map. There was an enemy that one dropped real nice gear extremely rarely (in practice never) or 100% of the time if you did certain movement pattern before entering the area.

Avatar image for junkboy
#19 Posted by Junkboy (652 posts) -

Fascinating read, thanks a bunch!

Avatar image for effache
#20 Posted by effache (343 posts) -

This was a more interesting read than pretty much anything I ever come across on the internet. Please, do more!

Avatar image for effache
#21 Posted by effache (343 posts) -

@gkhan said:

Pitfall Harry is made up of 4 colors. FOUR COLORS!
Pitfall Harry is made up of 4 colors. FOUR COLORS!

Pitfall is amazing :) It's also a minor miracle of programming that it even runs on a 2600, that device is insanely underpowered for a game like that. The developers had to break the machine in all sorts of ways to even get it to run. For instance: the 2600 only had support for single-colored sprites, but look at Pitfall Harry. He's a multicolored sprite. How did they do that?

Well, basically: magic. A CRT monitor draws the screen line by line from left to right with a cathode beam, which means that when the beam reaches the right edge, it has to travel back to the left side of the screen. During that time, you can squeeze in a few extra instructions, so what Pitfall does is that it changes the palette of the sprite while the beam is traveling to the left side of the screen. That's why every line of the Harry sprite is the same color. I cannot put in to words how clever that is, it's absolutely brilliant.

Getting Pitfall to run on a 2600 is sort-of like getting Crysis to run on a PS2. It's just insane that it was even possible.

Sorry for the double post, but this is just so incredibly insane and interesting. Where do you find pieces of technological minutia and game dev history like this? Is it mostly just developer talks/retrospectives like the pitfall one? This is the kind of thing I would love to dive deep into.

Avatar image for tothenines
#22 Posted by ToTheNines (1672 posts) -

My dumb head hurts a little, but you should definitely do more posts like this, interesting stuff.

Avatar image for honkalot
#23 Posted by Honkalot (1039 posts) -

Great post, really really interesting!

Avatar image for immortal_guy
#24 Posted by Immortal_Guy (203 posts) -

@gkhan: Are you aware of the methods players used to game the random number generator in Final Fantasy XII? The equipment you recieved when you opened a chest in that game was random, and to get some of the best items you had had like a 0.1% chance. However (if I understand this right) the game used a random number generator with a pre-determined seed, so the sequence of numbers you'd obtain was the same every time you turned the PS2 on - and it took one number from this sequence every time it needed a random number in the game. So, you could apparently garuntee rare treasure by loading a game, running to the chest without doing anything to generate a random number, and then making your character attack themselves over and over - an action that just required one random number, to determine the length of the "combo" you got. A telltale 5-hit-combo around 80 tries in would tell you you were at the position in the sequence where the next number would garuntee a rare item. I don't know whether that's a quirk of the PS2's PRNG or just the implementation in Final Fantasy XII, but given that they had a proper PRNG at their disposal it seems crazy that they didn't just use the system time as a seed or something.

Avatar image for mikemcn
#25 Posted by Mikemcn (8569 posts) -

Rad post!! I love the idea that we can't ever generate truly random values. There's something profound in the idea that any number you come up with always has a process which created it.

Avatar image for shindig
#26 Posted by Shindig (4875 posts) -

Just put your iPod on shuffle and watch the generator pick the same favourites.

Avatar image for liquiddragon
#27 Posted by liquiddragon (3289 posts) -

Cool man, thanks for writing!!

Avatar image for carlos1408
#28 Posted by Carlos1408 (1635 posts) -

Absolutely fascinating. Thanks for write up! :D

Avatar image for gkhan
#29 Posted by gkhan (1052 posts) -

@gkhan: Are you aware of the methods players used to game the random number generator in Final Fantasy XII? The equipment you recieved when you opened a chest in that game was random, and to get some of the best items you had had like a 0.1% chance. However (if I understand this right) the game used a random number generator with a pre-determined seed, so the sequence of numbers you'd obtain was the same every time you turned the PS2 on - and it took one number from this sequence every time it needed a random number in the game. So, you could apparently garuntee rare treasure by loading a game, running to the chest without doing anything to generate a random number, and then making your character attack themselves over and over - an action that just required one random number, to determine the length of the "combo" you got. A telltale 5-hit-combo around 80 tries in would tell you you were at the position in the sequence where the next number would garuntee a rare item. I don't know whether that's a quirk of the PS2's PRNG or just the implementation in Final Fantasy XII, but given that they had a proper PRNG at their disposal it seems crazy that they didn't just use the system time as a seed or something.

That's awesome, I wish I knew it before so I could've included it in the post :)

Reasons like this is why many developers use the current time (or any other source of outside entropy) as your seed instead of hard-coding it, so players can't make these kinds of exploits. It also shows why high quality random number generators are a good idea. Most developers (like the developers in Doom) think "I don't really need that high quality randomness, I just need something that's sort-of random, players will never notice the difference!". That attitude is mostly right, but it also leads to things you (as a developer) could never predict, like nerfed BFGs and weird looting techniques.

One clarification: saying "the PRNG in the PS2" is a bit wrong. PRNG's are software, generally speaking the games come with them themselves, it's not something that's built in to the console. You can run the same PRNG on a GameBoy, a PC and a PS4, it's just an algorithm that generates numbers (there are things called "hardware RNG's" that generate much higher quality random numbers for cryptographic purposes, but those aren't necessary for games). So it's not "the PS4's PRNG", it's "Final Fantasy XII's PRNG".

(all that said, operating systems often provide random number generators if programmers want to use them, but generally speaking PRNG's are part of the code of the game itself, not the operating system or the hardware. If you're on a Mac or Linux box, you can try this out for yourself by opening a terminal and typing "cat /dev/random | xxd -p", and see staggering amounts randomness before your eyes. Press Ctrl-C to abort)

Avatar image for deinile
#30 Posted by DeiNile (125 posts) -

This is such an awesome post. Please keep 'em coming!

Avatar image for sailfact
#31 Posted by Sailfact (10 posts) -

Great read, very interesting.

Avatar image for gee_rad
#32 Posted by Gee_rad (199 posts) -

@effache:A good place to start (for the Atari specifically) is the book Racing the Beam.

@gkhan: Luck manipulation can be a big factor in non–tool-assisted speedruns too! There was a great speedrun of Earthbound in a recent AGDQ/SGDQ. Basically, Earthbound generates a random number every time you do something in a menu (to pick a random sound), so by moving the cursor x times, you can get to a good random number that makes your characters get critical hits and the enemies miss. (I assume the route was determined using tools, but still, humans are able to memorize enough of it to get through the whole game.)

Legend of Zelda runners also manipulate the item drops. A normal pseudo-random generator determines whether an enemy drops an item, but IF it drops an item, the item it drops is determined by the number of enemies you've killed mod 10 and the type of enemy. (There are also guaranteed drops if you kill a certain number of enemies without getting hit.)

Bubble Bobble item drops might seem to be random at first, but all of them are determined by counters for things like the number of bubbles you blow or the distance you move.

Tetris also does something interesting. It essentially puts n of each tetromino into a bag and pulls one at pseudo-random until the bag is empty. (Or, equivalently, gives you a pseudo-random permutation of n copies of each tetromino.) This guarantees you don't get an extreme case of randomness where you, say, never get an I or get far more Zs than any other piece.

Also, there's a cool website that explains the procedural generation algorithm in Spelunky with interactive examples (it uses a version of spelunky ported to browsers, modded to only do the level generation): http://tinysubversions.com/spelunkyGen/

Avatar image for gkhan
#33 Edited by gkhan (1052 posts) -

@gee_rad: That's really cool. I'm not deep enough into the speedrunning community to know about those specific tricks, but I really dig that human players have learned how to do this as well.

The Tetris thing is interesting because it enables an algorithm that means that you could theoretically play forever, something which is not possible with the more basic algorithm of just spitting out random pieces. As someone who has played an unnecessary amount of Tetris in my life, I love the Random Generator. Even if you don't explicitly keep track of the bags, it allows you to "plan ahead" much better, and know on an instinctual level what kinds of pieces are "due". It really improves the game.