@datamoc/mw_games 0.7.0 → 0.7.2

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.
Files changed (121) hide show
  1. package/CHANGELOG.md +964 -0
  2. package/README.md +43 -3
  3. package/dist/actors/Affix.d.ts +7 -1
  4. package/dist/actors/Affix.d.ts.map +1 -1
  5. package/dist/actors/Affix.js +4 -2
  6. package/dist/actors/Affix.js.map +1 -1
  7. package/dist/actors/StatBlock.d.ts +20 -0
  8. package/dist/actors/StatBlock.d.ts.map +1 -1
  9. package/dist/actors/StatBlock.js +14 -3
  10. package/dist/actors/StatBlock.js.map +1 -1
  11. package/dist/actors/index.d.ts +2 -2
  12. package/dist/actors/index.d.ts.map +1 -1
  13. package/dist/actors/index.js +1 -1
  14. package/dist/actors/index.js.map +1 -1
  15. package/dist/ai/index.d.ts +118 -0
  16. package/dist/ai/index.d.ts.map +1 -0
  17. package/dist/ai/index.js +203 -0
  18. package/dist/ai/index.js.map +1 -0
  19. package/dist/ai/lua.d.ts +47 -0
  20. package/dist/ai/lua.d.ts.map +1 -0
  21. package/dist/ai/lua.js +195 -0
  22. package/dist/ai/lua.js.map +1 -0
  23. package/dist/ai/search.d.ts +59 -0
  24. package/dist/ai/search.d.ts.map +1 -0
  25. package/dist/ai/search.js +100 -0
  26. package/dist/ai/search.js.map +1 -0
  27. package/dist/board/Engine.d.ts +14 -0
  28. package/dist/board/Engine.d.ts.map +1 -1
  29. package/dist/board/Engine.js +33 -45
  30. package/dist/board/Engine.js.map +1 -1
  31. package/dist/board/index.d.ts +1 -1
  32. package/dist/board/index.d.ts.map +1 -1
  33. package/dist/board/index.js +1 -1
  34. package/dist/board/index.js.map +1 -1
  35. package/dist/core/Csv.d.ts +10 -0
  36. package/dist/core/Csv.d.ts.map +1 -1
  37. package/dist/core/Csv.js +34 -3
  38. package/dist/core/Csv.js.map +1 -1
  39. package/dist/core/Entity.d.ts +2 -2
  40. package/dist/core/Entity.d.ts.map +1 -1
  41. package/dist/core/Entity.js +18 -4
  42. package/dist/core/Entity.js.map +1 -1
  43. package/dist/index.d.ts +1 -0
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +1 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/mw_games.global.js +97 -97
  48. package/dist/mwl/actors.d.ts +3 -1
  49. package/dist/mwl/actors.d.ts.map +1 -1
  50. package/dist/mwl/actors.js +15 -2
  51. package/dist/mwl/actors.js.map +1 -1
  52. package/dist/mwl/catalog.d.ts.map +1 -1
  53. package/dist/mwl/catalog.js +16 -9
  54. package/dist/mwl/catalog.js.map +1 -1
  55. package/dist/mwl/compiler.d.ts +20 -0
  56. package/dist/mwl/compiler.d.ts.map +1 -1
  57. package/dist/mwl/compiler.js +76 -3
  58. package/dist/mwl/compiler.js.map +1 -1
  59. package/dist/mwl/conditions.d.ts +9 -0
  60. package/dist/mwl/conditions.d.ts.map +1 -0
  61. package/dist/mwl/conditions.js +162 -0
  62. package/dist/mwl/conditions.js.map +1 -0
  63. package/dist/mwl/content.d.ts +61 -0
  64. package/dist/mwl/content.d.ts.map +1 -1
  65. package/dist/mwl/content.js +95 -34
  66. package/dist/mwl/content.js.map +1 -1
  67. package/dist/mwl/expression.d.ts.map +1 -1
  68. package/dist/mwl/expression.js +16 -6
  69. package/dist/mwl/expression.js.map +1 -1
  70. package/dist/mwl/fengari.d.ts +8 -0
  71. package/dist/mwl/fengari.d.ts.map +1 -0
  72. package/dist/mwl/fengari.js +136 -0
  73. package/dist/mwl/fengari.js.map +1 -0
  74. package/dist/mwl/hooks.d.ts +1 -1
  75. package/dist/mwl/hooks.d.ts.map +1 -1
  76. package/dist/mwl/hooks.js.map +1 -1
  77. package/dist/mwl/index.d.ts +16 -7
  78. package/dist/mwl/index.d.ts.map +1 -1
  79. package/dist/mwl/index.js +7 -3
  80. package/dist/mwl/index.js.map +1 -1
  81. package/dist/mwl/persistence.d.ts.map +1 -1
  82. package/dist/mwl/persistence.js +10 -2
  83. package/dist/mwl/persistence.js.map +1 -1
  84. package/dist/mwl/readers.d.ts +18 -0
  85. package/dist/mwl/readers.d.ts.map +1 -0
  86. package/dist/mwl/readers.js +58 -0
  87. package/dist/mwl/readers.js.map +1 -0
  88. package/dist/mwl/report.d.ts +9 -0
  89. package/dist/mwl/report.d.ts.map +1 -0
  90. package/dist/mwl/report.js +36 -0
  91. package/dist/mwl/report.js.map +1 -0
  92. package/dist/mwl/runtime.d.ts +65 -2
  93. package/dist/mwl/runtime.d.ts.map +1 -1
  94. package/dist/mwl/runtime.js +245 -26
  95. package/dist/mwl/runtime.js.map +1 -1
  96. package/dist/mwl/schema.d.ts +13 -1
  97. package/dist/mwl/schema.d.ts.map +1 -1
  98. package/dist/mwl/schema.js +222 -7
  99. package/dist/mwl/schema.js.map +1 -1
  100. package/dist/mwl/scripts.d.ts +15 -0
  101. package/dist/mwl/scripts.d.ts.map +1 -0
  102. package/dist/mwl/scripts.js +23 -0
  103. package/dist/mwl/scripts.js.map +1 -0
  104. package/dist/mwl/utils.d.ts +8 -0
  105. package/dist/mwl/utils.d.ts.map +1 -0
  106. package/dist/mwl/utils.js +37 -0
  107. package/dist/mwl/utils.js.map +1 -0
  108. package/dist/two-d/render/Types2D.d.ts +19 -4
  109. package/dist/two-d/render/Types2D.d.ts.map +1 -1
  110. package/dist/two-d/render/Types2D.js +25 -0
  111. package/dist/two-d/render/Types2D.js.map +1 -1
  112. package/dist/two-d/render/index.d.ts +2 -2
  113. package/dist/two-d/render/index.d.ts.map +1 -1
  114. package/dist/two-d/render/index.js +1 -1
  115. package/dist/two-d/render/index.js.map +1 -1
  116. package/dist/version.d.ts +1 -1
  117. package/dist/version.js +1 -1
  118. package/package.json +27 -6
  119. package/tools/extract-html.d.mts +18 -0
  120. package/tools/extract-html.mjs +235 -0
  121. package/tools/mwl.mjs +86 -16
package/README.md CHANGED
@@ -11,7 +11,11 @@ of their own; improvements to `mwg`'s own files are shared back.
11
11
  **[Live examples and API docs](https://datamoc.github.io/mwg/)**: every example below,
12
12
  playable in the browser with no download, plus the generated API reference.
13
13
 
14
- > **Status: pre-alpha (v0.7.0).** Every module in the shared floor below, plus optional
14
+ **[AI project prompt](https://datamoc.github.io/mwg/ai-prompt/)**: a copy-ready prompt for
15
+ planning or porting a demanding game with mwg, with links to the [mwg reference](REFERENCE.md)
16
+ and the [mwg Pixel Dungeon study](https://datamoc.github.io/mwg-pixel-dungeon/).
17
+
18
+ > **Status: pre-alpha (v0.7.2).** Every module in the shared floor below, plus optional
15
19
  > 3D, mobile (Capacitor) and desktop (WebView2) packaging, is built and tested - see
16
20
  > [ROADMAP.md](ROADMAP.md) for the full, numbered history.
17
21
  >
@@ -394,14 +398,34 @@ npm run mwl -- extract-i18n game.mwl -o generated/i18n.json
394
398
  npm run mwl -- hooks game.mwl --manifest hooks.json -o generated/hooks.mjs
395
399
  ```
396
400
 
401
+ The input may also be a content directory. `mwl build content/ -o generated/`
402
+ reads every `.mwl` file recursively in stable path order and emits one merged,
403
+ validated catalog. Diagnostics retain each source file and line, so a game can
404
+ organize campaigns, assets, units, items, scenarios, dialogue, and AI data as separate files.
405
+
397
406
  `mwl build` is the normal game command: it produces `game-data.ts`, `i18n.json`,
398
407
  and `assets.json` in one build-time step. The game imports the generated module;
399
408
  it never calls `Mwl.compile()` at runtime. MWG also provides generic helpers for
400
409
  turning item effects into `actors` modifiers and for versioned, migratable MWL
401
410
  saves. Asset attributes such as `image`, `image_icon`, `profile`, `icon`, `file`,
402
411
  `sound`, and `*_sound` are collected into the manifest, including comma-separated
403
- sound lists and Wesnoth `~` image modifiers. Item slots, formulas, hooks, and
404
- business rules remain defined by the game.
412
+ sound lists, Wesnoth sound ranges such as `human-hit-[1~5].ogg`, and image
413
+ modifiers. Nested transform arguments are not mistaken for separate assets.
414
+ Item slots, formulas, hooks, and business rules remain defined by the game.
415
+
416
+ Campaign metadata can be authored with a `[campaign]` tag inside `[game]`. It requires an
417
+ `id` and accepts `name`, `title`, `description`, and `start_scene`; scenario and extension
418
+ children remain game-owned and are preserved by the compiler. The compiled metadata is
419
+ available as `contentCatalog(game).campaigns`.
420
+
421
+ For a large self-contained HTML page, `npm run extract:html -- page.html -o extracted/`
422
+ writes a rewritten `index.html`, an `assets/` directory, and a deterministic
423
+ `manifest.json`. Inline scripts, styles, and supported `data:` URLs are extracted in
424
+ source order. The original page is never overwritten, and unsupported data forms are
425
+ reported as warnings. The output directory is safe to regenerate: its extracted
426
+ `assets/` directory is replaced, while unrelated files are kept.
427
+ CSS `url(data:...)` values and HTML `srcset` candidates are handled too, including
428
+ their density descriptors.
405
429
 
406
430
  Translation messages are the values marked `_ "..."` in the source; the
407
431
  extracted catalog matches `@datamoc/mw_games/i18n`. Hooks are referenced as
@@ -419,6 +443,22 @@ receives the `[hook]` attributes as its context; a `condition=hook` objective
419
443
  receives its other attributes, so content can parameterize an engine predicate
420
444
  (`value` is the generic integer parameter).
421
445
 
446
+ Events trigger on `start`, `turn`, and `moveto`. A `moveto` event fires when a
447
+ unit arrives on a hex, filtered by `x`, `y`, `unit` and `side`, once by default
448
+ (and a spent one-shot stays spent across save/restore). A game whose own engine
449
+ resolves movement writes the new position into the world and calls
450
+ `runtime.fireMoveto(unitId)`, so the trigger works either way. A `[message]`
451
+ becomes an `MwlMessage` with its `text`, and its `speaker`, `portrait` and `side`
452
+ when the content gives them, which is enough for a real dialogue box instead of a
453
+ log line.
454
+
455
+ Dialogue choices are exposed through `MwlMessage.choices` and answered with
456
+ `runtime.answerDialogue(dialogueId, choiceIndex)`. Pending choices are part of the
457
+ saved world. Commands after a dialogue in the same event run immediately, before
458
+ the player answers, so deferred follow-up commands belong in the event named by
459
+ the selected choice. Events can also be invoked directly with `runtime.fireEvent(id)`;
460
+ moveto coordinates accept comma lists and inclusive ranges such as `1,3-5`.
461
+
422
462
  The generated data is plain TypeScript and works with the same local-file build
423
463
  pipeline as the rest of the framework. Wesnoth-specific MWL source belongs in
424
464
  the Wesnoth port, not in this framework package.
@@ -57,13 +57,19 @@ export interface AffixDef {
57
57
  export interface AffixTable {
58
58
  entries: readonly AffixDef[];
59
59
  }
60
+ export interface RollAffixOptions {
61
+ /** when supplied, only entries with this curse flag are eligible */
62
+ readonly curse?: boolean;
63
+ /** an additional game-owned eligibility predicate */
64
+ readonly predicate?: (entry: AffixDef) => boolean;
65
+ }
60
66
  /**
61
67
  * Weight-picks one affix from a table - the same "roll whether, then weight-pick which"
62
68
  * shape `rollLoot` already is, with a single entry reading as "always this one".
63
69
  *
64
70
  * @returns null when the table is empty or every entry has weight 0
65
71
  */
66
- export declare function rollAffix(table: AffixTable): AffixDef | null;
72
+ export declare function rollAffix(table: AffixTable, options?: RollAffixOptions): AffixDef | null;
67
73
  /** the affix an item carries, if any - stored on the item next to its upgrade `level` */
68
74
  export declare function affixOf(item: InventoryItem): string | undefined;
69
75
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Affix.d.ts","sourceRoot":"","sources":["../../src/actors/Affix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE3D,mGAAmG;AACnG,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;AAEzE,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,YAAY,CAAC;IACtB,IAAI,CAAC,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IAEX,OAAO,EAAE,YAAY,CAAC;IAEtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAE9B,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IAEf,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAK5D;AAED,yFAAyF;AACzF,wBAAgB,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,CAOrE;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAGrD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,aAAa,GAAG,IAAI,CAOtE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAI9E"}
1
+ {"version":3,"file":"Affix.d.ts","sourceRoot":"","sources":["../../src/actors/Affix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE3D,mGAAmG;AACnG,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;AAEzE,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,YAAY,CAAC;IACtB,IAAI,CAAC,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IAEX,OAAO,EAAE,YAAY,CAAC;IAEtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAE9B,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IAEf,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAChC,oEAAoE;IACpE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,qDAAqD;IACrD,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC;CAClD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,gBAAqB,GAAG,QAAQ,GAAG,IAAI,CAU5F;AAED,yFAAyF;AACzF,wBAAgB,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,CAOrE;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAGrD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,aAAa,GAAG,IAAI,CAOtE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAI9E"}
@@ -5,8 +5,10 @@ import * as Random from '../core/Random.js';
5
5
  *
6
6
  * @returns null when the table is empty or every entry has weight 0
7
7
  */
8
- export function rollAffix(table) {
9
- const live = table.entries.filter((entry) => entry.weight > 0);
8
+ export function rollAffix(table, options = {}) {
9
+ const live = table.entries.filter((entry) => entry.weight > 0 &&
10
+ (options.curse === undefined || Boolean(entry.curse) === options.curse) &&
11
+ (options.predicate?.(entry) ?? true));
10
12
  if (live.length === 0)
11
13
  return null;
12
14
  const index = Random.weighted(live.map((entry) => entry.weight));
@@ -1 +1 @@
1
- {"version":3,"file":"Affix.js","sourceRoot":"","sources":["../../src/actors/Affix.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAuE5C;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAAiB;IAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACjE,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,OAAO,CAAC,IAAmB;IAC1C,OAAO,IAAI,CAAC,KAAK,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAmB,EAAE,KAAe;IAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC;IAC1C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC;IACtB,8EAA8E;IAC9E,sEAAsE;IACtE,IAAI,KAAK,CAAC,KAAK;QAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;SAC/B,IAAI,QAAQ;QAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;AACxC,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CAAC,IAAmB;IAC9C,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;QAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IAClD,OAAO,IAAI,CAAC,KAAK,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,IAAmB,EAAE,EAAiB;IAC/D,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9B,WAAW,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO;IACR,CAAC;IACD,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACtB,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAe,EAAE,OAAqB;IACpE,IAAI,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IACpD,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrG,OAAO,IAAI,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"Affix.js","sourceRoot":"","sources":["../../src/actors/Affix.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AA8E5C;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAAiB,EAAE,OAAO,GAAqB,EAAE;IAC1E,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAChC,CAAC,KAAK,EAAE,EAAE,CACT,KAAK,CAAC,MAAM,GAAG,CAAC;QAChB,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,KAAK,CAAC;QACvE,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CACrC,CAAC;IACF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACjE,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,OAAO,CAAC,IAAmB;IAC1C,OAAO,IAAI,CAAC,KAAK,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAmB,EAAE,KAAe;IAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC;IAC1C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC;IACtB,8EAA8E;IAC9E,sEAAsE;IACtE,IAAI,KAAK,CAAC,KAAK;QAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;SAC/B,IAAI,QAAQ;QAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;AACxC,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CAAC,IAAmB;IAC9C,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;QAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IAClD,OAAO,IAAI,CAAC,KAAK,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,IAAmB,EAAE,EAAiB;IAC/D,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9B,WAAW,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO;IACR,CAAC;IACD,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACtB,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAe,EAAE,OAAqB;IACpE,IAAI,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IACpD,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrG,OAAO,IAAI,CAAC;AACb,CAAC"}
@@ -31,6 +31,26 @@ export interface StatBlockOptions {
31
31
  base: Stats;
32
32
  derived?: DerivedStat[];
33
33
  }
34
+ /**
35
+ * Resolves one stat's modifiers into a single number.
36
+ *
37
+ * Every `add` modifier applies first (summed together), then every `multiply` (each
38
+ * scaling the running total), then every `set` (the last one wins) - a stated, fixed order,
39
+ * so a +10% ring and a cursed -2 sword combine the same way regardless of equip order, and
40
+ * a `set` modifier (a polymorph, a stat drained to exactly zero) always wins over the rest.
41
+ */
42
+ /**
43
+ * Apply the framework's canonical add, multiply, then set composition.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * import { composeModifiers } from '@datamoc/mw_games/actors';
48
+ *
49
+ * const attack = composeModifiers(10, [{ stat: 'attack', op: 'add', value: 2 }]);
50
+ * console.log(attack); // 12
51
+ * ```
52
+ */
53
+ export declare function composeModifiers(base: number, modifiers: readonly Modifier[]): number;
34
54
  export declare class StatBlock {
35
55
  private baseValues;
36
56
  private derived;
@@ -1 +1 @@
1
- {"version":3,"file":"StatBlock.d.ts","sourceRoot":"","sources":["../../src/actors/StatBlock.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE3C,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,KAAK,CAAC;AAEpD,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,UAAU,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,2FAA2F;IAC3F,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,IAAI,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;CACxB;AAqBD,qBAAa,SAAS;IACrB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,KAAK,CAAsB;IAEnC,YAAY,OAAO,EAAE,gBAAgB,EAGpC;IAED,uEAAuE;IACvE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzB;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAGzC;IAED,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAGpC;IAED,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAIvC;IAED,qFAAqF;IACrF,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAGzC;IAED,wFAAwF;IACxF,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExB;IAED,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,YAAY;IAIpB;;;;;;;;;OASG;IACH,MAAM,IAAI;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAExB;IAED,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,GAAG,SAAS,CAO3E;CACD"}
1
+ {"version":3,"file":"StatBlock.d.ts","sourceRoot":"","sources":["../../src/actors/StatBlock.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE3C,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,KAAK,CAAC;AAEpD,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,UAAU,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,2FAA2F;IAC3F,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,IAAI,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;CACxB;AAED;;;;;;;GAOG;AACH;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,CASrF;AAED,qBAAa,SAAS;IACrB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,KAAK,CAAsB;IAEnC,YAAY,OAAO,EAAE,gBAAgB,EAGpC;IAED,uEAAuE;IACvE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzB;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAGzC;IAED,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAGpC;IAED,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAIvC;IAED,qFAAqF;IACrF,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAGzC;IAED,wFAAwF;IACxF,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExB;IAED,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,YAAY;IAIpB;;;;;;;;;OASG;IACH,MAAM,IAAI;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAExB;IAED,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,GAAG,SAAS,CAO3E;CACD"}
@@ -15,7 +15,18 @@
15
15
  * so a +10% ring and a cursed -2 sword combine the same way regardless of equip order, and
16
16
  * a `set` modifier (a polymorph, a stat drained to exactly zero) always wins over the rest.
17
17
  */
18
- function resolve(base, modifiers) {
18
+ /**
19
+ * Apply the framework's canonical add, multiply, then set composition.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * import { composeModifiers } from '@datamoc/mw_games/actors';
24
+ *
25
+ * const attack = composeModifiers(10, [{ stat: 'attack', op: 'add', value: 2 }]);
26
+ * console.log(attack); // 12
27
+ * ```
28
+ */
29
+ export function composeModifiers(base, modifiers) {
19
30
  const byOp = (op) => modifiers.filter((m) => m.op === op).sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
20
31
  let value = base;
21
32
  for (const m of byOp('add'))
@@ -65,10 +76,10 @@ export class StatBlock {
65
76
  return this.cache;
66
77
  const result = { ...this.baseValues };
67
78
  for (const name of Object.keys(result)) {
68
- result[name] = resolve(result[name], this.modifiersFor(name));
79
+ result[name] = composeModifiers(result[name], this.modifiersFor(name));
69
80
  }
70
81
  for (const d of this.derived) {
71
- result[d.name] = resolve(d.from(result), this.modifiersFor(d.name));
82
+ result[d.name] = composeModifiers(d.from(result), this.modifiersFor(d.name));
72
83
  }
73
84
  this.cache = result;
74
85
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"StatBlock.js","sourceRoot":"","sources":["../../src/actors/StatBlock.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StatBlock.js","sourceRoot":"","sources":["../../src/actors/StatBlock.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export { StatBlock } from './StatBlock.ts';
1
+ export { composeModifiers, StatBlock } from './StatBlock.ts';
2
2
  export type { Stats, Modifier, ModifierOp, DerivedStat, StatBlockOptions } from './StatBlock.ts';
3
3
  export { Progression, powerCurve } from './Progression.ts';
4
4
  export type { GrowthCurve } from './Progression.ts';
@@ -24,7 +24,7 @@ export type { LootEntry, LootTable } from './Loot.ts';
24
24
  export { Advancement } from './Advancement.ts';
25
25
  export type { AdvancementOption, AdvancementTier, AdvancementTierKind, AdvancementTrack } from './Advancement.ts';
26
26
  export { rollAffix, affixOf, applyAffix, removeAffix, copyAffix, matchesContext } from './Affix.ts';
27
- export type { AffixDef, AffixTable, AffixTrigger, AttackKind, AffixContext } from './Affix.ts';
27
+ export type { AffixDef, AffixTable, AffixTrigger, AttackKind, AffixContext, RollAffixOptions } from './Affix.ts';
28
28
  export { scaledModifiers } from './Scaling.ts';
29
29
  export type { LevelScale } from './Scaling.ts';
30
30
  export { assignAppearances, Appearances } from './Appearances.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export { StatBlock } from './StatBlock.js';
1
+ export { composeModifiers, StatBlock } from './StatBlock.js';
2
2
  export { Progression, powerCurve } from './Progression.js';
3
3
  export { skillCheck } from './skillCheck.js';
4
4
  export { SkillPoints } from './SkillPoints.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAQ3C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEpG,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAQ3C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEpG,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,118 @@
1
+ import type { AlphaBetaGame, AlphaBetaOptions, AlphaBetaResult } from './search.ts';
2
+ export { alphaBetaSearch } from './search.ts';
3
+ export type { AlphaBetaGame, AlphaBetaOptions, AlphaBetaResult, LuaAlphaBetaFunctions, LuaSearchValueAdapter, } from './search.ts';
4
+ /** JSON-shaped values are the only values that cross the AI boundary. */
5
+ export type AIValue = null | boolean | number | string | AIValue[] | {
6
+ readonly [key: string]: AIValue;
7
+ };
8
+ export type AIState = Record<string, AIValue>;
9
+ export interface AIAction {
10
+ readonly type: string;
11
+ readonly [key: string]: AIValue;
12
+ }
13
+ export interface AIDecisionInput {
14
+ readonly perception: AIValue;
15
+ readonly state?: AIState;
16
+ readonly signal?: AbortSignal;
17
+ readonly seed?: number;
18
+ readonly maxSteps?: number;
19
+ readonly maxMilliseconds?: number;
20
+ }
21
+ export interface AIDecisionContext {
22
+ readonly perception: AIValue;
23
+ readonly state: AIState;
24
+ readonly random: () => number;
25
+ readonly checkpoint: () => void;
26
+ emit(name: string, payload?: AIValue): void;
27
+ }
28
+ export interface AIDecision {
29
+ readonly agent: string;
30
+ readonly action: AIAction | null;
31
+ readonly state: AIState;
32
+ readonly behavior?: string;
33
+ readonly status: 'action' | 'idle' | 'cancelled' | 'budget-exceeded';
34
+ readonly steps: number;
35
+ readonly events: readonly AIEvent[];
36
+ }
37
+ export interface AIEvent {
38
+ readonly name: string;
39
+ readonly payload?: AIValue;
40
+ }
41
+ export interface AIDiagnostics {
42
+ readonly onDecision?: (decision: AIDecision) => void;
43
+ }
44
+ export interface AIBehavior {
45
+ readonly id: string;
46
+ readonly when?: (context: AIDecisionContext) => boolean;
47
+ readonly decide: (context: AIDecisionContext) => AIAction | null;
48
+ }
49
+ export interface AIAgentDefinition {
50
+ readonly id: string;
51
+ readonly behaviors: readonly AIBehavior[];
52
+ readonly scope?: 'actor' | 'controller';
53
+ readonly algorithm?: 'rules' | 'alpha_beta';
54
+ readonly depth?: number;
55
+ readonly maxNodes?: number;
56
+ }
57
+ export interface AIStateEnvelope {
58
+ readonly version: 1;
59
+ readonly agents: Readonly<Record<string, AIState>>;
60
+ }
61
+ export interface AIModule {
62
+ register(agent: AIAgentDefinition): void;
63
+ decide(agent: string, input: AIDecisionInput): AIDecision;
64
+ exportState(): AIStateEnvelope;
65
+ importState(envelope: AIStateEnvelope): void;
66
+ dispose(): void;
67
+ }
68
+ export interface JavaScriptAIOptions extends AIDiagnostics {
69
+ readonly maxSteps?: number;
70
+ readonly maxMilliseconds?: number;
71
+ readonly seed?: number;
72
+ }
73
+ /**
74
+ * Renderer-free AI runner for game-owned JavaScript behaviours.
75
+ *
76
+ * Behaviours are checked in declaration order. A matching behaviour may return
77
+ * `null` to yield an idle decision. Long-running behaviours must call
78
+ * `checkpoint()` regularly: JavaScript cannot interrupt a synchronous function
79
+ * that never yields or checks its budget.
80
+ */
81
+ /**
82
+ * Runs game-owned JavaScript behaviours without knowing anything about a renderer or game
83
+ * rules.
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * import { JavaScriptAI, AICancelledError, AIBudgetExceededError } from '@datamoc/mw_games/ai';
88
+ *
89
+ * const ai = new JavaScriptAI({ seed: 7 });
90
+ * ai.register({ id: 'guard', behaviors: [{ id: 'wait', decide: () => ({ type: 'wait' }) }] });
91
+ * const decision = ai.decide('guard', { perception: { visible: true } });
92
+ * console.log(decision.action?.type); // 'wait'
93
+ * void AICancelledError;
94
+ * void AIBudgetExceededError;
95
+ * ```
96
+ */
97
+ export declare class JavaScriptAI implements AIModule {
98
+ private readonly agents;
99
+ private readonly states;
100
+ private readonly options;
101
+ constructor(options?: JavaScriptAIOptions);
102
+ register(agent: AIAgentDefinition): void;
103
+ decide(agentId: string, input: AIDecisionInput): AIDecision;
104
+ /** Run alpha-beta against a game-owned state adapter for an actor or controller. */
105
+ search<State, Move>(game: AlphaBetaGame<State, Move>, state: State, options: AlphaBetaOptions): AlphaBetaResult<State, Move>;
106
+ exportState(): AIStateEnvelope;
107
+ importState(envelope: AIStateEnvelope): void;
108
+ dispose(): void;
109
+ }
110
+ /** Raised internally when a cooperative decision observes an aborted signal. */
111
+ export declare class AICancelledError extends Error {
112
+ constructor();
113
+ }
114
+ /** Raised internally when a cooperative decision exceeds its configured budget. */
115
+ export declare class AIBudgetExceededError extends Error {
116
+ constructor();
117
+ }
118
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,203 @@
1
+ import { alphaBetaSearch } from './search.js';
2
+ export { alphaBetaSearch } from './search.js';
3
+ const DEFAULT_MAX_STEPS = 10_000;
4
+ const DEFAULT_MAX_MILLISECONDS = 16;
5
+ /**
6
+ * Renderer-free AI runner for game-owned JavaScript behaviours.
7
+ *
8
+ * Behaviours are checked in declaration order. A matching behaviour may return
9
+ * `null` to yield an idle decision. Long-running behaviours must call
10
+ * `checkpoint()` regularly: JavaScript cannot interrupt a synchronous function
11
+ * that never yields or checks its budget.
12
+ */
13
+ /**
14
+ * Runs game-owned JavaScript behaviours without knowing anything about a renderer or game
15
+ * rules.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { JavaScriptAI, AICancelledError, AIBudgetExceededError } from '@datamoc/mw_games/ai';
20
+ *
21
+ * const ai = new JavaScriptAI({ seed: 7 });
22
+ * ai.register({ id: 'guard', behaviors: [{ id: 'wait', decide: () => ({ type: 'wait' }) }] });
23
+ * const decision = ai.decide('guard', { perception: { visible: true } });
24
+ * console.log(decision.action?.type); // 'wait'
25
+ * void AICancelledError;
26
+ * void AIBudgetExceededError;
27
+ * ```
28
+ */
29
+ export class JavaScriptAI {
30
+ constructor(options = {}) {
31
+ this.agents = new Map();
32
+ this.states = new Map();
33
+ this.options = options;
34
+ validatePositiveInteger(options.maxSteps ?? DEFAULT_MAX_STEPS, 'maxSteps');
35
+ validateNonNegativeFinite(options.maxMilliseconds ?? DEFAULT_MAX_MILLISECONDS, 'maxMilliseconds');
36
+ }
37
+ register(agent) {
38
+ if (!/^[A-Za-z_][A-Za-z0-9_.-]*$/.test(agent.id))
39
+ throw new Error(`invalid AI agent id: ${agent.id}`);
40
+ if (this.agents.has(agent.id))
41
+ throw new Error(`AI agent already registered: ${agent.id}`);
42
+ if (!agent.behaviors.length)
43
+ throw new Error(`AI agent has no behaviours: ${agent.id}`);
44
+ const ids = new Set();
45
+ for (const behavior of agent.behaviors) {
46
+ if (!behavior.id || ids.has(behavior.id))
47
+ throw new Error(`duplicate AI behaviour: ${behavior.id}`);
48
+ ids.add(behavior.id);
49
+ }
50
+ this.agents.set(agent.id, agent);
51
+ this.states.set(agent.id, {});
52
+ }
53
+ decide(agentId, input) {
54
+ const agent = this.agents.get(agentId);
55
+ if (!agent)
56
+ throw new Error(`unknown AI agent: ${agentId}`);
57
+ const state = cloneState(input.state ?? this.states.get(agentId) ?? {});
58
+ const maxSteps = input.maxSteps ?? this.options.maxSteps ?? DEFAULT_MAX_STEPS;
59
+ const maxMilliseconds = input.maxMilliseconds ?? this.options.maxMilliseconds ?? DEFAULT_MAX_MILLISECONDS;
60
+ validatePositiveInteger(maxSteps, 'maxSteps');
61
+ validateNonNegativeFinite(maxMilliseconds, 'maxMilliseconds');
62
+ let steps = 0;
63
+ const started = performanceNow();
64
+ const events = [];
65
+ const random = seededRandom(input.seed ?? this.options.seed ?? 0x6d7767);
66
+ const checkpoint = () => {
67
+ steps++;
68
+ if (input.signal?.aborted)
69
+ throw new AICancelledError();
70
+ if (steps > maxSteps || performanceNow() - started > maxMilliseconds)
71
+ throw new AIBudgetExceededError();
72
+ };
73
+ const context = {
74
+ perception: cloneValue(input.perception),
75
+ state,
76
+ random: () => {
77
+ checkpoint();
78
+ return random();
79
+ },
80
+ checkpoint,
81
+ emit(name, payload) {
82
+ if (!name)
83
+ throw new Error('AI event name must not be empty');
84
+ checkpoint();
85
+ events.push(payload === undefined ? { name } : { name, payload: cloneValue(payload) });
86
+ },
87
+ };
88
+ let action = null;
89
+ let behaviorId;
90
+ let status = 'idle';
91
+ try {
92
+ for (const behavior of agent.behaviors) {
93
+ checkpoint();
94
+ if (behavior.when && !behavior.when(context))
95
+ continue;
96
+ behaviorId = behavior.id;
97
+ action = validateAction(behavior.decide(context));
98
+ status = action ? 'action' : 'idle';
99
+ break;
100
+ }
101
+ }
102
+ catch (error) {
103
+ if (error instanceof AICancelledError)
104
+ status = 'cancelled';
105
+ else if (error instanceof AIBudgetExceededError)
106
+ status = 'budget-exceeded';
107
+ else
108
+ throw error;
109
+ }
110
+ const decision = {
111
+ agent: agentId,
112
+ action,
113
+ state: cloneState(state),
114
+ behavior: behaviorId,
115
+ status,
116
+ steps,
117
+ events,
118
+ };
119
+ this.states.set(agentId, cloneState(state));
120
+ this.options.onDecision?.(decision);
121
+ return decision;
122
+ }
123
+ /** Run alpha-beta against a game-owned state adapter for an actor or controller. */
124
+ search(game, state, options) {
125
+ return alphaBetaSearch(game, state, options);
126
+ }
127
+ exportState() {
128
+ return {
129
+ version: 1,
130
+ agents: Object.fromEntries([...this.states].map(([id, state]) => [id, cloneState(state)])),
131
+ };
132
+ }
133
+ importState(envelope) {
134
+ if (envelope.version !== 1)
135
+ throw new Error(`unsupported AI state version: ${envelope.version}`);
136
+ for (const [id, state] of Object.entries(envelope.agents)) {
137
+ if (!this.agents.has(id))
138
+ throw new Error(`AI state names unknown agent: ${id}`);
139
+ this.states.set(id, cloneState(state));
140
+ }
141
+ }
142
+ dispose() {
143
+ this.agents.clear();
144
+ this.states.clear();
145
+ }
146
+ }
147
+ /** Raised internally when a cooperative decision observes an aborted signal. */
148
+ export class AICancelledError extends Error {
149
+ constructor() {
150
+ super('AI decision cancelled');
151
+ this.name = 'AICancelledError';
152
+ }
153
+ }
154
+ /** Raised internally when a cooperative decision exceeds its configured budget. */
155
+ export class AIBudgetExceededError extends Error {
156
+ constructor() {
157
+ super('AI decision budget exceeded');
158
+ this.name = 'AIBudgetExceededError';
159
+ }
160
+ }
161
+ function validateAction(action) {
162
+ if (action === null)
163
+ return null;
164
+ if (!action ||
165
+ typeof action !== 'object' ||
166
+ Array.isArray(action) ||
167
+ typeof action.type !== 'string' ||
168
+ !action.type) {
169
+ throw new Error('AI action must be an object with a non-empty string type');
170
+ }
171
+ return cloneValue(action);
172
+ }
173
+ function cloneState(state) {
174
+ return cloneValue(state);
175
+ }
176
+ function cloneValue(value) {
177
+ if (value === null || typeof value !== 'object')
178
+ return value;
179
+ if (Array.isArray(value))
180
+ return value.map(cloneValue);
181
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, cloneValue(entry)]));
182
+ }
183
+ function seededRandom(seed) {
184
+ if (!Number.isInteger(seed))
185
+ throw new TypeError('AI seed must be an integer');
186
+ let state = seed >>> 0;
187
+ return () => {
188
+ state = (Math.imul(state, 1664525) + 1013904223) >>> 0;
189
+ return state / 0x1_0000_0000;
190
+ };
191
+ }
192
+ function validatePositiveInteger(value, name) {
193
+ if (!Number.isInteger(value) || value < 1)
194
+ throw new RangeError(`${name} must be a positive integer`);
195
+ }
196
+ function validateNonNegativeFinite(value, name) {
197
+ if (!Number.isFinite(value) || value < 0)
198
+ throw new RangeError(`${name} must be a non-negative number`);
199
+ }
200
+ function performanceNow() {
201
+ return typeof performance === 'undefined' ? Date.now() : performance.now();
202
+ }
203
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"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"}