July 15, 2026
How we measure combat and progression
In the overview post I said combat takes more time than you’d think. Still true. A Strength point has to feel different from the one before it. A six person party still has to reach the next story beat in a reasonable number of fights. Healing and temple costs have to matter without turning every trip into a bank run. I spent a long time reworking those systems, then building tools that run a lot of fights so I can look at outcomes instead of guessing.
This post is about those tools. The numbers come from the game as it runs today: combat rules, bestiary, items, spells. I’m writing for people who play games or make them. Lots of charts. That’s how I review retunes. When I change a combat rule, I usually re-run thousands of fights before I trust how it feels. One playthrough with a lucky party is not enough.
I would not have finished this without AI. The combat rules, balance harnesses, career and expedition sims, charts, and a lot of the design back and forth all happened with AI helping write code, catch mistakes, and push through the volume of tests and retunes. That did not replace deciding what feels fair, or what the story should support. It did make it possible to get this far without burning years of calendar time.
Scope note: Level and career numbers in this post stop at about level 13. That is on purpose. The first region and story arc (Sómariel into The Marrow, Earthwarden band) need to land cleanly before I spend balance time on the rest of the climb. Higher levels and later story stages are planned. Treat anything past 13 as not measured here yet.

Win rates, experience pace, career climb, and town economy. Each is a different check.
Why bother
Guessing works for a day or two. After that it gets expensive. I have seen (and shipped, at least in private builds) problems like:
- Level 8 still playing like level 3
- One strong magic weapon carrying the whole campaign
- The temple either never used or always draining the purse
- A six person party taking forever to reach the next story stage, because experience was still sized like a solo RPG
Most of that showed up here at some point. The fix was a full balance harness on top of the real combat engine: same formulas, same bestiary, same experience tables, run without graphics. Building it took real engineering time. A fixed random seed means I can replay fight 4271 and get the same result every time.
In practice I run a headless Godot tool that batches thousands of fights. Typical settings for the physical matchup board are 5,000 fights with seed 1. Other modes cover body saves, the career path, and the session pattern of leaving town, fighting until you need recovery, then coming back (more on that below). Expected win rates live in tables so I can see when a retune moved something.
What each stat does
Internal keys stay short (ST, IQ, DX, CN, SR). The UI says Strength, Intelligence, Agility, Constitution, and Spirit.
| Stat | What combat does with it |
|---|---|
| Strength | Melee hit accuracy; damage multiplier on melee and thrown; armor penetration on those attacks |
| Agility | Bow and thrown accuracy; dodge (Armor Class); initiative; flee chance; surprise rolls |
| Constitution | Hit points; walk healing; physical damage taken; poison and body saves; a once per fight “stalwart” clutch at high Constitution |
| Intelligence | Mind saves for now (more magic later) |
| Spirit | Paladin heal power; divine spell points |
Natural stats hard cap at 18. Creation soft caps at 15, and 16 through 18 come from later level ups. A lot of combat math uses a pivot of 10, so below 10 is weak and above 10 is strong, on a straight line rather than a complicated curve.
Each level grants 2 build points. Raising a stat costs more as the number climbs, and the step into 18 costs 5 points, so spreading points around versus stacking one stat is a real tradeoff.

Allocation costs from the live rules.
Hit chance
When accuracy and Armor Class (AC) match, you hit 55% of the time. Each point of difference moves that by 3.5%. The result is clamped so pure 0% and pure 100% do not show up.

Who feeds accuracy
I had this wrong in my head more than once. Here is how it works:

Melee and unarmed use Strength for accuracy. Bows and thrown weapons use Agility. Strength also multiplies damage on melee attacks and on thrown weapons (spears, axes, and the like). Bows do not get that Strength damage bonus; they hit based on Agility only. Armor penetration (ignoring part of worn armor Armor Class) works the same way: melee and thrown get it, bows do not. Soft dodge Armor Class is never stripped that way.

Constitution
Tough characters take less physical damage. Frail ones take more. When you are poisoned, each round of poison damage is lower if your Constitution is high and higher if it is low. Body saves also improve as Constitution goes up.


Average poison damage per round is about 2 at Constitution 6 and about 1 at Constitution 18, over many seeded rolls.
Fleeing
Flee chance uses the living party’s average Agility. At 10 it is 12.5%, and at 16 it is 21.5%. Those are the expected rates on the saves board.

The physical fight board
The fight runner builds a character, equips optional weapon and armor, loads a real monster from the bestiary, and runs the same combat path the player uses. I do not keep a second combat implementation just for spreadsheets.
On the full physical board I run 5,000 fights per row with seed 1. Each row has an expected win rate plus a tolerance band. Continuous integration runs a shorter set at 1,500 fights so testing on each merge doesn’t take forever. After a real retune I remeasure at 5,000 and only then change the expected values if the new numbers are intentional.

Short sword versus skeleton is around 82%. High Agility bow around 86%. Low Agility bow falls to about 55%. High Strength armor penetration usually beats a bony shell; low Strength still wins often, but less cleanly.
Here is a multi panel dump of the physical board, the continuous integration matchups, and the saves / poison / flee Monte Carlo:

Blue is expected, green is measured. When those stop lining up after a code change, the board fails. Then I either fix the math or update the expected values.
I can also sweep one coefficient at a time. Try three values for how much Strength buys in armor penetration, run a few thousand Warrior versus orc fights, and compare win rates. The knobs live in one tuning object so I can override them without rewriting the engine.
Experience points
The party is permanently six people. Experience points (XP) from a fight are level weighted across living members, and gold goes to the shared purse. If you owe temple resurrection debt, some of that gold gets garnished before it hits the purse.
The older “double total experience every level” approach, with nearly flat monster awards, made mid levels unreachable for six people. Inside the level 1 to 13 window I have been tuning two main ideas:
- Each level costs a Fibonacci style step (a bit larger than the last).
- Monsters have a power tier from 1 to 12, and the award is 100 times the tier weight. Integrity tests fail if an award does not match its tier.




Yardstick through level 13 only, assuming nothing but tier-1 kills. Real play mixes higher tiers as content gets harder.

Classes also have different unit sizes. A Rogue needs 540 units per step, a Warrior 600, and a Lightbringer 900. The curve shape is the same; the speed is different.

Career path tool
The career mode walks a scripted path through the real encounter tables: Sómariel soft, mid, and hard, then The Marrow floors 1 to 3. Victory is assumed. I only ask how many wins and how much experience get the party to levels 2, 5, 7, 9, 11, and 13.
The pinned expects have wide tolerances for sampling noise:

Rough shape: about 30 fights to level 2 on soft houses, about 280 to clear town through hard near The Marrow (around level 7), then thousands more through the three Marrow floors toward level 13. Tolerances are wide because I care more about the overall shape than one lucky seed.
If I add a monster to a real table, the career diet changes with it. I do not keep a separate fake bestiary just for balance tests.
Healing, gold, and going back to town
Walking regen
Out of combat, hit points slowly come back as you walk around. The rate scales with Constitution, and free regen stops once you reach half of max hit points. Dead characters do not recover this way. Conditions and resurrection still need the temple or spells.
Field and combat healing
Early healing is the Paladin spell Lay on Hands. It only targets one ally, costs 3 spell points, rolls 1d6+2 plus floor((Spirit - 7) / 2), and also cures poison on that target.
Earthwarden has no Mend. That book is built around damage, shields, and Magelight. Party wide heals show up later on Lightbringer (Rejuvenate). Early in the game, keeping people upright usually means Paladin healing, walking around until hit points trickle back on their own, and visiting the temple when you need a full top-up or a condition cured.

Town prices
Here is what the game charges:
| Service | Price |
|---|---|
| Heal missing hit points | 5 gold each |
| Cure a status | 120 gold |
| Resurrect | 500 gold |
| Restore spell points / song uses | 10 gold per point |
New parties start with 100 gold.

Leaving town, fighting, coming back
In play, a normal session looks something like this. You leave town, fight and loot for a while, use field heals and walking recovery between fights, then return to town when hit points, spell points, or gold pressure say it is time. Back in town you pay the temple, restock, maybe buy gear, and head out again. I call that leave-fight-return cycle the expedition loop. It’s the whole trip, not a single battle.
There is a sim for that loop. It asks how many fights happen between town visits, how bad the wounds are, and whether gold covers temple care and spell point restore.
It uses the same encounter path, experience, gold, and level ups as the career tool. How long you stay out before returning is an output I measure. I do not hand type a target trip length into the sim.
By default the recovery style is “field heals first”: heal allies under 80% hit points while casters keep a spell point reserve, walk about a dozen steps between fights, return on death or stone, and take full temple care in town. The gear ladder is on by default as well.
Fast mode is attrition, which means approximate damage with a labeled residual so the sim can run quickly. The current pin looks like this:
- Base damage taken factor of 1.90
- Extra ramp of 0.35 per level starting at level 4
- Soft path to level 5: about 10 fights per town visit, severity around 0.51, solvency around 2.0
- Full path to level 13: about 26 fights per town visit, severity around 0.56, solvency around 2.9


Solvency is gold on hand divided by recovery bills. Above 1 means you can usually pay. Around 3 is comfortable but still spending. Near 99 would mean temple visits barely cost anything relative to income.
There is also a slower full combat mode, plus an A versus B compare, so I can re pin that damage factor when combat or gear changes. Spell aware combat in the sim is trusted through about level 13 (Earthwarden and Fireball). Higher books are incomplete in this tool for now.
Gear the sim buys
Sim characters start with a weapon and a Padded Vest (+1 Armor Class). After victories, if gold allows and a 40 gold temple cushion remains, the expedition ladder buys upgrades in this order:
- Leather armor
- Legs
- Boots
- Gloves
- Wooden shield
- Leather cap
- Chain mail (catalog value 800 gold, so it is a real mid climb purchase)

Basic need gear only. No shop magic on this ladder, and plate is not on it.
Light is a resource too
Here is what light items do in the game:
| Item | Fuel | Healthy burn | Stutter | Notes |
|---|---|---|---|---|
| Torch | torch | 180 s (3 min) | 30 s | Burns out and is destroyed |
| Lantern | oil | 300 s (5 min) | 45 s | Refill from Lamp Oil (20 gold) |
| Everbright | none | always | none | Found magic light, no oil |
Fuel burns in dungeons, and outdoors or in town at night or dusk. It does not burn inside venues or on daytime streets. Thunderstorms make torches drain 1.75 times faster, while lanterns ignore the storm multiplier.

Earthwarden Magelight costs 4 spell points, lasts 50 map steps, and uses energy 1.2 with range 8. It is bright enough that you sometimes spend spell points instead of buying oil, but it still costs a real resource, so torches and lanterns do not become useless.
What worked in practice
I keep the balance tools on the same combat code the player uses. A separate spreadsheet of combat math usually drifts from the game within a week or two.
Dice paths accept an optional seed for tests. Without a seed the game still plays normally.
Tuning values (hit gap, Strength multiplier, armor penetration, Constitution toughness, flee, saves, backstab, and so on) live in one place. When I sweep, I change one field at a time.
With dice, a range is more useful than a single perfect percent. Something like “about 65%, plus or minus 8%” is a workable target.
I save charts by date and type so I can compare this week to last week.
I try to keep the questions separate:
| If this is off | What it tends to feel like |
|---|---|
| Fight win rates | Stats and gear do not seem to matter, or fights feel purely random |
| Experience / career path | Levels come too slow or too fast relative to the story |
| Expedition gold and heals | Too many temple trips, or recovery never matters |
Attrition mode is a fast approximation. The damage factor is labeled, and I re-check it against full party combat so the economy numbers do not drift from the real game.
What is still incomplete
Balance testing past level 13 is still ahead of me. I want the first region right before I measure the next stages the same way.
Magic fights are only partly under seed control, so physical 1v1 is still the most reliable board. The expedition sim has a slower full combat mode that is still catching up to the fast approximation for daily retunes. Spell coverage on those trips only goes through about level 13 until the higher books are wired in. I expect the numbers to keep moving as I play. The tools are there so I can see what moved.
If you want to steal the approach
You do not need Godot. The pieces that actually mattered for me were:
- Combat math that can run without the user interface
- Seeded random numbers
- A table of matchups with expected win ranges
- A level and experience sim that uses the real monster awards
- If the party wears down over a trip: heal costs, shop prices, and when you return to town
- Charts you keep when the knobs move
Keep it wired to the live formulas. A spreadsheet that diverges from the game is how you end up balancing a different combat system than the one players actually play.
A Tale of Light is a 2.5D dungeon crawler I am building in Godot. This post matches the balance tools, combat rules, item data, and spell catalog as of this writing. When I retune again, I’ll update the charts and numbers above.