If you’re an indie games advocate you’ve probably noticed a lot of games promote themselves as “Randomly Generated Levels” or “Procedurally generated world” but what does this mean? It seems a little entitled from us developers to expect from our community to know what these terms represent within a game, especially when they’ve probably never encountered them before.
Even in our own game, Void 21, we use procedurally generated levels. So what? And why do indie devs use this technique so much? In this article I’ll attempt to answer both of these questions and hopefully shed some light on the matter, and enable you all to make better informed purchasing decisions as well as understand what us devs are so presumptuously talking about.
What is Random Generation?
To start let’s define what Randomness is within the programming world. Randomness is the ability to obtain numbers without any seemingly predetermined pattern to how these numbers are created. So for example if I ask of the code to give me a number between 1 and 10000 at random, it should only very rarely give me the same number twice, usually giving me something like 3543, 3213, 6875, 42, 13, 1237, etc.
Now a Randomly generated level is when we make use of this ability to create numbers and apply it into how the game level is created. Here’s an example using Void 21:
Say, I want to create a new level, how long should the road be? Well I ask my friend the Random code and say “Dude, I need a level between 3000m and 7000m long, how long should it be?” And the code says 5463m, and so now my level length is 5463m.
Then I say “Dude, I want to place down some pylons, how many pylons should I place?” And the code tells me “You should place 324 pylons and they should be at positions 345, 12; 543, 19; 654, 2;”etc.
Et Voila, I’ve created a very basic level for my players without having to do much of any planning or “design”. Yey! But what if I want to create the same identical level twice? The next time I’m going to ask the Random generator to give me a number, it will most probably not give me the same values so what do I do? Welcome to procedural generation!
What is Procedural Generation?
Procedural generation is the idea that if I input a specific code into my number generator, when I ask it for a value at a specific point it will always give me the same exact result. This is useful to create the same level every time while still not having to design each individual level by hand.
Here’s an example to better understand how developers may make use of procedural generation, and this will also explain how games like The Binding of Isaac: Rebirth/Afterberth manage to make the same level for every seed.
Say I start from an 8 character “seed”. A seed can be any combination of numbers and letters; for example “78GH21J9”. Using this seed I can then start breaking it down to determine certain rules about how I’m going to create the level. Let’s use the previous idea and say we want to create a Void 21 level.
One way we can achieve this is to determine different roles for each position within the seed above. Say for example I want the first character to represent the length of my level, something between 3000m and 7000m long. The character can either be 0-9 or a-z so i establish a rule saying that 0-9 actually represent their numeric values and a-z represent numbers 10-35, thus now having a complete range of 0-35 from the first character.
I know the minimum length I want is 3000 meters, so I keep that in mind. I then determine what’s the maximum I want on top of that which is 7000m-3000m = 4000m. I then go and divide that value between the count of all the possible numbers I can get from the first position of the seed, so that’s 4000 / 35 and I get 114.28571, but rounding it to 114 is more elegant.
So now the mathematical formula to determine the road lengths is 3000m + [seedNumber] * 114m. In our example it would be 3000m + 7*114m = 3798m. If we were to use the maximum possible value in the seed it would be 3000m + 35*114m = 6990, which is very close to our target of 7000m.
All you do now is extrapolate this concept to every other part of your game et voila, the same exact level is obtained for the same seed, but now you have quite an insane amount of possible levels. In my case it’s 36^8 levels, which will hopefully keep the users busy.
So armed with the knowledge of what these two techniques are, why are they used so much by indie devs? The Binding of Isaac, Spelunky, Downwell, Race the Sun, and even No Man’s Sky, Elite: Dangerous and the original 1984 Elite use these but howcome? Well the answer is quite shockingly simple: Because it’s cheap and effective.
Here is what your average indie dev team looks like:
Zeenoh Games: Indie team in the Philippines
And here is what your average AAA title team looks like.
Assassin’s Creed Unity Dev Team
When your team includes 10s of 3D modelers and level designers whose sole purpose is to make sure that every rock, leaf and godray is in its place, you’re singing a different tune. Then you can justify manually crafting play areas and ensuring that the user experience is the best it can be for every second of gameplay, but the small developers can’t do that due to time and monetary restrictions, thus they employ the godly powers of math to do some of the work for them.
Wait but if these techniques are so efficient why doesn’t everyone use them? Well….
Unlike humans, Math doesn’t give two rats tails if your level is playable or not, if it looks good or not, if you’re even able to complete it or not. Math is like a lazy developer with no passion in their work: It will do its job exactly as requested but not an inch more. As you can imagine this can cause problems, in some genres more than others.
If Mario for example would have its levels randomly or procedurally generated, it might end up looking something like this:
Source: Palette swap http://paletteswap.net/wiiu_screenshot_tv_01repm3/
These techniques require a lot of testing and tweaking to make sure that what they create is still playable by the user. Even then some levels will slip through the QA filter and will frustrate your user base to incredible degrees so one has to tread carefully when dabbling in these waters. Most AAA companies see procedural generation as such a big risk they don’t even bother with it most times due to the potential negative press it can land them, but indies have no choice.
While Randomness and Procedural are awesome tools, they also don’t work very well for specific types of games, platformers being the best example here. Imagine if Super Meat Boy would apply generated levels? They wouldn’t be anywhere near as fun, precise, satisfying or rewarding.
You also have to come to terms with the fact that no matter how much QA you do, how well your rules are written and your code is implemented, mistakes will slip through. It is impossible to test 36^8 levels, that’s 2,821,109,907,456. If every person would spend 5 minutes to test a whole level, and we have the whole 7 billion world population at our disposal, It would take each person 33 hours to complete their bit of testing. Thus you have to accept the fact that issues will arise and implement solutions in your code to mitigate them. Quick updates and hotfixes are key here!
And one more issue but this one relates specifically to procedural generation. If you update your game at a later time to include more content, you are going to destroy all the seeds that people have played before the update. This is what happened when The Binding of Isaac went from Rebirth to Afterbirth. They introduced a lot of new items, level types, designs and even some bosses, thus the math of picking which items and floors to display for which seeds got changed, making all the previous seeds that people were sharing completely useless.
So there you have it, hopefully now you have a much better understanding as to why these techniques have engulfed the Indie scene and will also allow you to make better purchasing choices in the future.
And finally, a selfish act of self-promotion: Help us get it through Steam GreenLight if you’d like to give Void21 a shot :)