Showing posts with label Mapping. Show all posts
Showing posts with label Mapping. Show all posts

June 22, 2022

Preparing a Setting

I have been working hard on a setting of my home state in another universe. It's been way too long since I've run a game and I'm getting itchy. So far, this has been a good test of things I've learned and things I'm learning, and its given me an opportunity to re-write a lot of the market code in particular. That's helped clean things up and hopefully erased some hidden errors.

I've divided up the region into nine "regions." Not kingdoms, exactly. But distinct culturally (in the real world) and thus a good proxy for translation into a fantasy version. Some populations get swapped over to halfling, elven, orc, dwarf, etc.

The main challenge now is to apply these principles to the regions. There are some differences in tech level here, ranging from a T-8 chiefdom all the way up to T-12. The danger is that I will not be clever enough to avoid "sameness" in the relatively small areas in question (around twenty 20mile hexes). Of course, sameness is not necessarily a bad thing - these regions will share trade routes as well as language - but we want the variety to mean something. Otherwise, there is no reason for them to be separate autonomous regions.

My familiarity with the real-world terrain is also a crutch. Because the farmland is so fertile, nearly every square inch of land that can be farmed is being farmed, a development only in the last 100 or so years. Reconstructing the "original" terrain for a much less populous society has been an interesting challenge.

I will no doubt continue to refine the descriptions of and relationships between the regions, and my next task will be to seed the commodity list with enough stuff to satisfy a party starting out. A work like this is never done, but I want to get it into a playable state. I also have 1mile maps ready for many of the hexes, particularly in the northern part of the state.

February 15, 2022

Ex Nihilo VI: Tectonics III

Continuing on with the work of generating terrain from the tectonics. My first fresh crack uses both tectonic uplift and droplet erosion. These processes are cycled over and over until some condition is met. In this case, I start from a flat plane and stop when at least one cell is at its maximum height (25599 ft). The sea level is determined such that 29% of the total surface is land. I also apply a hypsometric curve to the land area so that higher elevations appear in roughly the same proportions that they do on our earth.

However, this algorithm generates a pretty boring topography. The mountains slope up uniformly from the coast, and the tectonic uniquenesses are not presevered. Usable, but disappointing.

The problem is that the erosion cycle is too powerful as the terrain grows from zero, and only the center of the continents (that is, the areas with the least erosion) have any chance of growing at all. To fix this, I began with a terrain generated directly from the relative uplift scaled to max height. The warping effects are clearly visible here but these will be smoothed out by the erosion algorithm.

Next, I again cycle through the erosion, but this time I rescale the height at the end of each cycle and apply the same hypsometric distribution. This yields a much more interesting topography.

The grayscale map is a bit hard to parse, so I threw the map into GIMP and applied a simple colormap. where 10,000 ft begins to turn into gray/white.

There are still some issues I can see, or improvements that can be made. Coastal areas are pretty uniformly low for many hexes inland (no Chilean Andes). Most areas do not have significant mountain ranges, although there is one range similar in size to the Tibetian plateau.

But this is the process. Design, test, repeat. This will be good for now and I'll move on to some other elements of the climate system.

April 9, 2021

Detail XIII: A Case Study VII

One full region is now generated:

There's plenty of material here, of course, but I can do better, particularly with the addition of features. Let's zoom in on the capital city here (Hex 25, infrastructure 42).

The first and easiest thing to place is a bridge. Hex 25 has a high enough infrastructure to be able to place bridges (as opposed to ferries or fords). This river has a Strahler number of 4. Therefore, the two hexes where the roads cross the river will have bridges on them, notated by black squares (for now).

I recommend reading through this series of posts to understand where I'm going next. We want to know what features this hex has by virtue of the specific layout. Moreover, it'd be nice if this were a true function: that is, for a single input of hexes, we have a single output set of features. That will allow us to save some storage space, since all we'll need to know is the original layout.

To place these features, we loop through the hexes from highest to lowest infrastructure - not worrying about whether the hex is itself civilized. That is, for a hex and its six neighbors, if there are 4/7 civilized hexes present in that set, then the central hex is of Type 4, quite good. Depending on the exact distribution of those civilized hexes (Type 4 has 8 possible layouts), the possible features could be a large keep with a village, a manor house with a village, an aquifer, or a quarry. Once a feature has been identified, all hexes in the set are removed from the list: this prevents the map from getting too busy.

I've only added a few things to the list given by the Tao above. But there are a lot of configurations which are empty - again, that's fine. Scarcity breeds innovation.

In addition to the bridges, we generate a medium keep with village and church, a toll road, several mines, and a quarry. Additionally, there are several outlying hexes with no specific feature, but which in this case would most likely be farms or other "non-village/city" communities of a few families.

I could also make use of the wilderness and deep country features discussed here; but that would need be on a different layer, not player-facing. Still, could be a useful DM tool.

March 26, 2021

Detail XII: A Case Study VI

Next up: lakes.

Lakes were complex to handle back in Detail VI: Lakes, but this project should be much simpler; again, I am placing them manually. Hex 15:

There are two important things to note here. One, I trace a river through the center of the lake to ensure that drainage is calculated properly. Second, the road hugs the river pretty nicely this time.

What I've got so far:

March 19, 2021

Detail XI: A Case Study V

Let us take stock of the map so far, with Hexes 24, 25, and 26.

The terrain blends very nicely. But these settlements need to be connected - at least, if the infrastructure exists to support them. The infrastructures are as follows: Hex 24 with 9, Hex 25 with 16, and Hex 26 with 7. Not a great deal of population here to maintain a good trail, but it's enough to at least have a road of some kind.

Road placement uses an A* algorithm with defined endpoints. In the cases here, the endpoints are the defined settlement hex and the edge exits; if no settlement exists I'll just define two exits.

The route weight is a bit complex but generally tries to pick the route with the most gradual elevation change. These being rather flat hexes, we'd expect a more or less straight road. There's some complexity when it comes to rivers. Unless a 20-hex has at least 12 points of infrastructure, it can't build a bridge or ferry. If it has less than this, it can't have a simple ford either if the river is larger than 2 Strahler points. Those rules yield the following network:

Pretty good. Nothing complex to overcome in this particular slice. We can get slightly more interesting results by adding a bit of a terrain penalty. Hex 26 is mostly marshy terrain - not necessarily impassible, but the road will definitely hug firmer terrain where available. So we'll add in a bit of a penalty for such.

Eh. Kind of interesting. The penalty weights probably need tweaking but I'll wait until I have more use cases.

March 17, 2021

Detail X: A Case Study IV

Under normal circumstances, I would place the rivers at this point. However, I am adding them by hand. Rivers are saved as a list of the hexes through which they flow, which makes this part more or less trivial. The Strahler numbers are saved for each in-flow hex and so the width of the river can be drawn accurately.

Hex 25; river in white temporarily for emphasis

The next step is determining which hexes are settled and which are wild. The infrastructure for Hex 25 is $I=16$. This isn't quite as simple as placing, for instance, 16 of 400 hexes as "settled." I reviewed the system for determining the relationship between infrastructure and number of settled hexes back in Detail III: Infrastructure. Briefly, each hex contributes to the total infrastructure based on the number of settled hexes that it itself borders.

There are then two broad scenarios for placing these hexes. The first is the case here, where I already know the "core" location of the main settlement within the hex. I want the other settled hexes to "cluster" around this one, so the base chance of settlement ($P_s = I/400$) is modified based on proximity to the constraints (there may be more than one in other cases): \[P_s = \left(\frac{I}{400}\right)^{|s - c|\cdot t}\], where $|s-c|$ is the distance between the 1-mile hex $s$ and the constraint $c$, and $t$ is a factor such that the sum of probabilities is equal to $I$. This added factor makes convergence a lot faster. Thanks to Scott for this idea!

For now I'm coding the settled hexes as grassland. The algorithm yields two Type VII hexes (1) and four Type VI hexes (2) for a total of $2\times1 + 4\times2 = 16 = I$. Perfect! In this case, they are all contiguous, but this need not be the case. Just luck of the draw and a consequence of the low overall infrastructure. 16 is really not very much at all.

The second scenario (and honestly, more common) is a 20-hex without a named settlement, and thus no specific constraint. Settled hexes will then tend to cluster around river features or roads. Therefore, we can do a similar adjustment with the distance to a random river or road:


However, most of the 20-hexes I'm looking at initially will have settlement features. This will come in handy later on.

March 15, 2021

Detail IX: A Case Study III

I previously covered terrain placement in Detail III and a bit in Detail IV. At the time, I was thinking of the effect that infrastructure had on the terrain, and so I used the terms somewhat interchangeably. The terrain type was simplified into "primary" and "secondary," but there are many cases where neighboring 20-hexes may have several different types between them. So the system needs to be able to take that into consideration.

At first, I just used a random choice between the available neighbor types, yielding something a bit like this:

This isn't really great, because the shape of the 20-hex is immediately identifiable.

To the surprise of no one, I'll turn to my old friend IDW. Normally, IDW is concerned with interpolating numerical values. Instead, for each hex, I'll determine the weights assigned for each potential terrain type. The 20-hex terrains are as follows:

Darker green is shortleaf pine (coded as c), lighter green is longleaf pine (n). Not a huge difference but adds some flavor. The green-brown is marshy terrain and not in view here. So we see that Hex 24 will be dominated by shortleaf pine and begin to transition to longleaf towards the south. Running the algorithm for the weights on a 1-hex near the bottom yields:

{'c': 1.3e-06, 'n': 1.9e-06}

So the longleaf pine is much more likely to be generated near the bottom. To use this in a random selector, I normalize these numbers to sum to unity.

{'c': 0.401, 'n': 0.599}

So there is about a 60% chance that that 1-hex will be longleaf as opposed to the dominate shortleaf.

Quite satisfying.

Detail VIII: A Case Study II

I had previously worked on height generation here: Detail I: One Mile Hexes. The underlying terrain is one of the more fundamental issues to tackle, as it determines road and river placement.

However, as we shall see, it's not of first priority for this particular Case Study. In the general case, the topography is important for placing rivers and other features; it'll be important here for roads, but rivers are all predetermined.

With that in mind, the altitudes of each 20-hex are defined as best I can. The 20-hex I'll work on first is designated No. 24. Its neighbors are 14, 15, 23, 25, 34, and 35. The heights for each of these must also be defined, or at least for most of them if available.

With these in hand, we can use IDW to get weights for each 1-hex based on the distance to the centers of the neighboring 20-hexes. The IDW output is heavily dependent on the number of neighbors $k$ and the exponent $x$ used to control the drop. The following graph shows the altitudes of a line of hexes across the middle of 24 and 25, with $k=2,\, x=2$.

Applied to all subhexes, the altitude is as follows (heights exaggerated for display, these low heights do not show up well in greyscale):

Some artifacts are still just barely visible, because $k=2$ means that only the central 20-hex and the closest neighbor will matter. Expanding that to $k=3, x=3$ may yield better results. There are still some artifacts, but these will probably get washed out when we add a little noise.

The amount of noise is determined by the topography type. Hex 24 is coded as "hills," and so the standard deviation of the gaussian function is set to $\sigma=150/6$. I'm still playing with those values: that is not a lot of height variation over 364 sq miles. Hex 25 has a topography of "plains," so the gaussian is contracted to $\sigma=25/6$.

 

That's not looking too bad. I considered a further "relaxation" step, where each hex would spill a bit of its height into its lowest neighbor. But that would require information we don't have in the self-contained system for the border hexes, and might lead to edge artifacts when 20-hexes are combined. So for now this seems good enough.

March 11, 2021

Detail VII: A Case Study I

The more work I have to get done in real life, the more my thoughts turn to working on The System. Particularly, I hadn't worked on the 1-mile generator in a while, and it was brought back to the front of my memory while proselytizing for the Higher Path recently. To try and refine a lot of that spaghetti, I decided to remake the area around my home into a (more) low-tech fantasy region.

Of course, Tao (Alexis) of the Higher Path bases his world on the late medieval/early Renaissance Old World. This side project will be similar, with the terrain and some of the demography based loosely in the "real world."

A major advantage of this project is that it makes the final product much more personal. At some level, a project based solely on imagined and random numbers has little soul - particularly in the development stage, where whole universes are destroyed and remade with a click. However, designing an alt-version of an area I'm intimately familiar with not only has soul, it has stakes. I've got real physical and spiritual blood in this land, and that naturally translates into greater care and eye for detail. If something is made up from whole cloth, there can be no accountability. These are places that I know personally - the decision to erase or augment them is felt more deeply.

To avoid totally doxxing myself (is anyone really anonymous online?), placenames will be concealed for now - and perhaps remade anyway to be more "fantasy."

I started with a 20-mile hex (20-hex hereafter) map of the whole State. Working from waterway and ecological maps, I assigned rivers and major vegetation types.

Normally, I would calculate hex-by-hex drainage for the river width. However, in the larger system I use, one 20-hex only drains to one other. In the real world, its commonplace for more than one river to flow through a single area of this size. It's over 364 square miles, of course. Instead, I used the Strahler number. The other advantage of using real waterways is that I can avoid the many issues I had with automatically placing rivers on the 1-hex maps. I had something that worked but it was kludgy, and hopefully I can return to it with more knowledge and a fresh brain in the future. Rivers can be manually input either way, and saved for future processing.

I'm a bit less strict on roads - since the modern era has roads criss-crossing every which way, I decided to preserve a handful of existing connections but largely rewrite the road network, and allow my algorithms to handle the internal road placement.

To determine settlement placement, I used only cities that were incorporated in the State by 1900. This cut the list down to 47. I use Alexis' infrastructure system to distribute infrastructure points, by dividing the 2010 population of each city by 10. This part made me very grateful for my code on the bigger map - doing this by hand was a chore. If I make any changes to the populations, I'm going to have to either do it all over again, or figure out how to apply the infrastructure algorithm I've already written to this subset of hexes.

But for now it is what it is. Road type and the presence of bridges or ferries (as opposed to simple fords) is determined by the infrastructure number, so its important to know.

My general plan for tackling and describing this project is as follows.

  • Quickly review the height algorithm. The area is best described as "flat and low," so we'll see if that generates any problems.
  • Refine the terrain assignment such that there is a "smooth" interpolation between 20-hexes of different terrain types. Like the height algorithm, discussed in previous posts, the ultimate goal here to create a distribution where the hex edge cannot readily be identified.
  • Because I'm working from a scale of 20 miles all the way down to 1 mile in a single step, I think I lose of some of the beauty of Alexis' working down to 6 miles and then to 2 miles. So I'll revisit the infrastructure assignment as well to try and beautify it. I'm not sure if the low infrastructure will help or hurt here but we'll see.
  • Once the settled/wilderness hexes are placed, roads and trails/tracks can be placed. There's always tweaking to be done when A* pathfinding is involved.
  • From there I'd like to consider types of features (of civilization) which could be placed based on waterways, settlement, and roads.
  • Lakes or coastlines. I may get to this one earlier; it's not as crucial since I'm manually placing these features.
As each piece of the puzzle is added, the gameability grows richer.

June 27, 2020

All Together Now

As I revisit my generation process from top to bottom (as I do every few quarters), it might be helpful to have a flowchart or at least a process list, both for my own reference and the general welfare of the public.
  1. Terrain generation, either from code or manually input (do not recommend)
  2. Derive currents by a) determining major trade currents at 0 and 45 latitudes, b) extending these currents and splitting them where they hit landforms, and c) interpolating these currents via IDW to make a nice smooth surface. I also have found that d) applying a Gaussian smooth filter to the results is even nicer.
  3. Assign sea surface temperature (SST) and measure the effect of the currents on that temperature: currents from the poles bringing cooler water down to the equator and vice versa.
  4. Generate areas of high and low pressure
  5. From the pressure map, obtain wind direction and speeds
  6. Determine the effect of topography on wind
  7. Apply base precipitation and use the on-shore winds to blow that moisture across the continents
  8. Use the coastal current temperatures and on-shore winds to determine areas of coastal climate influence
  9. Apply base temperature, then modify it according to the coastal climates
  10. Lapse the temperature up mountain slopes
  11. Run Koppen and Holdridge algorithms
At this point, social simulation can take over.

June 26, 2019

Detail VI: Lakes

Adding lakes was easy once I decided that I wasn't going to approach the beautiful detail of Undiscovered Worlds. All I need is a representation of a concept (which, at its heart, is the essence of a map anyway).

Low-quality lakes are easy to make. All I do is find where two rivers meet, then expand the lake around that point, flowing into any lower hexes. Usually, this means I end up with lots of long "lakes" which simply follow the river. This is a side effect of the terrain generation.


Still, small inconsistencies in the system are outweighed by its usefulness (and can always be addressed later). I can search over my 20-hex world map, find a place that looks interesting, and generate it quickly in detail.


One thing that inevitably comes to mind is just how much of this country is wild...but at the same time, there are a good number of scattered villages. How much conflict happens here between the humanoids and their encroaching civilization and the intelligent creatures who want to stay put? A good deal, I'll reckon. Not to mention, with a couple good scouts in your party, you might be able to hide from the law here for years. That's a lot of area to search.

I do have plans to implement a suggestion from Scott and blend the terrain edges together more smoothly.

Now if only I could get a proper SVG to PNG export...Inkscape is ok for some things but my installation has proved miserable when it comes to applying filters and blends.

June 19, 2019

Detail V | Roads VIII

Roads are easier than rivers because they do not shape the terrain they "flow" through as rivers do. I thought they would be more complicated but they turned out to be quite simple.

The river ingress and egress hexes are found by doing a transform on the character values of the strings of the names of the hexes. This gives a nice stochastic but repeatable location. For the roads, I simply reverse the inputs. Badabingbadaboom.

The roads (which are defined at the 20-hex level) enter the hex and make their way to the 1-hex with the highest infrastructure, which is located on the river and is assumed to be the settlement center. Where there are no roads, there are trails. Trails may or may not be well maintained, and they are not suitable for significant trade. But they allow transportation of goods and supplies to and from remote outposts such as mines which may not have access to a main trade road. Again, these trails all seek the assumed central hex.

Trails are also defined at the 20-hex level to connect settlements with low infrastructures. Generally speaking, a road will only occur through a 20-hex with $I\geq 50$. An exception is made if the road is being laid (and maintained) from capital to capital. Therefore, trails are used instead to connect lower $I$ settlements as well as provide access to hinterlands.

Darker hexes are less civilized, road in red

As a note on the trade system: only 20-hexes with a road can have a market. If your settlement has no market, you'll have to travel to find one. All goods produced in a 20-hex without a market must find their way down a trail to somewhere they can be sold. Therefore, for the purposes of the system, these goods are credited as being produced in the market settlement, even though their physical location might be different. My trade system engine assigns them to the market which is closest in the network.

This raises interesting gameplay situations. Most people in these remote locations would either make their own tools or carefully guard something they took a specific trip to buy. Very rarely would a merchant make their way down these dangerous and unfriendly trails to sell their wares. Plan accordingly.

June 11, 2019

Detail IV: Wilderness Colors

I've just been using a dark and light green to indicate wild and settled terrain. But I need to match that to the actual terrain colors from the 20-hex map.

I really like Welsh Piper's hex generation mechanism so I'll be borrowing some thoughts from here. For now, I'll just define a primary type, a secondary type, and a settled type.

Sometimes, settled will be the same color as unsettled. For example, the halflings, who live in icy terrain, wouldn't be able to grow cropland. In this case, I'll define something like settled = primary, where ice is primary and rock is secondary. So the settled areas are still delineated.

However, most of my test cases right now are in forested areas, so I'll concentrate on those. All those areas turn into grassland type when settled, at least in terms of display. I've also put a pattern over the wild 1-hexes to visually differentiate them if the secondary type is also grassland.

Blitpsy, population 4976, infrastructure 84

I also implemented a condition where the highest infrastructure hex must be on a river. This ensures that a settlement (when I get around to placing them) will always have access to the river.

South of Blitspy, starting to transition into grassland, some of which is settled and some which is not

Speaking of rivers and colors, I'm not sure the river stands out enough. I also kind of want to make the river a bit more fractalized, but I remember that I'm making a representation, a symbolic map, not a literal terrain map.

It does seem that the heightmap (which is shown by lightning the hex the higher you go) is almost invisible. That's fine; it'll mostly be important for determining the rivers and roads.

To do: roads, coastal 20-hexes, and river sources.

June 10, 2019

Detail III: Infrastructure

I have been thinking more about how to generate infrastructure for the detailed hexes. I've floated a few ideas here and there which seem to work well, but I thought of an interesting situation where the current system might give odd results.

To sum up, the infrastructure number of a 20-mile hex will indicate how many of the 400 1-mile hexes will be settled. For ease of experiment, let's assume that the 20-hex is forested, and that the settled 1-hexes are cleared land (whether for grazing animals or for houses, doesn't matter yet).

Previously, I was just using the infrastructure number as the number of settled 1-hexes, up to a maximum of 400, at which point the hex would be totally settled. But after reading this post several more times, I believe I can come up with a more robust system.

The problem is that infrastructure spread stops at the boundaries of a hegemony. This means there is a possibility of a hard edge where there is a totally settled 20-hex ($I\geq 400$) next to a relatively unsettled 20-hex (say, $I=10$). The whole point of the detailed 1-hex view is to give a smooth interpolation between discrete 20-hexes.

So what's the point?
The Tao (Alexis) uses 2-mile or 6-mile hexes, allowing a smoother interpolation because the detail is not as fine. With the 1-hex, there are 400 hexes that must be made to play nice. He gives a chart, however, detailing the behavior of each hex type and group depending on the number of wilderness hexes that surround it. 2-hexes which are completely settled (Type I) contribute 64 points of infrastructure to the total, and so on down the line. Read the links for more info, I won't rehash it here.

Since I'm not dealing with hex groups directly, I need a way to translate or spring-board off this existing system of ideas into my own map. I will define groups of 1-hexes in the following way: counting the 1-hex itself and the surrounding 6 hexes, how many are wild (of the 7 total)? This gives us 8 total types. Furthermore (and here's the distinctive key): these groups are not discrete. Each hex contributes not only to its own group type, but also those of its neighbors. In this way, the combinations are made even more unique...if it works.

TypeAdjacent SettledInfrastructure
I77
II66
III55
IV44
V33
VI22
VII11
VIII00

This has some interesting implications. Observe the minimum situation for a Type I hex:



The very presence of the Type I implies a further 6 Type IVs. That's a total of 31, if the above values are used.

Type II (total 24):


Type III (from here on out, I've tried to show the lowest configuration, there are others that could be higher, total 17):


Type IV (total 12):


Type V (total 7):


Type VI (total 4):


Type VII (total 1):



So how do I make this work? I'll start with a brute force approach.

It's very quick to run an algorithm over the 20-hex and get the total infrastructure number based on the 1-hexes. So what I'll do is gradually increase the number of settled 1-hexes and check the number. When I reach the target number, I'm done.

So far, this works pretty well.

$I=113$
Let's try it out for a stark difference. The top hex has $I=1000$, and the bottom two, $I=10$.


Not bad! The edge is still pretty hard...but not as hard. Furthermore, the individual hex groups could be identified for feature placement.

An issue with the infrastructure values for each hex type: The higher the numbers go, the fewer 1-hexes will end up on the final map. Earlier, I had defined 400 as the value of a filled 20-hex: but with the new system, a 20-hex must have $I=2268$. That's pretty high. But it does imply 346 sq. mi. of continuously occupied land (including farmland).

Finally, each iteration is totally random. I want a way to save them so if I come back later, or make a map for a game, I can reproduce it. Each configuration is extremely unique, and so I need a fingerprint. There are a couple of ways I can do it, but here's a very simple one.

First, I sort the hexes by their address, then assign 1 for settled and 0 for wilderness. Then I join all those numbers into a long binary string, padded to 400 zeros. For $I=1000$, that looks like this:
0b0000010000000000000010010011000100000000000000001000000000000000000001000000001001110000000000000101000000010000010000000000100000000010101010000100000010010000010001001000000000001000000011100000000000100000000001000100010010100000001101010000110010000000001000000010000000000000000010000100000000001000000000010000000000000000000010000000000100001000001001000100000000101000001011000100110000010000
But that's super long! So instead, I'll convert that number into hexadecimal. It's still long, but manageable.
0x400093100008000040270005010400802a840904480080e00200444a0350c802020000840080100000801082440282c4c10
I can save this fingerprint for use with this specific hex. When I'm recreating it, I can just pass the seed back to the generator. It's very simple. I think I should try and implement it for the height and river data, but that will require some extra thinking.

March 19, 2019

Detail II: Fresh Blood

I had begun working on detailed hex maps here.

It gave me no end of trouble. I wanted to be able to generate a single hex at a time, not the whole world, but there were so many continuity issues. So I took a page out of this book and began a different approach. I would lay down the rivers first, and only then would I generate terrain around it.


To generate the river path, I just use a random walk with a probability based on proximity to the goal (the river egress in red). This works out nice. But this is a flat hex. I had talked previously about using IDW to make a smooth interpolation between neighboring hexes, and adding noise. But I also want to ensure that the rivers have a constant downward slope.


Uh, oops. The river runs along a little ridge! Easy to fix. We just add height randomly until the conditions are satisfied that the river hexes are in a valley or trench.


Doing a few at a time and they line up nice! But the central river system isn't the only drainage I want to worry about - and I can use a bit of erosion like I've done for the world map. That's a quick calculation to figure out where everything should go...


Make the rivers display based on drainage-area:


Then erode. I'm not doing the full erosion code, just an average between the source and target hexes:


That looks pretty decent. What about the hex it drains into?


Whoa. Not, uh, what I expected. The river channels are all wrong. It's possible that there's something odd going on when the code tries to reconcile three input rivers. In many places, the river actually flows uphill! Not ideal. The brute force approach for the 2-river case simply is inadequate for a more complicated system. So then, we have $n$ inputs, with defined heights, $n-1$ connections at defined points, and a single exit, and every hex along the line must be lower than all that precede it.

This, by the way, is where my code starts to balloon into a spaghetti mess, as I desperately bug fix, welding on patches here and there. But eventually I get to a place that isn't totally borked. I still need to fix the way the drainage displays, however. Right now it's not continuous. I'll handle that in another post.


I also see effects from the master hex popping up - there is a clear cliff between the two here. This could ideally be avoided (it can be avoided using some other methods) but in this case I may just "relax" the edges towards the ideal (determined by IDW). Specifically, I'll lower the IDW exponent, making the edges smoother. Without the rivers, the effect is immediate.


But adding them causes a disturbance in the force. It turns out that the code for ensuring the valleys will eventually raise all the hexes...with a hard border at the master hex edge. With a little bit of retooling I can set that to start in the middle first, thus making it more likely that the edges will be relatively unadulterated.


Better. Not perfect, yet. But on the right track.


Eh. Great is the enemy of good and I'm tired of making these images tonight.