October 29, 2018

Elevation X: Once More with Filling

I have been working more on my terrain generation, and it's looking better if not entirely Earth-like. At some point, it will have to be "good enough." I made a change to the code which fixed some of the deposition problems, and definitely fixed the problem where the terrain would reach an equilibrium height (which was usually very low, like 3000 ft).

Of course, there are still problems with endorheic basins, and equilibrium. Eventually (around 22,000 ft), I stopped the generator and made some "manual" adjustments, which usually involves adding in some Perlin noise (or other types), running a few erosion cycles, and then scaling all the heights to [1, 25599] ft.

I also made some changes to the SVG code and got rid of the unsightly hex borders, so everything looks a little smoother now. I am considering writing some code to illustrate the height a little better, maybe one of the classic green-brown heightmaps. On a b/w map, anything under 6000 ft is basically not visible.

Next, I want to revisit the wind algorithm. The precipitation model is good, but the winds blow in odd directions onto the coast, and I think there is some weirdness going on there. There is too much moisture in some places, and not enough in others, so the Koppen map ends up evenly divided between utter desert and hostile rainforest. There's not nearly enough of Koppen class C, which is the most desirable (imho) for human habitation.

(what sorts of races prefer other climates? food for thought)

October 26, 2018

Resources XI: Silver Mining


The primary ore of silver (at least in ancient times and for my purposes) is galena. Galena is also a lead ore, and produces about 1-2% of silver. To my geologically untrained eye, its occurrence is more or less random, except for a relationship with chalcopyrite.

Because I'm itching to start playing, I may skip over silver (and gold) production in the trade system. I'll still work on them, of course, but I might use "silver" directly (as a raw resource) rather than bother to work out the details of production.

That brings to mind an interesting question about coinage. This would be restricted to an administrative center or licensed foundry, and while raw nuggets of metal could certainly be used in frontier towns, a gold mine does not necessarily equate to a flourishing coinage economy. The bullion has to make its way down to the foundry (if its located elsewhere) to be converted to spendable coinage appropriate to the realm. So that might be interesting to study later on, if I include foreign currencies rather than a flat "gp/sp/cp" across the globe. Unrealistic, I know, but gameable. I'm not a monster.

October 19, 2018

Detail I: One Mile Hexes

Since I'm not even close to being done with my world map, I decided to tackle the 1 mile hexes instead. (In my defense, the simulation I'm running now is taking a really long time to finish).

This is really complex project. The main issue is getting each chunk of 1hexes to match with the 20hex from the world map, in terms of the connective data like river flow, terrain at the edges, etc.

Each 20hex is made up of 400 1hexes. Getting raw heighmaps is easy enough. I just use an inverse distance weighting between all of the 20hex neighbors, then add noise until the total average is reasonably close to the 20hex height average.

Hex 13 from the Demoland Master Map
Then I can figure out drainage and streams (not really rivers at this point) using similar code for the world map - water flows downhill.

Thats a lot of basins! I would like most of them to pull together to a single exit hex. Each hex always has 0 or 1 river exits. Hex 13 happens to not have any rivers flowing into it; I picked it because I only want to worry about one new issue at a time. With a little playing around with the heights, I can get the following:

However, it takes a few minutes to run this particular code: I'll adjust the height of a basin, check the drainage pattern, and repeat until I've worked that number down to a point I like. The result looks good, but ends up messing with the average value too much. Sometimes, it's almost impossible to find a good network.

When rivers flow in and out, it gets even more complicated. I want to be able to put these together like puzzle pieces, so that means saving the entrance and exit hexes so I can use them again later if I want. But to ensure a consistent flow, I have to cheat again.

Hex 14, river sizes exaggerated
Right now I think I have a problem with my A* algorithm, which is supposed to find the best downhill path from the blue (entrance) to the red (exit). It works, but I think I can do better.

Explicitly connecting the drainage hexes together like this might actually end up being better in the long run; better than the height adjustment from above. I'd like to add some of the erosion code (or something similar) to give more realistic topography.

Why is there  a little break there??

So I need to fix my A* and work on erosion. I wonder if a simple flood fill path-finder wouldn't work better for connecting source and drain. It'd be less efficient, but then again, a winding path would look much better.

I'll probably put this back on the shelf and tackle the remaining issues with the world map generator. However, that's nearing a stage where it'll mostly be research for the trade system, at least to a point where I can get a game up and running.

October 8, 2018

Koppen with Smoothing

I kinda like this. I've also tweaked the temperature distribution a bit.

October 5, 2018

More Koppen

Testing out the new wind algorithm. With a perfectly flat world, we get the following Koppen distribution.

It's interesting that Af (tropical forest) butts right up against Cfa (temperate). This has to do with the heavy rain sweeping across the Af areas - on the border with Cfa, the temperature drops (and changes the category) but the precipitation does not change in kind. This leads to an odd boundary, but it's not unheard of in the wild. I'd just like to see a few more A categories, so I need to tweak the amount of precipitation.

I also am considering the mode smoothing discussed here. I think that might help the artistic effect at least.

October 3, 2018

Citizens of Demoland

Let's generate a few people to see how well the system is working. I'll use the Markov generator for names, and the probability calculators to generate properties. No classes yet, and the age doesn't account for the racial differences I plan.
  • Cadein, a 46 year old female human of level 0
  • Siâm, a 22 year old male human of level 0
  • Trynn, a 33 year old female human of level 1
  • Estan, a 66 year old female human of level 0
  • Refa, a 21 year old female human of level 0
  • Browrt, a 72 year old female human of level 0
  • Suli, a 71 year old female human of level 0
  • Siân, a 63 year old female human of level 2
  • Lynn, a 71 year old female human of level 0
  • Ifre, a 44 year old male human of level 0
  • Elyn, a 23 year old female human of level 0
  • Beth, a 36 year old female human of level 0
  • Wilym, a 47 year old male human of level 1
  • Arai, a 40 year old male elf of level 4
  • Treddun, a 31 year old male human of level 0
  • Gwalled, a 21 year old male human of level 1
  • Olina, a 37 year old female human of level 0
  • Jestaffith, a 27 year old male human of level 1
Arai is an elf of some distinction. Assuming the players are lower than level 4, they'd probably have to talk to Siân, and she could either make an introduction to Arai or find someone who could. In a martial culture (as this is D&D), combative prowess fits in rather nicely with social order - even in a "civilized" area. Perhaps he is even an artisan of some kind.

Gwalled is an up-and-comer. Certainly someone to keep an eye on, or who might be looking to sharpen his natural talent as a man-at-arms for the party. Trynn and Jestaffith are also not far behind.

Browrt, Suli, and Lynn have given their lives in labor with little to show for it.

The name generator also gave me these gems, which I assume sounds like someone on Pobol y Cwm having a stroke:

  • Llteigraidrynwenoladei
  • Gawalltegwen
  • Emlynervieulurice
  • Efoliesylynwenn
  • Neiloyddaffithan
  • Terchtonwynwynna
  • Gaendandawaladeweniforwen
  • Maromnellynnallyn
Obviously I need to fix the maximum length specification.

October 1, 2018

Demographics V: Battle of the Bulge

I really should have added this to the last post, but I'm kinda locked into my 3-times-a-week posting schedule, and I'm running dry on content while I work out some of the terrain issues. So the 2 real people and the 40 bots that read my page will just have to suffer through this journalistic malpractice.

Anyway, I presented a logistic model to describe the age distribution of a city. In reality, not every place/race will have a bottom heavy pyramid, which is indicative of rapid growth. Low growth pyramids (like many countries today) have square shaped "pyramids," and negative growth shows a bulge.

I wanted to replicate this better. At first, I thought I could just multiply by a shape function to force the distribution to be like I wanted, but there were too many challenges. Eventually, I settled on using polynomials.

But not just any polynomials. To ensure smoothness, I want to use Bezier curves.

Only, Bezier curves are parametric, and I want a function such that $B(x) = y$. Hm. After some searching, I found a way to interpolate between given points as long as they're evenly spaced, using Bernstein polynomials:
\[B^n_k (x) = \sum_{k=0}^n {n \choose k} t^k (1 - t)^{n-k}\]
This polynomial is used to approximate the curve like so, given sets of points $\lbrace x_k, y_k\rbrace$:
\[y(x) = \sum_{k=0}^n y_k B^n_k \left({x - \textrm{min}(X) \over \textrm{max}(X) - \textrm{min}(X)}\right)\]

For now, I'm using $n=5$, because I want 6 total points. This will allow 3 control nodes to restrict the shape of the curve.

High growth
Low growth


It's still not perfect. Nothing ever is. But it should give more realistic results. Given a growth rate regime, I can add some noise to the control points to generate gently varying curves. This takes a little more time to run through in Python than the level generation does, but that's ok. Most of this type of thing can be run on request when the party arrives in a town.

The players will never see it. But I'll know.

Also, I guess I shouldn't be surprised that no one else (that I've found) has worked on stuff like this for their games. Where are the designers? Or are they just worried about the art in their next Point A to Point B splat book adventure?