Tuesday, December 29, 2020

Refining continents

I've done more tinkering to my continents. With the inland-sea-removing function reinstated, I'm getting world maps like these:



A new element in these maps is rotation. I found that some continents were coming out rather square-shaped. I did a lot of tinkering with the way in which they're generated and couldn't reliably fix this. But it occurred to me that the visual annoyance of this could be greatly reduced if I simply rotated each continent by a random amount before placing it. I think it helps - if you look at the western-most continent in that last map, it's actually quite square, but because it's been rotated, it looks OK.

Now rotating a 2D shape around a given point is not very complicated. First, I make a copy of the continent into a backup array. Then I blank the continent. Then I go through it pixel by pixel. For each pixel, I apply the formula:

newx=x*cos(angle)-y*sin(angle)

newy=y*cos(angle)+x*sin(angle)

Then we simply take the value of {newx,newy} in the backup array (which contains a copy of the original continent) and paste that into {x,y} in the continent array.

(It's slightly more complicated, because if, like me, you want it to rotate around the centre rather than around the coordinates' point of origin, you have to add and subtract the coordinates of the centre at key points, but I'll ignore that for simplicity's sake.)

Now another thought occurred to me once I'd got this working. Suppose, before plugging x and y into the above formulae, I add an offset to them. And suppose that this offset varies! That's not difficult to do. All I need to do is create yet another diamond-square fractal. Then, as I go over the continent applying the above formulae, I add an offset to x and y before plugging them into the formulae, and the size of that offset varies depending on the value of the fractal that corresponds to that point. Might this produce interesting results?


Yes! It gives us crinklier coastlines! Lots of little peninsulas and islands. We don't want to over-use this effect though, as in real life continents don't have that kind of coastline all over. So some more judicious tinkering gives us maps like these:



With an effect like this, a little goes a long way. It's hard to get the balance right, but I think these are looking pretty decent.

Now we need to do something about mountains. With the original continent method, I put down mountain ranges and created the continents around them. We're not doing that with these. We could just put down mountain ranges at random across the continents, but it would be nice to do it a bit more realistically. That means ranges in two main kinds of places: where continents overlap (like the Himalayas), and along the edges of continents (like the Andes).

The Himalaya-type mountains are fairly straightforward. We just need to identify the points where continents overlap, and then send chains of mountain ranges meandering across them:


Sometimes a larger continent is drawn entirely covering a smaller one, triggering a mountain range where one wouldn't quite expect it, but this can make for quite nice effects (this one's zoomed in a bit:


That looks to me like it could easily be a fault line between three continental plates!

Now for Andes-style mountains. Ideally, we'd be able to run a mountain range along the edge of a continent, but this would be really tricky to do. Luckily, there's nothing stopping us tinkering with the shapes of the continents at this stage. So we can choose two points at opposite sides of the continent, and then run a chain of mountains from one to the other. We'll make land under and around the mountains, and we'll also delete all other land to one side of that new land. That way, we'll effectively create a new coastline near these mountains.

Needless to say, all of that proves easier said than done, but it generates some nice results:



As always, we don't want to over-use the effect, so it's only applied to some continents.

Now we can combine both of these mountain-making methods, and also bring back a host of other effects that we had before: smaller mountain ranges scattered over the land (with some noise applied to land elevation in general), chains of islands in the sea, and most crucially, removing land by applying a fractal to the whole map. For this last move, we'll do it much more judiciously than before. Only a few, fairly small areas on the map should see significant change.

All of this gets us global maps like these:



The mountains all look much the same height with this visualisation, so the ones at continent boundaries get a bit swamped out in these images, but they're considerably more prominent on the elevation maps and should become more so when the climates are added back in.

Yes, because as you can see, I've turned off the climate simulation for the moment. This is of course partly for the sake of speed while tinkering with the global terrain generation. But it's also because increasing the map size has also shown up issues with the climate routines, so some serious amendments to those are next on the agenda.

Thursday, November 26, 2020

Continents revisited

While putting together the new UI, I've taken the opportunity to do something I'd been thinking of for a while and quadrupled the size of the global map. This obviously allows for more features and detail in each world, but it also makes the regional map a bit more realistic. If I keep the regional map exactly as it was, it means that the scale has changed: each pixel on that map now represents an area of one square kilometre. I think the features I already have on the regional map, particularly the mountain ranges, make more sense if this is the scale.

However, increasing the global map size does show up some limitations of the global terrain generation. The basic continents are made by creating long mountain ranges and sort of spreading land out from them, then adding or removing extra bits of land. However, this doesn't scale up tremendously well.


They look pretty blobby. As things stand, UW improves their appearance by creating a diamond-square fractal and then using that to remove sections of land, to create jagged coastlines:


That gives us much nicer-looking landmasses. But now that the scale has changed, they simply look too small to be proper continents. I can't just scale up this method, because using the fractal to remove land will simply fragment everything. (I don't want to use it to add land, because then I'll just end up with a fractal global map, which is unrealistic in a different way.) Consider an actual world map:


The bits I've circled in red are the areas where it resembles the areas on my maps where the fractal is used to cut away the land. It's a relatively small proportion of the world. The methods I'm using at the moment can make interesting world maps, but they can't really generate something like Africa.

So what I need is a way to create the shapes of continents that don't look like vague blobs, and are interesting and varied, but without being all jagged and broken up. Then I can combine these with the methods I already have to get maps with all different kinds of land masses, just like reality.

It occurred to me that I already had a method of generating shapes a little like this: large lakes on the regional map. There, we take a large, simple shape with lots of straight lines, and distort it into something more natural-looking. Could we use a similar technique to create continents?

Well, first we need a shape to manipulate. A fairly straightforward way of doing this is with a Voronoi diagram. Now, I said at the start that I wasn't going to use those, but while I'm not storing the actual terrain as a Voronoi diagram, I can still use a Voronoi diagram to generate shapes that I subsequently manipulate.

It's a simple thing to program, even for me, and generates this sort of thing:


That would look lovely hanging on the wall. Anyway, as it stands, this diagram has an area equivalent to the global map. What I'm going to do is use it to create the shape of a continent, which will then be pasted onto the global map, not necessarily in the same position that it occupies here. The cells of this diagram are pretty large. I can easily make them smaller, of course, by having more of them, but I really only need a rough outline for our continent.

Now I need to pick out the cells that will make up our continent. A standard way of doing this kind of thing is to use Perlin noise or something similar, but I don't want that kind of shape and in any case I don't need anything that elaborate because most of the interest of this shape will come from the Voronoi cells, as they're quite large. Just a few randomly-placed circles should be enough:



Now we just keep the Voronoi cells that that blob goes over, and that makes the basic outline of our continent. That gives us results like these:



And this is just what I wanted - they already look like very stylised continents.

So we have a basic continent shape. Now we need to disrupt its borders as we did the lakes, so it looks more natural. This will require less disruption than we did then, in fact, because we aren't trying to disguise a gridlike original shape.

It takes a lot of tinkering to get something reasonable. I try to vary many of the variables not only from one continent to another, but also within a single continent, so their coastlines don't look too uniform - there should be some smoother bits, and some more jagged bits. This gets me shapes like these:







I'm pretty pleased with these - I think they look fairly believable as continents of various shapes and sizes. The little islands that sometimes appear around them are a happy accident, the result of the fill method. When the outline of the continent is drawn, I draw a box around it, and then fill inside that box, to make a sort of negative of the continent. Then I reverse that for the final version. Since the outline can sometimes cross over itself while making especially extravagant squiggles, this can leave the insides of loops as isolated bits of land on the final shape. You'll notice there are also some squiggles of blankness inside these continents, but it's easy to remove these.

The next step is to put these onto the world map. Rather than just slap a few on at random locations, I select just one or two focal points on the world map. At each focal point, a continent will be placed. Around these central continents, other continents will be placed, either overlapping the central ones or a little way off from them. In theory, this allows us to mimic the real world map, where continents cluster in groups, with wide oceans between the groups.

The results aren't perfect, but some of them are already starting to look like potentially interesting world maps (bear in mind these are made merely by the process just described, without any removal of inland seas or shifting the map or anything):





Clearly there's still a lot of finessing to do, but I think this method has the potential to produce a good base for global maps once we add back in all the other details.

Wednesday, September 2, 2020

Change of clothes

Just a quick update!

As ever, work on this continues to inch along when I'm able. I'm focusing at the moment on redesigning the interface of Undiscovered Worlds so it looks a little more appealing and intuitively useable. I'm using Nanogui, as it's not hugely over-complex and I like the look.

This is how it's looking at the moment:


Still plenty to be done, but I think it's looking reasonable!

Friday, July 24, 2020

Quick update

Hello everyone. This is just a brief post to update the project. I've been doing lots of unglamorous bug-squashing. At long last, the lakes are *mostly* behaving themselves. Rivers are too, usually, as long as you don't look too closely. A lot of issues remain, but it's all looking a little smoother than it was, and I need to move on while I still retain some will to live. I've also done more work on the coastlines, which are never good enough, but they're looking generally pretty decent. Surprisingly, I found that my landfill method was now actually counter-productive - the coasts looked better without it. So I've removed that, presumably getting some speed increase into the bargain.

I've done some rejigging of the colours used to draw the relief maps, and I'm quite pleased with the results:








I said previously that I intended to rewrite it so that when the regional map is scrolled, it generates only the tiles on the leading edge, shifting the rest of the map rather than regenerating the whole thing each step. After several days of working on this, I've found that it is indeed faster, but it's impossible to guarantee that those tiles are exactly correct. Regenerating the entire map after it has been scrolled in this way always results in changes in those leading edge tiles, no matter what I do to get around this. The absolute bedrock first principle of the regional map is that any given cell from the global map should always yield exactly the same tile on the regional map, no matter what, so I've very reluctantly had to give up on this and keep the system of regenerating the whole regional map every time it's scrolled.

(An unexpected byproduct of this was that I discovered the little algorithm that generates the marbling effect I've added to the maps - most apparent in the sea. It doesn't mean anything but adds some nice visual interest, I think, so the work wasn't entirely wasted.)

There are still a couple of more glaring bugs to get rid of, and then it's time to think about larger global maps and larger regional maps too. Both of these will probably also require a serious rethink of the UI, which at the moment doesn't really exist.

Friday, June 12, 2020

Surprise!!!

...it's a post about lakes!

In my last post, I talked about a new way of doing rift lakes that works by drawing the outline for the whole lake in one go and then filling it, rather than by trying to make each tile by itself, as I originally did. I wanted to make better rift lakes, of course, but I was also curious to see whether this method would work at all as a possible new approach to the other kinds of lakes.

Just as a reminder: Undiscovered Worlds has four kinds of lakes. At the global level, it has (1) what I refer to feebly as "normal" large lakes, and it has (2) rift lakes. Then, at the regional level, it also has (3) what I refer to equally feebly as "normal" small lakes, and it has (4) glacial lakes.

(3) and (4) are created from scratch at the regional level, because they are relatively small and wouldn't show at the global level. (1) and (2) are much larger and are created at the global level, and must be translated into something that looks reasonable at the regional level.

(I'm ignoring salt lakes here, not to mention wetlands and ergs, because these are all treated as varieties of normal large and small lakes.)

What I'm interested in here is lakes of type (1): very large, wide lakes along the lines of the American Great Lakes. To date, my attempts to make these look reasonable at the regional level haven't been very successful. They've got even worse in the new, rewritten version of UW, with so many overlapping functions trying to correct each other's problems that I don't really understand how they work any more, and they don't look very good. The basic approach, though, remains the same: go through the lake tile by tile, create terrain using the diamond-square algorithm to expand on the terrain elevations given in the global map, and flood any areas that fall below the surface level of the lake. I want to try to replace this with a new method entirely, where we instead calculate the outline of the entire lake in one go.

The first step is straightforward: we mark out all cells that lie on the border of a tile that corresponds to lake on the global map with a tile that does not correspond to lake. That gives us this sort of thing:


(Note that some bits of rivers are still present within the lakes, but they are weird - that is fine as obviously they aren't normally calculated when the lakes are actually there. The lakes are done before the rivers, remember.)

Then, for each lake, using one border tile chosen at random in world generation as our starting point, we go around this outline and select every nth highlighted cell to be a node. To start with I'm trying n=6. If we do this and join up the nodes with straight splines, we get:


Not so different in appearance, though the corners are a little blunted because the nodes aren't in them. But because this outline is now based on the nodes, rather than simply drawn directly onto the borders between the tiles, we can shift those nodes around and hopefully make it all look a bit more natural.

I could just give a random offset to each node, but I don't think that would distort the squareness enough. Rather, I use a running offset. We go round the outline, taking each node in turn, and apply the same offset to each, altering it a little each time. That gets us this:



Already some bits are looking almost reasonable there. Now we add a bit of random variation to each node in addition to the running offset:



The nodes are being connected by straight lines here. With a bit of random curve to them, and some additional jiggling of the other parameters, we get this:


I think that's starting to look reasonable.

After this, it's basically a matter of filling it in, and also adding a few islands. These are done with templates, and I'm careful to ensure that every island is placed such that it has clear water all around it - islands can't overlap with each other or with the lake coast.

With that done, and further tweaking of the various parameters, we get lakes like these:




I think these are OK. The great virtue of this approach is that the lakes are guaranteed to be single bodies of water - there is no chance of them somehow getting split into more than one, as could happen with the old approach. That means that you can't get weird situations where the outlet river leaves a different lake from the one the inlet rivers flow into.

A disadvantage of this method is that it can't handle islands that form in the lakes at the global level - that is, where entire tiles of land exist within the boundaries of the lake. So I need to tweak the global lake creation functions to ensure that those never form. Otherwise, it's not looking too bad.

So with that, the entire functionality of the original version of Undiscovered Worlds is now in place, and refined in many ways. The next stage is sorting out all kinds of appalling bugs that are also in place. After that, some tweaks to various things, and I hope to have an initial releasable version.


Thursday, May 14, 2020

Better rift lakes

This is what real rift lakes look like:


The old version of Undiscovered Worlds made rift lakes that looked a bit like big fuzzy caterpillars. This was because it used a simple method of pasting blobby templates over the river that runs through the rift lake. The problem with that is that you either make the lake look simply like a wide bit of river or you give it jagged edges. But a real rift lake is like neither of these. It has quite straight, smooth edges. So I thought about how this might be simulated more realistically.

I realised that a better lake coastline could be created simply by drawing the outline first and then filling in the lake inside it. The outline could be drawn using our familiar system of splines, which I've already used to work out the sea ice on the global map and the routes of rivers and mountain ridges on the regional map. All we have to do is identify control points for the splines and then draw a loop connecting them all up. Then we can use a flood fill to mark the whole lake surface within that loop.

There's a problem, though, which is that is very hard to do if we're calculating each tile of the regional map by itself. It's especially hard to do if we're dealing with a rift lake that extends beyond the area of the regional map. How will we know how to draw the outline in one of the tiles that's on the edge of the regional map?

I decided that the solution was to create an array that's larger than the regional map. This, the rift lake map, is bigger than the regional map by ten tiles in each direction. The plan is for UW to scan through this tile by tile. If it encounters a tile that is the start of a rift lake (i.e. the upstream end), it then moves downstream, tile by tile, plotting the control nodes for the outline that correspond to each lake tile. After it's done that, it can simply connect them all up using splines. Then, we can copy just the section of the rift lake map that corresponds to the regional map over and discard the bits that lie outside. This will ensure that our lakes are stable and look the same no matter where we scroll.

That's the theory anyway!

Let's start by putting in some simple nodes and then tweaking. For each tile, we'll have two nodes - one on each side of the lake. The start and end tiles will also have one additional node each, for the ends of the lake. We'll put those just where the main river enters the tile (or exits it, in the case of the last tile). For the other nodes, we'll look at which direction the main river is headed from this tile, and just stick them a bit of a distance away from the river in a roughly perpendicular direction from it. Then draw splines between them.

That yields the following:


The pink lines are (what will become) the rift lake outlines, overlaid onto this river map. Notice, in passing, the horrible forms of "normal" large lakes nearby. I'm hoping that if this attempt at a new way of making rift lake outlines works I might be able to adapt it to those as well. Who knows?

Anyway, obviously the rift lake outlines we have here won't do. They are made of straight lines because I've given no variation at all to the control points of the splines. First I double the number of nodes - each tile now has two nodes on each side of the lake. Then I add some random variation to their location, with the same variation being applied to nodes on each side of the lake. Finally, I adjust the ones near each end of the lake to taper towards the point. That gives us:


This is looking closer to what we want. Now it's basically a matter of adding some extra variation to the nodes so that the width of the lake varies, and allowing the splines to curve by giving (slightly) more variation to their interpolated control points:


I think these are looking pretty decent. Now it's a matter of filling it in with a simple flood fill and then assigning depths to each cell. I do this by drawing a series of large circles, the centres following the line of the main river that flows along the lake. The closer to the centre of the circle, the deeper the lake at that point, to a maximum of the depth that's stored in the global map for that tile. I use the lake shape that we've been drawing as a mask.

Finally, it would be nice to have the occasional island in there. These aren't common in rift lakes and when they do appear they're close to the shore. Adding them is a simple matter: find the shore, move just past it, put some bits of land down.

All of that gives us these:





Not perfect, but a lot better than what I had before, I think.

Wednesday, May 6, 2020

More or less there

Well, again there's been little activity on this blog for a while, but there's been plenty of activity behind the scenes. I've now nearly finished porting it all over. That means that the regional map level is up and running with all the features it had in the old version of Undiscovered Worlds. The only exception is rift lakes, which I want to do in a new way.

So first, here are some screenshots. These are all from a single sample world:











The major benefit is, once again, a tremendous speed increase. As I mentioned previously, the old version of Undiscovered Worlds could take about a minute to generate each map like these. The new version takes about four or five seconds for each one. This makes it far pleasanter to work on the code as well as actually browsing the worlds it creates. And for me at least, that alone makes it worth taking all the time to convert this all to C++.

Of course there are lots more changes along the way. I was able to find and eliminate quite a lot of bugs. Fortunately, I was also able to generate some new and even more baffling ones, just to keep things interesting. Here are some of the key developments:


Rivers

In the original version, rivers could carve out the land under them, potentially below sea level, creating estuaries and inlets. (They weren't really carving it out, because rivers are generated before the rest of the land, but that was the effect.) I found that this led to all sorts of bugs and problems and piled function upon function trying to resolve those problems, which were mostly associated with potentially allowing inlets to appear far inland where sea wasn't otherwise expected to be. Now rivers still carve in this way, but I don't allow them to drop below sea level. So rivers will not carve out inlets and estuaries. This resolves a lot of problems and makes some other things possible (see below).

But what about all those nice inlets? Well, they're easily dealt with. I just added a new function to add them. It looks for where rivers meet the sea and cuts out inlets based on their size. Although this is a more artificial way of doing it than letting the rivers make their own inlets (which is how Martin O'Leary does it, after all), I find it gives better results.

There are various other tweaks. I added extra wiggles to rivers that pass from one corner of a tile to the opposite one - these sections of rivers had tended to come out too straight in the previous version, but now they look a bit more natural. As always, the struggle at regional level is to prevent the map from looking like it's made up of square tiles, and this helps.

Coastlines

As I may have mentioned before, coastlines have caused me unending problems, and the new version is no exception. I managed to get coastlines in the old version looking pretty decent a fair amount of the time, so I was annoyed when transposing exactly the same routines to the new version delivered blocky, unconvincing coasts most of the time. I spent a lot of time trying all kinds of methods to rectify this. I eventually found a combination of methods helped:
  • I found that particular heights of the land at coasts, combined with particular depths of seas there, tended to produce better results. (This is something that would have taken forever to work out with the slower, older version.) So I added a function at the end of the global terrain generation that goes through the coasts and pushes the heights/depths towards these optimum values.
  • I had previously used blobby templates (in fact the same ones used for making small lakes) to break coastlines up a bit, using them to subtract land where the coasts were too straight. I added the ability to subtract land at these points too and I also allowed it to use larger templates, not just the very small ones I'd previously restricted it to. This made for really good results.
  • I had previously created the effect of fjords in glacial regions by extending mountain ranges out beyond the coasts. When I did this, I also set UW to extend occasional mountain ranges out in the same way in other locations, just to get occasional peninsulas. I greatly extended this in the new version. Peninsulas of this kind are much more common, especially in areas of greater general roughness, and they can occur even when only small hills are near the coasts. This makes for areas of coastline that are fairly jagged (though not to the extend of the fjord coasts, where more mountains are extended out and for longer). It also often creates islands off the tips of peninsulas, which look rather good. I found this method so effective at creating interesting coastlines that it was hard to find a balance between using it enough to make a difference and using it too much so that all coastlines look the same. I really want variety in the maps, but it's not easy to achieve.

So all of this helped to make the coastlines look pretty decent most of the time - although as before there are always a few bits that look annoying blocky or boring or whatever.

I was also able to make other changes, particularly with regard to "pools", or sections of sea that are cut off from the rest of the sea, which are unavoidable when generating coastlines in this way but which are obviously highly unrealistic. Previously, I used a flood fill function to find and eliminate these, but it was clunky and didn't always work. Now, though, having removed the ability of rivers to cut below sea level, I could guarantee that sea would never appear more than one tile away from the coast. This allowed me to create a new approach to pools: a simple pathfinding function. The program identifies which tiles are roughly on the coast (either tiles that correspond to land cells on the world map that border sea cells, or sea cells that border land ones). It goes through these tiles on the regional map, finding any sea cells they contain. It then identifies sea cells in neighbouring tiles that are further out to sea, and tries to trace a path to them. If it can't find such a path, it declares the start cell to be part of a pool and turns it into land.

Excursus on my pathfinding algorithm. Ignore this if you're one of those weird people who are inexplicably uninterested in pathfinding algorithms.

I didn't use A* or any other standard pathfinding algorithm for this. Instead I wrote a simple recursive function to do it. Now standard pathfinding algorithms are breadth-first: that is, they start from the start cell, then look at each of the neighbouring cells in turn, then look at each of their neighbouring cells in turn, and so on. A recursive function like mine doesn't do that. It's a depth-first algorithm: it looks in one direction first and exhausts all possibilities in that direction before turning to the next. This is usually fairly inefficient. However, a little improvement occurred to me which I haven't found in any of the sites on pathfinding algorithms that I looked at - though someone must have done it before because it's both fairly obvious and surprisingly effective.

The function works by moving to the north and calling itself, then moving to the east and calling itself, then to the south and calling itself, then to the west and calling itself. Then it returns, either to the previous recursion of itself, or the original calling function. That's a very basic recursive method.

But (this is my innovation), each time the function is called, before it calls itself again it checks to see what direction the target cell is in from the current location. It then changes the order of the directions based on that. For example, if the target cell is roughly south-southwest, it will move south and call itself, then move west and call itself, then move east and call itself, then move north and call itself. The order of the recursive calls is based on how likely it is that that direction will actually lead to the target.

This means that if there are no barriers in the way, the pathfinding function will simply go straight to the target cell without deviating at all. That's obviously quicker and more efficient even than A*.

However, there are two disadvantages. The first is that, as a recursive function, it risks a stack overflow if it calls itself too many times. That means it can't search over large areas without crashing.

The second is that if there are barriers in the way from the start to the target, it won't be very efficient. It will be like a fly bumping at a window trying to bash through it. Unlike the fly, it will find its way around eventually, but the path it comes up with will not be the optimal one and it will take longer than a more sophisticated breadth-first algorithm.

But I reasoned that neither of these was a big problem. First, if I was only trying to find a path from one tile to its neighbouring one, these are small areas that won't cause a crash. Second, most of the time, there would be a direct path from the start to the target, or one without too many obstacles, so my function would probably be pretty efficient for its purpose. And third, I don't care about getting a good path. I don't care what the path is, only whether there is one at all.

Gratifyingly, all of this proved correct. The pathfinding technique works well and very quickly.

End of boring excursus

A problem with this, though, is that it couldn't account for the extended mountain ranges, which stick out into the sea in fjord regions and elsewhere. These can create pools that are further from the coast than normal ones. My pathfinding routine couldn't cope with those. Eventually I solved this by creating a new flood-fill routine that goes over the map after the other ones. Like the one in the original version of UW, it looks for areas of sea that are smaller than a certain area. Instead of turning them into land, though, it turns them into lakes. The result of this is that crinkly coastlines tend to have crinkly-shaped lakes a little way inland, which I think looks rather good.

Deltas

Deltas can now be bigger and have more branches. However, this created a new problem. Delta branches are a river system of their own, which ignore other rivers, except for where they connect up with their host river. Any other rivers that may wander across the delta region don't interact with them. I originally thought this would help to create the impression of a confused watery area, but it actually detracts from the nice fan shape of the delta to see other rivers just going straight across it. So I created a function at the global river generation stage which diverts rivers of this kind. Now, if a river enters the delta of another river, it will change direction to follow one of the branches of that delta down to the sea. Because the routes of delta branches across tiles are calculated independently of the routes of normal rivers across the same tiles, this means that the two will cross, merge, and separate as they meander together through the same tiles on their way to the sea, which I think is quite a nice effect. It was a nightmare getting this relatively simple-sounding tweak to actually work, though.

Terrain roughness

Most of the terrain is created by taking height values from the global map and then filling in the tiles around them using the diamond-square algorithm. That algorithm uses a roughness value to determine how much variation to give the land: if that value is low, it simply graduates smoothly from one initial value to the next; if it is high, it crinkles up and down wildly as it goes. In the previous version, this roughness value varied slightly from tile to tile depending on the global roughness value. But it couldn't vary much, because then the boundaries between tiles were too apparent, where the land abruptly changed from being rough to smooth. Now, though, it occurred to me that the roughness value itself could be smoothed with the diamond-square algorithm. That is, the regional map itself now has an array storing its own roughness values. These are seeded from the global roughness values for each tile and then the rest are extrapolated via diamond-square, exactly as precipitation and temperature are already done. Now, when the program creates the terrain, it changes the roughness value within each tile as it does them. That means that within a single tile you can have areas with high roughness and others with low. This allows us to change the roughness gradually, not just at tile boundaries. And that allows us to have areas with relatively high roughness, rather than having everywhere be pretty flat apart from the mountain ranges, as in the old version. This adds more variety and texture to the maps, I think.

Lakes

They're evil and I hate them. Something went wrong with my lake coastline routines and they generated terrible results. I squodged together so many new ones to try to repair them that I don't really understand how they work any more, but they roughly work, though the lake shorelines tend to look implausibly crinkly. Only when I was taking the screenshots for this very post did I discover that lakes now have a tendency to crash the program. Why is that? Who knows! It'll have to be investigated. At any rate, they exist and they mostly don't appear to breach the laws of physics, and that's the best anyone can hope for with lakes.

I haven't yet implemented rift lakes at the regional level, because I'm not really happy with the old implementation and I want to try doing them in a different way, so I thought I'd save that for another blog post.

Where next?

Well, I asked this before, and my answer was to rewrite the whole thing rather than move on to something new. Now I've done that. What now? Well, as will be apparent from the above, there are lots of bugs to squash and remaining features to add in. Features that it needs next include:
  • The ability to scroll around the map more quickly. At the moment it generates the entire regional map every time you scroll, even by one tile. Obviously it's more efficient only to generate the new bit. I've deliberately not done this yet because I wanted to be sure that everything was working consistently and that each tile looked the same no matter where in the regional map it appeared.
  • The ability to generate regional maps of larger areas, not just the 30x30 square that it does by default. I think this would be really nice.
  • Possibly a new scale with larger worlds. If I were to double the height and width of the global map, it would have four times as much detail. That would mean that on the regional maps, one cell would be 1km square rather than 2km square. I wouldn't change how they are actually generated as I think that this scale would actually fit the features I have on them now.

Once I've done that, I'll aim to release something that other people can use and find appalling bugs in too. Yay!