detention-tables: measure STANDING ORDER's Act Two fight, and hold it

A second scenario gets pack-tables' arrangement: four configs (Teague plus
one, three or five wardens) against the declared six and the four-player
cut, 2000 runs at seed 11, cap 400, recorded to detention-baseline.json,
citeable as "detention", and --check added to npm run check.

standingorder joins all-specs' SCENARIOS, and simulate.mjs now reads that
list instead of keeping its own copy, so a new cast is fightable the day it
is registered. The lethality, focus and pack baselines are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
slaguru666
2026-09-16 11:15:38 +01:00
co-authored by Claude Opus 5
parent 0fa21263b4
commit e80f7bb564
6 changed files with 238 additions and 3 deletions
+4 -1
View File
@@ -55,6 +55,7 @@ import {
} from "../rules.mjs";
import { combatPowerFor } from "./powers.mjs";
import { WEAPONS, ARMOURS, NPCS, PREGENS } from "./content.mjs";
import { SCENARIOS } from "./all-specs.mjs";
import { ROSTER } from "./roster.mjs";
import { expandFromRegister } from "./expand-spec.mjs";
import { pathToFileURL } from "node:url";
@@ -513,7 +514,9 @@ export function measure(partySpecs, enemySpecs, { runs = 400, seed = 1 } = {}) {
const ALL_SPECS = new Map();
for (const s of [...NPCS, ...PREGENS, ...ROSTER]) ALL_SPECS.set(s.key, s);
for (const name of ["throughtrain", "starter", "lastadmission", "openday"]) {
/* The scenario list is all-specs.mjs's, so a new scenario's cast is fightable here the day
it is registered there, rather than the day somebody finds this second copy. */
for (const name of SCENARIOS) {
const mod = await import(`./scenario-${name}.mjs`);
for (const v of Object.values(mod)) {
if (Array.isArray(v)) for (const s of v) if (s?.ch && s.key) ALL_SPECS.set(s.key, s);