Skip to content
GENOPOOL

Document GP-DOC-19: Balancing

The Balancing Protocol

"Balanced" must be measurable, or the meta gets tuned by feel and solved in a spreadsheet. GENOPOOL's balancing is a written protocol: a harness, nine numeric health metrics with pass/fail thresholds, and for every failure a designated tuning lever.

The simulator IS the engine

The single most important architectural decision of the project: there is no separate simulation model. The race engine is written once, in TypeScript (Rapier physics, enhanced-determinism build, fixed 60 Hz timestep, seeded PRNG), and runs in two places:

  • in the browser, the game you play;
  • in a headless Node harness, the balancing rig.

Balancing a simplified proxy model and then porting the numbers to the real engine means balancing a different game: the physics is hypersensitive (one friction coefficient moves the meta). One source of truth, bit-for-bit. Python is used only to analyze the CSV files the harness produces, never to simulate a race.

Harness scale

Every campaign is identified by a master seed; genome, map and skill seeds derive from it, so any campaign replays identically. Each CSV embeds the engine git SHA, the master seed and the full parameter snapshot in its header.

RunScaleFeeds metrics
Meta run≥ 50,000 sampled genomes × ≥ 200 maps (mono- and multi-biome), optimal pilot#1 #2 #3 #4 #5
Skill run≥ 20,000 field races (12 creatures, pilot skill drawn in [0, 1])#7 #9
Breeding run≥ 2,000 greedy min-maxer trajectories × ≥ 20 generations, with and without inbreeding constraint#6
Landscape runone-allele neighborhood lattice over ≥ 5,000 genomes#8

Genome sampling is uniform over allele space plus an oversample of the "corners" (extreme genomes), to catch degenerate builds that uniform sampling would miss.

Discipline

one lever per iteration
re-run on the same seeds
compare, journal (parameters → metrics), repeat
  • All tuning levers live in a single registry (BALANCE / ECONOMY constants), stamped with a BALANCE_VERSION; every parameter change bumps the version and invalidates all previous snapshots and golden vectors.
  • Any formula change in the genome spec invalidates prior snapshots entirely: full re-run; CSVs from different engine versions are never mixed.
  • Distributions are inspected, never just means: a meta can be fine on average and broken at the extremes.
  • Release discipline: outcome-affecting parameters exist only compiled under a BALANCE_VERSION and ship through a versioned deployment with a fresh snapshot; they are never live-tweaked on production.

Because map seeds are published on-chain (Switchboard) and the engine is deterministic and open-source, every one of these measurements is reproducible by the community. The balancing protocol is an auditable claim, not an internal secret.

The nine meta-health metrics

The thresholds below are the design commitments the engine must satisfy before a balancing snapshot ships. They are targets, not a report; measured campaign values are internal working data and are superseded by each new snapshot.

#MetricDefinitionTarget (pass)Fail
1Viable build diversityshare of archetypes present in the top decile on at least one biome≥ 40 %< 25 %
2No global dominantshare of the 200 maps won by the single best-average genome≤ 30 %> 50 %
3Per-biome concentrationwin-share per archetype per biome, plus global Ginino archetype > 25 % on any biome, Gini < 0.45any archetype > 40 %, or Gini ≥ 0.55
4Intransitivitycycle rate over archetype triplets (A beats B on a majority of maps; A>B>C>A)≥ 15 %< 5 %
5Meta entropy per rotationnormalized Shannon entropy of winning archetypes over a 48-map rotation≥ 60 %< 45 %
6Breeding convergence speedgenerations for a greedy min-maxer to reach the 95th percentile on a fixed biome; ceiling of a closed inbred line≥ 6 generations, inbred line capped < 90th pcttarget hit in ≤ 2 generations, or an inbred line reaches the top decile
7Skill vs build decompositionvariance share of finish position explained by pilot skill vs build quality; upset rateskill 35-55 %, build 35-55 %, each ≥ 30 %; upsets 20-45 %either factor < 25 %
8Landscape smoothnessmean fitness change per single-allele step; density of local optima per biomemean Δ < 15 % of stat amplitude, > 1 local optimum per biomeΔ > 30 %, or a unique global optimum
9EV by skill percentile per tierprize expectation per race, in % of ticket, by within-band skill percentiletop 30 % positive; median in [-12 %, -8 %]; weak monotonicity; no sub-top-30 profile durably positivemedian < -15 %, or top 30 % ≤ 0, or a sub-median profile durably positive

What each metric protects

  • #1 Diversity: many genome archetypes must have somewhere they shine. If stats correlate too positively, one body plan does everything; the lever is hardening the trade-offs in the stat formulas.
  • #2 No global dominant: no single genome should win most maps regardless of biome. Protects the entire capture and breeding economy from collapsing onto one blueprint.
  • #3 Per-biome concentration: even a specialist's home biome must stay contested; each biome's speed gate mixes several stats rather than rewarding one.
  • #4 Intransitivity: a living meta needs rock-paper-scissors cycles between archetypes. A near-total order means one king and a solved ladder.
  • #5 Rotation entropy: the hourly map rotation must actually rotate the winners, so niche builds ("freaks") get their hour and hold market value.
  • #6 Breeding convergence: the genetics must not be solvable in a spreadsheet: a greedy optimizer needs 6+ generations to approach the frontier, and a closed inbred line must plateau below it. This is what keeps outcrossing, lineages and the specimen market meaningful.
  • #7 Skill vs build: the double constraint the whole model rests on: pilot skill must be the dominant, legally decisive factor, while build quality stays significant enough that breeding matters. Both between 35 % and 55 % of outcome variance, with a healthy upset rate.
  • #8 Landscape smoothness: breeding must be learnable. One-allele steps should move fitness gently, and each biome should hold several distinct local optima (several viable species), not one chaotic cliff or one global peak.
  • #9 EV per tier: the money layer must behave like a competition room, coherent with the published rake:
net(race) = payout(finish_pos) - ticket
payout    = pool_net · PAYOUT_SPLIT[pos]          // split 65 / 25 / 10 %
pool_net  = field_size · ticket · (1 - rake_tier) // rake: T1 12 %, T2 10 %, T3 8 %, T4 7 %, Major 6 %

Strong pilots (top ~30 % of their matchmaking band) finish positive on expectation; the median player pays roughly the rake and nothing more; expectation never decreases as skill rises; and no low-skill profile is durably positive: volume without skill must not pay, which is precisely what separates a contest of skill from everything else.

Built-in sanity check: with a payout split summing to 1, the ticket-weighted mean expectation across a whole tier equals -rake to ±0.5 pt by construction. Any deviation flags an accounting bug in the payout path, not a balance problem.

Failure → lever mapping

Every red metric has a designated lever (terrain gate weights, stamina cost, inbreeding penalty, skill-execution coefficient, rake, matchmaking band width, …), actioned one at a time and journaled. A metric is never "fixed" by re-rolling seeds: the re-run happens on the same seeds, and only the lever moves.