R-295: derive the counterfactual too, and name it hadHeRefused

Matching the step-5 prose against the derived source before placing markers left
five figures unmatched: 21.9, 74.3 and 3.8, twice each. They are the thing against
Ashcroft's undiminished 85 -- the contest that never happens, which Act Four prints
on purpose to price what THE OFFER sold.

Derived now as hadHeRefused, so the counterfactual is held to the rule like
everything else and carries a name that cannot be mistaken for an event. Quoting
those three as odds a GM meets is what went wrong in two sentences and a table.

Markers not placed: CLEAN_GROUND.md is c0's and they are in it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
slaguru666
2026-09-13 16:32:46 +01:00
co-authored by Claude Opus 5
parent a5c4378521
commit c2f7249d4d
2 changed files with 35 additions and 8 deletions
+16 -8
View File
@@ -115,12 +115,20 @@ export function step5Split() {
const insight = (expandFromRegister(spec).skills ?? [])
.find(s => s.fam === "insight")?.val ?? 0;
/* THE CONTEST THAT NEVER HAPPENS, derived on purpose. If Ashcroft refuses, the countdown
does not reach for him at all — it reaches for the lowest POW in the room — so the thing
never faces his undiminished 85. Act Four nevertheless prints that pair, correctly and
with a warning: it is what THE OFFER sold, and without it the reader cannot see the size
of the trade. It is citable here so the document's counterfactual is held to the rule
like everything else, and named `hadHeRefused` so nobody mistakes it for an event. It is
what quoting these numbers as odds a GM meets did to two sentences and a table. */
const rows = {
refused: { ...six, target: six.rating, who: six.who },
cut: { ...four, target: four.rating, who: four.who },
accepted: { ...accepted, target: accepted.rating, who: accepted.who }
refused: { ...six, target: six.rating, who: six.who },
cut: { ...four, target: four.rating, who: four.who },
accepted: { ...accepted, target: accepted.rating, who: accepted.who },
hadHeRefused: { who: ash.who, target: ash.rating }
};
for (const k of ["refused", "cut", "accepted"]) {
for (const k of ["refused", "cut", "accepted", "hadHeRefused"]) {
Object.assign(rows[k], split(THING_RATING, rows[k].target));
}
@@ -138,13 +146,13 @@ if (import.meta.main || process.argv[1]?.endsWith("step5-split.mjs")) {
const s = step5Split();
console.log(`\n The thing reaches at ${s.thing}. Ashcroft refuses on Insight, so `
+ `${s.refusedShare}% of tables are in the first row and ${s.acceptedShare}% the second.\n`);
console.log(" case resists taken held unsettled");
for (const k of ["refused", "cut", "accepted"]) {
console.log(" case resists taken held unsettled");
for (const k of ["refused", "cut", "accepted", "hadHeRefused"]) {
const r = s[k];
console.log(` ${k.padEnd(9)} ${(r.who + " " + r.target).padEnd(18)} `
console.log(` ${k.padEnd(13)} ${(r.who + " " + r.target).padEnd(18)} `
+ `${String(r.taken).padStart(5)} ${String(r.held).padStart(6)} ${String(r.unsettled).padStart(9)}`);
}
const b = s.blended;
console.log(` ${"blended".padEnd(9)} ${"across all games".padEnd(18)} `
console.log(` ${"blended".padEnd(13)} ${"across all games".padEnd(18)} `
+ `${String(b.taken).padStart(5)} ${String(b.held).padStart(6)} ${String(b.unsettled).padStart(9)}\n`);
}