Files
RingBRP/tools/powers-beasts.mjs
T
slaguru666andClaude Opus 5 f68b98190f bestiary + check-powers: read the seam, and classify what that reveals
bestiary.mjs built the document from NPCS, so it described 47 creatures of
147 while check-bestiary agreed with it — two things agreeing is not
verification when both read the same wrong source. It reads collectSpecs()
now: 184 creatures across 5 sections, every one with a measured lethality
figure, which only works because check-lethality was fixed first.

Three faults surfaced fixing it:

  - a second NPCS reference in focusParagraph()
  - which then broke on `rows`, because focusParagraph declares its own
    local `rows` for focus-fire data and shadowed the creature list. Keyed
    lookup now, so the shadowing cannot bite again.
  - the document grouped on the raw role tag against a list of four, and
    `if (!group.length) continue` DROPS an unlisted tag rather than
    mis-filing it. Nine of the twelve tags were absent, so those creatures
    would not have appeared at all. Twelve tags now map onto five sections,
    with a new "Beasts and heraldry", and a completeness assertion counts
    every creature into a section and fails if one is unplaced.

check-powers was the fifth consumer bypassing all-specs.mjs. It reconciled
its counts against BESTIARY while reading NPCS, so it called the document
wrong when the document was right.

Reading the real population then demanded 101 classifications. All 101 are
done and NOT ONE was wired. That is the right answer, not a shortfall:
the three available effects describe the creature — its own attack rating,
the damage it takes, whether it feels defence stacking — and essentially
every power is conditional on a place, a posture, a round count, a weapon
type, an attacker count, a named agent, or Coherence. R-275 records what
wiring one anyway costs: 25.1% to 75.2% on a single creature.

The near-misses are the evidence the reluctance was applied, not recited:
tangie's "HALF damage" is edged-only and ends in open flame; the_heron is
+30% or -20% depending on movement the harness does not have, so which
branch applies is undecidable; mirrorline's halving lands on an AGENT, not
on the creature, so wiring it would have protected the wrong combatant;
yale's defence waiver is capped at two attackers and its written counter is
a fourth agent, which defenceStacking:"ignores" cannot express.

Classifications live in four band files and are spread into POWERS last, so
a hand-written entry always wins a collision. 142 classified: 2 wired, 78
beyond the harness with a reason, 62 not fight rules.

All 23 guards pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 23:28:13 +01:00

90 lines
9.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* What each POWER in bestiary-beasts.mjs does in a fight — the beasts, heraldry and
* hybrids share of the classification, merged into POWERS in powers.mjs.
*
* Same three kinds, same rule: read the header of powers.mjs first, and in particular the
* `supporter` entry, which is the nearest relative of everything in this file. Its ARGENT
* AND GULES was wired as a flat half-damage because the harness has no ground, and the
* condition "while it stands on ground the borough holds" therefore applied always — the
* wipe rate moved from 25.1% to 75.2%, a fifty-point error caused entirely by wiring a
* conditional power. R-275.
*
* Nothing in this file is wired, and the reason is worth stating because this band is
* where the temptation is worst. Half of these creatures have a route through their
* armour written into the tactics, and every one of those routes is a condition:
*
* heath_cow half damage from edged, firearms and energy, FULL from bone or blunt
* water_bull armour 8 wet, dropping 1 a round from round three to a floor of 3
* sign_wyvern / gryphon armour halves once a wing or a leg is out
*
* damageFactor is a single unconditional number with no notion of what hit the creature,
* which round it is, or whether the thing is still standing up. Wiring any of the above
* would repeat the supporter's mistake exactly.
*
* Nor are the armour routes powers in the first place. Grounding a flyer halves its hide
* everywhere but the vital, and a wing carries none at all: that is `exposedHideFor` and
* the `bare` flag in anatomy.mjs already doing the work through the location table, and
* simulate.mjs applies it per location in armourAt(). The tactics of the eagle, the
* gryphon and the wyvern only describe it. So the classification below is about what each
* power adds ON TOP of that, and where the answer is "nothing", the entry says so.
*
* The charges and the drops — the azure bull's doubled gore, the tup's extra 1d4 on the
* run-up, the gryphon's 15m stoop for 3d6 — are extra damage DEALT on a named manoeuvre.
* The three effects the harness understands cover the creature's defence stacking, the
* damage it takes, and its own attack rating. None of them is a bonus to the damage it
* deals, and none of them can be gated on a straight line, a blind side or a target's SIZ.
*/
export const POWERS_BEASTS = {
/* ---- notSimulable: fight rules the harness cannot express ---- */
bull_azure: { name: "THE CHARGE", kind: "notSimulable",
why: "a named manoeuvre that doubles the gore only after 10m or more in a straight line, which the tactics itself says can be broken with cover or a scattered team — the harness has no ground to run across and no effect that multiplies damage dealt" },
enfield: { name: "BADLY ASSEMBLED", kind: "notSimulable",
why: "a crippled limb costs it nothing in initiative or attack, and the harness has no key that waives a wound penalty — woundPenaltyFrom is what simulate.mjs charges for a ruined limb, and defenceStacking: \"ignores\" waives the cumulative penalty instead, which is not the penalty this power waives" },
yale: { name: "BOTH WAYS AT ONCE", kind: "notSimulable",
why: "it defends two attackers in the same round at no penalty but the ordinary cumulative penalty returns at three or more, and defenceStacking: \"ignores\" has no attacker count — wiring it would waive the penalty against a whole party, which is the answer the tactics explicitly denies" },
man_tyger: { name: "THE FACE", kind: "notSimulable",
why: "costs each attacker a round to overcome the fact that it has a face, only while it is talking, and not at all from surprise or while it is already engaged — the harness has no talking, no surprise, and no way for an agent to lose a round" },
eagle_displayed: { name: "TWO HEADS", kind: "notSimulable",
why: "it cannot be surprised and no stealth approach works while it is airborne; the harness has neither surprise nor stealth, and the wings carrying none of its armour is the `bare` flag in anatomy.mjs, not this power" },
gryphon: { name: "STOOP AND DROP", kind: "notSimulable",
why: "a manoeuvre gated on the target being SIZ 16 or less, whose damage is a 15m fall for 3d6 ignoring armour and which then removes the agent from the fight — the harness cannot gate on a target's SIZ, has no height to drop from, and has no effect for damage dealt" },
sign_wyvern: { name: "A FOOT OF PAINT", kind: "notSimulable",
why: "−30% to attacks made against it from directly in front or behind and nothing from the side; the harness has no facing, and the only attack effect it has is the creature's own attackFactor, not a penalty on its attackers" },
cockatrice: { name: "THE LOOK", kind: "notSimulable",
why: "a POWx5 on meeting its eyes that cripples a location with no wound, ends when it dies, and is void for anybody working by touch or a mirror — the harness rolls no characteristics and has no eye contact to avoid" },
bearward_bear: { name: "THE DOGS ARE STILL COMING", kind: "notSimulable",
why: "it fights on while it can hear anything it takes for dogs and lies down after three full rounds of total silence; the harness has no sound, and a party in it never stops shouting or stops fighting" },
heath_cow: { name: "MILKED DRY", kind: "notSimulable",
why: "half damage from edged steel, firearms and energy but FULL from bone or a blunt improvised weapon, plus a foreleg-and-hind-leg route on the same side — damageFactor is one number with no notion of what hit it, and wiring 0.5 would make the rib in the church useless and halve the blunt hits too" },
tup: { name: "THE BLIND SIDE", kind: "notSimulable",
why: "a charge manoeuvre against a target who is not looking at it: automatic knockdown, a further 1d4 for the run-up and no defence roll, and nothing at all against anybody facing it — the harness has no facing and no effect for damage dealt" },
hollow_hog: { name: "GONE", kind: "notSimulable",
why: "any round it is not engaged it is out of sight at a −30% Spot and re-enters from a new direction; the harness has no positions to vanish into, never looks, and has no disengagement" },
water_bull: { name: "WET HIDE", kind: "notSimulable",
why: "armour 8 while wet, then 1 less each round from the third out of the water down to a floor of 3, so the whole power is a round count and a place — the harness has no clock on armour and damageFactor cannot decay; its 8 is already on the statblock" },
moor_cat: { name: "ONE PASS", kind: "notSimulable",
why: "its FIRST attack in a scene only, from ambush at +30% and knocking the target prone, after which any real injury sends it away for good — attackFactor is unconditional and permanent, so wiring 1.3 would give it the ambush bonus every round of a fight it does not want" },
gaunt_grey: { name: "STILL HUNGRY", kind: "notSimulable",
why: "ignores the penalties from crippled legs and fights on at any hit point total above zero; neither is one of the three effects — simulate.mjs charges the leg through woundPenaltyFrom and stops a combatant at hp 2 through conditionFor, and no key waives either" },
menagerie_ape: { name: "HANDS", kind: "notSimulable",
why: "opens any mechanical lock in a round, climbs anything, and disarms on a successful brawl attack — the harness has no doors and no inventory to take a weapon out of, and it flees an open fight rather than pressing one" },
/* ---- outOfCombat: not fight rules ---- */
white_hart: { name: "THE CHASE IS THE POINT", kind: "outOfCombat",
why: "it does not fight at all — an hourly POWx5 to break off a pursuit, and everybody still following after three hours is somewhere the case did not include" },
melusine: { name: "THE FONT IS A DOOR", kind: "outOfCombat",
why: "a movement rule between bodies of standing water within sight of her carving, confined by draining the font or breaking the line of sight; on land her own entry says she is a conversation" },
martlet: { name: "IT CANNOT COME DOWN", kind: "outOfCombat",
why: "it does not attack and is not a threat to anybody — a mark on one agent for the rest of the case and no recovery for anybody sleeping in earshot, ended by giving it somewhere to be" },
piety_pelican: { name: "PIETY", kind: "outOfCombat",
why: "she will not fight and cannot be driven off the nest; it is a healing bargain priced in her own hit points and in 1 Coherence permanently for every drinker if she dies of it" },
talbot: { name: "IT DOES NOT LOSE THE LINE", kind: "outOfCombat",
why: "an unbreakable track across hours and a Persuade off-switch out of the kennel book; its own entry says the fight itself is an 8-stone dog with a bite that four armed agents can kill" },
gazehound: { name: "IT SEES YOU FIRST", kind: "outOfCombat",
why: "its own entry says it is a HERALD, not a fight — automatic detection at 400m and whatever owns it knowing where the team is, and killing it is easy and pointless" },
cade_lamb: { name: "IT WANTS TO COME IN", kind: "outOfCombat",
why: "it cannot hurt anybody; the power is getting through a door left ajar, plus a −20% to Listen and Spot, and the harness never looks or listens" },
hinny: { name: "IT KNOWS THE ROUTE", kind: "outOfCombat",
why: "it does not attack — a sixty-year round it will not deviate from, and following it is the scenario rather than a fight" }
};