• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Windows Level/dungeon generation, suggestions?

Fredrik

Member
Hey.
I'm working on a randomally generating dungeon game where the levels generate room by room in a gridform and that the randomness for each level is specified with a given seed with random_set_seed(seed);
In the end of each level (or floor) there's a door taking you to the next level, by pressing the door the current generated level will be wiped and the game will generate a new level, as the entire game (as for now) is all happening in one room. The only thing really prechecking what floor you're on when you start the game is a variable; global.currentfloor, which is saved in a ini file (togheter with the seed), and this creates the problem I need some help with, since the only thing deciding what floor you're on is the global.currentfloor the level will always be generated the same based on the seed. So if you start a new game and the level is generated based on the random given seed and you then go down to the second floor so the game saves that you're on the second floor and then exit the game and open it again, the dungeon will still generate from the beginning as it was the first floor thus making the second floor not be the same generated level as the second floor was before you quit the game.

My problem is that I'm not sure how to fix this. I could perhaps try to make the game set and save a new seed before generating, making it so each floor has it's own seed, but I'm not sure. Any suggestions?
 

TsukaYuriko

☄️
Forum Staff
Moderator
Whenever you generate a random number, the PRNG will be advanced - this secondary factor is sometimes called a step, frame or other things, but the concept is similar to lottery balls. Each of them holds a number, and to generate a number, one of them is drawn pseudo-randomly - pseudo because using the same seed will result in the same number sequence every time. Or in other words, the lottery is rigged and it is perfectly possible to predict its results. :p

The main part that's tripping you up here is that setting a seed also resets the PRNG frame. To illustrate:
You set the seed and generate three random numbers. The numbers are 1, 2, 3.
You set the seed again (the same seed as before) and generate two random numbers. The numbers are 1, 2. (If you generated an additional number, it would be 3.)
You set the seed again and generate one random number. The number is 1. (If you generated additional numbers, they would be 2, 3.)
See what I'm getting at?

Given this, you have three options from what I can tell. "making it so each floor has its own seed", like you said, is the key here - all three of these work based on the assumption that you first retrieve a random number, then set it as the seed and proceed to perform level generation using that new seed.

Number one is keeping track of which frame of a particular seed you're intending to get a random number from (basically, this is already indicated by the level number). Then you can set the seed, advance the frame up to that point and generate the number you're looking for. You'd have to do this every time you want to retrieve a new seed to generate a level with, because GM:S' built-in PRNG operates on a single channel. This means that calling any other functions that generate random numbers using the built-in PRNG (and thus advancing the frame) will manipulate your level generation, and the result of this would, if you weren't taking care of it, be that sharing a seed with other players will result in them getting to play the same first stage... but all further stages will likely be different (as I'm almost certain that you're using randomness in many other places - which game doesn't?).

Number two is using multiple PRNG channels. This approach resolves the problem regarding usage of the PRNG between generation of levels by allowing you to essentially use multiple PRNGs at once, each with their own seed and frame. Advancing the frame of one does not advance the frame of the others, so you can generate as many random numbers between level generation as you want as long as you don't use the PRNG channel that is reserved for the generation of level seeds. This also means that you'd have to use yet another channel for actually generating levels (using the seed you obtained from the level seed generation channel). You'd still have to advance the frame of the level generation PRNG channel up to the current level's frame when resuming a game saved later than stage 1, though. An extension that facilitates this channeled approach happens to exist: http://gmc.yoyogames.com/index.php?showtopic=635690

Number three, which is only viable if there is a fixed amount of levels per playthrough, is simply pre-generating all seeds for level generation and saving them in your save file. That way, you can just read them back in depending on which level you're trying to generate, and they'll always come out the same way.
 

Fredrik

Member
Thanks for the answer! I took a break after getting stuck with this, but I'll look more into it now :)
 

Fredrik

Member
Just in tought if the last suggestion, preseting all the seeds for each floor (as I've had some problems with the other suggestions in the past and wanna try this one) To do this I'd have to set a variable for each seed, setting them to be random with the random(x); then saving them all and make a list checking "if floor is 1 = {seed = saved_seed_1}" and so on. So is there a way to.. let's say write something like if floor = 1 {seed = saved_seed[1]}, so instead of having a varaible for each level "saved_seed_1", "saved_seed_2" and so on, just having saved_seed[1] / saved_seed_[2] ?
 

TsukaYuriko

☄️
Forum Staff
Moderator
The pseudo-code you posted literally already follows the syntax for using arrays in GML. There is no need for maps.
 
Top