Files
RingBRP/tools/all-specs.mjs
T
slaguru666andClaude Opus 5 e80f7bb564 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>
2026-09-16 11:15:38 +01:00

58 lines
2.3 KiB
JavaScript

/**
* Every actor spec in the repository, collected once.
*
* Three things now need the same list — check-creatures validates it, make-portraits
* draws it, and mj-queue writes prompts for it — and this repository's one standing law
* is that a definition may not exist twice. The collection rule is a definition: a
* scenario cast is any exported array whose entries carry characteristics, so a new
* scenario is covered the day it is written rather than the day somebody remembers to
* add it to a list. That rule belongs in one place.
*
* `kind` is what buildActor will make of the spec: "agent" becomes a character actor,
* "npc" becomes an npc actor. It decides which portrait family a creature is drawn in
* and which prompt template it gets, so it is carried here rather than re-derived.
*/
import { NPCS, PREGENS } from "./content.mjs";
import { ROSTER } from "./roster.mjs";
/** Scenario modules whose casts join the list. */
export const SCENARIOS = ["throughtrain", "starter", "lastadmission", "openday", "standingorder"];
/**
* @returns {Promise<Array<{label: string, kind: "agent"|"npc", spec: object}>>}
* every spec, in a stable order, each tagged with where it came from.
*/
export async function collectSpecs() {
const sources = [
{ label: "content.mjs PREGENS", kind: "agent", specs: PREGENS },
{ label: "content.mjs NPCS", kind: "npc", specs: NPCS },
{ label: "roster.mjs ROSTER", kind: "agent", specs: ROSTER }
];
for (const s of SCENARIOS) {
const mod = await import(`./scenario-${s}.mjs`);
for (const [name, value] of Object.entries(mod)) {
if (Array.isArray(value) && value.some(x => x && typeof x === "object" && x.ch)) {
sources.push({ label: `scenario-${s}.mjs ${name}`, kind: "npc", specs: value });
}
}
}
const out = [];
for (const { label, kind, specs } of sources) {
for (const spec of specs) out.push({ label, kind, spec });
}
return out;
}
/** The same thing grouped, for callers that report per source. */
export async function collectSources() {
const flat = await collectSpecs();
const byLabel = new Map();
for (const row of flat) {
if (!byLabel.has(row.label)) byLabel.set(row.label, { label: row.label, kind: row.kind, specs: [] });
byLabel.get(row.label).specs.push(row.spec);
}
return [...byLabel.values()];
}