Files
RingBRP/tools/powers-folklore.mjs
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

71 lines
6.7 KiB
JavaScript
Raw Permalink 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-folklore.mjs does in a fight — the folklore 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. Its power was wired unconditionally because the harness has no ground,
* and that moved its wipe rate from 25.1% to 75.2% — R-275. Nothing in this file is wired.
* Every one of these twenty-five powers either is not about the exchange of blows at all, or
* turns on something the harness does not have: a place (a road, a pass, a cut, a pond, a
* church roof), a characteristic roll, a damage type, a target's SIZ, Coherence, a named
* quarry, or a manoeuvre that takes more than one round to land. The three effects the
* harness understands all describe the creature's own defences, damage taken, or attack
* rating; a penalty aimed at the agent's roll is not one of them, however tempting the
* arithmetic looks.
*/
export const POWERS_FOLKLORE = {
/* ---- notSimulable: fight rules the harness cannot express ---- */
hunt_master: { name: "RIGHT OF WAY", kind: "notSimulable",
why: "only against whatever stands between it and one named quarry, and the ride-down is its own 3d6 with a DEXx5 for half — the harness has no quarry, no ground to stand between, and rolls no characteristics" },
gabriel_hounds: { name: "OVERHEAD", kind: "notSimulable",
why: "fires on the round it passes above a group and costs a failed POWx5 the agent's next action; the harness has no fly-over, no action to lose and rolls no characteristics" },
black_annis: { name: "THE REACH", kind: "notSimulable",
why: "denies the target its Dodge, and only from full concealment in a cut it will not leave in daylight — the harness has no concealment, and none of the three effects touches the agent's defence" },
jenny_greenteeth: { name: "UNDER", kind: "notSimulable",
why: "only within arm's reach of water it cannot leave, and it resolves as a cumulative STRx5 grapple handed off to the ASPHYXIA rules rather than a combat" },
hunky_punk: { name: "MASONRY", kind: "notSimulable",
why: "the factor depends on the damage type — minimum from bullets, none from edged, full from a hammer or a fall — and damageFactor is a single number with no notion of what hit it; its ten points of armour are already on the statblock" },
the_teind: { name: "THE ACCOUNT", kind: "notSimulable",
why: "once per scene, an opposed POWx5 that removes an agent from the scene rather than injuring them, and is voidable by a volunteered substitution or by paying the debt — the harness rolls no characteristics and cannot lose a combatant to a bargain" },
dullahan: { name: "THE CALL", kind: "notSimulable",
why: "a POWx5 compulsion on one named person, and the flail only lands on whoever physically restrains them; the flail is already on the statblock and the harness has no name, no roll and no restraint" },
cu_sidhe: { name: "THREE BARKS", kind: "notSimulable",
why: "lands only on the third bark, after the scent and the close, and costs a failed POWx5 the next action — the harness has no sequence of rounds before a power arms and rolls no characteristics" },
tatterfoal: { name: "THE HEDGE", kind: "notSimulable",
why: "−40% to ranged attacks made against it, and the only attack effect the harness has is its own attackFactor; it also has no ranged fire and no hedge to be behind" },
dun_cow: { name: "THE CHARGE", kind: "notSimulable",
why: "a separate straight-line manoeuvre, triggered only by an attempt to take a sample from it, 4d6 with a DEXx5 to be elsewhere and four rounds to line up again — the harness has no trigger, no line and no reload clock" },
boobrie: { name: "THE LIFT", kind: "notSimulable",
why: "only against a target of SIZ 14 or under, and the damage is a drop a round after the talons close — the harness cannot gate on the target's SIZ and has no two-round manoeuvre" },
/* ---- outOfCombat: not fight rules ---- */
grey_mare: { name: "MOUNT UP", kind: "outOfCombat",
why: "it does not attack; touching its back is a POWx5 and a one-way ride to the parish boundary, and nobody has ever been killed by it" },
cailleach: { name: "THE PASS IS SHUT", kind: "outOfCombat",
why: "she cannot fight and will not try — a refusal, then an exposure clock of 1 point per ten minutes on the high ground, and a dead compass" },
gwrach: { name: "THE NAMING", kind: "outOfCombat",
why: "it does not fight and shooting it achieves nothing; the naming costs 1 Coherence and runs for twenty-four hours after the scene it appears in" },
sin_eater: { name: "SIXPENCE", kind: "outOfCombat",
why: "a bargain offered at a cordon and taken only by consent — 2 Coherence for a trained skill, and he will not take by force" },
lych_waiter: { name: "THE WATCH", kind: "outOfCombat",
why: "a STRx5 at a gate to carry grave goods out, without violence; the disposal is burying somebody new in the yard" },
crossroads_man: { name: "NO PARISH", kind: "outOfCombat",
why: "it defeats cordons, warrants, Borrowed Authority and boundaries — containment, not the exchange of blows; its fighting is the 1d6+1 already on the statblock" },
march_stone: { name: "ALWAYS WAS", kind: "outOfCombat",
why: "it rewrites every map and register within a mile and costs a reader 1 Coherence; containment is a two-officer watch, and it cannot be broken by anything carried" },
foundation_child: { name: "THE PIER", kind: "outOfCombat",
why: "it cannot hurt anybody — it holds a viaduct up, and removing it is an engineering problem on a multi-year clock" },
bog_offering: { name: "STANDING WATER", kind: "outOfCombat",
why: "it works on the building, flooding rooms an inch a day and ruining archives; it has never injured anybody" },
hearth_hob: { name: "THE DISH", kind: "outOfCombat",
why: "a payment taboo — thank it and it leaves, and the building's machinery fails over the following month" },
cauld_lad: { name: "COLD WORK", kind: "outOfCombat",
why: "it has never touched anybody; the −20% is on fine manual work and it doubles Repair and First Aid times" },
changeling: { name: "THE SUBSTITUTION", kind: "outOfCombat",
why: "it cannot hurt an adult and does not try; the power is one piece of information about the real child, and acting on it is a crossing" },
uninvited: { name: "THE GIFT", kind: "outOfCombat",
why: "it never attacks; the gift is permanent, rolled on a 1d6 table, and it is declined by inviting it in advance" },
pooka: { name: "THE RIDE", kind: "outOfCombat",
why: "it is not trying to kill anybody — an hour's journey ending in one Major Wound check and an agent who is inconvenienced rather than hurt" }
};