@alpaca-software/40kdc-data 1.1.2 → 1.1.3
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/gen-conformance.js +63 -0
- package/dist/gen-conformance.js.map +1 -1
- package/dist/translate/condition.d.ts.map +1 -1
- package/dist/translate/condition.js +13 -6
- package/dist/translate/condition.js.map +1 -1
- package/dist/translate/effect.d.ts.map +1 -1
- package/dist/translate/effect.js +36 -13
- package/dist/translate/effect.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"condition.d.ts","sourceRoot":"","sources":["../../src/translate/condition.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC;IAChC,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,kFAAkF;AAClF,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAsED,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAStD;AAyED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGlD;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"condition.d.ts","sourceRoot":"","sources":["../../src/translate/condition.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC;IAChC,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,kFAAkF;AAClF,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAsED,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAStD;AAyED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGlD;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAwPtD"}
|
|
@@ -184,8 +184,15 @@ export function describeCondition(c) {
|
|
|
184
184
|
return `${negate}during the ${str(p.phase)} phase`;
|
|
185
185
|
case "timing-is":
|
|
186
186
|
return `${negate}${describeTiming(p.timing)}`;
|
|
187
|
-
case "player-turn-is":
|
|
188
|
-
|
|
187
|
+
case "player-turn-is": {
|
|
188
|
+
const t = str(p.turn);
|
|
189
|
+
const phrase = t === "your-turn" || t === "your" || t === "own"
|
|
190
|
+
? "your"
|
|
191
|
+
: t === "opponent-turn" || t === "opponent"
|
|
192
|
+
? "the opponent's"
|
|
193
|
+
: "either player's";
|
|
194
|
+
return `${negate}in ${phrase} turn`;
|
|
195
|
+
}
|
|
189
196
|
case "charged-this-turn":
|
|
190
197
|
return `${negate}the unit charged this turn`;
|
|
191
198
|
case "advanced-this-turn":
|
|
@@ -231,10 +238,10 @@ export function describeCondition(c) {
|
|
|
231
238
|
where = `range of ${dekebab(str(p.weapon_name))}`;
|
|
232
239
|
else if (p.range_multiplier != null)
|
|
233
240
|
where = "half range of its ranged weapons";
|
|
234
|
-
else
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
241
|
+
else {
|
|
242
|
+
const range = p.range ?? p.range_inches ?? p.within_inches;
|
|
243
|
+
where = range === "engagement" ? "engagement range" : `${str(range)}"`;
|
|
244
|
+
}
|
|
238
245
|
return `${negate}an enemy unit is within ${where}`;
|
|
239
246
|
}
|
|
240
247
|
case "unit-within-range-of": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"condition.js","sourceRoot":"","sources":["../../src/translate/condition.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Humanize an Ability-DSL / scoring `condition` into plain English.\n *\n * Shared by the ability-text CLI (`commands/translate.ts`) and the scoring-card\n * translator (`scoring.ts`). Output is **ASCII-only** with a fixed clause and\n * parameter order: it is pinned byte-for-byte across the TS and Rust ports by\n * the `conformance/scoring-translation` corpus, so any phrasing change here is a\n * semantic corpus change (bump `conformance/SPEC_VERSION`).\n */\n\n/**\n * Minimal structural view of a condition node. Matches both the ability-dsl\n * condition schema and the `secondary-card` award `when` field (a simple node\n * carries `type` + `parameters` + `negated`; a compound node carries\n * `operator` + `operands`).\n */\nexport interface Condition {\n type?: string;\n operator?: \"and\" | \"or\" | \"not\";\n operands?: Condition[];\n parameters?: Record<string, unknown>;\n negated?: boolean;\n}\n\n/** kebab-case → space-separated words (`enemy-territory` → `enemy territory`). */\nexport function dekebab(s: string): string {\n return s.replace(/-/g, \" \");\n}\n\nfunction str(v: unknown): string {\n if (v == null) return \"?\";\n return typeof v === \"string\" ? v : String(v);\n}\n\n/**\n * A `timing-is` event token → natural GW-voice clause (\"each time a model in\n * this unit is destroyed\", \"at the start of the phase\"). Structural phase/turn\n * markers and the common trigger families are mapped explicitly; the fallback\n * routes `after-*`/`on-*` prefixes to \"after …\"/\"when …\" (so the old \"at on …\"\n * double-preposition can't occur) and everything else to \"at <event>\".\n */\n/**\n * Legacy `timing-is` strings → canonical `game-event` (Batch C unification). Data\n * is being canonicalized onto these targets; the alias map keeps un-migrated\n * strings rendering identically via the one vocabulary (`eventClause`).\n */\nconst TIMING_ALIASES: Record<string, string> = {\n advance: \"advances\",\n \"after-attacks\": \"after-unit-resolves-attacks\",\n \"after-attacking-unit-finishes-attacks\": \"after-unit-resolves-attacks\",\n \"after-shooting\": \"after-unit-resolves-attacks\",\n \"after-unit-shot\": \"after-unit-resolves-attacks\",\n \"after-unit-has-shot\": \"after-unit-resolves-attacks\",\n \"after-this-model-has-shot\": \"after-unit-resolves-attacks\",\n \"after-shot-hits-scored\": \"after-scoring-hit\",\n \"deep-strike\": \"deep-strike-setup\",\n end: \"end-of-turn\",\n start: \"start-of-turn\",\n \"fall-back\": \"falls-back\",\n \"model-destroyed\": \"on-model-destroyed\",\n \"on-destroyed\": \"on-unit-destroyed\",\n \"before-this-model-removed\": \"before-bearer-removed\",\n \"command-phase\": \"start-of-command-phase\",\n \"reinforcements-step\": \"reinforcements\",\n setup: \"unit-set-up\",\n \"set-up-this-turn\": \"unit-set-up\",\n \"after-move-through-terrain-over-4-inches\": \"moved-through-terrain\",\n \"after-moving-through-tall-terrain\": \"moved-through-terrain\",\n \"when-this-unit-selected-to-shoot\": \"selected-to-shoot\",\n};\n\n/**\n * Timing strings with no canonical `game-event` equivalent but an established\n * phrase: usage markers (which a future pass may move to the `usage` block) and\n * a couple of phase/state gates. Everything else degrades via the heuristics.\n */\nconst TIMING_ONLY_PHRASES: Record<string, string> = {\n \"once-per-battle\": \"once per battle\",\n \"once-per-phase\": \"once per phase\",\n \"once-per-opponent-turn\": \"once per opponent's turn\",\n \"first-this-battle\": \"the first time this battle\",\n \"first-time-this-phase\": \"the first time this phase\",\n \"in-reserves\": \"while it is in Reserves\",\n \"shooting-phase\": \"in the Shooting phase\",\n \"start-of-fight-phase\": \"at the start of the Fight phase\",\n \"first-movement-phase\": \"in your first Movement phase\",\n \"start-of-first-battle-round\": \"at the start of the first battle round\",\n \"start-of-movement-phase\": \"at the start of the Movement phase\",\n \"shooting-or-fight-phase\": \"in the Shooting or Fight phase\",\n \"this-model-starts-or-ends-a-move\": \"each time this model starts or ends a move\",\n \"end-of-normal-move\": \"when the unit ends a Normal move\",\n \"friendly-unit-empowered-within-9\":\n 'each time you spend 1 Pain token to Empower a friendly unit within 9\" of this unit',\n \"enemy-unit-fails-battle-shock\": \"each time an enemy unit fails a Battle-shock test\",\n \"enemy-unit-destroyed\": \"each time an enemy unit is destroyed\",\n};\n\nexport function describeTiming(timing: unknown): string {\n const t = str(timing);\n if (TIMING_ONLY_PHRASES[t]) return TIMING_ONLY_PHRASES[t];\n const canon = TIMING_ALIASES[t] ?? t;\n if (EVENT_PHRASES[canon]) return EVENT_PHRASES[canon];\n if (t.startsWith(\"after-\")) return `after ${dekebab(t.slice(6))}`;\n if (t.startsWith(\"on-\")) return `when ${dekebab(t.slice(3))}`;\n if (t.endsWith(\"-destroyed\")) return `each time ${dekebab(t)}`;\n return `at ${dekebab(t)}`;\n}\n\n/** `2` + `objective` → `2+ objectives`. Nouns here are all regular plurals. */\nfunction count(n: unknown, noun: string): string {\n return `${str(n)}+ ${noun}s`;\n}\n\n/**\n * Canonical `game-event` token → natural clause, for the reactive `trigger.event`.\n * This is the unified event vocabulary; the `timing-is` condition will be\n * canonicalized onto the same keys. Unmapped events degrade to `when <dekebab>`.\n */\nconst EVENT_PHRASES: Record<string, string> = {\n \"start-of-phase\": \"at the start of the phase\",\n \"end-of-phase\": \"at the end of the phase\",\n \"start-of-turn\": \"at the start of the turn\",\n \"end-of-turn\": \"at the end of the turn\",\n \"start-of-opponent-turn\": \"at the start of the opponent's turn\",\n \"end-of-opponent-turn\": \"at the end of the opponent's turn\",\n \"start-of-battle-round\": \"at the start of the battle round\",\n \"start-of-battle\": \"at the start of the battle\",\n \"army-selection\": \"when you select this model to include in your army\",\n \"start-of-command-phase\": \"at the start of the Command phase\",\n \"declare-battle-formations\": \"when declaring Battle Formations\",\n \"post-deployment\": \"after deployment\",\n \"unit-set-up\": \"when the unit is set up\",\n \"set-up-from-reserves\": \"when the unit arrives from Reserves\",\n \"arrives-from-strategic-reserves\": \"when the unit arrives from Strategic Reserves\",\n \"starts-in-strategic-reserves\": \"if the unit starts in Strategic Reserves\",\n \"game-start-in-reserves\": \"if the unit begins the battle in Reserves\",\n \"deep-strike-setup\": \"when the unit is set up by Deep Strike\",\n \"reinforcements\": \"when the unit arrives as Reinforcements\",\n \"normal-move\": \"when the unit makes a Normal move\",\n \"advance-move\": \"when the unit makes an Advance move\",\n advances: \"when the unit Advances\",\n \"fall-back-move\": \"when the unit makes a Fall Back move\",\n \"falls-back\": \"when the unit Falls Back\",\n \"charge-move\": \"when the unit makes a Charge move\",\n \"moved-through-terrain\": \"when the unit moves through terrain\",\n \"enemy-unit-ended-move\": \"an enemy unit ends a move\",\n \"enemy-unit-fell-back\": \"an enemy unit Falls Back\",\n \"before-hit-roll\": \"before a Hit roll is made\",\n \"after-hit-roll\": \"after a Hit roll is made\",\n \"before-wound-roll\": \"before a Wound roll is made\",\n \"after-wound-roll\": \"after a Wound roll is made\",\n \"before-save-roll\": \"before a saving throw is made\",\n \"after-save-roll\": \"after a saving throw is made\",\n \"before-damage-roll\": \"before a Damage roll is made\",\n \"after-damage-roll\": \"after a Damage roll is made\",\n \"before-charge-roll\": \"before a Charge roll is made\",\n \"after-charge-roll\": \"after a Charge roll is made\",\n \"before-advance-roll\": \"before an Advance roll is made\",\n \"after-advance-roll\": \"after an Advance roll is made\",\n \"before-battle-shock\": \"before a Battle-shock test\",\n \"after-battle-shock\": \"after a Battle-shock test\",\n \"on-unit-selected\": \"when the unit is selected\",\n \"selected-to-shoot\": \"when the unit is selected to shoot\",\n \"selected-to-fight\": \"when the unit is selected to fight\",\n \"selected-to-advance\": \"when the unit is selected to Advance\",\n \"after-unit-resolves-attacks\": \"after the unit resolves its attacks\",\n \"after-scoring-hit\": \"after scoring a hit\",\n \"after-enemy-unit-fires\": \"after an enemy unit shoots\",\n \"on-unit-destroyed\": \"when the unit is destroyed\",\n \"on-model-destroyed\": \"when a model in the unit is destroyed\",\n \"first-model-destroyed\": \"the first time a model in the unit is destroyed\",\n \"before-bearer-removed\": \"before this model is removed from play\",\n \"enemy-unit-destroyed-in-melee\": \"when an enemy unit is destroyed in melee\",\n \"on-damage-allocated\": \"when damage is allocated\",\n \"battle-shock-test\": \"when the unit takes a Battle-shock test\",\n \"leadership-test\": \"when the unit takes a Leadership test\",\n \"desperate-escape-test\": \"when the unit takes a Desperate Escape test\",\n};\n\nexport function eventClause(event: unknown): string {\n const e = str(event);\n return EVENT_PHRASES[e] ?? `when ${dekebab(e)}`;\n}\n\nexport function describeCondition(c: Condition): string {\n // Compound nodes first — join the operands with lowercase connectives so the\n // result reads naturally inside a \"... when X and Y\" clause.\n if (c.operator === \"and\" && c.operands) {\n return c.operands.map(describeCondition).join(\" and \");\n }\n if (c.operator === \"or\" && c.operands) {\n return c.operands.map(describeCondition).join(\" or \");\n }\n if (c.operator === \"not\" && c.operands) {\n return `not (${c.operands.map(describeCondition).join(\", \")})`;\n }\n\n const negate = c.negated ? \"not \" : \"\";\n const p = c.parameters ?? {};\n\n switch (c.type) {\n // ── Ability-DSL conditions (ported from commands/translate.ts) ──────────\n case \"phase-is\":\n return `${negate}during the ${str(p.phase)} phase`;\n case \"timing-is\":\n return `${negate}${describeTiming(p.timing)}`;\n case \"player-turn-is\":\n return `${negate}in ${p.turn === \"your-turn\" ? \"your\" : p.turn === \"opponent-turn\" ? \"the opponent's\" : \"either player's\"} turn`;\n case \"charged-this-turn\":\n return `${negate}the unit charged this turn`;\n case \"advanced-this-turn\":\n return `${negate}the unit advanced this turn`;\n case \"remained-stationary\":\n return `${negate}the unit remained stationary`;\n case \"unit-below-starting-strength\":\n return `${negate}the unit is below starting strength`;\n case \"unit-below-half-strength\":\n return `${negate}the ${p.subject === \"target\" ? \"target unit\" : \"unit\"} is below half strength`;\n case \"unit-has-keyword\":\n return `${negate}the unit has \"${str(p.keyword)}\"`;\n case \"target-has-keyword\":\n return `${negate}the target has \"${str(p.keyword)}\"`;\n case \"model-is-leader\":\n return `${negate}the model is leading a unit`;\n case \"is-attached\":\n return `${negate}attached to a ${p.keyword ? `${str(p.keyword)} ` : \"\"}unit`;\n case \"attack-is-type\":\n if (p.comparison === \"strength-greater-than-toughness\")\n return `${negate}when this attack's Strength is greater than the target's Toughness`;\n if (p.comparison != null) return `${negate}when ${dekebab(str(p.comparison))}`;\n return `${negate}for ${str(p.attack_type)} attacks`;\n case \"is-battle-shocked\":\n return `${negate}the unit is battle-shocked`;\n case \"has-lost-wounds\":\n return `${negate}the model has lost wounds`;\n case \"wounds-remaining-at-or-below\":\n return `${negate}the model has ${Number(p.threshold ?? 0)} or fewer wounds remaining`;\n case \"was-hit-by-attack\": {\n const subject = p.subject === \"target\" ? \"the target\" : \"the unit\";\n const atk = p.attack_type ? `${str(p.attack_type)} ` : \"\";\n const weapon = p.weapon_name ? ` by ${str(p.weapon_name)}` : \"\";\n const n = Number(p.count_min ?? 1);\n if (n > 1) return `${negate}${subject} was hit by ${n}+ ${atk}attacks${weapon} this phase`;\n return `${negate}${subject} was hit by ${atk === \"\" ? \"an attack\" : `a ${atk}attack`}${weapon} this phase`;\n }\n case \"opponent-unit-within-range\": {\n let where: string;\n if (p.weapon_name != null) where = `range of ${dekebab(str(p.weapon_name))}`;\n else if (p.range_multiplier != null) where = \"half range of its ranged weapons\";\n else if (p.range === \"engagement\") where = \"engagement range\";\n else where = `${str(p.range)}\"`;\n return `${negate}an enemy unit is within ${where}`;\n }\n case \"unit-within-range-of\": {\n const tt = str(p.target_type ?? \"target\");\n // `closest-eligible` names a specific model, not a radius — but a range, when\n // present, still bounds WHICH model is eligible (\"the closest ... within 18\\\"\").\n if (tt === \"closest-eligible\") {\n const within = p.range != null ? ` within ${str(p.range)}\"` : \"\";\n return `${negate}the target is the closest eligible target${within}`;\n }\n if (tt === \"area-terrain\") return `${negate}within an area terrain feature`;\n const who =\n tt === \"friendly-keyword\" && p.keyword\n ? `a friendly ${str(p.keyword)} unit`\n : tt === \"friendly\"\n ? \"a friendly unit\"\n : dekebab(tt);\n // A missing range stays as `?\"` so the audit still flags it as a data gap.\n const dist = p.range != null ? `${str(p.range)}\"` : '?\"';\n return `${negate}within ${dist} of ${who}`;\n }\n case \"within-range-of-objective\":\n return `${negate}within range of an objective`;\n case \"has-fought-this-phase\":\n return `${negate}has fought this phase`;\n case \"destroyed-by-attack-type\":\n return p.attack_type === \"any\"\n ? `${negate}destroyed by any attack`\n : `${negate}destroyed by a ${str(p.attack_type)} attack`;\n case \"attack-stat-compare\": {\n // Mirrors the Rust arm byte-for-byte: missing params render as \"\" (not \"?\").\n const sv = (v: unknown): string => (v == null ? \"\" : str(v));\n return `${negate}the attack's ${sv(p.attacker_stat)} is ${dekebab(sv(p.comparison))} the target's ${sv(p.target_stat)}`;\n }\n case \"made-ingress-move-this-turn\":\n return `${negate}the unit made an ingress move this turn`;\n case \"engagement-state\": {\n if (p.state == null) return `${negate}the unit is within Engagement Range`;\n const st = str(p.state);\n if (st === \"on-battlefield\") return `${negate}the unit is on the battlefield`;\n if (st === \"embarked\") return `${negate}the unit is embarked`;\n if (st === \"engaged\" || st === \"within-engagement-range\" || st === \"in-engagement-range\")\n return `${negate}the unit is within Engagement Range`;\n return `${negate}the unit is ${dekebab(st)}`;\n }\n case \"disposition-matches\": {\n const d = str(p.disposition);\n if (d === \"strategic-reserves\") return `${negate}the unit is in Strategic Reserves`;\n return `${negate}the unit's disposition is ${dekebab(d)}`;\n }\n case \"fights-first\":\n return `${negate}the unit has Fights First`;\n\n // ── Scoring conditions (secondary-card award `when`) ────────────────────\n case \"objective-majority\":\n return `${negate}you hold more objectives than the ${dekebab(str(p.relative_to ?? \"opponent\"))}`;\n case \"controls-objective\": {\n const noun = p.objective_role ? `${dekebab(str(p.objective_role))} objective` : \"objective\";\n let s = `${negate}you control ${count(p.count_min ?? 1, noun)}`;\n if (p.objective != null) s += ` (${dekebab(str(p.objective))})`;\n if (p.scope != null) s += ` in ${dekebab(str(p.scope))}`;\n if (p.exclude != null) s += ` (excluding ${dekebab(str(p.exclude))})`;\n return s;\n }\n case \"units-destroyed\": {\n let s = `${negate}${count(p.count_min ?? 1, `${str(p.side)} unit`)} destroyed`;\n if (p.window != null) s += ` ${dekebab(str(p.window))}`;\n return s;\n }\n case \"units-destroyed-comparison\": {\n const subj = (p.subject ?? {}) as Record<string, unknown>;\n const ref = (p.reference ?? {}) as Record<string, unknown>;\n const cmp = p.comparator === \"greater-or-equal\" ? \"at least as many\" : \"more\";\n const link = p.comparator === \"greater-or-equal\" ? \"as\" : \"than\";\n return `${negate}you destroyed ${cmp} ${str(subj.side)} units ${dekebab(str(subj.window))} ${link} ${str(ref.side)} units ${dekebab(str(ref.window))}`;\n }\n case \"new-objective-controlled\":\n return `${negate}you newly control ${count(p.count_min ?? 1, \"objective\")} this turn`;\n case \"destroyed-while-on-objective\": {\n const obj = p.objective_role ? `a ${dekebab(str(p.objective_role))} objective` : \"an objective\";\n let s = `${negate}${count(p.count_min ?? 1, \"enemy unit\")} destroyed`;\n if (p.destroyer_on_objective) s += ` by a unit on ${obj}`;\n if (p.victim_on_objective) s += ` while on ${obj}`;\n if (p.victim_started_turn_on_objective) s += ` that started the turn on ${obj}`;\n return s;\n }\n case \"destroyed-in-tagged-terrain\": {\n const where = p.at_start_of_turn ? \"that started the turn in\" : \"while in\";\n const terrain = p.tag != null ? `${dekebab(str(p.tag))} terrain` : \"a terrain area\";\n return `${negate}${count(p.count_min ?? 1, \"enemy unit\")} destroyed ${where} ${terrain}`;\n }\n case \"operation-markers\": {\n const side = p.side != null ? `${str(p.side)} ` : \"\";\n const min = typeof p.count_min === \"number\" ? p.count_min : undefined;\n const max = typeof p.count_max === \"number\" ? p.count_max : undefined;\n let s: string;\n if (max === 0) {\n s = `no ${side}operation markers on the battlefield`;\n } else if (min != null && max != null && min === max) {\n s = `exactly ${min} ${side}operation marker${min === 1 ? \"\" : \"s\"} on the battlefield`;\n } else {\n s = `${str(min ?? 1)}+ ${side}operation markers on the battlefield`;\n }\n if (p.within_range_of != null) s += ` within range of ${dekebab(str(p.within_range_of))}`;\n if (p.friendly_unit_in_same_terrain_area) s += \" with a friendly unit in the same terrain area\";\n if (p.no_enemy_in_terrain_area) s += \" and no enemy units in that terrain area\";\n return `${negate}${s}`;\n }\n case \"action-completed\": {\n let s = `${negate}${count(p.count_min ?? 1, \"action\")} completed`;\n if (p.action_id != null) s += ` (${dekebab(str(p.action_id))})`;\n if (p.target_kind != null) s += ` on ${dekebab(str(p.target_kind))}`;\n const tf = (p.target_filter ?? {}) as Record<string, unknown>;\n if (tf.objective_role != null) s += ` (${dekebab(str(tf.objective_role))})`;\n if (tf.in_enemy_territory) s += \" in enemy territory\";\n if (tf.exclude != null) s += ` (excluding ${dekebab(str(tf.exclude))})`;\n if (p.window != null) s += ` ${dekebab(str(p.window))}`;\n return s;\n }\n case \"objective-has-tag\": {\n let s = `${negate}${count(p.count_min ?? 1, \"objective\")} tagged ${dekebab(str(p.tag))}`;\n if (p.count_max != null) s += ` (at most ${str(p.count_max)})`;\n if (p.objective != null) s += ` (${dekebab(str(p.objective))})`;\n if (p.scope != null) s += ` in ${dekebab(str(p.scope))}`;\n if (p.last_marked) s += \" (most recently marked)\";\n return s;\n }\n case \"unit-has-tag\": {\n // Ability-gate use (no side/count) reads as a unit state; scoring use counts tagged units.\n if (p.side == null && p.count_min == null)\n return `${negate}the unit is tagged ${dekebab(str(p.tag))}`;\n let s = `${negate}${count(p.count_min ?? 1, `${str(p.side)} unit`)} tagged ${dekebab(str(p.tag))}`;\n if (p.window != null) s += ` (${dekebab(str(p.window))})`;\n return s;\n }\n case \"terrain-has-tag\": {\n let s = `${negate}terrain tagged ${dekebab(str(p.tag))}`;\n if (p.friendly_units_min != null) s += ` with ${str(p.friendly_units_min)}+ friendly units`;\n if (p.enemy_units_max != null) s += ` and at most ${str(p.enemy_units_max)} enemy units`;\n if (p.last_marked) s += \" (most recently marked)\";\n if (p.in_enemy_dz) s += \" in the enemy deployment zone\";\n return s;\n }\n case \"terrain-area-control\":\n return `${negate}you control a terrain area with ${str(p.min_models ?? 1)}+ models`;\n case \"territory-control\": {\n let s = `${negate}you control ${dekebab(str(p.territory_ref ?? \"your-territory\"))}`;\n if (p.enemy_units_max != null) s += ` with at most ${str(p.enemy_units_max)} enemy units`;\n return s;\n }\n case \"engagement-fronts\":\n return `${negate}you are engaged on ${str(p.count_min ?? 1)}+ fronts`;\n case \"token-count-at-or-above\":\n return `${negate}the unit has ${str(p.threshold)}+ ${dekebab(str(p.pool_id))}`;\n case \"battle-round\": {\n const min = p.min != null ? Number(p.min) : undefined;\n const max = p.max != null ? Number(p.max) : undefined;\n const ord = (n: number): string =>\n [\"zeroth\", \"first\", \"second\", \"third\", \"fourth\", \"fifth\"][n] ?? `${n}th`;\n let where: string;\n if (min != null && max != null)\n where = min === max ? `the ${ord(min)} battle round` : `battle rounds ${min}-${max}`;\n else if (min != null) where = `the ${ord(min)} battle round onward`;\n else if (max != null) where = `the first ${max} battle rounds`;\n else where = \"the battle round\";\n return `${negate}during ${where}`;\n }\n\n default:\n return `${negate}${dekebab(c.type ?? \"unknown\")}`;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"condition.js","sourceRoot":"","sources":["../../src/translate/condition.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Humanize an Ability-DSL / scoring `condition` into plain English.\n *\n * Shared by the ability-text CLI (`commands/translate.ts`) and the scoring-card\n * translator (`scoring.ts`). Output is **ASCII-only** with a fixed clause and\n * parameter order: it is pinned byte-for-byte across the TS and Rust ports by\n * the `conformance/scoring-translation` corpus, so any phrasing change here is a\n * semantic corpus change (bump `conformance/SPEC_VERSION`).\n */\n\n/**\n * Minimal structural view of a condition node. Matches both the ability-dsl\n * condition schema and the `secondary-card` award `when` field (a simple node\n * carries `type` + `parameters` + `negated`; a compound node carries\n * `operator` + `operands`).\n */\nexport interface Condition {\n type?: string;\n operator?: \"and\" | \"or\" | \"not\";\n operands?: Condition[];\n parameters?: Record<string, unknown>;\n negated?: boolean;\n}\n\n/** kebab-case → space-separated words (`enemy-territory` → `enemy territory`). */\nexport function dekebab(s: string): string {\n return s.replace(/-/g, \" \");\n}\n\nfunction str(v: unknown): string {\n if (v == null) return \"?\";\n return typeof v === \"string\" ? v : String(v);\n}\n\n/**\n * A `timing-is` event token → natural GW-voice clause (\"each time a model in\n * this unit is destroyed\", \"at the start of the phase\"). Structural phase/turn\n * markers and the common trigger families are mapped explicitly; the fallback\n * routes `after-*`/`on-*` prefixes to \"after …\"/\"when …\" (so the old \"at on …\"\n * double-preposition can't occur) and everything else to \"at <event>\".\n */\n/**\n * Legacy `timing-is` strings → canonical `game-event` (Batch C unification). Data\n * is being canonicalized onto these targets; the alias map keeps un-migrated\n * strings rendering identically via the one vocabulary (`eventClause`).\n */\nconst TIMING_ALIASES: Record<string, string> = {\n advance: \"advances\",\n \"after-attacks\": \"after-unit-resolves-attacks\",\n \"after-attacking-unit-finishes-attacks\": \"after-unit-resolves-attacks\",\n \"after-shooting\": \"after-unit-resolves-attacks\",\n \"after-unit-shot\": \"after-unit-resolves-attacks\",\n \"after-unit-has-shot\": \"after-unit-resolves-attacks\",\n \"after-this-model-has-shot\": \"after-unit-resolves-attacks\",\n \"after-shot-hits-scored\": \"after-scoring-hit\",\n \"deep-strike\": \"deep-strike-setup\",\n end: \"end-of-turn\",\n start: \"start-of-turn\",\n \"fall-back\": \"falls-back\",\n \"model-destroyed\": \"on-model-destroyed\",\n \"on-destroyed\": \"on-unit-destroyed\",\n \"before-this-model-removed\": \"before-bearer-removed\",\n \"command-phase\": \"start-of-command-phase\",\n \"reinforcements-step\": \"reinforcements\",\n setup: \"unit-set-up\",\n \"set-up-this-turn\": \"unit-set-up\",\n \"after-move-through-terrain-over-4-inches\": \"moved-through-terrain\",\n \"after-moving-through-tall-terrain\": \"moved-through-terrain\",\n \"when-this-unit-selected-to-shoot\": \"selected-to-shoot\",\n};\n\n/**\n * Timing strings with no canonical `game-event` equivalent but an established\n * phrase: usage markers (which a future pass may move to the `usage` block) and\n * a couple of phase/state gates. Everything else degrades via the heuristics.\n */\nconst TIMING_ONLY_PHRASES: Record<string, string> = {\n \"once-per-battle\": \"once per battle\",\n \"once-per-phase\": \"once per phase\",\n \"once-per-opponent-turn\": \"once per opponent's turn\",\n \"first-this-battle\": \"the first time this battle\",\n \"first-time-this-phase\": \"the first time this phase\",\n \"in-reserves\": \"while it is in Reserves\",\n \"shooting-phase\": \"in the Shooting phase\",\n \"start-of-fight-phase\": \"at the start of the Fight phase\",\n \"first-movement-phase\": \"in your first Movement phase\",\n \"start-of-first-battle-round\": \"at the start of the first battle round\",\n \"start-of-movement-phase\": \"at the start of the Movement phase\",\n \"shooting-or-fight-phase\": \"in the Shooting or Fight phase\",\n \"this-model-starts-or-ends-a-move\": \"each time this model starts or ends a move\",\n \"end-of-normal-move\": \"when the unit ends a Normal move\",\n \"friendly-unit-empowered-within-9\":\n 'each time you spend 1 Pain token to Empower a friendly unit within 9\" of this unit',\n \"enemy-unit-fails-battle-shock\": \"each time an enemy unit fails a Battle-shock test\",\n \"enemy-unit-destroyed\": \"each time an enemy unit is destroyed\",\n};\n\nexport function describeTiming(timing: unknown): string {\n const t = str(timing);\n if (TIMING_ONLY_PHRASES[t]) return TIMING_ONLY_PHRASES[t];\n const canon = TIMING_ALIASES[t] ?? t;\n if (EVENT_PHRASES[canon]) return EVENT_PHRASES[canon];\n if (t.startsWith(\"after-\")) return `after ${dekebab(t.slice(6))}`;\n if (t.startsWith(\"on-\")) return `when ${dekebab(t.slice(3))}`;\n if (t.endsWith(\"-destroyed\")) return `each time ${dekebab(t)}`;\n return `at ${dekebab(t)}`;\n}\n\n/** `2` + `objective` → `2+ objectives`. Nouns here are all regular plurals. */\nfunction count(n: unknown, noun: string): string {\n return `${str(n)}+ ${noun}s`;\n}\n\n/**\n * Canonical `game-event` token → natural clause, for the reactive `trigger.event`.\n * This is the unified event vocabulary; the `timing-is` condition will be\n * canonicalized onto the same keys. Unmapped events degrade to `when <dekebab>`.\n */\nconst EVENT_PHRASES: Record<string, string> = {\n \"start-of-phase\": \"at the start of the phase\",\n \"end-of-phase\": \"at the end of the phase\",\n \"start-of-turn\": \"at the start of the turn\",\n \"end-of-turn\": \"at the end of the turn\",\n \"start-of-opponent-turn\": \"at the start of the opponent's turn\",\n \"end-of-opponent-turn\": \"at the end of the opponent's turn\",\n \"start-of-battle-round\": \"at the start of the battle round\",\n \"start-of-battle\": \"at the start of the battle\",\n \"army-selection\": \"when you select this model to include in your army\",\n \"start-of-command-phase\": \"at the start of the Command phase\",\n \"declare-battle-formations\": \"when declaring Battle Formations\",\n \"post-deployment\": \"after deployment\",\n \"unit-set-up\": \"when the unit is set up\",\n \"set-up-from-reserves\": \"when the unit arrives from Reserves\",\n \"arrives-from-strategic-reserves\": \"when the unit arrives from Strategic Reserves\",\n \"starts-in-strategic-reserves\": \"if the unit starts in Strategic Reserves\",\n \"game-start-in-reserves\": \"if the unit begins the battle in Reserves\",\n \"deep-strike-setup\": \"when the unit is set up by Deep Strike\",\n \"reinforcements\": \"when the unit arrives as Reinforcements\",\n \"normal-move\": \"when the unit makes a Normal move\",\n \"advance-move\": \"when the unit makes an Advance move\",\n advances: \"when the unit Advances\",\n \"fall-back-move\": \"when the unit makes a Fall Back move\",\n \"falls-back\": \"when the unit Falls Back\",\n \"charge-move\": \"when the unit makes a Charge move\",\n \"moved-through-terrain\": \"when the unit moves through terrain\",\n \"enemy-unit-ended-move\": \"an enemy unit ends a move\",\n \"enemy-unit-fell-back\": \"an enemy unit Falls Back\",\n \"before-hit-roll\": \"before a Hit roll is made\",\n \"after-hit-roll\": \"after a Hit roll is made\",\n \"before-wound-roll\": \"before a Wound roll is made\",\n \"after-wound-roll\": \"after a Wound roll is made\",\n \"before-save-roll\": \"before a saving throw is made\",\n \"after-save-roll\": \"after a saving throw is made\",\n \"before-damage-roll\": \"before a Damage roll is made\",\n \"after-damage-roll\": \"after a Damage roll is made\",\n \"before-charge-roll\": \"before a Charge roll is made\",\n \"after-charge-roll\": \"after a Charge roll is made\",\n \"before-advance-roll\": \"before an Advance roll is made\",\n \"after-advance-roll\": \"after an Advance roll is made\",\n \"before-battle-shock\": \"before a Battle-shock test\",\n \"after-battle-shock\": \"after a Battle-shock test\",\n \"on-unit-selected\": \"when the unit is selected\",\n \"selected-to-shoot\": \"when the unit is selected to shoot\",\n \"selected-to-fight\": \"when the unit is selected to fight\",\n \"selected-to-advance\": \"when the unit is selected to Advance\",\n \"after-unit-resolves-attacks\": \"after the unit resolves its attacks\",\n \"after-scoring-hit\": \"after scoring a hit\",\n \"after-enemy-unit-fires\": \"after an enemy unit shoots\",\n \"on-unit-destroyed\": \"when the unit is destroyed\",\n \"on-model-destroyed\": \"when a model in the unit is destroyed\",\n \"first-model-destroyed\": \"the first time a model in the unit is destroyed\",\n \"before-bearer-removed\": \"before this model is removed from play\",\n \"enemy-unit-destroyed-in-melee\": \"when an enemy unit is destroyed in melee\",\n \"on-damage-allocated\": \"when damage is allocated\",\n \"battle-shock-test\": \"when the unit takes a Battle-shock test\",\n \"leadership-test\": \"when the unit takes a Leadership test\",\n \"desperate-escape-test\": \"when the unit takes a Desperate Escape test\",\n};\n\nexport function eventClause(event: unknown): string {\n const e = str(event);\n return EVENT_PHRASES[e] ?? `when ${dekebab(e)}`;\n}\n\nexport function describeCondition(c: Condition): string {\n // Compound nodes first — join the operands with lowercase connectives so the\n // result reads naturally inside a \"... when X and Y\" clause.\n if (c.operator === \"and\" && c.operands) {\n return c.operands.map(describeCondition).join(\" and \");\n }\n if (c.operator === \"or\" && c.operands) {\n return c.operands.map(describeCondition).join(\" or \");\n }\n if (c.operator === \"not\" && c.operands) {\n return `not (${c.operands.map(describeCondition).join(\", \")})`;\n }\n\n const negate = c.negated ? \"not \" : \"\";\n const p = c.parameters ?? {};\n\n switch (c.type) {\n // ── Ability-DSL conditions (ported from commands/translate.ts) ──────────\n case \"phase-is\":\n return `${negate}during the ${str(p.phase)} phase`;\n case \"timing-is\":\n return `${negate}${describeTiming(p.timing)}`;\n case \"player-turn-is\": {\n const t = str(p.turn);\n const phrase =\n t === \"your-turn\" || t === \"your\" || t === \"own\"\n ? \"your\"\n : t === \"opponent-turn\" || t === \"opponent\"\n ? \"the opponent's\"\n : \"either player's\";\n return `${negate}in ${phrase} turn`;\n }\n case \"charged-this-turn\":\n return `${negate}the unit charged this turn`;\n case \"advanced-this-turn\":\n return `${negate}the unit advanced this turn`;\n case \"remained-stationary\":\n return `${negate}the unit remained stationary`;\n case \"unit-below-starting-strength\":\n return `${negate}the unit is below starting strength`;\n case \"unit-below-half-strength\":\n return `${negate}the ${p.subject === \"target\" ? \"target unit\" : \"unit\"} is below half strength`;\n case \"unit-has-keyword\":\n return `${negate}the unit has \"${str(p.keyword)}\"`;\n case \"target-has-keyword\":\n return `${negate}the target has \"${str(p.keyword)}\"`;\n case \"model-is-leader\":\n return `${negate}the model is leading a unit`;\n case \"is-attached\":\n return `${negate}attached to a ${p.keyword ? `${str(p.keyword)} ` : \"\"}unit`;\n case \"attack-is-type\":\n if (p.comparison === \"strength-greater-than-toughness\")\n return `${negate}when this attack's Strength is greater than the target's Toughness`;\n if (p.comparison != null) return `${negate}when ${dekebab(str(p.comparison))}`;\n return `${negate}for ${str(p.attack_type)} attacks`;\n case \"is-battle-shocked\":\n return `${negate}the unit is battle-shocked`;\n case \"has-lost-wounds\":\n return `${negate}the model has lost wounds`;\n case \"wounds-remaining-at-or-below\":\n return `${negate}the model has ${Number(p.threshold ?? 0)} or fewer wounds remaining`;\n case \"was-hit-by-attack\": {\n const subject = p.subject === \"target\" ? \"the target\" : \"the unit\";\n const atk = p.attack_type ? `${str(p.attack_type)} ` : \"\";\n const weapon = p.weapon_name ? ` by ${str(p.weapon_name)}` : \"\";\n const n = Number(p.count_min ?? 1);\n if (n > 1) return `${negate}${subject} was hit by ${n}+ ${atk}attacks${weapon} this phase`;\n return `${negate}${subject} was hit by ${atk === \"\" ? \"an attack\" : `a ${atk}attack`}${weapon} this phase`;\n }\n case \"opponent-unit-within-range\": {\n let where: string;\n if (p.weapon_name != null) where = `range of ${dekebab(str(p.weapon_name))}`;\n else if (p.range_multiplier != null) where = \"half range of its ranged weapons\";\n else {\n const range = p.range ?? p.range_inches ?? p.within_inches;\n where = range === \"engagement\" ? \"engagement range\" : `${str(range)}\"`;\n }\n return `${negate}an enemy unit is within ${where}`;\n }\n case \"unit-within-range-of\": {\n const tt = str(p.target_type ?? \"target\");\n // `closest-eligible` names a specific model, not a radius — but a range, when\n // present, still bounds WHICH model is eligible (\"the closest ... within 18\\\"\").\n if (tt === \"closest-eligible\") {\n const within = p.range != null ? ` within ${str(p.range)}\"` : \"\";\n return `${negate}the target is the closest eligible target${within}`;\n }\n if (tt === \"area-terrain\") return `${negate}within an area terrain feature`;\n const who =\n tt === \"friendly-keyword\" && p.keyword\n ? `a friendly ${str(p.keyword)} unit`\n : tt === \"friendly\"\n ? \"a friendly unit\"\n : dekebab(tt);\n // A missing range stays as `?\"` so the audit still flags it as a data gap.\n const dist = p.range != null ? `${str(p.range)}\"` : '?\"';\n return `${negate}within ${dist} of ${who}`;\n }\n case \"within-range-of-objective\":\n return `${negate}within range of an objective`;\n case \"has-fought-this-phase\":\n return `${negate}has fought this phase`;\n case \"destroyed-by-attack-type\":\n return p.attack_type === \"any\"\n ? `${negate}destroyed by any attack`\n : `${negate}destroyed by a ${str(p.attack_type)} attack`;\n case \"attack-stat-compare\": {\n // Mirrors the Rust arm byte-for-byte: missing params render as \"\" (not \"?\").\n const sv = (v: unknown): string => (v == null ? \"\" : str(v));\n return `${negate}the attack's ${sv(p.attacker_stat)} is ${dekebab(sv(p.comparison))} the target's ${sv(p.target_stat)}`;\n }\n case \"made-ingress-move-this-turn\":\n return `${negate}the unit made an ingress move this turn`;\n case \"engagement-state\": {\n if (p.state == null) return `${negate}the unit is within Engagement Range`;\n const st = str(p.state);\n if (st === \"on-battlefield\") return `${negate}the unit is on the battlefield`;\n if (st === \"embarked\") return `${negate}the unit is embarked`;\n if (st === \"engaged\" || st === \"within-engagement-range\" || st === \"in-engagement-range\")\n return `${negate}the unit is within Engagement Range`;\n return `${negate}the unit is ${dekebab(st)}`;\n }\n case \"disposition-matches\": {\n const d = str(p.disposition);\n if (d === \"strategic-reserves\") return `${negate}the unit is in Strategic Reserves`;\n return `${negate}the unit's disposition is ${dekebab(d)}`;\n }\n case \"fights-first\":\n return `${negate}the unit has Fights First`;\n\n // ── Scoring conditions (secondary-card award `when`) ────────────────────\n case \"objective-majority\":\n return `${negate}you hold more objectives than the ${dekebab(str(p.relative_to ?? \"opponent\"))}`;\n case \"controls-objective\": {\n const noun = p.objective_role ? `${dekebab(str(p.objective_role))} objective` : \"objective\";\n let s = `${negate}you control ${count(p.count_min ?? 1, noun)}`;\n if (p.objective != null) s += ` (${dekebab(str(p.objective))})`;\n if (p.scope != null) s += ` in ${dekebab(str(p.scope))}`;\n if (p.exclude != null) s += ` (excluding ${dekebab(str(p.exclude))})`;\n return s;\n }\n case \"units-destroyed\": {\n let s = `${negate}${count(p.count_min ?? 1, `${str(p.side)} unit`)} destroyed`;\n if (p.window != null) s += ` ${dekebab(str(p.window))}`;\n return s;\n }\n case \"units-destroyed-comparison\": {\n const subj = (p.subject ?? {}) as Record<string, unknown>;\n const ref = (p.reference ?? {}) as Record<string, unknown>;\n const cmp = p.comparator === \"greater-or-equal\" ? \"at least as many\" : \"more\";\n const link = p.comparator === \"greater-or-equal\" ? \"as\" : \"than\";\n return `${negate}you destroyed ${cmp} ${str(subj.side)} units ${dekebab(str(subj.window))} ${link} ${str(ref.side)} units ${dekebab(str(ref.window))}`;\n }\n case \"new-objective-controlled\":\n return `${negate}you newly control ${count(p.count_min ?? 1, \"objective\")} this turn`;\n case \"destroyed-while-on-objective\": {\n const obj = p.objective_role ? `a ${dekebab(str(p.objective_role))} objective` : \"an objective\";\n let s = `${negate}${count(p.count_min ?? 1, \"enemy unit\")} destroyed`;\n if (p.destroyer_on_objective) s += ` by a unit on ${obj}`;\n if (p.victim_on_objective) s += ` while on ${obj}`;\n if (p.victim_started_turn_on_objective) s += ` that started the turn on ${obj}`;\n return s;\n }\n case \"destroyed-in-tagged-terrain\": {\n const where = p.at_start_of_turn ? \"that started the turn in\" : \"while in\";\n const terrain = p.tag != null ? `${dekebab(str(p.tag))} terrain` : \"a terrain area\";\n return `${negate}${count(p.count_min ?? 1, \"enemy unit\")} destroyed ${where} ${terrain}`;\n }\n case \"operation-markers\": {\n const side = p.side != null ? `${str(p.side)} ` : \"\";\n const min = typeof p.count_min === \"number\" ? p.count_min : undefined;\n const max = typeof p.count_max === \"number\" ? p.count_max : undefined;\n let s: string;\n if (max === 0) {\n s = `no ${side}operation markers on the battlefield`;\n } else if (min != null && max != null && min === max) {\n s = `exactly ${min} ${side}operation marker${min === 1 ? \"\" : \"s\"} on the battlefield`;\n } else {\n s = `${str(min ?? 1)}+ ${side}operation markers on the battlefield`;\n }\n if (p.within_range_of != null) s += ` within range of ${dekebab(str(p.within_range_of))}`;\n if (p.friendly_unit_in_same_terrain_area) s += \" with a friendly unit in the same terrain area\";\n if (p.no_enemy_in_terrain_area) s += \" and no enemy units in that terrain area\";\n return `${negate}${s}`;\n }\n case \"action-completed\": {\n let s = `${negate}${count(p.count_min ?? 1, \"action\")} completed`;\n if (p.action_id != null) s += ` (${dekebab(str(p.action_id))})`;\n if (p.target_kind != null) s += ` on ${dekebab(str(p.target_kind))}`;\n const tf = (p.target_filter ?? {}) as Record<string, unknown>;\n if (tf.objective_role != null) s += ` (${dekebab(str(tf.objective_role))})`;\n if (tf.in_enemy_territory) s += \" in enemy territory\";\n if (tf.exclude != null) s += ` (excluding ${dekebab(str(tf.exclude))})`;\n if (p.window != null) s += ` ${dekebab(str(p.window))}`;\n return s;\n }\n case \"objective-has-tag\": {\n let s = `${negate}${count(p.count_min ?? 1, \"objective\")} tagged ${dekebab(str(p.tag))}`;\n if (p.count_max != null) s += ` (at most ${str(p.count_max)})`;\n if (p.objective != null) s += ` (${dekebab(str(p.objective))})`;\n if (p.scope != null) s += ` in ${dekebab(str(p.scope))}`;\n if (p.last_marked) s += \" (most recently marked)\";\n return s;\n }\n case \"unit-has-tag\": {\n // Ability-gate use (no side/count) reads as a unit state; scoring use counts tagged units.\n if (p.side == null && p.count_min == null)\n return `${negate}the unit is tagged ${dekebab(str(p.tag))}`;\n let s = `${negate}${count(p.count_min ?? 1, `${str(p.side)} unit`)} tagged ${dekebab(str(p.tag))}`;\n if (p.window != null) s += ` (${dekebab(str(p.window))})`;\n return s;\n }\n case \"terrain-has-tag\": {\n let s = `${negate}terrain tagged ${dekebab(str(p.tag))}`;\n if (p.friendly_units_min != null) s += ` with ${str(p.friendly_units_min)}+ friendly units`;\n if (p.enemy_units_max != null) s += ` and at most ${str(p.enemy_units_max)} enemy units`;\n if (p.last_marked) s += \" (most recently marked)\";\n if (p.in_enemy_dz) s += \" in the enemy deployment zone\";\n return s;\n }\n case \"terrain-area-control\":\n return `${negate}you control a terrain area with ${str(p.min_models ?? 1)}+ models`;\n case \"territory-control\": {\n let s = `${negate}you control ${dekebab(str(p.territory_ref ?? \"your-territory\"))}`;\n if (p.enemy_units_max != null) s += ` with at most ${str(p.enemy_units_max)} enemy units`;\n return s;\n }\n case \"engagement-fronts\":\n return `${negate}you are engaged on ${str(p.count_min ?? 1)}+ fronts`;\n case \"token-count-at-or-above\":\n return `${negate}the unit has ${str(p.threshold)}+ ${dekebab(str(p.pool_id))}`;\n case \"battle-round\": {\n const min = p.min != null ? Number(p.min) : undefined;\n const max = p.max != null ? Number(p.max) : undefined;\n const ord = (n: number): string =>\n [\"zeroth\", \"first\", \"second\", \"third\", \"fourth\", \"fifth\"][n] ?? `${n}th`;\n let where: string;\n if (min != null && max != null)\n where = min === max ? `the ${ord(min)} battle round` : `battle rounds ${min}-${max}`;\n else if (min != null) where = `the ${ord(min)} battle round onward`;\n else if (max != null) where = `the first ${max} battle rounds`;\n else where = \"the battle round\";\n return `${negate}during ${where}`;\n }\n\n default:\n return `${negate}${dekebab(c.type ?? \"unknown\")}`;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../../src/translate/effect.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"effect.d.ts","sourceRoot":"","sources":["../../src/translate/effect.ts"],"names":[],"mappings":"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"}
|
package/dist/translate/effect.js
CHANGED
|
@@ -425,6 +425,15 @@ function joinAndLeadIns(operands) {
|
|
|
425
425
|
parts.push(excludedTargetKeywords(kws));
|
|
426
426
|
continue;
|
|
427
427
|
}
|
|
428
|
+
if (!op.negated && op.type === "unit-has-keyword") {
|
|
429
|
+
const kws = [];
|
|
430
|
+
while (i < operands.length && !operands[i].negated && operands[i].type === "unit-has-keyword") {
|
|
431
|
+
kws.push(jstr((operands[i].parameters ?? {}).keyword));
|
|
432
|
+
i++;
|
|
433
|
+
}
|
|
434
|
+
parts.push(kws.length >= 2 ? `if the unit is a ${kws.join(" ")} unit` : `if the unit has the ${kws[0]} keyword`);
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
428
437
|
parts.push(conditionLeadIn(op));
|
|
429
438
|
i++;
|
|
430
439
|
}
|
|
@@ -462,12 +471,15 @@ function conditionLeadIn(c) {
|
|
|
462
471
|
return `after being attached to a ${p.keyword ? `${jstr(p.keyword)} ` : ""}unit`;
|
|
463
472
|
case "timing-is":
|
|
464
473
|
return describeTiming(p.timing);
|
|
465
|
-
case "player-turn-is":
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
474
|
+
case "player-turn-is": {
|
|
475
|
+
const t = jstr(p.turn);
|
|
476
|
+
const phrase = t === "your-turn" || t === "your" || t === "own"
|
|
477
|
+
? "your"
|
|
478
|
+
: t === "opponent-turn" || t === "opponent"
|
|
479
|
+
? "the opponent's"
|
|
480
|
+
: "either player's";
|
|
481
|
+
return `in ${phrase} turn`;
|
|
482
|
+
}
|
|
471
483
|
case "model-is-leader":
|
|
472
484
|
return "while this model leads a unit";
|
|
473
485
|
case "charged-this-turn":
|
|
@@ -524,8 +536,10 @@ function conditionLeadIn(c) {
|
|
|
524
536
|
where = `range of ${dekebab(jstr(p.weapon_name))}`;
|
|
525
537
|
else if (p.range_multiplier != null)
|
|
526
538
|
where = "half range of its ranged weapons";
|
|
527
|
-
else
|
|
528
|
-
|
|
539
|
+
else {
|
|
540
|
+
const range = p.range ?? p.range_inches ?? p.within_inches;
|
|
541
|
+
where = range === "engagement" ? "engagement range" : `${jstr(range)}"`;
|
|
542
|
+
}
|
|
529
543
|
return `while an enemy unit is within ${where}`;
|
|
530
544
|
}
|
|
531
545
|
case "engagement-state": {
|
|
@@ -798,8 +812,14 @@ function describeEffectInlineBase(e, ctx = {}) {
|
|
|
798
812
|
return `${subj} ${v(subj, "gets")} ${signed(m.operation, m.value)} to ${rollName(m.roll)} rolls${ctxNote}`;
|
|
799
813
|
}
|
|
800
814
|
case "re-roll": {
|
|
801
|
-
const
|
|
802
|
-
const which =
|
|
815
|
+
const rn = jstr(m.roll);
|
|
816
|
+
const which = rn === "any"
|
|
817
|
+
? m.subset === "ones"
|
|
818
|
+
? "any roll of 1"
|
|
819
|
+
: "any roll"
|
|
820
|
+
: m.subset === "ones"
|
|
821
|
+
? `a ${rollName(m.roll)} roll of 1`
|
|
822
|
+
: `the ${rollName(m.roll)} roll`;
|
|
803
823
|
return `you can re-roll ${which}`;
|
|
804
824
|
}
|
|
805
825
|
case "mortal-wounds": {
|
|
@@ -1143,8 +1163,10 @@ function describeEffectInlineBase(e, ctx = {}) {
|
|
|
1143
1163
|
const led = m.led_by != null ? ` led by a ${titleCase(jstr(m.led_by))} model` : "";
|
|
1144
1164
|
return `at the start of the Declare Battle Formations step, ${subj} can join one friendly unit${led}, becoming part of that Bodyguard unit`;
|
|
1145
1165
|
}
|
|
1146
|
-
case "fallback-and-act":
|
|
1147
|
-
|
|
1166
|
+
case "fallback-and-act": {
|
|
1167
|
+
const acts = m.can_charge === true ? "shoot and declare a charge" : "shoot";
|
|
1168
|
+
return `${subj} is eligible to ${acts} in a turn in which it Fell Back`;
|
|
1169
|
+
}
|
|
1148
1170
|
case "fight-eligibility-extension": {
|
|
1149
1171
|
const r = jstr(m.range);
|
|
1150
1172
|
return (`when determining which models in ${subj} are eligible to fight, ` +
|
|
@@ -1483,7 +1505,8 @@ function timingOfCondition(c) {
|
|
|
1483
1505
|
function conditionWithinRange(c) {
|
|
1484
1506
|
if (c?.type !== "unit-within-range-of" && c?.type !== "opponent-unit-within-range")
|
|
1485
1507
|
return undefined;
|
|
1486
|
-
const
|
|
1508
|
+
const params = c.parameters ?? {};
|
|
1509
|
+
const r = params.range ?? params.range_inches ?? params.within_inches;
|
|
1487
1510
|
return typeof r === "number" ? r : undefined;
|
|
1488
1511
|
}
|
|
1489
1512
|
function renderTopLevel(e, scope, usage, trigger) {
|