3 Oct 2026. docs/ev.js (the closed form behind the rankings, the unit pages and Army vs Army) and the calculator's dice engine (docs/app.js) now read the keywords node tools/matrix.js --unread listed as read in part or not at all (34 at BSData 374f505, the same 34 at 8b91e6b). Rules read on Wahapedia's 11th-edition core rules and datasheets, in our own words; no rules text here. Datasheets at BSData 8b91e6b. Our own numbers.
What changed
27 of the 34 are read now, in both engines, with the same counts. 7 stay unread: six aren't dice, and a lone "-" is a gap in the data.
- Each keyword is read whole. ev.js used to look for words anywhere in a weapon's keyword line, so "Psychic Assassin" counted as Psychic, "Sustained Hits D3" as Sustained Hits 1, "Blast 2" as Blast, and "Lethal Hits: non-Monster/Vehicle" as Lethal Hits against everything. Now each comma-separated keyword is tidied (upper case, every kind of dash a hyphen, so the Stonesinger's non-breaking hyphen reads) and matched in full. The calculator's seed (
weaponKeywordFlags) does the same, and a unit test holds the two readers equal on every weapon in build/units.json. - A condition on the target. The core rules say an ability followed by keywords applies only against a target with one of them. "Lethal Hits: non-Monster/Vehicle" counts against a target that is neither a MONSTER nor a VEHICLE; "Sustained Hits 2: Monster/Vehicle" and "Devastating Wounds: Monster/Vehicle" against either; "Devastating Wounds: Infantry" against Infantry. ev.js reads them against the target's keywords (a joined unit's include its characters'); the calculator leaves them out of a weapon's own switches and adds them in
gatherParams, through ev.js's reader, against the defender's keywords. - Anti-X in every spelling. A slash list ("Anti-Monster/Vehicle 4+" counts against either), "non-" ("Anti-non-Monster/Vehicle 2+" against neither), no hyphen ("Anti Vehicle 3+"), no "+" ("Anti-fly 2" is 2+). The calculator now reads every weapon's Anti-X against the target's keywords. It read none before: Anti-X there was only the manual "Crit wounds on" pick, so an Anti-Infantry 4+ gun into Infantry showed fewer wounds in the calculator than on its unit page. The manual pick still applies on top (the better of the two).
- Blast X and Cleave X. X more attacks for every five models in the target (Blast alone is Blast 1). Cleave counts only when all of a weapon's attacks go into one target, and ours always do. "Cleave 2+" (the Squighog Boyz' Big Choppa, a misprint) reads as Cleave 2.
- Sustained Hits D3. Each critical hit rolls its extra hits. ev.js mixes the kill walk over the roll (the average is Sustained Hits 2's, but the kills spread differently against multi-wound models); the calculator rolls it.
- Rapid Fire D3 and D6+3. The extra attacks at half range are rolled with the weapon's own (they were left out). The calculator's Rapid Fire field takes dice now ("D6+3").
- "Twin Linked" without its hyphen is Twin-linked.
- Conversion (on its datasheets: against a target more than 12" away, an unmodified hit roll of 4+ is a critical hit). Our reading: on beyond half range, off within it. Every Conversion gun in the pool reaches 24" or more, so its half range is 12" or more and beyond half range is always beyond 12". The rankings' table is beyond half range, so it counts there. The calculator switches it on for that weapon alone (its own
conversionswitch, not the shared "Crit on" pick, so the unit's other weapons keep their 6s). - Psychic Assassin (the Culexus): 6 attacks against a PSYKER. It isn't Psychic any more, so cover counts against it.
- Overcharge (the Arkanyst Evaluator's top setting): its hazard roll takes 2 off the die, so it fails on 1 to 4.
Not read, and why (none of them changes the dice of an attack):
| Keyword | Who | Why not |
|---|---|---|
| Harpooned | Norn Assimilator | +2 to a charge after hitting a Monster or Vehicle: a charge roll, not an attack (delivery, T-569) |
| Reverberating Summons | Great Unclean One | Returns a Plaguebearer to another unit for each model it slays: models returned, not damage |
| Linked Fire | Fire Prism | Measures range and sight from another Fire Prism, at 1 attack: reach, not dice |
| Plasma Warhead | Deathstrike | Picks no target and rolls against each unit near its marker: targeting, not dice |
| Defensive Array, Hive Defences | Hammerfall Bunker, Sporocyst | Fire Overwatch for 0 CP: when it shoots, not how |
| "-" | Deathwatch Terminators, Kastelan Robots, Lychguard, Myphitic Blight-hauler | An empty slot in the data, nothing to read. ev.js skips it; tools/matrix.js still lists it, so its keys don't move under the points ledger's frozen ev.js |
"Lethal Hits: non-" (the Grot Mega-Tank, Legends, its condition cut off in the data) is read as plain Lethal Hits, as before.
The numbers that move
The rankings rebuilt with today's data and only this change: 81 units' Offense moves (71 live, Legends and Crucible aside): 44 up, 15 down, and 12 where only the weaker of a unit's ranged and melee numbers moved. Rapid Fire's dice and Psychic Assassin move nothing in the rankings (the table is beyond half range, has no PSYKER target and no cover); they move the calculator and Army vs Army.
"Offense, five targets summed" is the unit page's best damage into each stand-in target (GEQ, MEQ, TEQ, light and heavy vehicle), the better of ranged and melee, added up. The Offense score and Value are percentiles over every unit, so the other units' scores shift by a tenth or two as the movers re-sort: 1,390 units move that way only.
The biggest moves, every keyword together (live units):
| Unit | Army | Offense, five targets summed | Offense score | Keywords it carries |
|---|---|---|---|---|
| Stonesinger | Aeldari | 22.683 → 35.652 (+57.2%) | 80.6 → 98.8 | Anti-X spellings |
| Gunwagon | Orks | 12.775 → 18.013 (+41.0%) | 30.3 → 61.8 | Lethal Hits with a condition, Cleave X, Blast X, Anti-X spellings, Devastating Wounds with a condition |
| Deffkilla Wartrike | Orks | 22.089 → 29.139 (+31.9%) | 85 → 94.8 | Lethal Hits with a condition, Cleave X |
| Warboss in Mega Armour | Orks | 19.104 → 24.838 (+30.0%) | 71.2 → 88.3 | Lethal Hits with a condition, Cleave X |
| Trukk | Orks | 11.379 → 14.163 (+24.5%) | 21.2 → 30.9 | Lethal Hits with a condition, Cleave X, Blast X |
| Night Spinner | Aeldari | 10.14 → 12.452 (+22.8%) | 16.1 → 27.2 | Twin Linked |
| Battlewagon | Orks | 11.976 → 14.666 (+22.5%) | 25.6 → 38.7 | Lethal Hits with a condition, Cleave X |
| Squighog Boyz | Orks | 21.126 → 25.431 (+20.4%) | 76 → 90.9 | Lethal Hits with a condition, Cleave X, Anti-X spellings |
| Knight Defender | Imperial Knights | 10.207 → 12.171 (+19.2%) | 19.6 → 31.5 | Sustained Hits D3, Conversion |
| Beastboss | Orks | 32.038 → 26.725 (−16.6%) | 97.8 → 90.4 | Lethal Hits with a condition, Sustained Hits with a condition |
| Warboss | Orks | 20.022 → 23.318 (+16.5%) | 78 → 86.8 | Lethal Hits with a condition, Cleave X |
| Trazyn the Infinite | Necrons | 9.729 → 11.317 (+16.3%) | 13.5 → 20.3 | Sustained Hits D3 |
| Blitza-bommer | Orks | 5.692 → 4.803 (−15.6%) | 6.3 → 4.1 | Lethal Hits with a condition |
| Dakkajet | Orks | 8.474 → 7.17 (−15.4%) | 11 → 8.2 | Lethal Hits with a condition |
| Deffkoptas | Orks | 19.328 → 22.24 (+15.1%) | 74.6 → 83 | Lethal Hits with a condition, Cleave X, Blast X |
Each keyword on its own
To split the moves between keywords, the rankings were rebuilt ten more times, each time with one keyword written back the way the old reader took it (Lethal Hits with its condition as plain Lethal Hits, Cleave dropped, Sustained Hits D3 as Sustained Hits 1, and so on) and every other keyword read: the difference from today's rankings is that keyword's own doing. The ten biggest moves of each, live units only, with the unit's before and after scores (every keyword together):
Lethal Hits with a condition (Lethal Hits: non-Monster/Vehicle)
36 units' Offense moves by this keyword alone (31 live, Legends and Crucible aside).
| Unit | Army | Its own move (five targets summed) | Offense score, before → now | Value, before → now | Letter |
|---|---|---|---|---|---|
| Blitza-bommer | Orks | 5.69 → 4.80 (−15.6%) | 6.3 → 4.1 | 43.4 → 42.3 | C |
| Dakkajet | Orks | 8.47 → 7.17 (−15.4%) | 11 → 8.2 | 42.8 → 41.4 | C |
| Burna-bommer | Orks | 9.74 → 8.76 (−10.1%) | 12.6 → 10.3 | 43.6 → 42.4 | C |
| Big Mek Dakkarig | Orks | 16.58 → 15.32 (−7.6%) | 59.7 → 51.5 | 50 → 46 | A |
| Flash Gitz | Orks | 23.29 → 21.55 (−7.5%) | 86.3 → 80.1 | 66.5 → 63.4 | S |
| Warbuggies | Orks | 26.19 → 24.69 (−5.7%) | 90 → 79.4 | 76.4 → 71.1 | A |
| Big'ed Bossbunka | Orks | 2.79 → 2.63 (−5.6%) | 2.9 → 2.5 | 39.8 → 39.6 | C |
| Warbikers | Orks | 15.65 → 14.88 (−4.9%) | 43.1 → 36.3 | 46.6 → 43.2 | C |
| Wazdakka Gutsmek | Orks | 17.57 → 16.77 (−4.6%) | 53.4 → 54.9 | 43.4 → 44.1 | S |
| Wartrakks | Orks | 13.74 → 13.35 (−2.9%) | 39.7 → 35.8 | 36 → 34 | C → D |
Cleave X
28 units' Offense moves by this keyword alone (25 live, Legends and Crucible aside).
| Unit | Army | Its own move (five targets summed) | Offense score, before → now | Value, before → now | Letter |
|---|---|---|---|---|---|
| Deffkilla Wartrike | Orks | 22.09 → 29.14 (+31.9%) | 85 → 94.8 | 66.4 → 71.3 | A |
| Warboss in Mega Armour | Orks | 19.10 → 24.84 (+30.0%) | 71.2 → 88.3 | 59.4 → 67.9 | B → A |
| Gunwagon | Orks | 14.14 → 18.01 (+27.4%) | 30.3 → 61.8 | 63.2 → 79 | B → A |
| Trukk | Orks | 11.38 → 14.16 (+24.5%) | 21.2 → 30.9 | 56.4 → 61.2 | S |
| Battlewagon | Orks | 11.98 → 14.67 (+22.5%) | 25.6 → 38.7 | 54.9 → 61.4 | B |
| Warboss | Orks | 20.02 → 23.32 (+16.5%) | 78 → 86.8 | 45.2 → 49.6 | S |
| Deffkoptas | Orks | 19.52 → 22.24 (+13.9%) | 74.6 → 83 | 71.8 → 76 | A |
| Nazdreg | Orks | 20.17 → 22.88 (+13.4%) | 78.8 → 85.6 | 52.8 → 56.2 | B |
| Wazdakka Gutsmek | Orks | 14.88 → 16.77 (+12.7%) | 53.4 → 54.9 | 43.4 → 44.1 | S |
| Deff Dread | Orks | 18.85 → 20.86 (+10.7%) | 69.8 → 78.8 | 68.7 → 73.2 | A |
Sustained Hits D3
15 units' Offense moves by this keyword alone (13 live, Legends and Crucible aside).
| Unit | Army | Its own move (five targets summed) | Offense score, before → now | Value, before → now | Letter |
|---|---|---|---|---|---|
| Trazyn the Infinite | Necrons | 9.73 → 11.32 (+16.3%) | 13.5 → 20.3 | 55 → 58.4 | B |
| Knight Defender | Imperial Knights | 11.16 → 12.17 (+9.0%) | 19.6 → 31.5 | 47.4 → 53.4 | B |
| Doom Scythe | Necrons | 16.54 → 17.70 (+7.0%) | 54.1 → 59.8 | 56 → 58.9 | B |
| Haarken Worldclaimer | Chaos Space Marines | 17.05 → 17.77 (+4.3%) | 53.9 → 58.2 | 35.4 → 37.6 | C |
| Chaos Acastus Knight Asterius | Chaos Knights | 7.39 → 7.69 (+4.0%) | 11.3 → 13.7 | 34.7 → 35.9 | D → C |
| Monolith | Necrons | 10.72 → 11.11 (+3.6%) | 24.1 → 25.6 | 54 → 54.8 | B |
| Acastus Knight Asterius | Imperial Knights | 7.45 → 7.72 (+3.6%) | 11.6 → 14.1 | 34.8 → 36.1 | D → C |
| Armiger Moirax | Imperial Knights | 17.34 → 17.88 (+3.2%) | 56.9 → 62.1 | 67.4 → 70.1 | A |
| War Dog Moirax | Chaos Knights | 17.34 → 17.88 (+3.2%) | 56.9 → 62.1 | 67.4 → 70.1 | A |
| Hearthkyn Warriors | Leagues of Votann | 19.91 → 20.22 (+1.6%) | 65.3 → 67.7 | 74.7 → 75.9 | S |
Blast X
18 units' Offense moves by this keyword alone (14 live, Legends and Crucible aside).
| Unit | Army | Its own move (five targets summed) | Offense score, before → now | Value, before → now | Letter |
|---|---|---|---|---|---|
| Mek Gunz | Orks | 23.23 → 25.65 (+10.4%) | 87.4 → 90.1 | 60.2 → 61.5 | B |
| Killa Kans | Orks | 17.58 → 18.80 (+7.0%) | 58.5 → 61.6 | 67.8 → 69.4 | A |
| Burna-bommer | Orks | 8.45 → 8.76 (+3.6%) | 12.6 → 10.3 | 43.6 → 42.4 | C |
| Morkanaut | Orks | 11.28 → 11.45 (+1.5%) | 27.4 → 27.5 | 55 → 55.1 | B |
| Stompa | Orks | 8.56 → 8.59 (+0.4%) | 17.7 → 17.8 | 44.2 → 44.3 | C |
| Gorkanaut | Orks | 13.72 → 13.74 (+0.2%) | 32.9 → 40.5 | 59.3 → 63.1 | B |
| Deffkoptas | Orks | 22.21 → 22.24 (+0.1%) | 74.6 → 83 | 71.8 → 76 | A |
| Boyz | Orks | 36.12 → 36.12 (0.0%) | 97.5 → 97.5 | 81.8 → 81.8 | S |
| Gunwagon | Orks | 18.01 → 18.01 (0.0%) | 30.3 → 61.8 | 63.2 → 79 | B → A |
| Hunta Rig | Orks | 15.64 → 15.64 (0.0%) | 39.3 → 49.8 | 68.9 → 74.1 | A |
Conversion
7 units' Offense moves by this keyword alone (7 live, Legends and Crucible aside).
| Unit | Army | Its own move (five targets summed) | Offense score, before → now | Value, before → now | Letter |
|---|---|---|---|---|---|
| Knight Defender | Imperial Knights | 10.60 → 12.17 (+14.8%) | 19.6 → 31.5 | 47.4 → 53.4 | B |
| Chaos Acastus Knight Asterius | Chaos Knights | 7.08 → 7.69 (+8.5%) | 11.3 → 13.7 | 34.7 → 35.9 | D → C |
| Acastus Knight Asterius | Imperial Knights | 7.16 → 7.72 (+7.8%) | 11.6 → 14.1 | 34.8 → 36.1 | D → C |
| Brôkhyr Thunderkyn | Leagues of Votann | 29.85 → 31.17 (+4.4%) | 94.8 → 95.9 | 65.6 → 66.2 | S |
| Armiger Moirax | Imperial Knights | 17.34 → 17.88 (+3.2%) | 56.9 → 62.1 | 67.4 → 70.1 | A |
| War Dog Moirax | Chaos Knights | 17.34 → 17.88 (+3.2%) | 56.9 → 62.1 | 67.4 → 70.1 | A |
| Hekaton Land Fortress | Leagues of Votann | 15.91 → 16.03 (+0.7%) | 53.2 → 53.9 | 71 → 71.3 | S |
Anti-X spellings
12 units' Offense moves by this keyword alone (11 live, Legends and Crucible aside).
| Unit | Army | Its own move (five targets summed) | Offense score, before → now | Value, before → now | Letter |
|---|---|---|---|---|---|
| Stonesinger | Aeldari | 22.68 → 35.65 (+57.2%) | 80.6 → 98.8 | 45.9 → 55 | C → B |
| Squighog Boyz | Orks | 22.36 → 25.43 (+13.7%) | 76 → 90.9 | 53.6 → 61 | S |
| Ancient in Terminator Armour | Space Marines | 19.80 → 21.85 (+10.4%) | 68.3 → 82.2 | 59.3 → 66.3 | B → A |
| Gunwagon | Orks | 16.81 → 18.01 (+7.2%) | 30.3 → 61.8 | 63.2 → 79 | B → A |
| Beastboss on Squigosaur | Orks | 24.25 → 25.54 (+5.3%) | 84.6 → 88.5 | 85.6 → 87.5 | S |
| Painboss | Orks | 12.28 → 12.83 (+4.5%) | 29.3 → 32.7 | 19.9 → 21.6 | D |
| Beast Snagga Boyz | Orks | 43.64 → 45.56 (+4.4%) | 99.1 → 99.5 | 88.1 → 88.3 | S |
| Mozrog Skragbad | Orks | 23.57 → 24.61 (+4.4%) | 81.9 → 85 | 83.8 → 85.3 | S |
| Hunta Rig | Orks | 15.19 → 15.64 (+2.9%) | 39.3 → 49.8 | 68.9 → 74.1 | A |
| Kill Rig | Orks | 14.48 → 14.77 (+1.9%) | 34.5 → 44.8 | 65.8 → 70.9 | A |
Twin Linked
6 units' Offense moves by this keyword alone (5 live, Legends and Crucible aside).
| Unit | Army | Its own move (five targets summed) | Offense score, before → now | Value, before → now | Letter |
|---|---|---|---|---|---|
| Night Spinner | Aeldari | 10.14 → 12.45 (+22.8%) | 16.1 → 27.2 | 30.1 → 35.7 | D → C |
| Warlock Skyrunners | Aeldari | 15.00 → 16.47 (+9.8%) | 33.2 → 41.5 | 27.4 → 31.5 | A |
| Farseer Skyrunner | Aeldari | 18.39 → 19.48 (+5.9%) | 57.7 → 62.9 | 44.8 → 47.4 | A |
| Hellions | Drukhari | 22.25 → 22.25 (0.0%) | 75.2 → 74.9 | 53.5 → 53.3 | S |
| Shining Spears | Aeldari | 33.54 → 33.54 (0.0%) | 94.9 → 94.7 | 55.3 → 55.2 | A |
Devastating Wounds with a condition
8 units' Offense moves by this keyword alone (6 live, Legends and Crucible aside).
| Unit | Army | Its own move (five targets summed) | Offense score, before → now | Value, before → now | Letter |
|---|---|---|---|---|---|
| Leystalker | Aeldari | 10.19 → 9.26 (−9.1%) | 20.1 → 14.1 | 12.3 → 9.3 | D |
| Painboy | Orks | 21.54 → 20.25 (−6.0%) | 83.2 → 74 | 44.6 → 40 | S |
| Warbuggies | Orks | 25.88 → 24.69 (−4.6%) | 90 → 79.4 | 76.4 → 71.1 | A |
| Gunwagon | Orks | 18.01 → 18.01 (0.0%) | 30.3 → 61.8 | 63.2 → 79 | B → A |
| Knight Desecrator | Chaos Knights | 11.82 → 11.82 (0.0%) | 30.7 → 30.5 | 46.2 → 46.1 | B |
| Zodgrod Wortsnagga | Orks | 25.49 → 25.49 (0.0%) | 91.6 → 91.5 | 56.5 → 56.4 | B |
Sustained Hits with a condition
1 units' Offense moves by this keyword alone (1 live, Legends and Crucible aside).
| Unit | Army | Its own move (five targets summed) | Offense score, before → now | Value, before → now | Letter |
|---|---|---|---|---|---|
| Beastboss | Orks | 32.04 → 26.73 (−16.6%) | 97.8 → 90.4 | 62.8 → 59.1 | A |
Overcharge
1 units' Offense moves by this keyword alone (1 live, Legends and Crucible aside).
| Unit | Army | Its own move (five targets summed) | Offense score, before → now | Value, before → now | Letter |
|---|---|---|---|---|---|
| Arkanyst Evaluator | Leagues of Votann | 16.37 → 15.38 (−6.1%) | 58.1 → 53.8 | 34.9 → 32.8 | B |
Letters that move on the site
16 letters move: 11 by the units' own numbers (9 live, 2 Legends), 5 because Value is a percentile and the movers re-sort it (3 live, 2 Legends).
| Unit | Army | Letter | Value | Why |
|---|---|---|---|---|
| Gunwagon | Orks | B → A | 63.2 → 79 | Cleave (+27.4% alone), Anti-Monster/Vehicle (+7.2%) |
| Warboss in Mega Armour | Orks | B → A | 59.4 → 67.9 | Cleave |
| Ancient in Terminator Armour | Space Marines | B → A | 59.3 → 66.3 | "Anti Vehicle 3+" on its chainfist |
| Stonesinger | Aeldari | C → B | 45.9 → 55 | Anti-Monster/Vehicle and Anti-non-Monster/Vehicle |
| Night Spinner | Aeldari | D → C | 30.1 → 35.7 | Twin Linked |
| Acastus Knight Asterius | Imperial Knights | D → C | 34.8 → 36.1 | Conversion and Sustained Hits D3 |
| Chaos Acastus Knight Asterius | Chaos Knights | D → C | 34.7 → 35.9 | Conversion and Sustained Hits D3 |
| Wartrakks | Orks | C → D | 36 → 34 | Lethal Hits no longer against vehicles |
| Wazbom Blastajet | Orks | C → D | 35.5 → 33.8 | Lethal Hits no longer against vehicles |
| Lifta Wagon (Legends) | Orks | A → S | 73.8 → 83 | Cleave (+19.5% alone) |
| Kill Tank (Legends) | Orks | C → B | 49.2 → 50.6 | Cleave and Anti-Monster/Vehicle (+4.5% and +4.4% alone) |
| Impulsor | Space Marines | A → B | 65.1 → 64.9 | Re-sorting only (its numbers didn't move) |
| Aquila Kill Team | Agents of the Imperium | A → B | 65.2 → 64.9 | Re-sorting only (Rapid Fire D3 counts at half range, which the table isn't) |
| Wave Serpent | Aeldari | A → B | 65.1 → 64.8 | Re-sorting only (its numbers didn't move) |
| Bike Squad (Legends) | Space Marines | A → B | 65.1 → 64.9 | Re-sorting only |
| Shadow Spectres (Legends) | Aeldari | D → C | 34.9 → 35 | Re-sorting only |
The calculator
Besides the rules above, three things a player sees:
- Anti-X counts on its own against a target with the keyword (every Anti weapon, not only the new spellings). The weapon's keyword badges already showed it; the numbers now follow.
- The Rapid Fire field takes a number or dice ("D6+3"); a Knight's battle cannon fills it from its keyword.
- Conditions follow the target. An Ork shoota has Lethal Hits into Intercessors and none into a Rhino; the Painboy's syringe's Devastating Wounds work into Infantry only.
Tests
- tests/unit/keywords.test.js (new): each keyword's closed form against a value worked by hand (24 cases: both sides of every condition, Cleave and Blast at 10, 12 and 4 models, the core rules' Blast 2 example, Conversion beyond and within half range, each Anti spelling into a matching and a non-matching target, Rapid Fire D3 and D6+3 at and beyond half range, Psychic Assassin into a Psyker and not, with cover; Overcharge's hazard cost 4/6 against 2/6; Sustained Hits D3 the same hits as Sustained Hits 2, different kills); the closed form against the dice engine with the parameters the calculator builds, on those 24 and 9 real profiles (Big Choppa, the rapid-fire battle cannon at half range, the conversion beam cannon, the Thump Gun into a Rhino, the Big Shoota into Termagants and into a Rhino, the Stone Stave, the frag cannon at half range): attacks, hits, wounds and unsaved wounds within 4% over 40,000 volleys; the calculator's seed and ev.js's reader alike on every weapon; the 15 newly read keywords classified as read by tools/matrix.js, the 6 non-dice ones as unread.
- tests/unit/volley.test.js: a volley with Sustained Hits D3, Rapid Fire D6+3, Blast 2, Cleave 1 and Lethal Hits: every bullet adds up to the engine's own counts, as for the other rules.
- tests/unit/invariants.test.js: the attack-count invariant reads Blast X, Cleave X and dice Rapid Fire, and compares the readers on the abilities without a condition. tests/unit/ev.test.js's harness reads a dice Sustained Hits. tests/unit/matrix.test.js: the killDP check drops Cleave with Blast (both add attacks by the target's size); a condition keeps a profile's key apart.
- The whole suite (unit and browser, BSData 8b91e6b): 464 passed, 4 failed, the same four as at the old head: ledgercheck (
beta: '3'against tools/ledger-best.json), matrix's killDP bound on one cell (T-606), and on this machine share's clipboard and shootout's big units (timeouts).
The points ledger didn't move
The ledger reads its frozen inputs (T-603: eb3590a, hash 30f0056e6103), so this card's docs/ev.js never reaches it. node tools/ledger-inputs.js --verify: 26 inputs match the lock. With this card's docs/ev.js and app.js in place, every ledger tool was rerun (ledger.js, charge.js and spawn.js --write for Tyranids and Space Marines, soakfx.js --write, scarcity.js --write, ledger-merge.js): all nine outputs, docs/lab/ledger/tyranids.json and space-marines.json, tools/charge-, spawn-, soakfx-, scarcity-tyranids.json and charge-, spawn-, spawn-rules-space-marines.json, are byte-identical to the commit before (sha256). With this card's tools/matrix.js and allocate.js as well (the ledger runs them live, against its frozen ev.js), every number is identical and only meta.engine moves (the hash of the ledger's engine files, two of which this card edits) with the merge's sha256 of the scarcity file that carries it; the committed outputs are left as they were. matrix.js reads every new field of ev.js's reader as absent when it isn't there, so under the frozen ev.js its keys and classes are what they were.
For the supervisor
Decided alone.
- The calculator reads Anti-X from keywords now, for every Anti weapon. It never did; reading the new spellings in the dice engine needed it, and it brings the calculator to the unit pages' numbers. Worth a line to Jordan: a player who set the manual pick for an Anti weapon will see the same result; one who didn't sees more wounds.
- Conversion as beyond half range. No range state exists outside half range; every Conversion gun reaches 24" or more, so the reading is exact beyond half range. Inside half range a 48" gun could still be beyond 12"; we take it as off there.
- "Cleave 2+" as Cleave 2, "Anti-fly 2" as 2+, "Lethal Hits: non-" as plain Lethal Hits. Data misprints, read the way the rule must mean.
- The lone "-" stays on the matrix's list (7 entries), so tools/matrix.js behaves the same under the ledger's frozen ev.js.
Doubts.
- The "+X blast" note under the calculator's hits now counts Cleave's extra attacks too (both are per five models); its label still says Blast.
- tools/allocate.js reads Blast X (T-569's field tool, not live); it doesn't read Cleave on melee groups yet.
- Rapid Fire's dice are rolled once per volley for the whole squad in the calculator, as its Attacks dice already are: the same average, a wider spread than one roll per model.
Screenshots (scratchpad, not committed): the calculator's default and the Stonesinger's and Gunwagon's pages (top and Offense), desktop and 390px, light and dark.