T-588 (design/ledger.md; section 11 is the JSON this writes). Command: node tools/ledger.js --write (about 53 s), which writes docs/lab/ledger/tyranids.json and this report. Tests: tests/unit/ledger.test.js. Data: BSData 374f505; the top-quarter field from tools/field.js (build/field/states.json), from tournament lists in grimstat-corpus 570b8c6 (CC BY 4.0, published by players and organisers on MiniHeadQuarters; the listhammer/ folder is not read). Engine hash b22f9d8b1efe, inputs frozen at b3c4169 (hash 1b88e955b9b3, T-603), field 8fd085059e24. Our own numbers from the datasheets' dice; no rules text. A data file for the Lab page (T-589): no ranking, no tier, nothing on the site's scores changes.
In short
52 units, 1106 forms (819 solo, 287 joined; each joined form is listed under both its members), from 117 bases (sizes × loadouts × pairings) split by the 10 matched-play detachments' 14 variants where they change the dice or the listed rules; 919 distinct dice computed. The typical army is 2,000 points from the top-quarter field (630 datasheet-sizes in expected copies; the field's 2001.9 points scaled by 0.99905). metaKillRate (β 6): 0.445 enemy points removed per point activated, one turn (shooting 0.389, fight 0.493). Thin classes: aircraft, other. Parity: 200 cells drawn from the 686,459 the run read, against ev.js: worst |Δ damage per attack| 4.4e−16, worst |Δ unsaved wounds| 1.1e−16; long-run wounds on 20 one-wound targets equal ev.js's damage to 1.1e−16; 0 above it elsewhere: pass. A second run writes a byte-identical JSON (the test).
What each column is
Every rate is for one turn, per 100 points of the form's own cost (its members' points at their sizes; repeat-unit costs ignored).
- kill[β].ranged / .melee (enemy points per 100 points): the points the form removes from the typical army in one turn: its shooting phase (ranged), then its fight phase into what its own shooting left, with every charge landing (melee; Lance on; the page multiplies melee by its "melee lands" slider). allocate.js's kernel at β: each gun spreads its fire over the army's units by σ ∝ R × (v ÷ v*)^β (R the wounds the army holds of the unit, v the points one volley removes, v* the gun's best), a unit the phase would overkill is saturated and the rest spills to the gun's next best targets, pass after pass until the fire is spent or nothing it can hurt is left (the kernel's five-pass cap is lifted here: at β ∞ each pass opens one target, and the cap lost most of a gun's fire): so a chaff-killer runs out of chaff. Every gun fires; points per wound are fluid. β ∞ is each gun's single best target, spill to the next best.
- kill[β].byClass: where that kill came from, ranged plus melee (every charge landing), by the army's unit classes (field.js); it sums to ranged + melee.
- soak[β].shoot / .fight (enemy points per 100 points): the enemy points that must activate into the form to remove it, in the shooting phase and, apart, the fight phase (every charge landing). Each army unit's efficiency is the wounds its whole phase removes from the form per point of the unit; the army draws its most efficient units first, each up to its copies in the army. At β ∞ a strict greedy walk; at finite β all units are drawn at once, each at its supply × (efficiency ÷ the best's)^β, an exhausted unit dropping out. Joined forms and units of several statlines are removed group by group (squad bodies, then the leader), carrying what the army has left; the leader's defensive lend (leaderfx.json) and the detachment's defensive effects apply to every group. Soak is never below the cheapest single-unit cost (each group's wounds at the army's best efficiency into it), and no unit is drawn beyond its supply (the tests).
- ocPer100: OC × models per 100 points (the members summed). actionsPer100: one action per unit (a joined unit is one) per 100 points, 0 when it can't act. canAction: every unit can, except AIRCRAFT (11th edition lets them make only ingress moves and gives them OC "-"; no Tyranid datasheet says a unit can't act, and the missions' actions name their own units). In this army: Harpy, Hive Crone can't.
- rules: non-dice abilities the page can weight, in our words with the ability's name: positional on one line (Lone Operative → soak; Deep Strike, Scouts, Infiltrators and the coverage's arrival and movement rules → meleeLands; Fights First → meleeKill; mortal wounds outside attacks and Overwatch rules → kill) or army-wide on the total (Synapse, auras, healing, spawning, command points, Battle-shock, hindering or marking enemies). From the datasheet's core abilities, the SYNAPSE keyword, unitfx.json's kinds and the detachment's rules' kinds (coverage report, 2 Oct). Not listed: list-building, once-a-battle, chosen-target, OC and lead kinds (lead rules that are dice live in leaderfx.json and are computed in).
- Wired in (T-596): every form's
landsfrom the charge model (tools/charge-tyranids.json, T-590);spawnPer100andspawnUnitsPer100(rounds 1 to 3 averaged),spawnAnywhereandspawnGateon the 88 forms that place or return models (tools/spawn-tyranids.json, T-595; 37 place them anywhere, 9 need their melee to land). Rules those count are markedmeasured(723 charge, 183 spawn, counted per form) and take no multiplier on the page. - metaKillRate (meta): the typical army into itself, one shooting phase and one fight phase at β 6, the points removed per point activated (a unit with a gun activates its points in shooting, 1730.1 points in all; a unit with a melee line in the fight, 1990.3), the two phases pooled. The page multiplies Soak by it to get our points saved. Beside it in the JSON: each β, and each phase's own rate.
Forms. Every legal size (BSData's points per size) × Auto-equip's squad at that size (docs/loadout.js's all-rounder into the rankings' five stand-ins, as the site's Auto-equip; the datasheet's wargear is an extra solo form where it differs) × each matched-play detachment and each way to answer its choices × alone or joined with each legal leader (bsdata.js canJoin via matrix.js contextEnv: the squad at each size, both members at Auto-equip). Each form fires with its own unconditional abilities (unitfx.json at the matrix's unit level), the army rules (Synapse reaches others as an aura and adds nothing here), the detachment's effects and a joined leader's lend; a condition the engine can't check counts as not met (no shares, as tools/v4walk.js); a rule's own choice takes its first option. Detachments that give a form the same dice and the same listed rules are one form (detachments lists them; "Any detachment" when all do). The army's units carry their own abilities and default wargear, no detachment.
The typical army
| Class | Points of 2,000 | Share | Datasheets | Top-quarter lists with one (of –) | Thin |
|---|---|---|---|---|---|
| aircraft | 0.0 | 0.0% | 0 | – | thin |
| heavy vehicle | 265.6 | 13.3% | 50 | – | |
| light vehicle | 287.8 | 14.4% | 81 | – | |
| monster | 239.0 | 11.9% | 44 | – | |
| character | 321.2 | 16.1% | 160 | – | |
| cavalry and beasts | 138.7 | 6.9% | 38 | – | |
| heavy infantry | 382.8 | 19.1% | 77 | – | |
| chaff | 95.5 | 4.8% | 35 | – | |
| elite infantry | 269.3 | 13.5% | 96 | – | |
| other | 0.0 | 0.0% | 0 | – | thin |
A class is thin when fewer than 12 of the top-quarter lists field one (about a tenth) or fewer than 5 datasheets make it up; an absent class is thin. The biggest single entries: C'tan Shard of the Void Dragon (Necrons, 1 model, 33.0 expected points); Allarus Custodians (Adeptus Custodes, 6 models, 28.8 expected points); Defiler (Emperor's Children, 1 model, 28.2 expected points); Lokhust Destroyers (Necrons, 6 models, 26.9 expected points); Wolf Guard Terminators (Space Wolves, 10 models, 25.1 expected points); Vertus Praetors (Adeptus Custodes, 3 models, 24.3 expected points); Allarus Custodians (Adeptus Custodes, 5 models, 19.7 expected points); C'tan Shard of the Nightbringer (Necrons, 1 model, 18.8 expected points).
metaKillRate
| β | Shooting phase removes | per point activated | Fight phase removes | per point activated | Pooled (metaKillRate) | Per army point |
|---|---|---|---|---|---|---|
| 3 | 586.9 | 0.339 | 877.8 | 0.441 | 0.394 | 0.732 |
| 6 | 672.3 | 0.389 | 982.2 | 0.493 | 0.445 | 0.827 |
| 12 | 731.0 | 0.423 | 1052.2 | 0.529 | 0.479 | 0.892 |
| ∞ | 760.3 | 0.439 | 1097.7 | 0.552 | 0.499 | 0.929 |
The tests
| Test | Result |
|---|---|
| Parity: 200 cells drawn (seed 588) from the 686,459 read, against ev.js's profileVs at a random squad and target size | damage per attack 4.4e−16, unsaved wounds 1.1e−16 (bar 1e−9); long-run wounds removed on 20 one-wound targets 1.1e−16; above ev.js's damage elsewhere: 0; pass |
| A second run | the JSON byte-identical (tests/unit/ledger.test.js) |
| Supply | no class gives more kill than the army holds of it; no army unit drawn beyond its supply in any Soak walk; Soak never below the cheapest single-unit cost |
| By hand | one Norn Emissary's shooting Soak against a two-unit toy army (Leman Russ Punishers and Skitarii Rangers), at β ∞, 6 and 3, worked from the dice by hand |
Each unit's best solo form at β 6 (alphabetical; no ranking, no tier)
The form shown is each unit's solo form with the highest Kill ranged + 0.6 × Kill melee + (Soak shoot + 0.6 × Soak fight) × metaKillRate (0.445): the page's default Value with only Kill and Soak weighted, a choice for this table only. Kill and Soak in enemy points per 100 points.
| Unit | Form | Kill ranged | Kill melee | Soak shoot | Soak fight | OC/100 | Actions/100 |
|---|---|---|---|---|---|---|---|
| Barbgaunts | 5 models, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 190.8 | 31.2 | 237.2 | 138.4 | 9.1 | 1.818 |
| Biovores | 3 models, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 61.4 | 18.4 | 266.9 | 155.4 | 2.1 | 0.714 |
| Broodlord | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 136.1 | 144.9 | 101.0 | 1.3 | 1.250 |
| Carnifexes | 2 models, Auto-equip, Invasion Fleet (Swarming Instincts) | 94.8 | 77.5 | 426.2 | 196.0 | 3.3 | 0.556 |
| Deathleaper | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 117.5 | 305.6 | 146.3 | 1.3 | 1.250 |
| Exocrine | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 107.6 | 21.3 | 335.5 | 169.7 | 3.0 | 0.741 |
| Gargoyles | 20 models, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 53.6 | 28.3 | 141.0 | 103.6 | 25.8 | 0.645 |
| Genestealers | 10 models, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 191.2 | 219.7 | 149.7 | 7.1 | 0.714 |
| Harpy | 1 model, Auto-equip, Invasion Fleet (Swarming Instincts) | 62.8 | 14.8 | 157.8 | 341.0 | 0.0 | 0.000 |
| Harridan | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 53.1 | 15.6 | 333.2 | 99.9 | 0.0 | 0.164 |
| Haruspex | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 21.8 | 154.3 | 392.7 | 187.1 | 3.2 | 0.800 |
| Hierophant | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 50.0 | 21.4 | 456.3 | 281.1 | 1.5 | 0.123 |
| Hive Crone | 1 model, datasheet wargear (no choices), Subterranean Assault | 93.3 | 24.3 | 171.7 | 371.1 | 0.0 | 0.000 |
| Hive Guard | 6 models, datasheet wargear, Subterranean Assault | 114.8 | 38.7 | 520.1 | 247.5 | 3.8 | 0.625 |
| Hive Tyrant | 1 model, Auto-equip, Invasion Fleet (Swarming Instincts) | 0.0 | 100.0 | 284.7 | 123.8 | 1.5 | 0.513 |
| Hormagaunts | 20 models, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 139.5 | 227.7 | 155.4 | 33.3 | 0.833 |
| Hyperadapted Raveners | 5 models, datasheet wargear (no choices), Subterranean Assault | 35.5 | 145.7 | 174.2 | 108.5 | 3.0 | 0.606 |
| Lictor | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 156.6 | 182.5 | 85.7 | 1.7 | 1.667 |
| Maleceptor | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 68.2 | 35.4 | 422.8 | 198.9 | 2.2 | 0.556 |
| Mawloc | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 106.1 | 335.5 | 169.7 | 3.0 | 0.741 |
| Mucolid Spores | 2 models, datasheet wargear (no choices), Ambush Predators or 8 others | 0.0 | 0.0 | 83.8 | 61.0 | 0.0 | 1.667 |
| Neurogaunts | 22 models, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 71.1 | 276.6 | 201.6 | 24.4 | 1.111 |
| Neurolictor | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 77.3 | 234.1 | 136.4 | 1.3 | 1.250 |
| Neurotyrant | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 67.4 | 22.3 | 218.3 | 148.9 | 2.3 | 0.769 |
| Norn Assimilator | 1 model, datasheet wargear (no choices), Subterranean Assault | 26.6 | 81.9 | 431.7 | 148.3 | 2.0 | 0.400 |
| Norn Emissary | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 30.1 | 62.5 | 754.3 | 190.6 | 2.0 | 0.400 |
| Old One Eye | 1 model, datasheet wargear (no choices), Subterranean Assault | 0.0 | 107.5 | 371.3 | 205.7 | 2.1 | 0.714 |
| Parasite of Mortrex | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 92.3 | 130.2 | 66.3 | 1.4 | 1.429 |
| Psychophage | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 31.6 | 84.5 | 363.8 | 219.5 | 2.7 | 0.909 |
| Pyrovores | 3 models, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 129.6 | 18.6 | 373.6 | 217.5 | 3.0 | 1.000 |
| Raveners | 5 models, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 151.8 | 196.6 | 127.6 | 4.0 | 0.800 |
| Ripper Swarms | 3 models, Auto-equip, Invasion Fleet (Swarming Instincts) | 59.2 | 47.3 | 169.9 | 108.5 | 0.0 | 2.000 |
| Screamer-killer | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 42.2 | 134.7 | 275.3 | 167.8 | 2.4 | 0.800 |
| Spore Mines | 6 models, datasheet wargear (no choices), Ambush Predators or 8 others | 0.0 | 0.0 | 28.7 | 26.0 | 0.0 | 0.909 |
| Sporocyst | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 57.3 | 27.9 | 206.9 | 112.2 | 0.0 | 0.690 |
| Termagants | 20 models, datasheet wargear, Invasion Fleet (Swarming Instincts) | 75.5 | 39.8 | 248.4 | 169.5 | 36.4 | 0.909 |
| Tervigon | 1 model, datasheet wargear, Invasion Fleet (Swarming Instincts) | 29.5 | 51.2 | 654.5 | 229.5 | 3.1 | 0.625 |
| The Red Terror | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 135.6 | 153.5 | 97.7 | 2.3 | 0.769 |
| The Swarmlord | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 39.5 | 86.3 | 264.4 | 115.0 | 1.4 | 0.476 |
| Toxicrene | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 77.0 | 93.1 | 409.0 | 194.9 | 3.3 | 0.833 |
| Trygon | 1 model, datasheet wargear (no choices), Subterranean Assault | 35.2 | 127.2 | 323.5 | 163.6 | 2.9 | 0.714 |
| Tyranid Prime with Lash Whip | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 183.3 | 136.2 | 78.7 | 1.3 | 1.333 |
| Tyranid Warriors with Melee Bio-Weapons | 6 models, datasheet wargear (no choices), Warrior Bioform Onslaught | 0.0 | 147.0 | 239.9 | 174.4 | 8.0 | 0.667 |
| Tyranid Warriors with Ranged Bio-Weapons | 3 models, Auto-equip, Invasion Fleet (Swarming Instincts) | 125.9 | 129.0 | 237.5 | 152.9 | 10.0 | 1.667 |
| Tyrannocyte | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 60.1 | 59.3 | 310.3 | 195.7 | 2.5 | 1.250 |
| Tyrannofex | 1 model, Auto-equip, Subterranean Assault | 101.1 | 21.3 | 1062.0 | 239.7 | 2.9 | 0.588 |
| Tyrant Guard | 6 models, datasheet wargear, Invasion Fleet (Swarming Instincts) | 0.0 | 96.0 | 612.6 | 292.2 | 3.5 | 0.588 |
| Venomthropes | 6 models, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 149.6 | 346.9 | 179.0 | 5.5 | 0.909 |
| Von Ryan's Leapers | 6 models, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 179.1 | 375.3 | 199.7 | 5.7 | 0.952 |
| Winged Hive Tyrant | 1 model, Auto-equip, Invasion Fleet (Swarming Instincts) | 0.0 | 83.0 | 236.4 | 124.6 | 1.6 | 0.541 |
| Winged Tyranid Prime | 1 model, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 0.0 | 130.7 | 121.2 | 73.3 | 1.5 | 1.538 |
| Zoanthropes | 6 models, datasheet wargear (no choices), Invasion Fleet (Swarming Instincts) | 84.7 | 12.5 | 260.8 | 190.5 | 3.2 | 0.526 |
What is not computed exactly, and why
- Vouched conditions (Synapse range, a Battle-shocked target, an objective, below Starting Strength, a chosen enemy) count as not met everywhere: the effects that need them add nothing to Kill or Soak. Their worth is the page's army-wide multipliers (Synapse) or out of scope; counting them in the dice and again as a multiplier would count them twice.
- A rule's own choice (the Norns' Singular Purpose, for one) takes its first option; detachment choices are each a variant.
- Bodyguards' rules toward their leader (Tyrant Guard's Feel No Pain for its character) are noted in unitfx.json, not in the effects files, so a joined form's Soak leaves them out; likewise enhancements and stratagems.
- Spawning, healing, auras on others, command points, mortal wounds outside attacks are listed as rules, not computed (no numbers for how often or how much in the files the matrix reads).
- Soak past the army's phase: 130 forms need more than the army's whole phase in at least one β and phase (Harpy; Harridan; Hierophant; Hive Crone; Norn Emissary; Tyrannofex; Carnifexes + Old One Eye; Tyrant Guard + Hive Tyrant; Tyrant Guard + Neurotyrant; Tyrant Guard + The Swarmlord…); the rest is priced at the army's average efficiency into them. Every form can be hurt in both phases.
- Fluid points: a unit's activation is drawn in fractions (as the field's copies are fractional), and points per wound are fluid, as everywhere in the matrix work.
Decided alone
- Soak at finite β draws the army's units together at supply × (efficiency ÷ best)^β, the soak twin of the kernel's targeting weights; β ∞ is the greedy walk the design names. The weights take each unit's supply at the start of the group being removed, so units of equal efficiency run dry together and the walk is exact (piecewise linear).
- metaKillRate is per point activated, both phases pooled (Soak counts enemy points activated, so the rate it is multiplied by is per activated point); each phase's own rate and the rate per army point are in the JSON and the table above.
- One turn, shooting first: the fight phase goes into what the form's own shooting left, so the two lines together never take more of a unit than the army holds; byClass is where that kill came from (ranged plus melee at every charge landing), not the form's kill into each class alone, and it sums to the two lines.
- Spill without a cap: the kernel's five saturation passes are lifted to as many as the army has units, for Kill and metaKillRate alike (at β ∞ each pass opens one target, and five lost most of a gun's fire).
- Thin classes: fewer than 12 of the 115 top-quarter lists, or fewer than 5 datasheets.
- Detachments: the ten matched-play ones (the four Boarding Actions ones left out); every form has one. Joined forms use Auto-equip for both members only; the datasheet's wargear is an extra form for solo units.
- canAction: every unit except AIRCRAFT.
- Rules mapping: arrival and movement kinds on meleeLands with Deep Strike; mortal wounds outside attacks and Overwatch on kill (the contract's
killline); hindering and marking enemies with the army-wide kinds. Each form lists its detachment's non-dice rules too (so detachments merge only when those match).
Reviewers' letters: Auspex, Hivemind and the second creator's files (reports/tiers/panel/), each panel's patchDrop respected (auspex: every name matched; hivemind: every name matched; second: every name matched).