@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.
@@ -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,CA8OtD"}
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
- return `${negate}in ${p.turn === "your-turn" ? "your" : p.turn === "opponent-turn" ? "the opponent's" : "either player's"} turn`;
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 if (p.range === "engagement")
235
- where = "engagement range";
236
- else
237
- where = `${str(p.range)}"`;
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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"}
@@ -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
- return p.turn === "your-turn"
467
- ? "in your turn"
468
- : p.turn === "opponent-turn"
469
- ? "in the opponent's turn"
470
- : "in either player's turn";
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
- where = p.range === "engagement" ? "engagement range" : `${jstr(p.range)}"`;
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 noun = rollName(m.roll);
802
- const which = m.subset === "ones" ? `a ${noun} roll of 1` : `the ${noun} roll`;
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
- return `${subj} is eligible to shoot and declare a charge in a turn in which it Fell Back`;
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 r = (c.parameters ?? {}).range;
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) {