ce1103ec0dfa0e6d0835bb082c66bb028c34aab2
80
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ce1103ec0d |
R-267: a guarded home for the first disabling blow
Another session verified R-266's measurement, agreed the frame was better than its own, and declined to publish it because the figure had no guarded lineage a doubter could re-derive. It was right, and the fix costs 0.7s of build time -- which is the number I should have checked before calling it a reading tool and not a guard. first-blood.mjs gains --update/--check and is now both the reader and the measurement of record; check-firstblood.mjs is a thin wrapper over it, the same shape as check-bestiary. Compares the recorded figures exactly, then asserts only what a page would claim: first blood lands within 5 points of even in the cut, and its swing exceeds the six-a-side line's by more than both noises. Recording it moved the swing from the scratch run's 43 to 40 against a seed-to-seed spread of 2.1 -- high by more than its own noise, which is the argument in miniature. update-readme's COUNT_WORD could not reach thirteen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
8e5a30a263 |
CLEAN GROUND v0.9: the anchor cannot fight, and the cut is three
Reading two narrated fights from another session showed Dominic attacking at `vs 1`, four times in one of them. Confirmed against the sheet rather than the log: weapons is empty and his only combat skill is Firearm (Pistol) 43, with nothing to fire. So the four-player cut fights with Renshaw and Bhattacharya on compact pistols and Braithwaite on a knife — a quarter of the party out of any fight, and a large part of why EXPOSURE already said violence at four players is party-ending without knowing that was the reason. A defect I introduced. "He carries no weapon, and the GM must not fix it" was written as characterisation about an anchor having both hands full, and was never checked against a fight. Not fixed by arming him, which would cost the character to solve what is really a briefing failure. Said out loud instead: his entry now states the 1% plainly and instructs the GM to tell his player BEFORE the game that Dodge 63, First Aid 40, Insight 63 and the anchor are his set-piece. A player who is not told will roll at 1% for twenty minutes and conclude the sheet is broken, which is the actual harm here. The scaling note carries the three-attacker arithmetic and points at Agyeman as fixing the sum as well as the lane; EXPOSURE names the cause in its own prose. Also recorded in the pass-3 log, deliberately NOT applied: the bimodality now has a mechanism — both sides disable at half max HP, so each disable thins the return fire and makes the next likelier, and first blood is a true coin worth 43 points of wipe rate in the cut against 14 at six-vs-six. It reproduces exactly. It stays out of the scenario because it comes from a reading tool with no guarded baseline, and a GM-facing page may not carry a figure nobody can re-derive. The duller published sentence is the checkable one. If that measurement gets a guarded home the paragraph should be reframed around the first disabling blow, which is the better frame. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
19ed0b5f0f |
R-266: the coin is the first disabling blow, and it lands in round two
Reading both ends of the four-player cut — seed 5's sweep and seed 2's wipe — says the fight is not decided by round five but by whoever lands the first disabling hit, on average in round two. Both sides disable on one good blow, so each one thins the return fire and makes the next likelier; nothing pulls a fight back toward the middle. tools/first-blood.mjs measures it: 49.7/50.3 on who strikes first, and 23.1% vs 66.5% wipes on either side of that. Six against six is the control at 8.6% vs 22.4%. A reading tool, not a guard — it records nothing, and no figure from it goes on a generated page. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
6b95a2c5a5 |
CLEAN GROUND v0.8: the player chair found the refusals, and both needed deciding
Desk pass 3 is committed alongside — full session from the player chair, choosing against the scenario at every junction, seed 5580 with one corrected branch at 7731. Every failure case and every pass-2 fix held. What it found instead were the two things players do that no GM-chair pass can reach, because both are refusals rather than rolls. "We are not going through." Three acts live on the far side and the document had no line about declining to cross, which is the most professionally sensible choice a party can make after reading a coroner's note about a man who walked himself to death. Answered now with a reason and not a compulsion: the entry is pegged to a tree that no longer exists, so a seam with no peg does not sit still — waiting does not make it safer, it makes it unfindable, and the forty-one go with it. Registry says that once and leaves the choice alone. A party that still refuses gets a real ending in ten minutes rather than four railroaded hours. "Can we cancel it from in here." A Research fumble and an Anomaly Lore success both landed on a question the document could not answer either way. Decided rather than fudged: cancellation is a REGISTRY ACT ON OUR SIDE, because the entry is a record and the record is held here. So it cannot be done from inside, somebody has to be back through before it happens, and anyone still in the duplicate when it goes goes with it, having never been filed as being there. The Close now costs not only what they choose but who is standing where when it takes effect, and if they are bringing anyone through those two questions collide. Also: Ray Teasdale, the clearance foreman the timeline always implied and the roster never carried — a Persuade success in pass 3 bought an interview with a man who did not exist. Act One's failure case no longer assumes the party is at the farm, since pass 3 spent the act twenty miles away and the automatic notch sat uselessly on the other side of the county. The re-cut is answered on a success as well as a fumble, with the reason: the entry is pegged to the older authority and there is no older tree. Fix 7's conditional target moved onto the countdown row, because I missed it myself eight minutes after writing it. A special for reading the child. And the bimodality paragraph, which took three attempts to earn its place: held when its citation failed, verified after another session found the cause — three separate random generators, so a seed named a different fight in each tool — and corrected once more when its illustration turned out to compare targeting modes rather than the two ends. Published now as 23% nobody down against 45% everybody, decided by round five, with the focus-fire claim removed. Twenty-three fixes across three passes. The cadence is complete; what remains is the print pack and two decisions that are not a scenario's to make. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e84c85be02 |
R-265: name the denominator the two-down row is zero out of
The round-five race line read "zero in 2000 fights", which invites the reading that no fight in the run was a wipe. It is zero out of the 84 that reach round five with two of the three down — a small bucket, and the sentence should say so before the figure goes to print in a scenario. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
8627fa3536 |
One generator, so a citation names one fight (R-265)
tools/playthrough.mjs exists to show a reader why a measured number is what it is. I cited it to another session — read seed 2, see the wipe the 45% row is made of — and the reproduction failed in front of them. They reported different outcomes at both seeds and guessed the cause correctly from outside: the two tools were not drawing from the same stream. They were not. simulate.mjs used a private mulberry32 makeRng; playthrough.mjs had its own LCG written to look like it. Both deterministic, both reproducible alone, and "seed 2" named a different fight in each — which breaks the only thing the tool is for. Its own comment claimed a seed here names the same fight there. check-focus carried a third copy of that LCG, so the two guards described the same game with different dice. makeRng is exported and both files use it. A playthrough seed is now exactly the first fight of simulate.mjs --seed <n>: --runs 1 --seed 2 and the playthrough give 9 rounds, 4 of 4 down, 1 dead, both. The other half was my citation rather than the code: the command I sent omitted --mode, so it plays both targeting arms and prints two fights. They read the last line, I quoted the first. The summary line now names the arm. check-focus re-recorded under the shared stream; figures move a point or two. What it buys is that the bimodality analysis now reproduces the published means exactly — 2.31, 3.03, 0.40, 0.42 against the four rows CLEAN GROUND publishes. Under the old LCG it agreed to within a decimal, which looked like corroboration and was two experiments landing near each other. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
796bb7df73 |
CLEAN GROUND: the second EXPOSURE table, and four ratios that moved with it
Another session re-pinned the main exposure table at
|
||
|
|
8f3e1ff48e |
CLEAN GROUND: re-pin EXPOSURE against the corrected harness
The table was measured at |
||
|
|
6f33525b3a |
CLEAN GROUND v0.7: pass 2's seven fixes, and an opposed roll the game has not got
Desk pass 2 stressed Act Four across five contrarian branches at seed 9314 and is
committed alongside. The fixes from pass 1 held — beat 3's ungated tell worked and
the four-beat spine stopped the sprawl — but the stress found seven more holes.
The serious one: rehearsal step 5 is beat 3's guaranteed fallback, and in branch C
both sides rolled successes, which rules.mjs has no way to resolve. It defines no
opposed roll at all, while the hollow man's tactics text, slice-text.mjs and this
scenario all ask for one. Same class as Scent and Science (Botany): content naming
a mechanic the engine cannot perform.
GM ESSENTIALS now carries a SCENARIO-LOCAL ruling so the case is playable — both
roll, better band wins, ties to the agent, both fail and nothing happens — using
only banding the game already has, labelled a local ruling rather than a rule.
rules.mjs is untouched: whether the system gains a real opposed roll is not a
scenario's call, it is logged as an open question, and the text says to delete the
local ruling if that rule ever lands.
Verified against rules.mjs's own banding rather than by eye. Branch C now resolves
to Okonkwo resisting on equal bands. Branch D, with fix 7, has the understudy
prefer Ashcroft if he accepted THE OFFER, resisting at Difficult —
applyDifficulty(85,"difficult") is 42, the system's own grade and not a number I
invented — which finally makes the fiction and the numbers agree, because a
compromised anchor was previously the hardest man in the room to take.
Also in: the early-kill branch, which pass 2 measured at ten minutes of act and
thirty-five of dead air, now continues as Braithwaite's twenty minutes over a body
wearing Prichard's face, with nobody having yet asked where the real Prichard is;
a miss for Psychology, since the best line in the document cannot sit behind one
40% roll; a critical result for Borrowed Authority, which happens one roll in
twenty-five; step 5's target named as the lowest POW in the room, Okonkwo at 55%,
because a thing that has practised thirty years takes the easiest file; and one
sentence saying the hollow man's anchor immunity does NOT transfer, set up by
Ashcroft being skipped in Act Three so that he draws the wrong conclusion.
The EXPOSURE table is marked correct-as-of-5450521 and still needs re-pinning: the
harness rewrite landed at
|
||
|
|
ad5fd57568 |
The harness was fighting a different animal (R-264)
Reading a narrated supporter fight showed it being hit on armR and head. It has wings; it
has never had arms. Three defects, all in the pipeline every published number comes from.
1. It located hits by species, not body plan — simulate.mjs read defender.species where
the game writes spec.bodyPlan ?? spec.species ?? "baseline" into speciesProfile
(build-packs.mjs:294). The barghest, kelpie and church grim were fought on two legs
with arms, and the supporter with no wings, so the fight its tactics call the one the
agents can win could not occur in a measured fight.
2. Armour was one scalar for the whole creature, and the harness's locations had no
armour field. Bare wings, the grounded halving and the vital exemption — R-254 and
R-255 — were invisible to every number. Worn armour was summed the same way, which put
a stab vest on a cleaner's head.
3. Nothing was ever grounded: a wing could be ruined and the creature kept flying.
Fixed in the game's order — locate, then apply what that location carries, every term
imported from rules.mjs. A ruined wing calls groundedPlanFor and the wounds carry across
by severity through remapLocationDamage, the function _preUpdate uses.
A bug of mine no guard would have caught: remapLocationDamage returns { damage, moved,
rescaled } and my first draft passed the whole object where a damage map was expected, so
every wound a creature carried was forgiven the moment it came down. check-lethality would
have passed it — fewer wounds means a longer fight, which reads as a number moving, and
this commit moves numbers. Found by probing a landing by hand.
20 of 47 creatures moved, 18 deadlier and 2 less. The supporter goes 69.3% -> 25.1% wiped,
3.38 -> 2.16 down, second deadliest to fourth: it was being measured as a 30-hit-point
creature in uniform armour 9 that could not be grounded. The small rises elsewhere are the
party's armour no longer covering locations it never protected.
check-focus then caught the page overclaiming, which is what it is for: focus fire still
helps in all 30 but only 28 clear their own noise where 31 of 31 did. The guard was
asserting more than the page needs — the bestiary prints that count from the artifact and
cannot overstate it — so it now checks only what the page asserts outright, and the page
rewrote itself to "in 28 of them".
Both baselines re-recorded. Minor version, not a patch: the published numbers changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
5dcaaf519a |
The simulator can be read now, not just totalled (R-263)
Every guard here reports a number per creature, and a number cannot say why a fight went the way it did. That gap is what produced R-258 through R-260: each written from a side harness built to watch a fight, each modelling something slightly different from the game, two of the three wrong in ways no guard could catch because no guard was involved. runFight takes an optional `say` sink. It reports what the simulator already decided — the attack roll and its target, a defence and the penalty it was made at, the landing level after a dodge downgrades it, damage against armour before and after armourAgainst, the location, major wounds, disablement, death. It never touches the generator, so a narrated fight and a silent one are the same fight; check-lethality and check-focus both still match their baselines exactly with the hook in place. tools/playthrough.mjs (npm run play) is its consumer, in the same commit deliberately: a hook with no reader is the exact defect this project keeps finding in its own rules, and adding one to the measurement pipeline with only a scratchpad file calling it would have been committing the thing I have spent the session removing. Pack size comes from focus-baseline.json so the fight you read is the fight check-focus measures; creatures recorded as pinned are played solo. Three redcaps, seed 20260913, same seed both ways. Spread fire: wiped in 10 rounds, 3 dead, and all three redcaps still standing — 39 hit points spread three ways so that none of it finished anything. Focus fire: same opening, diverging at one target choice in round 1, party wins in 20 with two up. The +13.2 points check-focus records, seen once instead of averaged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
104b588e86 |
R-262: the second R-261, renumbered, deferring to the one that was committed
Two sessions numbered an entry against the same committed log, which ended at
R-260, and both picked R-261. Mine was written first but was uncommitted, so the
other session could not have seen it and had every reason to think the number was
free. When it staged docs/REVIEW_LOG.md my entry was sitting in the file, so it
went out inside
|
||
|
|
1d915c55cf |
check-focus: the focus-fire claim is an artifact, not a sentence (R-261)
R-258 put a tactic on a GM-facing page from an unguarded harness, R-259 found it worth
nothing, R-260 found the replacement right for the wrong reason. Three corrections, each
landing as prose with nothing checking it — the arrangement that let
|
||
|
|
555fa761c0 |
check-rollable: guard eleven, because a real skill is not the same as a route
check-scenarios resolves every skill a scenario NAMES against the catalogue, which is a different question from whether anybody present can roll it. CLEAN GROUND shipped four commits with three clues gated on Track (base 10), Navigate (base 10) and Science (Botany) — base 1, so the 1% floor was the whole of it — and every guard passed, because all three are perfectly real skills. A desk playtest found it by auditing the acts against the sheets the scenario casts. That audit is mechanical, so it belongs in the build. Two tiers. Corpus-wide, some roster agent must reach VIABLE for every skill any scenario names. Per scenario, a document that DECLARES its cast is held to that cast instead, and that is the tier that catches this defect class. The cast is declared rather than inferred, and that is the interesting part. The first version scraped pc_ keys out of the prose and swept up the substitutes named in CLEAN GROUND's player-count scaling — a cast of nine instead of six, which put Sandoval and his Track 35 in scope and made the guard pass the very bug it was written for. A guard that guesses the cast is worse than none, because it reports success. CLEAN GROUND now carries a cast comment and the guard reads it off the raw text, since scenarioText strips HTML comments. Verified load-bearing rather than assumed: re-injecting the original Track tag into the real CLEAN_GROUND.md fails the guard, naming the skill, the base chance and the declared cast. Worth recording that the corpus-wide tier would never have caught it — Lindqvist trains Botany at 40, so it is rollable by the roster and simply not by the six who were cast. The first fixture test passed for that reason and misled me; only the declared-cast tier finds this. VIABLE is 25 and is justified, not picked: it is the commonest base chance in the catalogue, what an untrained agent brings to Spot, Listen or Brawl, so it is the level the game itself treats as worth attempting. Below it a clue is not gated, it is buried. check-scenarios exports its tag parser rather than growing a second copy, behind the invokedDirectly pattern simulate.mjs already uses; a duplicated parser is exactly what this repository's one standing law forbids. update-readme then caught me fairly — it cross-checks the advertised guard list against npm run check — so the guard is registered there too and the README advertises eleven in all three places. No REVIEW_LOG entry: the log is clean at R-260 and is being appended to every few minutes by concurrent work, so the end of that file is the likeliest place to collide. Left for whoever next touches it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
48216bae10 |
Focus fire across all 47, and the same confound one turn later (R-260)
Measured in simulate.mjs. For each creature, the pack size whose spread-fire win rate lands nearest 50% — a fight at 0% or 100% cannot show an effect, which is why R-259's first sample was three-quarters useless — then focus versus spread, 2000 fights across three seeds. 31 of 47 creatures had a pack size that could show anything. Focus fire helped 31 of 31, by more than that row's own noise 31 of 31 times, mean +12.8 points. Best is 6x The margin, 40.4% -> 61.1%. The other 16 are unmeasurable rather than unaffected: eleven are trivial six at a time, five are hopeless in pairs. R-259's decomposition was confounded, and I wrote it while correcting a confound. It credited the defence ladder with 4-5 points by comparing dodge <=30% against dodge >=55% — but the low-dodge samples were PAIRS and the high-dodge ones TRIOS. Held at a fixed pack size, dodge is worth 1-2 points. Pack size is the driver: 8.0 points for a pair, 14-15 for three or more, then flat. What focus fire buys is that a dead creature stops attacking and a half-dead one does not attack any less. Two failures, one cause: comparing groups that differ in more than the thing being measured. The control is cheap and I did not run it until the third time. The bestiary advised concentrating fire and gave the ladder as the reason — right advice, wrong reason. It now gives the reason that survives measurement. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
bf8db68383 |
CLEAN GROUND v0.6: the eight fixes desk pass 1 earned, and its log
Desk pass 1 is committed alongside, seed 4271 and the roll stream printed, so the run is re-checkable rather than remembered. It failed the scenario, which is what it was for. The pre-flight audit did the real damage before a die was rolled: Track, Navigate and Science (Botany) were named by the acts and rollable by nobody in the cast, and Botany is base 1 — the same unusable-test defect fixed in Act Four two commits earlier and left standing in Act One. check-scenarios cannot see this; it resolves skill names and has no opinion on whether anyone present can roll one. Then the dice found the rest. Xenology (Baseline) failed and Act Four had no route left, which is the concentration risk logged as an open question arriving as a dead end on the first run. A fumbled Anomaly Lore had no written result and I invented a ruling at the desk. Act One's failure case backstopped arrival rather than the peg. The act ran 4:25 against 3:55 on three lucky rolls. Fixed: the notch is automatic and the three broken routes moved onto Spot, Knowledge and Anomaly Lore; every roll in the document now carries a written miss; the Act Four tell is ungated, with Xenology buying it early and privately instead of holding the only key; the fumble is answered by the re-cut delusion, tried once, failing in silence; Act Four has a four-beat spine because with no mechanical threat the structure has to be in the text; and THE OFFER finally fires Ashcroft's seam, priced at 2 Coherence he must accept before being told. Verified by re-running seed 4271 through the rewritten acts, so the identical rolls that broke the run were put back through the fix. Every one now has an answer, and Act One's three must-land clues all land despite two failures. Timing is improved and NOT solved: cuts recover 20-25 minutes, landing near 4:00-4:05 on a 3:55 budget, and on-the-minute is a fail for strangers. A third cut is likely needed and the candidate is named. Whether Act Four's spine holds 45 minutes, and whether THE OFFER plays as a decision, cannot be settled from a desk and are recorded as such. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
995f3fa94e |
The firing order was worth nothing, measured properly (R-259)
R-258 put a tactic in the bestiary on the strength of a table-side harness — cheapest weapon first, best weapon last, 10.7 points of win rate across 24 orderings. Measured in simulate.mjs, the pipeline every published number comes from, it is worth +0.27 points, with per-seed differences of -1.5 to +1.8 against 2.6 points of noise on a single arm. Zero. The toy lied for two reasons, both mine. Its party had one uniquely valuable weapon (an anti-materiel rifle the borough does not own, so unhalved, worth double anything else) so there was something to sequence around; the frozen party is 4.09, 3.98, 1.43, 1.43 — two near-identical pairs. And the toy fixed the order every round, while the game re-rolls Reaction every round and has no rule for holding an action, which I checked before measuring. The order is not a decision the rules offer, and I had written table advice for it. The page is corrected: the ladder stays, because it is derived and true, and it now says you cannot choose who goes first. What is worth doing, measured the same way: committing a round's attacks to one target, in fights that can actually move (a fight at 0.2% or 100% cannot show an effect and three of my first four samples were pinned there). Against dodge <= 30% focus fire gains 7.6 points, which is just killing attackers sooner; against dodge >= 55% it gains 12.2, so about 4-5 points is the defence ladder and the rest is arithmetic unrelated to dodging. Separating them needed contested fights at both ends of the dodge range — without that control I would have credited all 13.8 points against three redcaps to the ladder, which is R-255's mistake again. runFight gained two hooks, off by default and unused by the baseline: partySequence rearranges the party within the slots initiative already gave them, leaving enemies where they fell so the experiment isolates agent order from who acts before the creature; and partyTargets "focus" concentrates fire. Both roll the same dice, and check-lethality confirms all 47 creatures still fight exactly as recorded. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
f932a79121 |
The firing order, in the bestiary, generated (R-258)
DEFENCE_STEP is -30, so a creature's Dodge is not a percentage it has for a round — it is one it has once or twice. The median dodge in the book is 45% and goes 45 -> 15 -> 1 inside a single round. No player-facing document said so, which hid a real decision: what order the party shoots in. The bestiary now has a section on it. Only a landing hit spends a defence, so a miss strips nothing; each landing hit makes the next attack of that round easier; therefore the cheapest reliable weapon fires first and the one you most need to land fires last — against the supporter, the weapon the borough does not own. Everything it states is generated from DEFENCE_STEP, resolveBands and the statblocks: the step, the ladder, the median, the spread (13 of 47 creatures stripped by one landing hit, 25 by two, 9 by three) and the list of the hardest to strip. Negative-tested by setting the step to -15 and -20; the page rewrites itself both times. No win rates are published: the ordering measurements come from a table-side harness that ignores wound penalties, bleeding and dying, so the page states the mechanism and quotes no percentages. My first draft used the dodgiest creature in the book as the worked example — 80%, three landing hits to strip — directly beneath a claim that the first attack of the round eats the dodge. True of a modest dodge, false of a good one, and both were on the same page. tools/bestiary.mjs --check has existed since the document did, with the comment "(for the guards)", and no guard ever ran it: a check written and wired to nothing, the same shape as every rule found computed and never read. That was tolerable while the page restated statblocks and is not now that it derives from rules — change DEFENCE_STEP and the document lies to a GM. check-bestiary.mjs is the tenth guard, negative-tested both ways it can fail: a rule change that staler the page, and a hand-edit of the page. update-readme flagged it as "run by the build, not advertised" before I listed it, and the README's count word went from nine to ten by itself. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
15da21d265 |
CLEAN GROUND: the understudy cannot hurt them and the refugees can
Measured rather than asserted: tools/simulate.mjs, 2000 runs a row at seed 11 against the named cast of six, at a clean tree, with the command in the section so any figure can be re-checked after a rule moves. Re-ran two rows to confirm determinism before publishing them. The understudy alone is 0.48 of six hurt, no wipes, median two rounds — a 1d3 punch at 60%. Six of the column wipe one party in twelve and ten wipe five in six, with the curve between them almost vertical. So the lethal encounter in this scenario is not the monster in Act Four, it is the refugees in Act Two, which is the case's moral argument turning out to be its combat maths too. Four consequences written up for the GM: do not buff the understudy, because the horror is that it passed every test the party had; adding hollow men buys rounds and not danger, and six of them cost a median twelve rounds that the Close then pays for; the column must never become a threat, for the second reason that the table will lose; and the four-player cut is a different game, where three of the column already wipe two parties in five. Every row is a floor — the harness models no bleeding, Panic, Coherence, cover or fire modes, and Panic and Coherence are both live here. Act Two now carries a pointer to the section, since that is where the dangerous encounter is. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5450521ed2 |
CLEAN GROUND: four sheets of paper, one of which is a trick
CG-H01 is a coroner holding something he cannot file — unfiled man, ninety-year -old joints on a forty-year-old body, and boots resoled nine times by hand, which is the premise in one detail and is not pointed at. CG-H02 is the 1962 minute. Paragraph 4 has the Registrar warning that a place recorded as the place the displaced go must afterwards be furnished with displaced persons, and the Committee noting it without regarding it as an obstacle. Paragraph 5 orders a review that was never held. It is minuted by A.E.W., Clerk (Junior), who is Bhattacharya's predecessor, so that sheet goes into his hand and nothing is said. CG-H03a and CG-H03b are one almanac page each, eleven years apart, same hand and same ruled paper. Seven days of weather and miles walked, and a column headed TO CLEAN GROUND reading 41 mi on every line of both. Laid side by side there is no roll and no explanation: the table says it out loud. The counts carry the cost — fifty-three then, forty-one now. Numbers checked against the rest of the document: 41 survivors including the six hollow men, 11 duplicated miles, and the 41-mile figure inherited from 1962 when it was true on the real map and untestable from inside ever since. Still outstanding: a print-ready A4 pack at 11pt. H03a and H03b must print identically or the trick dies. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c3a337314f |
One armourAgainst, in the authority, shared with the harness (R-257)
Left open by R-256. Two rules decided how a hit meets armour — armourAgainst (a critical
ignores it, a special halves it, rounded down) and damageAfterArmour (what is left never
goes below zero). Both lived in ringbrp.mjs, which is the game. Neither lived in
rules.mjs, which is the authority, so the guard that forbids redefining a rule had
nothing to forbid. tools/simulate.mjs applied armour from its own inline copies of both,
as it had since it was written.
They agreed, which is the whole point. Nothing published was wrong and no guard could
have said they were two things rather than one. But every number in BESTIARY.md, every
row of the lethality baseline and every measurement quoted from R-251 onward comes out of
that harness: change how a special hit meets armour and the game changes, the numbers
describing the game do not, and all nine guards still pass. Same shape as
|
||
|
|
bb10613992 |
CLEAN GROUND: three things the GM says out loud, and the words they must not
The crossing, the first sight of the column, and Ivy at the stump — placed in their acts rather than collected in a section, so the GM meets each one where it is needed. Four sentences, three and three. The notes around them carry more than the prose does. The crossing must not say nuclear, 1962 or ash: the Geiger says the first, Bhattacharya says the second, and ash is a word a player should reach for unaided. The column's six at the back are the hollow men and are one item in a list, not a pause. Ivy's question is reported rather than quoted so it survives both branches, and she does not argue, plead or bargain — anything that makes her pitiable cheapens a decision that has to be taken by people who respect her. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
f847cb2171 |
The sheet header said 9 while the body said 4 (R-256)
Verifying R-255 on a live sheet found the rule working everywhere it was built and contradicted in the first place a GM looks. The header's ARMOUR field is the hide the creature HAS; on a grounded beast the hit-location table under it read 4 and the header still read 9. Nothing computes off that field, so nothing in the code was wrong. It was wrong at the table. The field stays editable and stays 9 — that is the creature's hide and what a GM types into. Under it, when system.grounded is set, the sheet now says what is in play: DOWN: 4 · CHEST 9, derived from exposedHideFor rather than from a second opinion, with the reason on the tooltip. Verified live: no badge in the air, and grounded the badge and the location table agree at 4 with the forequarters at 9. check-rules forbids redefining a rule by NAME, which misses how this goes wrong in practice — nobody redefines exposedHideFor, they write Math.floor(hide / 2) in the sheet because it is cheaper than an import. I wrote that version first and check-rules passed it. It now fails any file outside rules.mjs that halves a hide inline, naming file and line; check files are exempt because stating the expected value independently is what a test is for. That guard also turned up something I have not fixed, recorded in R-256: armourAgainst lives in ringbrp.mjs rather than rules.mjs, and tools/simulate.mjs has its own inline copy of it. They agree today so no published number is wrong, but every figure in the bestiary and the lethality baseline comes out of that simulator. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c0d33ee81d |
Hide 9, grounded 4, vital exempt — the borough is worth 56 points again
R-254 shipped the belly rule and called +6.4 points "modest on purpose". That read the
wrong statistic. +6.4 measured whether grounding helps; the question was whether the
borough still matters, and the gap between fighting the supporter on borough ground and
off it had fallen from 60.6 points to 44.9. Half damage from every departmental weapon is
meant to be the fight's central problem, and I had quietly taken sixteen points off it
while reporting a small number about something else. Same error as R-251.
Three changes that only work together:
- hide 7 -> 9, restoring the weight on the axis that should hurt
- grounded still halves it, 9 -> 4, which an ordinary round beats
- exposedHideFor now takes the location's kind and leaves `vital` unhalved: a beast on
its belly is not presenting its chest to the floor
Measured: 28.4% on borough ground flying, 68.4% grounded, 84.6% off it — a 56.2 point gap
against 44.9 before. Predicted 28.4 / 84.3 / 55.9 before building.
The composition of the three hide functions lives in prepareDerivedData where no test
could reach it, and check-anatomy's guard 6 is deliberately one-sided so it would not
have caught the vital losing its exemption. check-behaviour now composes the same
expression from the real supporter spec and the real tables. Negative-tested four ways:
removing the exemption, un-baring the wings, removing the halving, and inflating the hide
past what a round can beat each fail it with the right message.
Cost: the supporter goes from fifth to second deadliest creature in the book (2.84 -> 3.38
down, 46.8% -> 69.3% wiped). check-lethality refused the build until that row was
deliberately re-recorded.
BESTIARY.md printed the new hide and said nothing about it halving, because the body-plan
blurb predates the rule. The README said "eight guards" in three sentences above a
generated block listing nine. Both are the signature defect in prose: a number written
down that nothing reads. Both now generate.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
ee4e687c6c |
CLEAN GROUND casts six from the duty roster, and Scent was never a test
No new sheets: Ashcroft, Bhattacharya, Renshaw, Braithwaite, Pollard and Okonkwo, cast for six non-overlapping lanes with an act each. Skill figures read out of expandFromRegister rather than retyped, so the compendium stays the authority. Two defects the casting found. Scent's base chance is 0, so the 1% floor was the whole of it and Act Four's "only test that works" was a roll nobody could make; it is Xenology (Baseline) now, which is what the skill is for. That puts the one reliable test on Braithwaite's sheet alone, so the scaling note refuses to let him be dropped and the risk is logged as an open question. Bhattacharya's private box now carries RESERVE ENTRY, which hands the briefing-or-discover decision to a player instead of the GM. Still an outline: no read-aloud, handouts, Act Four exposure model or playtest. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
ca040b7926 |
The belly is not armoured (R-254)
R-95 made losing a wing change the animal. R-96 took the hide off the
wing so losing one was possible. Separately each was right and each was
measured. Together they gave the party a soft target and deleted it the
moment the party hit it:
winged 6/20 ranged faces land on armour 0 (a bare wing)
quadruped 0/20
A service round on borough ground averages 3.75 after halving — 3.75
through a bare wing, 0 through hide 7 — so grounding the creature took
the party's chance of winning from 44.9% to 1.4%, while its own tactics
told the GM that grounding it was the fight they could actually win.
Found by measuring something else. Every aimed-shot configuration made
the party worse, and the most aggressive was the worst: aiming at a wing
at -20% grounds it in 99% of fights and HALVES the win rate to 10.1%.
Buying the objective reliably was the fastest way to lose, which only
makes sense if the objective is a trap. So no aimed-shot rule; the
problem was never the lack of one.
It also retires the "+31 points" I reported for grounding at 1.7.3. That
was win-rate-if-grounded against win-rate-if-not — selection bias, since
the parties that grounded it were the ones shooting well. Forcing the
grounding gives the causal value and it was -43. A correlation of +31
and a causation of -43 out of the same mechanic.
The fix: a heraldic beast is armoured the way it is drawn, across the
back and the flanks. On its belly half that hide is no longer in the
way, so exposedHideFor halves natural armour while system.grounded is
set. Hide 7 becomes 3.
flying grounded worth
on borough ground 45.3% 51.7% +6.4
off borough ground 90.6% 97.9% +7.3
Modest deliberately. Grounding should help, not decide — the borough is
still the real answer. Losing its damage modifier was worth +26.5 and
would have made the wing the whole fight.
check-anatomy gains a sixth property: a flyer must not be harder to hurt
on the ground than in the air. The first version probed at a single
4-point round and declared the fix broken, because 4 sits inside the one
band where a bare wing beats a halved hide — below 5 damage the creature
really is better off grounded, above it much worse. Integrating across
1-12 gives 2.83 flying against 3.75 grounded and reads it correctly.
Negative-tested against 1.7.8's behaviour, which it names.
The lethality baseline is unchanged: its simulation never grounds
anything, so system.grounded never comes up there.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
97fe2704e8 |
Measure creatures over 2000 runs, not 200 (R-253)
R-252 established that a recorded figure carried several points of slack
at 200 runs and that only more runs narrows it. This is that.
Measured by taking every creature under four different base seeds and
looking at how far the four answers sat apart, which is the noise a GM
reading the bestiary is unknowingly trusting:
mean spread worst creature
200 runs 1.28 points 11.5 points
2000 runs 0.36 points 2.7 points
The worst case is what mattered. One creature's published wipe rate
could be eleven points from the same creature rolled with different
dice, on a figure printed in docs/BESTIARY.md for somebody to plan an
evening around. Under three now.
It corrected 19 of 47 published figures, mean 0.35 points: the arrears
6% -> 8.9%, the supporter 44% -> 46.8%, the nuckelavee 13.5% -> 16%.
Each was a sampling artefact printed as a property.
The cost is the part worth recording, because it is why this was never
done. I guessed "maybe a minute of build time" when I suggested it,
which was wrong by a factor of thirty and would have been a fair reason
to say no:
check-lethality alone 0.29s -> 1.88s
whole nine-guard suite 2.55s
BESTIARY.md regenerates from the baseline, so its run count follows
automatically; its header now also says the seeds are derived per
creature, since "at seed 11" stopped being the whole truth in R-252.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
2dbea88d4b |
Seed the lethality sim per creature (R-252)
Each creature now derives its own seed from its key, FNV-1a mixed into
the base seed, instead of every one of them being measured against seed
11.
This is the second reading of the request and the one I had not tested.
What I checked before was position independence — whether a creature's
numbers depend on its neighbours — and that was already true and still
is: inserting a creature ahead of the barghest changes 0 of 47 existing
rows under the new scheme, same as the old. What was NOT true is that
each creature had its own dice. All forty-seven faced the same two
hundred sequences.
Measured, because the argument for doing it is better than the result:
shared 11 per-creature
mean wipe rate across bestiary 5.67% 5.67%
mean agents down 0.538 0.522
rows changed -- 34 of 47
Seed 11 was not biasing the book. There was no systematic luck to
remove, and the aggregate is unmoved to two decimal places. What the
change buys is decorrelation: the error in each row no longer comes from
the same draw as every other row.
The useful number fell out of the comparison rather than the change.
Individual creatures moved up to four points of wipe rate purely from
being handed different dice — the courier 3.5% -> 7.5%, the long walker
66.5% -> 62.5%, quarantine unit 84.5% -> 88.5%. That is the sampling
noise inside any single recorded figure at 200 runs, and it means these
numbers are an exact regression fingerprint and a loose description of a
creature at the same time. Only more runs narrows the second; more seeds
does not. R-252 says so on the page.
seedMode is recorded alongside the numbers and checked, because changing
how a seed is derived moves every row without changing SEED itself. A
baseline from the old scheme is now refused rather than compared against
this one silently and wrongly — verified by running the new code against
the old file before re-recording.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
e54ce9130d |
R-251: measure what ddc4f99 actually did, four commits late
The baseline needed no re-recording — |
||
|
|
ddc4f99ff4 |
Hit locations reach ordinary combat, and creatures get a body
THE DEFECT. locationFor had ONE caller in the engine, hitLocationRoll, and hitLocationRoll was called from fall, burn, detonate and burstAttack. Falling, fire, explosions and automatic fire. Nothing else. rollWeaponDamage rolled dice, printed a number and returned it, so the chat Damage button, the character sheet's damage button and the item sheet's all stopped there. A grenade knew which arm it took off. A sword did not. Every individual piece was already correct - the tables, per-location armour and coverage, disable and destroy thresholds, Major Wound, dying, death, the figure on the sheet. They simply were not joined up, which is why this reads as a wiring change rather than a new subsystem. - rollWeaponDamage now carries through to hitLocationRoll: it rolls the location, applies that location's armour, applies the wound, and handles the rest through the machinery that already owned it. Nothing here re-implements any of that - locationModeFor picks the melee or ranged column from the weapon's class. The two columns have always differed and nothing was choosing between them - with no target it does exactly what it did before and SAYS SO on a card, rather than failing quietly - burstAttack opts out with locate:false - it rolls its own location per round, and letting both fire would have applied every round of a burst twice BODY PLANS. Two new tables: quadruped (four legs, fore/hindquarters, neck, a head that is hard to reach) and winged (that, plus wings). Forequarters are the vital. DISABLE EITHER WING AND IT CANNOT FLY, which is the fight a party can win. Barghest, Kelpie and Church grim were all species "baseline" - a black dog, a horse and a grave-hound, each hit-located with two arms and a chest. Fixed. Added "The supporter", a winged heraldic beast, so the new table is exercised by real content instead of existing unused. Body plan is a NEW FIELD, not a species. A bear is not a playable people with characteristic dice and talents, so creature specs take bodyPlan and the playable species list is untouched. THE NPC SHEET had no hit locations at all - 102 lines against the character sheet's 627 - while every NPC in the game had them derived and wired to consequences. It now carries the body-plan selector, the figure, the per-location table, the condition and a GROUNDED flag. The sheet class already extended the character sheet, so it already HAD the context; the template never used it. FOUND IN PASSING, by the new guard: kind "body" - the abdomen, the trunk, the hindquarters - did nothing whatever. Its printed effect has always promised "-30% to all Physical actions and bleeding 1 hit point per round until First Aid" and the code delivered none of it, on every body plan including the humanoid default. It now bleeds 1, or 2 destroyed, exactly as bodyX says. NEW GUARD: check-anatomy. Every body plan must cover 1-20 exactly once in BOTH modes, every location must be drawn and every drawn shape must be a location, and every kind must be one locationEffectsFor acts on, has effect text for, and has a destruction outcome. Verified it fails on a d20 gap, a shapeless limb and an unhandled kind before wiring it in. Ninth guard. VERIFIED IN A RUNNING FOUNDRY, not just unit-tested: melee bar reads the Melee column and the rifle reads Ranged on the same creature; forequarters graded as a vital hit; a maxed wing set flightLost and the sheet said GROUNDED; the real chat Damage button rolled 1D20 15, found the right foreleg, applied 12 through armour, disabled the leg and took the dog from 16 to 4; and with nothing targeted nothing was touched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
748e061b56 |
CLEAN GROUND: an outline where the department authored its own monster
A v0.1 rough outline, freely adapted from A Hollow Tree (2023) — the walk north that never arrives, and a predator that imitates. Everything else comes out of the system: a 1962 reserve entry that was never cancelled, forty-one people looping eleven duplicated miles, and Borrowed Authority as a detector that can only tell filed from unfiled. Uses existing bestiary entries only. Marked not-runnable: no pregens, read-aloud, handouts, Act Four exposure model or playtest yet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
0c0996858f |
A GM screen taken from the rules that actually run
The figures a GM reaches for mid-scene, on one page: the order of operations, the circumstance ladder, how a roll bands, reaction, the combat round, hit locations, wounds and bleeding, both tracks, the way home, the stations, and the environment. Every number was checked by running the function rather than by reading it — 58 of 58 against rules.mjs, including the eight that moved out of ringbrp.mjs. That matters more than usual here, because `design/` still carries four rulings the code has overtaken: hit points as CON+MAS, a Major Wound at max(9, HP/3), "no hit locations, final", and marksmanship style fixed by home-world gravity. rules.mjs is the authority and the page says so at the top. It is also written to drop straight onto a Loom board: 34 cards, 23 links, nothing swallowed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
322389bc8a |
A bestiary a GM can actually read, and the defect it found immediately
Forty-six creatures and no way to look at them. They live in content.mjs, which is source code, and in the compendium, which shows one actor at a time behind two clicks. A GM prepping a case can browse neither, so in practice the bestiary was whatever the GM happened to remember writing. docs/BESTIARY.md is generated, never hand-written, for the reason the rules journal is generated from rules.mjs: a reference that can disagree with the thing it references is worse than no reference. It opens with a one-page table sorted by how much of a party each creature puts on the floor - the part that gets printed - then an entry each with characteristics, attack, the POWER line pulled out of the tactics, and the measured figure read straight from the lethality baseline. Every number is derived, so the document cannot drift, and check-lethality already refuses the build if the measurements move. IT FOUND SOMETHING IN ITS FIRST RUN. The generic heavy natural attack is keyed `grasp` and was NAMED "Vesh grasp limb". Twenty-two creatures carry it and five are Vesh, so the at-a-glance table cheerfully printed "Vesh grasp limb" against a black dog, a kelpie, a church grim and an apple tree. Renamed to "Grasping limb"; the key is untouched, so every kit reference and every built pack still resolves. That defect was invisible for as long as nobody could see the bestiary in one place, which is the argument for the document. The caveats are given more room than the numbers, deliberately. The measured column is SOLO against ONE frozen party, and the document says so three times: encounter lethality moves with how many there are and, much harder, with who the players brought - the same fight runs 0% to 100% across party choice. It points at --spread rather than pretending a single figure is an answer. Also records the real remaining gap: 21 creatures fight with nothing but their own bodies and still carry human anatomy, so the barghest can be shot in the left arm. The machinery to fix that is built and measured; what is missing is anatomy tables for the shapes they actually are - a quadruped, an immobile object, a swarm. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
2d4f7f18be |
Twenty-four new creatures, and the anatomies finally get used
The bestiary goes 22 to 46: eight more FOLKLORE, eight more HORROR, eight more FORWARD. Ten of the forty-six are now Vesh or Cadence, up from two. That ratio is the point. Both anatomies have had complete hit-location tables, body geometry, species talents and location effects for the whole life of this project and nothing used either, so none of it ran outside the character generator. They are now written to be WORTH the anatomy rather than to wear it: - The relay is five Cadence bodies holding a crossing open, and the crossing closes as they are destroyed. No vital, no head, 10% off everything per body lost - it cannot be dropped and cannot be ignored, which is the species argument entire. - The courier is a Vesh that fights at half rating while its one grasp limb is full. Disable the limb and it drops the consignment and fights properly. The whole encounter turns on a trade the party has to work out. - The census cannot be usefully fought at all: no head means no killing shot, so the fight lasts until somebody opens the ridge, by which time it has counted everyone. - Knockers are the only folklore Cadence, and the committee is a Cadence because a committee IS several bodies and one decision. The rest is written to the house line that most of these are arrangements rather than fights, because a bestiary where every answer is a gun has one page. The washer at the ford will not fight and cannot be made to; the apple tree man wants a drink it has been owed since 1961; the waiting room's exit was never locked and nobody stands up. Measured, 250 runs against four duty-roster agents, seed 11. Nothing accidental turned up: the non-combat entries sit at 0.0-0.1 agents hurt, the fighters at 1.4-2.3, and the only creature over a 10% solo wipe is the stanchion at 14.4% - which is a fixed object with 12 armour whose own tactics say it is a demolition problem and not a fight. The harness can only force a fight, so read that number as "the party punched the pillar". Art regenerated: 24 new portraits, and the eight new non-humans verified to draw exactly as many body parts as their location tables have entries. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
f88c31649c |
The bestiary's first non-human creatures
vesh and cadence have had complete hit-location tables, body geometry, species talents and location effects since they were written, and no creature had ever used either. So none of that had run outside the character generator, and the whole bestiary was hit-located as a person - including a black dog and a stack of paper. THE CHOIR IS A CADENCE. It always was: its tactics say "run them as ELEVEN separate bodies with one initiative between them", which is Distributed and Quorum described in prose because the species that models it had no users. Retagged, and given the two talents. No scenario prose refers to it, so nothing else moves. PRECEDENT is new, and is a Vesh - the first. Built to exercise what makes the species different rather than to be another sack of hit points: no head, so no fight against one ends on a lucky roll, and a sensory ridge for a vital that runs the length of its back and is correspondingly easy to hit. It is also not hostile, which is the point; the encounter is a conversation with something that answers questions about an event that has not happened yet. Two things left deliberately unfixed and written down rather than fudged: - The choir is eleven in the fiction and five in the location table. Reconciling it properly means giving cadence a per-creature body count, which stops the table being a constant and makes the paper doll follow it. That is the right fix and it is not a small one. A note on the spec says so. - Precedent gets unblinking but not out_of_step, though SPECIES.vesh grants both. An npc actor has no Coherence track, and out_of_step costs 1 to use. Also corrects a comment in creature-schema.mjs claiming Out of Step is vesh-locked. It is not - five postings and a roster agent offer it to humans, and locking it would take it off all six. SPECIES[x].talents is what a species is GRANTED; TALENTS[].species is what only that species may HAVE. Two different fields, and only the second locks. Simulated: Precedent 0.68 of 4 hurt over 3 rounds, no wipes. The choir alone is trivial; at the eleven its own tactics call for, 3.05 of 4 hurt, median 18 rounds, 0.3% wipes. Read both as floors - the harness does not model hit locations, so a Cadence's entire mechanical identity is exactly what it cannot yet measure. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
187a317a0a |
mj-queue: the illustrated upgrade path, without a self-bot
The Mac bridge posts /imagine to Discord with a user token. It is not ported here and should not be: Midjourney's terms since 27 May 2026 forbid automated access, there is no official API, and the bridge's own memory note records Discord silently dropping its interactions from 22 July — which is what enforcement looks like from inside. A Windows clone would be a second self-bot on the same account. So this does everything except talk to Discord, which turns out to be most of the work. `next` derives a prompt from the creature's spec and puts it on the clipboard; you paste it yourself; `file` or `watch` renames the download to the canonical name and retires the generated placeholder. One at a time, because the memory note is explicit that concurrent jobs in one channel steal each other's grids. Prompts are derived, not written — anatomy from the location table, scale from SIZ, build from STR against SIZ, plating from naturalArmour — so they cannot drift from the statblock. Three things learned by reading the data rather than assuming it: - tactics is written for a GM, not an illustrator. "Advances by bounds, 15 m per round" put a rate of fire in an art prompt. role is the one-line essence and is already the sentence you would hand an artist. Sentences carrying mechanics are dropped; dates and ages are kept. - era is the wrong test for whether something is a person. It classified Mr Bewley of the Registry and everyone in 1881 Cordera as monsters, because their kit is old. - 18 creatures are species "baseline" and are not human-shaped — a black dog, a case file that eats case files, a machine that has decided it is the site. The prompt refuses to describe a body it cannot verify, and `list` names them. That is a statblock to write, not something to paper over here. `sheet` emits a prompt sheet that the existing gen-art.mjs parses unchanged, so if the bridge ever works again the whole bestiary drives from it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
10f588b666 |
Plan: the creature forge
Five parts - schema and validator, lethality harness, forge CLI, procedural portraits, Foundry importer - built on three findings: the species machinery (vesh, cadence) is fully implemented and completely unused, the published measured lethality tables cannot be reproduced by anything in the repo, and RINGBRP.figures already holds the per-species geometry procedural portraits would need. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c6924d6ea8 |
THROUGH TRAIN: art prompt sheet, and a runner for it
Prompts for all 43 assets - 16 duty-roster portraits, 14 NPC portraits from TT_CAST, and the 13 scene plates, none of which had a recorded prompt, so none of them could be regenerated. Art direction is frontier newspaper engraving, and the present-day Bureau material is drawn in the same 1881 hand as Cordera with modern people composed as tintype portraits, so the two halves read as one document. Three rules are written into the sheet because they protect meaning rather than style: nothing modern is drawn on the 1881 side, the train is absence rather than a glowing spectre, and nobody is lit as a villain. tools/gen-art.mjs parses the sheet rather than keeping a second copy of the prompts, expands the style tokens and drives mj-gen. Dry run by default, because --run fires paid generations. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
973b4a53aa |
THROUGH TRAIN rewritten into five acts
Act One is now an induction at the Bureau, Act Two puts the players through the crossing and makes them find the train, Act Three is a town-side obstacle, Act Four is the boarding, Act Five is the four minutes. 4h00 in five acts, was 3h30 in three. The restructure earns one thing the old shape could not: THE CROSSING OPENS WHERE THE RECORD SAYS THE LINE IS, which is an empty bench of scrub on the wrong side of the wash. The agents arrive where the paperwork put the railway, not where the railway is, so the fraud is the ground under their feet and finding the train is real work. Registry's file has this wrong and Bewley believes the file. - Act Three: Rance Doyle and five unpaid miners take the agents for company detectives, and they are not wrong to. Resolves on what the players SAY - no roll makes it go away, no roll makes it a fight. Losing costs them the 1881 issue, not their lives. His brother Tom is aboard and dies at minute two of every pass, which is the wiring between the acts - new cast: Bewley, Prosser, Rance Doyle, Shard, Tom Doyle, Cordera man - new handouts: the company notice, and the six names in Ambrose's hand - 8 GM pages, 10 handouts, 15 actors, 13 plates MEASURED, 400 runs each: the Act Three standoff is 0.4/4 hurt from cover and 1.25/4 in the open, both ending early - but FOUGHT TO A FINISH it puts 1.75 of 4 down and wipes the party in 24% of runs. The early stop is what makes the act survivable, not the miners being weak. My first draft of that table was guessed and wrong in all three rows. FOUND AND FIXED: there is no Ride skill in this game and never has been. The boarding set-piece has asked for "[CUS: Ride, then Athletics]" since it was written, through a playtest, which is an instruction to roll a thing nobody has. Horses are now handled by a local and the agent rolls Athletics. NEW GUARD: check-scenarios resolves every [CUS: Skill] tag in every scenario against SKILL_CATALOGUE and fails the build on a skill that does not exist. Verified it fails on the real bug before wiring it in. Sixth guard. NOTE: the three new plates (Bureau, north bench, standoff) are placeholders in this commit - Midjourney is still rendering them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c05d488b9d |
Play THROUGH TRAIN end to end; fix three scenes the dice could not reach
Ran the whole case with five agents — briefing, kit swap, Mercy Draw, the
crossing, Cordera, the water tower, the four minutes, the locomotive, the
brakes, the register. It completed, and it exposed one serious defect and two
smaller ones. All three are the same shape: the scenario put dice in front of
things the fiction says should simply happen.
1. THE ENDING WAS UNREACHABLE. Convincing Kell to stop was gated on Persuade
or Status. Only THREE of the ten duty-roster agents have either trained —
the Field Lead has Persuade 15 and Status 15. Three separate attempts on
him all failed and the scenario had no way to end; I narrated it as working
because otherwise there was no ending, which is exactly the improvisation a
scenario is supposed to prevent.
It now takes NO ROLL if the party can tell Kell one true thing about his own
train — the coal, the four minutes, the north bench. He has waited a
hundred and forty-five years for somebody who knows what is wrong to say
so. Only a party that knows nothing rolls, at average, and a failure costs
a pass rather than the ending.
2. THE PAPERS NEEDED PERSUADE. Showing one side the other's document is the
move the scenario is proudest of, and it sat behind Persuade at −30%:
15% became 1%. Both men WANT their paper read — Merritt is proud of his
letter, Ambrose's whole grievance is that nobody has looked at his writ.
No roll, between passes.
3. THE BOARDING SORTED ITSELF BADLY. Athletics runs 25–60% across the roster.
Putting all five on the water tower left the doctor and the Registry officer
missing twice each, carried across on the department's plank, passengers in
their own set-piece, two passes gone. The text now names which route suits
whom before they choose.
What worked, and is worth recording: the automatic clues absorbed two failed
rolls in Act One without the trail stalling; Standing Order 9 caught Okonkwo
checking a wristwatch in an 1881 street and cost a Coherence and a clock tick;
the fumble-is-a-fall rule fired on a 100 at the tower for five damage; the
exposure table held — one hit across the whole fight, on the agent who left
cover to work on Doyle; and the reset landed exactly as intended, with Doyle
standing up at the top of the car and Nkemdirim's hit staying where it was.
Version 1.4.1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
5bc46879c7 |
THROUGH TRAIN: put the gunfight inside the loop
The loop is no longer just a train going round. It is FOUR MINUTES with a
gunfight in it, and those four minutes have run about two million times.
Two sides, and neither is the villain. Cass Merritt and three hired men have a
signed letter of engagement from the company telling them to surrender the
payroll to nobody "upon any pretext whatsoever, including the presentation of
any paper". Josiah Ambrose and four Cordera miners have a sealed writ of
attachment from a territorial judge naming that same payroll against eleven
weeks of unpaid wages. Both documents are genuine. Neither man has seen the
other's. The company sold the same money twice and is not aboard. Both are
handouts now, and they only mean anything held in the same hand.
The mission is restated everywhere it appears — briefing page, case brief, GM
essentials: CLOSE IT. Closing the crossing does not kill anybody, it lets them
go. The loop ends, 3 November 1881 resumes from 11:44, and everyone aboard walks
forward into the life they would have had — including Ambrose and a miner named
Doyle, who did not survive the real four minutes. The agents are not choosing
who lives; they are choosing to stop holding history still, having met the
people it lands on.
The standing order is louder in three places: NOTHING MODERN GOES THROUGH.
Two things the playtest found, both now written into the text:
- THE FIGHT WAS A TPK GENERATOR. Modelled with all nine shooters firing at the
party it wiped them 171 times in 200. The model was wrong — the two sides
are shooting at EACH OTHER — so the scenario now carries a measured exposure
table: head down draws nothing, acting from cover costs half a party member
and no wipes over 300 runs, moving in the open costs one, and going for the
payroll box wipes more than half of all parties. The GM is told to say that
last row out loud BEFORE anybody commits to it.
- THE LOOP RESETS AND THE AGENTS DO NOT. Everyone who belongs to 1881 is back
up unhurt on the next pass. The agents keep their wounds. Nothing said so,
and a player who assumes otherwise takes risks that kill them. It is now
stated in capitals in both documents, with the played pass that prompted it
— two of four down at 0 hit points, one untouched because he stayed on the
floor.
Nine cast members, eight handouts, ten plates.
Version 1.4.0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
774e95dea8 |
THROUGH TRAIN — the crossing starter, and two more playtest fixes
A train has been running the same four miles of track since 3 November 1881. It
has never stopped. Sixty-one people are aboard and all of them are alive.
The supernatural is science fiction underneath, which is the point. A railway
company laid track to a filed survey instead of to the ground, then described the
line as being where it was not — ten thousand times, in timetables and waybills
and telegraph orders, for six months, at a constant speed. Reality keeps a record
of what belongs where, and that is the most patient argument there is. The record
gave way with No. 9 inside it, and the RUNNING is what holds the crossing open: a
standing wave sustained by its own motion the way a bow sustains a note.
So the players must board a train that cannot stop, and then find that sixty-one
people at six passes is four hours they do not have. The ending is what they
choose to do about arithmetic they cannot beat, in front of a conductor holding
the manifest. No roll resolves it.
It is also the case that teaches Standing Order 9: NOTHING MODERN GOES THROUGH.
Using a modern object across costs a Coherence and moves the clock; carrying it
costs nothing; anchors are exempt. The catalogue already had the 1881 issue —
Webley, Martini-Henry, oil lantern, brass compass, pocket watch, buff coat,
laudanum — so the constraint needed no new content and gives the table something
to feel in the first twenty minutes.
Ships as docs/scenarios/THROUGH_TRAIN.md and a Foundry Adventure: 7 GM pages, 6
handouts including the survey that started it and a manifest deliberately held
back to Act Three, the case file at Containment 6 / Resources 5 / Clearance 4
with its four legs loaded, four of the people aboard, and 7 plates to show.
Two fixes from playing it:
- Bhattacharya's RESEARCH was 1%. Placing the new skills last night I swapped
Occult into Registry's core and took Research out — a records office that
cannot look anything up. Research is back in core; Antiquities gets its
Knowledge back the same way.
- The boarding was unrunnable. At halved skill the set-piece put four agents on
12–31% and all four missed, which stalls the one scene the scenario is built
around. It is an average roll now and only a fumble is a fall, with the
reason written into the text so nobody "fixes" it back. Re-run: 3 of 4 aboard
on the first pass and one waiting for the next, which is the shape it wanted.
Version 1.3.0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
ab619f4b73 |
Remove the dice textures and the whole Dice So Nice path
Deleted: the seven PNGs in dice/, tools/make-dice-textures.mjs, the `npm run dice` script, the RB_DICE colourset and texture tables, diceSetFor, the diceSoNiceReady hook, and rbDressDice — which was tagging ten roll sites with coloursets that no longer existed. 99 lines of module, plus the assets. README and DEPLOY updated; they still advertised all of it. Recoverable with `git revert` if it is ever wanted back. This also explains the 01-that-was-12. The RESULT was never wrong: skillRoll rolls one 1d100 and grades on roll.total, and the chat card derives the tens and units it prints from that same total. Checked all 100 values of percentileFaces and 60 live rolls — the printed faces reconstruct the graded number every time, with no mismatches. What disagreed was the ANIMATION. The custom addDicePreset labels registered for d100 and d10 remapped which physical face means what, so Dice So Nice could land showing 01 while the roll behind it was 12. Nothing downstream ever read the animated faces, so no roll was ever adjudicated on the wrong number — but a table watching the dice had every reason to believe otherwise, which is its own kind of wrong. Disabling the skins in 1.0.6 already removed it; deleting them makes it permanent. Verified in a running Foundry after removal: skill roll, weapon damage, hit location, major wound and Coherence all resolve and post their cards, no errors, and game.ringbrp.diceSetFor is gone from the API. Version 1.0.7. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
53481bdfc1 |
Ship the LAST ADMISSION plates as showable images
A third journal in the adventure — LAST ADMISSION — Show the players — holding the seven scene plates and the floor plan as eight image pages at player visibility. Right-click, Show Players, done. title.show is false and there is no caption, on purpose: the table gets the picture and nothing else. No heading telling them which room this is, no label naming the thing on the stairs. The page NAMES exist only for the GM's sidebar so the right one can be found in a hurry under pressure, and the players never see them. Ordered by when each comes up, not by asset number, for the same reason. The builder throws if a plate is missing from disk, because a missing image is a blank frame on a projector in front of six people. Verified in Foundry: eight pages import at OBSERVER, the image loads, and the rendered page contains no headings, no figcaption and no text at all. Version 1.0.3. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
51bd8e618a |
Audit every remaining sheet and dialog; add the Culland Hall scene
Opened all of it this time, rather than driving the system through its API.
Two more defects of the same family as the NPC sheet, and in the same place —
the types added last:
- Talent and Art had no TYPES.Item.* label, so their sheets printed the raw
key "TYPES.Item.talent" under the name.
- Neither had a branch in item-sheet.hbs or an isTalent/isPower flag, so the
Detail tab rendered EMPTY over a document holding category, rule, uses per
case, Coherence cost, push cost and origin. Eleven of thirteen types were
handled, which is exactly the shape an eye skips.
Both now have a header statline and a full Detail section, and a guard walks
template.json: every declared type must have a label, a flag set in ringbrp.mjs,
and an {{#if isX}} section in the sheet.
One hardening fix: loseCoherence applies the cost and THEN announces it, so
anything that throws in between leaves the actor quietly poorer with no message.
localize() throws on a non-string, which an unrecognised reason key is.
Everything else came back clean, and it is worth recording what was checked so
the next audit knows what "checked" meant: 13 item types opened, all render; the
expedition sheet (4 tabs); all 7 chat cards driven through their real entry
points — roll, coherence, reaction via Combat.rollAll, hit location, weapon
damage, major wound, and contact through a case file that actually has a group;
all 3 dialogs opened by clicking the controls a player clicks. No errors, no raw
localisation keys anywhere.
Also: Culland Hall as a playable Scene. Drawn as SVG rather than generated,
because a room count, a door position and a label are all load-bearing here and
a generator cannot be trusted with any of them — three label-collision passes in
the browser before it was clean, which is the documented cost of doing it this
way. 2800x2000 at 100px to the square so the Foundry grid lands on the grid
drawn into the image; 5ft squares; no walls, because half-done walls are worse
than none and a GM who wants vision can add them in ten minutes.
Verified in Foundry: the scene imports, activates, and draws.
Version 1.0.2.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
1bf8d7f6fb |
Playtest LAST ADMISSION: five fixes, one new guard
Played it through in Foundry with the six on their civilian sheets. Five
defects, all of the house's favourite kind — a number written down that nothing
reads.
1. Pollard and Agyeman were armed and armoured as CIVILIANS. The police trade
kit carries a revolver and a stab vest, which is right for a serving
officer and wrong for a British civilian, and it ended the scenario's only
fight in a single round. expandFromRegister's civilian mode now strips
firearms and body armour from trade kit as well as induction and standing
issue, and the build throws if one gets through. Wren Finch keeps her
knife — a knife is not an issued weapon.
2. Old Marrow's shears were a utility knife. The page said 1d8+1; the actor
in the pack held 1d4+2, so a GM running off the token had a different
fight from the one written down. He now carries a billhook — an actual
garden tool that is already in the catalogue — and the page says 1d8+2,
which is what a billhook does.
3. He was too soft to be the fight the scenario promises. At the original
numbers he died in an average of 2.4 rounds and in 6 runs of 20 he was
dead before he ever swung. Retuned over thirty runs to HP 20, armour 2:
about four and a half rounds, somebody hurt in 28 of 30, somebody dropped
in 9 of 30. The verification run took four rounds and left Pollard on
eight hit points.
4. Two stat lines disagreed with the generated sheets — Marrow 16 against 15,
Enderby 13 against 12.
5. Two rolls had no failure written: the body, and Sammy's ankle pull. The
body is now marked "no roll" outright, because there is no better answer
to buy. The pull has a fumble result.
New guard: check-behaviour parses the scenario's own fight line out of the page
HTML and compares it to the actor the build will generate — hit points against
hitPoints(CON,SIZ), armour against naturalArmour, and shear damage against the
catalogue entry for whatever he is actually holding. Verified it bites by
reverting the damage to 1d8+1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
d063b3c016 |
Add LAST ADMISSION, a two-hour haunted-house prologue
OPEN DAY was too complex for a first night: a fixed timetable the GM narrates minute by minute, three things that must be left unresolved, ten serial approach scenes, and no combat. This is the replacement opener — same premise engine, a third of the moving parts, and something to hit. A cheap scare attraction on the last night of its six-week run, in a real empty hall, with paying public still inside. Three of the ghosts on the poster were invented in an afternoon by a marketing agency, printed on the tickets and the wall panel and the call sheets, and performed forty times a night to twelve thousand people who agreed to believe them for eighteen pounds each. They are in the building now. They are not ghosts, they are entries, and they have exactly as much inside them as was written down — a page each, which they do, and nothing else. That makes them simple to run and simple to stop: hurt them, or break the script. Both work; the script is faster and cheaper, and a table that finds it should feel clever. The fourth name on the panel was copied off a memorial in the parish church because the layout needed four. Edith Crane was real, died in a real fire here in 1963, and nobody wrote her a page because nobody had to. She never attacks, cannot be hurt, and will not speak until she is asked her name. She wants her name off a poster. The night ends on whether it comes down tonight or on Monday — and Monday is two performances away. Written for the second intake specifically, on their civilian sheets, with each one's job as their way in: Renshaw is IN the show and knows the running order, Ferriby wired it, Sharrock built the sets, Pollard is on the door, Braithwaite and Ashcroft paid to get in. Each shortcuts a different part of the middle and none of them is required. Art: eight plates commissioned, seven kept. The wall panel plate was cut after two attempts both produced three frames instead of four — a picture that contradicts a count the scenario turns on is worse than no picture, so the panel is a handout the GM shows rather than describes. The freed green-room plate went onto the Act One page, where the call sheet is. OPEN DAY stays in the repo as the longer, quieter alternative; both scenarios say plainly which is which and that nothing depends on the choice. Verified in Foundry: the adventure imports, six cast, seven GM pages, five handouts, plates load. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
f185c92088 |
Add OPEN DAY, the recruitment prologue
Ten civilians, one decommissioned telephone exchange, and eleven minutes during
which the building went back to being on the street it was built on. Nothing
attacks anybody. Nothing wants anything. That is the horror, and it is the whole
design.
The premise was already in the pregens. Wren Finch's biography said she was
inside a building "on the night it stopped being on the street it was on", and
Soraya Rahimi's said she talked a caller down on air "for eleven minutes, and
the recording does not play back the same way twice". Those are two views of one
afternoon, so the scenario is built at the intersection and the other eight
"How they found her/him" lines are the same afternoon from eight more jobs.
Nothing in the prologue contradicts a sheet, because the sheets came first.
The reconciliation pass, which is most of the work:
- Finch's line said "night". The open day is an afternoon. One word changed on
the pregen, and both are true. Her line also says she was the only witness
who could describe the inside, so she is the one who goes into number 11 —
written into the location note rather than left to chance.
- Rahimi's line says she was ON AIR. So the disconnected telephone that rings
at 15:45 is patched through to her outside broadcast, which makes the canon
line and the scene the same event instead of two coincidences.
- Okonkwo carries two men out; Nkemdirim's patient has a forearm that healed
crooked over a break he took six minutes ago. Both seams needed an injury in
Act Two and there was none, so 15:50 and 15:51 now have one.
- Sandoval's forty minutes of traffic sit inside an eleven-minute window. That
is the anomaly, so it is on the handout in those words.
- "Prine" collided with an NPC already in the world. The engineer is Kearsley.
Structure: 2h15 against the house 3h30, stated in the design intent, because a
prologue exists to make the first real case land. No combat, no antagonist, no
Coherence — the last one is thematic, not a simplification: Coherence is what it
costs to keep looking once you know what you are looking at, and these ten do
not know yet. The Briefing is the first time the word is said aloud.
Ships as docs/scenarios/OPEN_DAY.md (the full GM document) and a Foundry
Adventure in a new `prologue` pack: 8 GM pages, 7 handouts, 5 NPCs, and ten
generated plates. The PCs are the "(before)" pregens already in the Pregens
pack — a second copy here would give a GM two sets of the same ten people and
no way to know which one their notes were on.
Verified in Foundry: the adventure imports, both journals render branded, the
countdown table reads as a table, and all ten plates load.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
7f8355f0d0 |
Add the player primer and cheat sheet, and brand every journal
Ten pages a player reads before session one, in their own compendium at OBSERVER ownership: nine of setting, one cheat sheet. The draft called the organisation "the Bureau"; everything else in the game calls it the department or the agency, so that is what it is called. Thin areas filled rather than padded: the seven character principles as a list, the real Coherence band table instead of a paragraph describing one, and "what continuity is not" pulled out of the middle of a page because it is the most important sentence for a new player. The cheat sheet's numbers are computed from rules.mjs and lang/en.json at build time. A hand-typed one would have been the sixth time this project shipped a number that disagreed with the code, and the one the players were holding. R-250: the design tokens were never on :root. Journals rendered as default parchment, and four things were wrong in sequence — v14's hook is renderJournalEntrySheet; its `element` is the node, so `[0]` returns the first CHILD and put the class on a header button; there is no .journal-page-content in v14; and then the real one: with the selector matching, font-size, line-height and padding all applied while every colour did not, because the palette is declared on .ringbrp-sheet/.ringbrp-chat/.ringbrp-window and never on :root. A journal inherited no tokens, so every var() silently became nothing. A rule that HALF applies is not a specificity problem — I spent three attempts treating it as one, including a version bump on a cache theory that was wrong. Branded: primer, rulebook, starter GM text and handouts. Scoped by flag, so other modules' journals are untouched. Version 0.9.0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
d9bce12c27 |
Replace the starter with BLACK PLATFORM, and make the dialogs ask questions
The starter is now an action case: a train running through a station whose rails were lifted in 1976, two engineers aboard, eleven minutes until it returns. Descend, take the platform, board, rescue, fight forward along a moving train, stop it. Simpler than PAPER WINDOW on purpose — one clue scene, no social subsystem — which also means it cannot reproduce R-248, because there are no groups or standings to leave unwired. Every agent can fight, deliberately: floors of firearm 42%, melee 40%, Brawl 40%, Dodge 40% so nobody is a spectator on their first evening. Floors only RAISE, so a posting already better stays better — Callum's shield lands at 53, not the floor's 45. The builder now handles combat floors, extra weapons issued for a case, and a scenario with NO Borrowed Authority at all; the last was assumed to exist and would have thrown. Two new tests: every floor names a real skill, and every agent clears the fighting floors the handout promises. Sixty-two dialog strings reworded. They were naming mechanics at people: "Situational modifier %" is now "Anything else helping or hurting? (%)", "Target cover" is "Is the target behind anything?", "Difficult (÷2)" is "Difficult — half your skill". Labels ask the question; hints say what it does to the number; notifications say what to do next rather than what went wrong. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |