# Materials and Mining Yield

Each entry in `data/materials.json` carries the tuning fields that decide how long a
material takes to dig, how much it wears your tool, how many units one tile drops, what it
sells for, and how tough it is as a wall. Change these to reshape a material's role in the
economy and the dig curve.

## In plain terms

Every diggable thing in the world is one entry in `materials.json`. A handful of numeric
fields on that entry set its whole personality: a cheap early filler like dirt, a valuable
deep ore like quartz, a fortress-grade wall block. There's no separate materials script to
edit; the JSON is the whole tuning surface. A couple of fields (`dig_time`,
`durability_cost`) have hardcoded fallbacks in the dig code that only apply when the key is
missing, so always set them explicitly on a real material.

A note on units used below:

- **tile** — one 32-pixel cell of the world grid. Digging removes one tile.
- **unit** — one item of the material added to your inventory. One tile can drop several
  units (see Variable yield).
- **tier** — an integer difficulty rank (`material_tier`) shared with tools. A pickaxe can
  only break materials up to its own tier (plus one, at heavy cost).
- **VP (Value Point)** — the economy's price anchor; `trade_value` is a material's VP worth.

## The tuning fields

| Setting | Where it lives | What it controls | Turn it up / down |
|---|---|---|---|
| `dig_time` | `materials.json` → `<mat>` | Seconds to dig one tile at 1x tool speed. Actual time is `dig_time` divided by the tool's `dig_speed_multiplier`. | Higher = slower to mine; the single biggest lever on how tedious a layer feels. Fallback `2.0` if missing. |
| `gather_time` | `materials.json` → `<mat>` | Seconds to harvest one unit of a surface/forest source (wood, etc.) at 1x. | Mirror of `dig_time` for gathered (non-terrain) sources. |
| `terrain_hp` | `materials.json` → `<mat>` | How much "health" a buried tile has. Machines (drills) chew this down at their work rate; hand-digging uses `dig_time` instead. | Higher = machines take longer per tile. Pair it with `dig_time` so hand and machine mining feel consistent. |
| `wall_hp` | `materials.json` → `<mat>` | Hit points of a single wall layer built from this material — how much Maw chewing it absorbs. `0` means the material cannot be a wall. | Higher = sturdier walls. This is the core defensive lever; see the wall-material table below. |
| `base_chew_resistance` | `materials.json` → `<mat>` | A secondary hardness factor a wall of this material applies against the Maw, on top of `wall_hp`. `0` for non-wall materials. | Higher = the Maw makes slower progress even once it starts biting. |
| `trade_value` | `materials.json` → `<mat>` | The material's worth in Value Points — the anchor every villager trade, task reward, and exchange prices off. | Higher = more food/gold per unit at the trade window. Ripples across the whole economy; nudge gently. |
| `durability_cost` | `materials.json` → `<mat>` | Tool durability spent per tile dug. Multiplied by 4 when a tool digs one tier above its rating (see Tools and Durability). | Higher = tools wear out faster on this material. Fallback `1.0` if missing. |
| `material_tier` | `materials.json` → `<mat>` | The difficulty rank that gates which pickaxe can break it. A tool digs up to its `max_material_tier`, plus exactly one tier higher at 4x durability cost. | Raising a tier pushes a material later in progression and demands a better pickaxe. |
| `first_depth` | `materials.json` → `<mat>` | The shallowest depth (in tiles below the surface) at which this material can appear. Used to keep a material out of layers above where it belongs. | Higher = the player meets it deeper. Layer bands themselves live in `layers.json`. |
| `yield_weights` | `materials.json` → `<mat>` | A list of weights driving how many units one tile drops (see Variable yield). Omit it and every tile drops exactly 1. | Longer / flatter list = bigger and more variable hauls per tile. |

Supporting flags on the same entries: `is_wall_material`, `is_crafting_material`, `is_fuel`
(with `fuel_seconds` and `work_rate_mult` for how long it burns and how much it speeds a
machine), `source_type` (terrain / forest / refined / processed / discovery / exotic /
astrolabe / machine / supply), and `max_stack` for placeable consumables like dynamite.

## Variable yield: how `yield_weights` works

Most tiles drop one unit. Give a material a `yield_weights` list and each dig instead rolls a
weighted random amount. The list reads positionally: the weight at position 1 is the chance
of dropping 1 unit, position 2 the chance of 2 units, and so on. The dig code
(`roll_yield` in `TerrainDigging.gd`) sums the weights and picks a bucket proportionally, so
they don't need to add up to 100. The weights are relative.

Worked example — dirt is `[94, 5, 1]`:

- 94 out of 100 digs drop 1 unit, 5 drop 2, 1 drops 3.
- Average haul ≈ 1.07 units per tile — essentially always 1, with a rare bonus.

Worked example — sulfur is `[25, 20, 18, 15, 12, 10]`:

- Six buckets, so a tile can drop anywhere from 1 to 6 units.
- Average haul ≈ 3.0 units per tile — a deliberately generous, swingy source.

Want bigger hauls? Add more buckets or shift weight toward the later positions. Want a
stingier, more predictable material? Concentrate weight on bucket 1.

### Skill and class modifiers on yield

Two skill-system effects sit on top of `yield_weights`. They're **not** in `materials.json` —
the skill tuning lives in `balance.json → skills` and the capstone is a code constant. Full
context in [Skills, Classes, and Handicaps](/docs/underroot/skills-classes-and-handicaps).

- **Rich Veins** (Digging capstone, skill node 5, shared) — after a tile's yield is rolled,
  there's a **~10% chance to double the drop** (`randf < 0.10`, `grant ×= 2` in
  `TerrainDigging.gd`). Any run that trains Digging to node 5 earns it; a Miner reaches it
  fastest.
- **Mason forage handicap** — a Mason run harvests **12% less from foraging** (`harvest_yield`
  ×0.88, applied in `SkillManager.scaled_yield` for foraging sources only, never on
  underground digs). It's the Mason's class trade-off for stronger walls. Note this scales
  *forest/surface* hauls, not dug-tile yield.

Foraging yield is also lifted by the Foraging skill bonus itself (`scaled_yield` multiplies by
the skill's `get_mult`), so a trained Hunter out-harvests everyone and a Mason under-harvests.

## Natural terrain materials (the mining curve)

The dig-and-descend materials, in roughly the order the player meets them. Numbers are the
exact current defaults.

| Material | `first_depth` | `dig_time` | `terrain_hp` | `wall_hp` | `base_chew_resistance` | `trade_value` | `durability_cost` | `material_tier` | `yield_weights` |
|---|---|---|---|---|---|---|---|---|---|
| Dirt | surface | `1.0` | `10` | `30` | `0.5` | `1` | `0.5` | `1` | `[94,5,1]` |
| Clay | `13` | `2.0` | `20` | `60` | `1.0` | `3` | `0.75` | `1` | `[93,6,1]` |
| Stone | `27` | `5.0` | `50` | `150` | `2.0` | `3` | `1.0` | `2` | `[93,5,2]` |
| Coal | `27` | `4.0` | `30` | `0` | `0.0` | `3` | `1.0` | `2` | `[92,6,2]` |
| Sulfur | `52` | `6.0` | `35` | `0` | `0.0` | `5` | `1.0` | `2` | `[25,20,18,15,12,10]` |
| Iron Ore | — | `8.0` | `60` | `0` | `0.0` | `8` | `1.5` | `3` | `[80,15,5]` |
| Dense Stone | `113` | `9.0` | `80` | `250` | `3.5` | `12` | `2.0` | `4` | `[92,5,3]` |
| Copper Ore | `141` | `10.0` | `65` | `0` | `0.0` | `15` | `2.0` | `4` | `[92,5,3]` |
| Tin Ore | `141` | `10.0` | `60` | `0` | `0.0` | `15` | `2.0` | `4` | `[92,5,3]` |
| Limestone | `201` | `8.0` | `55` | `180` | `2.5` | `16` | `2.5` | `5` | `[91,6,3]` |
| Deep Coal | `233` | `7.0` | `45` | `0` | `0.0` | `16` | `2.0` | `5` | `[91,7,2]` |
| Quartz | `263` | `20.0` | `120` | `0` | `0.0` | `50` | `3.0` | `6` | `[90,7,3]` |

Wood is the odd one out: a forest source with `dig_time 0`, `gather_time 2.0`, `wall_hp 50`,
`trade_value 2`, and `yield_weights [85,10,5]`. It is harvested from trees, not dug.

Coal and Deep Coal are fuels: coal burns `60` seconds at `work_rate_mult 1.0`; deep coal
burns `120` seconds at `1.25`. (Crude oil `200s / 1.5` and ethanol `280s / 1.8` are processed
fuels — see Machine Tuning.)

## Exotic and Astrolabe materials (endgame)

These show up only after the Astrolabe ritual seeds them, or as high-tier deposits. They
carry no `trade_value` (not sold at the window) and no `yield_weights` (drop 1 per tile),
and none are wall materials.

| Material | Source | `first_depth` | `dig_time` | `terrain_hp` | `durability_cost` | `material_tier` |
|---|---|---|---|---|---|---|
| Root Amber | astrolabe | — | `6.0` | `35` | `2.5` | `5` |
| Pale Chalk | astrolabe | — | `5.0` | `28` | `2.0` | `5` |
| Wavellite | astrolabe | — | `8.0` | `42` | `3.0` | `6` |
| Magnetite | astrolabe | — | `9.0` | `52` | `3.0` | `6` |
| Ancient Clay | exotic | `13` | `14.0` | `55` | `3.0` | `6` |
| Obsidian | astrolabe | — | `12.0` | `65` | `3.5` | `7` |
| Chromite | astrolabe | — | `14.0` | `70` | `3.5` | `7` |
| Ember Essence | exotic | — | `22.0` | `85` | `4.0` | `7` |
| Prismatic Shard | exotic | `113` | `18.0` | `90` | `4.0` | `7` |
| Void Iron | exotic | — | `28.0` | `110` | `4.5` | `7` |

Only the Quartzite Pick (tier 7) or the Smith's Grand Pick can break tier-7 exotics — see the
pickaxe ladder in Tools and Durability.

## Champion-forged materials (Grand Anvil)

Two materials exist only through the Smith's **Grand Anvil** landmark (Crafting skill node 3,
champion-only — see [Machine Tuning](/docs/underroot/machine-tuning)):

- **`grand_alloy`** — a `processed` crafting material (`is_crafting_material true`, not a wall
  and not sold). Forging it on the Anvil also opens the `grand_pickaxe` masterwork recipe.
- **`glazed_vault_block`** — a `crafted` wall material and the **toughest wall in the game**:
  `wall_hp 5000`, `base_chew_resistance 7.0`. Because it's champion-gated it doesn't shift the
  baseline defensive economy, but it's the number to watch if a Smith run makes the Maw feel
  trivial.

## Wall materials at a glance

`wall_hp` and `base_chew_resistance` together set how much punishment one wall layer takes.
Raw terrain, refined metals, and crafted/glazed blocks span a wide range:

| Wall material | `wall_hp` | `base_chew_resistance` | Source |
|---|---|---|---|
| Glass | `10` | `0.4` | processed |
| Dirt | `30` | `0.5` | terrain |
| Wood | `50` | `0.8` | forest |
| Clay | `60` | `1.0` | terrain |
| Stone | `150` | `2.0` | terrain |
| Limestone | `180` | `2.5` | terrain |
| Glazed Stone | `225` | `2.5` | crafted |
| Dense Stone | `250` | `3.5` | terrain |
| Cement | `320` | `3.0` | processed |
| Glazed Cement | `480` | `3.8` | crafted |
| Iron | `400` | `3.5` | refined |
| Bronze | `520` | `4.2` | refined |
| Glazed Iron | `600` | `4.5` | crafted |
| Glazed Bronze | `720` | `5.0` | crafted |
| Steel | `750` | `5.5` | refined |
| Glazed Steel | `1125` | `7.0` | crafted |
| Vault Block | `1600` | `6.5` | crafted |
| Glazed Vault Block | `5000` | `7.0` | crafted (Grand Anvil, Smith champion) |

Walls stack up to 9 layers, each layer costing one raw unit, so effective defense is
`wall_hp` times the stack height. Raise any single `wall_hp` value and it multiplies
straight through the whole defensive economy. Treat it as a high-impact lever. The Glazed
Vault Block sits far above the rest on purpose — it's a champion payoff, not a mid-run wall.

## Safe to change / handle with care

- **`trade_value`** feeds the entire villager economy: trades, task rewards, exchange rates.
  A change here is felt everywhere prices are quoted. Move it a point or two and re-check the
  trade window; don't jump it.
- **`wall_hp`** scales defense linearly and then stacks up to 9x. Small increases make late
  walls much tankier; large ones can trivialize the Maw. The Glazed Vault Block already sits
  at the ceiling (5000) — don't raise it without checking the Maw's late-game chew rate.
- **`material_tier`** gates progression. Bumping a common material's tier can strand a player
  who has no pickaxe able to break it. Verify a reachable tool covers every tier.
- **`dig_time` and `terrain_hp`** should move together. Change one without the other and
  hand-digging and machine-digging disagree on how hard a material is.
- **`first_depth`** set too deep can make a required crafting input unreachable at the point a
  recipe needs it. Cross-check against `layers.json` bands.
- **Yield is also skill-scaled.** Rich Veins (~10% double dig) and the Foraging skill/Mason
  handicap sit on top of `yield_weights`, so a maxed player's real haul runs above the raw
  averages here. Those live in the skill system, not `materials.json`.

Any edit to `materials.json` needs the data validator and, for gameplay-affecting numbers, the
smoke test — see [The Safe Change Workflow](/docs/underroot/the-safe-change-workflow).

## Related

- [Tools and Durability](/docs/underroot/tools-and-durability)
- [Machine Tuning](/docs/underroot/machine-tuning)
- [Skills, Classes, and Handicaps](/docs/underroot/skills-classes-and-handicaps)
- [Layers and Progression Pacing](/docs/underroot/layers-and-progression-pacing)
- [The Economy Model](/docs/underroot/the-economy-model)
- [Village Buildings](/docs/underroot/village-buildings)
- [The Safe Change Workflow](/docs/underroot/the-safe-change-workflow)