# Progression & Balancing Design Rules and principles that govern the production tree, progression pacing, and balancing. This document contains **rules only** — concrete content (item lists, recipes, unlock levels, stat numbers) lives in the config files and `content_design.md`; those numbers must follow the rules stated here. ## Player-experience goals What each phase of a run should feel like: - **Early:** learning belts and ratios with forgiving chains. The building block economy is the main constraint; the player bootstraps a self-sustaining factory from the starting stock. - **Mid:** deeper chains, the first real ratio puzzles, and the first meaningful drop decisions (which schematic, when to push). - **Late:** combat feeds the factory — capital production requires salvage. Progress means extending and refactoring the existing factory, not rebuilding it. Strange ratios are deliberate optimization puzzles. Overarching: an experienced player gains efficiency through **knowledge** — layout foresight, understanding chains, exploiting shortcut recipes — never through hidden mechanics. An inexperienced setup should not cost much more than an experienced one; experience pays off in how easily the factory adapts later (see Refactorability). ## Resource phases - A run has exactly **four base inputs**: 1. Two mined ores available from the start. 2. A third mined ore unlocked mid-game (slower to mine than the starting ores). 3. A fourth input unlocked late-game, obtainable **only** from reprocessing salvaged scrap. - The fourth input is the core loop hook: capital ship production requires fighting (salvaging and reprocessing), not just mining. - There is no direct "resource unlock" mechanism. Miner recipes unlock **implicitly** (REQ-LOCK-IMPLICIT) when some unlocked schematic's material chain reaches that ore. Resource pacing is therefore controlled entirely through the `unlock_at_station_level` values of ships, modules, and assembler recipe schematics — and the content must guarantee that the chains actually connect (a mid-game schematic must require an item whose chain reaches the third ore, or the ore never unlocks). ## Production tree rules ### Structure - **One new base input chain per phase.** Factory complexity ramps alongside ship size; no phase adds more than one new bottom-level chain. - **Intermediates are generic shared parts.** Keep the item count low — modules and hulls of a tier draw from a shared pool of that tier's intermediates rather than each having bespoke inputs. - **Thematic naming over thematic items.** Inputs should be plausible for what the recipe produces (crystals for lasers, heat sinks for bigger lasers). Achieve this through naming and chain membership, not by adding item types: rename a generic part, don't add a parallel one. ### Ratios - **Ratio "niceness" degrades with tier.** The producer:consumer ratios needed for 100% throughput follow a curve: - Tier 1 (ore → basic material): trivially nice (e.g. 1:1 or 1:2 miner:smelter). - Tier 2: slightly complex but still clean (e.g. 2:3). - Higher tiers: increasingly strange ratios, as deliberate optimization puzzles. - Exceptions in both directions are allowed when there is a reason — a clean late chain as a breather, an odd early chain as a teaser — but the curve is the default. ### Shortcut recipes - Some strange chains get a **shortcut recipe**: an explicitly unlockable assembler recipe schematic (`unlock_at_station_level ≥ 0`, drop-only per REQ-LOCK-EXPLICIT) that skips a step (e.g. t1 → t3 directly) and yields nice ratios for a chain whose base path is strange. - **Not every strange chain gets a shortcut.** Some strangeness is permanent; the absence of a fix is a valid design choice. - **Shortcuts are pure rewards, never balance factors.** An item's threat value is the *maximum* across its producing recipes (REQ-THREAT-ITEM), so unlocking a cheaper recipe does not lower the item's threat accounting — the player gains real factory efficiency without their ships being valued cheaper and without enemy wave budgets shifting. Consequently: **balance every chain around its base (expensive) path**; the shortcut's savings define the size of the reward. ### Refactorability - **Rule (the property):** unlocking the next tier or size of a thing must be an *extension* of the existing production line — adding assemblers and belts to what is already built — never a teardown and rebuild. - **Default technique:** the bigger version introduces one new intermediate that is produced from a subset of the smaller version's inputs (possibly plus one additional low-tier material), and otherwise reuses the smaller version's inputs. Existing lines keep running and feed the new intermediate's assemblers. - The property is the rule; the technique is only the default. It may be broken where it fights thematic plausibility, as long as the property still holds. ## Cost archetypes Every item has two cost knobs: **material quantity** and **cycle time**. Both feed the threat value identically (threat = recursive production-seconds, REQ-MOD-THREAT), so the split between them does not change what an item is *worth* — it changes what kind of **factory pressure** it creates: - **Material-heavy, fast** (e.g. armor plates): simple items; stress belt throughput, splitter logistics, and miner/smelter counts. - **Time-heavy, lean** (e.g. shield modules): technically complex items; few inputs — possibly higher-tier ones — but long cycles; stress assembler counts and parallelization. **Rule:** each module family commits to a clear archetype, so factories supporting different fleet doctrines feel structurally different to build. ## Threat model (balancing backbone) - Threat cost = total recursive production-seconds (REQ-MOD-THREAT). One factory-second equals one threat; player output and enemy wave budgets are denominated in the same currency. - **Rule: combat power per threat is roughly constant** across all ships, modules, and tiers. Higher tiers are better per *ship* and per *module slot*, not per invested factory-second — their advantage is concentration (fewer, bigger things; slot geometry per `content_design.md`) and qualitative capabilities, not a better exchange rate. Deviations from this rule are deliberate and documented. - **Difficulty race:** the enemy threat rate (`threat_rate_formula`) is tuned against the factory output (threat/s) achievable by a competent player — slightly below it early, crossing above it eventually. The game is endless; enemy scaling must ultimately outpace any factory, and player skill shifts *when*, not *whether*. - **All time scaling lives in the threat rate** — waves get bigger, ships of a given schematic never get individually stronger. There is no ship level dimension: stat formulas are plain values, and per-ship level scaling (`ship_level_formula`) does not exist (see Action items). Push scaling on enemy defence stations is the separate, player-triggered difficulty axis and keeps its level formulas. ## Unlock & drop pacing - **Starting set rule:** the schematics unlocked at game start (`unlock_at_station_level = -1`) must be exactly enough to reach the first push unaided — a functioning block loop, small hulls, a basic weapon, and the salvage loop. Nothing more. - The `unlock_at_station_level` ladder mirrors the resource phases: mid-tier hulls/modules/recipes at low station levels, capital content at higher levels. A schematic must not become available before the chains its materials need can be unlocked alongside it. - **No duplicate drops.** Ship and module schematics leave the drop pool once owned, exactly as assembler recipe schematics already do. There are no schematic level-ups; player power grows through unlock breadth and factory scale only, which keeps power-per-threat exact on both sides. The pool therefore shrinks over a run and late pushes increasingly offer artifacts — intended: the late game is a race for the win condition. Per-item progression may return later as Mk2 upgrade recipes (see Open tasks), never as free level-ups. - **Artifacts trade power for progress.** Artifact options compete with schematic picks in the same choice dialog; the artifact chance must be tuned so that taking one is a real decision (giving up a level-up or unlock), not automatic in either direction. ## Scrap & reprocessing economy - Scrap is the bridge from combat back into the factory, with two sinks: **smelting** (same basic materials as ore — the safe, boring option) and **reprocessing** (probabilistic higher intermediates, including the late-game input — the gamble that eventually becomes mandatory). - The reprocessing output pool renormalizes over implicitly unlocked items (REQ-LOCK-REPROCESSING-POOL), so its output quality improves automatically as the run progresses. **Rule:** weights are authored for the *fully unlocked* pool state; early-game behavior falls out of renormalization for free and needs no separate staging. - **Rule: ship scrap drops are derived, never authored.** A destroyed ship drops `threat cost × scrap_per_threat` (a `world.toml` key), with the threat cost computed from its actual hull plus installed modules (REQ-MOD-THREAT) — a kitted-out ship drops more scrap than a bare hull automatically. `ships.toml` carries no scrap value. Defence stations are the exception: they keep authored `scrap_drop_formula`s, because pushing rewards are tuned independently of ship production costs. - Consequence: the threat value of scrap is the constant `1 / scrap_per_threat`. The min-`scrap_drop` schematic derivation (REQ-THREAT-SCRAP) and its potential circularity disappear. - **Rule:** the late-game input's income rate meaningfully gates capital production. The tuning target is expressed as "capital ships per boss cycle for a player who fights at parity", not as an absolute rate. ## Building block economy - Building blocks are the only global currency and the early game's central constraint. The early game is a bootstrap problem: convert the starting stock into a self-sustaining block loop before the first waves bite. - **Rule:** the starting stock suffices for a minimal block loop plus the first shipyard — with a little slack for beginner mistakes, but not enough to skip the loop entirely. - **Rule:** asteroid expansions compete with buildings for the same currency. Expansion pricing makes "more space" a real alternative to "more stuff", not an afterthought. ## Numeric guardrails Constraints that every recipe must respect, independent of tuning: - **Belt throughput:** belt speed and per-tile capacity cap how fast a single belt can feed an input. A recipe whose per-cycle inputs cannot be sustained by one belt per input at 100% duty cycle is a *deliberate* design (forcing parallel belts/splitters as part of a high-tier puzzle) — never an accident of quantity choice. - **Buffer burstiness:** input buffers hold 2× the per-cycle amount (REQ-MAT-INPUT-BUFFER), so large per-cycle quantities create bursty belt demand. Low tiers prefer small quantities with short cycles; big-batch recipes are reserved for high tiers where burstiness is part of the puzzle. - **Cycle times scale with tier** monotonically — a higher-tier item never has a shorter total chain time than a lower-tier item of the same role. ## Open tasks / future work - **Rework `recipes.toml`** once the rules in this document are fixed: the current tree feels too close to Factorio; apply the thematic-naming rule and the ratio curve to it (renames and quantity changes, not new items). - **Balancing pass** (see placeholders in `content_design.md`): set the `unlock_at_station_level` ladder, real threat costs and `default_modules`, reprocessing weights, and the threat-rate formulas according to the rules above. - **Mk2 upgrade recipes** — the deferred design for per-item progression, to revisit once the config has stabilized. A duplicate-style drop unlocks a distinct `*_mk2` item whose recipe consumes the Mk1 item plus higher-tier parts. This preserves power-per-threat (the extra power is paid in real production-seconds, since threat is recursive), satisfies the refactorability rule (the Mk1 line keeps running and feeds one new assembler), and keeps balancing one-dimensional (no level variable anywhere). Enemy-side progression happens via `default_modules` variants per era instead of a level formula. ## Action items — changes beyond this document Agreed changes that require edits to `requirements.md`, the code, and the configs: 1. **Derive ship scrap from threat.** Add `scrap_per_threat` to `world.toml`; remove `[ship.loot].scrap_drop` from `ships.toml`; update REQ-RES-SCRAP-DROP; replace REQ-THREAT-SCRAP with the constant `1 / scrap_per_threat`. Station `scrap_drop_formula`s stay. 2. **Remove schematic upgrades.** Owned ship/module schematics leave the drop pool (REQ-DEF-SCHEMATIC-DROP); drop the new-unlock/level-up annotation from the choice dialog; remove `player_production_level` from `ships.toml`, `modules.toml`, and the code paths that increment and evaluate it (REQ-BLD-SHIPYARD, REQ-MOD-CONFIG). 3. **Remove ship levels entirely.** Delete `ship_level_formula` (REQ-WAV-SHIP-LEVEL); replace all stat formulas in `ships.toml` and `modules.toml` with plain values (REQ-SHP-STATS, REQ-MOD-CONFIG, REQ-MOD-STAT-CALC evaluation rules). Enemy defence stations keep their station-level formulas — push scaling is unaffected. 4. **Balancing tool follow-up.** Remove the per-ship-entry `level` from `balancing.toml` and the `L` display format (REQ-BAL-TEAM, REQ-BAL-CONFIG-GAME, REQ-BAL-UI-WIDGET, REQ-BAL-UI-INSPECT-WINDOW); station entries keep their level. Ship stats panels no longer evaluate at a level (REQ-MOD-UI-STATS-PANEL, REQ-UI-SHIP-STATS-PANEL). 5. **Fill unfillable schematic slots with artifacts.** With duplicates removed, the schematic drop pool can run dry — previously unreachable. Decision: every slot in the choice dialog that cannot be filled with a schematic because the eligible pool is exhausted is filled with an artifact option instead (in addition to any artifact option granted by the regular artifact roll). A push therefore always awards a full dialog. Update REQ-DEF-SCHEMATIC-DROP. 6. **Confirm wave scaling carries alone.** With per-ship level scaling gone, `threat_rate_formula` is the only time-scaling axis; verify the current `world.toml` values still produce the intended difficulty curve (the config reportedly already runs with a flat ship level, so this is likely a review, not a retune).