# The Villager Economy

Wren the scout visits the base with a menu of deals: hand over raw materials for food, buy
supplies and rare materials with gold, buy tools and cosmetics, gamble on the Scout's Wager,
or convert one material into another. Every deal is priced in `data/trades.json`, with one
shared "exchange rate" tuned in `data/balance.json`. Here's each trade and its numbers.

## In plain terms

The visit popup holds five deal boards, each tuned on its own:

1. **Material-for-food trades** — dump cheap dug materials (dirt, clay, stone) straight
   into the food bar.
2. **Gold trades** — spend gold for supplies (food/water) or for materials delivered to
   inventory.
3. **Tool offers** — buy the starter axe/pickaxe with dug materials, or buy higher-tier
   tools (iron axe/pickaxe, stockable as spares) and dynamite with gold once you can craft
   them yourself.
4. **Cosmetic offers** — buy digger cosmetics with gold.
5. **The Scout's Wager** — an optional gold gamble for exotic materials or rare cosmetics.

A sixth board, **Material Exchange**, isn't in `trades.json` at all. It prices off a single
"efficiency" knob in `balance.json` plus each material's `trade_value` (see
[The Economy Model](/docs/underroot/the-economy-model)).

`VillagerVisitPopup` loads everything below. The values hardcoded in that script are
fallbacks only; the JSON is the tuning surface. If the file goes missing or a section is
absent, those built-in defaults take over.

## Material-for-food trades

File: `trades.json` → `material_food_trades`. Each entry means "**`cost`** units of the
material buys **`food_per`** food." A dirt entry of `cost 3, food_per 1` reads in the UI
as `(3 : 1)` and gives 1 food per 3 dirt handed over.

| Material | Where it lives | `cost` | `food_per` | Effect |
|---|---|---|---|---|
| `dirt` | `trades.json` → `material_food_trades` | `3` | `1` | 3 dirt → 1 food. The lowest-value dump. |
| `clay` | `trades.json` → `material_food_trades` | `1` | `1` | 1 clay → 1 food. |
| `stone` | `trades.json` → `material_food_trades` | `1` | `2` | 1 stone → 2 food. The best rate on the board, and the one that keeps the trade alive past depth 27. |

The player trades in multiples of `cost`; food granted is `(quantity / cost) × food_per`.
The steppers snap to whole lots, so a partial lot can never be stranded.

**The rate improves with depth, on purpose.** Measured in `trade_value` per food, the
ladder runs 3 (dirt) → 3 (clay) → 1.5 (stone). Stone was priced at `food_per 1` until
September 2026, which put all three on a flat 3 trade-value per food. That read as
consistent, but it made stone the worst deal on the board by effort — 5 seconds of digging
per food against clay's 2 — and since stone is most of what a digger cuts past depth 27,
the whole board went quiet exactly when a run gets dangerous. Doubling stone's payout fixes
the late-game deadness without touching the early game, where stone is out of reach anyway.

For scale when tuning: the food bar runs 0–100 and drains `0.04`/second, doubled to
`0.08`/second while working, so **1 food buys 12.5 seconds of digging**. Against each
material's `dig_time` that gives a return on effort of 4.2× for dirt, 6.3× for clay, and
5.0× for stone. The competing gold path (`5` food for `10` gold) is a flat 2 gold per food.

These three are the player's main hunger safety valve before farms and lodges come online,
so nudge gently. Want early food to come easier? Turn `cost` down or `food_per` up on dirt
or clay — stone won't move the early game either way.

One thing this board does **not** do: the Trading skill multiplier and the Silver Tongue
capstone apply only to the Material Exchange, never to these food ratios (see
[Skill and class modifiers](#skill-and-class-modifiers)). A maxed Merchant hands over the
same 3 dirt as a day-one digger.

## Gold trades

File: `trades.json` → `gold_trades`. `type: "supply"` pours the reward straight into the
food or water bar; `type: "item"` delivers the material to inventory. `gold_cost` is the
price for `gives_amount` units.

| Gives | Where it lives | `gives_amount` | `gold_cost` | `type` | Notes |
|---|---|---|---|---|---|
| `food` | `trades.json` → `gold_trades` | `5` | `10` | `supply` | Emergency food top-up. |
| `water` | `trades.json` → `gold_trades` | `5` | `10` | `supply` | Emergency water top-up. |
| `wood` | `trades.json` → `gold_trades` | `20` | `15` | `item` | Bulk surface fuel/building stock. |
| `coal` | `trades.json` → `gold_trades` | `20` | `20` | `item` | Bulk mid-tier fuel. |
| `deep_coal` | `trades.json` → `gold_trades` | `8` | `40` | `item` | Higher-grade fuel. |
| `strange_root` | `trades.json` → `gold_trades` | `5` | `25` | `item` | **Only appears during the Black Rot challenge** (`challenge: black_rot`). Hidden in normal runs. |
| `iron` | `trades.json` → `gold_trades` | `2` | `25` | `item` | Buy your way past an iron shortage. |
| `ancient_clay` | `trades.json` → `gold_trades` | `1` | `220` | `item` | Exotic; premium price. |
| `prismatic_shard` | `trades.json` → `gold_trades` | `1` | `380` | `item` | Exotic; premium price. |
| `void_iron` | `trades.json` → `gold_trades` | `1` | `450` | `item` | Exotic; premium price. |
| `ember_essence` | `trades.json` → `gold_trades` | `1` | `600` | `item` | Exotic; the most expensive single buy. |

Add a `challenge` key to gate any gold trade to a challenge, the way `strange_root` does.
Without that key the trade is always offered. Raise the exotic prices and gold becomes a
slower route to post-Astrolabe materials; lower them and a gold-rich player can skip mining
for them.

## Tool offers

File: `trades.json` → `tool_offers`. Wren's tool board sells two kinds of goods: **starter
tools bartered for dug materials** (one-time), and **gold-priced tools/consumables** that
appear once the player could craft them and are bought by quantity up to a stack cap.

| Tool | Where it lives | Price | Kind | Gate |
|---|---|---|---|---|
| Axe (`axe`) | `trades.json` → `tool_offers` | `30 dirt`, `10 clay` | one-time barter | always shown |
| Pickaxe (`pickaxe`) | `trades.json` → `tool_offers` | `50 dirt`, `25 clay` | one-time barter | always shown |
| Iron Axe (`iron_axe`) | `trades.json` → `tool_offers` | `500 🪙` each | up to 5 spares (→ `ToolState`) | recipe `iron_axe` unlocked |
| Iron Pickaxe (`iron_pickaxe`) | `trades.json` → `tool_offers` | `750 🪙` each | up to 5 spares (→ `ToolState`) | recipe `iron_pickaxe` unlocked |
| Dynamite (`dynamite`) | `trades.json` → `tool_offers` | `250 🪙` each | repeatable (→ `Inventory`), capped to `max_stack` (5) | recipe `dynamite` unlocked |

Optional fields on a `tool_offer`:

- **`gold_cost`** (int) — price the offer in gold instead of dug materials, sold with a
  `− N +` quantity stepper. A **persistent tool** (`iron_axe`/`iron_pickaxe`) is bought as
  spares routed to `ToolState`, up to `TOOL_MAX_STACK` (5) minus the count already owned;
  `add_tool` runs once per spare (auto-equipping if it beats the current tool, the rest
  waiting as full-durability reserves). Because a tool that breaks decrements the owned
  count and swaps in a fresh spare, the player re-buys as they wear out. A **consumable** is
  a quantity buy routed to `Inventory`.
- **`consumable`** (bool) — the offer is a stackable item (dynamite) rather than a tool;
  capped so a purchase can't push past the material's `max_stack`.
- **`gate_recipe`** (string) — hides the row until that recipe is unlocked
  (`CraftingUnlockManager.is_unlocked`), i.e. once the player has seen its inputs. Gold thus
  shortcuts the *grind*, not the *progression*. No `gate_recipe` → always shown.

All gold consumers on the visit board — gold trades, gold tools, and consumables — draw on
one shared gold budget, so no combination of selections can overspend when the player hits
TRADE. Mining charge is deliberately **not** sold here; it stays craft-only so it remains a
progression reward.

The starter barter offers are a fallback path to the axe/pickaxe for a player who hasn't
crafted them, so keep those costs in cheap surface materials. The gold prices are pure sinks
— raise them if gold is flowing too freely, lower them to make the shortcut cheaper.

## Cosmetic offers

File: `trades.json` → `cosmetic_offers`. Gold-priced digger cosmetics. Ownership is
account-wide — it lives in `config.json`, not the save slot — so a player buys each of
these once across all runs. The whole board disappears once the player owns everything on
it (nothing left to sell).

| Cosmetic id | Where it lives | `gold_cost` | Notes |
|---|---|---|---|
| `tunic_furtrim` | `trades.json` → `cosmetic_offers` | `400` | "Fur-trimmed Tunic". Body garment, no effect. |
| `tunic_robe` | `trades.json` → `cosmetic_offers` | `350` | "Robe". Body garment, no effect. |
| `boots_ironshod` | `trades.json` → `cosmetic_offers` | `300` | "Iron-shod Boots". Footwear, no effect. |
| `extra_gloves` | `trades.json` → `cosmetic_offers` | `2500` | "Berry-picking Gloves". The only ware on this board that carries gameplay traits: `berry_speed_mult` 1.6 (**+60% picking speed**) and `berry_yield_mult` 1.2 (**+20% food per harvest**), both in `cosmetics.json` → `effect`. |
| `dye_slate` | `trades.json` → `cosmetic_offers` | `200` | A dye. |

The id must match an entry in `cosmetics.json`, and the row label is that entry's `name` —
so a rename in `cosmetics.json` changes what Wren's board reads. Any traits on the item are
printed as a line beneath the name, so a priced ware explains itself before the player
commits the gold. `gold_cost` is pure sink pricing for the looks; where a cosmetic also
carries an `effect`, that effect is the real reason to save for it. These were repriced up
(from 20–1000 gold) once gold started flowing freely enough that the old prices meant little.

**On the gloves' two traits.** Picking speed is the weaker half by a wide margin: a bush
holds 20 berries and then rests a full day, so the +60% saves a few seconds per bush cycle
while bush stock and regrowth set the real ceiling. The yield multiplier raises that ceiling
instead — it scales the food *granted*, never the berries deducted (scaling the deduction
would strip bushes faster for the same total, a net zero). Tune the yield figure if the
gloves feel over- or under-priced at 2500; the speed figure barely moves the needle.

## The Scout's Wager

File: `trades.json` → `wager`. An optional once-per-visit gold gamble. A win returns an
exotic material or, some of the time, a rare wager-exclusive cosmetic. A loss returns a
small "consolation" pile of common materials, so the stake is never a total loss.

### Wager tuning values

| Setting | Where it lives | Default | What it controls |
|---|---|---|---|
| `cost` | `trades.json` → `wager` | `25` | Base ante in gold (the starting stake before population scaling). |
| `cost_pop_interval` | `trades.json` → `wager` | `50` | Every this-many of **peak** population adds one price step. |
| `cost_step_first` | `trades.json` → `wager` | `5` | Gold added by the first price step. |
| `cost_step_growth` | `trades.json` → `wager` | `1` | Extra gold each later step adds on top of the previous one. |
| `success_chance` | `trades.json` → `wager` | `0.05` | Win chance before the first Astrolabe ritual (5 in 100). |
| `success_chance_post_astrolabe` | `trades.json` → `wager` | `0.15` | Win chance once the ritual has seeded exotics (15 in 100). |
| `cosmetic_chance` | `trades.json` → `wager` | `0.6` | On a win, the share that pays a rare cosmetic instead of an exotic — but only while un-owned wager cosmetics remain; after that a win is always an exotic. |

**How the ante scales.** Each visit re-derives the effective stake from the run's peak
(high-water) population, so it never drops when villagers are lost. With `n` =
peak population ÷ `cost_pop_interval`, the cost is
`cost + n × cost_step_first + cost_step_growth × (n−1) × n ÷ 2`. On the defaults that runs
25 → 30 → 36 → 43 … as population crosses each 50-villager mark. Worn "luck" cosmetics
like the Lucky Amulet, the **Trading capstone Silver Tongue**, and the **Chieftain wager
handicap** all multiply the win chance on top of the base rate (see Skill and class
modifiers below).

### Wager prize pools

| Pool | Where it lives | Contents |
|---|---|---|
| `exotic_pool` | `trades.json` → `wager` | `ember_essence`, `void_iron`, `ancient_clay`, `prismatic_shard` — the four exotics a pre-ritual win can return. |
| `exotic_pool_post_astrolabe` | `trades.json` → `wager` | The four above **plus** `root_amber`, `pale_chalk`, `wavellite`, `magnetite`, `obsidian`, `chromite` — ten exotics once the ritual has seeded the world. The larger pool is why the post-ritual win rate is raised: any one specific exotic stays about as findable. |
| `consolation_pool` | `trades.json` → `wager` | The common-material payouts on a loss, each with a `min`/`max` count (see below). |

**Consolation pool (loss payout).** Each entry pays a random amount between `min` and
`max`.

| Material | `min` | `max` |
|---|---|---|
| `stone` | `8` | `15` |
| `iron` | `3` | `8` |
| `wood` | `5` | `12` |
| `coal` | `4` | `10` |
| `clay` | `6` | `14` |
| `quartz` | `2` | `5` |
| `fossil` | `1` | `3` |
| `strange_root` | `1` | `2` |
| `deep_coal` | `2` | `4` |
| `limestone` | `4` | `10` |

One wager-only constant lives outside the JSON: the dice-reveal animation delay
(`WAGER_REVEAL_DELAY`, 2.6 seconds) is a script constant in `VillagerVisitPopup`, pure
presentation. Everything that touches odds or payouts sits in `trades.json`.

## Material Exchange efficiency

The Material Exchange board converts one dug material into another at a loss. It isn't in
`trades.json`; it prices off each material's `trade_value` and one efficiency knob.

| Setting | Where it lives | Default | What it controls |
|---|---|---|---|
| `basic_efficiency` | `balance.json` → `trading` | `0.45` | The Wren-visit exchange rate. Output = `floor(input_qty × trade_value_in ÷ trade_value_out × 0.45 × trade_mult)`. A player recovers about 45% of the value they put in, before any skill/class multiplier. |
| `astrolabe_efficiency` | `balance.json` → `trading` | `0.85` | The **Astrolabe machine's** auto-trade rate (read by `MachineController`, not the Wren popup). The machine converts far more efficiently than a scout visit — about 85% of value. |
| `astrolabe_auto_interval` | `balance.json` → `trading` | `30.0` | Seconds between the Astrolabe machine's automatic conversions. |

`trade_value` for each material lives in `materials.json`
([Materials and Mining Yield](/docs/underroot/materials-and-mining-yield)). Both
efficiencies multiply that value, so editing one material's `trade_value` shifts every
exchange and every price anchored to it. Turn `basic_efficiency` up and hand exchanges get
more generous, closer to break-even. Turn it down and mining the right material directly
beats converting.

## Skill and class modifiers

On top of the JSON prices, the run's **Trading skill** and **chosen class** shift trade value
and wager luck. These are skill-system knobs, not `trades.json` values — the tuning lives in
`balance.json → skills` and the capstone magnitudes are code constants. Full detail in
[Skills, Classes, and Handicaps](/docs/underroot/skills-classes-and-handicaps).

| Modifier | Source | Effect | Where applied |
|---|---|---|---|
| Trading skill bonus | `balance.json → skills` node ladder | Multiplies the material-exchange `trade_mult` by `1.0 + node bonus` (up to +45% at node 5, +75% for a Merchant champion at node 7). | `VillagerVisitPopup._calc_exchange` |
| **Silver Tongue** (Trading capstone, node 5) | code constant | Adds a flat **+0.25** to the trade multiplier **and** multiplies Scout's Wager luck by **×1.25**. Shared — any run that trains Trading to node 5 earns it. | `VillagerVisitPopup` (exchange + wager) |
| **Chieftain handicap** | `class_info.chieftain.handicap.mults` | The Chieftain has "no head for coin": trade value **×0.85** (−15%) and wager luck **×0.50** (−50%). The wager hit is the deeper of the two because it's dodgeable (a Chieftain who never wagers pays nothing). Applied after the skill bonus, so even a Chieftain who trains Trading trades below par. | `SkillManager.class_penalty("trade")` / `("wager")` |

Every modifier in this table reaches the Material Exchange and the Wager only. The
material-for-food ratios and the gold prices are flat for every class and every skill level.

The Merchant is the trade specialist (champion of Trading, no trade penalty, and the trade-value
strength), while the Chieftain is its deliberate opposite — strong village growth bought with
weak trades and wagers. Silver Tongue stacks additively with the Trading skill's bonus, then the
Chieftain penalty (if any) multiplies the result.

## Safe to change or handle with care

- **Material-for-food `cost`/`food_per`** compounds against the whole survival economy.
  Cheap food here can trivialize the early hunger loop. Move in single steps and feel-test.
  Dirt and clay are the early-game knobs; stone only reaches a player past depth 27, so it
  tunes the late game alone. Watch stone especially against its crafting demand — 27 recipes
  want 321 units of it across a run, and it is the one food material the player also needs
  for tools.
- **`success_chance` / `success_chance_post_astrolabe`** are per-roll odds. Small raises
  feel large across a long run. Keep the post-ritual value above the pre-ritual one so the
  wager stays worth playing after the pool grows to ten exotics. Remember Silver Tongue and
  luck cosmetics multiply these, so the effective ceiling is above the JSON number.
- **`basic_efficiency`** is one multiplier on every hand exchange in the game. Change it and
  all material-to-material conversions shift at once. The Trading skill and Silver Tongue stack
  on top of it, so a maxed trader already recovers well above 45%.
- **Exotic `gold_cost` values** are the gold escape hatch for post-Astrolabe materials.
  Set them too low and gold farming replaces deep mining.
- **Gold `tool_offers` prices** (iron axe/pickaxe, dynamite) are gold sinks that also
  shortcut the tool grind. The iron tools are stockable up to 5 spares, so a full restock is
  5× the listed price; too low and gold hoarding replaces crafting. The `gate_recipe` keeps
  them from appearing before the player could craft the item anyway.
- **`berry_yield_mult` on the gloves** (`cosmetics.json`, default `1.2`) is a permanent,
  account-wide food multiplier on every bush the player ever picks. It is bounded by bush
  stock and regrowth, so it scales gently, but it never expires — treat it like a survival
  knob, not a cosmetic one.

Any edit to `trades.json` or `balance.json` needs the data validator and a smoke test
before it ships — see [The Safe Change Workflow](/docs/underroot/the-safe-change-workflow).

## Related

- [The Economy Model](/docs/underroot/the-economy-model)
- [Villager Tasks and Projects](/docs/underroot/villager-tasks-and-projects)
- [Materials and Mining Yield](/docs/underroot/materials-and-mining-yield)
- [Cosmetics and Digger Forms](/docs/underroot/cosmetics-and-digger-forms)
- [Skills, Classes, and Handicaps](/docs/underroot/skills-classes-and-handicaps)
- [The Astrolabe Consequence Curve](/docs/underroot/the-astrolabe-consequence-curve)
- [The Safe Change Workflow](/docs/underroot/the-safe-change-workflow)
- [Where Balance Lives](/docs/underroot/where-balance-lives)
