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

silver
lead/galena

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)\]
Easy!

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

Decline


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?

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.