September 28, 2018

Demographics IV: Not Just the Men, But the Women and Children Too

How old are these NPCs?

I want something that makes general sense, particularly given the racial makeup of the particular location. So I'll use population pyramids as a starting point.

The standard fantasy race tropes have never made much sense to me. If elves are super long lived, or even immortal, then there would be essentially no way for a human and an elf to ever understand each other. Languages aside, the cultural contexts would be utterly incompatible.

Dwarfs seem to be a bit better, only living a few centuries. Still.

Tolkien generally addresses this problem by limiting contact between the races. Even the men who deal with elves regularly tend to be long-lived themselves (but still not thousands of years).

I think this is untenable. With such a difference in culture and time, eventually one race would take over.

But we can still introduce some differences into the populations, stretch them out a bit, etc.

One problem (that I encounter quite frequently) is that things like this are usually descriptive rather than prescriptive. That is, there is plenty of data showing the types of distributions I'd like to see (and their consequences), but not much discussing why those happen to be the case. So I have to make it up, or at least parameterize it a bit.

I'll use a logistic growth function:
\[P(x) = {1 \over 1 + \exp\left(-\left(x-x_0\right)\right)}\]
$k$, the growth rate, will be defined by the following, where $x_m$ is the "maximum" age, or at least the age at which there is only 0.1% of the population.
\[k = {-1 \over x_m - x_0}\ln\left({1 \over 0.001} + 1\right)\]
Then, $x_0$ will be the 50th percentile age, or the median age. We must also multiply by a factor $L$ such that all the percentages will add up to 100%. I'll see 250 as the absolute upper age, and only start counting children toward the population at age 15.
\[L = {1 \over \sum_{x=15}^{250} P(x)}\]

So for $x_0=35$, $x_m = 100$ (or a typical human population):
Eh, it's a good start. Split it 49/51 or so for men and women, and there you go.

Soon, I'll write some code to apply this to Demoland, and have a more comprehensive example. Not everyone thinks as abstractly as I do.

September 26, 2018

Wind IV: Rain I: Water is Wet

So I've gotten the wind working more or less how I want. Now I need to push water (in the form of rain) across the landscape.

The initial inputs are observed from the current influences. Cold currents are dry, mild currents are half-wet, and warm currents are the wettest. These begin at the coasts. Then, based on the wind map, the rain moves across the landscape. It drops more water (and exhausts itself faster) when a positive slope is encountered.

Some of the code isn't working exactly like I want it. There are too many straight lines here, but overall I'm able to avoid a lot of ad hoc, and in the end, that's on the right track.

July
January

The wind is altered both by the existing terrain and by the natural winds which are the sole product of the pressure zones. These are the default where nothing else exists. Eventually, though, the air runs out of moisture, leading to the large arid areas in the center of the larger continents.

September 24, 2018

Plaintext Character Sheet

I really thought I'd find something about this elsewhere. But only a few places even alluded to it.

What if, instead of complex pdfs or spreadsheets, we just used a plain, customized text file for our games?

It's not flashy. But it's easy to use, and literally in the most portable format. Gaming on your computer or phone? In any operating system? Easy. At a physical table? Just print it out and update it. All your info, history, stats, etc, can be kept, in the order you like.

But it requires something I haven't seen a lot of these days: players doing work. Many (myself included) want to show up to the table and reap the benefits of the countless hours the DM has slaved over their creation. Why is it that way?

We whine when a little bit of math is required to calculate food, or carrying capacity, etc. Don't whine! Do the work! Instead of endless masturbatory posts on r/DnD with yet another fox-tiefling genasi bard devil with a heart of gold or whatever the hell people are doing these days, put in a little effort to build a character that isn't a Mary Sue.

And I mean build. Don't sketch. Building is done in the game, and polishing between sessions. Double-check your math. Can I really carry 180 lb without slowing down? Where are all my pack animals? Did I leave my sword at the inn or not? Do we have enough rations and health to make it through the jungle?

So far, the plaintext system makes this really easy because I can compartmentalize my items, their weight, any relevant data about them. All my abilities, right there on the page. No more flipping.

It's not fancy, sure. But I don't want fancy - I want something that works. I'm going to experiment with this in a PbP game I'm playing in and see how it goes.

Ideally, you could hand draw it. That could be cool too. I want to say Alexis has a post about this but I can't remember what it is.

It really boggles my mind that there's nothing really about this - not even a "don't use them, they suck!" It's like we've not even considered it. Is it too simple?

Here's the sheet I have right now. Bit of a wall of text, but I can pull it up on my phone, laptop, anywhere.

Mnophet Setep-en-Anubis, Horadrim Initiate

Awakened Gnome
Folk Hero
Fighter 4
Cleric 1

Kills   21

AC  12 (leather armor)
HP  48/48
THP 0
HD  4+1 4d10/1d8

SAVE   OOO
FAIL   OOO

gp  1146
sp  33
cp  105

encumbered at 90 lb
heavily encumbered at 180 lb

Passive Perception 13

Prof    +3
Init    +2
Speed   25

STR 18  +4
DEX 15  +2
CON 15  +2
INT 12  +1
WIS 10  +0
CHA 9   -1

STR +7  *
DEX +2
CON +5  *
INT +1
WIS +0
CHA -1
Acrobatics      +2
Animal Handling +3  *
Arcana          +1
Athletics       +4
Deception       -1
History         +1
Insight         +3  *
Intimidation    -1
Investigation   +1
Medicine        +0
Nature          +1
Perception      +3  *
Performance     -1
Persuasion      -1
Religion        +1
Sleight of Hand +2
Stealth         +5  *
Survival        +3  *
Proficiency with brewer's supplies
--equipped-- 37.5 + 21.05 = 58.55 lb
Sandsword +1            2 lb        +7, 1d6+4 piercing, martial, finesse, light, cast sand for blindness (3 charges), DC 13 per charge or DC 15 for all 3, recharges on short rest in sand
Scimitar                3 lb        +7, 1d6+4 slashing, martial, finesse, light
Handaxe (2)             2 lb        +7, 1d6+4 slashing, simple, light, range, thrown (20/60)
Longbow                 2 lb        +5, 1d8+2 piercing, martial, arrow, heavy, range, two handed
Arrows (234)            0.05 lb
Arrows +1 (9)           0.05 lb
Leather armor           10 lb       AC 11, light
Pouch                   1 lb
Backpack                5 lb        l cu.ft or 30 lb
Fine travelers clothes  3 lb
--backpack-- 21.55 lb
Tinderbox               1 lb        action to light torch, 1 minute to light fire
Waterskin               5 lb        4 pts of liquid
Hempen rope             10 lb       2 HP, DC 17 STR to break
Poison vials (10)       0.05 lb
Healer's kit            3 lb        10 uses
Anubis statuette        0.5 lb totem of the Horadrim
Wand of Magic Detection 1 lb        cast Detect magic, 1d3 charges at dawn
Map
Ink pen
Ink
Letter to Head Priest
Scorpion shell          0.05 lb
--camel-- 107 lb
Crowbar                 5 lb        adv on STR checks
Hammer                  3 lb
Pitons (10)             0.25 lb
Torches (10)            1 lb        1 hr, 20/40 ft, 1 fire dmg
Rations (10)            2 lb
Ceremonial dagger (18)  1 lb
Shovel                  5 lb
Iron pot                10 lb
Brewer's supplies       9 lb
Chain shirt             20 lb       AC 13, medium
Iron spikes (9)         0.5 lb
Two-Weapon Fighting: When you engage in two-weapon fighting, you can add your ability modifier to the damage of the second attack.
Stealthy (feat): If you are hidden, you can move up to 10 feet in the open without revealing yourself if you end the move in a position where you're not clearly visible
Second Wind: You have a limited well of stamina that you can draw on to protect yourself from harm. On your turn, you can use a bonus action to regain hit points equal to 1d10 + your fighter level. Once you use this feature, you must finish a short or long rest before you can use it again.
Second Wind             1/1
Action Surge: Starting at 2nd level, you can push yourself beyond your normal limits for a moment. On your turn, you can take one additional action on top of your regular action and a possible bonus action. Once you use this feature, you must finish a short or long rest before you can use it again. Starting at 17th level, you can use it twice before a rest, but only once on the same turn.
Action Surge            1/1
Battle Master:  You have four superiority dice, which are d8s. A superiority die is expended when you use it. You regain all of your expended superiority dice when you finish a short or long rest. You gain another superiority die at 7th level and one more at 15th level. DC = 8 + prof + STR = 15.
Superiority Dice        4/4
Commanders Strike: When you take the Attack action on your turn, you can forgo one of your attacks and use a bonus action to direct one of your companions to strike. When you do so, choose a friendly creature who can see or hear you and expend one superiority die. That creature can immediately use its reaction to make one weapon attack, adding the superiority die to the attack’s damage roll
Riposte: When a creature misses you with a melee attack, you can use your reaction and expend one superiority die to make a melee weapon attack against the creature. If you hit, you add the superiority die to the attack's damage roll.
Sweeping Attack: When you hit a creature with a melee weapon attack, you can expend one superiority die to attempt to damage another creature with the same attack. Choose another creature within 5 feet of the original target and within your reach. If the original attack roll would hit the second creature, it takes damage equal to the number you roll on your superiority die. The damage is of the same type dealt by the original attack.
--Spells--
WIS +3, DC 11
0: Spare the Dying, abjuration, 1 action, instant, VS. You touch a living creature that has 0 hit points. The  creature becomes stable. This spell has no effect on  undead or constructs.
0: Thaumaturgy, abjuration, 1 action, 1 minute, 30 ft, V. You manifest a minor wonder, a sign of supernatur,al power, within range. You create one of the following magical effects within range. Your voice booms up to three times as loud as normal for 1 minute. You cause flames to flicker, brighten, dim, or change color for 1 minute. You cause harmless tremors in the ground for 1 minute. You create an instantaneous sound that originates from a point of your choice within range, such as a rumble of thunder, the cry of a raven, or ominous whispers. You instantaneously cause an unlocked door or window to fly open or slam shut. You alter the appearance of your eyes for 1 minute. If you cast this spell multiple times, you can have up to three of its 1-minute effects active at a time, and you can dismiss such an effect as an action.
0: Sacred Flame, abjuration, 1 action, instant, 60 ft, VS. Flame-like radiance descends on a creature that you can see within range. The target must succeed on a Dexterity saving throw or take 1d8 radiant damage. The target gains no benefit from cover for this saving throw. The spell's damage increases by 1d8 when you reach 5th level (2d8), 11th level (3d8), and 17th level (4d8).
0: Chill Touch, abjuration, 1 action, 1 round, VS. You create a ghostly, skeletal hand in the space of a creature within range. Make a ranged spell attack against the creature to assail it with the chill of the grave. On a hit, the target takes 1d8 necrotic damage, and it can't regain hit points until the start of your next turn. Until then, the hand clings to the target. If you hit an undead target, it also has disadvantage on attack rolls against you until the end of your next turn. This spell's damage increases by 1d8 when you reach 5th level (2d8), 11th level (3d8), and 17th level (4d8).
2/2
1: Ray of Sickness, necromancy, 1 action, 1 minute, 60 ft, VS, concentration. A ray of sickening greenish energy lashes out toward a creature within range. Make a ranged spell attack against the target. On a hit, the target takes 2d8 poison damage and must make a Constitution saving throw. On a failed save, it is also poisoned until the end of your next turn. When you cast this spell using a spell slot of 2nd level or higher, the damage increases by 1d8 for each slot level above 1st.
1: False Life, necromancy, 1 action, 1 hour, self, VSM. Bolstering yourself with a necromantic facsimile of life, you gain 1d4+4 temporary hit points for the duration.

September 21, 2018

Rivers V: Muddy Waters

Now that I have the speed of rivers, I can start to figure out the balance between the deposition of sediment and the erosion of the terrain.

To reiterate, the map scale makes deposition a bit of a challenge, because the amount of sediment being picked up is enormous. This also assumes that every hex has a single drainage point.

If 1 ft of height is removed from a 347 sq.mi hex, that's nearly 275 million cubic meters of sediment that's got to go somewhere. Even if we assume that not all of it is pushed along, it's still literally tons of material.

There's a lot of studies on sediment capacities and things, but less general than I'd like - since sediment capacity and transport is something we can measure, it's not usually predicted. However, we can still draw a few conclusions.

First of all, the amount of deposited sediment is however much material is eroded away $\partial h \cdot A_h$ (where $A_h = 347$ sq.mi), plus all that's coming down the river, over the time step in question $\partial t = 2.5\cdot10^5$ yr. That's pretty straightforward.
\[Q_s = {\partial h \cdot A_h \over \partial t}\]
For a river with 70 drainage points, $Q_s = 0.369$ cu.ft/s.

We can do something similar for the amount of material that the river can hold, where $A$ is the drainage area and $S$ is the slope.
\[Q_t = k_t A^{1.5} S\]
For the river in the previous example, $Q_t = 0.836$ cu.ft/s. So the capacity is greater than that which is added to the load, and nothing happens.

$Q_s$, of course, grows as we continue down the river. So at some point it will be bigger than $Q_t$, at which point it will deposit $\partial t (Q_s - Q_t)$ cu.ft of material, or add ${\partial t \over A_h} (Q_s - Q_t)$ feet to the height of the hex. $Q_s$ is set to $Q_t$ and continues on its way.

Now, this turns out to not use velocity at all! This is alright, because knowing the velocity is still useful. There is still a lot of tweaking and testing I have to do to get this to work, and the velocity will be more helpful when determining which river routes are suitable for trade.

September 19, 2018

Wind III: Swirls

I needed to redo the wind algorithm, but I want to avoid solving the Reynolds equation over the surface, because that's dangerously close to my real-world research.

So instead of pushing it along hex vector directions, I propagate each wind cell to every neighbor, and then add the vectors in inelastic collisions.

This puts me on the right track, but there's still something missing. For one, the code is ignorant of the hexmap layout, and so it's unaware that there are 60 degree turns at the folds, and the equator is also a problem (notice the big black splotch below). However, I'm getting much more simulated flow this time, and so I think I'm close.

I'm also using a box blur here on the values to make them smoother. If you do this a few times, it approximates a Gaussian blur, so that's easy to do. I'm not sure if I'll stick with this for the final iteration or just use it for display.


Another interesting effect is that the wind dies out going up a mountain slope, but increases to gale-like proportions on the other side. Hm. Some experimentation will be necessary but I can tweak that after I fix the actual propagation.

September 17, 2018

Demoland Demographics

Continuing from here.

I think there are still some issues in interpreting numbers and percentages. After all, as attractive as it could be, I'm not attempting to build a steady state system, which never changes. Instead, this should be reactive and on-the-fly, providing a baseline for the players to interact with.

In the previous post, I developed a model for character levels that might be encountered. In this post, I'll apply that equation directly to the towns in Demoland, but with a few caveats.

city pop 0 1 2 3 4 5 6 7 8
Llen 698 469 154 51 17 5 2 1

Betryn 698 469 154 51 17 5 2 1

Cadewin 798 536 176 58 19 6 2 1

Gerlin 2295 1541 507 167 55 18 6 2 1
Derl 2893 1943 639 210 69 23 7 2 1
Andox 5587 3752 1235 406 134 44 14 5 2 1
Ffith 1397 938 309 102 33 11 4 1

Norys 499 335 110 36 12 4 1


Malis 2694 1809 595 196 64 21 7 2 1
Kenor 599 402 132 44 14 5 2 1


Firstly, I haven't taken a look at age distribution yet. I think this is an interesting aspect and I'll be tackling it later. But age and level taken together are not so simple. It would be laughable to encounter a Level 5 child of a mere eight years old, and yet the system would allow for such a possibility if I simply multiplied the distributions (as I plan to do with class distribution and racial distribution). If (for example) 10% of all population are children, and there are 100 Level 5s in a city (requiring about 40,000 people total), then is at least 1 a child?

This does a gross injustice to the science of statistics, but I must keep my model simple somehow.

And yet there must be room for true diversity. It doesn't matter if there's one dwarf in a town of a thousand people - he might just be the sole Level 6. It's rare, yes, but the system must allow for the possibility.

Hence the difficulty. These posts, while useful for testing the model, only give the most normal, steady-state situation. A true encounter "table" (really, it's an encounter model) could include the Level 6 dwarf, but discourage the Level 5 child. This is the ideal. But I'll work on age later.

One way to think about this order is that it's emergent, not determinant. The Level 8 does not ensure or build Andox: he is there because Andox will have a Level 8. The numbers are retroactive.

I could have a population "generator" that makes a separate roll for each person. It's a simple enough calculation to do with Python. That would make, say, Llen and Betryn different (currently, they are the same because they have the same population).

0 1 2 3 4 5 6 7
Llen 698 466 146 61 13 10 5 1
Betryn 698 454 155 55 21 8 3 1 1

Hm. That's way better. However, it takes a bit more elbow grease to implement in Excel. However, it can totally be done. I leave the implementation as an exercise to the reader.

Ultimately, I think what I'm building is a context and location aware NPC generator. But it should also give direction to the DM about what type of place this is. If the $k$ value remains fixed, then this becomes a matter of thinking about how different levels are stratified in differently-sized populations. And if we want the Level 7 guy to help us, we've got to go here (and not there) to find him. I think this will be richer once the classes are added, since it's constrained by geography and the trade network, and not merely a function of population.

Lots to learn. Lots to think about.

September 14, 2018

Elevation IX: Rivers IV: Rolling Down the River

Someone recently pointed out that my river code will probably not be satisfactory until I add deposition. I tend to agree. My code so far is merely erosion, and the models I'm modifying don't account for deposition either.

All in all, deposition is pretty important for smaller scale modelling, but it's worth considering if it could have an effect. But it turns out it's pretty complicated, and you need to know some things like the type and size of sediment each river is carrying. So I need a way to simplify the model.

However, the first thing I need to know is how fast the river is flowing. If it slows down too much, it may deposit sediment, which could end up correcting its own course.

Part of the problem I'm dealing with is again one of scale. To affect an average of 1 ft of change in a 20 mile hex, you'd need to remove (or deposit) about half a billion tons of soil. So in the real world, these things are studied on much smaller scales. Throughout this process, there are a couple of places I have to disengage from reality, if only because I'm limited in the amount of information I can provide and my sampling density.

To determine velocity, I generally need to know the discharge amount of the river, its depth and width, and the slope and roughness of the channel. None of these are easy.

There are many models relating drainage area (the only variable I really have besides slope) to the discharge amount, but they all yield numbers that are much higher than I want to use. Remember that a single hex covers 346.6 sq.mi. That's a lot of water to collect. The following equation is often offered for width in terms of drainage area (the coefficients vary across studies but are usually in this range):
\[w\textrm{ [ft]} = 13.23 \left(A\textrm{ [mi$^2$]}\right)^{0.446}\]
But this yields a channel width of 180ft for a single hex. This is probably real world realistic, but it's not what I need to use. I just don't have enough detail at this scale to say for sure if all 400 hexes are draining out at a single point on the edge of a hex. But if I just use the number of hexes (1 in this case) instead of the area, I get $w = 13$ ft. This is reasonable, even if it's not strictly accurate.

The depth of the river is another matter. In the real world, this is easy to measure, and so it's usually offered as an input rather than a result. However, I can use the same process to arrive at the following:
\[d\textrm{ [ft]} = 0.9951 \left(A\right)^{0.3012}\]
This yields a depth of a little less than a foot. That's still a fairly substantial stream - it would present a significant obstacle to trade, to say nothing of travel on foot. My small hiking experience has crossed many streams of just a few inches depth, and anything more than a foot is a noticeable, but not insurmountable, obstruction. The width to depth ratio is about 14, which is reasonable, but it has a large variation depending on very local conditions.

I considered using the Rosgen Classification, but I don't think I have enough data to make it worth it.

I need a few more geometrical parameters, the cross-sectional area, and the wetted perimeter. For now, I'll just use an ellipse to model it, although this isn't really ideal. It's not ideal because I have to use the following equations to find the perimeter:
\[\varepsilon = {\sqrt{w^2 - (2 d)^2} \over w}\]
\[P_W = w \pi \left(1 - \sum_{i=1}^\infty {(2 i)!^2\over(2^i i!)^4} {\varepsilon^{2 i}\over 2 i - 1}\right)\]
It was at this point I wondered if it's all worth it. The area is simply(er) given by:
\[A_R = {\pi w d \over 2}\]
These can be used to determine the hydraulic radius:
\[R_H = {A_R \over P_W}\]
And then the Manning Equation is used to finally determine the flow velocity:
\[v = {1 \over n}R_H^{2 \over 3}S^{1\over2}\]
Where $S = {\Delta y \over \Delta x}$, and $n$ is the Manning roughness factor, which varies depending on topography. I may use a random function to determine it in future, but for now I've set it at $n = 0.05$.

For testing, I picked a stream path at random. This once again demonstrates the scale problem. A drop of 400 ft over 20 miles is nothing. Generally speaking, walking along a slope is can be perceived at around 2.5%, which corresponds to a height change of 2640 ft. That's a lot, but of course the local terrain will be much different. All the slopes here are much less than 2%.


That yields the following profiles for slope, accumulated drainage area, and velocity in mph.


Sedimentation will be related to the river velocity; if it drops below a certain threshold, it may end changing the whole course of the river.

September 12, 2018

Demographics III: Who Lives in that Castle?

I've done some picking at demographic growth models before, but I want to tackle how the strata of levels fall out in any given place (and also class distribution). After all, for all my grand rhetoric, the telos of this project is a system that describes what players see, and forms how they can interact with the environment.

What I've built kind of matches distributions such as this, but in general the higher levels are much rarer in my system. That's not a bad thing, necessarily, but it might require some fiat to address the issues I talked about here.

Right now, I have two types of population divisions, and I'm not sure which one to use. The first is the population of the local hex. The second is the hegemonic population of any hex that relies on the central hex for markets or connections to the trade network. This is important, because you might regularly encounter people from a day's journey down the road doing business in the city. Due to the way the math works out, it's not as simple as just adding the numbers; essentially, the density changes the demographic distribution (which makes sense).

Either one is easy to implement. But I think, since these are essentially customized encounter tables, that I'll stick with the local hex, which is still a large area.

I'm going to use an exponential distribution to model the percentage of each population at each level. Then I can just multiply by the total population.
\[P_\ell = {1 \over \sum_{n=0}^{20} {1 \over k^{n - 1}}} k^{1 - \ell}\]
where $k$ is the shape constant (I've experimented and I like the results at $k=3.039$) and $\ell=0\to20$ is the level in question.

I like this because it gives percentages and not cut-offs (which are always a good idea to avoid). For example, a tiny village of 500 will probably not have a retired 14th level fighter...but out of 17,083 such villages, one will!

Obviously this is more detail than a simple 1d100 can provide...you could use a couple of them to simulate 1d1000000...or you could just use a damn computer already. Here's a table anyway, but feel free to roll your own numbers. This is easier to implement in Excel than some of the things I've talked about.


level%1 of
067.09443897%1
122.07780157%5
27.26482447%14
32.39053125%42
40.78661772%127
50.25884097%386
60.08517307%1,174
70.02802668%3,568
80.00922234%10,843
90.00303466%32,953
100.00099857%100,143
110.00032859%304,334
120.00010812%924,873
130.00003558%2,810,688
140.00001171%8,541,680
150.00000385%25,958,164
160.00000127%78,886,861
170.00000042%239,737,171
180.00000014%728,561,262
190.00000005%2,214,097,675
200.00000001%6,728,642,833
I don't particularly like that there would only be one Level 20 in our own world. But that's the way the distribution crumbles. However, as I mentioned before, fiat can still be used when necessary. Even though I don't like using fiat.

September 10, 2018

Temperature III: Generating Temperature

Now I'm really on a kick. I want to move away from manually drawing anything I can, so I can focus my creative efforts to the greatest effect. Temperature will be a fun one to work on.

The baseline proved tricky to try and match to Earth values, So I made my own:


\[ T = \frac{T_{max} - T_{min}}{2} \cos\left(2 \frac{\pi}{180^\circ} \ell \right) + \frac{T_{max} + T_{min}}{2} \], where $T_{max}=90$, $T_{min}=1$ if the latitude $\ell$ is below the equator ($\ell < 0$) and $T_{min}=41$ otherwise.

The equator stays roughly the same, but the baseline will shift back and forth between January (blue) and July (red).

January

This color scale is a bit misleading, I think. But it does show the general plan.

September 7, 2018

Better Tectonics

I figured out a method that fixes the weird hex distance stuff I'd been working with. First thing I used it for was the fault line map (to use for erosion uplift).


Looks like candy. Let's turn that into an uplift map, rendered as an elevation map.


Cool. Making progress.

September 5, 2018

Demographics II: Racial Diversity

Real races, that is.

I've been mulling over the applicability of the trade system to non-trade things, specifically race and some classes. Class distribution will be harder to implement but racial distribution turned out to be super simple.

Back to Demoland: Let's assign 1 "reference" of humans to all cities. Then replace that with 1 reference of dwarfs in Norys and Gerlin, and with 1 of elves near Ffith. First I run the resource code to determine availability, like everything else. This gives me the following numbers for Andox:

{'human': 11.149800849953373, 'dwarf': 0.6676576289379996, 'elf': 0.2330468227424749}

Alright. Now what? Simply normalize: divide each of those numbers by the total, which is around 12. Round it out (I don't need floating point accuracy), and we have a percentage for each race:

{'human': 0.925, 'dwarf': 0.055, 'elf': 0.019}

Very cool! There are still some conceptual issues to work out:

  1. Do enclaves form at all? This supposes that the demographics pretty much totally smooth out. And in this case, I've only got a few sources of non-humans in a sea of humanity. Maybe that makes a difference. But it does give me some slight differences already.
  2. What about immigration? These policies vary throughout history, from totally open to totally closed. Implementing the system as is might result in very cosmopolitan trade cities, but you might want cases where outsiders are allowed to trade but not necessarily to live.
  3. To that point, though this might indicate the race of any given person the party might encounter, not necessarily the static distribution of the total population.
A lot to consider. But the simple version works, and that feels good.

September 3, 2018

Current Influences

A big part of Azelor's Guide is the effect that currents have on temperatures. Generally speaking, if a warm current is near a coastline, the climate there will be warmer than it might otherwise be (Spain, for example). So this is pretty necessary for any kind of complex climate.

This should be easy (famous last words) because I already have the wind maps and the current maps. So theoretically, I just work inwards from the coasts, scaling the "degree" of influence to the wind speed. I'm not sure yet how I want to map the influence to the temperature, but that will come later.

Green - mild, blue - cold, red - hot, yellow - continental, dark yellow - continental plus

One thing I do notices is that I think the continental influence should be closer to the coast. I think I should also explore the wind model to see if I can push those winds a bit further inland. Right now, they are breaking against the elevation change, so I probably need to reduce the wind loss as it moves uphill.

First, though, I'll see how the model works when I run it on non-dummy data.