Skill Chain
godot-resource-data-patterns → godot-economy-system →
(godot-combat-system | godot-rpg-stats | godot-game-loop-waves) →
godot-monte-carlo-balancer → godot-testing-patterns → godot-builder
The Iron Law: Source-Extracted, Zero Config
No hand-copied numbers in the sim. Parse Resources / source at startup so the next run reflects designer edits.
Abstract Model (mandatory Phase 0)
| Abstraction |
Meaning |
If absent |
| Session |
Bounded attempt |
— |
| Threat |
Pressure toward fail |
delete |
| Defense / agency |
Player levers |
delete |
| Faults |
Attention taxes |
delete |
| Resources |
Consumable flow |
delete |
| In-run economy |
Session spend |
delete |
| Meta economy |
Shop / unlocks / prestige |
delete |
| Grade |
Stars / rank / time / score |
delete |
Write BALANCE_PLAN.md. Simulate only mapped rows.
Progressive disclosure
MANDATORY: Read the linked reference before implementing that phase.
Do NOT Load:
- example-lane-defense.md — unless Phase 0 maps to lane-defense / shift TD
- 06-genre-adaptation.md — unless genre ≠ default PvE win%-band session
- 07-godot-calibration.md — only when starting calibration or Phase 0 did not waive physics/AI (waiver = fully formulaic math-only game, documented in BALANCE_PLAN.md)
Phase 0 — Audit → [references/00-game-audit.md](references/00-game-audit.md)
Genre, win/fail, modes, catalog, influence graph, economy, styles + primary metric, extraction plan. Confirm with designer.
Phase 1 — Extract → [references/01-source-extraction.md](references/01-source-extraction.md)
Resource-first decision tree; inspect before any simulate.
Phase 2 — Sim → [references/02-simulation-engine.md](references/02-simulation-engine.md)
Behavioral PlayStyle × InputModel (mouse/touch/gamepad), SessionModel for mobile, seeded SmallRng, rayon over independent jobs.
Phase 3 — Analyze → [references/03-analysis-reporting.md](references/03-analysis-reporting.md)
Wilson/bootstrap CI verdicts; secondary agency checks; stable JSON.
Phase 4 — Economy → [references/04-economy-retention.md](references/04-economy-retention.md)
Careers, farms, interest curve, reward-cadence checkpoints.
Phase 5 — Tune → [references/05-tuning-generation.md](references/05-tuning-generation.md)
Band-scored bruteforce; emit .tres when the project is Resource-first.
Phase 6 — Genre → [references/06-genre-adaptation.md](references/06-genre-adaptation.md)
Metric overrides + Domain Skill chains.
Phase 7 — Calibrate → [references/07-godot-calibration.md](references/07-godot-calibration.md)
3–5 golden cells vs headless Godot before full-matrix sign-off (unless waived).
Bundled Resources
Canonical layout after copy:
tools/
balance_lab.ps1 # from launcher.ps1
balance_lab.sh # from launcher.sh
balance_lab/
Cargo.toml
src/main.rs # clap stubs — expand per Phase 0
[scripts/balance-lab-template/](scripts/balance-lab-template/)
Copy Cargo.toml + src/ into tools/balancelab/. Place launchers as tools/balancelab.ps1 / tools/balance_lab.sh (siblings of the crate dir).
[scripts/comparebalancesnapshots.py](scripts/comparebalancesnapshots.py)
CI-aware snapshot diff.
[references/json-schema.md](references/json-schema.md)
Stable --json field contract.
CLI Contract
balance-lab inspect
balance-lab simulate --level 3 --style average --runs 1000
balance-lab career --style casual --runs 200
balance-lab mode <key> --runs 500
balance-lab bruteforce --level 4 ...
balance-lab gen-level ...
balance-lab calibrate --cells golden.json
balance-lab --json <any command>
balance-lab --seed 42 <any command>
Target Bands (default; Phase 0 overrides)
Bands are defined per style × input_model cell. Default input model is mouse.
| Style |
Input |
Win-rate target |
Below → |
Above → |
| afk |
mouse |
5% – 55% |
TOO HARD |
TOO EASY |
| casual |
mouse |
55% – 90% |
TOO HARD |
TOO EASY |
| average |
mouse |
70% – 95% |
TOO HARD |
TOO EASY |
| pro |
mouse |
90% – 100% |
TOO HARD |
— |
| afk |
touch |
5% – 55% |
TOO HARD |
TOO EASY |
| casual |
touch |
55% – 90% |
TOO HARD |
TOO EASY |
| average |
touch |
65% – 92% |
TOO HARD |
TOO EASY |
| pro |
touch |
85% – 100% |
TOO HARD |
— |
A level is only OK when every simulated style × input_model cell lands inside its band. Difficulty must come from the level curve, not from punishing input speed alone.
Platform Rule: If the game ships on mobile, the matrix MUST include touch input models. A level that is OK on mouse but TOO HARD on touch is TOO HARD.
CI verdict law (single source of truth)
| Mode |
Runs/cell |
OK rule |
| Search / working |
100–300 |
95% CI overlaps band; else TOOHARD / TOOEASY / INCONCLUSIVE |
| Sign-off / DoD / snapshot |
≥1000 |
95% CI fully ⊆ band for every style × shipped input model |
Fighting / educational / idle often replace win% — set primary metric in Phase 0.
NEVER Do
Data & Extraction
- NEVER hardcode game numbers or skip existing Resources /
.tres — hand copies rot into false conclusions; regex farms on Resource projects fight the data layer. Resource-first; regex only for inline formula coefficients. Flag every (default!) in inspect before the first simulate.
- NEVER skip embedded formulas — extract coefficients; one reimplementation in sim. Shape change must fail the regex loudly.
Simulation Fidelity
- NEVER simulate only optimal play — a pro-only PASS ships an unplayable floor; AFK/casual failures are the bug players feel.
- NEVER model humans as instantaneous — zero-delay agents clear jam/fault windows real players miss; difficulty collapses into twitch gates.
- NEVER reuse desktop reaction/tap parameters for mobile — touch has lower taps/sec, higher miss chance, and occlusion; balancing against mouse numbers ships an unplayable mobile game.
- NEVER assume uninterrupted sessions on mobile — model interruptions (notifications, app switching) and session-length caps; a level requiring 12 minutes of unbroken attention fails the platform.
- NEVER let precision-dependent mechanics go untested on touch — any mechanic requiring accurate/fast pointing must be simulated with the touch accuracy model before sign-off.
- NEVER skip meta-game — omit shop/upgrades/modes/replay → “balanced” sessions with broken careers.
- NEVER use unseeded or
HashMap-hashed seed paths — default hasher is process-randomized → false CI diffs across machines/rayon schedules; use seed_for + stable hash; unit-test determinism.
- NEVER share
RunState/RNG across rayon jobs — cross-talk masquerades as balance noise and breaks reproducibility.
- NEVER claim mathematical balance from an uncalibrated physics/AI model — Phase 7 or documented waiver; abstract DPS ≠ Godot collisions.
Judging Balance
- NEVER judge by a single average — histograms, downtime, failure-by-kind, resource ratios hide coin-flips vs skill cliffs.
- NEVER verdict on point estimates alone — CI law (search overlap / sign-off ⊆); ≥300 search, ≥1000 sign-off.
- NEVER declare winnable without resource-flow checks — pressure AND income vs consumption (classic starved-but-“beatable” bug).
- NEVER balance difficulty and economy separately — clear-time changes currency/minute; re-run careers after difficulty edits.
- NEVER over-nerf a farm without re-checking shop reachability — post-exploit patches often strand the ladder.
- NEVER balance PvP with sole AFK→pro PvE bands — matchup / MMR metrics.
Tuning & Maintenance
- NEVER tune one session in isolation — full matrix + career after changes.
- NEVER accept generated content without sim validation.
- NEVER emit
.gd factories into a Resource-first project — emit .tres / Resource shape.
- NEVER cache
GameData across game-source edits.
- NEVER make designers compile manually — self-rebuilding launchers; stale binaries → stale conclusions.
- NEVER stdout-only for agents —
--json + gamedatahash.
Golden path (first engagement)
- Phase 0 →
BALANCE_PLAN.md + designer lock on bands/metrics.
- Phase 1 extract →
inspect → if unexpected (default!), stop and fix extract ([example-lane-defense.md](references/example-lane-defense.md) smell).
- Phase 2–3: one cell at 300 runs (Search overlap) → full matrix → SignOff ⊆ at 1000.
- Phase 4 career → farm/shop flags → Phase 7 calibrate (unless waived) → snapshot JSON.
Definition of Done
inspect verified; no unexpected (default!).
- Seed-determinism test passes.
- Phase 7 PASS (or Phase 0 waiver recorded).
- Full matrix (all levels × all styles × all shipped input models, ≥1000 runs/cell) — every cell CI ⊆ band (sign-off law).
- Modes + career: currency/minute OK; no dominant farm; shop reachable.
- Interest curve + reward-cadence checkpoints PASS.
- Regression JSON snapshot committed for CI.
Reference
Progressive disclosure: open Official Documentation links only when researching a specific API;
load Related Skills when routing work to a peer domain — do not preload the whole lattice.
Official Documentation
- Resources — Preferred extract source for GameData (
.tres over regex farms).
- JSON — Snapshot / CI balance JSON emit and parse.
- FileAccess — Reading exported balance dumps and golden cells.
- ResourceLoader — Loading designer Resources for extract/calibration.
- Command line tutorial — Headless Godot for Phase 7 calibration runs.
- Unit testing — Determinism tests around seeds and extract.
- OS — Process/env hooks for lab launchers.
- ProjectSettings — Paths and feature tags for CI balance jobs.
- RandomNumberGenerator — Seeded RNG patterns mirrored by the Rust lab.
- SceneTree — Headless scene boot for golden-cell calibration.
- Engine — Time scale / frames for headless sims.
- ConfigFile — Optional designer band overrides outside code.
Related Skills
Prerequisites
Complements
Downstream / consumers
Master
- godot-master — Library router and mirrored module entry for the balance lab.