@alpaca-software/40kdc-data 0.4.15 → 0.4.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/author-batch.d.ts.map +1 -1
- package/dist/author-batch.js +3 -2
- package/dist/author-batch.js.map +1 -1
- package/dist/commands/translate.d.ts +3 -2
- package/dist/commands/translate.d.ts.map +1 -1
- package/dist/commands/translate.js +6 -154
- package/dist/commands/translate.js.map +1 -1
- package/dist/data/bundle.generated.js +1 -1
- package/dist/data/bundle.generated.js.map +1 -1
- package/dist/data/entities.d.ts +7 -0
- package/dist/data/entities.d.ts.map +1 -1
- package/dist/data/entities.js +10 -0
- package/dist/data/entities.js.map +1 -1
- package/dist/gen-conformance.js +57 -1
- package/dist/gen-conformance.js.map +1 -1
- package/dist/generated.d.ts +1 -1
- package/dist/generated.d.ts.map +1 -1
- package/dist/generated.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +16 -1
- package/dist/runner.js.map +1 -1
- package/dist/terrain/index.d.ts +2 -2
- package/dist/terrain/index.d.ts.map +1 -1
- package/dist/terrain/index.js +1 -1
- package/dist/terrain/index.js.map +1 -1
- package/dist/terrain/solve.d.ts +71 -0
- package/dist/terrain/solve.d.ts.map +1 -1
- package/dist/terrain/solve.js +165 -0
- package/dist/terrain/solve.js.map +1 -1
- package/dist/translate/condition.d.ts.map +1 -1
- package/dist/translate/condition.js +11 -0
- package/dist/translate/condition.js.map +1 -1
- package/dist/translate/effect.d.ts +72 -0
- package/dist/translate/effect.d.ts.map +1 -0
- package/dist/translate/effect.js +241 -0
- package/dist/translate/effect.js.map +1 -0
- package/dist/translate/index.d.ts +7 -4
- package/dist/translate/index.d.ts.map +1 -1
- package/dist/translate/index.js +7 -4
- package/dist/translate/index.js.map +1 -1
- package/package.json +2 -2
- package/schemas/enrichment/ability-dsl/condition.schema.json +2 -2
package/dist/data/entities.d.ts
CHANGED
|
@@ -53,6 +53,13 @@ export declare class AbilityView {
|
|
|
53
53
|
/** The ability's id (`ability_id` in the raw record). */
|
|
54
54
|
get id(): string;
|
|
55
55
|
get name(): string;
|
|
56
|
+
/**
|
|
57
|
+
* Generated plain-English approximation of this ability's effect + scope,
|
|
58
|
+
* rendered from the DSL by the conformance-pinned describer
|
|
59
|
+
* (`translate/effect.ts`). The dataset carries no rules prose; this is the
|
|
60
|
+
* displayable stand-in.
|
|
61
|
+
*/
|
|
62
|
+
describe(): string;
|
|
56
63
|
/** Game phases this ability acts in, unioned across its phase-mappings. */
|
|
57
64
|
get phases(): Phase[];
|
|
58
65
|
/** Units that list this ability in their `ability_ids`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../src/data/entities.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EACV,eAAe,EACf,OAAO,EACP,KAAK,EACL,IAAI,EACJ,aAAa,EACb,MAAM,EACN,aAAa,EACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE5E,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC5B,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../src/data/entities.ts"],"names":[],"mappings":"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"}
|
package/dist/data/entities.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { buffsFromKeyword } from "../cruncher/from-keyword.js";
|
|
2
2
|
import { effectToBuffs, } from "../cruncher/from-dsl.js";
|
|
3
|
+
import { describeAbility } from "../translate/effect.js";
|
|
3
4
|
/** A unit, linked to its faction, weapons, and abilities. */
|
|
4
5
|
export class UnitView {
|
|
5
6
|
raw;
|
|
@@ -70,6 +71,15 @@ export class AbilityView {
|
|
|
70
71
|
get name() {
|
|
71
72
|
return this.raw.name;
|
|
72
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Generated plain-English approximation of this ability's effect + scope,
|
|
76
|
+
* rendered from the DSL by the conformance-pinned describer
|
|
77
|
+
* (`translate/effect.ts`). The dataset carries no rules prose; this is the
|
|
78
|
+
* displayable stand-in.
|
|
79
|
+
*/
|
|
80
|
+
describe() {
|
|
81
|
+
return describeAbility(this.raw);
|
|
82
|
+
}
|
|
73
83
|
/** Game phases this ability acts in, unioned across its phase-mappings. */
|
|
74
84
|
get phases() {
|
|
75
85
|
return this.ds.phasesFor("ability", this.raw.ability_id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entities.js","sourceRoot":"","sources":["../../src/data/entities.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EACL,aAAa,GAGd,MAAM,yBAAyB,CAAC;AAGjC,6DAA6D;AAC7D,MAAM,OAAO,QAAQ;IAGR;IACQ;IAHnB;IACE,wCAAwC;IAC/B,GAAS,EACD,EAAW;QADnB,QAAG,GAAH,GAAG,CAAM;QACD,OAAE,GAAF,EAAE,CAAS;IAC3B,CAAC;IAEJ,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,yEAAyE;IACzE,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACnD,CAAC;IAED,sEAAsE;IACtE,IAAI,OAAO;QACT,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,yEAAyE;IACzE,IAAI,SAAS;QACX,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,+EAA+E;IAC/E,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,CAAC,GAAG,CAAC;QACb,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,UAAU,CAClB,YAAY,IAAI,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,WAAW,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,qBAAqB,CAChG,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,WAAW;IAGX;IACQ;IAHnB;IACE,yCAAyC;IAChC,GAAoB,EACZ,EAAW;QADnB,QAAG,GAAH,GAAG,CAAiB;QACZ,OAAE,GAAF,EAAE,CAAS;IAC3B,CAAC;IAEJ,yDAAyD;IACzD,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;IAC7B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,2EAA2E;IAC3E,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC3D,CAAC;IAED,2DAA2D;IAC3D,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACvD,CAAC;IAED;;;;;;;;OAQG;IACH,QAAQ,CACN,MAAkB,EAClB,OAAuB,EACvB,cAAsC,UAAU;QAEhD,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,OAAO,CAAC;IAClE,CAAC;IAED;;;;OAIG;IACH,aAAa,CACX,MAAkB,EAClB,OAAuB,EACvB,cAAsC,UAAU;QAEhD,MAAM,GAAG,GAAkB,OAAO,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAC5D,OAAO,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;IAClE,CAAC;CACF;AAED,mDAAmD;AACnD,MAAM,OAAO,UAAU;IAGV;IACQ;IAHnB;IACE,0CAA0C;IACjC,GAAW,EACH,EAAW;QADnB,QAAG,GAAH,GAAG,CAAQ;QACH,OAAE,GAAF,EAAE,CAAS;IAC3B,CAAC;IAEJ,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,yDAAyD;IACzD,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,iDAAiD;IACjD,SAAS,CAAC,CAAC,GAAG,CAAC;QACb,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,UAAU,CAClB,cAAc,IAAI,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,WAAW,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,qBAAqB,CAClG,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;OAGG;IACH,UAAU,CACR,CAAC,GAAG,CAAC;QAEL,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;QACpC,MAAM,GAAG,GAAsF,EAAE,CAAC;QAClG,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACxD,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,GAAG,CAAC,IAAI,CAAC;gBACP,OAAO,EAAE,IAAI;gBACb,UAAU,EAAE,GAAG,CAAC,UAAiD;aAClE,CAAC,CAAC;QACL,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,CAAqB,EAAE,OAAsB;QACxD,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,GAAG,GAAW,EAAE,CAAC;QACvB,KAAK,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7D,GAAG,CAAC,IAAI,CACN,GAAG,gBAAgB,CAAC;gBAClB,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE;gBACrB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM;gBAC1B,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnD,OAAO;aACR,CAAC,CACH,CAAC;QACJ,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IAGjB;IACQ;IAHnB;IACE,iDAAiD;IACxC,GAAkB,EACV,EAAW;QADnB,QAAG,GAAH,GAAG,CAAe;QACV,OAAE,GAAF,EAAE,CAAS;IAC3B,CAAC;IAEJ,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,wDAAwD;IACxD,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CACN,UAA+C,EAC/C,QAAgB,EAChB,OAAsB;QAEtB,OAAO,gBAAgB,CAAC;YACtB,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE;YACtB,QAAQ;YACR,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM;YACvB,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,OAAO;SACR,CAAC,CAAC;IACL,CAAC;CACF;AAED,mEAAmE;AACnE,MAAM,OAAO,WAAW;IAGX;IACQ;IAHnB;IACE,2CAA2C;IAClC,GAAY,EACJ,EAAW;QADnB,QAAG,GAAH,GAAG,CAAS;QACJ,OAAE,GAAF,EAAE,CAAS;IAC3B,CAAC;IAEJ,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,8EAA8E;IAC9E,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,+EAA+E;IAC/E,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,wDAAwD;IACxD,IAAI,OAAO;QACT,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,GAAG,GAAiB,EAAE,CAAC;QAC7B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBAAE,SAAS;gBAClC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACpB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED,8DAA8D;AAC9D,SAAS,UAAU,CAAI,GAAyB,EAAE,GAAkC;IAClF,MAAM,GAAG,GAAQ,EAAE,CAAC;IACpB,KAAK,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,SAAS;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["/**\n * Linked views over the richly-connected entity types. Each wraps a raw\n * generated record and resolves its relationships lazily against the owning\n * {@link Dataset}; the full underlying record is always available via `.raw`.\n *\n * @packageDocumentation\n */\nimport type {\n AbilityDSLEntry,\n Faction,\n Phase,\n Unit,\n WargearOption,\n Weapon,\n WeaponKeyword,\n} from \"../generated.js\";\nimport type { Buff, BuffSource, EngineContext } from \"../cruncher/buffs.js\";\nimport { buffsFromKeyword } from \"../cruncher/from-keyword.js\";\nimport {\n effectToBuffs,\n type EffectTranslation,\n type TranslationPerspective,\n} from \"../cruncher/from-dsl.js\";\nimport type { Dataset } from \"./dataset.js\";\n\n/** A unit, linked to its faction, weapons, and abilities. */\nexport class UnitView {\n constructor(\n /** The full generated `Unit` record. */\n readonly raw: Unit,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** The unit's faction, or `undefined` if its `faction_id` is unknown. */\n get faction(): FactionView | undefined {\n return this.ds.factions.get(this.raw.faction_id);\n }\n\n /** Weapons referenced by `weapon_ids`; unresolved ids are skipped. */\n get weapons(): WeaponView[] {\n return resolveAll(this.raw.weapon_ids, (id) => this.ds.weapons.get(id));\n }\n\n /** Abilities referenced by `ability_ids`; unresolved ids are skipped. */\n get abilities(): AbilityView[] {\n return resolveAll(this.raw.ability_ids, (id) => this.ds.abilities.get(id));\n }\n\n /** Wargear options (weapon swaps, add-ons, choices) authored for this unit. */\n get wargearOptions(): WargearOption[] {\n return this.ds.wargearOptionsOf(this.raw);\n }\n\n /**\n * The stat profile at index `i` (default 0). Returns the schema-generated\n * profile object directly so callers can feed it straight to the engine\n * without an intermediate wrapper.\n */\n profileAt(i = 0): Unit[\"profiles\"][number] {\n const profile = this.raw.profiles[i];\n if (profile === undefined) {\n throw new RangeError(\n `UnitView(${this.raw.id}).profileAt(${i}): only ${this.raw.profiles.length} profile(s) defined`,\n );\n }\n return profile;\n }\n}\n\n/**\n * An ability, linked to the phases it acts in and the units that have it.\n *\n * Phases are not stored on the ability — they live in `phase-mappings` records.\n *\n * @example\n * units.find(\"Kharn\")!.abilities\n * .filter(a => a.phases.includes(\"shooting\"));\n */\nexport class AbilityView {\n constructor(\n /** The full generated ability record. */\n readonly raw: AbilityDSLEntry,\n private readonly ds: Dataset,\n ) {}\n\n /** The ability's id (`ability_id` in the raw record). */\n get id(): string {\n return this.raw.ability_id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** Game phases this ability acts in, unioned across its phase-mappings. */\n get phases(): Phase[] {\n return this.ds.phasesFor(\"ability\", this.raw.ability_id);\n }\n\n /** Units that list this ability in their `ability_ids`. */\n get units(): UnitView[] {\n return this.ds.unitsWithAbility(this.raw.ability_id);\n }\n\n /**\n * Buff stack this ability contributes against `context`, with provenance\n * tagged via `source` (the caller knows whether this ability is being read\n * as army, detachment, unit, leader, etc.). DSL branches the buff layer\n * can't auto-apply are dropped here; call {@link describeBuffs} if you\n * also want the diagnostics. `perspective` defaults to `\"attacker\"`; pass\n * `\"target\"` to translate the ability as a defensive buff (FNP, T/Sv\n * stat-mods, save rerolls, incoming hit penalties).\n */\n getBuffs(\n source: BuffSource,\n context?: EngineContext,\n perspective: TranslationPerspective = \"attacker\",\n ): Buff[] {\n return this.describeBuffs(source, context, perspective).applied;\n }\n\n /**\n * Full DSL→Buff translation, including the `unsupported` list of effect\n * fragments the buff layer can't model. The SPA renders these as warnings\n * so users see which abilities have effects that need a manual toggle.\n */\n describeBuffs(\n source: BuffSource,\n context?: EngineContext,\n perspective: TranslationPerspective = \"attacker\",\n ): EffectTranslation {\n const ctx: EngineContext = context ?? { phase: \"shooting\" };\n return effectToBuffs(this.raw.effect, source, ctx, perspective);\n }\n}\n\n/** A weapon, linked to the units that carry it. */\nexport class WeaponView {\n constructor(\n /** The full generated `Weapon` record. */\n readonly raw: Weapon,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** Units that list this weapon in their `weapon_ids`. */\n get units(): UnitView[] {\n return this.ds.unitsWithWeapon(this.raw.id);\n }\n\n /** The stat profile at index `i` (default 0). */\n profileAt(i = 0): Weapon[\"profiles\"][number] {\n const profile = this.raw.profiles[i];\n if (profile === undefined) {\n throw new RangeError(\n `WeaponView(${this.raw.id}).profileAt(${i}): only ${this.raw.profiles.length} profile(s) defined`,\n );\n }\n return profile;\n }\n\n /**\n * Catalog views for each keyword referenced by profile `i`, paired with the\n * reference-site parameters. Unresolved keyword ids are skipped.\n */\n keywordsAt(\n i = 0,\n ): { keyword: WeaponKeywordView; parameters: Record<string, unknown> | undefined }[] {\n const profile = this.profileAt(i);\n const refs = profile.keywords ?? [];\n const out: { keyword: WeaponKeywordView; parameters: Record<string, unknown> | undefined }[] = [];\n for (const ref of refs) {\n const view = this.ds.weaponKeywords.get(ref.keyword_id);\n if (!view) continue;\n out.push({\n keyword: view,\n parameters: ref.parameters as Record<string, unknown> | undefined,\n });\n }\n return out;\n }\n\n /**\n * Buffs contributed by profile `i`'s intrinsic keywords against `context` —\n * the natural \"what does this profile bring on its own?\" call the engine\n * makes automatically before adding ability/manual buffs.\n */\n profileBuffs(i: number | undefined, context: EngineContext): Buff[] {\n const index = i ?? 0;\n const out: Buff[] = [];\n for (const { keyword, parameters } of this.keywordsAt(index)) {\n out.push(\n ...buffsFromKeyword({\n keywordId: keyword.id,\n weaponId: this.raw.id,\n effect: keyword.raw.effect,\n ...(parameters !== undefined ? { parameters } : {}),\n context,\n }),\n );\n }\n return out;\n }\n}\n\n/**\n * A weapon-keyword catalog entry, linked to the weapons whose profiles\n * reference it. Exposes the keyword's mechanical effect as a buff stack\n * via {@link getBuffs}.\n */\nexport class WeaponKeywordView {\n constructor(\n /** The full generated `WeaponKeyword` record. */\n readonly raw: WeaponKeyword,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** Weapons whose profiles reference this keyword id. */\n get weapons(): WeaponView[] {\n return this.ds.weaponsWithKeyword(this.raw.id);\n }\n\n /**\n * Buff contributions from this catalog entry, for one reference site:\n * pass the keyword's `parameters` (e.g. `{ value: 1 }` for Sustained Hits 1)\n * along with the `weaponId` that's carrying it (used as the buff source)\n * and the engine `context` (e.g. attacker stationary?).\n */\n getBuffs(\n parameters: Record<string, unknown> | undefined,\n weaponId: string,\n context: EngineContext,\n ): Buff[] {\n return buffsFromKeyword({\n keywordId: this.raw.id,\n weaponId,\n effect: this.raw.effect,\n ...(parameters !== undefined ? { parameters } : {}),\n context,\n });\n }\n}\n\n/** A faction, linked to its units and the records scoped to it. */\nexport class FactionView {\n constructor(\n /** The full generated `Faction` record. */\n readonly raw: Faction,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** Units whose `faction_id` is this faction (may be empty for successors). */\n get units(): UnitView[] {\n return this.ds.units.byFaction(this.raw.id);\n }\n\n /** Faction-scoped abilities (abilities whose `faction_id` is this faction). */\n get abilities(): AbilityView[] {\n return this.ds.abilities.byFaction(this.raw.id);\n }\n\n /** Distinct weapons carried by this faction's units. */\n get weapons(): WeaponView[] {\n const seen = new Set<string>();\n const out: WeaponView[] = [];\n for (const unit of this.units) {\n for (const weapon of unit.weapons) {\n if (seen.has(weapon.id)) continue;\n seen.add(weapon.id);\n out.push(weapon);\n }\n }\n return out;\n }\n}\n\n/** Resolve a list of ids, dropping any that don't resolve. */\nfunction resolveAll<V>(ids: string[] | undefined, get: (id: string) => V | undefined): V[] {\n const out: V[] = [];\n for (const id of ids ?? []) {\n const v = get(id);\n if (v !== undefined) out.push(v);\n }\n return out;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"entities.js","sourceRoot":"","sources":["../../src/data/entities.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Linked views over the richly-connected entity types. Each wraps a raw\n * generated record and resolves its relationships lazily against the owning\n * {@link Dataset}; the full underlying record is always available via `.raw`.\n *\n * @packageDocumentation\n */\nimport type {\n AbilityDSLEntry,\n Faction,\n Phase,\n Unit,\n WargearOption,\n Weapon,\n WeaponKeyword,\n} from \"../generated.js\";\nimport type { Buff, BuffSource, EngineContext } from \"../cruncher/buffs.js\";\nimport { buffsFromKeyword } from \"../cruncher/from-keyword.js\";\nimport {\n effectToBuffs,\n type EffectTranslation,\n type TranslationPerspective,\n} from \"../cruncher/from-dsl.js\";\nimport type { Dataset } from \"./dataset.js\";\nimport { describeAbility } from \"../translate/effect.js\";\n\n/** A unit, linked to its faction, weapons, and abilities. */\nexport class UnitView {\n constructor(\n /** The full generated `Unit` record. */\n readonly raw: Unit,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** The unit's faction, or `undefined` if its `faction_id` is unknown. */\n get faction(): FactionView | undefined {\n return this.ds.factions.get(this.raw.faction_id);\n }\n\n /** Weapons referenced by `weapon_ids`; unresolved ids are skipped. */\n get weapons(): WeaponView[] {\n return resolveAll(this.raw.weapon_ids, (id) => this.ds.weapons.get(id));\n }\n\n /** Abilities referenced by `ability_ids`; unresolved ids are skipped. */\n get abilities(): AbilityView[] {\n return resolveAll(this.raw.ability_ids, (id) => this.ds.abilities.get(id));\n }\n\n /** Wargear options (weapon swaps, add-ons, choices) authored for this unit. */\n get wargearOptions(): WargearOption[] {\n return this.ds.wargearOptionsOf(this.raw);\n }\n\n /**\n * The stat profile at index `i` (default 0). Returns the schema-generated\n * profile object directly so callers can feed it straight to the engine\n * without an intermediate wrapper.\n */\n profileAt(i = 0): Unit[\"profiles\"][number] {\n const profile = this.raw.profiles[i];\n if (profile === undefined) {\n throw new RangeError(\n `UnitView(${this.raw.id}).profileAt(${i}): only ${this.raw.profiles.length} profile(s) defined`,\n );\n }\n return profile;\n }\n}\n\n/**\n * An ability, linked to the phases it acts in and the units that have it.\n *\n * Phases are not stored on the ability — they live in `phase-mappings` records.\n *\n * @example\n * units.find(\"Kharn\")!.abilities\n * .filter(a => a.phases.includes(\"shooting\"));\n */\nexport class AbilityView {\n constructor(\n /** The full generated ability record. */\n readonly raw: AbilityDSLEntry,\n private readonly ds: Dataset,\n ) {}\n\n /** The ability's id (`ability_id` in the raw record). */\n get id(): string {\n return this.raw.ability_id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /**\n * Generated plain-English approximation of this ability's effect + scope,\n * rendered from the DSL by the conformance-pinned describer\n * (`translate/effect.ts`). The dataset carries no rules prose; this is the\n * displayable stand-in.\n */\n describe(): string {\n return describeAbility(this.raw);\n }\n\n /** Game phases this ability acts in, unioned across its phase-mappings. */\n get phases(): Phase[] {\n return this.ds.phasesFor(\"ability\", this.raw.ability_id);\n }\n\n /** Units that list this ability in their `ability_ids`. */\n get units(): UnitView[] {\n return this.ds.unitsWithAbility(this.raw.ability_id);\n }\n\n /**\n * Buff stack this ability contributes against `context`, with provenance\n * tagged via `source` (the caller knows whether this ability is being read\n * as army, detachment, unit, leader, etc.). DSL branches the buff layer\n * can't auto-apply are dropped here; call {@link describeBuffs} if you\n * also want the diagnostics. `perspective` defaults to `\"attacker\"`; pass\n * `\"target\"` to translate the ability as a defensive buff (FNP, T/Sv\n * stat-mods, save rerolls, incoming hit penalties).\n */\n getBuffs(\n source: BuffSource,\n context?: EngineContext,\n perspective: TranslationPerspective = \"attacker\",\n ): Buff[] {\n return this.describeBuffs(source, context, perspective).applied;\n }\n\n /**\n * Full DSL→Buff translation, including the `unsupported` list of effect\n * fragments the buff layer can't model. The SPA renders these as warnings\n * so users see which abilities have effects that need a manual toggle.\n */\n describeBuffs(\n source: BuffSource,\n context?: EngineContext,\n perspective: TranslationPerspective = \"attacker\",\n ): EffectTranslation {\n const ctx: EngineContext = context ?? { phase: \"shooting\" };\n return effectToBuffs(this.raw.effect, source, ctx, perspective);\n }\n}\n\n/** A weapon, linked to the units that carry it. */\nexport class WeaponView {\n constructor(\n /** The full generated `Weapon` record. */\n readonly raw: Weapon,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** Units that list this weapon in their `weapon_ids`. */\n get units(): UnitView[] {\n return this.ds.unitsWithWeapon(this.raw.id);\n }\n\n /** The stat profile at index `i` (default 0). */\n profileAt(i = 0): Weapon[\"profiles\"][number] {\n const profile = this.raw.profiles[i];\n if (profile === undefined) {\n throw new RangeError(\n `WeaponView(${this.raw.id}).profileAt(${i}): only ${this.raw.profiles.length} profile(s) defined`,\n );\n }\n return profile;\n }\n\n /**\n * Catalog views for each keyword referenced by profile `i`, paired with the\n * reference-site parameters. Unresolved keyword ids are skipped.\n */\n keywordsAt(\n i = 0,\n ): { keyword: WeaponKeywordView; parameters: Record<string, unknown> | undefined }[] {\n const profile = this.profileAt(i);\n const refs = profile.keywords ?? [];\n const out: { keyword: WeaponKeywordView; parameters: Record<string, unknown> | undefined }[] = [];\n for (const ref of refs) {\n const view = this.ds.weaponKeywords.get(ref.keyword_id);\n if (!view) continue;\n out.push({\n keyword: view,\n parameters: ref.parameters as Record<string, unknown> | undefined,\n });\n }\n return out;\n }\n\n /**\n * Buffs contributed by profile `i`'s intrinsic keywords against `context` —\n * the natural \"what does this profile bring on its own?\" call the engine\n * makes automatically before adding ability/manual buffs.\n */\n profileBuffs(i: number | undefined, context: EngineContext): Buff[] {\n const index = i ?? 0;\n const out: Buff[] = [];\n for (const { keyword, parameters } of this.keywordsAt(index)) {\n out.push(\n ...buffsFromKeyword({\n keywordId: keyword.id,\n weaponId: this.raw.id,\n effect: keyword.raw.effect,\n ...(parameters !== undefined ? { parameters } : {}),\n context,\n }),\n );\n }\n return out;\n }\n}\n\n/**\n * A weapon-keyword catalog entry, linked to the weapons whose profiles\n * reference it. Exposes the keyword's mechanical effect as a buff stack\n * via {@link getBuffs}.\n */\nexport class WeaponKeywordView {\n constructor(\n /** The full generated `WeaponKeyword` record. */\n readonly raw: WeaponKeyword,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** Weapons whose profiles reference this keyword id. */\n get weapons(): WeaponView[] {\n return this.ds.weaponsWithKeyword(this.raw.id);\n }\n\n /**\n * Buff contributions from this catalog entry, for one reference site:\n * pass the keyword's `parameters` (e.g. `{ value: 1 }` for Sustained Hits 1)\n * along with the `weaponId` that's carrying it (used as the buff source)\n * and the engine `context` (e.g. attacker stationary?).\n */\n getBuffs(\n parameters: Record<string, unknown> | undefined,\n weaponId: string,\n context: EngineContext,\n ): Buff[] {\n return buffsFromKeyword({\n keywordId: this.raw.id,\n weaponId,\n effect: this.raw.effect,\n ...(parameters !== undefined ? { parameters } : {}),\n context,\n });\n }\n}\n\n/** A faction, linked to its units and the records scoped to it. */\nexport class FactionView {\n constructor(\n /** The full generated `Faction` record. */\n readonly raw: Faction,\n private readonly ds: Dataset,\n ) {}\n\n get id(): string {\n return this.raw.id;\n }\n\n get name(): string {\n return this.raw.name;\n }\n\n /** Units whose `faction_id` is this faction (may be empty for successors). */\n get units(): UnitView[] {\n return this.ds.units.byFaction(this.raw.id);\n }\n\n /** Faction-scoped abilities (abilities whose `faction_id` is this faction). */\n get abilities(): AbilityView[] {\n return this.ds.abilities.byFaction(this.raw.id);\n }\n\n /** Distinct weapons carried by this faction's units. */\n get weapons(): WeaponView[] {\n const seen = new Set<string>();\n const out: WeaponView[] = [];\n for (const unit of this.units) {\n for (const weapon of unit.weapons) {\n if (seen.has(weapon.id)) continue;\n seen.add(weapon.id);\n out.push(weapon);\n }\n }\n return out;\n }\n}\n\n/** Resolve a list of ids, dropping any that don't resolve. */\nfunction resolveAll<V>(ids: string[] | undefined, get: (id: string) => V | undefined): V[] {\n const out: V[] = [];\n for (const id of ids ?? []) {\n const v = get(id);\n if (v !== undefined) out.push(v);\n }\n return out;\n}\n"]}
|
package/dist/gen-conformance.js
CHANGED
|
@@ -24,7 +24,7 @@ import { dirname, join } from "node:path";
|
|
|
24
24
|
import { fileURLToPath } from "node:url";
|
|
25
25
|
import { Dataset } from "./data/dataset.js";
|
|
26
26
|
import { normalizeName } from "./data/normalize.js";
|
|
27
|
-
import { describeScoringCard } from "./translate/index.js";
|
|
27
|
+
import { describeScoringCard, describeAbility } from "./translate/index.js";
|
|
28
28
|
import { awardsOf } from "./scoring/index.js";
|
|
29
29
|
import { createRunnerState, dispatch } from "./runner.js";
|
|
30
30
|
import { exportRoster } from "./export/index.js";
|
|
@@ -878,11 +878,67 @@ function genTerrainKeystones() {
|
|
|
878
878
|
writeJson(join(CONFORMANCE, "terrain-keystones", "cases.json"), cases);
|
|
879
879
|
console.log(`terrain-keystones/cases.json: ${cases.length} cases`);
|
|
880
880
|
}
|
|
881
|
+
/**
|
|
882
|
+
* Effect-translation corpus: pin the Ability-DSL effect describer
|
|
883
|
+
* (`describeEffect`/`describeAbility` — the "ability.print()") across the TS
|
|
884
|
+
* and Rust ports. Cases embed the raw `effect` (+ `scope`) so parity does not
|
|
885
|
+
* depend on collection dup-id resolution; selection greedily covers every
|
|
886
|
+
* effect node type at least once (up to 5 exemplars per type) over the
|
|
887
|
+
* id-sorted ability list, so the corpus stays small but exhaustive by shape.
|
|
888
|
+
*/
|
|
889
|
+
function genEffectTranslation() {
|
|
890
|
+
const ds = Dataset.embedded();
|
|
891
|
+
mkdirSync(join(CONFORMANCE, "effect-translation"), { recursive: true });
|
|
892
|
+
const collectTypes = (e, out) => {
|
|
893
|
+
if (Array.isArray(e)) {
|
|
894
|
+
for (const v of e)
|
|
895
|
+
collectTypes(v, out);
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
if (typeof e !== "object" || e === null)
|
|
899
|
+
return;
|
|
900
|
+
const rec = e;
|
|
901
|
+
if (typeof rec.type === "string")
|
|
902
|
+
out.add(rec.type);
|
|
903
|
+
for (const key of ["effect", "on_success", "on_fail", "steps", "options", "condition"]) {
|
|
904
|
+
if (key in rec)
|
|
905
|
+
collectTypes(rec[key], out);
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
const abilities = ds.abilities.all
|
|
909
|
+
.slice()
|
|
910
|
+
.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
911
|
+
const seen = new Map();
|
|
912
|
+
const CAP = 5;
|
|
913
|
+
const cases = [];
|
|
914
|
+
for (const a of abilities) {
|
|
915
|
+
const types = new Set();
|
|
916
|
+
collectTypes(a.raw.effect, types);
|
|
917
|
+
let fresh = false;
|
|
918
|
+
for (const t of types) {
|
|
919
|
+
if ((seen.get(t) ?? 0) < CAP)
|
|
920
|
+
fresh = true;
|
|
921
|
+
}
|
|
922
|
+
if (!fresh)
|
|
923
|
+
continue;
|
|
924
|
+
for (const t of types)
|
|
925
|
+
seen.set(t, (seen.get(t) ?? 0) + 1);
|
|
926
|
+
cases.push({
|
|
927
|
+
caseId: `${a.id}#${cases.length}`,
|
|
928
|
+
effect: a.raw.effect,
|
|
929
|
+
scope: a.raw.scope ?? null,
|
|
930
|
+
expected: { text: describeAbility({ effect: a.raw.effect, scope: a.raw.scope }) },
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
writeJson(join(CONFORMANCE, "effect-translation", "cases.json"), cases);
|
|
934
|
+
console.log(`effect-translation/cases.json: ${cases.length} cases (${seen.size} node types)`);
|
|
935
|
+
}
|
|
881
936
|
genNormalize();
|
|
882
937
|
genRosters();
|
|
883
938
|
genLinkedApi();
|
|
884
939
|
genAttribution();
|
|
885
940
|
genScoringTranslation();
|
|
941
|
+
genEffectTranslation();
|
|
886
942
|
genScoring();
|
|
887
943
|
genTerrainResolver();
|
|
888
944
|
genTerrainKeystones();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gen-conformance.js","sourceRoot":"","sources":["../src/gen-conformance.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generate the cross-implementation conformance corpus under repo-root\n * `conformance/`. The TypeScript package is the reference implementation, so\n * the goldens it emits are what the Rust crate must reproduce byte-for-byte\n * (structurally). Run via `npm run gen:conformance`; CI regenerates and asserts\n * `git diff --exit-code conformance/` is clean.\n *\n * Outputs:\n * - `conformance/normalize.json` — `[{ input, expected }]` for normalizeName.\n * - `conformance/roster/<case>/expected.roster.json` — the resolved Roster.\n * - `conformance/roster/<case>/expected.<fmt>.{txt,json}` — every export\n * target's golden output. The TS exporter is the oracle; the Rust mirror\n * asserts byte-equal output for the same Roster.\n * - `conformance/roster/<case>/input.newrecruit-{wtc-compact,wtc-full,simple}.txt`\n * — text inputs derived from the seed by the exporter, so a re-import\n * regression in either implementation surfaces immediately.\n *\n * Seeding: each `<case>/` carries one canonical input — either the legacy\n * `input.json` (ListForge) or `input.newrecruit-json.json` (NewRecruit). Other\n * inputs are derived.\n */\nimport { readdirSync, readFileSync, writeFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { Dataset } from \"./data/dataset.js\";\nimport { normalizeName } from \"./data/normalize.js\";\nimport { describeScoringCard } from \"./translate/index.js\";\nimport { awardsOf } from \"./scoring/index.js\";\nimport { createRunnerState, dispatch } from \"./runner.js\";\nimport { exportRoster, type ExportFormat } from \"./export/index.js\";\nimport { importRoster, REGISTERED_ADAPTERS } from \"./import/import-roster.js\";\nimport { selectAdapter } from \"./import/adapter.js\";\nimport type { ParsedRoster, Roster } from \"./import/types.js\";\nimport { encodeBase } from \"./runner.js\";\nimport { attributeStages } from \"./cruncher/attribution.js\";\nimport type { EngineInput } from \"./cruncher/index.js\";\nimport {\n resolveLayout,\n type TerrainTemplate as ResolverTemplate,\n type TerrainLayout as ResolverLayout,\n} from \"./terrain/resolve.js\";\nimport { keystoneMeasurements, BOARD_INCHES } from \"./terrain/keystones.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst REPO_ROOT = join(__dirname, \"../..\");\nconst CONFORMANCE = join(REPO_ROOT, \"conformance\");\n\nconst NORMALIZE_INPUTS = [\n // NFD diacritic strip\n \"Khârn the Betrayer\",\n \"Brôkhyr\",\n \"Ûthar\",\n \"Magnús\",\n // apostrophe / quote variants\n \"T'au\",\n \"Be’lakor\",\n \"Kor’sarro Khan\",\n \"Aetaos'rau'keres\",\n \"‘quoted’\",\n // whitespace / hyphen collapse + trim\n \"Brôkhyr Iron-master\",\n \" the betrayer \",\n \"space--marines\",\n // casefold\n \"KHÂRN THE BETRAYER\",\n // already-normalized (idempotence)\n \"kharn the betrayer\",\n // distinctness anchors (must NOT collapse together)\n \"Khorne\",\n \"Khârn\",\n // Unicode whitespace beyond ASCII — every Unicode whitespace must collapse\n // identically across implementations or `find(\"Khorne Lord\")` and\n // `find(\"Khorne Lord\")` will silently disagree across ports.\n \"Khorne Lord\",\n \"Khorne Lord\",\n // Turkish dotted-I: NFD decomposes to `I` + combining dot above; the dot is\n // stripped, then locale-independent lowercase yields `i`. The case pins that\n // no implementation introduces locale-aware casefolding (which would map\n // `I` → `ı` under Turkish locale and break ASCII-text search).\n \"İmperial Fists\",\n // Zero-width joiner: passes through every step today. Pinned so behavior\n // does not silently change — if a future commit strips Cf-category chars,\n // this golden updates in the same PR.\n \"KhorneLord\",\n];\n\nfunction writeJson(path: string, value: unknown): void {\n writeFileSync(path, `${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction writeText(path: string, value: string): void {\n writeFileSync(path, value);\n}\n\nfunction genNormalize(): void {\n const table = NORMALIZE_INPUTS.map((input) => ({ input, expected: normalizeName(input) }));\n writeJson(join(CONFORMANCE, \"normalize.json\"), table);\n console.log(`normalize.json: ${table.length} cases`);\n}\n\n/** Locate the canonical input for a fixture dir: prefer `input.json` (legacy\n * ListForge), then `input.newrecruit-json.json` (NewRecruit), then the\n * text-only `input.gw.txt` (GW app export — import-only, like ListForge). */\nfunction seedRoster(caseDir: string, ds: Dataset): Roster {\n const decoded = decodeCanonicalSeed(caseDir);\n return importRoster(decoded, { dataset: ds });\n}\n\n/** Return the decoded payload for the canonical seed — the same value the\n * import pipeline would dispatch on. JSON seeds come back parsed; text seeds\n * come back as the raw string. */\nfunction decodeCanonicalSeed(caseDir: string): unknown {\n const jsonSeed = join(caseDir, \"input.json\");\n if (existsSync(jsonSeed)) {\n return JSON.parse(readFileSync(jsonSeed, \"utf8\"));\n }\n const nrSeed = join(caseDir, \"input.newrecruit-json.json\");\n if (existsSync(nrSeed)) {\n return JSON.parse(readFileSync(nrSeed, \"utf8\"));\n }\n const gwSeed = join(caseDir, \"input.gw.txt\");\n if (existsSync(gwSeed)) {\n return readFileSync(gwSeed, \"utf8\");\n }\n throw new Error(`no canonical input found in ${caseDir}`);\n}\n\n/** Run a decoded payload through the adapter pipeline up to (but not past)\n * resolution. The result is the format-agnostic ParsedRoster — the same\n * intermediate the resolver consumes. Pinning this layer surfaces parser\n * regressions even when resolution masks them. */\nfunction parsedFromCanonicalSeed(caseDir: string): ParsedRoster {\n const decoded = decodeCanonicalSeed(caseDir);\n const adapter = selectAdapter(decoded, [...REGISTERED_ADAPTERS]);\n return adapter.parse(decoded);\n}\n\nconst TEXT_FORMATS: { format: ExportFormat; inputName: string; goldenName: string }[] = [\n {\n format: \"newrecruit-wtc-compact\",\n inputName: \"input.newrecruit-wtc-compact.txt\",\n goldenName: \"expected.newrecruit-wtc-compact.txt\",\n },\n {\n format: \"newrecruit-wtc-full\",\n inputName: \"input.newrecruit-wtc-full.txt\",\n goldenName: \"expected.newrecruit-wtc-full.txt\",\n },\n {\n format: \"newrecruit-simple\",\n inputName: \"input.newrecruit-simple.txt\",\n goldenName: \"expected.newrecruit-simple.txt\",\n },\n];\n\nfunction genRosters(): void {\n const ds = Dataset.embedded();\n const rosterDir = join(CONFORMANCE, \"roster\");\n for (const entry of readdirSync(rosterDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const caseDir = join(rosterDir, entry.name);\n\n const seed = seedRoster(caseDir, ds);\n writeJson(join(caseDir, \"expected.roster.json\"), seed);\n\n // Parsed-stage golden — the intermediate ParsedRoster produced by the\n // adapter for the canonical seed, before resolution. Catches parser bugs\n // that resolution would otherwise mask (e.g. wrong unit count from a\n // duplicate cost line that resolves to the same unit twice).\n writeJson(join(caseDir, \"expected.parsed.json\"), parsedFromCanonicalSeed(caseDir));\n\n // JSON export golden — NewRecruit-shaped skeleton.\n const jsonOut = exportRoster(seed, \"newrecruit-json\");\n writeJson(join(caseDir, \"expected.newrecruit-json.json\"), JSON.parse(jsonOut));\n\n // Canonical Roster JSON export — should equal the resolved roster.\n writeJson(join(caseDir, \"expected.roster-json.json\"), JSON.parse(exportRoster(seed, \"roster-json\")));\n\n // Text exports: always write the export golden so every fixture exercises\n // the cross-implementation byte-equality check. Only write the\n // `input.*.txt` round-trip seed when the fixture was authored for the\n // NewRecruit pipeline — legacy ListForge fixtures carry decoration\n // (multi-force warnings, leader-attachment inference) that the simple/wtc\n // exporters can't fully preserve, so the round-trip would fail\n // structurally rather than uncover a parser bug.\n const isNewRecruitSeed = existsSync(join(caseDir, \"input.newrecruit-json.json\"));\n for (const { format, inputName, goldenName } of TEXT_FORMATS) {\n const out = exportRoster(seed, format);\n writeText(join(caseDir, goldenName), out);\n if (isNewRecruitSeed) {\n writeText(join(caseDir, inputName), out);\n }\n }\n\n // Rosterizer JSON export + a derived round-trip input. The exporter is\n // deterministic and round-trips through the adapter, so emitting it as\n // both `expected.rosterizer.json` and `input.rosterizer.json` pins the\n // cross-implementation goldens and the importer regression at the same\n // time. Same NewRecruit-seed gate as the text formats — multi-force\n // ListForge fixtures lose their provisional leader-attachment under\n // round-trip, so they only get the export golden, not the derived input.\n const rosterizerOut = exportRoster(seed, \"rosterizer\");\n writeJson(join(caseDir, \"expected.rosterizer.json\"), JSON.parse(rosterizerOut));\n if (isNewRecruitSeed) {\n writeJson(join(caseDir, \"input.rosterizer.json\"), JSON.parse(rosterizerOut));\n }\n\n console.log(\n `roster/${entry.name}: ${seed.units.length} units, ${seed.diagnostics.warnings.length} warnings`,\n );\n }\n}\n\n/**\n * Linked-API query cases. Each descriptor names a query method on Dataset, the\n * args to call it with, and how the result should be compared.\n *\n * `comparison: \"ordered\"` pins the result order — used for queries that iterate\n * a data-driven array (`unit.ability_ids`, `unit.weapon_ids`) where order is\n * encoded in the data and both implementations iterate it the same way.\n *\n * `comparison: \"set\"` pins only the set of ids — used for queries that walk an\n * index (faction → abilities, ability → phases) where iteration order depends\n * on dataset bundler internals and is incidental. Ids are sorted before\n * comparison.\n *\n * `comparison: \"scalar\"` pins a single id-or-null result (find_* and\n * faction_of(unit)).\n */\ntype LinkedApiQuery =\n | { name: string; query: \"find_unit\"; args: { query: string }; comparison: \"scalar\" }\n | { name: string; query: \"find_weapon\"; args: { query: string }; comparison: \"scalar\" }\n | { name: string; query: \"find_faction\"; args: { query: string }; comparison: \"scalar\" }\n | { name: string; query: \"find_ability\"; args: { query: string }; comparison: \"scalar\" }\n | { name: string; query: \"abilities_of\"; args: { unitId: string }; comparison: \"ordered\" }\n | { name: string; query: \"weapons_of\"; args: { unitId: string }; comparison: \"ordered\" }\n | { name: string; query: \"phases_of\"; args: { abilityId: string }; comparison: \"set\" }\n | { name: string; query: \"faction_of\"; args: { unitId: string }; comparison: \"scalar\" }\n | { name: string; query: \"abilities_of_faction\"; args: { factionId: string }; comparison: \"set\" }\n | { name: string; query: \"weapons_of_faction\"; args: { factionId: string }; comparison: \"set\" }\n | { name: string; query: \"base_size_of\"; args: { unitId: string }; comparison: \"scalar\" }\n | { name: string; query: \"model_bases_of\"; args: { unitId: string }; comparison: \"ordered\" };\n\nconst LINKED_API_QUERIES: LinkedApiQuery[] = [\n // find_unit: diacritic-insensitive lookup, miss returns null.\n { name: \"find_unit by diacritic name\", query: \"find_unit\", args: { query: \"Kharn\" }, comparison: \"scalar\" },\n { name: \"find_unit miss returns null\", query: \"find_unit\", args: { query: \"not-a-real-unit-xyz\" }, comparison: \"scalar\" },\n // find_weapon: hyphen + space tolerance.\n { name: \"find_weapon by name\", query: \"find_weapon\", args: { query: \"bolt rifle\" }, comparison: \"scalar\" },\n // find_faction: punctuation/diacritic tolerance.\n { name: \"find_faction by display name\", query: \"find_faction\", args: { query: \"World Eaters\" }, comparison: \"scalar\" },\n // find_ability: ability name lookup.\n { name: \"find_ability by name\", query: \"find_ability\", args: { query: \"Berzerker Frenzy\" }, comparison: \"scalar\" },\n // abilities_of(unit): ordered, iterates unit.ability_ids array.\n { name: \"abilities_of intercessor-squad\", query: \"abilities_of\", args: { unitId: \"intercessor-squad\" }, comparison: \"ordered\" },\n { name: \"abilities_of kharn-the-betrayer\", query: \"abilities_of\", args: { unitId: \"kharn-the-betrayer\" }, comparison: \"ordered\" },\n // weapons_of(unit): ordered, iterates unit.weapon_ids array.\n { name: \"weapons_of intercessor-squad\", query: \"weapons_of\", args: { unitId: \"intercessor-squad\" }, comparison: \"ordered\" },\n { name: \"weapons_of kharn-the-betrayer\", query: \"weapons_of\", args: { unitId: \"kharn-the-betrayer\" }, comparison: \"ordered\" },\n // phases_of(ability): compared as set (phase index iteration order is incidental).\n { name: \"phases_of berzerker-frenzy\", query: \"phases_of\", args: { abilityId: \"berzerker-frenzy\" }, comparison: \"set\" },\n // faction_of(unit): scalar id or null.\n { name: \"faction_of intercessor-squad\", query: \"faction_of\", args: { unitId: \"intercessor-squad\" }, comparison: \"scalar\" },\n // abilities_of_faction: compared as set (collection-index order is incidental).\n { name: \"abilities_of_faction world-eaters\", query: \"abilities_of_faction\", args: { factionId: \"world-eaters\" }, comparison: \"set\" },\n // weapons_of_faction: compared as set.\n { name: \"weapons_of_faction world-eaters\", query: \"weapons_of_faction\", args: { factionId: \"world-eaters\" }, comparison: \"set\" },\n // base_size_of(unit): scalar encoded base — round, oval, and a draft flying-base.\n { name: \"base_size_of intercessor-squad\", query: \"base_size_of\", args: { unitId: \"intercessor-squad\" }, comparison: \"scalar\" },\n { name: \"base_size_of vertus-praetors\", query: \"base_size_of\", args: { unitId: \"vertus-praetors\" }, comparison: \"scalar\" },\n { name: \"base_size_of windriders (draft flying base)\", query: \"base_size_of\", args: { unitId: \"windriders\" }, comparison: \"scalar\" },\n // model_bases_of(unit): ordered per-model bases; jakhals mixes 28.5mm bodies with a 40mm Dishonoured.\n { name: \"model_bases_of jakhals (mixed)\", query: \"model_bases_of\", args: { unitId: \"jakhals\" }, comparison: \"ordered\" },\n];\n\nfunction genLinkedApi(): void {\n const ds = Dataset.embedded();\n const cases = LINKED_API_QUERIES.map((q) => {\n const expected = runLinkedQuery(ds, q);\n return { ...q, expected };\n });\n writeJson(join(CONFORMANCE, \"linked-api\", \"cases.json\"), cases);\n console.log(`linked-api/cases.json: ${cases.length} cases`);\n}\n\nfunction runLinkedQuery(ds: Dataset, q: LinkedApiQuery): string | null | string[] {\n switch (q.query) {\n case \"find_unit\":\n return ds.units.find(q.args.query)?.id ?? null;\n case \"find_weapon\":\n return ds.weapons.find(q.args.query)?.id ?? null;\n case \"find_faction\":\n return ds.factions.find(q.args.query)?.id ?? null;\n case \"find_ability\":\n return ds.abilities.find(q.args.query)?.id ?? null;\n case \"abilities_of\": {\n const u = ds.units.get(q.args.unitId);\n if (!u) throw new Error(`abilities_of: unknown unit ${q.args.unitId}`);\n return u.abilities.map((a) => a.id);\n }\n case \"weapons_of\": {\n const u = ds.units.get(q.args.unitId);\n if (!u) throw new Error(`weapons_of: unknown unit ${q.args.unitId}`);\n return u.weapons.map((w) => w.id);\n }\n case \"phases_of\": {\n const a = ds.abilities.get(q.args.abilityId);\n if (!a) throw new Error(`phases_of: unknown ability ${q.args.abilityId}`);\n return [...a.phases].sort();\n }\n case \"faction_of\": {\n const u = ds.units.get(q.args.unitId);\n if (!u) throw new Error(`faction_of: unknown unit ${q.args.unitId}`);\n return u.faction?.id ?? null;\n }\n case \"abilities_of_faction\":\n return ds.abilities.byFaction(q.args.factionId).map((a) => a.id).sort();\n case \"weapons_of_faction\": {\n // Mirrors Rust `weapons_of_faction`: aggregate weapons across the\n // faction's units and dedupe by id. The collection-level\n // `weapons.byFaction()` is a different operation (it looks up weapons\n // whose own `faction_id` is set, which is empty for most factions).\n const f = ds.factions.get(q.args.factionId);\n if (!f) throw new Error(`weapons_of_faction: unknown faction ${q.args.factionId}`);\n return f.weapons.map((w) => w.id).sort();\n }\n case \"base_size_of\": {\n const u = ds.units.get(q.args.unitId);\n if (!u) throw new Error(`base_size_of: unknown unit ${q.args.unitId}`);\n return encodeBase(u.raw.base_size_mm);\n }\n case \"model_bases_of\": {\n const u = ds.units.get(q.args.unitId);\n if (!u) throw new Error(`model_bases_of: unknown unit ${q.args.unitId}`);\n const comp = ds.unitCompositions.find((c) => c.unit_id === q.args.unitId);\n return (comp?.models ?? []).map((m) => `${m.name}=${encodeBase(m.base_size_mm) ?? \"none\"}`);\n }\n }\n}\n\n/**\n * Attribution corpus: reuses the existing cruncher inputs from the cases that\n * carry at least one groupable buff (ability or manual). The expected shape\n * is the AttributedStage array produced by attributeStages; both\n * implementations of the leave-one-out decomposition must reproduce it\n * within the per-stage float tolerance.\n */\nconst ATTRIBUTION_CASE_FILES = [\n \"05-anti-infantry-vs-cultist.json\",\n \"07-twin-linked-heavy-stationary-vs-knight.json\",\n];\n\ninterface CruncherCaseInput {\n name: string;\n attacker: { weaponId: string; profileIndex: number };\n modelsFiring: number;\n target: { unitId: string; profileIndex: number; modelCount?: number };\n context: EngineInput[\"context\"];\n buffs: EngineInput[\"buffs\"];\n}\n\nfunction loadAttributionInput(ds: Dataset, filename: string): {\n name: string;\n input: EngineInput;\n} {\n const path = join(CONFORMANCE, \"cruncher\", filename);\n const c = JSON.parse(readFileSync(path, \"utf8\")) as CruncherCaseInput;\n const weapon = ds.weapons.get(c.attacker.weaponId);\n const unit = ds.units.get(c.target.unitId);\n if (!weapon) throw new Error(`attribution: unknown weapon ${c.attacker.weaponId}`);\n if (!unit) throw new Error(`attribution: unknown unit ${c.target.unitId}`);\n return {\n name: c.name,\n input: {\n attacker: { weapon: weapon.raw, profileIndex: c.attacker.profileIndex },\n target: {\n unit: unit.raw,\n profileIndex: c.target.profileIndex,\n ...(c.target.modelCount !== undefined ? { modelCount: c.target.modelCount } : {}),\n },\n modelsFiring: c.modelsFiring,\n buffs: c.buffs,\n context: c.context,\n },\n };\n}\n\nfunction genAttribution(): void {\n const ds = Dataset.embedded();\n const cases = ATTRIBUTION_CASE_FILES.map((filename, idx) => {\n const { name, input } = loadAttributionInput(ds, filename);\n const stages = attributeStages(input, ds);\n return {\n // Persist the input by file reference so the corpus stays a single\n // source of truth — the cruncher case file already pins the EngineInput.\n name,\n cruncher_case: filename,\n expected: stages.map((s) => ({\n name: s.name,\n expected: s.expected,\n baseline: s.baseline,\n lifts: s.lifts.map((l) => ({ source: l.source, delta: l.delta })),\n residual: s.residual,\n intrinsics: s.intrinsics,\n })),\n // Stable ordering of cases in the corpus file.\n _order: idx,\n };\n });\n // Sort by _order and strip the helper before writing.\n cases.sort((a, b) => a._order - b._order);\n const serialised = cases.map(({ _order: _o, ...rest }) => rest);\n writeJson(join(CONFORMANCE, \"attribution\", \"cases.json\"), serialised);\n console.log(`attribution/cases.json: ${cases.length} cases`);\n}\n\n/**\n * Scoring-card translation corpus: humanize each primary mission card's\n * `awards` into plain English. The TS translator is the oracle; the Rust port\n * must reproduce every string byte-for-byte (the differ compares structurally,\n * no tolerance). Only `card_type: \"primary\"` cards are pinned — the 14-card\n * secondary deck isn't revealed yet. Cases are sorted by id for stability, and\n * the `awards` array order within each card is load-bearing.\n */\nfunction genScoringTranslation(): void {\n const ds = Dataset.embedded();\n mkdirSync(join(CONFORMANCE, \"scoring-translation\"), { recursive: true });\n // Pin the translation of every mission card's awards — primary and secondary\n // alike (the secondary deck has the same `awards` shape and deserves the same\n // cross-impl pinning).\n const cases = ds.missionCards.all\n .filter((c) => c.card_type === \"primary\" || c.card_type === \"secondary\")\n .slice()\n .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))\n .map((card) => ({ cardId: card.id, expected: { awards: describeScoringCard(card) } }));\n writeJson(join(CONFORMANCE, \"scoring-translation\", \"cases.json\"), cases);\n console.log(`scoring-translation/cases.json: ${cases.length} cases`);\n}\n\n/**\n * Scoring-engine corpus: pin the pure VP arithmetic of the scoring engine\n * (`tools/src/scoring/` — the oracle) so the Rust `wh40kdc::scoring` port\n * reproduces it. Three ops, each case `{ name, op, args, expected }`:\n *\n * - `score_event` — per card and approach, assert every award matching the\n * approach (by its full-`awards`-array index). Pins `scoreAward`, `scoreTurn`\n * (exclusive-group \"highest only\", `vp_per × count` clamped to `per_max`,\n * cumulative sums), `scoreCap` (tactical 5 vs fixed `vp_max`/uncapped), and\n * `scoreSecondaryEvent`; primary cards also carry a `roundCap` to pin\n * `scorePrimaryEvent`. `cap: null` means uncapped (Infinity has no JSON form).\n * - `score_state` — replay scenarios over a `PlayerGame`, pinning the per-round\n * cap (15), per-game primary cap (45), grand-total cap (100), score+discard,\n * and undo.\n * - `wtc_result` — the 20-point band mapping across its boundaries.\n *\n * Goldens are produced by driving the TS runner's own `dispatch`, so the corpus\n * and the runner agree by construction; the cross-impl contract is the Rust\n * runner reproducing them. Integers are compared exactly (no tolerance).\n */\nfunction genScoring(): void {\n const ds = Dataset.embedded();\n mkdirSync(join(CONFORMANCE, \"scoring\"), { recursive: true });\n\n // One initialized runner state, reused across cases (the ops don't mutate it).\n const specVersion = Number.parseInt(\n readFileSync(join(CONFORMANCE, \"SPEC_VERSION\"), \"utf8\").trim(),\n 10,\n );\n const state = createRunnerState();\n const init = dispatch(state, {\n op: \"init\",\n args: { spec_version: specVersion, locale: \"C\", tz: \"UTC\", seed: 0 },\n });\n if (!init.ok) throw new Error(`gen scoring: init failed: ${JSON.stringify(init)}`);\n const run = (op: string, args: unknown): unknown => {\n const r = dispatch(state, { op, args });\n if (!r.ok) throw new Error(`gen scoring: ${op} failed: ${JSON.stringify(r)} for ${JSON.stringify(args)}`);\n return r.value;\n };\n\n type Case = { name: string; op: string; args: unknown; expected: unknown };\n const cases: Case[] = [];\n\n // score_event: every mission card, both approaches. Assert the approach's\n // awards by their full-array index; count vp_per awards to their per_max\n // (else 2) so the cap logic actually bites.\n const cards = ds.missionCards.all\n .slice()\n .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));\n for (const card of cards) {\n for (const approach of [\"fixed\", \"tactical\"] as const) {\n const asserted = awardsOf(card)\n .map((aw, index) => ({ aw, index }))\n .filter(({ aw }) => aw.mode == null || aw.mode === approach)\n .map(({ aw, index }) =>\n aw.vp_per != null ? { index, count: aw.per_max ?? 2 } : { index },\n );\n const args: Record<string, unknown> = { cardId: card.id, approach, asserted };\n if (card.card_type === \"primary\") args.roundCap = 15;\n cases.push({\n name: `score_event/${card.id}/${approach}`,\n op: \"score_event\",\n args,\n expected: run(\"score_event\", args),\n });\n }\n }\n\n // score_state: hand-authored replay scenarios. Card ids are real deck/mission\n // cards; expected state is whatever the engine produces.\n const stateScenarios: { name: string; args: unknown }[] = [\n {\n name: \"primary-round-and-game-caps\",\n args: {\n approach: \"tactical\",\n ops: [\n { kind: \"set-primary\", round: 1, vp: 30, roundCap: 15, gameCap: 45 },\n { kind: \"set-primary\", round: 2, vp: 30, roundCap: 15, gameCap: 45 },\n { kind: \"set-primary\", round: 3, vp: 30, roundCap: 15, gameCap: 45 },\n { kind: \"set-primary\", round: 4, vp: 30, roundCap: 15, gameCap: 45 },\n ],\n },\n },\n {\n // The full primary path: a card's raw round total, clamped to the round\n // cap on store, then cleared back to 0 by a set-primary 0.\n name: \"score-primary-then-clear\",\n args: {\n approach: \"tactical\",\n ops: [\n {\n kind: \"score-primary\",\n cardId: \"battlefield-dominance\",\n round: 2,\n asserted: awardsOf(ds.missionCards.get(\"battlefield-dominance\")!).map((aw, index) =>\n aw.vp_per != null ? { index, count: aw.per_max ?? 3 } : { index },\n ),\n roundCap: 15,\n gameCap: 45,\n },\n { kind: \"set-primary\", round: 3, vp: 99, roundCap: 15, gameCap: 45 },\n { kind: \"set-primary\", round: 2, vp: 0, roundCap: 15, gameCap: 45 },\n ],\n },\n },\n {\n name: \"secondary-score-and-undo\",\n args: {\n approach: \"tactical\",\n ops: [\n { kind: \"draw\", cardId: \"no-prisoners\" },\n { kind: \"score-secondary\", cardId: \"no-prisoners\", round: 2, asserted: [{ index: 0, count: 3 }] },\n { kind: \"remove-score\", index: 0 },\n ],\n },\n },\n {\n // Uncapped set-primary (no caps) overshoots so the 100 grand-total cap bites.\n name: \"grand-total-cap-at-100\",\n args: {\n approach: \"tactical\",\n ops: [\n { kind: \"set-primary\", round: 1, vp: 30 },\n { kind: \"set-primary\", round: 2, vp: 30 },\n { kind: \"set-primary\", round: 3, vp: 30 },\n { kind: \"set-primary\", round: 4, vp: 30 },\n { kind: \"set-primary\", round: 5, vp: 30 },\n { kind: \"draw\", cardId: \"no-prisoners\" },\n { kind: \"score-secondary\", cardId: \"no-prisoners\", round: 5, asserted: [{ index: 0, count: 99 }] },\n ],\n },\n },\n ];\n for (const s of stateScenarios) {\n cases.push({ name: `score_state/${s.name}`, op: \"score_state\", args: s.args, expected: run(\"score_state\", s.args) });\n }\n\n // wtc_result: band boundaries and symmetry.\n const wtcPairs: [number, number][] = [\n [50, 50],\n [48, 45],\n [45, 50],\n [56, 50],\n [50, 61],\n [100, 50],\n [100, 49],\n [0, 100],\n [60, 40],\n [55, 50],\n ];\n for (const [a, b] of wtcPairs) {\n const args = { a, b };\n cases.push({ name: `wtc_result/${a}-${b}`, op: \"wtc_result\", args, expected: run(\"wtc_result\", args) });\n }\n\n writeJson(join(CONFORMANCE, \"scoring\", \"cases.json\"), cases);\n console.log(`scoring/cases.json: ${cases.length} cases`);\n}\n\n/**\n * Terrain-resolver corpus: resolve template-anchored layouts to absolute\n * board-space vertices (y-down inches). The TS resolver is the oracle; the Rust\n * port must reproduce every vertex within 5e-4 (per-area invariant in\n * CONFORMANCE.md). Cases are self-contained — each carries its own `templates`\n * and `layout` — so the corpus does not depend on the bundled catalog and the\n * runner op can pass both in `args`. Coverage: per-template centroid anchoring\n * (identity), cardinal + oblique rotations, both mirror axes on an asymmetric\n * shape, embedded-feature composition, explicit parenting, and the inline\n * footprint escape hatch.\n */\nfunction genTerrainResolver(): void {\n mkdirSync(join(CONFORMANCE, \"terrain-resolver\"), { recursive: true });\n\n const areaLarge: ResolverTemplate = {\n id: \"area-large\",\n name: \"Large Area\",\n kind: \"area\",\n footprint: { type: \"rectangle\", width: 11.5, height: 7 },\n };\n const areaMedium: ResolverTemplate = {\n id: \"area-medium\",\n name: \"Medium Area\",\n kind: \"area\",\n footprint: { type: \"rectangle\", width: 6, height: 4 },\n };\n const areaTrapezoid: ResolverTemplate = {\n id: \"area-trapezoid\",\n name: \"Trapezoid Area\",\n kind: \"area\",\n footprint: {\n type: \"polygon\",\n points: [\n { x: 0, y: 0 },\n { x: 8, y: 0 },\n { x: 2, y: 11.5 },\n { x: 0, y: 11.5 },\n ],\n },\n };\n const wedge: ResolverTemplate = {\n id: \"wedge\",\n name: \"Right Wedge\",\n kind: \"area\",\n footprint: { type: \"right-triangle\", width: 8, height: 11.5 },\n };\n const wallLong: ResolverTemplate = {\n id: \"wall-long\",\n name: \"Long Wall\",\n kind: \"feature\",\n footprint: { type: \"rectangle\", width: 7, height: 0.25 },\n };\n const ruinComposed: ResolverTemplate = {\n id: \"ruin-composed\",\n name: \"Composed Ruin\",\n kind: \"area\",\n footprint: { type: \"rectangle\", width: 11.5, height: 7 },\n features: [\n { id: \"back-wall\", template: \"wall-long\", position: { x: 0, y: -3 } },\n { id: \"side-wall\", template: \"wall-long\", position: { x: -5, y: 0 }, rotation_degrees: 90, mirror: \"horizontal\" },\n ],\n };\n\n const baseCatalog = [areaLarge, areaMedium, areaTrapezoid, wedge, wallLong];\n\n const layoutCases: { name: string; templates: ResolverTemplate[]; layout: ResolverLayout }[] = [\n {\n name: \"identity-large\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-large\", position: { x: 30, y: 22 } }] },\n },\n {\n name: \"identity-wedge\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"wedge\", position: { x: 12, y: 30 } }] },\n },\n {\n name: \"identity-trapezoid\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-trapezoid\", position: { x: 40, y: 18 } }] },\n },\n {\n name: \"rotate-medium-90\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-medium\", position: { x: 30, y: 22 }, rotation_degrees: 90 }] },\n },\n {\n name: \"rotate-medium-180\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-medium\", position: { x: 30, y: 22 }, rotation_degrees: 180 }] },\n },\n {\n name: \"rotate-medium-270\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-medium\", position: { x: 30, y: 22 }, rotation_degrees: 270 }] },\n },\n {\n name: \"rotate-large-oblique-55\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-large\", position: { x: 30, y: 22 }, rotation_degrees: 55 }] },\n },\n {\n name: \"rotate-trapezoid-oblique-235\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-trapezoid\", position: { x: 35.75, y: 27 }, rotation_degrees: 235 }] },\n },\n {\n name: \"mirror-trapezoid-horizontal\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-trapezoid\", position: { x: 40, y: 18 }, mirror: \"horizontal\" }] },\n },\n {\n name: \"mirror-trapezoid-vertical-rot90\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-trapezoid\", position: { x: 40, y: 18 }, rotation_degrees: 90, mirror: \"vertical\" }] },\n },\n {\n name: \"composition-ruin-rot90-mirror-h\",\n templates: [ruinComposed, wallLong],\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"a1\", template: \"ruin-composed\", position: { x: 30, y: 22 }, rotation_degrees: 90, mirror: \"horizontal\" }] },\n },\n {\n name: \"explicit-parent-feature\",\n templates: [areaLarge, wallLong],\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n { id: \"a1\", template: \"area-large\", position: { x: 30, y: 22 }, rotation_degrees: 90, mirror: \"horizontal\" },\n { id: \"back-wall\", template: \"wall-long\", parent_area_id: \"a1\", position: { x: 0, y: -3 } },\n ],\n },\n },\n {\n name: \"inline-footprint-polygon\",\n templates: [],\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n footprint: { type: \"polygon\", points: [{ x: 0, y: 0 }, { x: 4, y: 0 }, { x: 2, y: 5 }] },\n position: { x: 50, y: 40 },\n rotation_degrees: 30,\n },\n ],\n },\n },\n ];\n\n const cases = layoutCases.map((c) => ({\n name: c.name,\n templates: c.templates,\n layout: c.layout,\n expected: { pieces: resolveLayout(c.layout, c.templates) },\n }));\n writeJson(join(CONFORMANCE, \"terrain-resolver\", \"cases.json\"), cases);\n console.log(`terrain-resolver/cases.json: ${cases.length} cases`);\n}\n\n/**\n * Terrain-keystones corpus: derive the printed distance of each authored\n * keystone (board edge → piece feature) from resolved geometry. The TS helper\n * is the oracle; the Rust port must reproduce every distance within 5e-4.\n * Cases are self-contained like the resolver corpus. Coverage: all four\n * edges, vertex and bounding-face refs, an oblique rotation, a mirrored\n * asymmetric shape, a parented feature (composition through the parent\n * frame), an inline footprint, and a custom board size.\n */\nfunction genTerrainKeystones(): void {\n mkdirSync(join(CONFORMANCE, \"terrain-keystones\"), { recursive: true });\n\n const areaLarge: ResolverTemplate = {\n id: \"area-large\",\n name: \"Large Area\",\n kind: \"area\",\n footprint: { type: \"rectangle\", width: 11.5, height: 7 },\n };\n const areaTrapezoid: ResolverTemplate = {\n id: \"area-trapezoid\",\n name: \"Trapezoid Area\",\n kind: \"area\",\n footprint: {\n type: \"polygon\",\n points: [\n { x: 0, y: 0 },\n { x: 8, y: 0 },\n { x: 2, y: 11.5 },\n { x: 0, y: 11.5 },\n ],\n },\n };\n const wallLong: ResolverTemplate = {\n id: \"wall-long\",\n name: \"Long Wall\",\n kind: \"feature\",\n footprint: { type: \"rectangle\", width: 7, height: 0.25 },\n };\n const catalog = [areaLarge, areaTrapezoid, wallLong];\n\n const keystoneCases: {\n name: string;\n templates: ResolverTemplate[];\n layout: ResolverLayout;\n board?: { width: number; height: number };\n }[] = [\n {\n name: \"identity-four-edges-vertices\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n template: \"area-large\",\n position: { x: 30, y: 22 },\n keystones: [\n { edge: \"left\", ref: { kind: \"vertex\", index: 0 } },\n { edge: \"top\", ref: { kind: \"vertex\", index: 1 } },\n { edge: \"right\", ref: { kind: \"vertex\", index: 2 } },\n { edge: \"bottom\", ref: { kind: \"vertex\", index: 3 } },\n ],\n },\n ],\n },\n },\n {\n name: \"identity-bounding-faces\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n template: \"area-large\",\n position: { x: 20, y: 30 },\n keystones: [\n { edge: \"left\", ref: { kind: \"face\", side: \"min-x\" } },\n { edge: \"right\", ref: { kind: \"face\", side: \"max-x\" } },\n { edge: \"top\", ref: { kind: \"face\", side: \"min-y\" } },\n { edge: \"bottom\", ref: { kind: \"face\", side: \"max-y\" } },\n ],\n },\n ],\n },\n },\n {\n name: \"oblique-rotation-vertex\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n template: \"area-trapezoid\",\n position: { x: 35.75, y: 27 },\n rotation_degrees: 235,\n keystones: [\n { edge: \"left\", ref: { kind: \"vertex\", index: 2 } },\n { edge: \"bottom\", ref: { kind: \"face\", side: \"max-y\" } },\n ],\n },\n ],\n },\n },\n {\n name: \"mirrored-trapezoid-vertex\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n template: \"area-trapezoid\",\n position: { x: 40, y: 18 },\n mirror: \"horizontal\",\n keystones: [\n { edge: \"right\", ref: { kind: \"vertex\", index: 1 } },\n { edge: \"top\", ref: { kind: \"vertex\", index: 0 } },\n ],\n },\n ],\n },\n },\n {\n name: \"parented-feature-keystone\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"a1\",\n template: \"area-large\",\n position: { x: 30, y: 22 },\n rotation_degrees: 90,\n mirror: \"horizontal\",\n keystones: [{ edge: \"left\", ref: { kind: \"vertex\", index: 0 } }],\n },\n {\n id: \"back-wall\",\n template: \"wall-long\",\n parent_area_id: \"a1\",\n position: { x: 0, y: -3 },\n keystones: [\n { edge: \"top\", ref: { kind: \"vertex\", index: 1 } },\n { edge: \"right\", ref: { kind: \"face\", side: \"max-x\" } },\n ],\n },\n ],\n },\n },\n {\n name: \"inline-footprint-keystone\",\n templates: [],\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n footprint: { type: \"polygon\", points: [{ x: 0, y: 0 }, { x: 4, y: 0 }, { x: 2, y: 5 }] },\n position: { x: 50, y: 40 },\n rotation_degrees: 30,\n keystones: [\n { edge: \"right\", ref: { kind: \"vertex\", index: 0 } },\n { edge: \"bottom\", ref: { kind: \"vertex\", index: 2 } },\n ],\n },\n ],\n },\n },\n {\n name: \"custom-board-extents\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n template: \"area-large\",\n position: { x: 15, y: 15 },\n keystones: [\n { edge: \"right\", ref: { kind: \"face\", side: \"max-x\" } },\n { edge: \"bottom\", ref: { kind: \"face\", side: \"max-y\" } },\n ],\n },\n ],\n },\n board: { width: 30, height: 22.4 },\n },\n ];\n\n const cases = keystoneCases.map((c) => ({\n name: c.name,\n templates: c.templates,\n layout: c.layout,\n ...(c.board ? { board: c.board } : {}),\n expected: {\n measurements: keystoneMeasurements(c.layout, c.templates, c.board ?? BOARD_INCHES),\n },\n }));\n writeJson(join(CONFORMANCE, \"terrain-keystones\", \"cases.json\"), cases);\n console.log(`terrain-keystones/cases.json: ${cases.length} cases`);\n}\n\ngenNormalize();\ngenRosters();\ngenLinkedApi();\ngenAttribution();\ngenScoringTranslation();\ngenScoring();\ngenTerrainResolver();\ngenTerrainKeystones();\n"]}
|
|
1
|
+
{"version":3,"file":"gen-conformance.js","sourceRoot":"","sources":["../src/gen-conformance.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generate the cross-implementation conformance corpus under repo-root\n * `conformance/`. The TypeScript package is the reference implementation, so\n * the goldens it emits are what the Rust crate must reproduce byte-for-byte\n * (structurally). Run via `npm run gen:conformance`; CI regenerates and asserts\n * `git diff --exit-code conformance/` is clean.\n *\n * Outputs:\n * - `conformance/normalize.json` — `[{ input, expected }]` for normalizeName.\n * - `conformance/roster/<case>/expected.roster.json` — the resolved Roster.\n * - `conformance/roster/<case>/expected.<fmt>.{txt,json}` — every export\n * target's golden output. The TS exporter is the oracle; the Rust mirror\n * asserts byte-equal output for the same Roster.\n * - `conformance/roster/<case>/input.newrecruit-{wtc-compact,wtc-full,simple}.txt`\n * — text inputs derived from the seed by the exporter, so a re-import\n * regression in either implementation surfaces immediately.\n *\n * Seeding: each `<case>/` carries one canonical input — either the legacy\n * `input.json` (ListForge) or `input.newrecruit-json.json` (NewRecruit). Other\n * inputs are derived.\n */\nimport { readdirSync, readFileSync, writeFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { Dataset } from \"./data/dataset.js\";\nimport { normalizeName } from \"./data/normalize.js\";\nimport { describeScoringCard, describeAbility, type Effect } from \"./translate/index.js\";\nimport { awardsOf } from \"./scoring/index.js\";\nimport { createRunnerState, dispatch } from \"./runner.js\";\nimport { exportRoster, type ExportFormat } from \"./export/index.js\";\nimport { importRoster, REGISTERED_ADAPTERS } from \"./import/import-roster.js\";\nimport { selectAdapter } from \"./import/adapter.js\";\nimport type { ParsedRoster, Roster } from \"./import/types.js\";\nimport { encodeBase } from \"./runner.js\";\nimport { attributeStages } from \"./cruncher/attribution.js\";\nimport type { EngineInput } from \"./cruncher/index.js\";\nimport {\n resolveLayout,\n type TerrainTemplate as ResolverTemplate,\n type TerrainLayout as ResolverLayout,\n} from \"./terrain/resolve.js\";\nimport { keystoneMeasurements, BOARD_INCHES } from \"./terrain/keystones.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst REPO_ROOT = join(__dirname, \"../..\");\nconst CONFORMANCE = join(REPO_ROOT, \"conformance\");\n\nconst NORMALIZE_INPUTS = [\n // NFD diacritic strip\n \"Khârn the Betrayer\",\n \"Brôkhyr\",\n \"Ûthar\",\n \"Magnús\",\n // apostrophe / quote variants\n \"T'au\",\n \"Be’lakor\",\n \"Kor’sarro Khan\",\n \"Aetaos'rau'keres\",\n \"‘quoted’\",\n // whitespace / hyphen collapse + trim\n \"Brôkhyr Iron-master\",\n \" the betrayer \",\n \"space--marines\",\n // casefold\n \"KHÂRN THE BETRAYER\",\n // already-normalized (idempotence)\n \"kharn the betrayer\",\n // distinctness anchors (must NOT collapse together)\n \"Khorne\",\n \"Khârn\",\n // Unicode whitespace beyond ASCII — every Unicode whitespace must collapse\n // identically across implementations or `find(\"Khorne Lord\")` and\n // `find(\"Khorne Lord\")` will silently disagree across ports.\n \"Khorne Lord\",\n \"Khorne Lord\",\n // Turkish dotted-I: NFD decomposes to `I` + combining dot above; the dot is\n // stripped, then locale-independent lowercase yields `i`. The case pins that\n // no implementation introduces locale-aware casefolding (which would map\n // `I` → `ı` under Turkish locale and break ASCII-text search).\n \"İmperial Fists\",\n // Zero-width joiner: passes through every step today. Pinned so behavior\n // does not silently change — if a future commit strips Cf-category chars,\n // this golden updates in the same PR.\n \"KhorneLord\",\n];\n\nfunction writeJson(path: string, value: unknown): void {\n writeFileSync(path, `${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction writeText(path: string, value: string): void {\n writeFileSync(path, value);\n}\n\nfunction genNormalize(): void {\n const table = NORMALIZE_INPUTS.map((input) => ({ input, expected: normalizeName(input) }));\n writeJson(join(CONFORMANCE, \"normalize.json\"), table);\n console.log(`normalize.json: ${table.length} cases`);\n}\n\n/** Locate the canonical input for a fixture dir: prefer `input.json` (legacy\n * ListForge), then `input.newrecruit-json.json` (NewRecruit), then the\n * text-only `input.gw.txt` (GW app export — import-only, like ListForge). */\nfunction seedRoster(caseDir: string, ds: Dataset): Roster {\n const decoded = decodeCanonicalSeed(caseDir);\n return importRoster(decoded, { dataset: ds });\n}\n\n/** Return the decoded payload for the canonical seed — the same value the\n * import pipeline would dispatch on. JSON seeds come back parsed; text seeds\n * come back as the raw string. */\nfunction decodeCanonicalSeed(caseDir: string): unknown {\n const jsonSeed = join(caseDir, \"input.json\");\n if (existsSync(jsonSeed)) {\n return JSON.parse(readFileSync(jsonSeed, \"utf8\"));\n }\n const nrSeed = join(caseDir, \"input.newrecruit-json.json\");\n if (existsSync(nrSeed)) {\n return JSON.parse(readFileSync(nrSeed, \"utf8\"));\n }\n const gwSeed = join(caseDir, \"input.gw.txt\");\n if (existsSync(gwSeed)) {\n return readFileSync(gwSeed, \"utf8\");\n }\n throw new Error(`no canonical input found in ${caseDir}`);\n}\n\n/** Run a decoded payload through the adapter pipeline up to (but not past)\n * resolution. The result is the format-agnostic ParsedRoster — the same\n * intermediate the resolver consumes. Pinning this layer surfaces parser\n * regressions even when resolution masks them. */\nfunction parsedFromCanonicalSeed(caseDir: string): ParsedRoster {\n const decoded = decodeCanonicalSeed(caseDir);\n const adapter = selectAdapter(decoded, [...REGISTERED_ADAPTERS]);\n return adapter.parse(decoded);\n}\n\nconst TEXT_FORMATS: { format: ExportFormat; inputName: string; goldenName: string }[] = [\n {\n format: \"newrecruit-wtc-compact\",\n inputName: \"input.newrecruit-wtc-compact.txt\",\n goldenName: \"expected.newrecruit-wtc-compact.txt\",\n },\n {\n format: \"newrecruit-wtc-full\",\n inputName: \"input.newrecruit-wtc-full.txt\",\n goldenName: \"expected.newrecruit-wtc-full.txt\",\n },\n {\n format: \"newrecruit-simple\",\n inputName: \"input.newrecruit-simple.txt\",\n goldenName: \"expected.newrecruit-simple.txt\",\n },\n];\n\nfunction genRosters(): void {\n const ds = Dataset.embedded();\n const rosterDir = join(CONFORMANCE, \"roster\");\n for (const entry of readdirSync(rosterDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const caseDir = join(rosterDir, entry.name);\n\n const seed = seedRoster(caseDir, ds);\n writeJson(join(caseDir, \"expected.roster.json\"), seed);\n\n // Parsed-stage golden — the intermediate ParsedRoster produced by the\n // adapter for the canonical seed, before resolution. Catches parser bugs\n // that resolution would otherwise mask (e.g. wrong unit count from a\n // duplicate cost line that resolves to the same unit twice).\n writeJson(join(caseDir, \"expected.parsed.json\"), parsedFromCanonicalSeed(caseDir));\n\n // JSON export golden — NewRecruit-shaped skeleton.\n const jsonOut = exportRoster(seed, \"newrecruit-json\");\n writeJson(join(caseDir, \"expected.newrecruit-json.json\"), JSON.parse(jsonOut));\n\n // Canonical Roster JSON export — should equal the resolved roster.\n writeJson(join(caseDir, \"expected.roster-json.json\"), JSON.parse(exportRoster(seed, \"roster-json\")));\n\n // Text exports: always write the export golden so every fixture exercises\n // the cross-implementation byte-equality check. Only write the\n // `input.*.txt` round-trip seed when the fixture was authored for the\n // NewRecruit pipeline — legacy ListForge fixtures carry decoration\n // (multi-force warnings, leader-attachment inference) that the simple/wtc\n // exporters can't fully preserve, so the round-trip would fail\n // structurally rather than uncover a parser bug.\n const isNewRecruitSeed = existsSync(join(caseDir, \"input.newrecruit-json.json\"));\n for (const { format, inputName, goldenName } of TEXT_FORMATS) {\n const out = exportRoster(seed, format);\n writeText(join(caseDir, goldenName), out);\n if (isNewRecruitSeed) {\n writeText(join(caseDir, inputName), out);\n }\n }\n\n // Rosterizer JSON export + a derived round-trip input. The exporter is\n // deterministic and round-trips through the adapter, so emitting it as\n // both `expected.rosterizer.json` and `input.rosterizer.json` pins the\n // cross-implementation goldens and the importer regression at the same\n // time. Same NewRecruit-seed gate as the text formats — multi-force\n // ListForge fixtures lose their provisional leader-attachment under\n // round-trip, so they only get the export golden, not the derived input.\n const rosterizerOut = exportRoster(seed, \"rosterizer\");\n writeJson(join(caseDir, \"expected.rosterizer.json\"), JSON.parse(rosterizerOut));\n if (isNewRecruitSeed) {\n writeJson(join(caseDir, \"input.rosterizer.json\"), JSON.parse(rosterizerOut));\n }\n\n console.log(\n `roster/${entry.name}: ${seed.units.length} units, ${seed.diagnostics.warnings.length} warnings`,\n );\n }\n}\n\n/**\n * Linked-API query cases. Each descriptor names a query method on Dataset, the\n * args to call it with, and how the result should be compared.\n *\n * `comparison: \"ordered\"` pins the result order — used for queries that iterate\n * a data-driven array (`unit.ability_ids`, `unit.weapon_ids`) where order is\n * encoded in the data and both implementations iterate it the same way.\n *\n * `comparison: \"set\"` pins only the set of ids — used for queries that walk an\n * index (faction → abilities, ability → phases) where iteration order depends\n * on dataset bundler internals and is incidental. Ids are sorted before\n * comparison.\n *\n * `comparison: \"scalar\"` pins a single id-or-null result (find_* and\n * faction_of(unit)).\n */\ntype LinkedApiQuery =\n | { name: string; query: \"find_unit\"; args: { query: string }; comparison: \"scalar\" }\n | { name: string; query: \"find_weapon\"; args: { query: string }; comparison: \"scalar\" }\n | { name: string; query: \"find_faction\"; args: { query: string }; comparison: \"scalar\" }\n | { name: string; query: \"find_ability\"; args: { query: string }; comparison: \"scalar\" }\n | { name: string; query: \"abilities_of\"; args: { unitId: string }; comparison: \"ordered\" }\n | { name: string; query: \"weapons_of\"; args: { unitId: string }; comparison: \"ordered\" }\n | { name: string; query: \"phases_of\"; args: { abilityId: string }; comparison: \"set\" }\n | { name: string; query: \"faction_of\"; args: { unitId: string }; comparison: \"scalar\" }\n | { name: string; query: \"abilities_of_faction\"; args: { factionId: string }; comparison: \"set\" }\n | { name: string; query: \"weapons_of_faction\"; args: { factionId: string }; comparison: \"set\" }\n | { name: string; query: \"base_size_of\"; args: { unitId: string }; comparison: \"scalar\" }\n | { name: string; query: \"model_bases_of\"; args: { unitId: string }; comparison: \"ordered\" };\n\nconst LINKED_API_QUERIES: LinkedApiQuery[] = [\n // find_unit: diacritic-insensitive lookup, miss returns null.\n { name: \"find_unit by diacritic name\", query: \"find_unit\", args: { query: \"Kharn\" }, comparison: \"scalar\" },\n { name: \"find_unit miss returns null\", query: \"find_unit\", args: { query: \"not-a-real-unit-xyz\" }, comparison: \"scalar\" },\n // find_weapon: hyphen + space tolerance.\n { name: \"find_weapon by name\", query: \"find_weapon\", args: { query: \"bolt rifle\" }, comparison: \"scalar\" },\n // find_faction: punctuation/diacritic tolerance.\n { name: \"find_faction by display name\", query: \"find_faction\", args: { query: \"World Eaters\" }, comparison: \"scalar\" },\n // find_ability: ability name lookup.\n { name: \"find_ability by name\", query: \"find_ability\", args: { query: \"Berzerker Frenzy\" }, comparison: \"scalar\" },\n // abilities_of(unit): ordered, iterates unit.ability_ids array.\n { name: \"abilities_of intercessor-squad\", query: \"abilities_of\", args: { unitId: \"intercessor-squad\" }, comparison: \"ordered\" },\n { name: \"abilities_of kharn-the-betrayer\", query: \"abilities_of\", args: { unitId: \"kharn-the-betrayer\" }, comparison: \"ordered\" },\n // weapons_of(unit): ordered, iterates unit.weapon_ids array.\n { name: \"weapons_of intercessor-squad\", query: \"weapons_of\", args: { unitId: \"intercessor-squad\" }, comparison: \"ordered\" },\n { name: \"weapons_of kharn-the-betrayer\", query: \"weapons_of\", args: { unitId: \"kharn-the-betrayer\" }, comparison: \"ordered\" },\n // phases_of(ability): compared as set (phase index iteration order is incidental).\n { name: \"phases_of berzerker-frenzy\", query: \"phases_of\", args: { abilityId: \"berzerker-frenzy\" }, comparison: \"set\" },\n // faction_of(unit): scalar id or null.\n { name: \"faction_of intercessor-squad\", query: \"faction_of\", args: { unitId: \"intercessor-squad\" }, comparison: \"scalar\" },\n // abilities_of_faction: compared as set (collection-index order is incidental).\n { name: \"abilities_of_faction world-eaters\", query: \"abilities_of_faction\", args: { factionId: \"world-eaters\" }, comparison: \"set\" },\n // weapons_of_faction: compared as set.\n { name: \"weapons_of_faction world-eaters\", query: \"weapons_of_faction\", args: { factionId: \"world-eaters\" }, comparison: \"set\" },\n // base_size_of(unit): scalar encoded base — round, oval, and a draft flying-base.\n { name: \"base_size_of intercessor-squad\", query: \"base_size_of\", args: { unitId: \"intercessor-squad\" }, comparison: \"scalar\" },\n { name: \"base_size_of vertus-praetors\", query: \"base_size_of\", args: { unitId: \"vertus-praetors\" }, comparison: \"scalar\" },\n { name: \"base_size_of windriders (draft flying base)\", query: \"base_size_of\", args: { unitId: \"windriders\" }, comparison: \"scalar\" },\n // model_bases_of(unit): ordered per-model bases; jakhals mixes 28.5mm bodies with a 40mm Dishonoured.\n { name: \"model_bases_of jakhals (mixed)\", query: \"model_bases_of\", args: { unitId: \"jakhals\" }, comparison: \"ordered\" },\n];\n\nfunction genLinkedApi(): void {\n const ds = Dataset.embedded();\n const cases = LINKED_API_QUERIES.map((q) => {\n const expected = runLinkedQuery(ds, q);\n return { ...q, expected };\n });\n writeJson(join(CONFORMANCE, \"linked-api\", \"cases.json\"), cases);\n console.log(`linked-api/cases.json: ${cases.length} cases`);\n}\n\nfunction runLinkedQuery(ds: Dataset, q: LinkedApiQuery): string | null | string[] {\n switch (q.query) {\n case \"find_unit\":\n return ds.units.find(q.args.query)?.id ?? null;\n case \"find_weapon\":\n return ds.weapons.find(q.args.query)?.id ?? null;\n case \"find_faction\":\n return ds.factions.find(q.args.query)?.id ?? null;\n case \"find_ability\":\n return ds.abilities.find(q.args.query)?.id ?? null;\n case \"abilities_of\": {\n const u = ds.units.get(q.args.unitId);\n if (!u) throw new Error(`abilities_of: unknown unit ${q.args.unitId}`);\n return u.abilities.map((a) => a.id);\n }\n case \"weapons_of\": {\n const u = ds.units.get(q.args.unitId);\n if (!u) throw new Error(`weapons_of: unknown unit ${q.args.unitId}`);\n return u.weapons.map((w) => w.id);\n }\n case \"phases_of\": {\n const a = ds.abilities.get(q.args.abilityId);\n if (!a) throw new Error(`phases_of: unknown ability ${q.args.abilityId}`);\n return [...a.phases].sort();\n }\n case \"faction_of\": {\n const u = ds.units.get(q.args.unitId);\n if (!u) throw new Error(`faction_of: unknown unit ${q.args.unitId}`);\n return u.faction?.id ?? null;\n }\n case \"abilities_of_faction\":\n return ds.abilities.byFaction(q.args.factionId).map((a) => a.id).sort();\n case \"weapons_of_faction\": {\n // Mirrors Rust `weapons_of_faction`: aggregate weapons across the\n // faction's units and dedupe by id. The collection-level\n // `weapons.byFaction()` is a different operation (it looks up weapons\n // whose own `faction_id` is set, which is empty for most factions).\n const f = ds.factions.get(q.args.factionId);\n if (!f) throw new Error(`weapons_of_faction: unknown faction ${q.args.factionId}`);\n return f.weapons.map((w) => w.id).sort();\n }\n case \"base_size_of\": {\n const u = ds.units.get(q.args.unitId);\n if (!u) throw new Error(`base_size_of: unknown unit ${q.args.unitId}`);\n return encodeBase(u.raw.base_size_mm);\n }\n case \"model_bases_of\": {\n const u = ds.units.get(q.args.unitId);\n if (!u) throw new Error(`model_bases_of: unknown unit ${q.args.unitId}`);\n const comp = ds.unitCompositions.find((c) => c.unit_id === q.args.unitId);\n return (comp?.models ?? []).map((m) => `${m.name}=${encodeBase(m.base_size_mm) ?? \"none\"}`);\n }\n }\n}\n\n/**\n * Attribution corpus: reuses the existing cruncher inputs from the cases that\n * carry at least one groupable buff (ability or manual). The expected shape\n * is the AttributedStage array produced by attributeStages; both\n * implementations of the leave-one-out decomposition must reproduce it\n * within the per-stage float tolerance.\n */\nconst ATTRIBUTION_CASE_FILES = [\n \"05-anti-infantry-vs-cultist.json\",\n \"07-twin-linked-heavy-stationary-vs-knight.json\",\n];\n\ninterface CruncherCaseInput {\n name: string;\n attacker: { weaponId: string; profileIndex: number };\n modelsFiring: number;\n target: { unitId: string; profileIndex: number; modelCount?: number };\n context: EngineInput[\"context\"];\n buffs: EngineInput[\"buffs\"];\n}\n\nfunction loadAttributionInput(ds: Dataset, filename: string): {\n name: string;\n input: EngineInput;\n} {\n const path = join(CONFORMANCE, \"cruncher\", filename);\n const c = JSON.parse(readFileSync(path, \"utf8\")) as CruncherCaseInput;\n const weapon = ds.weapons.get(c.attacker.weaponId);\n const unit = ds.units.get(c.target.unitId);\n if (!weapon) throw new Error(`attribution: unknown weapon ${c.attacker.weaponId}`);\n if (!unit) throw new Error(`attribution: unknown unit ${c.target.unitId}`);\n return {\n name: c.name,\n input: {\n attacker: { weapon: weapon.raw, profileIndex: c.attacker.profileIndex },\n target: {\n unit: unit.raw,\n profileIndex: c.target.profileIndex,\n ...(c.target.modelCount !== undefined ? { modelCount: c.target.modelCount } : {}),\n },\n modelsFiring: c.modelsFiring,\n buffs: c.buffs,\n context: c.context,\n },\n };\n}\n\nfunction genAttribution(): void {\n const ds = Dataset.embedded();\n const cases = ATTRIBUTION_CASE_FILES.map((filename, idx) => {\n const { name, input } = loadAttributionInput(ds, filename);\n const stages = attributeStages(input, ds);\n return {\n // Persist the input by file reference so the corpus stays a single\n // source of truth — the cruncher case file already pins the EngineInput.\n name,\n cruncher_case: filename,\n expected: stages.map((s) => ({\n name: s.name,\n expected: s.expected,\n baseline: s.baseline,\n lifts: s.lifts.map((l) => ({ source: l.source, delta: l.delta })),\n residual: s.residual,\n intrinsics: s.intrinsics,\n })),\n // Stable ordering of cases in the corpus file.\n _order: idx,\n };\n });\n // Sort by _order and strip the helper before writing.\n cases.sort((a, b) => a._order - b._order);\n const serialised = cases.map(({ _order: _o, ...rest }) => rest);\n writeJson(join(CONFORMANCE, \"attribution\", \"cases.json\"), serialised);\n console.log(`attribution/cases.json: ${cases.length} cases`);\n}\n\n/**\n * Scoring-card translation corpus: humanize each primary mission card's\n * `awards` into plain English. The TS translator is the oracle; the Rust port\n * must reproduce every string byte-for-byte (the differ compares structurally,\n * no tolerance). Only `card_type: \"primary\"` cards are pinned — the 14-card\n * secondary deck isn't revealed yet. Cases are sorted by id for stability, and\n * the `awards` array order within each card is load-bearing.\n */\nfunction genScoringTranslation(): void {\n const ds = Dataset.embedded();\n mkdirSync(join(CONFORMANCE, \"scoring-translation\"), { recursive: true });\n // Pin the translation of every mission card's awards — primary and secondary\n // alike (the secondary deck has the same `awards` shape and deserves the same\n // cross-impl pinning).\n const cases = ds.missionCards.all\n .filter((c) => c.card_type === \"primary\" || c.card_type === \"secondary\")\n .slice()\n .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))\n .map((card) => ({ cardId: card.id, expected: { awards: describeScoringCard(card) } }));\n writeJson(join(CONFORMANCE, \"scoring-translation\", \"cases.json\"), cases);\n console.log(`scoring-translation/cases.json: ${cases.length} cases`);\n}\n\n/**\n * Scoring-engine corpus: pin the pure VP arithmetic of the scoring engine\n * (`tools/src/scoring/` — the oracle) so the Rust `wh40kdc::scoring` port\n * reproduces it. Three ops, each case `{ name, op, args, expected }`:\n *\n * - `score_event` — per card and approach, assert every award matching the\n * approach (by its full-`awards`-array index). Pins `scoreAward`, `scoreTurn`\n * (exclusive-group \"highest only\", `vp_per × count` clamped to `per_max`,\n * cumulative sums), `scoreCap` (tactical 5 vs fixed `vp_max`/uncapped), and\n * `scoreSecondaryEvent`; primary cards also carry a `roundCap` to pin\n * `scorePrimaryEvent`. `cap: null` means uncapped (Infinity has no JSON form).\n * - `score_state` — replay scenarios over a `PlayerGame`, pinning the per-round\n * cap (15), per-game primary cap (45), grand-total cap (100), score+discard,\n * and undo.\n * - `wtc_result` — the 20-point band mapping across its boundaries.\n *\n * Goldens are produced by driving the TS runner's own `dispatch`, so the corpus\n * and the runner agree by construction; the cross-impl contract is the Rust\n * runner reproducing them. Integers are compared exactly (no tolerance).\n */\nfunction genScoring(): void {\n const ds = Dataset.embedded();\n mkdirSync(join(CONFORMANCE, \"scoring\"), { recursive: true });\n\n // One initialized runner state, reused across cases (the ops don't mutate it).\n const specVersion = Number.parseInt(\n readFileSync(join(CONFORMANCE, \"SPEC_VERSION\"), \"utf8\").trim(),\n 10,\n );\n const state = createRunnerState();\n const init = dispatch(state, {\n op: \"init\",\n args: { spec_version: specVersion, locale: \"C\", tz: \"UTC\", seed: 0 },\n });\n if (!init.ok) throw new Error(`gen scoring: init failed: ${JSON.stringify(init)}`);\n const run = (op: string, args: unknown): unknown => {\n const r = dispatch(state, { op, args });\n if (!r.ok) throw new Error(`gen scoring: ${op} failed: ${JSON.stringify(r)} for ${JSON.stringify(args)}`);\n return r.value;\n };\n\n type Case = { name: string; op: string; args: unknown; expected: unknown };\n const cases: Case[] = [];\n\n // score_event: every mission card, both approaches. Assert the approach's\n // awards by their full-array index; count vp_per awards to their per_max\n // (else 2) so the cap logic actually bites.\n const cards = ds.missionCards.all\n .slice()\n .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));\n for (const card of cards) {\n for (const approach of [\"fixed\", \"tactical\"] as const) {\n const asserted = awardsOf(card)\n .map((aw, index) => ({ aw, index }))\n .filter(({ aw }) => aw.mode == null || aw.mode === approach)\n .map(({ aw, index }) =>\n aw.vp_per != null ? { index, count: aw.per_max ?? 2 } : { index },\n );\n const args: Record<string, unknown> = { cardId: card.id, approach, asserted };\n if (card.card_type === \"primary\") args.roundCap = 15;\n cases.push({\n name: `score_event/${card.id}/${approach}`,\n op: \"score_event\",\n args,\n expected: run(\"score_event\", args),\n });\n }\n }\n\n // score_state: hand-authored replay scenarios. Card ids are real deck/mission\n // cards; expected state is whatever the engine produces.\n const stateScenarios: { name: string; args: unknown }[] = [\n {\n name: \"primary-round-and-game-caps\",\n args: {\n approach: \"tactical\",\n ops: [\n { kind: \"set-primary\", round: 1, vp: 30, roundCap: 15, gameCap: 45 },\n { kind: \"set-primary\", round: 2, vp: 30, roundCap: 15, gameCap: 45 },\n { kind: \"set-primary\", round: 3, vp: 30, roundCap: 15, gameCap: 45 },\n { kind: \"set-primary\", round: 4, vp: 30, roundCap: 15, gameCap: 45 },\n ],\n },\n },\n {\n // The full primary path: a card's raw round total, clamped to the round\n // cap on store, then cleared back to 0 by a set-primary 0.\n name: \"score-primary-then-clear\",\n args: {\n approach: \"tactical\",\n ops: [\n {\n kind: \"score-primary\",\n cardId: \"battlefield-dominance\",\n round: 2,\n asserted: awardsOf(ds.missionCards.get(\"battlefield-dominance\")!).map((aw, index) =>\n aw.vp_per != null ? { index, count: aw.per_max ?? 3 } : { index },\n ),\n roundCap: 15,\n gameCap: 45,\n },\n { kind: \"set-primary\", round: 3, vp: 99, roundCap: 15, gameCap: 45 },\n { kind: \"set-primary\", round: 2, vp: 0, roundCap: 15, gameCap: 45 },\n ],\n },\n },\n {\n name: \"secondary-score-and-undo\",\n args: {\n approach: \"tactical\",\n ops: [\n { kind: \"draw\", cardId: \"no-prisoners\" },\n { kind: \"score-secondary\", cardId: \"no-prisoners\", round: 2, asserted: [{ index: 0, count: 3 }] },\n { kind: \"remove-score\", index: 0 },\n ],\n },\n },\n {\n // Uncapped set-primary (no caps) overshoots so the 100 grand-total cap bites.\n name: \"grand-total-cap-at-100\",\n args: {\n approach: \"tactical\",\n ops: [\n { kind: \"set-primary\", round: 1, vp: 30 },\n { kind: \"set-primary\", round: 2, vp: 30 },\n { kind: \"set-primary\", round: 3, vp: 30 },\n { kind: \"set-primary\", round: 4, vp: 30 },\n { kind: \"set-primary\", round: 5, vp: 30 },\n { kind: \"draw\", cardId: \"no-prisoners\" },\n { kind: \"score-secondary\", cardId: \"no-prisoners\", round: 5, asserted: [{ index: 0, count: 99 }] },\n ],\n },\n },\n ];\n for (const s of stateScenarios) {\n cases.push({ name: `score_state/${s.name}`, op: \"score_state\", args: s.args, expected: run(\"score_state\", s.args) });\n }\n\n // wtc_result: band boundaries and symmetry.\n const wtcPairs: [number, number][] = [\n [50, 50],\n [48, 45],\n [45, 50],\n [56, 50],\n [50, 61],\n [100, 50],\n [100, 49],\n [0, 100],\n [60, 40],\n [55, 50],\n ];\n for (const [a, b] of wtcPairs) {\n const args = { a, b };\n cases.push({ name: `wtc_result/${a}-${b}`, op: \"wtc_result\", args, expected: run(\"wtc_result\", args) });\n }\n\n writeJson(join(CONFORMANCE, \"scoring\", \"cases.json\"), cases);\n console.log(`scoring/cases.json: ${cases.length} cases`);\n}\n\n/**\n * Terrain-resolver corpus: resolve template-anchored layouts to absolute\n * board-space vertices (y-down inches). The TS resolver is the oracle; the Rust\n * port must reproduce every vertex within 5e-4 (per-area invariant in\n * CONFORMANCE.md). Cases are self-contained — each carries its own `templates`\n * and `layout` — so the corpus does not depend on the bundled catalog and the\n * runner op can pass both in `args`. Coverage: per-template centroid anchoring\n * (identity), cardinal + oblique rotations, both mirror axes on an asymmetric\n * shape, embedded-feature composition, explicit parenting, and the inline\n * footprint escape hatch.\n */\nfunction genTerrainResolver(): void {\n mkdirSync(join(CONFORMANCE, \"terrain-resolver\"), { recursive: true });\n\n const areaLarge: ResolverTemplate = {\n id: \"area-large\",\n name: \"Large Area\",\n kind: \"area\",\n footprint: { type: \"rectangle\", width: 11.5, height: 7 },\n };\n const areaMedium: ResolverTemplate = {\n id: \"area-medium\",\n name: \"Medium Area\",\n kind: \"area\",\n footprint: { type: \"rectangle\", width: 6, height: 4 },\n };\n const areaTrapezoid: ResolverTemplate = {\n id: \"area-trapezoid\",\n name: \"Trapezoid Area\",\n kind: \"area\",\n footprint: {\n type: \"polygon\",\n points: [\n { x: 0, y: 0 },\n { x: 8, y: 0 },\n { x: 2, y: 11.5 },\n { x: 0, y: 11.5 },\n ],\n },\n };\n const wedge: ResolverTemplate = {\n id: \"wedge\",\n name: \"Right Wedge\",\n kind: \"area\",\n footprint: { type: \"right-triangle\", width: 8, height: 11.5 },\n };\n const wallLong: ResolverTemplate = {\n id: \"wall-long\",\n name: \"Long Wall\",\n kind: \"feature\",\n footprint: { type: \"rectangle\", width: 7, height: 0.25 },\n };\n const ruinComposed: ResolverTemplate = {\n id: \"ruin-composed\",\n name: \"Composed Ruin\",\n kind: \"area\",\n footprint: { type: \"rectangle\", width: 11.5, height: 7 },\n features: [\n { id: \"back-wall\", template: \"wall-long\", position: { x: 0, y: -3 } },\n { id: \"side-wall\", template: \"wall-long\", position: { x: -5, y: 0 }, rotation_degrees: 90, mirror: \"horizontal\" },\n ],\n };\n\n const baseCatalog = [areaLarge, areaMedium, areaTrapezoid, wedge, wallLong];\n\n const layoutCases: { name: string; templates: ResolverTemplate[]; layout: ResolverLayout }[] = [\n {\n name: \"identity-large\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-large\", position: { x: 30, y: 22 } }] },\n },\n {\n name: \"identity-wedge\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"wedge\", position: { x: 12, y: 30 } }] },\n },\n {\n name: \"identity-trapezoid\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-trapezoid\", position: { x: 40, y: 18 } }] },\n },\n {\n name: \"rotate-medium-90\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-medium\", position: { x: 30, y: 22 }, rotation_degrees: 90 }] },\n },\n {\n name: \"rotate-medium-180\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-medium\", position: { x: 30, y: 22 }, rotation_degrees: 180 }] },\n },\n {\n name: \"rotate-medium-270\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-medium\", position: { x: 30, y: 22 }, rotation_degrees: 270 }] },\n },\n {\n name: \"rotate-large-oblique-55\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-large\", position: { x: 30, y: 22 }, rotation_degrees: 55 }] },\n },\n {\n name: \"rotate-trapezoid-oblique-235\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-trapezoid\", position: { x: 35.75, y: 27 }, rotation_degrees: 235 }] },\n },\n {\n name: \"mirror-trapezoid-horizontal\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-trapezoid\", position: { x: 40, y: 18 }, mirror: \"horizontal\" }] },\n },\n {\n name: \"mirror-trapezoid-vertical-rot90\",\n templates: baseCatalog,\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"p\", template: \"area-trapezoid\", position: { x: 40, y: 18 }, rotation_degrees: 90, mirror: \"vertical\" }] },\n },\n {\n name: \"composition-ruin-rot90-mirror-h\",\n templates: [ruinComposed, wallLong],\n layout: { id: \"c\", name: \"c\", pieces: [{ id: \"a1\", template: \"ruin-composed\", position: { x: 30, y: 22 }, rotation_degrees: 90, mirror: \"horizontal\" }] },\n },\n {\n name: \"explicit-parent-feature\",\n templates: [areaLarge, wallLong],\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n { id: \"a1\", template: \"area-large\", position: { x: 30, y: 22 }, rotation_degrees: 90, mirror: \"horizontal\" },\n { id: \"back-wall\", template: \"wall-long\", parent_area_id: \"a1\", position: { x: 0, y: -3 } },\n ],\n },\n },\n {\n name: \"inline-footprint-polygon\",\n templates: [],\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n footprint: { type: \"polygon\", points: [{ x: 0, y: 0 }, { x: 4, y: 0 }, { x: 2, y: 5 }] },\n position: { x: 50, y: 40 },\n rotation_degrees: 30,\n },\n ],\n },\n },\n ];\n\n const cases = layoutCases.map((c) => ({\n name: c.name,\n templates: c.templates,\n layout: c.layout,\n expected: { pieces: resolveLayout(c.layout, c.templates) },\n }));\n writeJson(join(CONFORMANCE, \"terrain-resolver\", \"cases.json\"), cases);\n console.log(`terrain-resolver/cases.json: ${cases.length} cases`);\n}\n\n/**\n * Terrain-keystones corpus: derive the printed distance of each authored\n * keystone (board edge → piece feature) from resolved geometry. The TS helper\n * is the oracle; the Rust port must reproduce every distance within 5e-4.\n * Cases are self-contained like the resolver corpus. Coverage: all four\n * edges, vertex and bounding-face refs, an oblique rotation, a mirrored\n * asymmetric shape, a parented feature (composition through the parent\n * frame), an inline footprint, and a custom board size.\n */\nfunction genTerrainKeystones(): void {\n mkdirSync(join(CONFORMANCE, \"terrain-keystones\"), { recursive: true });\n\n const areaLarge: ResolverTemplate = {\n id: \"area-large\",\n name: \"Large Area\",\n kind: \"area\",\n footprint: { type: \"rectangle\", width: 11.5, height: 7 },\n };\n const areaTrapezoid: ResolverTemplate = {\n id: \"area-trapezoid\",\n name: \"Trapezoid Area\",\n kind: \"area\",\n footprint: {\n type: \"polygon\",\n points: [\n { x: 0, y: 0 },\n { x: 8, y: 0 },\n { x: 2, y: 11.5 },\n { x: 0, y: 11.5 },\n ],\n },\n };\n const wallLong: ResolverTemplate = {\n id: \"wall-long\",\n name: \"Long Wall\",\n kind: \"feature\",\n footprint: { type: \"rectangle\", width: 7, height: 0.25 },\n };\n const catalog = [areaLarge, areaTrapezoid, wallLong];\n\n const keystoneCases: {\n name: string;\n templates: ResolverTemplate[];\n layout: ResolverLayout;\n board?: { width: number; height: number };\n }[] = [\n {\n name: \"identity-four-edges-vertices\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n template: \"area-large\",\n position: { x: 30, y: 22 },\n keystones: [\n { edge: \"left\", ref: { kind: \"vertex\", index: 0 } },\n { edge: \"top\", ref: { kind: \"vertex\", index: 1 } },\n { edge: \"right\", ref: { kind: \"vertex\", index: 2 } },\n { edge: \"bottom\", ref: { kind: \"vertex\", index: 3 } },\n ],\n },\n ],\n },\n },\n {\n name: \"identity-bounding-faces\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n template: \"area-large\",\n position: { x: 20, y: 30 },\n keystones: [\n { edge: \"left\", ref: { kind: \"face\", side: \"min-x\" } },\n { edge: \"right\", ref: { kind: \"face\", side: \"max-x\" } },\n { edge: \"top\", ref: { kind: \"face\", side: \"min-y\" } },\n { edge: \"bottom\", ref: { kind: \"face\", side: \"max-y\" } },\n ],\n },\n ],\n },\n },\n {\n name: \"oblique-rotation-vertex\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n template: \"area-trapezoid\",\n position: { x: 35.75, y: 27 },\n rotation_degrees: 235,\n keystones: [\n { edge: \"left\", ref: { kind: \"vertex\", index: 2 } },\n { edge: \"bottom\", ref: { kind: \"face\", side: \"max-y\" } },\n ],\n },\n ],\n },\n },\n {\n name: \"mirrored-trapezoid-vertex\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n template: \"area-trapezoid\",\n position: { x: 40, y: 18 },\n mirror: \"horizontal\",\n keystones: [\n { edge: \"right\", ref: { kind: \"vertex\", index: 1 } },\n { edge: \"top\", ref: { kind: \"vertex\", index: 0 } },\n ],\n },\n ],\n },\n },\n {\n name: \"parented-feature-keystone\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"a1\",\n template: \"area-large\",\n position: { x: 30, y: 22 },\n rotation_degrees: 90,\n mirror: \"horizontal\",\n keystones: [{ edge: \"left\", ref: { kind: \"vertex\", index: 0 } }],\n },\n {\n id: \"back-wall\",\n template: \"wall-long\",\n parent_area_id: \"a1\",\n position: { x: 0, y: -3 },\n keystones: [\n { edge: \"top\", ref: { kind: \"vertex\", index: 1 } },\n { edge: \"right\", ref: { kind: \"face\", side: \"max-x\" } },\n ],\n },\n ],\n },\n },\n {\n name: \"inline-footprint-keystone\",\n templates: [],\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n footprint: { type: \"polygon\", points: [{ x: 0, y: 0 }, { x: 4, y: 0 }, { x: 2, y: 5 }] },\n position: { x: 50, y: 40 },\n rotation_degrees: 30,\n keystones: [\n { edge: \"right\", ref: { kind: \"vertex\", index: 0 } },\n { edge: \"bottom\", ref: { kind: \"vertex\", index: 2 } },\n ],\n },\n ],\n },\n },\n {\n name: \"custom-board-extents\",\n templates: catalog,\n layout: {\n id: \"c\",\n name: \"c\",\n pieces: [\n {\n id: \"p\",\n template: \"area-large\",\n position: { x: 15, y: 15 },\n keystones: [\n { edge: \"right\", ref: { kind: \"face\", side: \"max-x\" } },\n { edge: \"bottom\", ref: { kind: \"face\", side: \"max-y\" } },\n ],\n },\n ],\n },\n board: { width: 30, height: 22.4 },\n },\n ];\n\n const cases = keystoneCases.map((c) => ({\n name: c.name,\n templates: c.templates,\n layout: c.layout,\n ...(c.board ? { board: c.board } : {}),\n expected: {\n measurements: keystoneMeasurements(c.layout, c.templates, c.board ?? BOARD_INCHES),\n },\n }));\n writeJson(join(CONFORMANCE, \"terrain-keystones\", \"cases.json\"), cases);\n console.log(`terrain-keystones/cases.json: ${cases.length} cases`);\n}\n\n/**\n * Effect-translation corpus: pin the Ability-DSL effect describer\n * (`describeEffect`/`describeAbility` — the \"ability.print()\") across the TS\n * and Rust ports. Cases embed the raw `effect` (+ `scope`) so parity does not\n * depend on collection dup-id resolution; selection greedily covers every\n * effect node type at least once (up to 5 exemplars per type) over the\n * id-sorted ability list, so the corpus stays small but exhaustive by shape.\n */\nfunction genEffectTranslation(): void {\n const ds = Dataset.embedded();\n mkdirSync(join(CONFORMANCE, \"effect-translation\"), { recursive: true });\n\n const collectTypes = (e: unknown, out: Set<string>): void => {\n if (Array.isArray(e)) {\n for (const v of e) collectTypes(v, out);\n return;\n }\n if (typeof e !== \"object\" || e === null) return;\n const rec = e as Record<string, unknown>;\n if (typeof rec.type === \"string\") out.add(rec.type);\n for (const key of [\"effect\", \"on_success\", \"on_fail\", \"steps\", \"options\", \"condition\"]) {\n if (key in rec) collectTypes(rec[key], out);\n }\n };\n\n const abilities = ds.abilities.all\n .slice()\n .sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));\n\n const seen = new Map<string, number>();\n const CAP = 5;\n const cases: unknown[] = [];\n for (const a of abilities) {\n const types = new Set<string>();\n collectTypes(a.raw.effect, types);\n let fresh = false;\n for (const t of types) {\n if ((seen.get(t) ?? 0) < CAP) fresh = true;\n }\n if (!fresh) continue;\n for (const t of types) seen.set(t, (seen.get(t) ?? 0) + 1);\n cases.push({\n caseId: `${a.id}#${cases.length}`,\n effect: a.raw.effect,\n scope: a.raw.scope ?? null,\n expected: { text: describeAbility({ effect: a.raw.effect as Effect, scope: a.raw.scope }) },\n });\n }\n writeJson(join(CONFORMANCE, \"effect-translation\", \"cases.json\"), cases);\n console.log(`effect-translation/cases.json: ${cases.length} cases (${seen.size} node types)`);\n}\n\ngenNormalize();\ngenRosters();\ngenLinkedApi();\ngenAttribution();\ngenScoringTranslation();\ngenEffectTranslation();\ngenScoring();\ngenTerrainResolver();\ngenTerrainKeystones();\n"]}
|
package/dist/generated.d.ts
CHANGED
|
@@ -662,7 +662,7 @@ export interface ArmyCompositionPredicate1 {
|
|
|
662
662
|
* via the `definition` "simple-condition".
|
|
663
663
|
*/
|
|
664
664
|
export interface SimpleCondition {
|
|
665
|
-
type: "phase-is" | "timing-is" | "player-turn-is" | "unit-below-starting-strength" | "unit-below-half-strength" | "unit-has-keyword" | "unit-within-range-of" | "model-is-leader" | "target-has-keyword" | "charged-this-turn" | "advanced-this-turn" | "remained-stationary" | "is-battle-shocked" | "has-lost-wounds" | "opponent-unit-within-range" | "within-range-of-objective" | "attack-is-type" | "has-fought-this-phase" | "destroyed-by-attack-type" | "controls-objective" | "is-attached" | "terrain-area-control" | "engagement-state" | "territory-control" | "fights-first" | "disposition-matches" | "units-destroyed" | "units-destroyed-comparison" | "objective-majority" | "action-completed" | "objective-has-tag" | "unit-has-tag" | "terrain-has-tag" | "new-objective-controlled" | "engagement-fronts" | "destroyed-while-on-objective" | "destroyed-in-tagged-terrain" | "operation-markers";
|
|
665
|
+
type: "phase-is" | "timing-is" | "player-turn-is" | "unit-below-starting-strength" | "unit-below-half-strength" | "unit-has-keyword" | "unit-within-range-of" | "model-is-leader" | "target-has-keyword" | "charged-this-turn" | "advanced-this-turn" | "remained-stationary" | "is-battle-shocked" | "has-lost-wounds" | "was-hit-by-attack" | "opponent-unit-within-range" | "within-range-of-objective" | "attack-is-type" | "has-fought-this-phase" | "destroyed-by-attack-type" | "controls-objective" | "is-attached" | "terrain-area-control" | "engagement-state" | "territory-control" | "fights-first" | "disposition-matches" | "units-destroyed" | "units-destroyed-comparison" | "objective-majority" | "action-completed" | "objective-has-tag" | "unit-has-tag" | "terrain-has-tag" | "new-objective-controlled" | "engagement-fronts" | "destroyed-while-on-objective" | "destroyed-in-tagged-terrain" | "operation-markers";
|
|
666
666
|
parameters?: {
|
|
667
667
|
[k: string]: unknown;
|
|
668
668
|
};
|