Ultima Ratio Regum 0.9 (release date: December 31st 2021) is generating the graphics and details and interactions for dozens upon dozens of different sorts of in-game items and currencies and trade goods and more, and one of these is TREASURE MAPS. I often get asked for more information about generating the various in-game visuals, and I thought these would make an interesting case study – so let’s get started.
To begin with, this is what a generated world map might look like:
The overall objective of the game has always been a kind of procedurally-generated treasure hunt – i.e. using all the information in the world to locate a small number of crucial items somewhere in the game – and so it seemed time with 0.9 to add treasure maps, and maps in general, as a means of pointing the player towards where they might go, and more generally just adding a new source of world information for the player to acquire and use. 0.9 is currently in very active development for (hopefully) a release at the end of 2021; while there are many other items being generated (such as weapons, armour, books, pocket watches, spices, firearms, mining equipment, bows, and a million other things), I thought the treasure maps would make an interesting generator to go into some more detail with.
So for starters, what sorts of maps should be available? After consideration I settled on three potential map sizes of “small” (5×5), “medium” (8×8) and “large” (11×11), whose in-game prices would obviously reflect the amount of information shown on the map (and also the quality of the map parchment, but we’ll get to that later). The first task was to get grids of appropriate sizes generating; I debated having each icon or square on the treasure map be 2×2 or 4×4, but 2×2 turned out to be too small to convey meaningful information using an ANSI tileset and 4×4 didn’t leave much room for a map of actually significant size, so I went with 3×3. You can see in this gif that each 3×3 is a square of blue ‘x’s with a map in the middle, and the game is generating small, medium and large treasure maps within the confines of the lookup image window (the red ‘x’s). It does this by starting at a local (0,0) coordinate, iterating from left to right until it gets beyond the size of the map, then incrementing the y value by 1 and resetting the x value to 0, and continually doing this until both the x and y values have exceeded the allowed size of that particular treasure map. So far so good – the game could generate a grid of tiles at various sizes, and make sure they all could fit within the limits of the image size.
The next step was to get some basic code in there for showing a different 3×3 set of tiles on the grid depending on what should appear there, and for adding various colours. This led to a first test in which I replaced the grid of blue ‘x’s with just a dark grey for the background, a grey spike for a mountain, and a light blue octagon to represent a lake. Even with this minor change it immediately became apparent roughly what the final aesthetic for the maps was going to look like, and I immediately liked what I saw. It was immediately apparent what these maps were going to look like when finished (roughly, anyway) and the kind of graphical potential the ANSI tileset gave me within these confines. Things in the game are already shown on several different scales, such as the world map, the city view, the local view the player walks around on, and so forth, and so adding another one didn’t seem like a problem at all.
So each of these 3×3 pictures depicted one tile on the world map, or 200×200 tiles the player could actually walk around in person. So on this scale we would want to see things like mountains, settlements, forests, cities, coastlines, roads, rivers, and so forth. The next step was to add some more of the world map features into the generator and make sure they all looked distinctive and at least reasonably clear to the player, and also to start thinking about the colour of the fabric (a kind of canvas, I guess, or a thick paper or some sort?) these were being drawn on. I don’t know about you but dark grey paper is quite rare, so I settled on a nice pale biege / yellow colour, clearly implying the sort of substance these maps are being made from but also suggesting at least a little bit of age, or wear. It was also important that I either pick a light colour for the paper and a dark colour for the icons painted on it, or vice versa, in order to ensure readability for players trying to make sense of these maps. After a bit of experimenting I settled on this kind of colour, and started to add some more icons.
These were coming along well, but the “empty” world map tiles shown on this demonstration map – i.e. those that are just land and don’t contain any features of interest (although they might, of course, contain treasure…!) were very boring at this stage, since nothing showed to suggest they exist. The map in the above version therefore opened up the possibility for maps showing large areas of “empty” terrain being empty, and therefore uninteresting, themselves; and in turn I felt it was important the maps show the different biomes (deserts, jungles, taiga, polar, etc) in order to help players work out where the map is pointing them to. After a range of different experiments, I settled on a single central dot on the 3×3 grid within the map to depict just a normal tile of normal terrain showing nothing else, but the colour of the dot would tell the player what terrain was there. (In the below case, desert and tropical).
I then went back and implemented this range of colours for all the possibilities of biomes (deserts, savannah, jungles, temperate, swamp, taiga, tundra, polar) and duplicated this for the forested tiles as well, although this latter naturally doesn’t apply to polar regions, which tend not to be overly full of trees.
The time had then come to implement a number of the other features that should be appearing on these world-map-scale treasure maps (we’ll talk about “local”- or “human”-scale maps later). I then therefore moved into adding a bunch of the other world map features such as fortresses, cities – which stretch across many tiles even on the world map – ocean tiles, tribal settlements, towns, roads, rivers, and so forth. Adding some more of these in and putting them into a quick demo version of a final map gave us something like this:
With all of these pieces now in place for displaying terrain, trees, rivers, roads, various structures and so forth on the treasure maps, I thought the next step was to take a moment in order to create a full demo of what these maps would look like. I didn’t yet have a completely clear idea of what these maps were going to look like, and with these various pieces now implemented it was important to check they actually looked good when combined with each other! Given that I had developed visuals for just “normal” tiles (normal desert tile, normal tropical tile, etc) I was alaso keen to check that these integrated well with the more distinctive parts of the map, and also to ensure the colours merged well, and nothing looked strange or peculiar when this set of colours and shapes were combined. I then therefore spent a little bit of time trying to create three quite different demo maps. The small one is a desert with a fortress, a lake and and some mountains as well as a volcano; the medium one gives us a city between a temperate and a savannah biome with an ocean and a road leading out of the city; and the large one offers us a polar landscape with rivers, a lake, various sorts of forests, and a tribal settlement. This yielded the following:
I was very pleased with these! They seemed to be coming along well, and were developing their own visual styles, and the balance between the lighter tiles (e.g. for just normal terrain) and the busier tiles (mountains, lakes, forests, etc) seemed to be working really nicely, and giving a good evocative sense of what these kinds of spaces might look like to the player when trying to seek them out. The next step was that I realised a few other structures were still missing, so these now got added. This included monasteries, mines, universities (to be added soon), graveyards, slums, and various other structures on the world map I forgot about on the first sweep, so those also got added in to these three demo maps. You can see a university on the left of the middle map, a graveyard and a slum above and underneath the city on the middle map, and a monastery in the bottom-left of the large map. It was also time to add some shading to suggest a rippling texture in these maps, and at around this time I decided I didn’t like how cities looked, and so I changed it. With shading added and some new important structures included in the database, we therefore now had this:
Next up was the fact these were still very square, whereas a proper (treasure) map should be just a little bit less “pristine”, especially around the edges. The next step was therefore to add a system whereby the edges could be blurred a little bit while still leaving the main image of the map intact. I created a system to enable the edges of the map to “flow” up and down (or left and right) as the edges went along, and to make sure these edges varied with each possible generation – I believe there are 10 potential top edges, and 10 for left, right, and bottom edges, so 10,000 total possible edges for the maps as a whole. When generating a map the game now takes one from a random set of potential top, left, right and bottom edges, and then when generating the images figures out what each corner should look like at each edge intersection and adds an appropriate corner. Although they took a while to really implement, I’m very happy with how these are looking. I didn’t want them to look too chaotic – since these are being sold in shops (in thematic terms) and because I want the player’s attention to be on the content rather than the edges (in design terms) – but I also didn’t want them to look like naval or geographical charts produced in some ministry somewhere. At this point I also noticed that some of the lighter colours (such as the white for the diamond mine in the large map) weren’t blending nicely with the black and were sort of merging into the canvas colour, so I added some special rules to treat the light colours differently. With the edges added and these minor graphical tweaks, this is what they then looked like:
Now, pretty much all items in URR 0.9 have three qualities – high, medium, and low. This will affect their prices and in the future what else you can do with them, so a low-quality shovel is obviously going to be worse for digging up treasure than a high-quality shovel. Some items have other variants such as small, medium, and large, and this is of course the case for the treasure maps as well as many other items. I therefore needed to implement a way to get the quality varying in the maps, and also to add some additional challenge to the player’s process of using these maps. I tried having the edges change in shape, as if parts had been ripped out or ripped off the map, but that actually looked lousy, so instead I went with a model where some parts of the map had been scrubbed off, and other parts had holes in them, which looked like this:
At this point I accidentally created an intriguing graphical glitch, which reminded me rather of the visuals of Brogue, and hence merited a mention:
But although it looked kind of funky, it was time for this bug to go.
At this point the “global” maps were basically complete, at three possible sizes and three different qualities, and were able to show everything required for pointing out an area on this map. With this complete the next step was to think about “local” rather than “global” maps, i.e. maps that show you something on the human scale of the world. The above maps all show you things on the world map scale of the sort you can look at by looking at the world map or “T”raveling around the world. However, when there are 200×200 tiles for you to walk around on in every one tile of the world map, having an “X” on a single world tile is only so helpful when there are 40,000 on foot tiles in that grid which might contain the thing you’re looking to dig up. This is where the local maps come in. Whereas the global maps are relatively sparse, I made a decision that I wanted the local maps to look a bit thicker in information, with more detail and less blank space. Here’s what I came up with! Some of the map tiles being represented here should be obvious, some a little more cryptic – but that’s ok, since they’re all different, and that’s the important thing. (There are in fact a dozen tiles shown here for things which are not yet in the game…)
However, upon completing this set I realised I’d made a mistake, because of course on the human-scale map a tree can take up multiple tiles, and each 3×3 in the above ^ is supposed to represent a single walkable tile, e.g. a single tile containing a chair, a single wall tile, or a single part of a tree. At this point I went back and made appropriate tree changes, which left us with this for a large tree and a smaller one:
And that was good enough.
The next step was to create some mock-ups of these local-scale maps to make sure they actually looked good, and were clear and legible and so forth. I spent a little while creating some mockups of three “local-scale” treasure maps that could potentially generate, and I tried to make sure in these mockups that the variety of locations was reflected. I did some experimenting here and changed a few of the symbols, and a few of the colours, to make them connect with each other more crisply or pleasingly than they were before, but here’s what we wound up with!
So, for instance, in the small map we see someone who has helpfully buried treasure at the peak of what looks to still be an active volcano; the medium map shows us inside a mansion and that something is buried two tiles beneath a torch in a hallway (good luck digging that one up without upsetting the owners), and the third shows some treasure next to a river or coastline accompanied by what looks like a fairly up-market house (surrounded by a hedge, one of the new terrain features that 0.9 will be bringing in). These therefore give detail about which exact tile in the entire game world something is buried in… but there are 2,500,000,000 (i.e. 2.5 billion) tiles in the game world, so how one earth do you find the area where this tree is, or where this mansion is? Well, again, by triangulating the other information in the world – ask the seller roughly where in the world the map refers to, show the map to people, read books about the area you think it might be in, maybe even listen to a bard singing a song about local buried treasure – and of course, just explore. Some of these mechanics will find their way into 0.9, others for 0.10.
The next thing of course was to check how these handled being of lower-quality, and setting the quality to “low” yielded these:
Again, tougher, but not unusable. The first one still tells you it’s at the top of a volcano; the second’s fancy floors (the purply-tiles) show you it’s indoors (clearly in some expensive or important building) and gives you an orientation of wall pieces and wooden flooring to try to match up; and the third is clearly outdoors, just south of some water, and with a building nearby to the west. These are obviously going to be much tougher than the high-quality ones, but hey – you get what you pay for! Also, for reference, here’s what medium-quality maps of both sorts look like:
With that done, all that remained was to move this code out of the separate Python file I used for coding and testing the game’s procedural graphics (this being obviously vastly faster than waiting for the game to recompile every time I want to test how something looks) and into the main game itself. This didn’t take too long and in the process I actually discovered a tiny handful of minor world generation bugs that had been lurking in the game for probably years and nobody (myself included) had yet noticed. These are therefore now fully implemented in the game, and you can buy maps at stores in 0.9 (releasing Dec 31st this year). Maps in-game might temporarily not show the treasure location, because I’m crunching (in a healthy wholesome way) to get this out in the next month and I might not have time to code in “what is the treasure?” mechanics, but if not, that’ll be coming extremely soon after the 0.9 release, probably in a 0.9.1 or something like that, but they still show all the other information here. Overall I really am very happy with how these look, and the normal maps will definitely be an interesting mechanic to add into the game, and treasure maps are such an exciting addition to bring to URR.
Whew! Thank you so much for reading this, friends. I do hope it was worth your time.
Is this kind of postmortem of designing a generator interesting? If it is, please do let me know in the comments box (or on Twitter, by email, whatever). It’s a lot of effort writing this up, and although I genuinely did enjoy putting this post together, this will probably remain a very rare thing unless there’s interest – so if there is interest, let me know! And if you enjoyed it, please do share it around, since this was a heck of a thing to write, and it would be fab to get as much interest in it as possible. Thanks everyone!