Map generation in Escape from Aeon

Intro

Hey! I'm Rauno, the technical half of our global team working on Escape from Aeon (EFA). I've been thinking about writing a proper devlog post for a long time now and this topic seems like a good one to start on.

Map generation is an endless rabbit hole — and a popular one to jump into, as proven by the roguelike/lite boom in recent years.

It's also one of the core elements of any game of this genre and the first thing that's listed in the Berlin Interpretation list!

While it can be a big time sink, it can also be a whole lot of fun and very satisfactory when you get some cool and/or unexpected results from it.

The map generation approach in EFA combines a few of the usual styles, so most floors contain:

some rectangular rooms (with set ranges for width/height) and a few prefab rooms

that are connected by corridors (with set ranges for length and how many times they are allowed to "snake" to form a connection to a room)

various environmental details that are added as the last step

Some floors have specific requirements - like the special starting room on the first floor and the Primacore on the last floor.

The breakdown

In most cases, the generation flow in EFA works like this:

Create an empty two-dimensional array for the floor (100x100 tiles in our case) Place the first Room in a random position, weighted towards the center of the grid From that Room, branch out with a Corridor in any direction If we hit our "snaking" chance, branch out from that last Corridor perpendicularly repeat X times Add another Room at the end of the last Corridor added GOTO 3. until we hit our desired amount of Rooms Optional steps that are dependent on settings for more randomised connections between Rooms, repeat step 3 with a random Room as our source clean up Corridors that aren't connected at both ends to a Room or a Corridor (so basically any dead ends) create direct connections between Rooms by adding a Corridor between two rooms, where the two Rooms are within a certain distance the number of already existing connections between the two Rooms are under our set limit the two Rooms *can* be directly connected, i.e. they are on the same axis. Sidenote: the plan is to add the "snaking" connection part to this as well, so we could also make connections between Rooms using multiple Corridors add Doors at the end of (some) Corridors Pick a position for the Player to spawn - just take a random tile within a random Room - and place an Entrance tile there Pick a position for the Exit - just take a random tile within a random Room that is of a certain distance from the Entrance - we don't want the trip to be too short nor too long and is not in a prefab Room, expect in some special cases Generate a list of Rooms that are valid for spawning in exclude the Room that the Player spawns in exclude some specific Prefab Rooms Use those Rooms to place environmental details (Cover, vending machines, radiation and more) Validate that the floor is actually traversable by running a pathfinding algorithm from Entrance to Exit optionally, make sure that the path is not too short nor too long And as the final step - spawn some Monsters! (by taking the Rooms from step #12 and picking positions from within them)

Of course, some details - like validating that Corridors/Rooms don't overlap when placing them - have been omitted from this list.

Also, everything is seeded so that maps can be easily reproduced, which is useful for saving/loading, debugging and potentially even seeded runs. Since we're using C# (and Unity), our seed is just an int used for initialising an instance of System.Random.

For fun - and debugging, but mostly fun :) - we're also saving the resulting maps and the step taken to get to them into .png files.

Settings and Tools

For ease of modification, a bunch of the parameters are stuffed into .json files, one per each set of floors.

But finally, just a few weeks ago - after nearly two years of development - I decided that the loop of "edit .json file & re-run game" was too much hassle and threw together a test scene inside Unity that would expose those parameters for easier modification.

I'm very glad I decided to do that - it was one of those all-too-rare times I really got into a "flow state" and ended up productively coding for about 4 hours in a row, resulting in the basis of the tool implemented in one go :)

This also led to a lot of clean-up in the previously existing map generation code, new features for it, a new pathfinding algorithm being taken into use and a lot more parameters being extracted from the code into the .json file.

All in all, a very successful undertaking.

Conclusion

Let me know whether you enjoyed reading this (or not!) and if there's any specific topic you'd like to see me writing about more in relation to EFA. I'm thinking that all these Editor extensions are a good potential next topic, since I haven't happened upon that much information related to that topic, at least when comparing with other areas.

And also - check out our freshly updated demo build of EFA, quite a lot of new stuff added and older stuff improved in the last 4 months :)

Pictures

A sample map —





Steps taken to get the map above —





