Derive all combat stats from documented anchors (content_design.md,
'Combat stat anchors'): weapon DPS ~0.6 per threat with a mild size
discount traded for range (railgun m/l damage 17/70), hull HP at 15
per hull threat (drone 60 up to capitals 15500), armor at a 20/threat
premium (armor_plates 640 HP), repair at ~2 HP/s per threat (25 HP per
cycle), salvager range fixed to 60 m with cargo 20, and a monotone
mobility ladder (the placeholder drone was the least agile ship).
Stations anchored to 'a fresh station holds one early parity wave';
enemy level 0 matches the player station and scales per push. HQ 5000
HP. scrap_despawn_seconds 30 -> 120 so capital-sized scrap drops are
collectable.
Rewrite balancing.toml as the canonical 12-arena suite: class mirrors,
equal-threat cross-tier matchups with counts from the verified threat
values, a two-to-one decisiveness check, armored-vs-glass and
repair-escort doctrine matchups, and station assault. The carrier
arena is expected to lose until drone launching exists (hangar is dead
threat) - documented, not stat-compensated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DyCu8vwChKMbLJQ3xosYEN
Four algorithm fixes to bring ThreatCostCalculator.cpp into agreement with
tools/threat_report.py and the newly amended REQ-THREAT-ITEM semantics:
6. Scrap-consuming recipes as threat fallback only. Non-reprocessing recipes
that take scrap as an input are excluded from an item's threat computation
whenever at least one scrap-free recipe (miner/smelter/assembler) produces
that item. Previously the scrap_smelting recipe (1 scrap → 1 iron_ingot)
would have inflated iron_ingot's threat via the max rule.
7. Per-unit item threat. computeRecipeThreatPerUnit() now divides by the
recipe's output amount, so multi-output recipes price each unit correctly.
Example: copper_wire (1 copper_ingot, 1 s, output 2) is now 1.5, not 3.
8. Fixpoint resolution. The resolution loop now alternates the non-reprocessing
pass and the reprocessing pass until neither makes progress, rather than
running the reprocessing pass once at the end. Items downstream of
reprocessing-only items (voidsteel_plate, capital_core, capital hulls,
drone_hangar_module) now resolve correctly.
9. Max rule across staggered recipes. An item is committed only once every
eligible recipe producing it is computable, so a shallow shortcut recipe
(e.g. shortcut_steel_plate: 3 iron_ore → 1 steel_plate, resolvable one
iteration earlier) cannot undercut the expensive base path. A deadlock
fallback (require_all_recipes=False) handles potential recipe cycles.
docs/requirements.md: REQ-THREAT-ITEM amended for per-unit division, the
scrap-fallback rule, and order-independence via fixpoint.
docs/progression_design.md: action items 6-9 removed (completed); remaining
items 1-5 renumbered unchanged.
tools/threat_report.py: NOTE updated — C++ now matches Python semantics.
bin/test/data/config/recipes.toml: four minimal test recipes added (one per
fix: scrap_iron, dual_wire, downstream_product, staggered_item_{cheap,expensive}).
src/test/ThreatCostCalculatorTest.cpp: four new TEST_CASEs covering each fix.
Expected values with the live config (bin/app/data/config) verified by
threat_report.py: iron_ingot 2, copper_wire 1.5, steel_plate 7, control_chip
12, voidsteel_plate 141, capital_core 240; fitted ships 10.5/47/99/233.5/
354.5/722.5/1491.5/1436.5. All 378 test cases pass.
recipes.toml: full v2 rewrite - iron/copper/quartz mining, smelting
incl. the value-losing scrap sink, reprocessing (4 scrap / 4 s,
voidsteel at 20% of the full pool), tiered intermediates, hulls,
module prefabs, and the three drop-only shortcut recipes.
modules.toml: lasers renamed to railguns (implementation unchanged),
prefab materials and numbers-pass production times; combat stats stay
placeholders for the arena pass.
ships.toml: hull-item materials, numbers-pass base production times,
and geometry-validated default_modules loadouts for every ship (waves
now spawn armed).
visuals.toml: item entries for the new palette (quartz, silicon,
copper_coil, control_chip, capacitor_bank, hardened_steel,
ceramic_plate, voidsteel, voidsteel_plate, railgun modules); retired
titanium/alloy/laser items removed.
world.toml: scrap_per_threat = 0.25 per the numbers pass.
threat_report.py: commit an item's threat only once every eligible
recipe is computable - the previous first-resolved-wins behavior let
shortcut recipes underprice items (same flaw exists in
ThreatCostCalculator, recorded as action item 9). Verified: all
default_modules placements valid, verify_recipes and verify_layouts
pass, and the report reproduces the numbers-pass tables exactly
(fitted: 10.5/47/99/233.5/354.5/722.5/1491.5/1436.5). Doc tables
updated for the three geometry-corrected loadouts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DyCu8vwChKMbLJQ3xosYEN