February 6, 2020

Elevation XVI: Clean Your Plate

I'm still not ready to do full tectonic movement simulations.

However, I think I can get some mileage out of using plates themselves to generate a better uplift map. The code for this is pretty simple, some general flood-fill algorithms along the fault lines:

In this model, each hex is only affected by the faults it actually borders:

This gives us some smooth transitions and some stark differences - which I feel effectively captures the action of subducting and overlapping plate faults.

In reality, the difference between ocean and land is not a unimodal curve. Earth differs in this regard because it has uniquely defined oceans in the first place.

However, no one is interested in fitting a curve to this specific shape. Until now.

This consists of a piecewise curve as:
h_1(x) = 55 \exp\left(-\frac{x}{0.65}\right)\textrm{ if }x >= 0
\] \[
h_2(x) = 55 \exp\left(\frac{x}{0.15}\right)\textrm{ if }x < 0
\] \[
h_3(x) = 15 \exp\left(-\left(\frac{x + 4.6}{1.5\sqrt{2}}\right)^2\right)\textrm{ if }x < 0
Where the full cumulative distribution is given by \[H(x) = \int_{-11}^x h_1(n) + h_2(n) + h_3(n)\textrm{ d}n\]

This is in units of 1000 km, which is not what I want. However, if I scale both the inputs and outputs to $[0,1]$, I get a non-linear I/O curve similar to a gamma correction.

Doesn't look quite how I wanted it. Lets do a simulation run.
Starting to see some of those shapes: but the distribution is not great. Most of the mountain chains are reasonably distributed except for the big pile in the middle.

I'll continue to work on this. I'm getting closer to what I want.

January 29, 2020

Elevation XV: From Square One

I wanted to take a break from prehistory stuff while I read up on hunter-gatherer sociology. I decided to revisit terrain generation.

My current terrain was created by drawing continents I liked, loosely matching them with tectonics, generating uplift values from that, then performing hydraulic erosion until I liked it. I'm still not ready to move into tectonic simulation, but I wanted some landforms that more closely mimicked the plates I'd drawn. I also took the opportunity to clean up the hydraulic erosion code.

It turns out, perhaps predictably, that the tectonic input map is perhaps the most important variable of all.
Fault map, showing convergent influence in red (with transform in green and divergent in blue)
I experimented with a variety of drop-off functions (Gaussians, other exponentials) to find a good way to find the closest fault (or most influential fault, by strength) to a given hex. This took a really long time, because I had to iterate over ~2000 fault hexes for each of the ~250000 world hexes. Some Poisson sampling helped, but even then, my uplift map ends up with circular ripples.
Uplift map: the Poisson disks are particularly obvious along the convergent equatorial fault
Where the uplift map is too patterned, the landforms tend to be also. So I tried adding in various kinds of warped and ridged noise to try and mix up those forms. One big problem with using noise of any kind is that it looks much too uniform at all scales. A quick look at Earth's coastline reveals a variety of types of "noisy" coastline, some smooth, some rough. So any kind of realistic noise function will need to approximate this variety. The hydraulic erosion discussed below can help with this. However, I still think more work is needed to obtain a better fault/uplift map from the input tectonics. One on-going issue is that the basic tectonic distribution persists from the time when I did most of my work by direct sketching. Maybe next week I'll work a bit on a generated (or at least computed) fault map to add more variety.

There are four basic processes which can alter the altitude of a hex: d$u$, the uplift of the plate; d$e$, the removal through erosion; d$s$, the deposition of transported sediment (from eroded material); d$c$, coastal erosion.

Although I had used a simplified version of this model before, I hadn't considered some practical limits:
  • A hex will stop eroding once it is completely "ground down," that is, its height is equal to the height of the hex to which it drains. At this point, water no longer flows. Hexes under sea-level do not erode with the same mechanism. For now, I've turned it off, but a possible alternative is a constant rate of erosion. As always, erosion rate is determined by how many hexes drain into the target.
  • On the other end, once a hex has been completely filled with sediment, it won't accept any more drainage. This one is a bit more complicated: I compare the height of the hex to the height of all other options that the source hex could use. Once the sediment makes the hex no longer the lowest of all the source's neighbors, drainage will instead flow into the new target. So it might not necessarily reach the height of the source.
  • Coastal erosion stops once the hex has been eroded under sea level. The erosion rate is faster the more sides are exposed to the ocean. I think it might be interesting to continue to transport and deposit that sediment elsewhere, but that would require the current model to run every iteration.
The coastlines look pretty good but the overall landforms indicate I need to do more work with tectonics and uplift

December 28, 2019

Prehistory I

I alluded to this mechanism in the previous post. I want to see how tribal hunter-gatherer societies, with small carrying capacities (around Dunbar's number) spread and grow through time without the added constraints of the full historical generator.

Each tribal polity can only occupy one hex at a time (not a strictly realistic assumption, but we can simply say that there are no other polities of note in the area). Carrying capacity $K$ decreases as resources in the hex are used up. Once $K$ converges with the population size, the tribe must either move or split to maintain balance. When a tribe leaves, the area begins to recover.

There are certain hexes with a high desirability which serve as generators: once a tribe reaches one, there's never any incentive to leave, and so more and more tribes are spun off as a result. When I add discoveries, these will become probable Ur-city locations.

The desirability issue is particularly obvious when a saturation point is reached. I've not yet added oceanic migration, so the tribes bounce around from place to place like so many gas molecules in a closed container.

(I feel compelled to point out that 1500 years is a pretty long time. In 519 AD, the Kingdom of Wessex was founded. In fantasy, we typically deal with deep-time related to people groups - thousand year reigns are not unusual. In real life, empires are generally much more temporary.)

This simulation progresses much faster than the "civilized" simulation, due to code rewrites and the fact that these tribes aren't doing much other than running around and eating all the wildlife.

In these first runs, I noticed that the raw desirability, which is the main selection factor, is far too high for areas that humans (the only race I'm working with for exploratory purposes) would normally avoid, such as deep tundra. So that will need to be fixed. I also want to add a mechanism for tribal warfare, if there is a some greener grass on the other side but it's occupied already.

December 12, 2019

History XXII: R&D

I have long been fascinated by the Worlds: History project. Go check it out.

One idea I'd like to steal gain inspiration from is the discovery system. People groups have chances to learn new technologies over time (or even lose them). It's quite comprehensive in design if not fully filled out.

I love this. Conceptually, it should synthesize with my existing tech tree, yielding at least the following benefits:
  1. Prehistory is now possible; Year 0 doesn't necessarily start with the first city, and every polity doesn't begin with a city/settlement.
  2. Tribes/polities should be able to migrate more rapidly, reaching more area of the planet's surface.
  3. Technology will be different in different areas. This already exists but is fairly deterministic, based on population density. If your density is X, then you have agriculture, for example. This is captured by the tech level.
The downsides? It's a whole 'nother branch of work for me in addition to all of the research I'm already doing. So it might be useful to build it as a toggled mod. Additionally, DrTardigrade is working on timescales many factors larger than mine.

November 13, 2019

History XXI: Cliodynamics IV

Of the tweaking of parameters there is no end.

I've had to suspend some of my own disbelief regarding civilization decay. For the most part, the simulation runs best if civilizations are allowed to grow to their fullest extent. Cliodynamic pressure can collapse a state but not (by itself) remove them from the map.

I also implemented a few changes for armed forces. Recall the distributions of the ages for each race. Each hegemony is then given a standing army based on the number of civilians between the ages of 15 and 50 (relative to human lifespan). This number is further reduced by 50% (since mostly males will fight), 10% (not all will be fit to fight), and 50% again (not all are willing). This article was helpful. Each year, the army is appreciated by new recruits and depreciated by those who die in battle. I'd like to find a way to depreciate retirees as well but without a cellular automation I'm not sure how just yet.

This significantly speeds up the battle simulation as a new military calculation is not required for each battle. In addition, armies can depreciate to the point where they are no longer viable. The amount of troops able to be concentrated at a single point of attack or defense is as follows: \[H = {A \over c} L(d)\], where $A$ is the army size, $c$ is the number of violent conflicts the hegemony is embroiled in, and $L(d)$ is a function of the distance $d$ between the capital and the point of battle. $L(d)$ encodes the army's logistical ability to supply distant points. Large armies can reach further but require additional support. \[L(d) = {1 \over \left({1 + {1 \over s}}\right)^d}\], where $s$ is the support parameter $s=2.82$.

One thing that becomes immediately apparent in the early years is the small troop sizes. A hegemony of approximately 10,000 people may only be able to support an army of 1000 or fewer (and that's at maximum $H$). In the first few hundred years, battle numbers are commonly in the dozens of troops, not thousands.

I tweaked some of the secession mechanics as well. I'd really like to implement some promotion and linearization but I have to think about how best to implement it and whether or not it'd be too computationally expensive. Currently there are still some issues where polities will either fracture into a billion competing hegemonies or glom together into massive, continent-spanning empires.

It's interesting that most polities haven't been able to stick around long enough to reach higher technologies. Most of them end up staying around Tech 6 or 7, which is barely past animal husbandry; a party in these areas would be hard pressed to find any kind of good gear or even wealth. But I suppose glory is always there for the taking.

October 17, 2019

History XX: Cliodynamics III

Continuing from here.

Recall these equations: \[\dot{\log N} = r_0 \log N \left(1 - {\log N \over k_\textrm{max} - c W}\right) - d \log N W\] \[\dot{\Xi} = \rho_0 \log N \left(1 - {\log N \over k_\textrm{max} - c W}\right) - b \log N\] \[\dot{W} = a \log N^2 - b W - \alpha \Xi\], where $N$ is the population, $\Xi$ is the power of the state, and $W$ is the intensity of warfare.

Turchin's original works don't make it very clear that these are log-scaled numbers. I decided to track this discretely for each individual city, so I imagine there will be a handful of second-order effects.

This does result in some pretty intense cycling.
$S$ in red, $A$ in blue
The total area fluctuates over about 200 years, while the $S$ lags that pattern slightly. I'm trying to think of a good way to tie $W$ or $\Xi$ to $S$, so that internal conflict will not arise when $S$ is high and collective solidarity is strong.

However, an error in the code (neglecting to restrict $k_\textrm{max} - c W$ to positive values) resulted in a situation where populations skyrocketed to billions of people in a single city.

Fixing that error introduced another artifact where it was extremely difficult for any significant hegemonies to arise and stabilize. The largest city topped out at less than 1500 inhabitants: barely a village.

The timescale is appropriate at about 200 years. But we want something more in terms of population, especially if we want the PCs to be able to have steel weapons and access to higher forms of magic such as wizardry and bardic training.

With some work, this could be tweaked to account for the longer lifespans of different races, if that's a thing in your game. If your elves live to 1000, their empires are more likely to last around 2000 years instead.

September 11, 2019

History XIX: Cliodynamics II

Continuing from here.

I'm still a little confused how Turchin's original spatial simulation could collapse at all, given an $S_\textrm{crit}=0.003$. Theoretically, this implies a frontier of 3 to a total area of 1000. My calculations indicate that this could be achieved by a circular area of radius 666 (oddly enough). Which is absolutely enormous. In his real-world simulations, he implements a restriction on what constitutes a frontier space, and this makes much more sense in terms of generating low $S$. Adjusting $S_\textrm{crit}$ doesn't help much: even at $S_\textrm{crit}=0.02$, the theoretical empire is three times the size of Europe before it undergoes spontaneous collapse.
A few more changes to implement before the next run:
  • Mountains and rivers make $S$ decay more slowly.
  • Cities can now send settlers as soon as they reach a population of $2P_0=300$.
  • However, only hexes which derive at least 25% of their infrastructure from the parent city can be settled. This forces a condition where capitals must be dependent on growth from their satellite hubs at a certain point.
Let's see how these do.
$S$ in red; $A$ in blue (hinterlands in light blue dashed, cities in darker blue dashed)
One interesting thing I noticed right away was that the population of the largest cities (and then the kingdoms) quickly stabilized. No fresh blood was available to work the fields, and all resources were efficiently distributed with no surplus. No new cities could form because of the rules listed above. In the absence of mechanisms to shake up the existing power structure, the hegemony remained in relative status. $S$ and $P$ fluctuated somewhat, based mostly in this case on fluctuations in the population of the largest city moving around a transition point.

Because my cities are grown from scratch, there is a practical limitation on how soon they can "meet" and create metaethnic frontiers. In almost all cases, a hegemony is surrounded not by other hegemonies, but by the wilderness, which should certainly provide enough danger to increase collective solidarity.

However, a random troll in the wilderness is not as dangerous to society as another hegemony who might be eyeing your infrastructure and resources. To this end, I can consider increasing $S\to0.25$ or a similar value in cases where the frontier is not a metaethnic border but a wilderness border.

How does that help?

Better! Interesting that $S$ begins to increase as the total $A$ does - it looks like this is when Mengj starts to bump up against other competing hegemonies.

More things to try:

September 9, 2019

History XVIII: Cliodynamics I

I have recently been reading up on cliodynamics, which is the application of mathematical models to historical population sociodynamics. If this sounds familiar, that's because it's exactly what I've been doing for the last few months. So it's good to put a name on it.

One thing that particularly interests me is the theory of social collapse. This is something that's been missing from my own work, try as I might. I think that cliodynamics might be able to help me answer this question.

In one of his models, Peter Turchin defines a measure called asabiya, which is an Arabic term implying social cohesion. Turchin applies this in a simulation by logistically raising the asabiya of a hinterland/border cell to 1, while internal cells exponentially decay to 0. If the average asabiya of a whole hegemony reaches a critical value, the entire thing collapses. \[S_{t+1} = S_t + r_0 S_ t (1 - S_t)\] \[S_{t+1} = S_t - \delta S_t\]
The effect of this is that empires should only last about 200 years on median, which is much closer to the real world than the massive empires I've been dealing with. Once a critical mass is reached, my empires last...forever. There's no real pressure to collapse, barring a random extinction event such as a plague.

Another paper in the same vein explores secession and hierarchy elements in a manner that is very similar to mine. So I'm happy to synthesize it into my body of knowledge.

However, I still need to account for the size to asabiya feedback mechanism. In all these models, the size of the polity $A(t)$ is part of a larger model which is affected by $S(t)$ (the asabiya), or even the metaasabiya $R(t)$. My own $A(t)$ is determined by the growth of cities and their infrastructure reach.

Therefore, I'm going to pull in another model developed by Turchin to correlate population $N$, state resources $S$, and internal warfare $W$. This provides a way to "hook into" the $K$ carrying capacity mechanism and thereby connect the two models. In particular, we have: \[\dot{N} = r_0 N \left(1 - {N \over k_\textrm{max} - c W}\right) - d N W\] \[\dot{S} = \rho_0 N \left(1 - {N \over k_\textrm{max} - c W}\right) - b N\] \[\dot{W} = a N^2 - b W - \alpha S\]
So as population $N$ varies, it will affect total area $A$ and therefore $S$ (I don't know why he uses the same variable for asabiya and state resources).

The question is how to discretize this function. The model as given is a hegemony/polity-level equation, governing the total state. Therefore, I have to scale W to the individual city:\[\dot{N_i} = r_0 N_i \left(1 - {N_i \over k_{i,\textrm{max}} - c W {N_i\over\sum_j N_j}}\right) - d N_i W {N_i\over\sum_j N_j}\]

I also don't have to collapse the entire hegemony at once if the critical point $S_{crit}$ is reached. Normally, secession is controlled by a loyalty variable. I'll still maintain this, but I'll also make secession likely to happen if the average asabiya is below the critical point, regardless of loyalty score. This will cause quick collapse if the empire overextends itself but also provides an opportunity for it to "recover" after that collapse.

First: some testing of the basic asabiya concept. I'll run the model as normal, while keeping track of what the asabiya should be. Then examine which hegemonies should have collapsed. The only change I'll make to the normal model is to suppress other collapsing mechanisms such as surrender and secession.

Initially, I thought that I should use the area-dependent asabiya model: \[S_{t+1} = S_t + r_0 \left(1 - {A \over 2 b}\right) S_ t (1 - S_t)\] to account for the size of the polity. This proved to a very strong feedback effect to the point where $S$ decayed to its end-state nearly immediately.

Examining the largest hegemony (the Thav empire) using the non-area-dependent model:
S (red), A (blue): over time
It quickly becomes clear that there is an effect introduced by Turchin's simulation space which accelerates empire demise. Here, the asabiya of this large empire does not drop even close to the $S_\textrm{crit}=0.003$ value which provides Turchin with such historical variation. I believe this to be due to a few factors.

In these early stages of implementation, there is still no feedback from $S\to A$. Therefore, there can be no collapsing mechanism as $S$ enters a positive (and mutually destructive) feedback loop. There are a couple of places I can connect this loop. The first is in terms of warfare escalation. If the power differential between two hegemonies is above a threshold, it becomes more likely that the stronger will invade. Individual hex power is defined by the following equation: \[P = A \bar S \exp(-d/h)\], where $d$ is the distance from the capital and $h$ is a drop-off factor usually equal to 2. We can average this for every hex in the hegemony to determine the $\bar P$ for the hegemony. In the case of Thav above, $\bar P = 4.72036$. This will also be interesting to examine over time to see if it's useful anywhere else.

The largest hegemony during this 500-year run is the Winan empire:

The jump in $A$ appears to be directly attributable to the expansion mechanic kicking in around 335. All of a sudden, the few (4) cities that Winan has conquered begin pumping out colony cities. This dramatically increases the reach of the empire, which has a detrimental effect on $S$. From this and the Thav simulation we can see that it takes between 300-400 years for a city to grow to expansion size (under the current rules).

Of course, there is no law in the real world that demands that settlements refuse to send out settlers unless they have more than 5000 people. But these rules are justified elsewhere on this blog.

Looking at overall power:

There's a slight bump during the initial expansive "golden age", but this quickly returns to what appears to be a pretty steady number. The interesting thing is that $\bar P$ appears to be steady regardless of the continued movement of $S$ or $A$.

The other place is in the infrastructure spread calculation. Remember that as cities grow, they spread their influence, creating new borderlands for the empire (and eventually butting heads with other empires). What if this growth (already affected by terrain) were also affected by the power of the city in question? More powerful cities could spread their influence further and vice versa. In addition, when Turchin applies this model to real-world conditions, he imposes an additional constraint that regions must experience a certain amount of cultural conflict to be considered true "frontiers." For example, linguistic and religious borders contributed to this intensity score. That shouldn't be terribly difficult to implement. I'll try these next time.

Through all this, I feel very much as if I'm exploring an actual history. Although it's shaped by my own decisions and preconditions, on net it's stochastic to feel alien. And that's pretty cool.

August 9, 2019

History XVII: Cradle of Civilizations

I have been working mostly on updates to the code. Now it runs a little smoother.

To this point, I've been randomly placing cities across the map. Because each race has a highly preferred climate, this usually means that, e.g., elven cities will all end up in roughly the same place. But occasionally there will be a city placed far across the map, on the other side of the world.

I'm not, for the moment, interested in creating a grand mythology. They're cool, and maybe I'll work on some lore at some point, but for now it's irrelevant. However, I do wonder if a single-origin point for each race wouldn't give even more verisimilitude.

The first settlement (for each race) will be randomly placed. Each subsequent city must then be a specific distance from an existing settlement. This can model expansion from a single-origin point.

If the initial city is not in an optimally desirable location, then migration should naturally occur up towards those optimal locations.

Seems good-ish so far. I think the city generation ought to be a bit higher to account for the additional constraints.With this model, none of the races would have met another "civilized" race yet after 1200 years.

Whether that's likely or not is up to the discretion of the reader.

Stranger Railroads


Yes, yes, I know that Stranger Things is responsible for "helping revive" mainstream interest in D&D.

Who cares?

The people making money off of D&D, of course. The hobby is not significantly enriched by this.

In fact, it's hurt.

This is the same effect that brought us the vapidity of 5th edition, reinforced by high budget dramatic productions which pretend to play D&D.

Stranger Things S3 is no different. Its heavy-handed lip service sends the message that this way to "play" is not only acceptable, but desirable.

All season long, Will wants to play D&D with his friends, who are increasingly mired with girl-problems. When he finally gets his board and story set up, he is able to force them to sit at the table. Conveniently hidden from accountability behind his screen, he railroads their characters through his plot with the subtlety of John Henry's hammer.

In the Stranger Things game philosophy, the players must dance to the DM's tune. There is no opportunity for the players to make choices. Only false choices can be presented, otherwise the "game" (of course, it's not really a game) is ruined.

Fed up, Mike makes a choice. And it's a good one! To save the village (why do they care) and become heroes (which, of course, is the only possible outcome of this so-called game), they must defeat the zombies. Mike decides that the best option is to ignite the room they are in, killing the party but also the zombies and living on forever as heroes.

Of course, in the grand scheme of the season, this is a signpost to the climatic scene. But more importantly, it's a deviation from the Supreme Overload Will's script. "You can't do that!" he whines. Why not? It's the only meaningful choice the players have made!

Without these meaningful choices, the game is not a game. It's just a series of guesses to see which way the DM wants the party to go; and never fear, you can't guess wrong. Sure, you have "agency" as long as you select from the following pre-approved list of actions.

Don't worry, you can't make the wrong choice, because all roads lead to the same point.

Which leads me to ask, what's the point?