@alpaca-software/40kdc-data 0.5.14 → 0.5.16
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/abilities-resolver/resolver.d.ts.map +1 -1
- package/dist/abilities-resolver/resolver.js +6 -2
- package/dist/abilities-resolver/resolver.js.map +1 -1
- package/dist/audit-coverage.d.ts.map +1 -1
- package/dist/audit-coverage.js +90 -1
- package/dist/audit-coverage.js.map +1 -1
- package/dist/audit-phrasing.d.ts +64 -0
- package/dist/audit-phrasing.d.ts.map +1 -0
- package/dist/audit-phrasing.js +208 -0
- package/dist/audit-phrasing.js.map +1 -0
- package/dist/build-share-registry.d.ts +2 -0
- package/dist/build-share-registry.d.ts.map +1 -0
- package/dist/build-share-registry.js +115 -0
- package/dist/build-share-registry.js.map +1 -0
- package/dist/cli.js +7 -0
- package/dist/cli.js.map +1 -1
- package/dist/codegen-data.js +23 -0
- package/dist/codegen-data.js.map +1 -1
- package/dist/commands/translate.d.ts.map +1 -1
- package/dist/commands/translate.js +2 -5
- package/dist/commands/translate.js.map +1 -1
- package/dist/commands/validate-all.d.ts.map +1 -1
- package/dist/commands/validate-all.js +8 -3
- package/dist/commands/validate-all.js.map +1 -1
- package/dist/data/bundle.generated.js +1 -1
- package/dist/data/bundle.generated.js.map +1 -1
- package/dist/data/dataset.d.ts +33 -1
- package/dist/data/dataset.d.ts.map +1 -1
- package/dist/data/dataset.js +107 -1
- package/dist/data/dataset.js.map +1 -1
- package/dist/data/index.d.ts +4 -0
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +4 -0
- package/dist/data/index.js.map +1 -1
- package/dist/data/types.d.ts +3 -1
- package/dist/data/types.d.ts.map +1 -1
- package/dist/data/types.js +1 -0
- package/dist/data/types.js.map +1 -1
- package/dist/gen-conformance.js +162 -0
- package/dist/gen-conformance.js.map +1 -1
- package/dist/generated.d.ts +125 -0
- package/dist/generated.d.ts.map +1 -1
- package/dist/generated.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrity.d.ts +32 -0
- package/dist/integrity.d.ts.map +1 -0
- package/dist/integrity.js +120 -0
- package/dist/integrity.js.map +1 -0
- package/dist/report.d.ts +1 -1
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +2 -2
- package/dist/report.js.map +1 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +42 -0
- package/dist/runner.js.map +1 -1
- package/dist/share/codec.d.ts +83 -0
- package/dist/share/codec.d.ts.map +1 -0
- package/dist/share/codec.js +230 -0
- package/dist/share/codec.js.map +1 -0
- package/dist/share/index.d.ts +30 -0
- package/dist/share/index.d.ts.map +1 -0
- package/dist/share/index.js +36 -0
- package/dist/share/index.js.map +1 -0
- package/dist/share/registry.d.ts +42 -0
- package/dist/share/registry.d.ts.map +1 -0
- package/dist/share/registry.generated.d.ts +4 -0
- package/dist/share/registry.generated.d.ts.map +1 -0
- package/dist/share/registry.generated.js +4 -0
- package/dist/share/registry.generated.js.map +1 -0
- package/dist/share/registry.js +68 -0
- package/dist/share/registry.js.map +1 -0
- package/dist/terrain/index.d.ts +2 -2
- package/dist/terrain/index.d.ts.map +1 -1
- package/dist/terrain/index.js +1 -1
- package/dist/terrain/index.js.map +1 -1
- package/dist/terrain/solve.d.ts +76 -0
- package/dist/terrain/solve.d.ts.map +1 -1
- package/dist/terrain/solve.js +138 -0
- package/dist/terrain/solve.js.map +1 -1
- package/dist/translate/condition.d.ts +1 -0
- package/dist/translate/condition.d.ts.map +1 -1
- package/dist/translate/condition.js +101 -7
- package/dist/translate/condition.js.map +1 -1
- package/dist/translate/effect.d.ts +28 -20
- package/dist/translate/effect.d.ts.map +1 -1
- package/dist/translate/effect.js +483 -114
- package/dist/translate/effect.js.map +1 -1
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +1 -0
- package/dist/validate.js.map +1 -1
- package/package.json +3 -1
- package/schemas/core/allied-rule.schema.json +115 -0
- package/schemas/core/detachment.schema.json +38 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effect.js","sourceRoot":"","sources":["../../src/translate/effect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAkB,MAAM,gBAAgB,CAAC;AAkD5E,yEAAyE;AACzE,SAAS,IAAI,CAAC,CAAU;IACtB,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,GAAG,CAAC;IAC1B,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpD,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,YAAY,CAAC,CAAU;IAC9B,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AACnC,CAAC;AAED,SAAS,MAAM,CAAC,SAAkB,EAAE,KAAc;IAChD,MAAM,EAAE,GAAG,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACtE,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,SAAkB;IACxD,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,KAAK;YACR,OAAO,GAAG,EAAE,GAAG,CAAC;QAClB,KAAK,KAAK;YACR,OAAO,GAAG,EAAE,UAAU,CAAC;QACzB,KAAK,IAAI;YACP,OAAO,gBAAgB,EAAE,EAAE,CAAC;QAC9B,KAAK,IAAI;YACP,OAAO,aAAa,EAAE,EAAE,CAAC;QAC3B,KAAK,IAAI;YACP,OAAO,WAAW,EAAE,EAAE,CAAC;QACzB;YACE,OAAO,GAAG,EAAE,GAAG,CAAC;IACpB,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,oBAAoB,CAAC,CAAS;IAC5C,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAEtC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,MAAM,KAAK,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI;gBAAE,OAAO,oBAAoB,MAAM,EAAE,CAAC;YACxD,IAAI,CAAC,CAAC,SAAS,KAAK,KAAK;gBAAE,OAAO,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,KAAK,QAAQ,MAAM,EAAE,CAAC;YAClG,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,MAAM,EAAE,CAAC;QACjF,CAAC;QACD,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI;gBAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,QAAQ,MAAM,EAAE,CAAC;YACtG,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,QAAQ,MAAM,EAAE,CAAC;QACxF,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,OAAO,WAAW,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,GAAG,GAAG,QAAQ,MAAM,EAAE,CAAC;QACtE,CAAC;QACD,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC1E,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,YAAY,CAAC;YACxC,MAAM,MAAM,GAAG,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAChE,OAAO,QAAQ,IAAI,CAAC,MAAM,CAAC,qBAAqB,MAAM,GAAG,MAAM,EAAE,CAAC;QACpE,CAAC;QACD,KAAK,cAAc;YACjB,OAAO,GAAG,MAAM,uBAAuB,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC;QAC9D,KAAK,MAAM;YACT,OAAO,GAAG,MAAM,eAAe,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;QACjE,KAAK,mBAAmB;YACtB,OAAO,GAAG,MAAM,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC;QACjE,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC,CAAC;YACvG,IAAI,CAAC,CAAC,WAAW,IAAI,IAAI;gBAAE,OAAO,GAAG,MAAM,MAAM,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,UAAU,EAAE,EAAE,CAAC;YACnF,IAAI,CAAC,CAAC,WAAW,IAAI,IAAI;gBAAE,OAAO,GAAG,MAAM,MAAM,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,iBAAiB,EAAE,EAAE,CAAC;YAC1F,OAAO,GAAG,MAAM,mBAAmB,EAAE,EAAE,CAAC;QAC1C,CAAC;QACD,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,CAAC;YAC3C,MAAM,GAAG,GAAG,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,OAAO,GAAG,MAAM,UAAU,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,GAAG,EAAE,CAAC;QACxF,CAAC;QACD,KAAK,mBAAmB,CAAC,CAAC,CAAC;YACzB,MAAM,IAAI,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC;YACnC,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC;YACnC,MAAM,MAAM,GAAG,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,OAAO,GAAG,MAAM,UAAU,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,GAAG,MAAM,EAAE,CAAC;QAChG,CAAC;QACD,KAAK,kBAAkB;YACrB,OAAO,6BAA6B,MAAM,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/E,KAAK,cAAc;YACjB,OAAO,UAAU,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,gBAAgB,MAAM,SAAS,IAAI,CAAC,CAAC,CAAC,gBAAgB,IAAI,MAAM,CAAC,SAAS,CAAC;QAChH,KAAK,mBAAmB;YACtB,OAAO,WAAW,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,6BAA6B,MAAM,EAAE,CAAC;QACvE,KAAK,SAAS;YACZ,OAAO,QAAQ,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QACrC,KAAK,WAAW;YACd,OAAO,UAAU,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QACvC,KAAK,eAAe;YAClB,OAAO,QAAQ,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QACxD,KAAK,gBAAgB;YACnB,OAAO,SAAS,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3D,KAAK,qBAAqB,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI;gBAAE,OAAO,WAAW,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,MAAM,EAAE,CAAC;YACvG,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI;gBAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,cAAc,MAAM,EAAE,CAAC;YACxG,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI;gBAAE,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC;YAC3F,OAAO,yBAAyB,MAAM,EAAE,CAAC;QAC3C,CAAC;QACD,KAAK,aAAa;YAChB,OAAO,GAAG,MAAM,eAAe,CAAC;QAClC,KAAK,YAAY;YACf,OAAO,GAAG,MAAM,cAAc,CAAC;QACjC,KAAK,gBAAgB;YACnB,OAAO,GAAG,MAAM,kBAAkB,CAAC;QACrC,KAAK,gBAAgB;YACnB,OAAO,GAAG,MAAM,kBAAkB,CAAC;QACrC,KAAK,aAAa;YAChB,OAAO,GAAG,MAAM,kBAAkB,CAAC;QACrC,KAAK,kBAAkB;YACrB,OAAO,GAAG,MAAM,wBAAwB,CAAC;QAC3C,KAAK,oBAAoB,CAAC,CAAC,CAAC;YAC1B,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,gBAAgB,CAAC;YACjD,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9E,OAAO,GAAG,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,GAAG,KAAK,GAAG,GAAG,EAAE,CAAC;QACjG,CAAC;QACD,KAAK,4BAA4B,CAAC,CAAC,CAAC;YAClC,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI;gBAAE,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,MAAM,EAAE,CAAC;YACnF,OAAO,gBAAgB,MAAM,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,CAAC;QACD,KAAK,aAAa;YAChB,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,MAAM,EAAE,CAAC;QAC5D,KAAK,sBAAsB;YACzB,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,wBAAwB,MAAM,EAAE,CAAC;QACzE,KAAK,wBAAwB;YAC3B,OAAO,GAAG,MAAM,oCAAoC,CAAC;QACvD,KAAK,kBAAkB;YACrB,OAAO,2BAA2B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC3D,KAAK,eAAe;YAClB,OAAO,wBAAwB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACxD,KAAK,UAAU;YACb,OAAO,OAAO,MAAM,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAEpD,kCAAkC;QAClC,KAAK,aAAa;YAChB,OAAO,MAAM,iBAAiB,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,KAAK,oBAAoB,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;QAC/F,KAAK,UAAU;YACb,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,OAAO,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1F,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,IAAI,GAAG,gBAAgB,CAAC,CAAC,CAAC,UAAU,IAAI,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;YAClE,MAAM,OAAO,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC9E,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,OAAO,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,OAAO,GAAG,IAAI,EAAE,CAAC;QAC/D,CAAC;QACD,KAAK,sBAAsB,CAAC,CAAC,CAAC;YAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YACvE,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;iBAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,SAAS,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;iBAC3G,IAAI,CAAC,KAAK,CAAC,CAAC;YACf,OAAO,QAAQ,IAAI,KAAK,IAAI,EAAE,CAAC;QACjC,CAAC;QAED;YACE,OAAO,IAAI,CAAC,CAAC,IAAI,IAAI,SAAS,GAAG,CAAC;IACtC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,CAAS,EAAE,QAAgB,CAAC;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAErC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,aAAa;YAChB,OAAO,GAAG,MAAM,MAAM,iBAAiB,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QAC9G,KAAK,UAAU;YACb,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzE,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,OAAO,CACL,GAAG,MAAM,GAAG,KAAK,aAAa,KAAK,KAAK;gBACxC,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,KAAK,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAC9F,CAAC;QACJ,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,IAAI,GAAG,gBAAgB,CAAC,CAAC,CAAC,UAAU,IAAI,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC;YAClE,MAAM,OAAO,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC9E,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,OAAO,GAAG,MAAM,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,OAAO,GAAG,IAAI,EAAE,CAAC;QAChF,CAAC;QACD,KAAK,sBAAsB,CAAC,CAAC,CAAC;YAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YACvE,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,GAAG,KAAK,QAAQ,IAAI,SAAS,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;YAC9F,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;gBAClC,KAAK,CAAC,IAAI,CACR,GAAG,MAAM,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,QAAQ,oBAAoB,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAC3J,CAAC;YACJ,CAAC;YACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QACD;YACE,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,CAAC;AACH,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,aAAa,CAAC,CAAgB;IAC5C,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3E,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAC3C,OAAO,UAAU,KAAK,GAAG,MAAM,eAAe,QAAQ,GAAG,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,CAA2B;IAC3D,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAClB,MAAM,QAAQ,GAAG,CAAC,CAAC,iBAAiB,IAAI,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,CAAC,CAAC,iBAAiB,IAAI,EAAE,CAAC;IAC3C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9D,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IACjF,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,OAAO,eAAe,IAAI,GAAG,GAAG,GAAG,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,CAAc;IAC5C,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,MAAM,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAChD,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7D,CAAC","sourcesContent":["/**\n * Humanize an Ability-DSL `effect` tree into plain English — the\n * `ability.print()` of the dataset. Output is an *approximation* generated\n * purely from the structured data (no external rules text), ASCII-only, with\n * a fixed clause order: it is pinned byte-for-byte across the TS and Rust\n * ports by the `conformance/effect-translation` corpus, so any phrasing\n * change here is a semantic corpus change (bump `conformance/SPEC_VERSION`).\n *\n * Container nodes (`sequence`, `conditional`, `choice`, `dice-gated`,\n * `dice-pool-allocation`) render block-style with two-space indentation and\n * an ASCII `-> ` arrow; leaves render as single clauses. Unknown leaf types\n * and unrecognized modifier shapes degrade to a deterministic bracketed form\n * (`[the-type]`) rather than failing — coverage improves as authoring does.\n */\n\nimport { describeCondition, dekebab, type Condition } from \"./condition.js\";\n\n/**\n * Minimal structural view of an effect node. Matches the ability-dsl effect\n * schema: a single effect carries `type` + `target` + `modifier`; containers\n * carry their own shape (`steps`, `options`, `condition`/`effect`, dice\n * fields).\n */\nexport interface Effect {\n type?: string;\n target?: string;\n modifier?: Record<string, unknown>;\n condition?: Condition;\n effect?: Effect;\n steps?: Effect[];\n options?: (Effect & {\n name?: string;\n requirement?: Record<string, unknown>;\n })[];\n choice_label?: string;\n dice?: string;\n threshold?: number | string;\n comparison?: string;\n on_success?: Effect | null;\n on_fail?: Effect | null;\n pool?: { count: number; die: string };\n max_activations?: number;\n}\n\n/** Ability scope, as carried on enrichment ability entries. */\nexport interface AbilityScope {\n range?: string;\n duration?: string;\n range_inches?: number;\n}\n\n/** Curated keyword filter naming which units an ability benefits. */\nexport interface AbilityAppliesTo {\n required_keywords?: string[];\n excluded_keywords?: string[];\n}\n\n/** Minimal ability view for `describeAbility`. */\nexport interface AbilityLike {\n name?: string;\n effect?: Effect;\n scope?: AbilityScope;\n applies_to?: AbilityAppliesTo | null;\n}\n\n/** JS-template stringification (numbers print without trailing `.0`). */\nfunction jstr(v: unknown): string {\n if (v == null) return \"?\";\n if (Array.isArray(v)) return v.map(jstr).join(\", \");\n return String(v);\n}\n\nfunction formatTarget(t?: string): string {\n return t ? dekebab(t) : \"target\";\n}\n\nfunction signed(operation: unknown, value: unknown): string {\n const op = operation === \"add\" || operation === \"improve\" ? \"+\" : \"-\";\n return `${op}${jstr(value)}`;\n}\n\nfunction formatComparison(comp: string, threshold: unknown): string {\n const th = jstr(threshold);\n switch (comp) {\n case \"gte\":\n return `${th}+`;\n case \"lte\":\n return `${th} or less`;\n case \"gt\":\n return `greater than ${th}`;\n case \"lt\":\n return `less than ${th}`;\n case \"eq\":\n return `exactly ${th}`;\n default:\n return `${th}+`;\n }\n}\n\n/** Single-clause translation for leaf effects (and inline container forms). */\nexport function describeEffectInline(e: Effect): string {\n const m = e.modifier ?? {};\n const target = formatTarget(e.target);\n\n switch (e.type) {\n case \"stat-modifier\": {\n const scope = m.attack_type ? ` (${jstr(m.attack_type)})` : \"\";\n if (m.stat == null) return `modify stats for ${target}`;\n if (m.operation === \"set\") return `set ${jstr(m.stat)} to ${jstr(m.value)}${scope} for ${target}`;\n return `${signed(m.operation, m.value)} ${jstr(m.stat)}${scope} for ${target}`;\n }\n case \"roll-modifier\": {\n const ctx = m.context ? ` (${jstr(m.context)})` : \"\";\n if (m.value == null) return `${dekebab(jstr(m.operation))} ${jstr(m.roll)} rolls${ctx} for ${target}`;\n return `${signed(m.operation, m.value)} to ${jstr(m.roll)} rolls${ctx} for ${target}`;\n }\n case \"re-roll\": {\n const subset = m.subset ? ` (${dekebab(jstr(m.subset))})` : \"\";\n const atk = m.attack_type ? ` (${jstr(m.attack_type)})` : \"\";\n return `re-roll ${jstr(m.roll)} rolls${subset}${atk} for ${target}`;\n }\n case \"mortal-wounds\": {\n const amount = m.count ?? m.amount ?? (m.amount_table ? \"variable\" : \"?\");\n const range = m.range ?? m.range_inches;\n const within = range != null ? ` (within ${jstr(range)}\")` : \"\";\n return `deal ${jstr(amount)} mortal wounds to ${target}${within}`;\n }\n case \"feel-no-pain\":\n return `${target} gains Feel No Pain ${jstr(m.threshold)}+`;\n case \"ward\":\n return `${target} gains Ward ${jstr(m.threshold ?? m.value)}+`;\n case \"invulnerable-save\":\n return `${target} gains a ${jstr(m.value)}+ invulnerable save`;\n case \"keyword-grant\": {\n const kw = Array.isArray(m.keywords) ? m.keywords.map(jstr).join(\", \") : jstr(m.keyword ?? \"keywords\");\n if (m.weapon_name != null) return `${target}'s ${jstr(m.weapon_name)} gains ${kw}`;\n if (m.weapon_type != null) return `${target}'s ${jstr(m.weapon_type)} weapons gain ${kw}`;\n return `${target}'s weapons gain ${kw}`;\n }\n case \"ability-grant\": {\n const grant = m.grant_type ?? m.ability_id;\n const cap = m.capacity != null ? ` (${jstr(m.capacity)})` : \"\";\n return `${target} gains ${grant != null ? dekebab(jstr(grant)) : \"an ability\"}${cap}`;\n }\n case \"movement-modifier\": {\n const kind = m.move_type ?? m.type;\n const dist = m.distance ?? m.value;\n const inches = dist != null ? ` ${jstr(dist)}\"` : \"\";\n return `${target} gains ${kind != null ? dekebab(jstr(kind)) : \"a movement effect\"}${inches}`;\n }\n case \"damage-reduction\":\n return `reduce incoming damage to ${target} by ${jstr(m.amount ?? m.value)}`;\n case \"resurrection\":\n return `return ${jstr(m.count ?? 1)} model(s) to ${target} with ${jstr(m.wounds_remaining ?? \"full\")} wounds`;\n case \"model-destruction\":\n return `destroy ${jstr(m.count)} non-leader model(s) from ${target}`;\n case \"cp-gain\":\n return `gain ${jstr(m.amount)} CP`;\n case \"cp-refund\":\n return `refund ${jstr(m.amount)} CP`;\n case \"resource-gain\":\n return `gain ${jstr(m.amount)} to ${jstr(m.pool_id)}`;\n case \"resource-spend\":\n return `spend ${jstr(m.amount)} from ${jstr(m.pool_id)}`;\n case \"leadership-modifier\": {\n if (m.test != null && m.operation == null) return `force a ${dekebab(jstr(m.test))} test on ${target}`;\n if (m.test != null) return `${dekebab(jstr(m.operation))} ${dekebab(jstr(m.test))} tests for ${target}`;\n if (m.operation != null) return `${signed(m.operation, m.value)} Leadership for ${target}`;\n return `modify Leadership for ${target}`;\n }\n case \"fight-first\":\n return `${target} fights first`;\n case \"fight-last\":\n return `${target} fights last`;\n case \"fight-on-death\":\n return `${target} fights on death`;\n case \"shoot-on-death\":\n return `${target} shoots on death`;\n case \"deep-strike\":\n return `${target} can deep strike`;\n case \"fallback-and-act\":\n return `${target} can fall back and act`;\n case \"attack-restriction\": {\n const what = m.restriction ?? m.restriction_type;\n const range = m.range != null ? ` (within ${jstr(m.range)}\")` : \"\";\n const max = m.max_models != null ? ` (max ${jstr(m.max_models)} models)` : \"\";\n return `${target}: ${what != null ? dekebab(jstr(what)) : \"attack restriction\"}${range}${max}`;\n }\n case \"objective-control-modifier\": {\n if (m.operation != null) return `${signed(m.operation, m.value)} OC for ${target}`;\n return `modify OC of ${target} by ${jstr(m.value)}`;\n }\n case \"bs-modifier\":\n return `${signed(m.operation, m.value)} BS for ${target}`;\n case \"charge-roll-modifier\":\n return `${signed(m.operation, m.value)} to charge rolls for ${target}`;\n case \"engagement-passthrough\":\n return `${target} can move through engagement range`;\n case \"terrain-area-tag\":\n return `tag the terrain area as ${dekebab(jstr(m.tag))}`;\n case \"objective-tag\":\n return `tag the objective as ${dekebab(jstr(m.tag))}`;\n case \"unit-tag\":\n return `tag ${target} as ${dekebab(jstr(m.tag))}`;\n\n // Container types — inline forms.\n case \"conditional\":\n return `if ${describeCondition(e.condition ?? {})}: ${describeEffectInline(e.effect ?? {})}`;\n case \"sequence\":\n return (e.steps ?? []).map(describeEffectInline).join(\"; \");\n case \"choice\": {\n const label = e.choice_label ? ` (${e.choice_label})` : \"\";\n return `choose one${label}: ${(e.options ?? []).map(describeEffectInline).join(\" / \")}`;\n }\n case \"dice-gated\": {\n const comp = formatComparison(e.comparison ?? \"gte\", e.threshold);\n const success = e.on_success ? describeEffectInline(e.on_success) : \"nothing\";\n const fail = e.on_fail ? `, otherwise ${describeEffectInline(e.on_fail)}` : \"\";\n return `roll ${jstr(e.dice)}: on ${comp}, ${success}${fail}`;\n }\n case \"dice-pool-allocation\": {\n const pool = e.pool ? `${jstr(e.pool.count)}${jstr(e.pool.die)}` : \"?\";\n const opts = (e.options ?? [])\n .map((o) => `${jstr(o.name)} (${jstr(o.requirement?.min_value)}+): ${describeEffectInline(o.effect ?? {})}`)\n .join(\" / \");\n return `roll ${pool}: ${opts}`;\n }\n\n default:\n return `[${e.type ?? \"unknown\"}]`;\n }\n}\n\n/**\n * Block translation of an effect tree. Containers expand over multiple lines\n * with two-space indentation; leaves delegate to `describeEffectInline`.\n */\nexport function describeEffect(e: Effect, depth: number = 0): string {\n const indent = \" \".repeat(depth);\n const arrow = depth > 0 ? \"-> \" : \"\";\n\n switch (e.type) {\n case \"conditional\":\n return `${indent}If ${describeCondition(e.condition ?? {})}:\\n` + describeEffect(e.effect ?? {}, depth + 1);\n case \"sequence\":\n return (e.steps ?? []).map((s) => describeEffect(s, depth)).join(\"\\n\");\n case \"choice\": {\n const label = e.choice_label ? ` (${e.choice_label})` : \"\";\n return (\n `${indent}${arrow}Choose one${label}:\\n` +\n (e.options ?? []).map((o, i) => `${indent} ${i + 1}. ${describeEffectInline(o)}`).join(\"\\n\")\n );\n }\n case \"dice-gated\": {\n const comp = formatComparison(e.comparison ?? \"gte\", e.threshold);\n const success = e.on_success ? describeEffectInline(e.on_success) : \"nothing\";\n const fail = e.on_fail ? `, otherwise ${describeEffectInline(e.on_fail)}` : \"\";\n return `${indent}${arrow}Roll ${jstr(e.dice)}: on ${comp}, ${success}${fail}`;\n }\n case \"dice-pool-allocation\": {\n const pool = e.pool ? `${jstr(e.pool.count)}${jstr(e.pool.die)}` : \"?\";\n const lines = [`${indent}${arrow}Roll ${pool} (max ${jstr(e.max_activations)} activations):`];\n for (const opt of e.options ?? []) {\n lines.push(\n `${indent} - ${jstr(opt.name)}: need ${jstr(opt.requirement?.type)} of ${jstr(opt.requirement?.min_value)}+ -> ${describeEffectInline(opt.effect ?? {})}`\n );\n }\n return lines.join(\"\\n\");\n }\n default:\n return `${indent}${arrow}${describeEffectInline(e)}`;\n }\n}\n\n/** `Scope: aura (6\"). Duration: phase.` — empty string when absent. */\nexport function describeScope(s?: AbilityScope): string {\n if (!s || (!s.range && !s.duration)) return \"\";\n const range = dekebab(s.range ?? \"\");\n const inches = s.range_inches != null ? ` (${jstr(s.range_inches)}\")` : \"\";\n const duration = dekebab(s.duration ?? \"\");\n return `Scope: ${range}${inches}. Duration: ${duration}.`;\n}\n\n/**\n * `Applies to: units with Possessed.` — the roster-highlighting audience named\n * by a curated `applies_to` filter. Empty string when the filter is absent or\n * carries no keywords (nothing to say). `required_keywords` reads as an AND set;\n * `excluded_keywords` render as a trailing `(excluding …)`.\n */\nexport function describeAppliesTo(a?: AbilityAppliesTo | null): string {\n if (!a) return \"\";\n const required = a.required_keywords ?? [];\n const excluded = a.excluded_keywords ?? [];\n if (required.length === 0 && excluded.length === 0) return \"\";\n const base = required.length ? `units with ${required.join(\", \")}` : \"all units\";\n const exc = excluded.length ? ` (excluding ${excluded.join(\", \")})` : \"\";\n return `Applies to: ${base}${exc}.`;\n}\n\n/**\n * Full generated text for an ability: the effect tree, a trailing scope line,\n * and a trailing `Applies to:` line when the ability carries a curated\n * `applies_to` filter. This is the `ability.print()` consumers render when the\n * dataset carries no rules prose.\n */\nexport function describeAbility(a: AbilityLike): string {\n const effect = a.effect ? describeEffect(a.effect) : \"\";\n const scope = describeScope(a.scope);\n const applies = describeAppliesTo(a.applies_to);\n return [effect, scope, applies].filter(Boolean).join(\"\\n\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"effect.js","sourceRoot":"","sources":["../../src/translate/effect.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Humanize an Ability-DSL `effect` tree into natural English — the\n * `ability.print()` of the dataset. Output is an *approximation* generated\n * purely from the structured data (no external rules text): subject-first,\n * GW-datasheet voice, with scope range + duration woven into the sentence and\n * single-leaf conditionals inlined. ASCII-only. It is pinned byte-for-byte\n * across the TS / Rust / Python ports by the `conformance/effect-translation`\n * corpus, so any phrasing change here is a semantic corpus change (bump\n * `conformance/SPEC_VERSION`).\n *\n * Container nodes (`sequence`, `choice`, `dice-gated`, `dice-pool-allocation`,\n * and a `conditional` wrapping a container) render block-style with two-space\n * indentation; a `conditional` wrapping a single leaf inlines to one sentence.\n * Unknown leaf types degrade to a deterministic bracketed form (`[the-type]`).\n */\n\nimport { describeCondition, describeTiming, dekebab, type Condition } from \"./condition.js\";\n\n/**\n * Minimal structural view of an effect node. Matches the ability-dsl effect\n * schema: a single effect carries `type` + `target` + `modifier`; containers\n * carry their own shape (`steps`, `options`, `condition`/`effect`, dice\n * fields).\n */\nexport interface Effect {\n type?: string;\n target?: string;\n modifier?: Record<string, unknown>;\n condition?: Condition;\n effect?: Effect;\n steps?: Effect[];\n options?: (Effect & {\n name?: string;\n requirement?: Record<string, unknown>;\n })[];\n choice_label?: string;\n dice?: string;\n threshold?: number | string;\n comparison?: string;\n on_success?: Effect | null;\n on_fail?: Effect | null;\n pool?: { count: number; die: string };\n max_activations?: number;\n}\n\n/** Ability scope, as carried on enrichment ability entries. */\nexport interface AbilityScope {\n range?: string;\n duration?: string;\n range_inches?: number;\n}\n\n/** Curated keyword filter naming which units an ability benefits. */\nexport interface AbilityAppliesTo {\n required_keywords?: string[];\n excluded_keywords?: string[];\n}\n\n/** Minimal ability view for `describeAbility`. */\nexport interface AbilityLike {\n name?: string;\n effect?: Effect;\n scope?: AbilityScope;\n applies_to?: AbilityAppliesTo | null;\n}\n\n/** Rendering context threaded down from the ability (scope info the leaf needs). */\ninterface Ctx {\n /** Aura/blast radius in inches, for `*-within-aura` targets and within-range effects. */\n rangeInches?: number;\n}\n\nconst CONTAINER_TYPES = new Set([\n \"sequence\",\n \"choice\",\n \"dice-gated\",\n \"dice-pool-allocation\",\n]);\n\n/** JS-template stringification (numbers print without trailing `.0`). */\nfunction jstr(v: unknown): string {\n if (v == null) return \"?\";\n if (Array.isArray(v)) return v.map(jstr).join(\", \");\n return String(v);\n}\n\n/** Uppercase the first character (idempotent; leaves the rest untouched). */\nfunction capitalize(s: string): string {\n return s.length === 0 ? s : s[0].toUpperCase() + s.slice(1);\n}\n\n/** Small words kept lowercase mid-phrase in Title Case (`Benefit of Cover`, not `Benefit Of Cover`). */\nconst TITLE_SMALL = new Set([\"of\", \"or\", \"and\", \"the\", \"a\", \"an\", \"to\", \"in\", \"on\", \"for\", \"with\"]);\n\n/** kebab/space token → Title Case (`deep-strike` → `Deep Strike`, `shoot-and-scoot` → `Shoot and Scoot`). */\nfunction titleCase(s: string): string {\n return dekebab(s)\n .split(\" \")\n .map((w, i) => {\n if (w.length === 0) return w;\n if (i > 0 && TITLE_SMALL.has(w.toLowerCase())) return w.toLowerCase();\n return w[0].toUpperCase() + w.slice(1);\n })\n .join(\" \");\n}\n\n/** A GW weapon keyword token → bracketed caps (`lethal-hits` → `[LETHAL HITS]`). */\nfunction bracketKeyword(k: unknown): string {\n return `[${dekebab(jstr(k)).toUpperCase()}]`;\n}\n\n/** Dice tokens print with a capital `D` (`d3` → `D3`, `2d6` → `2D6`). */\nfunction diceCase(v: unknown): string {\n return jstr(v).replace(/d/gi, \"D\");\n}\n\n/** A leadership/escape test token → GW name (`battle-shock` → `Battle-shock`). */\nconst TEST_NAMES: Record<string, string> = {\n \"battle-shock\": \"Battle-shock\",\n \"desperate-escape\": \"Desperate Escape\",\n};\nfunction testName(test: unknown): string {\n const t = jstr(test);\n return TEST_NAMES[t] ?? titleCase(t);\n}\n\n/** Does a subject noun phrase take a plural verb? (`enemy units within 6\"`, `all friendly units`). */\nfunction isPlural(subj: string): boolean {\n return / units\\b/.test(subj) || /^all /.test(subj) || /^(enemy|friendly) units/.test(subj);\n}\n\n/** Subject-verb agreement: pick the plural form of a present-tense verb when the subject is plural. */\nconst PLURAL_VERBS: Record<string, string> = {\n has: \"have\",\n is: \"are\",\n gets: \"get\",\n gains: \"gain\",\n suffers: \"suffer\",\n retains: \"retain\",\n makes: \"make\",\n};\nfunction v(subj: string, singular: string): string {\n if (!isPlural(subj)) return singular;\n return PLURAL_VERBS[singular] ?? singular.replace(/s$/, \"\");\n}\n\n/** Full characteristic name for a stat token (`Sv` → `Save`). */\nconst STAT_NAMES: Record<string, string> = {\n M: \"Move\",\n T: \"Toughness\",\n Sv: \"Save\",\n W: \"Wounds\",\n A: \"Attacks\",\n Ld: \"Leadership\",\n OC: \"Objective Control\",\n S: \"Strength\",\n WS: \"Weapon Skill\",\n BS: \"Ballistic Skill\",\n AP: \"Armour Penetration\",\n D: \"Damage\",\n Range: \"Range\",\n};\n\nfunction statName(stat: unknown): string {\n const s = jstr(stat);\n return STAT_NAMES[s] ?? titleCase(s);\n}\n\n/** Resource-pool token → display name (`cp` → `CP`, otherwise Title Case). */\nfunction poolName(pool: unknown): string {\n const p = jstr(pool);\n return p.toLowerCase() === \"cp\" ? \"CP\" : titleCase(p);\n}\n\n/** Roll noun for a roll token (`hit` → `Hit`, `attacks-characteristic` → `Attacks characteristic`). */\nconst ROLL_NAMES: Record<string, string> = {\n hit: \"Hit\",\n wound: \"Wound\",\n charge: \"Charge\",\n damage: \"Damage\",\n advance: \"Advance\",\n save: \"Saving throw\",\n leadership: \"Leadership\",\n};\n\nfunction rollName(roll: unknown): string {\n const r = jstr(roll);\n return ROLL_NAMES[r] ?? titleCase(r);\n}\n\n/** `+1` / `-1` from an operation + value (a negative value flips the sign, so never `+-1`). */\nfunction signed(operation: unknown, value: unknown): string {\n const positive = operation === \"add\" || operation === \"improve\";\n let sign = positive ? 1 : -1;\n const n = Number(value);\n if (!Number.isNaN(n) && n < 0) {\n sign = -sign;\n value = Math.abs(n);\n }\n return `${sign > 0 ? \"+\" : \"-\"}${jstr(value)}`;\n}\n\n/** Dice comparison → \"a 4+\", \"a 3 or less\", etc. (for dice-gated thresholds). */\nfunction formatComparison(comp: string, threshold: unknown): string {\n const th = jstr(threshold);\n switch (comp) {\n case \"gte\":\n return `a ${th}+`;\n case \"lte\":\n return `a ${th} or less`;\n case \"gt\":\n return `greater than ${th}`;\n case \"lt\":\n return `less than ${th}`;\n case \"eq\":\n return `exactly ${th}`;\n default:\n return `a ${th}+`;\n }\n}\n\n/**\n * Humanized subject for an effect `target`. Aura targets resolve their radius\n * from the ability scope (threaded via {@link Ctx}); everything else is a fixed\n * noun phrase in GW datasheet voice.\n */\nfunction subject(target: string | undefined, ctx: Ctx): string {\n const within = ctx.rangeInches != null ? ` within ${jstr(ctx.rangeInches)}\"` : \" nearby\";\n switch (target) {\n case \"self\":\n case \"bearer\":\n return \"this model\";\n case \"unit\":\n return \"the unit\";\n case \"attached-unit\":\n return \"the unit this model leads\";\n case \"target\":\n return \"the target\";\n case \"attacker\":\n return \"the attacking unit\";\n case \"defender\":\n return \"your unit\";\n case \"all-friendly\":\n return \"all friendly units\";\n case \"all-enemy\":\n return \"all enemy units\";\n case \"friendly-within-aura\":\n return `friendly units${within}`;\n case \"enemy-within-aura\":\n return `enemy units${within}`;\n default:\n return \"the unit\";\n }\n}\n\n/** Possessive form of a subject noun phrase (`the unit` → `the unit's`). */\nfunction possessive(s: string): string {\n return s.endsWith(\"s\") ? `${s}'` : `${s}'s`;\n}\n\n/** Possessive pronoun agreeing with the subject (`its` / `their`). */\nfunction pronoun(subj: string): string {\n return isPlural(subj) ? \"their\" : \"its\";\n}\n\n/**\n * Duration → woven clause. `lead` sits at the very front of the sentence\n * (\"Once per battle, …\"); `trail` sits after the trigger/condition and before\n * the effect (\"…, until the end of the phase, …\"). `permanent` adds nothing.\n */\nfunction durationClauses(duration: string | undefined): { lead: string; trail: string } {\n switch (duration) {\n case \"phase\":\n return { lead: \"\", trail: \"until the end of the phase\" };\n case \"turn\":\n return { lead: \"\", trail: \"until the end of the turn\" };\n case \"battle\":\n return { lead: \"\", trail: \"for the rest of the battle\" };\n case \"battle-round\":\n return { lead: \"\", trail: \"until the end of the battle round\" };\n case \"until-next-command-phase\":\n return { lead: \"\", trail: \"until your next Command phase\" };\n case \"one-use\":\n return { lead: \"once per battle\", trail: \"\" };\n default: // permanent / absent\n return { lead: \"\", trail: \"\" };\n }\n}\n\n/**\n * A condition rendered as a natural lead-in clause (lowercase-initial — the\n * caller capitalizes at the sentence boundary). Falls back to `if <condition>`\n * for shapes without a dedicated framing.\n */\nfunction conditionLeadIn(c: Condition): string {\n // Compound nodes recurse so each part reads in its natural framing.\n if (c.operator === \"and\" && c.operands) return c.operands.map(conditionLeadIn).join(\", \");\n if (c.operator === \"or\" && c.operands) return c.operands.map(conditionLeadIn).join(\" or \");\n if (c.operator === \"not\" && c.operands)\n return `unless ${c.operands.map((o) => conditionLeadIn(o).replace(/^if /, \"\")).join(\" or \")}`;\n if (c.negated) return `if ${describeCondition(c)}`;\n\n const p = c.parameters ?? {};\n switch (c.type) {\n case \"phase-is\":\n return `during the ${titleCase(jstr(p.phase))} phase`;\n case \"is-attached\":\n return `after being attached to a ${p.keyword ? `${jstr(p.keyword)} ` : \"\"}unit`;\n case \"timing-is\":\n return describeTiming(p.timing);\n case \"player-turn-is\":\n return p.turn === \"your-turn\"\n ? \"in your turn\"\n : p.turn === \"opponent-turn\"\n ? \"in the opponent's turn\"\n : \"in either player's turn\";\n case \"model-is-leader\":\n return \"while this model leads a unit\";\n case \"charged-this-turn\":\n return \"if the unit charged this turn\";\n case \"advanced-this-turn\":\n return \"if the unit Advanced this turn\";\n case \"remained-stationary\":\n return \"if the unit Remained Stationary\";\n case \"target-has-keyword\":\n return `against ${jstr(p.keyword)} targets`;\n case \"unit-has-keyword\":\n return `if the unit has the ${jstr(p.keyword)} keyword`;\n case \"is-battle-shocked\":\n return \"while the unit is Battle-shocked\";\n case \"unit-below-half-strength\":\n return \"while the unit is below half strength\";\n case \"unit-below-starting-strength\":\n return \"while the unit is below its starting strength\";\n case \"has-lost-wounds\":\n return \"while the model has lost wounds\";\n case \"attack-is-type\":\n if (p.comparison === \"strength-greater-than-toughness\")\n return \"when this attack's Strength is greater than the target's Toughness\";\n if (p.comparison != null) return `when ${dekebab(jstr(p.comparison))}`;\n return `with ${jstr(p.attack_type)} attacks`;\n case \"destroyed-by-attack-type\":\n return `when destroyed by a ${jstr(p.attack_type)} attack`;\n case \"opponent-unit-within-range\": {\n let where: string;\n if (p.weapon_name != null) where = `range of ${dekebab(jstr(p.weapon_name))}`;\n else if (p.range_multiplier != null) where = \"half range of its ranged weapons\";\n else where = p.range === \"engagement\" ? \"engagement range\" : `${jstr(p.range)}\"`;\n return `while an enemy unit is within ${where}`;\n }\n default:\n return `if ${describeCondition(c)}`;\n }\n}\n\n/** Single-clause translation for leaf effects (lowercase-initial, no period). */\nexport function describeEffectInline(e: Effect, ctx: Ctx = {}): string {\n const m = e.modifier ?? {};\n const subj = subject(e.target, ctx);\n\n switch (e.type) {\n case \"stat-modifier\": {\n const scope = m.attack_type ? ` (${jstr(m.attack_type)})` : \"\";\n if (m.stat == null) return `modify ${possessive(subj)} characteristics${scope}`;\n if (m.operation === \"set\")\n return `modify ${possessive(subj)} ${statName(m.stat)} characteristic to ${jstr(m.value)}${scope}`;\n let val = m.value;\n let verb = m.operation === \"subtract\" || m.operation === \"worsen\" ? \"subtract\" : \"add\";\n const n = Number(val); // a negative value flips the verb so we never say \"add -1\"\n if (!Number.isNaN(n) && n < 0) {\n verb = verb === \"add\" ? \"subtract\" : \"add\";\n val = Math.abs(n);\n }\n const prep = verb === \"add\" ? \"to\" : \"from\";\n return `${verb} ${jstr(val)} ${prep} ${possessive(subj)} ${statName(m.stat)} characteristic${scope}`;\n }\n case \"roll-modifier\": {\n const ctxNote = m.context ? ` (${jstr(m.context)})` : \"\";\n if (m.critical_on != null) {\n const crit = m.roll === \"wound\" ? \"Critical Wounds\" : \"Critical Hits\";\n return `${subj} ${v(subj, \"scores\")} ${crit} on ${rollName(m.roll)} rolls of ${jstr(m.critical_on)}+`;\n }\n if (m.value == null) return `${dekebab(jstr(m.operation))} ${possessive(subj)} ${rollName(m.roll)} rolls${ctxNote}`;\n return `${subj} ${v(subj, \"gets\")} ${signed(m.operation, m.value)} to ${rollName(m.roll)} rolls${ctxNote}`;\n }\n case \"re-roll\": {\n const noun = rollName(m.roll);\n const which = m.subset === \"ones\" ? `a ${noun} roll of 1` : `the ${noun} roll`;\n return `you can re-roll ${which}`;\n }\n case \"mortal-wounds\": {\n const range = m.range ?? m.range_inches ?? ctx.rangeInches;\n const subjMW =\n e.target === \"enemy-within-aura\" && range != null\n ? `each enemy unit within ${jstr(range)}\"`\n : subj;\n const verb = subjMW.startsWith(\"each \") ? \"suffers\" : v(subjMW, \"suffers\");\n const a =\n m.count != null\n ? jstr(m.count)\n : m.amount != null\n ? jstr(m.amount)\n : m.dice != null\n ? diceCase(m.dice)\n : m.table || m.amount_table\n ? \"a number of\"\n : null;\n // Deadly-Demise-style triggers carry no count here — the amount is the\n // model's Deadly Demise rating, so describe the trigger instead of \"?\".\n if (a == null && m.trigger != null)\n return `when this model is destroyed, ${subjMW} ${verb} mortal wounds (${titleCase(jstr(m.trigger))})`;\n const amt = a ?? \"?\";\n const noun = amt === \"1\" ? \"mortal wound\" : \"mortal wounds\";\n return `${subjMW} ${verb} ${amt} ${noun}`;\n }\n case \"feel-no-pain\": {\n const vs = m.scope === \"mortal\" ? \" against mortal wounds\" : \"\";\n return `${subj} ${v(subj, \"has\")} the Feel No Pain ${jstr(m.threshold)}+ ability${vs}`;\n }\n case \"ward\":\n return `${subj} ${v(subj, \"has\")} the Ward ${jstr(m.threshold ?? m.value)}+ ability`;\n case \"invulnerable-save\":\n return `${subj} ${v(subj, \"has\")} a ${jstr(m.invuln_sv ?? m.value ?? m.threshold)}+ invulnerable save`;\n case \"keyword-grant\": {\n const kw = Array.isArray(m.keywords)\n ? m.keywords.map(bracketKeyword).join(\" and \")\n : bracketKeyword(m.keyword ?? \"keywords\");\n if (m.weapon_name != null) return `${possessive(subj)} ${jstr(m.weapon_name)} gains ${kw}`;\n if (m.weapon_type != null) return `${possessive(subj)} ${jstr(m.weapon_type)} weapons gain ${kw}`;\n return `${possessive(subj)} weapons gain ${kw}`;\n }\n case \"ability-grant\": {\n const grant = m.grant_type ?? m.ability_id;\n const cap = m.capacity != null ? ` (${jstr(m.capacity)})` : \"\";\n return grant != null\n ? `${subj} ${v(subj, \"gains\")} the ${titleCase(jstr(grant))} ability${cap}`\n : `${subj} ${v(subj, \"gains\")} an ability${cap}`;\n }\n case \"movement-modifier\": {\n const kind = m.move_type ?? m.type;\n if (jstr(kind) === \"move-through\") return `${subj} can move through enemy models and terrain`;\n const dist = m.distance ?? m.value;\n const inches = dist != null && jstr(dist) !== \"0\" ? ` ${jstr(dist)}\"` : \"\";\n return kind != null\n ? `${subj} ${v(subj, \"has\")} the ${titleCase(jstr(kind))}${inches} ability`\n : `${subj} ${v(subj, \"gains\")} a movement ability`;\n }\n case \"damage-reduction\": {\n const r = jstr(m.reduction ?? m.amount ?? m.value);\n const how =\n r === \"half\"\n ? \"halve the Damage of that attack\"\n : r === \"to-zero\"\n ? \"reduce the Damage of that attack to 0\"\n : `reduce the Damage of that attack by ${r}`;\n return `each time an attack targets ${subj}, ${how}`;\n }\n case \"resurrection\": {\n const count = m.count != null ? diceCase(m.count) : \"1\";\n const noun = count === \"1\" ? \"destroyed model\" : \"destroyed models\";\n const wounds = m.wounds_remaining ?? \"full\";\n return `return ${count} ${noun} to ${subj} with ${jstr(wounds)} wounds`;\n }\n case \"model-destruction\": {\n const count = m.count != null ? diceCase(m.count) : \"1\";\n const noun = count === \"1\" ? \"model\" : \"models\";\n return `destroy ${count} ${noun} in ${subj}`;\n }\n case \"cp-gain\":\n return `you gain ${jstr(m.amount ?? 1)}CP`;\n case \"cp-refund\": {\n const strat = m.stratagem != null ? `the ${titleCase(jstr(m.stratagem))} Stratagem` : \"one Stratagem\";\n return `you can use ${strat} on ${subj} for 0CP`;\n }\n case \"resource-gain\":\n return `you gain ${jstr(m.amount ?? m.value)} ${poolName(m.pool_id ?? m.resource)}`;\n case \"resource-spend\":\n return `spend ${jstr(m.amount ?? m.value)} ${poolName(m.pool_id ?? m.resource)}`;\n case \"leadership-modifier\": {\n const test = m.test != null ? `${testName(m.test)} test` : null;\n if (test != null && m.operation == null) return `${subj} must take a ${test}`;\n if (test != null && m.operation === \"re-roll\") return `${subj} can re-roll ${testName(m.test)} tests`;\n if (test != null && m.value != null)\n return `${m.operation === \"add\" ? \"add\" : \"subtract\"} ${jstr(m.value)} ${m.operation === \"add\" ? \"to\" : \"from\"} the ${testName(m.test)} test of ${subj}`;\n if (m.operation != null && m.value != null)\n return `${m.operation === \"add\" || m.operation === \"improve\" ? \"add\" : \"subtract\"} ${jstr(m.value)} ${m.operation === \"add\" || m.operation === \"improve\" ? \"to\" : \"from\"} the Leadership characteristic of ${subj}`;\n return `modify ${possessive(subj)} Leadership characteristic`;\n }\n case \"fight-first\":\n return `${subj} ${v(subj, \"has\")} the Fights First ability`;\n case \"fight-last\":\n return `${subj} ${v(subj, \"has\")} the Fights Last ability`;\n case \"fight-on-death\":\n return subj === \"this model\"\n ? `each time this model is destroyed, it can fight before being removed from play`\n : `each time a model in ${subj} is destroyed, it can fight before being removed from play`;\n case \"shoot-on-death\":\n return subj === \"this model\"\n ? `each time this model is destroyed, it can shoot before being removed from play`\n : `each time a model in ${subj} is destroyed, it can shoot before being removed from play`;\n case \"deep-strike\":\n return `${subj} has the Deep Strike ability`;\n case \"fallback-and-act\":\n return `${subj} is eligible to shoot and declare a charge in a turn in which it Fell Back`;\n case \"engagement-passthrough\":\n return `${subj} can move through enemy models`;\n case \"attack-restriction\":\n return describeAttackRestriction(m, subj);\n case \"objective-control-modifier\": {\n if (m.sticky)\n return `${subj} ${v(subj, \"retains\")} control of objective markers even after no models remain in range, until the enemy retakes them (sticky objectives)`;\n if (m.operation === \"halve\") return `halve the Objective Control characteristic of ${subj}`;\n if (m.operation != null)\n return `${subj} ${v(subj, \"gets\")} ${signed(m.operation, m.value)} to ${pronoun(subj)} Objective Control characteristic`;\n return `modify ${possessive(subj)} Objective Control characteristic`;\n }\n case \"bs-modifier\":\n return `${subj} ${v(subj, \"gets\")} ${signed(m.operation, m.value)} to Ballistic Skill`;\n case \"charge-roll-modifier\":\n return `${subj} ${v(subj, \"gets\")} ${signed(m.operation, m.value)} to Charge rolls`;\n case \"terrain-area-tag\":\n return `the terrain area is marked as ${dekebab(jstr(m.tag))}`;\n case \"objective-tag\":\n return `the objective is marked as ${dekebab(jstr(m.tag))}`;\n case \"unit-tag\":\n return `${subj} ${v(subj, \"is\")} marked as ${dekebab(jstr(m.tag))}`;\n\n // Container types — inline forms.\n case \"conditional\":\n return `${conditionLeadIn(e.condition ?? {})}, ${describeEffectInline(e.effect ?? {}, ctx)}`;\n case \"sequence\":\n return (e.steps ?? []).map((s) => describeEffectInline(s, ctx)).join(\"; \");\n case \"choice\": {\n const label = e.choice_label ? ` (${titleCase(e.choice_label)})` : \"\";\n return `select one of the following${label}: ${(e.options ?? []).map((o) => describeEffectInline(o, ctx)).join(\" / \")}`;\n }\n case \"dice-gated\": {\n const comp = formatComparison(e.comparison ?? \"gte\", e.threshold);\n const success = e.on_success ? describeEffectInline(e.on_success, ctx) : \"nothing happens\";\n const fail = e.on_fail ? `; otherwise, ${describeEffectInline(e.on_fail, ctx)}` : \"\";\n return `roll one ${diceCase(e.dice)}: on ${comp}, ${success}${fail}`;\n }\n case \"dice-pool-allocation\": {\n const pool = e.pool ? `${jstr(e.pool.count)}${jstr(e.pool.die)}` : \"?\";\n const opts = (e.options ?? [])\n .map((o) => `${jstr(o.name)} (${jstr(o.requirement?.min_value)}+): ${describeEffectInline(o.effect ?? {}, ctx)}`)\n .join(\" / \");\n return `roll ${pool}: ${opts}`;\n }\n\n default:\n return `[${e.type ?? \"unknown\"}]`;\n }\n}\n\n/** Per-slug GW-prose for `attack-restriction` (reads `restriction` or `restriction_type`). */\nfunction describeAttackRestriction(m: Record<string, unknown>, subj: string): string {\n // Some entries express the restriction as a forbidden action (`attack_type: charge`).\n if (m.restriction == null && m.restriction_type == null && m.attack_type != null)\n return `${subj} cannot ${jstr(m.attack_type)}`;\n const slug = jstr(m.restriction ?? m.restriction_type);\n const range = m.range != null ? jstr(m.range) : null;\n switch (slug) {\n case \"worsen-incoming-ap\":\n return `each time an attack targets ${subj}, worsen the Armour Penetration of that attack by ${jstr(m.value ?? 1)}`;\n case \"cannot-be-targeted-unless-closest-or-within-12\":\n return `${subj} can only be targeted if it is the closest eligible target or within 12\"`;\n case \"targeting-range-limit\":\n return `${subj} can only target enemy units within ${range ?? \"?\"}\"`;\n case \"reinforcement-denial\":\n return `enemy units cannot be set up from Reserves within ${range ?? \"?\"}\" of ${subj}`;\n case \"must-be-warlord\":\n return \"this model must be your Warlord\";\n case \"cannot-be-warlord\":\n return \"this model cannot be your Warlord\";\n case \"unique-unit-limit\":\n return \"you can include only one of this unit in your army\";\n case \"no-charge\":\n return `${subj} cannot charge`;\n default:\n return `${subj}: ${dekebab(slug)}${range != null ? ` (within ${range}\")` : \"\"}`;\n }\n}\n\n/**\n * Block translation of a *container* effect tree (multi-line, two-space\n * indentation). Leaves and conditionals are handled inline by the caller.\n */\nexport function describeEffect(e: Effect, depth: number = 0, ctx: Ctx = {}): string {\n const indent = \" \".repeat(depth);\n const arrow = depth > 0 ? \"-> \" : \"\";\n\n switch (e.type) {\n case \"conditional\": {\n const inner = e.effect ?? {};\n if (CONTAINER_TYPES.has(inner.type ?? \"\")) {\n return `${indent}${capitalize(conditionLeadIn(e.condition ?? {}))}:\\n` + describeEffect(inner, depth + 1, ctx);\n }\n return `${indent}${arrow}${capitalize(conditionLeadIn(e.condition ?? {}))}, ${describeEffectInline(inner, ctx)}.`;\n }\n case \"sequence\":\n return (e.steps ?? [])\n .map((s) => describeEffect(s, depth, ctx))\n .join(\"\\n\");\n case \"choice\": {\n const label = e.choice_label ? ` (${titleCase(e.choice_label)})` : \"\";\n return (\n `${indent}Select one of the following${label}:\\n` +\n (e.options ?? []).map((o) => `${indent} - ${capitalize(describeEffectInline(o, ctx))}.`).join(\"\\n\")\n );\n }\n case \"dice-gated\": {\n const comp = formatComparison(e.comparison ?? \"gte\", e.threshold);\n const success = e.on_success ? describeEffectInline(e.on_success, ctx) : \"nothing happens\";\n const fail = e.on_fail ? `; otherwise, ${describeEffectInline(e.on_fail, ctx)}` : \"\";\n return `${indent}${arrow}Roll one ${diceCase(e.dice)}: on ${comp}, ${success}${fail}.`;\n }\n case \"dice-pool-allocation\": {\n const pool = e.pool ? `${jstr(e.pool.count)}${jstr(e.pool.die)}` : \"?\";\n const lines = [`${indent}${arrow}Roll ${pool} (max ${jstr(e.max_activations)} activations):`];\n for (const opt of e.options ?? []) {\n lines.push(\n `${indent} - ${jstr(opt.name)}: need ${jstr(opt.requirement?.type)} of ${jstr(opt.requirement?.min_value)}+ -> ${describeEffectInline(opt.effect ?? {}, ctx)}`\n );\n }\n return lines.join(\"\\n\");\n }\n default:\n // Leaf at block position — render as a single capitalized sentence.\n return `${indent}${arrow}${capitalize(describeEffectInline(e, ctx))}.`;\n }\n}\n\n/** `Scope: aura (6\"). Duration: phase.` — retained for the legacy translate CLI footer. */\nexport function describeScope(s?: AbilityScope): string {\n if (!s || (!s.range && !s.duration)) return \"\";\n const range = dekebab(s.range ?? \"\");\n const inches = s.range_inches != null ? ` (${jstr(s.range_inches)}\")` : \"\";\n const duration = dekebab(s.duration ?? \"\");\n return `Scope: ${range}${inches}. Duration: ${duration}.`;\n}\n\n/**\n * `Applies to: units with Possessed.` — the roster-highlighting audience named\n * by a curated `applies_to` filter. Empty string when the filter is absent or\n * carries no keywords (nothing to say). `required_keywords` reads as an AND set;\n * `excluded_keywords` render as a trailing `(excluding …)`.\n */\nexport function describeAppliesTo(a?: AbilityAppliesTo | null): string {\n if (!a) return \"\";\n const required = a.required_keywords ?? [];\n const excluded = a.excluded_keywords ?? [];\n if (required.length === 0 && excluded.length === 0) return \"\";\n const base = required.length ? `units with ${required.join(\", \")}` : \"all units\";\n const exc = excluded.length ? ` (excluding ${excluded.join(\", \")})` : \"\";\n return `Applies to: ${base}${exc}.`;\n}\n\n/** Join non-empty clauses with \", \", capitalize the sentence, and end with a period. */\nfunction assembleSentence(parts: string[]): string {\n const body = parts.filter((p) => p.length > 0).join(\", \");\n if (body.length === 0) return \"\";\n const period = body.endsWith(\".\") || body.endsWith(\":\") ? \"\" : \".\";\n return capitalize(body) + period;\n}\n\n/**\n * Full generated text for an ability: a natural-English sentence (effect with\n * scope range + duration woven in, single-leaf conditionals inlined) plus a\n * trailing `Applies to:` line when the ability carries a curated `applies_to`\n * filter. This is the `ability.print()` consumers render when the dataset\n * carries no rules prose.\n */\nexport function describeAbility(a: AbilityLike): string {\n const core = a.effect ? renderTopLevel(a.effect, a.scope) : \"\";\n const applies = describeAppliesTo(a.applies_to);\n return [core, applies].filter(Boolean).join(\"\\n\");\n}\n\n/** Assemble the top-level sentence/block, weaving scope duration + range. */\nfunction renderTopLevel(e: Effect, scope?: AbilityScope): string {\n const ctx: Ctx = { rangeInches: scope?.range_inches };\n const { lead, trail } = durationClauses(scope?.duration);\n\n if (e.type === \"conditional\") {\n const inner = e.effect ?? {};\n const leadIn = conditionLeadIn(e.condition ?? {});\n if (CONTAINER_TYPES.has(inner.type ?? \"\")) {\n // Block: \"<lead-in>[, <duration>]:\" then the indented container.\n const header = [lead, leadIn, trail].filter((p) => p.length > 0).join(\", \");\n return capitalize(header) + \":\\n\" + describeEffect(inner, 1, ctx);\n }\n return assembleSentence([lead, leadIn, trail, describeEffectInline(inner, ctx)]);\n }\n\n if (CONTAINER_TYPES.has(e.type ?? \"\")) {\n // Containers render block; a duration lead-in prefixes the block when present.\n const block = describeEffect(e, 0, ctx);\n const dur = lead || trail;\n return dur ? capitalize(dur) + \":\\n\" + block : block;\n }\n\n return assembleSentence([lead, trail, describeEffectInline(e, ctx)]);\n}\n"]}
|
package/dist/validate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAS3B,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAS3B,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAmDD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,CAAC,CAkF3B"}
|
package/dist/validate.js
CHANGED
|
@@ -15,6 +15,7 @@ const SCHEMA_MAP = {
|
|
|
15
15
|
"weapon-keywords": "https://40kdc.dev/schemas/core/weapon-keyword.schema.json",
|
|
16
16
|
"game-versions": "https://40kdc.dev/schemas/core/game-version.schema.json",
|
|
17
17
|
detachments: "https://40kdc.dev/schemas/core/detachment.schema.json",
|
|
18
|
+
allies: "https://40kdc.dev/schemas/core/allied-rule.schema.json",
|
|
18
19
|
enhancements: "https://40kdc.dev/schemas/core/enhancement.schema.json",
|
|
19
20
|
stratagems: "https://40kdc.dev/schemas/core/stratagem.schema.json",
|
|
20
21
|
"wargear-options": "https://40kdc.dev/schemas/core/wargear-option.schema.json",
|
package/dist/validate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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","sourcesContent":["import type Ajv from \"ajv\";\nimport { readFileSync } from \"node:fs\";\nimport { glob } from \"glob\";\nimport { resolve, basename } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = fileURLToPath(new URL(\".\", import.meta.url));\nconst DATA_ROOT = resolve(__dirname, \"../../data\");\n\nexport interface ValidationError {\n file: string;\n index: number;\n errors: Array<{ path: string; message: string }>;\n}\n\nexport interface ValidationResult {\n totalFiles: number;\n totalItems: number;\n passed: number;\n failed: number;\n errors: ValidationError[];\n}\n\n/**\n * Map from data file base-name prefix to schema $id.\n */\nconst SCHEMA_MAP: Record<string, string> = {\n factions: \"https://40kdc.dev/schemas/core/faction.schema.json\",\n units: \"https://40kdc.dev/schemas/core/unit.schema.json\",\n \"target-profiles\": \"https://40kdc.dev/schemas/core/target-profile.schema.json\",\n weapons: \"https://40kdc.dev/schemas/core/weapon.schema.json\",\n \"weapon-keywords\": \"https://40kdc.dev/schemas/core/weapon-keyword.schema.json\",\n \"game-versions\": \"https://40kdc.dev/schemas/core/game-version.schema.json\",\n detachments: \"https://40kdc.dev/schemas/core/detachment.schema.json\",\n enhancements: \"https://40kdc.dev/schemas/core/enhancement.schema.json\",\n stratagems: \"https://40kdc.dev/schemas/core/stratagem.schema.json\",\n \"wargear-options\": \"https://40kdc.dev/schemas/core/wargear-option.schema.json\",\n wargear: \"https://40kdc.dev/schemas/core/wargear.schema.json\",\n \"leader-attachments\": \"https://40kdc.dev/schemas/core/leader-attachment.schema.json\",\n \"unit-compositions\": \"https://40kdc.dev/schemas/core/unit-composition.schema.json\",\n \"force-dispositions\": \"https://40kdc.dev/schemas/core/force-disposition.schema.json\",\n \"deployment-patterns\": \"https://40kdc.dev/schemas/core/deployment-pattern.schema.json\",\n \"mission-matchups\": \"https://40kdc.dev/schemas/core/mission-matchup.schema.json\",\n missions: \"https://40kdc.dev/schemas/core/mission.schema.json\",\n \"secondary-cards\": \"https://40kdc.dev/schemas/core/secondary-card.schema.json\",\n \"terrain-templates\": \"https://40kdc.dev/schemas/core/terrain-template.schema.json\",\n \"terrain-layouts\": \"https://40kdc.dev/schemas/core/terrain-layout.schema.json\",\n \"hull-shapes\": \"https://40kdc.dev/schemas/core/hull-shape.schema.json\",\n \"phase-mappings\": \"https://40kdc.dev/schemas/enrichment/phase-mapping.schema.json\",\n \"timing-flags\": \"https://40kdc.dev/schemas/enrichment/timing-flag.schema.json\",\n \"interaction-flags\": \"https://40kdc.dev/schemas/enrichment/interaction-flag.schema.json\",\n abilities: \"https://40kdc.dev/schemas/enrichment/ability-dsl/ability.schema.json\",\n \"resource-pools\": \"https://40kdc.dev/schemas/enrichment/resource-pool.schema.json\",\n};\n\n/**\n * Determine which schema $id to use for a given data file path.\n * Convention: the file's base name starts with a SCHEMA_MAP prefix (real data is\n * `<prefix>.json`; test fixtures are `<prefix>-good.json` / `<prefix>-bad.json`).\n * Prefixes are tried longest-first so `wargear-options.json` resolves to the\n * wargear-option schema rather than the shorter `wargear` key (distinct entities).\n */\nconst SCHEMA_PREFIXES = Object.keys(SCHEMA_MAP).sort((a, b) => b.length - a.length);\nfunction resolveSchemaId(filePath: string): string | null {\n const base = basename(filePath);\n for (const prefix of SCHEMA_PREFIXES) {\n if (base.startsWith(prefix)) return SCHEMA_MAP[prefix];\n }\n return null;\n}\n\n/**\n * Validate all data files matching the given glob pattern.\n * Each data file is expected to be a JSON array; each element is validated individually.\n */\nexport async function validateFiles(\n ajv: Ajv,\n pattern: string,\n cwd?: string,\n): Promise<ValidationResult> {\n const root = cwd ?? DATA_ROOT;\n const files = await glob(pattern, { cwd: root, absolute: true });\n\n const result: ValidationResult = {\n totalFiles: files.length,\n totalItems: 0,\n passed: 0,\n failed: 0,\n errors: [],\n };\n\n for (const file of files) {\n // Underscore-prefixed files are scratch/reports (e.g. the converter's\n // `_wargear-options.unparsed.json`), not dataset entities — skip them.\n if (basename(file).startsWith(\"_\")) continue;\n const schemaId = resolveSchemaId(file);\n if (!schemaId) {\n result.errors.push({\n file,\n index: -1,\n errors: [{ path: \"\", message: `No schema mapping found for file: ${basename(file)}` }],\n });\n result.failed++;\n continue;\n }\n\n const validate = ajv.getSchema(schemaId);\n if (!validate) {\n result.errors.push({\n file,\n index: -1,\n errors: [{ path: \"\", message: `Schema not found: ${schemaId}` }],\n });\n result.failed++;\n continue;\n }\n\n let data: unknown;\n try {\n const raw = readFileSync(file, \"utf-8\");\n data = JSON.parse(raw);\n } catch (err) {\n result.errors.push({\n file,\n index: -1,\n errors: [{ path: \"\", message: `Failed to parse JSON: ${(err as Error).message}` }],\n });\n result.failed++;\n continue;\n }\n\n if (!Array.isArray(data)) {\n result.errors.push({\n file,\n index: -1,\n errors: [{ path: \"\", message: \"Data file must be a JSON array\" }],\n });\n result.failed++;\n continue;\n }\n\n for (let i = 0; i < data.length; i++) {\n result.totalItems++;\n const valid = validate(data[i]);\n if (valid) {\n result.passed++;\n } else {\n result.failed++;\n result.errors.push({\n file,\n index: i,\n errors: (validate.errors ?? []).map((e) => ({\n path: e.instancePath || \"/\",\n message: e.message ?? \"Unknown validation error\",\n })),\n });\n }\n }\n }\n\n return result;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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","sourcesContent":["import type Ajv from \"ajv\";\nimport { readFileSync } from \"node:fs\";\nimport { glob } from \"glob\";\nimport { resolve, basename } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = fileURLToPath(new URL(\".\", import.meta.url));\nconst DATA_ROOT = resolve(__dirname, \"../../data\");\n\nexport interface ValidationError {\n file: string;\n index: number;\n errors: Array<{ path: string; message: string }>;\n}\n\nexport interface ValidationResult {\n totalFiles: number;\n totalItems: number;\n passed: number;\n failed: number;\n errors: ValidationError[];\n}\n\n/**\n * Map from data file base-name prefix to schema $id.\n */\nconst SCHEMA_MAP: Record<string, string> = {\n factions: \"https://40kdc.dev/schemas/core/faction.schema.json\",\n units: \"https://40kdc.dev/schemas/core/unit.schema.json\",\n \"target-profiles\": \"https://40kdc.dev/schemas/core/target-profile.schema.json\",\n weapons: \"https://40kdc.dev/schemas/core/weapon.schema.json\",\n \"weapon-keywords\": \"https://40kdc.dev/schemas/core/weapon-keyword.schema.json\",\n \"game-versions\": \"https://40kdc.dev/schemas/core/game-version.schema.json\",\n detachments: \"https://40kdc.dev/schemas/core/detachment.schema.json\",\n allies: \"https://40kdc.dev/schemas/core/allied-rule.schema.json\",\n enhancements: \"https://40kdc.dev/schemas/core/enhancement.schema.json\",\n stratagems: \"https://40kdc.dev/schemas/core/stratagem.schema.json\",\n \"wargear-options\": \"https://40kdc.dev/schemas/core/wargear-option.schema.json\",\n wargear: \"https://40kdc.dev/schemas/core/wargear.schema.json\",\n \"leader-attachments\": \"https://40kdc.dev/schemas/core/leader-attachment.schema.json\",\n \"unit-compositions\": \"https://40kdc.dev/schemas/core/unit-composition.schema.json\",\n \"force-dispositions\": \"https://40kdc.dev/schemas/core/force-disposition.schema.json\",\n \"deployment-patterns\": \"https://40kdc.dev/schemas/core/deployment-pattern.schema.json\",\n \"mission-matchups\": \"https://40kdc.dev/schemas/core/mission-matchup.schema.json\",\n missions: \"https://40kdc.dev/schemas/core/mission.schema.json\",\n \"secondary-cards\": \"https://40kdc.dev/schemas/core/secondary-card.schema.json\",\n \"terrain-templates\": \"https://40kdc.dev/schemas/core/terrain-template.schema.json\",\n \"terrain-layouts\": \"https://40kdc.dev/schemas/core/terrain-layout.schema.json\",\n \"hull-shapes\": \"https://40kdc.dev/schemas/core/hull-shape.schema.json\",\n \"phase-mappings\": \"https://40kdc.dev/schemas/enrichment/phase-mapping.schema.json\",\n \"timing-flags\": \"https://40kdc.dev/schemas/enrichment/timing-flag.schema.json\",\n \"interaction-flags\": \"https://40kdc.dev/schemas/enrichment/interaction-flag.schema.json\",\n abilities: \"https://40kdc.dev/schemas/enrichment/ability-dsl/ability.schema.json\",\n \"resource-pools\": \"https://40kdc.dev/schemas/enrichment/resource-pool.schema.json\",\n};\n\n/**\n * Determine which schema $id to use for a given data file path.\n * Convention: the file's base name starts with a SCHEMA_MAP prefix (real data is\n * `<prefix>.json`; test fixtures are `<prefix>-good.json` / `<prefix>-bad.json`).\n * Prefixes are tried longest-first so `wargear-options.json` resolves to the\n * wargear-option schema rather than the shorter `wargear` key (distinct entities).\n */\nconst SCHEMA_PREFIXES = Object.keys(SCHEMA_MAP).sort((a, b) => b.length - a.length);\nfunction resolveSchemaId(filePath: string): string | null {\n const base = basename(filePath);\n for (const prefix of SCHEMA_PREFIXES) {\n if (base.startsWith(prefix)) return SCHEMA_MAP[prefix];\n }\n return null;\n}\n\n/**\n * Validate all data files matching the given glob pattern.\n * Each data file is expected to be a JSON array; each element is validated individually.\n */\nexport async function validateFiles(\n ajv: Ajv,\n pattern: string,\n cwd?: string,\n): Promise<ValidationResult> {\n const root = cwd ?? DATA_ROOT;\n const files = await glob(pattern, { cwd: root, absolute: true });\n\n const result: ValidationResult = {\n totalFiles: files.length,\n totalItems: 0,\n passed: 0,\n failed: 0,\n errors: [],\n };\n\n for (const file of files) {\n // Underscore-prefixed files are scratch/reports (e.g. the converter's\n // `_wargear-options.unparsed.json`), not dataset entities — skip them.\n if (basename(file).startsWith(\"_\")) continue;\n const schemaId = resolveSchemaId(file);\n if (!schemaId) {\n result.errors.push({\n file,\n index: -1,\n errors: [{ path: \"\", message: `No schema mapping found for file: ${basename(file)}` }],\n });\n result.failed++;\n continue;\n }\n\n const validate = ajv.getSchema(schemaId);\n if (!validate) {\n result.errors.push({\n file,\n index: -1,\n errors: [{ path: \"\", message: `Schema not found: ${schemaId}` }],\n });\n result.failed++;\n continue;\n }\n\n let data: unknown;\n try {\n const raw = readFileSync(file, \"utf-8\");\n data = JSON.parse(raw);\n } catch (err) {\n result.errors.push({\n file,\n index: -1,\n errors: [{ path: \"\", message: `Failed to parse JSON: ${(err as Error).message}` }],\n });\n result.failed++;\n continue;\n }\n\n if (!Array.isArray(data)) {\n result.errors.push({\n file,\n index: -1,\n errors: [{ path: \"\", message: \"Data file must be a JSON array\" }],\n });\n result.failed++;\n continue;\n }\n\n for (let i = 0; i < data.length; i++) {\n result.totalItems++;\n const valid = validate(data[i]);\n if (valid) {\n result.passed++;\n } else {\n result.failed++;\n result.errors.push({\n file,\n index: i,\n errors: (validate.errors ?? []).map((e) => ({\n path: e.instancePath || \"/\",\n message: e.message ?? \"Unknown validation error\",\n })),\n });\n }\n }\n }\n\n return result;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alpaca-software/40kdc-data",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The 40kdc Warhammer 40K dataset behind a linked, typed API — find units, follow them to their weapons, abilities, phases, and factions. Also validates data against the canonical JSON Schemas.",
|
|
6
6
|
"keywords": [
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"build": "npm run codegen:data && tsc",
|
|
56
56
|
"postbuild": "npm run audit:coverage",
|
|
57
57
|
"codegen:data": "tsx src/codegen-data.ts",
|
|
58
|
+
"registry:build": "tsx src/build-share-registry.ts",
|
|
58
59
|
"gen:conformance": "tsx src/gen-conformance.ts",
|
|
59
60
|
"docs:api": "typedoc",
|
|
60
61
|
"docs:api:html": "typedoc --options typedoc.html.json",
|
|
@@ -64,6 +65,7 @@
|
|
|
64
65
|
"validate:enrichment": "tsx src/cli.ts validate-enrichment",
|
|
65
66
|
"translate": "tsx src/cli.ts translate",
|
|
66
67
|
"audit:coverage": "tsx src/cli.ts audit-coverage --write",
|
|
68
|
+
"audit:phrasing": "tsx src/cli.ts audit-phrasing --write",
|
|
67
69
|
"scrub:defensive-flag": "tsx src/scrub-defensive-flag.ts",
|
|
68
70
|
"extract:faction-pack": "tsx src/extract-faction-pack.ts",
|
|
69
71
|
"author:input": "tsx src/author-input.ts",
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://40kdc.dev/schemas/core/allied-rule.schema.json",
|
|
4
|
+
"title": "AlliedRule",
|
|
5
|
+
"description": "A community-authored model of an allied-detachment / 'soup' rule: the named exception by which units lacking the army's chosen Faction keyword may still be included (e.g. Daemonic Pact, Brood Brothers, Iconoclast Fiefdom's Damned access). One rule = one allied source pool; a faction that allies in several pools (the Chaos cult pattern: a Chaos Knights pool plus a matching-god Daemons pool) carries one rule per pool. The rule is gated by two optional, AND-combined conditions: an army-wide keyword condition (`army_keywords_any`) and/or a selected detachment (`detachment_id`).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"id": { "$ref": "../defs/common.schema.json#/$defs/entity-id" },
|
|
9
|
+
"name": { "type": "string", "minLength": 1, "maxLength": 128 },
|
|
10
|
+
"label": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Short panel/category heading a list builder groups this pool under (e.g. 'Daemons', 'Imperial Agents', 'Titanic Allies'). Defaults to `name` when omitted."
|
|
13
|
+
},
|
|
14
|
+
"army_keywords_any": {
|
|
15
|
+
"$ref": "../defs/common.schema.json#/$defs/keyword-list",
|
|
16
|
+
"description": "Army gate: every model in the army must carry at least one of these keywords for the rule to apply (e.g. ['Chaos Knights', 'Heretic Astartes'] for Daemonic Pact). Empty = no army-level gate (the rule is then gated only by `detachment_id`, whose detachment is itself faction-locked)."
|
|
17
|
+
},
|
|
18
|
+
"detachment_id": {
|
|
19
|
+
"oneOf": [
|
|
20
|
+
{ "$ref": "../defs/common.schema.json#/$defs/entity-id" },
|
|
21
|
+
{ "type": "null" }
|
|
22
|
+
],
|
|
23
|
+
"description": "Detachment gate: this exact detachment must be selected for the rule to apply (e.g. 'iconoclast-fiefdom'). null = no detachment-level gate. Independent of the detachment's combat rule (`detachment_rule_id`)."
|
|
24
|
+
},
|
|
25
|
+
"source_faction_id": {
|
|
26
|
+
"oneOf": [
|
|
27
|
+
{ "$ref": "../defs/common.schema.json#/$defs/entity-id" },
|
|
28
|
+
{ "type": "null" }
|
|
29
|
+
],
|
|
30
|
+
"description": "Faction the ally pool is drawn from, when scoping by faction is needed to disambiguate units whose id is shared across factions. Optional hint; `source_keywords` is the primary filter."
|
|
31
|
+
},
|
|
32
|
+
"source_keywords": {
|
|
33
|
+
"$ref": "../defs/common.schema.json#/$defs/keyword-list",
|
|
34
|
+
"description": "A unit qualifies for this pool when it carries any of these keywords (e.g. ['Legiones Daemonica'], ['Damned'], ['Vanguard Invader']). Empty = the whole `source_faction_id` is the pool."
|
|
35
|
+
},
|
|
36
|
+
"required_keywords": {
|
|
37
|
+
"$ref": "../defs/common.schema.json#/$defs/keyword-list",
|
|
38
|
+
"description": "Additional filter: a unit must carry ALL of these to be included via this rule (e.g. the matching god ['Khorne'] for a per-god Daemon pool)."
|
|
39
|
+
},
|
|
40
|
+
"excluded_keywords": {
|
|
41
|
+
"$ref": "../defs/common.schema.json#/$defs/keyword-list",
|
|
42
|
+
"description": "A unit carrying ANY of these cannot be included via this rule (e.g. Brood Brothers bans 'Aircraft', 'Epic Hero', 'Ogryn', ...)."
|
|
43
|
+
},
|
|
44
|
+
"roles": {
|
|
45
|
+
"type": "array",
|
|
46
|
+
"items": { "type": "string" },
|
|
47
|
+
"uniqueItems": true,
|
|
48
|
+
"description": "Optional battlefield-role filter (matched against a unit's `role`). Empty = no role restriction."
|
|
49
|
+
},
|
|
50
|
+
"points_limits": {
|
|
51
|
+
"type": "array",
|
|
52
|
+
"items": { "$ref": "#/$defs/allied-points-limit" },
|
|
53
|
+
"description": "Absolute points cap on the combined cost of units included via this rule, per battle size. Empty = no points cap. A rule lists at most one entry per battle size.",
|
|
54
|
+
"uniqueItems": true
|
|
55
|
+
},
|
|
56
|
+
"max_units": {
|
|
57
|
+
"oneOf": [
|
|
58
|
+
{ "type": "integer", "minimum": 0 },
|
|
59
|
+
{ "type": "null" }
|
|
60
|
+
],
|
|
61
|
+
"description": "Optional cap on the number of units included via this rule, independent of points. null = no unit-count cap."
|
|
62
|
+
},
|
|
63
|
+
"cannot_be_warlord": {
|
|
64
|
+
"type": "boolean",
|
|
65
|
+
"default": false,
|
|
66
|
+
"description": "True when units included via this rule cannot be the army's Warlord (e.g. Daemonic Pact, Star Children's Blessings)."
|
|
67
|
+
},
|
|
68
|
+
"cannot_take_enhancements": {
|
|
69
|
+
"type": "boolean",
|
|
70
|
+
"default": false,
|
|
71
|
+
"description": "True when units included via this rule cannot be given Enhancements (e.g. Daemonic Pact)."
|
|
72
|
+
},
|
|
73
|
+
"warlord_required_keyword": {
|
|
74
|
+
"oneOf": [
|
|
75
|
+
{ "$ref": "../defs/common.schema.json#/$defs/keyword" },
|
|
76
|
+
{ "type": "null" }
|
|
77
|
+
],
|
|
78
|
+
"description": "Host-Warlord requirement: a model carrying this keyword must be the army's Warlord (e.g. Brood Brothers requires a 'Genestealer Cults' Warlord). null = no such requirement."
|
|
79
|
+
},
|
|
80
|
+
"removes_ability_ids": {
|
|
81
|
+
"type": "array",
|
|
82
|
+
"items": { "$ref": "../defs/common.schema.json#/$defs/entity-id" },
|
|
83
|
+
"uniqueItems": true,
|
|
84
|
+
"description": "Abilities that included units lose under this rule (e.g. Astra Militarum units lose 'voice-of-command' under Brood Brothers). A display/effect hint, not a construction constraint."
|
|
85
|
+
},
|
|
86
|
+
"battleline_ratio_keywords": {
|
|
87
|
+
"$ref": "../defs/common.schema.json#/$defs/keyword-list",
|
|
88
|
+
"description": "Per-keyword Battleline ratio constraint: for each keyword listed, the number of non-BATTLELINE units with that keyword included via this rule cannot exceed the number of BATTLELINE units with that keyword included via this rule (e.g. Daemonic Pact's per-god ['Khorne','Tzeentch','Nurgle','Slaanesh'])."
|
|
89
|
+
},
|
|
90
|
+
"game_version": { "$ref": "../defs/game-version-ref.schema.json" },
|
|
91
|
+
"notes": { "type": "string" }
|
|
92
|
+
},
|
|
93
|
+
"required": ["id", "name", "game_version"],
|
|
94
|
+
"additionalProperties": false,
|
|
95
|
+
"$defs": {
|
|
96
|
+
"allied-points-limit": {
|
|
97
|
+
"type": "object",
|
|
98
|
+
"description": "The combined points cap for units included via an allied rule at one battle size.",
|
|
99
|
+
"properties": {
|
|
100
|
+
"battle_size": {
|
|
101
|
+
"type": "string",
|
|
102
|
+
"enum": ["incursion", "strike-force", "onslaught"],
|
|
103
|
+
"description": "Battle size this cap applies at. Includes 'onslaught' (3000 pts), which ally rules reference even though the core roster battle-size enum lists only incursion/strike-force."
|
|
104
|
+
},
|
|
105
|
+
"max_points": {
|
|
106
|
+
"type": "integer",
|
|
107
|
+
"minimum": 0,
|
|
108
|
+
"description": "Maximum combined points of units included via the rule at this battle size."
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"required": ["battle_size", "max_points"],
|
|
112
|
+
"additionalProperties": false
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -55,8 +55,45 @@
|
|
|
55
55
|
{ "type": "null" }
|
|
56
56
|
]
|
|
57
57
|
},
|
|
58
|
+
"granted_keywords": {
|
|
59
|
+
"type": "array",
|
|
60
|
+
"items": { "$ref": "#/$defs/granted-keyword" },
|
|
61
|
+
"description": "Construction keywords this detachment grants to matching units while it is selected (e.g. Houndpack Lance grants 'Battleline' to 'War Dog' units). A unit carrying any keyword in a grant's `to_keywords` gains that grant's `keyword` for army-construction purposes (datasheet-count caps, battlefield role). Empty/absent when the detachment grants no construction keywords. Distinct from combat keywords, which live in the ability DSL."
|
|
62
|
+
},
|
|
63
|
+
"unit_minimums": {
|
|
64
|
+
"type": "array",
|
|
65
|
+
"items": { "$ref": "#/$defs/unit-minimum" },
|
|
66
|
+
"description": "Minimum unit counts the detachment requires while selected (e.g. Houndpack Lance: 'your army must include three or more WAR DOG units'). Each entry requires at least `min` units carrying `keyword`. Empty/absent when the detachment imposes no minimum."
|
|
67
|
+
},
|
|
58
68
|
"game_version": { "$ref": "../defs/game-version-ref.schema.json" }
|
|
59
69
|
},
|
|
60
70
|
"required": ["id", "name", "faction_id", "game_version"],
|
|
61
|
-
"additionalProperties": false
|
|
71
|
+
"additionalProperties": false,
|
|
72
|
+
"$defs": {
|
|
73
|
+
"granted-keyword": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"description": "A construction keyword a detachment grants to units matching a keyword filter. Blanket by default (every matching unit gains it); when `max_selected` is set, the keyword is instead granted to up to that many matching units of the player's choice (e.g. Houndpack Lance: 'select three WAR DOG units; they gain CHARACTER').",
|
|
76
|
+
"properties": {
|
|
77
|
+
"keyword": { "$ref": "../defs/common.schema.json#/$defs/keyword" },
|
|
78
|
+
"to_keywords": { "$ref": "../defs/common.schema.json#/$defs/keyword-list" },
|
|
79
|
+
"max_selected": {
|
|
80
|
+
"type": "integer",
|
|
81
|
+
"minimum": 1,
|
|
82
|
+
"description": "When present, the grant is not blanket: the player selects up to this many matching units to receive `keyword` (e.g. 3 WAR DOG units gain CHARACTER under Houndpack Lance). Absent = every matching unit gains it."
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"required": ["keyword", "to_keywords"],
|
|
86
|
+
"additionalProperties": false
|
|
87
|
+
},
|
|
88
|
+
"unit-minimum": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"description": "A minimum number of units carrying a keyword that the detachment requires.",
|
|
91
|
+
"properties": {
|
|
92
|
+
"keyword": { "$ref": "../defs/common.schema.json#/$defs/keyword" },
|
|
93
|
+
"min": { "type": "integer", "minimum": 1 }
|
|
94
|
+
},
|
|
95
|
+
"required": ["keyword", "min"],
|
|
96
|
+
"additionalProperties": false
|
|
97
|
+
}
|
|
98
|
+
}
|
|
62
99
|
}
|