I wanted to create a random level generation system for Fool's End Daily Challenges. This mode randomly generates one level per day for all users to play and compete in a high score chase.
Design challenges for this project included:
-providing lots of variation between levels day-to-day.
-making sure that the daily level is generated the same for all users.
-creating a way to score points, and sharing those scores via Steam Leaderboards.
-providing lots of variation between levels day-to-day.
-making sure that the daily level is generated the same for all users.
-creating a way to score points, and sharing those scores via Steam Leaderboards.
PROCESS
I used the Spelunky method, which involves dividing the game level into smaller rectangles, called rooms. Each room is then filled with what appears to be random contents, but is actually selected (mostly randomly) from a manually curated list of room types, all with predetermined contents laid out.

The level is divided into 16 rooms, distributed 4x4.
GENERATING CONTENT FOR EACH ROOM
Each room is made up of 16x16px tiles, laid out 8 rows by 10 columns. Each tile's individual contents are predefined by a 1-digit/letter string, so that when the script for building rooms runs it designates the string as a tile. For instance, I use 0 to designate an empty tile, 1 for a dirt tile, 2 for rock.
The individual tile types also present an opportunity for randomness too. Eg. "3" gives a 50% chance of rock 50% chance of empty. The "6" creates a chunk, which is a 5x3 set of tiles (determined in another script) designed to add some variation and chaos to generation.
After deciding what each room archetype consists of, I created the system to dictate the rooms that each level would be created from.


CREATING THE ROOMS
Similar to the system for constructing tiles within a room, each room is represented with an integer. 0 is a stock standard room with no threats to the player. 1,2,3,4,5,6,7 are rooms with varying levels of threat to the player, whether it be lava, bombs, chaotic chunks or gargoyle laden rooms. Room 8 are entrance type rooms, designed to spawn and drop the player into a space without any imminent threat. Similarly, 9 represents exit rooms, templates with an exit door and ideally a tense climactic escape scenario. The room RoomGen script makes sure that there is a room 8 and 9 present in each level, and then shuffles the remaining options to create the rest of the level.
In the Spelunky level design method there is normally a desired path created through another room type that has a guaranteed throughway. Instead, because all tiles are breakable to the player, the player can create their own desired path.
MAINTAINinG CONSISTENCY FOR EACH PLAYER
I needed a way for randomised parts of the level to stay consistent for every player. Unlike the level generation process, I didn't have any obvious method to follow.
By default in Gamemaker the game's seed is randomly determined at launch of the game. Therefore the seed would be different each time each player boots up the game, making each player's Daily Challenge completely different. The only variable that I knew would be the same for each player every day would be the date.
So I set global.seed = ((day*137) + (month*137) + year);
Why do I multiply the d/m/y by 137? Sometimes the total result of d+m+y could equal the same result. For instance, the 8 March 2024 would be 8+3+2024= 2035. 7 April would be 7+4+2024 = 2035. Within one month I would be generating an identical level. By multiplying the sum by 137 I can space out these recurring numbers and create more variation. In this method, 8 March 2024 would be 1096 + 411 + 2024 = 3542. 7 April would be 959+548+2024 = 3531. The seeds stay different for longer. I could multiply the day and month by more but this provides sufficient variation without making the seed string overly lengthy.
This seed is then saved to the local files. If the player has played the Daily Challenge on that seed before, then their score will only update to Steam if they have surpassed the previous high score.
This seed also sets the level's biome to be CAVES, JUNGLE or OSSUARY.
This seed only pertains to the Daily Challenge levels, the rest of the game's randomised elements (decor variation, SFX modulation etc.) run off a different seed.