March 29, 2019

Cities III: Toponymy

My generated names are too similar and there is no delineation between personal names and place names. What I'd like is a system to assign toponyms that are similar between settlements. This will aid player recognition (ha, who am I kidding) in terms of culture and personal names. Think, for example, the cities of Leningrad or Cardiff share elements with other cities in those countries, based on the toponyms -grad (place) and caer- (fort). Hence, it's unlikely that you would mistake, upon first hearing, that Petrograd and Caernarfon were personal names.

I'd be remiss if I did not mention this excellent series on naming places, over on Here Dragons Abound. This is a constant source of inspiration.

Since I have no database of names in real use, how do I find these toponyms? And how do I ensure they are consistently applied?

I'll start simply, by assuming that the name is terrain independent: no special convention for hills or mountains or valleys (Cwm Rhondda).

It should be fairly short, 4-5 letters.

It could be either a prefix or a post fix. But that'll need to be consistent.

Not every town will have the same version of the toponym. See the example above of Cardiff and Caernarfon. There are a couple of ways to do this (I might implement lenition rules in the future), but I think the easiest thing to do for now is to generate a new toponym that is within a threshold Levenshtein distance from an existing toponym. This'll account for differences in language and culture.

I won't do it by nation/hegemony (which I have yet to implement, coming soon with the political rules), I'll give each city a chance to take on a toponym similar or the same as that of the city which spawned it (I've been calling these "mother cities"). For now, I only track the mother city, but when I break the peace and install war/rebellion rules, the mother city may be in a different hegemony (even now it can be destroyed and no longer exist, but its children live on). This will preserve culture across national boundaries.

So when a city is being assigned a name, it will have a 20% chance of being assigned one of the current toponyms from its mother city's list. There is a 20% chance it will take a similar toponym, and 10% that it will create an entirely new one (which is then added to the mother's list). This will allow a bit of linguistic drift and everything won't be perfectly uniform.

Since the toponyms will be generated from the racial Markov chains, there should be similarities (but not replication) between, e.g., dwarfs and dwarfs, or orcs and orcs. A savvy player could perhaps pay attention to a town's name and discern some of the history and culture of that place.

Of course, in real history, settlement names change all the time for many reasons. But for now I'll keep names static. One thing at a time.

Let's try it out.

Mother city: Iowendawn, population 898, founded 3183 (human)

Toponyms: Umieu-, Teg-, Cos-
  • Uedestkamtowty, population 395, founded 3608
  • Umieuzowenki, population 1964, founded 3550
  • Umieuronwe, population 16079, founded 3178
  • Umieuaenkilbede, population 9566, founded 3275
  • Umieutamtopry, population 1254, founded 3520
  • Umieuprach, population 1503, founded 3601
  • Unostangel, population 1414, founded 3549
  • Umieudesogon, population 12765, founded 3157
  • Ukopach, population 1899, founded 3563
  • Tegcorwe, population 1799, founded 3092
  • Cosmadei, population 3411, founded 3549
  • Tegmorwen, population 229, founded 3405
  • Dustrys, population 333, founded 3602
It's not perfect, but I like it. It does expose a problem in that the names are generally very long, and the addition of a toponym makes it even worse. We want players to be able to say the names, after all (with a minimum of giggling). The answer lies in the Big Phoney package, which uses neural networks to categorize different syllables. It seems to work pretty well, translating the word into ARPABET:

Umieuaenkilbede $\rightarrow$ Y UW2 M UW0 AA1 NG K IH0 L B EH2 D $\rightarrow$ Yoom-yoo-ang-kil-behd $\rightarrow$ /juˌmuɑˈŋkɪlbɛˌd/

Uedestkamtowty $\rightarrow$ Y UW2 D IH0 S T K AE1 M T OW0 T IY0 $\rightarrow$ Yoo-dist-kam-toa-tea $\rightarrow$ /juˌdɪstkæˈmtoʊti/

I can use this to limit the number of syllables a word has, for ease of pronunciation. I have not been able to find an easy converter between ARPABET and IPA but that is not a priority (update: this package works). However, it's not terribly fast, so I may need to explore a less robust method. I could limit the overall word length to something more manageable, and use this to produce pronunciation guides for players.

March 20, 2019

Resources XX: Old Makes Way for the New

Not all resources can be extracted more efficiently or in greater quantities as local population increases.

In particular, raw agricultural resources will be pushed out of the way by the city.

Hence, I need a signal to indicate when a good is inversely proportional to local population (or infrastructure, or population density, etc).

I'll call this "Type A."

Type A goods, so far, are just those which require physical land to function, which is agricultural resources. Of course, we can think of cases where, say, a strip mine grows in area, but since this is only a single type of mine, we'll leave it alone for now.

The Type A goods (in the system so far) are:

commodity
wood
wheat
maize
oats
barley
cassava
rice

Inverting these numbers requires knowing (or guessing) the highest infrastructure. Although the infrastructure can rise quite a bit (the maximum I have so far is 2742), anything higher than 400 represents a fully settled hex. And indeed, there are considerations here that I might explore later: as the amount of available area grows, so does the number of hands necessary to farm that land. So there is inevitably a trade-off in how much you are able to produce.

All of the Type A goods are also Tech-6 (T-6). This means that only a single point of infrastructure is necessary to begin producing them. I think the best system as a first approximation is that of diminishing returns. A T-7 or T-8 hex may have more hands available, but each additional level reduces the efficiency of production. This is an easy way to account for the reduced amount of farmland or harvestable forest. If we consider that the production per person $p$ drops as the infrastructure $I$ increases $1\to400$, we then see that $p$ is related to base production $p_0$ by \[p = {p_0 \over 399}\left(400 - I\right)\]. I'll have to run some more tests and see how this actually works in practice, but I feel it's a reasonable start.

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.

March 18, 2019

Resources XIX: Stage 0 Materials

Here are the raw resources I've researched so far.

But I have an interesting problem. A lot of these are ores with modern scientific names. That presents an odd immersion-breaker; a dwarf trader would (perhaps) not carry hematite. He'd carry red-iron, or something. However, I don't want to fall into the trap of making up too many names, while balancing that with playability.


For certain minerals, if only a few places produced it, it would make sense to call it after the producing nation or city. A good example is psilomelane, a manganese ore. Only 141 cities produce it. Of these, 10 cities control 50% of the total production: Nabib, Ashdinjem, Cusraq, Lahmanazlib, Rogan, Malia, Siaglen, Silil, Qoloob, and Crewnevanch. All great names to draw from: nabibite, Cusraq iron, qolooban. In an obscure, independent world, those would work great! Psilomelane is, after all, a Greek phrase meaning smooth-black, from the appearance of the stone. So all these things must be taken into account in order to present a consistent and immersive world to player. Having to memorize "qolooban" if you want to supply your blacksmithery is not terribly immersive.

But nonetheless, I will try.

commodity unit tech level occurrence unit/ref ref/acre acre/pop ref/1000 common
wood bd.ft 6 7000000 0.0029 100
goethite lb 7 0.0446 93750 6.311 bog-iron
limonite lb 7 0.0775 93750 157.8557 brown-iron
umber lb 7 0.0194 125000000 9.697
magnetite lb 8 0.0963 93750 0.2524
hematite lb 9 0.1008 93750 0.0101 red-iron
silver oz 8 0.0334 15000 3.8788
wheat lb 6 2500000 0.0001 100
maize lb 6 3528000 0.0001 500
oats lb 6 2500000 0.0007 1
gold oz 6 0.0035 1500 1.7455
barley lb 6 2500000 0.0001 1000
cassava lb 6 52083 0.0011 100
rice lb 6 62500 0.0001 100
chalcopyrite lb 6 0.1699 223404 24.4156 goldstone
azurite lb 7 0.034 47872 113.9394 bluestone
malachite lb 7 0.0777 103723 52.5874 greenstone
clay lb 6 0.0775 937500 157.8557
coal lb 9 0.11 9000000 0.1818
psilomelane lb 7 0.0123 23438 0.9697 bubblestone
pyrolusite lb 7 0.0201 23438 0.9697 blackstone

March 12, 2019

Trade III: You Have Something I Want

Time to put everything together and generate a trade network.

The network graph itself is created from the roads, seaways, and rivers. Right now, I have about 10 thousand separate resource-producing settlements, and about 20 thousand roads connecting them.

The problem I am running into is that networkx is pretty slow with this many edges (about 15,000 nodes and twice as many edges). But I found that pre-processing the trade distances makes this much faster. For instance, two cities may be connected by more than one route, even if its just a road and a navigable river. Although local circumstances may require trade to flow along a non-optimal route (the road is blocked, the river is too choppy), the vast majority of trade will occur in aggregate along the shortest route. Therefore, non-optimal routes are irrelevant to the market network; many of those 30,000 edges will never be used.

The process to assign a resource reference is as follows:
  • From the list of available raw resources for a given city hex, select those which the current infrastructure level will support
  • Determine the reference amount that the city can produce
  • Calculate the gold reference for every hex using the system described here
  • Calculate the reference costs for each raw resource
  • Calculate the labor costs for each raw resource. Really this is more of a measure of the amount of references available, and not the cost directly, but I can define a base cost just like any other material good and get, for example, the daily income of an ironworker
  • Calculate the costs for each manufactured commodity. Because a given good might depend on a number of other manufactured goods, I have to make sure that I do them in the right order. To this end, I define goods in stages. Hematite, as a raw resource, is a Stage 0 good. Iron ore is made from Hematite, and is thus a Stage 1 good. So all Stage 0 goods must be assigned and priced before the Stage 1 goods can be calculated. For every multi-stage good, the overall Stage must be $n+1$ where $n$ is the highest Stage used in the recipe
Manufactured goods are defined through recipes. This takes a lot of guesswork sometimes. For example:
'iron (ore)': {'min1': {'charcoal': 1; 'coal': 2};
'min2': {'goethite': 1.6; 'limonite': 1.8; 'magnetite': 1.4; 'hematite': 1.4};
'labor': 'ironsmith'}
This recipe for general iron ore says that you will need 1 lb of charcoal, or 2 lb of coal (whichever is cheaper), and the cheapest ore between 1.6 lb of goethite, 1.8 lb of limonite, 1.4 lb of magnetite, or 1.4 lb of hematite. These raw materials are then shaped by an ironsmith to produce 1 lb of iron ore.

This system is nicely versatile.

One snag that I've run into is the presence of trade networks without access to any precious metals at all, yet perhaps quite robust industry. There are a few solutions to this.
  1. Remove these networks entirely. No precious metal economy, no economy.
  2. Structure these to work as barter economies
  3. Use another substance as the practical fiat currency
  4. Assign a small amount of gold to the economy to lubricate it
2 and 3 are the most likely, historically speaking. But they also require the most work. The easiest for now is just 1. I think I'll redo a long history once I have a good number of raw resources defined. That should take care of most of these outposts. Most of them are small isolated mountain towns, which makes sense that they might not have structured economies, but there are several large cities in there (around 80k), which starts to make less sense in my mind.

Full trade network (sea routes not yet added), after many attempts to use force-directed layout

March 6, 2019

Resources XVIII: Rebirth

It's time to take a break from history generation to discuss a bit of resource placement. I'd like to see how the models I have currently will perform when applied to a larger area, and then dive into more of the raw materials. These are what I need to create enough of a framework to start running games again - any updates to the system are fine as long as they are to processed materials, not raw resources. Those need to be in place (or at least a minimum working set of them).

To do this, I needed to revisit some of the old numbers and make sure they make sense.

Surprise! Basically none of them do. So I reorganized my workflow.

First, I look around for production numbers for both ancient and modern times. I then compare these to a known quantity, particularly one that I'm holding fixed. I can use pricing ratios to make an educated guess as to the reference amounts and the production numbers, assuming a 500:1 improvement since the Industrial Revolution.

For example, I know that in Roman Britain, silver production was about 200 tons, gold around 9 tons, and copper around 15000 tons. This implies that for equivalent amounts of labor, I can get 75x more copper than silver, and 20x more silver than gold.

Similarly, one region in ancient Greece had a working force of 11,000 and output 200 tons of silver annually. If the ratio of gold to silver prices is about 10 (it fluctuates wildly, of course, but was around 10 in antiquity), and 1 reference of gold is equal to 1500 oz, then a reference of silver is about 15000 oz. Since the ratio of silver to copper is about 20, now I know the reference amounts and production quantities for gold, copper, and silver. Some research yields occurrence amounts, and generally, this research process must differ between categories. Minerals are easy to guess - but agriculture is not. Thankfully, the Romans took good notes about how much material they produced, giving a reference point for how much a technomagically minded society could produce if they put their minds to it.

This is not a terribly academic process, but it's a process, and it's based on numbers, regardless of realism. There are a lot of ways to tackle this problem, but I'll see if this one works for me.

I also need a mechanism for scoping this work. I want to get this into a playable state so I can start running games again, but if I spend years and years researching every possible item on the table, that's foolish. I think I might begin with the equipment lists in the PHB (poorly designed though they are) and develop the items that players might want as basics (with modification, of course). Then, if they want an additional item, it is more or less trivial to add (assuming that the raw materials and industries are already defined).

One thing I am assuming is that magic has little effect on overall production. Of course, this would not be strictly true. Any wizard, for example, smart enough to build traps in his dungeon would be smart enough to put that brain to work building an industrial production facility, putting all the local glassmakers out of business and declaring economic victory over the entire trade network. So there are some sociological questions that arise when considering why magic is not prevalent in the economy. Perhaps it is too rare. Perhaps the magical portion of the population (already a higher slice of the social strata) has bigger things of concern. Lots to think about.

But I'm rambling now, so I'll stop. Plenty to come soon.

March 4, 2019

Roads VII: Row, Boys, Row

What I did with the roads, I now do with the seaways (I'm calling them seaways because its a convenient one-word descriptor).

I toyed a long time with the idea of reducing the number of these trade routes between harbors. If there are two routes between two harbors, over time, one will emerge as the dominant one. For my purposes, I can just say that the "shortest" route will be the best. Therefore, why generate all possible routes?

Eventually, though, I decided to take the extra time to generate everything. Well, not everything. Only harbors with a certain infrastructure (50, for now) are eligible, and I only look at harbors within a 50-hex distance. Longer journeys are certainly possible, but not all at once. Certainly not for trade, which will find the quickest and easiest route to transport goods (as mentioned before).


As a result, there are only a few places where you can travel between continents. However, it is theoretically possible to travel to every single continent.

There are also a couple of issues where some of the seaways are drawn as straight lines (a few can be seen in the figure above). Ideally, the lines follow the currents. It's kind of neat to show a straight line diagram, but if I want that, I'll make that. I think this error happens because of the route-splitter.

Let me back up. I'm generating routes between harbors of sufficient size, A to B. But let's say that this route passes just off-shore of a town too small to have its own harbor. Well, it's reasonable to assume that this would be an ideal place (politics aside) to resupply your merchant vessel. So the algorithm will find places such as this (C) and split A>B into A>C and C>B. All three are now connected rather than just the two. This allows a more robust network and lets smaller cities benefit from the commercial activity of larger ones. However, I have a bug in the code that when no C is found, it looks like the algorithm abandons the original path entirely. Should be trivial to fix (the programmers famous last words).

And if a party is interested in a much longer journey, it is trivial to generate it.

At this point, I'm starting to be interesting in taking all this data and condensing it into a trade network. I've already written a bit about this here, but so far all my testing has been done with manual inputs. Now, I can simply run an algorithm over my map data and generate nodes, edges, and weights from the cities, roads, seaways, and river routes. Things are finally coming up Milhouse.

March 1, 2019

Roads VI: Better Roads and Gardens

Generating a road takes a long time, because there are a lot of things to consider when picking targets, etc.

So it is better to generate them post-hoc, rather than in situ. Still takes a while, but I can blow through a lot more history and get some people on the map to debug.



I really like these results. The basic method here that I select the largest city in a region of continuous infrastructure. Then, a road is placed to every other city in that region if the target city is in the same size class. This generates a main road network artery. For every other city in the region of a certain infrastructure (so not every single village), a road is place to the next nearest road. In this way, all cities of the requisite infrastructure are joined together in a network that makes sense.



I particularly like that not every settlement has a road to it. These are the hinterlands. But if I add resource placement to the history generator, I might need to force high-resource areas to have roads. No sense in having a gold mine if you can't get to or from it easily.

Next, I'll determine the seaways in a similar fashion.