Files
dota_factory/docs/balancing/history.md
Malte Langkabel a93f7c3897 Arena round 6: revert railgun_m damage, correct playtest record
Arena re-run after the playtest-1 adjustments:

- spam-cruiser arena landed at par (default +9%) - the range buff alone
  priced out the small-gun-spam meta, so revert railgun_m damage 16 -> 14
  (range stays 80). The buff had regressed drone-swarm-vs-cruisers to
  +47%, largely via a hit-count breakpoint (60 HP drone: 5 hits at
  14 dmg, 4 at 16).
- battleship +30% / dreadnought +29% vs pure railgun_s fleets accepted
  as reach-doctrine texture (the l gun's 130 m standoff working as
  intended); repair kept at 4 HP/s (below par in-fight is the correct
  price for free between-wave sustain).

Also corrects the playtest-1 record: it was two FULL playthroughs won in
~40 min each with cruisers only (not two pushes) - a 2.5-3x run-length
gap. Pacing knobs deliberately deferred to playtest 2, since those runs
predate the repair nerf and the l-gun siege range.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DyCu8vwChKMbLJQ3xosYEN
2026-07-06 22:10:06 +02:00

8.8 KiB
Raw Blame History

Balancing History

Chronological record of the balancing work: what was decided, what was found, what changed. Current values live in derived.md; this file explains how they got there.

2026-07-02/03 — rules and structural decisions

  • Rules document written (now rules.md): ratio curve, shortcut recipes, refactorability, cost archetypes, threat model, growth curve.
  • Scrap derived from threat (scrap_per_threat), replacing authored per-ship scrap drops; scrap threat became the constant 1/scrap_per_threat, removing the old min-scrap_drop derivation and its circularity.
  • Duplicate schematic drops removed (no level-ups); ship/module levels removed entirely — all time scaling lives in the threat rate, push scaling stays on stations. Mk2 upgrade recipes noted as the future per-item progression.
  • Growth-curve rules added: escalating expansion costs, designed doubling time, growth limited by economy not waiting; resource deposits designed (deposit-gated mid resource in expansion territory).
  • Production tree v2 decided: iron/copper everywhere (M-type asteroid), quartz in geodes (mid), voidsteel battle-forged from scrap (late); titanium dropped; lasers renamed to railguns, lasers reserved as a future weapon type.

2026-07-03 — targets, tree, numbers

  • Balancing targets fixed: ≤2 h run, phases 15/614/15+, factory curve 25/60/120/150, threat ladder, 25-ship swarm, block roots.
  • Tree structure drafted and numbers computed (recursive threat calculator); ratio curve realized; fitted ships within 96124% of the strawman ladder (small end hot from fixed chain overhead — ladder later adopted the achieved values).
  • Rule bugs found by the numbers work: the scrap→ingot smelter recipe would inflate basic materials via the max rule (fixed: scrap-consuming recipes are threat fallback only); recipe output amounts were ignored (fixed: per-unit division); items downstream of reprocessing-only items never resolved (fixed: fixpoint resolution); a shortcut recipe resolving earlier than the base path silently underpriced items (fixed: commit only when all eligible recipes are computable). All four fixed in ThreatCostCalculator with tests, and implemented in tools/threat_report.py.
  • v2 tree written into the configs; default_modules loadouts geometry-validated (the numbers-pass loadouts for battlecruiser and dreadnought were geometrically impossible — L-modifiers don't fit beside full gun complements; corrected loadouts landed closer to the ladder).

2026-07-04 — combat stats, arena rounds 15

Initial stats derived from the anchors (weapon DPS ≈0.6/threat flat, hull 15 HP/threat, armor 20/threat, repair 2 HP/s/threat, station range 200).

  • Round 1: concentrated fleets won all equal-threat cross-tier matchups flawlessly; glass beat armored; repair escort flawless; two stations shrugged off a 3× swarm. Changes: concentration tax on m/l gun damage (railgun_m 17→14, railgun_l 70→52), armor 640→1000, repair 25→12, station range 200→120. (Team-1 "bias" in mirrors later shown to be noise.)
  • Round 2 (EHP-margin logging added): battleship +33% while dreadnought 37% (stabilizer range + opposing armor); glass still +11%. Changes: stabilizer range ×1.5→×1.3; per-hull trims introduced (BC 2700→2500, BS 7500→7000, DN/CV 15500→19000).
  • Round 3 (narrow lanes — geometry fixed into the fixture): DN closed to 11%, BS +22%, swarm flipped to +14% over cruisers, glass +12% third time. Changes: armor 1000→1200, BC 2500→2000, BS 7000→6300, DN/CV 19000→22500.
  • Round 4: glass-vs-armored resolved (+3% armored); noise floor established (~±10%/run: BS ignored a 10% EHP cut; repair drifted 14→24% untouched). Convergence policy adopted: two-round signals only, ±20% converged. Changes: BC 2000→2200, DN/CV 22500→24000; BS +23% accepted as doctrine texture (mechanical range edge vs. pure small fleets).
  • Round 5 (durations logged; end-condition bug fixed upstream): TTK anchor validated (mirrors 23/71/95 s; DN-vs-swarm 214 s outlier accepted); dreadnought +3%, everything else inside band. Final changes: BC 2200→2400, repair 12→9 (persistent +24% escort margin). Combat pass declared converged.

2026-07-05/06 — pacing pass

  • Unlock ladder set (starting set drone/frigate/railgun_s/salvager; quartz gate at level 2; capitals at 89 with unlock_requires chains); threat rate 2*x + 0.15*x*x; starting blocks 1000→200; expansion 400 flat pending the cost formula; artifacts 3→5.
  • Bug found: the building_block recipe was silently locked at game start (building blocks appear in no schematic's materials, so implicit unlocking could never reach the recipe) — fixed with an explicit unlock_at_station_level = -1.
  • Expansion cost formula implemented and set (300 + 50*x + 10*x*x): quadratic, so costs outrun the roughly linear block income gradually — ~1 expansion per cycle mid-game, 23 cycles apart late.
  • First full balancing round complete. Next: full-game playtests against the run-shape targets.

2026-07-06 — playtest 1 (two full playthroughs)

Two complete runs, WON in ~40 min each with cruiser fleets only — never needing capitals. (Initially misread as "two pushes in 40 min, pacing on target"; corrected in round 6.) That is roughly cycle 8 against the win-cycle target of 2024: a 2.53× pacing gap. Pacing knobs deliberately untouched this round — the runs rode 9 HP/s repair and stations nothing outranged, both nerfed below; playtest 2 measures the remaining gap.

  • Meta finding: cruisers filled with 12× railgun_s dominate. Predicted by the numbers in hindsight: the concentration tax makes railgun_s the best DPS/threat (0.62 vs m 0.48, l 0.41), range is the big guns' only mechanical edge (armor is added HP, not damage reduction — no anti-swarm mechanic), repair sustain covers the closing distance, and stations outranged every ship gun (120 vs railgun_l's 100), so even capitals had to tank-and-brawl. The cruiser compounds it: first hull with a large 1×1 canvas (12 cells) and a nearly quartz-free chain.
  • Repair tool confirmed overpowered (second signal after the persistent +24% arena escort margin): the arena only prices in-fight sustain; real runs add free full top-offs in every 1545 s wave gap across the whole swarm. The 0.7 HP/s-per-threat prior is wrong for wave defence.
  • Changes: repair_tool 9→4 HP/s; railgun_l range 100→130 (now outranges stations — buys the siege role the capital ladder promises); railgun_m 14→16 dmg and range 70→80 (tax softened: m sits at 0.55 DPS/threat, between s and l). Module threats unchanged (costs untouched), so no ladder recalculation needed.
  • New tracked arena added: railgun_s-spam cruisers (8× 178) vs default cruisers (6× 233.5) — the spam side should win a brawl somewhat, but a blowout means the small-gun premium needs retuning.
  • Open: re-run the arena suite to check the range/damage changes against the round 15 results; next playtest should verify big guns now feel worth climbing to and repair is merely good.

2026-07-06 — arena round 6 (checking the playtest-1 adjustments)

Mirrors healthy (58% margins, durations 24/66/91 s). Results:

  • Spam-cruiser arena: default cruisers +9% — the meta is priced out, and the range buff alone did the work.
  • Regression: drone swarm vs cruisers +47% for cruisers (was +14% swarm in round 3). Besides the wider range gap, the damage buff crossed a breakpoint: 14 dmg kills a 60 HP drone in 5 hits, 16 in 4 — a hidden ~25% effective-DPS gain vs drones. Change: railgun_m damage 16→14 (range stays 80); the tax stands, reach is the compensation.
  • Battleship +30% and dreadnought +29% vs pure railgun_s fleets: accepted as reach-doctrine texture (BS was already accepted at +23%) — the l gun's 130 m standoff is exactly what the range buff bought; the counter is your own reach or 2:1 numbers, not equal-threat small guns. Watch, don't tune.
  • Repair escort flipped to raw +16%: kept at 4 HP/s deliberately — the arena cannot price the free between-wave top-offs, so slightly below par in-fight is the correct price for a module whose run-value includes them. Playtest 2 decides; 6 is the fallback if repair feels dead.
  • Station assault: the 3× swarm cracked the fortified position keeping 45% EHP. No knob this round touched it; together with playtest 1's trivially easy pushes it flags station strength as the first pacing lever for the next pass.

Pacing deferred: playtest 1's 40-min wins predate the repair nerf and the l-gun siege range. If playtest 2 still wins by ~cycle 10, the levers are enemy station scaling (3000 + 1500*x likely too shallow), the threat rate, and possibly artifact_win_count.