Url-RL: all new map generation

Hello dear readers!
As you might have guessed from the screenshots in the first post, the generated maps weren’t really satisfying. Also I wanted to avoid maps looking too similar, even if different on a detail level.
So I tried to tackle both of these problems when redoing my mapgen, and this is the concept I came up with:
Being inspired from 2D-graphical software like Photoshop or GIMP, I thought about having layers. And masks.
So I first create a master mask, that doesn’t hold any tile information, just index numbers to divide the map into several areas.
As second step, there are different “styles”, basically different map generation algorithms.
Finally, I assign a random style to each area and fill the content generated by each chosen style into the main-map, bounded by the maskindex.
The way to get variety in different maps is to have (preferably much) more styles than areas. So at one generation, you go with caves, water and a city, in the next run you have desert and swamp, for example.
Now let’s look at some details of the process:

Areas – generation of the mask

As first approach, I just filled a bunch of axis-aligned rectangles into the map, each with a random mask-index. Problem: When one of the last rectangles happens to be very big, it will erase all the previous content and thus making a quite boring map.

I improved that by using modulo, when filling in the mask-index. I added the former index on a given tile to the index the rectangle wanted to place there. Modulo took care of keeping the sum of both indices in range of the maximum number of styles used (so far I mostly used 2-3 different areas).
The result is a nice mix of areas with sometimes larger structures, sometimes smaller or oblong ones.
This approach might fit to artificial structures like cities or industry complexes, but my map-filling styles are mostly of organic nature, and the straight orthogonal borders between them looked out of place.
First I tried some kind of smoothing, but I couldn’t get it do to more than rounding the edges a little – not enough, the long axis-aligned borders still persisted. In all the screenshots of masks you see here, the smoothing is already in action.Then I remembered that the grid class I use (part of a “basic data-structures” library), has a quite arcane feature of iterating over circular areas inside the grid.
Guess what – exactly what I needed!
So I mixed circular shapes and rectangular shapes, and things felt like being on a good way. To keep the further story short, I used the also builtin “iterate over a line” feature to create triangles, making sure none of the edges would be axis-aligned. I was close to implement a super-complicated algorithm I drafted on paper – but then I got a way simpler idea:1. pick random point x1, y1
2. define bigDeltaX, bigDeltaY, smallDeltaX, smallDeltaY
3. x2, y2 = x1 + bigDeltaX, y1 + smallDeltaY
4. x3, y3 = x1 + smallDeltaX, y1 + bigDeltaYIt took me a few attempts to find sensible values for small and big delta, finally I went with 1 to 25% of map-edge-length for the small deltas, and 25% to 50% respective for the big deltas. Big long pointy triangles all over the map didn’t look very good.
The last improvement for the mask generation was to turn the circles to ellipses, where the x-radius would be 50-80% of the y-radius or vice-versa. Sometimes overlapping circles created half-moon- or archipelago-like structures, which in most cases just looked weird.

The images above feature ellipsis and triangles – that’s the (for now) final way masks are created.
The way things are implemented right now, I have no control at time of mask creation, which style will go into which index later – so it must look reasonable for every combination. I might switch to introduce presets later, a little more about that at the end of the post.

Styles – let’s get to the content

While the mapgen turned out to be a little more complex than I originally wanted, my amount of content is quite the opposite of complex yet. The set of available tiles is very limited so far and boils down to:

Ground – Wall – Shallow Water – Deep Water
(and a few debug tiles, but these don’t count here)

So with basically three tiles there is just so much you can do. So far I came up with:

Caves

Created with cellular automata, and thanks to roguebasin a very nifty parameter set-up, so it creates almost no isolated areas.

Desert

A dead-simple one, empty area, filling in a wall tile with 10% probability, so basically the cheapest way of noise you can get. I might look into other noise generation later, but for now it is good. I don’t know yet which of these styles will survive and which are placeholders.

Garden

Here I tried something with artificial structures. Also I wanted a style that contains water, but just as a minor element, not like a lake or an ocean. So I created a bunch of patterns of a given size – in my current version they are 5×5 tiles – and spam these patterns, randomly selected in a grid-wise manner over the designated garden-area. Fun part here was a little helper function, that converted a string-definition into a table that could be easier processed during looping over the map.
Basically it went from:"11111 12221 13231 12221 11111" to{ {1,1,1,1,1} , {1,2,2,2,1} , etc. }

Water

Here it turned out a little effort is needed. I had to deal with the depth, whether to put shallow or deep water, and decided this by checking the surroundings within a radius varying from none(1×1), over 3×3 up to a 5×5 area if they consist purely of water and if yes, put a deep-water tile. As next step, I let the cellular automata smooth things out, and finally twisted some knobs until things looked good.
Another area of attention was the coast line. This led me to something that I don’t like much; now it is required to fill the water style into the mask as last – because it needs to know if the border cells are ground or wall, so it can adapt it’s coast.
This spaghetti-dependency is not turning out to be a problem right now, but I have a feeling it might do so at some point. Well, I will deal with it at given time.

Border

This is the special bonus area, that appears on every map, it just cages the map with wall tiles, so there is no way to leave for nobody!
At first, I just spammed the border as final step into the map, but then I noticed the water wouldn’t adapt to it, and I don’t get these nice shallow-water coastal areas at map borders. So it got converted into a style, and it gets its own mask-index. In difference to the other styles, the relation between style and mask-index is fix.

Conclusion & What next

In general, I am very happy with the results so far – especially in comparison to the former algorithm. I didn’t reach the goal of maps looking substantially different now, but there are some things I can do about it. For example, I can vary the number of styles used at same time. Or I can vary things in the mask generation step. I have rectangles, ellipsies and triangles and am using only tris and ellipsis right now. Also the amount of each of these shapes that get drawn can be varied.
I think about having sort of presets here, where one could be a “civilized area” for example, that would use only rectangles and triangles during mask generation, and pick preferably artifical map-content styles.
Also, sometimes areas clash in an improvable way into each other – if you look at the last screenshot with the red marked island, you see at the southern coast the garden-area stopping right at the water. A bit of beach would have been nice here.
The red tiles are debug tiles by the way, marking inaccessible tiles for now – inaccessible for land-walkers, so the deep water renders the island unreachable. I keep this displayed all time, so I have a better chance of finding these random seeds that bug the map out, if they exist.

But for now, I keep the map generation as-is, because there are a lot of other things left to do. More about that next time. Github (check if there is a mapgen-v2 branch, if things look old in master).