[email protected]
Level Design Portfolio
  • HIGHLIGHTS:
    • Camera
    • Collaborations
  • The Long Dark
  • World Design

Telling stories through captivating gameplay.

Warning, this is a construction zone!

Flip through the tabs above to view Open Worlds and other Level Design works I've been crafting since 2014.

Or click the red button
to review my professional work as a Game Design generalist.

Fast Travel to Game Design

How to get random variation using the same seed

28/4/2014

4 Comments

 
You are testing your 2D platformer script that randomly generates a set of platforms based on a song that the player chose. For testing purposes, you use the same song over and over again. But you start to realize that if a player dies in the middle of their song, they will be given the exact same set of platforms if they start again before the song ends. This violates your design because you do not want the player to be able to memorize the pattern of platforms, but you cannot change the seed either. It would make sense in most cases to load a new seed after the player dies, but the background is a visualization of the song that is partially based on the seed number... and your programmer spent weeks coding it to work just right.
Picture
This is Tactical Measure and is not my work. FInd out about what it actually is by clicking here.
Here is an easy solution for anyone who runs into this rare problem, which could have many manifestations other than the example described above. Other solutions include altering the code that selects seeds for your random number generator or using multiple seeds to remove the conditions that require you to keep the same seed. Scripters who do not have access to this code or need a quick fix while they wait for someone else to take a look at it can take advantage of the following method.

1. Use an update loop that will call your GetRandom() function a random* number of times before the first time you need it
2. Try to introduce multiple layers of randomness (i.e. a random distance at a random angle from a random point)**
3. Call GetRandom() a random number of times in between uses and only choose one random solution at a time 
    (and only choose it right before it is needed) instead of determining all of them at the same time using iteration


*the amount of times this function is called cannot be dependant on the seed but could use the current time as input to make a regular or irregular update interval or be procedurally generated by taking the timing of specific player actions as input
**If multiple layers are impossible because you are selecting from three objects that must be ordered randomly for a total of three events, try to introduce a fourth or fifth random object to provide more variation. These new objects can be functionally the same as the already existing objects but should at least be visually different - bigger or smaller and/or a different colour.

l33t section (tl;dr):
WHY? Why would anyone put themselves in this situation in the first place? It could have been accidental, or in some cases it could be desired to maintain the seed in between different play sessions. Procedurally generated levels, as seen in Minecraft, rely on using the same seed during level loading to get the same level composition. The level always reads a set number of characters at the beginning of the seed, but that means all future GetRandom() calls start at the same place each time the level is done loading. As mentioned above, there are better solutions but not everyone is able to implement them.

n00b section (full explanation):
WHAT IS A SEED? It is a pseudorandom string of numbers that are used to generate behaviour that appears random. Having the same seed means having the exact same set of numbers, which leads to the same results even if the designer expects them to be random. Here is an example that explains why the above method works:

THE PROBLEM
Flipping coin simulator with original seed:
010001101001111 = heads, tails, heads, heads, heads, tails, tails, heads, tails, tails, heads, heads, heads, heads

Flipping coin simulation with a new seed:
101010001101001 = tails, heads, tails, heads, tails, heads, heads, heads, tails, tails, heads, tails, heads, heads, tails

Flipping coin simulator which loads the original seed again:
010001101001111 = heads, tails, heads, heads, heads, tails, tails, heads, tails, tails, heads, heads, heads, heads
…now we have a pattern that does not seem random at all. If the player wrote down the order of results from the original seed then they could use that to predict the next "random" coin flip which would definitely make the game feel less random!

THE SOLUTION
We solve this problem by calling our GetRandom() function a random number of times and not printing a result 
The results that are printed now appear random, even with the same seed:

Flipping coin simulator with original seed:
010001101001111 = heads, heads, tails, tails

Flipping coin simulator which loads the original seed again:
010001101001111 = heads, tails, tails, tails


Notice that you are now using a lot more of your seed if you want the same number of printed results. That's OK, seeds are very long and you can pretend that they are of infinite length.

Some people might call this solution "hacky" and it is. I adapted it from a happy coincidence that seemed to be violating my expectations, given that I was quite sure the same seed was being loaded each time I replayed the same level again.        
So, while it is "hacky," it is "happy" too. And if it makes you happy and doesn't ruin anyone else's code then just do it.  
4 Comments

    James Dodge

    Level Designer

    View my profile on LinkedIn

    Categories

    All
    CameraAnalysis
    CameraDevelopment
    GlobalGameJam
    Photoshop
    TombRaider


    Archives

    October 2021
    December 2017
    November 2017
    October 2017
    September 2017
    August 2017
    July 2017
    June 2017
    May 2017
    April 2017
    March 2017
    February 2017
    January 2017
    December 2016
    October 2016
    September 2016
    June 2016
    May 2016
    March 2016
    February 2016
    August 2015
    July 2015
    March 2015
    February 2015
    December 2014
    September 2014
    August 2014
    July 2014
    April 2014
    January 2014
    December 2013
    November 2013
    October 2013
    August 2013


    RSS Feed

Site powered by Weebly. Managed by Bluehost