@datamoc/mw_games 0.20.0 → 0.23.0

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 (151) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/dist/audio/Channels.d.ts +19 -0
  3. package/dist/audio/Channels.d.ts.map +1 -1
  4. package/dist/audio/Channels.js +33 -4
  5. package/dist/audio/Channels.js.map +1 -1
  6. package/dist/audio/LoopTags.d.ts +37 -0
  7. package/dist/audio/LoopTags.d.ts.map +1 -0
  8. package/dist/audio/LoopTags.js +116 -0
  9. package/dist/audio/LoopTags.js.map +1 -0
  10. package/dist/audio/Midi.d.ts +29 -0
  11. package/dist/audio/Midi.d.ts.map +1 -1
  12. package/dist/audio/Midi.js +30 -1
  13. package/dist/audio/Midi.js.map +1 -1
  14. package/dist/audio/MidiRender.d.ts +3 -2
  15. package/dist/audio/MidiRender.d.ts.map +1 -1
  16. package/dist/audio/MidiRender.js +2 -2
  17. package/dist/audio/MidiRender.js.map +1 -1
  18. package/dist/audio/humanize/Groove.d.ts +80 -0
  19. package/dist/audio/humanize/Groove.d.ts.map +1 -0
  20. package/dist/audio/humanize/Groove.js +102 -0
  21. package/dist/audio/humanize/Groove.js.map +1 -0
  22. package/dist/audio/humanize/GrooveConverter.d.ts +49 -0
  23. package/dist/audio/humanize/GrooveConverter.d.ts.map +1 -0
  24. package/dist/audio/humanize/GrooveConverter.js +344 -0
  25. package/dist/audio/humanize/GrooveConverter.js.map +1 -0
  26. package/dist/audio/humanize/GrooveExtractor.d.ts +49 -0
  27. package/dist/audio/humanize/GrooveExtractor.d.ts.map +1 -0
  28. package/dist/audio/humanize/GrooveExtractor.js +179 -0
  29. package/dist/audio/humanize/GrooveExtractor.js.map +1 -0
  30. package/dist/audio/humanize/GrooveHumanizer.d.ts +34 -0
  31. package/dist/audio/humanize/GrooveHumanizer.d.ts.map +1 -0
  32. package/dist/audio/humanize/GrooveHumanizer.js +37 -0
  33. package/dist/audio/humanize/GrooveHumanizer.js.map +1 -0
  34. package/dist/audio/humanize/Humanize.d.ts +54 -0
  35. package/dist/audio/humanize/Humanize.d.ts.map +1 -0
  36. package/dist/audio/humanize/Humanize.js +239 -0
  37. package/dist/audio/humanize/Humanize.js.map +1 -0
  38. package/dist/audio/humanize/HumanizerFactory.d.ts +68 -0
  39. package/dist/audio/humanize/HumanizerFactory.d.ts.map +1 -0
  40. package/dist/audio/humanize/HumanizerFactory.js +84 -0
  41. package/dist/audio/humanize/HumanizerFactory.js.map +1 -0
  42. package/dist/audio/humanize/LiteHumanizer.d.ts +30 -0
  43. package/dist/audio/humanize/LiteHumanizer.d.ts.map +1 -0
  44. package/dist/audio/humanize/LiteHumanizer.js +35 -0
  45. package/dist/audio/humanize/LiteHumanizer.js.map +1 -0
  46. package/dist/audio/humanize/Onsets.d.ts +26 -0
  47. package/dist/audio/humanize/Onsets.d.ts.map +1 -0
  48. package/dist/audio/humanize/Onsets.js +164 -0
  49. package/dist/audio/humanize/Onsets.js.map +1 -0
  50. package/dist/audio/index.d.ts +14 -1
  51. package/dist/audio/index.d.ts.map +1 -1
  52. package/dist/audio/index.js +7 -0
  53. package/dist/audio/index.js.map +1 -1
  54. package/dist/board/bitboard.d.ts +132 -0
  55. package/dist/board/bitboard.d.ts.map +1 -0
  56. package/dist/board/bitboard.js +495 -0
  57. package/dist/board/bitboard.js.map +1 -0
  58. package/dist/board/chess.d.ts +16 -0
  59. package/dist/board/chess.d.ts.map +1 -1
  60. package/dist/board/chess.js +43 -0
  61. package/dist/board/chess.js.map +1 -1
  62. package/dist/board/index.d.ts +9 -1
  63. package/dist/board/index.d.ts.map +1 -1
  64. package/dist/board/index.js +5 -1
  65. package/dist/board/index.js.map +1 -1
  66. package/dist/board/openings.d.ts +58 -0
  67. package/dist/board/openings.d.ts.map +1 -0
  68. package/dist/board/openings.js +45 -0
  69. package/dist/board/openings.js.map +1 -0
  70. package/dist/board/tablebase.d.ts +118 -0
  71. package/dist/board/tablebase.d.ts.map +1 -0
  72. package/dist/board/tablebase.js +414 -0
  73. package/dist/board/tablebase.js.map +1 -0
  74. package/dist/board/tourney.d.ts +90 -0
  75. package/dist/board/tourney.d.ts.map +1 -0
  76. package/dist/board/tourney.js +1013 -0
  77. package/dist/board/tourney.js.map +1 -0
  78. package/dist/core/JavaRandom.d.ts +55 -0
  79. package/dist/core/JavaRandom.d.ts.map +1 -0
  80. package/dist/core/JavaRandom.js +81 -0
  81. package/dist/core/JavaRandom.js.map +1 -0
  82. package/dist/core/index.d.ts +2 -0
  83. package/dist/core/index.d.ts.map +1 -1
  84. package/dist/core/index.js +1 -0
  85. package/dist/core/index.js.map +1 -1
  86. package/dist/mw_games.global.js +123 -116
  87. package/dist/rpg/EventRunner.d.ts +7 -0
  88. package/dist/rpg/EventRunner.d.ts.map +1 -1
  89. package/dist/rpg/EventRunner.js +6 -0
  90. package/dist/rpg/EventRunner.js.map +1 -1
  91. package/dist/rpg/MoveRoute.d.ts +35 -4
  92. package/dist/rpg/MoveRoute.d.ts.map +1 -1
  93. package/dist/rpg/MoveRoute.js +40 -11
  94. package/dist/rpg/MoveRoute.js.map +1 -1
  95. package/dist/two-d/render/FogLayer.d.ts +68 -0
  96. package/dist/two-d/render/FogLayer.d.ts.map +1 -0
  97. package/dist/two-d/render/FogLayer.js +83 -0
  98. package/dist/two-d/render/FogLayer.js.map +1 -0
  99. package/dist/two-d/render/LiquidLayer.d.ts +62 -0
  100. package/dist/two-d/render/LiquidLayer.d.ts.map +1 -0
  101. package/dist/two-d/render/LiquidLayer.js +102 -0
  102. package/dist/two-d/render/LiquidLayer.js.map +1 -0
  103. package/dist/two-d/render/RpgmAutotile.d.ts +42 -0
  104. package/dist/two-d/render/RpgmAutotile.d.ts.map +1 -1
  105. package/dist/two-d/render/RpgmAutotile.js +71 -4
  106. package/dist/two-d/render/RpgmAutotile.js.map +1 -1
  107. package/dist/two-d/render/TileMap.d.ts +50 -2
  108. package/dist/two-d/render/TileMap.d.ts.map +1 -1
  109. package/dist/two-d/render/TileMap.js +120 -2
  110. package/dist/two-d/render/TileMap.js.map +1 -1
  111. package/dist/two-d/render/index.d.ts +7 -3
  112. package/dist/two-d/render/index.d.ts.map +1 -1
  113. package/dist/two-d/render/index.js +3 -1
  114. package/dist/two-d/render/index.js.map +1 -1
  115. package/dist/two-d/ui/Label.d.ts.map +1 -1
  116. package/dist/two-d/ui/Label.js +11 -2
  117. package/dist/two-d/ui/Label.js.map +1 -1
  118. package/dist/two-d/ui/ListView.d.ts +24 -0
  119. package/dist/two-d/ui/ListView.d.ts.map +1 -1
  120. package/dist/two-d/ui/ListView.js +97 -4
  121. package/dist/two-d/ui/ListView.js.map +1 -1
  122. package/dist/two-d/ui/MessageLog.d.ts +62 -0
  123. package/dist/two-d/ui/MessageLog.d.ts.map +1 -0
  124. package/dist/two-d/ui/MessageLog.js +114 -0
  125. package/dist/two-d/ui/MessageLog.js.map +1 -0
  126. package/dist/two-d/ui/RadioGroup.d.ts +68 -0
  127. package/dist/two-d/ui/RadioGroup.d.ts.map +1 -0
  128. package/dist/two-d/ui/RadioGroup.js +177 -0
  129. package/dist/two-d/ui/RadioGroup.js.map +1 -0
  130. package/dist/two-d/ui/TextModel.d.ts +26 -1
  131. package/dist/two-d/ui/TextModel.d.ts.map +1 -1
  132. package/dist/two-d/ui/TextModel.js +56 -7
  133. package/dist/two-d/ui/TextModel.js.map +1 -1
  134. package/dist/two-d/ui/TextSharpness.d.ts +33 -0
  135. package/dist/two-d/ui/TextSharpness.d.ts.map +1 -0
  136. package/dist/two-d/ui/TextSharpness.js +56 -0
  137. package/dist/two-d/ui/TextSharpness.js.map +1 -0
  138. package/dist/two-d/ui/index.d.ts +5 -0
  139. package/dist/two-d/ui/index.d.ts.map +1 -1
  140. package/dist/two-d/ui/index.js +3 -0
  141. package/dist/two-d/ui/index.js.map +1 -1
  142. package/dist/version.d.ts +1 -1
  143. package/dist/version.js +1 -1
  144. package/package.json +19 -7
  145. package/sbom.cdx.json +194 -32
  146. package/tools/build-tablebases.d.mts +22 -0
  147. package/tools/build-tablebases.mjs +549 -0
  148. package/tools/compile-openings.d.mts +20 -0
  149. package/tools/compile-openings.mjs +130 -0
  150. package/tools/play-uci.d.mts +26 -0
  151. package/tools/play-uci.mjs +194 -0
@@ -95,6 +95,13 @@ export interface EventRunnerOptions {
95
95
  game: GameState;
96
96
  /** carries out a move command; the runner itself does not know what "moving" means */
97
97
  move?: (target: string, steps: readonly MoveStep[]) => Promise<void>;
98
+ /**
99
+ * Called for a command the runner does not know (a converter's `transfer`, `picture`,
100
+ * `sound`, ...), and for a `goto` in a straight `run()`, which ends that list. Without
101
+ * it an unknown command is skipped silently; a game that converts foreign event data
102
+ * passes one to make every dropped command loud.
103
+ */
104
+ onUnknownCommand?: (command: EventCommand) => void;
98
105
  }
99
106
  /**
100
107
  * @example
@@ -1 +1 @@
1
- {"version":3,"file":"EventRunner.d.ts","sourceRoot":"","sources":["../../src/rpg/EventRunner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EventRunner.d.ts","sourceRoot":"","sources":["../../src/rpg/EventRunner.ts"],"names":[],"mappings":"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"}
@@ -25,6 +25,10 @@ export class EventRunner {
25
25
  async run(commands) {
26
26
  const jump = await this.runList(commands);
27
27
  if (jump !== undefined) {
28
+ if (this.options.onUnknownCommand) {
29
+ this.options.onUnknownCommand({ goto: jump });
30
+ return this.state;
31
+ }
28
32
  throw new Error(`a "goto ${jump}" only runs inside runStory, not a straight run`);
29
33
  }
30
34
  return this.state;
@@ -109,7 +113,9 @@ export class EventRunner {
109
113
  }
110
114
  if ('call' in command) {
111
115
  await command.call(this.state);
116
+ return undefined;
112
117
  }
118
+ this.options.onUnknownCommand?.(command);
113
119
  return undefined;
114
120
  }
115
121
  speak(text, speaker, portrait, choices) {
@@ -1 +1 @@
1
- {"version":3,"file":"EventRunner.js","sourceRoot":"","sources":["../../src/rpg/EventRunner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EventRunner.js","sourceRoot":"","sources":["../../src/rpg/EventRunner.ts"],"names":[],"mappings":"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"}
@@ -9,13 +9,28 @@ export type MoveRouteStep = {
9
9
  dir: Direction4;
10
10
  } | {
11
11
  dir: 'random';
12
- } | {
12
+ }
13
+ /** one tile along (or against) the way the mover currently faces */
14
+ | {
15
+ dir: 'forward' | 'backward';
16
+ } | ({
13
17
  dir: 'toward' | 'away';
14
- x: number;
15
- y: number;
18
+ } & RouteTarget)
19
+ /** a step of any size and direction, diagonals included; `canMove` is asked with the same `dx`/`dy` */
20
+ | {
21
+ step: {
22
+ dx: number;
23
+ dy: number;
24
+ };
16
25
  } | {
17
26
  turn: Direction4 | 'random';
18
- } | {
27
+ }
28
+ /** a quarter or half turn from the way the mover currently faces */
29
+ | {
30
+ turn: 'around' | 'left90' | 'right90';
31
+ } | ({
32
+ turn: 'toward' | 'away';
33
+ } & RouteTarget) | {
19
34
  jump: {
20
35
  dx: number;
21
36
  dy: number;
@@ -23,6 +38,19 @@ export type MoveRouteStep = {
23
38
  } | {
24
39
  wait: number;
25
40
  };
41
+ /**
42
+ * Where a `toward`/`away` step aims: fixed tile coordinates, or a function asked when the step
43
+ * is reached, for a target that keeps moving (a player, another event).
44
+ */
45
+ export type RouteTarget = {
46
+ x: number;
47
+ y: number;
48
+ } | {
49
+ target: () => {
50
+ x: number;
51
+ y: number;
52
+ };
53
+ };
26
54
  export interface MoveRoute {
27
55
  steps: readonly MoveRouteStep[];
28
56
  /** loops back to the first step once the last one finishes, rather than stopping there */
@@ -81,6 +109,9 @@ export declare class MoveRouteRunner {
81
109
  /** @returns whether the step actually moved/turned/waited, so the runner can decide to skip it */
82
110
  private runStep;
83
111
  private resolveDirection;
112
+ private resolveTurn;
113
+ /** one tile along the larger axis towards (or away from) a target, from where the mover stands now */
114
+ private resolveAim;
84
115
  private attempt;
85
116
  private pickDirection;
86
117
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MoveRoute.d.ts","sourceRoot":"","sources":["../../src/rpg/MoveRoute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAW5D;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACtB;IAAE,GAAG,EAAE,UAAU,CAAA;CAAE,GACnB;IAAE,GAAG,EAAE,QAAQ,CAAA;CAAE,GACjB;IAAE,GAAG,EAAE,QAAQ,GAAG,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpB,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IAEhC,0FAA0F;IAC1F,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAChC,2GAA2G;IAC3G,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IAE9C,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,eAAe;IAC3B,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,OAAO,CAAK;IAEpB,YAAY,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,gBAAqB,EAI7E;IAED,yDAAyD;IACzD,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAevB;IAED,kGAAkG;IAClG,OAAO,CAAC,OAAO;IAqBf,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,aAAa;CAIrB"}
1
+ {"version":3,"file":"MoveRoute.d.ts","sourceRoot":"","sources":["../../src/rpg/MoveRoute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAmB5D;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACtB;IAAE,GAAG,EAAE,UAAU,CAAA;CAAE,GACnB;IAAE,GAAG,EAAE,QAAQ,CAAA;CAAE;AACnB,oEAAoE;GAClE;IAAE,GAAG,EAAE,SAAS,GAAG,UAAU,CAAA;CAAE,GAC/B,CAAC;IAAE,GAAG,EAAE,QAAQ,GAAG,MAAM,CAAA;CAAE,GAAG,WAAW,CAAC;AAC5C,uGAAuG;GACrG;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAA;CAAE;AACjC,oEAAoE;GAClE;IAAE,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAA;CAAE,GACzC,CAAC;IAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAA;CAAE,GAAG,WAAW,CAAC,GAC3C;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpB;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAEhG,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IAEhC,0FAA0F;IAC1F,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAChC,2GAA2G;IAC3G,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IAE9C,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,eAAe;IAC3B,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,OAAO,CAAK;IAEpB,YAAY,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,gBAAqB,EAI7E;IAED,yDAAyD;IACzD,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAevB;IAED,kGAAkG;IAClG,OAAO,CAAC,OAAO;IAwBf,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,WAAW;IAgBnB,sGAAsG;IACtG,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,aAAa;CAIrB"}
@@ -6,6 +6,13 @@ const DELTA = {
6
6
  left: { dx: -1, dy: 0 },
7
7
  right: { dx: 1, dy: 0 },
8
8
  };
9
+ /** what a quarter or half turn from each facing lands on */
10
+ const TURNED = {
11
+ up: { around: 'down', left90: 'left', right90: 'right' },
12
+ down: { around: 'up', left90: 'right', right90: 'left' },
13
+ left: { around: 'right', left90: 'down', right90: 'up' },
14
+ right: { around: 'left', left90: 'up', right90: 'down' },
15
+ };
9
16
  /**
10
17
  * Drives a `GridMover` through a `MoveRoute` over successive `update(dt)` calls - the piece
11
18
  * `GridMover`'s own one-step-at-a-time `moveBy`/`turnTo` deliberately leaves out (see its own
@@ -66,8 +73,7 @@ export class MoveRouteRunner {
66
73
  /** @returns whether the step actually moved/turned/waited, so the runner can decide to skip it */
67
74
  runStep(step) {
68
75
  if ('turn' in step) {
69
- const direction = step.turn === 'random' ? this.pickDirection() : step.turn;
70
- const { dx, dy } = DELTA[direction];
76
+ const { dx, dy } = this.resolveTurn(step);
71
77
  this.mover.turnTo(dx, dy);
72
78
  return true;
73
79
  }
@@ -78,23 +84,46 @@ export class MoveRouteRunner {
78
84
  if ('jump' in step) {
79
85
  return this.attempt(step.jump.dx, step.jump.dy, (dx, dy) => this.mover.jumpBy(dx, dy));
80
86
  }
87
+ if ('step' in step) {
88
+ return this.attempt(step.step.dx, step.step.dy, (dx, dy) => this.mover.moveBy(dx, dy));
89
+ }
81
90
  const { dx, dy } = this.resolveDirection(step);
82
91
  return this.attempt(dx, dy, (dx, dy) => this.mover.moveBy(dx, dy));
83
92
  }
84
93
  resolveDirection(step) {
85
94
  if (step.dir === 'random')
86
95
  return DELTA[this.pickDirection()];
87
- if (step.dir === 'toward' || step.dir === 'away') {
88
- const sign = step.dir === 'toward' ? 1 : -1;
89
- const ddx = step.x - this.mover.x;
90
- const ddy = step.y - this.mover.y;
91
- //the larger axis first, matching the direction a step would actually close (or open)
92
- return Math.abs(ddx) >= Math.abs(ddy)
93
- ? { dx: sign * Math.sign(ddx) || 0, dy: 0 }
94
- : { dx: 0, dy: sign * Math.sign(ddy) || 0 };
95
- }
96
+ if (step.dir === 'forward')
97
+ return DELTA[this.mover.facing];
98
+ if (step.dir === 'backward')
99
+ return DELTA[TURNED[this.mover.facing].around];
100
+ if (step.dir === 'toward' || step.dir === 'away')
101
+ return this.resolveAim(step.dir, step);
96
102
  return DELTA[step.dir];
97
103
  }
104
+ resolveTurn(step) {
105
+ if (step.turn === 'random')
106
+ return DELTA[this.pickDirection()];
107
+ if (step.turn === 'around' || step.turn === 'left90' || step.turn === 'right90') {
108
+ return DELTA[TURNED[this.mover.facing][step.turn]];
109
+ }
110
+ if (step.turn === 'toward' || step.turn === 'away') {
111
+ const aim = this.resolveAim(step.turn, step);
112
+ return aim.dx === 0 && aim.dy === 0 ? DELTA[this.mover.facing] : aim;
113
+ }
114
+ return DELTA[step.turn];
115
+ }
116
+ /** one tile along the larger axis towards (or away from) a target, from where the mover stands now */
117
+ resolveAim(way, aim) {
118
+ const at = 'target' in aim ? aim.target() : aim;
119
+ const sign = way === 'toward' ? 1 : -1;
120
+ const ddx = at.x - this.mover.x;
121
+ const ddy = at.y - this.mover.y;
122
+ //the larger axis first, matching the direction a step would actually close (or open)
123
+ return Math.abs(ddx) >= Math.abs(ddy)
124
+ ? { dx: sign * Math.sign(ddx) || 0, dy: 0 }
125
+ : { dx: 0, dy: sign * Math.sign(ddy) || 0 };
126
+ }
98
127
  attempt(dx, dy, move) {
99
128
  if (dx === 0 && dy === 0)
100
129
  return true;
@@ -1 +1 @@
1
- {"version":3,"file":"MoveRoute.js","sourceRoot":"","sources":["../../src/rpg/MoveRoute.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MoveRoute.js","sourceRoot":"","sources":["../../src/rpg/MoveRoute.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import { Sprite } from 'pixi.js';
2
+ /** red, green, blue, alpha, each 0 to 255 */
3
+ export type FogColor = readonly [number, number, number, number];
4
+ /**
5
+ * What a cell's fog state is: one state number for the whole cell, or `resolution *
6
+ * resolution` of them (row-major) so a cell can be shaded in parts, the half-lit wall edge
7
+ * of a classic roguelike.
8
+ */
9
+ export type FogCell = number | ArrayLike<number>;
10
+ /**
11
+ * Paints per-cell fog into an RGBA pixel buffer of `width * resolution` by `height *
12
+ * resolution` pixels. Pure: no canvas involved, so the shading rule is checkable anywhere.
13
+ * A state with no palette entry paints transparent.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { paintFogPixels } from '@datamoc/mw_games/two-d/render';
18
+ *
19
+ * const pixels = new Uint8ClampedArray(2 * 1 * 4);
20
+ * paintFogPixels(pixels, 2, 1, 1, (x) => x, [[0, 0, 0, 0], [0, 0, 0, 255]]);
21
+ * console.log(pixels[7]); // 255 - the second cell is fully fogged
22
+ * ```
23
+ */
24
+ export declare function paintFogPixels(pixels: Uint8ClampedArray | Uint8Array, width: number, height: number, resolution: number, state: (x: number, y: number) => FogCell, palette: readonly FogColor[]): void;
25
+ export interface FogLayerOptions {
26
+ /** map size in tiles */
27
+ width: number;
28
+ height: number;
29
+ /** tile size in world units; default 16 */
30
+ tileSize?: number;
31
+ /** fog pixels per tile along each axis; default 2 */
32
+ resolution?: number;
33
+ /** the RGBA colour of each state number */
34
+ palette: readonly FogColor[];
35
+ }
36
+ /**
37
+ * A smooth fog-of-war overlay: a small canvas with `resolution` pixels per tile, scaled up
38
+ * with linear filtering, so fog edges blur into the next cell instead of stepping by whole
39
+ * tiles. Draw it above terrain and characters, and call `refresh` when visibility changes.
40
+ * Needs a DOM canvas; `paintFogPixels` is the same shading without one.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import { FogLayer } from '@datamoc/mw_games/two-d/render';
45
+ *
46
+ * const fog = new FogLayer({
47
+ * width: 20,
48
+ * height: 20,
49
+ * palette: [[0, 0, 0, 0], [0, 0, 0, 150], [0, 0, 0, 255]], // seen, remembered, unknown
50
+ * });
51
+ * fog.refresh((x, y) => (x < 5 ? 0 : 2));
52
+ * ```
53
+ */
54
+ export declare class FogLayer extends Sprite {
55
+ private readonly context;
56
+ private readonly image;
57
+ private readonly columns;
58
+ private readonly rows;
59
+ private readonly cellResolution;
60
+ private palette;
61
+ constructor(options: FogLayerOptions);
62
+ /** swaps the palette, for a brightness setting; call `refresh` afterwards */
63
+ setPalette(palette: readonly FogColor[]): void;
64
+ refresh(state: (x: number, y: number) => FogCell): void;
65
+ /** the texture is generated for this layer alone, so it goes with it */
66
+ destroy(): void;
67
+ }
68
+ //# sourceMappingURL=FogLayer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FogLayer.d.ts","sourceRoot":"","sources":["../../../src/two-d/render/FogLayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAW,MAAM,SAAS,CAAC;AAE1C,6CAA6C;AAC7C,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEjE;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC7B,MAAM,EAAE,iBAAiB,GAAG,UAAU,EACtC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,EACxC,OAAO,EAAE,SAAS,QAAQ,EAAE,GAC1B,IAAI,CAcN;AAED,MAAM,WAAW,eAAe;IAC/B,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,QAAS,SAAQ,MAAM;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,OAAO,CAAsB;IAErC,YAAY,OAAO,EAAE,eAAe,EAiBnC;IAED,6EAA6E;IAC7E,UAAU,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,GAAG,IAAI,CAE7C;IAED,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAItD;IAED,wEAAwE;IAC/D,OAAO,IAAI,IAAI,CAEvB;CACD"}
@@ -0,0 +1,83 @@
1
+ import { Sprite, Texture } from 'pixi.js';
2
+ /**
3
+ * Paints per-cell fog into an RGBA pixel buffer of `width * resolution` by `height *
4
+ * resolution` pixels. Pure: no canvas involved, so the shading rule is checkable anywhere.
5
+ * A state with no palette entry paints transparent.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { paintFogPixels } from '@datamoc/mw_games/two-d/render';
10
+ *
11
+ * const pixels = new Uint8ClampedArray(2 * 1 * 4);
12
+ * paintFogPixels(pixels, 2, 1, 1, (x) => x, [[0, 0, 0, 0], [0, 0, 0, 255]]);
13
+ * console.log(pixels[7]); // 255 - the second cell is fully fogged
14
+ * ```
15
+ */
16
+ export function paintFogPixels(pixels, width, height, resolution, state, palette) {
17
+ const stride = width * resolution;
18
+ for (let y = 0; y < height; y++) {
19
+ for (let x = 0; x < width; x++) {
20
+ const cell = state(x, y);
21
+ for (let row = 0; row < resolution; row++) {
22
+ for (let column = 0; column < resolution; column++) {
23
+ const value = typeof cell === 'number' ? cell : (cell[row * resolution + column] ?? 0);
24
+ const color = palette[value] ?? [0, 0, 0, 0];
25
+ pixels.set(color, ((y * resolution + row) * stride + x * resolution + column) * 4);
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
31
+ /**
32
+ * A smooth fog-of-war overlay: a small canvas with `resolution` pixels per tile, scaled up
33
+ * with linear filtering, so fog edges blur into the next cell instead of stepping by whole
34
+ * tiles. Draw it above terrain and characters, and call `refresh` when visibility changes.
35
+ * Needs a DOM canvas; `paintFogPixels` is the same shading without one.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * import { FogLayer } from '@datamoc/mw_games/two-d/render';
40
+ *
41
+ * const fog = new FogLayer({
42
+ * width: 20,
43
+ * height: 20,
44
+ * palette: [[0, 0, 0, 0], [0, 0, 0, 150], [0, 0, 0, 255]], // seen, remembered, unknown
45
+ * });
46
+ * fog.refresh((x, y) => (x < 5 ? 0 : 2));
47
+ * ```
48
+ */
49
+ export class FogLayer extends Sprite {
50
+ constructor(options) {
51
+ const resolution = options.resolution ?? 2;
52
+ const canvas = document.createElement('canvas');
53
+ canvas.width = options.width * resolution;
54
+ canvas.height = options.height * resolution;
55
+ const context = canvas.getContext('2d');
56
+ if (!context)
57
+ throw new Error('FogLayer needs a 2D canvas context');
58
+ super(Texture.from(canvas));
59
+ this.context = context;
60
+ this.image = context.createImageData(canvas.width, canvas.height);
61
+ this.columns = options.width;
62
+ this.rows = options.height;
63
+ this.cellResolution = resolution;
64
+ this.palette = options.palette;
65
+ this.texture.source.scaleMode = 'linear';
66
+ this.scale.set((options.tileSize ?? 16) / resolution);
67
+ this.eventMode = 'none';
68
+ }
69
+ /** swaps the palette, for a brightness setting; call `refresh` afterwards */
70
+ setPalette(palette) {
71
+ this.palette = palette;
72
+ }
73
+ refresh(state) {
74
+ paintFogPixels(this.image.data, this.columns, this.rows, this.cellResolution, state, this.palette);
75
+ this.context.putImageData(this.image, 0, 0);
76
+ this.texture.source.update();
77
+ }
78
+ /** the texture is generated for this layer alone, so it goes with it */
79
+ destroy() {
80
+ super.destroy({ texture: true, textureSource: true });
81
+ }
82
+ }
83
+ //# sourceMappingURL=FogLayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FogLayer.js","sourceRoot":"","sources":["../../../src/two-d/render/FogLayer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import { Container } from 'pixi.js';
2
+ import type { Texture2D } from './Types2D.ts';
3
+ export interface LiquidLayerOptions {
4
+ /** the repeating liquid surface texture */
5
+ texture: Texture2D;
6
+ /** map size in tiles */
7
+ width: number;
8
+ height: number;
9
+ /** tile size in world units; default 16 */
10
+ tileSize?: number;
11
+ /** which cells hold liquid */
12
+ isLiquid: (x: number, y: number) => boolean;
13
+ /** texture pixels scrolled per second, downwards when positive; default 5 */
14
+ speed?: number;
15
+ /** the sprite an expanding ripple draws; without one `ripple` does nothing */
16
+ rippleTexture?: Texture2D;
17
+ /** seconds a ripple takes to grow and fade; default 0.5 */
18
+ rippleDuration?: number;
19
+ }
20
+ /**
21
+ * An animated liquid surface under a tile map: one scrolling tiling quad per liquid cell,
22
+ * so each cell can carry its own visibility tint (`setCellColor`, the same idea as
23
+ * `TileMap.setCellColor`) without showing liquid in cells the player has not seen. `ripple`
24
+ * spawns a ring that grows and fades on a cell. Drive it with `update(dt)` each frame.
25
+ *
26
+ * Every child opts out of pointer events: a decorative layer must never swallow the taps
27
+ * meant for the map beneath it.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * import { Texture } from 'pixi.js';
32
+ * import { LiquidLayer } from '@datamoc/mw_games/two-d/render';
33
+ *
34
+ * const water = new LiquidLayer({
35
+ * texture: Texture.EMPTY,
36
+ * width: 8,
37
+ * height: 8,
38
+ * isLiquid: (x, y) => y > 5,
39
+ * });
40
+ * water.setCellColor(3, 6, 0xffffff); // lit; a tint of 0 hides the cell
41
+ * water.update(1 / 60);
42
+ * ```
43
+ */
44
+ export declare class LiquidLayer extends Container {
45
+ private readonly cells;
46
+ private readonly ripples;
47
+ private readonly columns;
48
+ private readonly tileSize;
49
+ private readonly speed;
50
+ private readonly rippleTexture?;
51
+ private readonly rippleDuration;
52
+ private offset;
53
+ constructor(options: LiquidLayerOptions);
54
+ /** tints one cell; a tint of 0 hides it, and cells start hidden until lit */
55
+ setCellColor(x: number, y: number, tint: number): void;
56
+ /** starts a ripple on a visible liquid cell */
57
+ ripple(x: number, y: number): void;
58
+ /** how many ripples are still growing */
59
+ get rippleCount(): number;
60
+ update(dt: number): void;
61
+ }
62
+ //# sourceMappingURL=LiquidLayer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LiquidLayer.d.ts","sourceRoot":"","sources":["../../../src/two-d/render/LiquidLayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAwB,MAAM,SAAS,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,WAAW,kBAAkB;IAClC,2CAA2C;IAC3C,OAAO,EAAE,SAAS,CAAC;IACnB,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,WAAY,SAAQ,SAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;IACjE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAY;IAC3C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,MAAM,CAAK;IAEnB,YAAY,OAAO,EAAE,kBAAkB,EAyBtC;IAED,6EAA6E;IAC7E,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAKrD;IAED,+CAA+C;IAC/C,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CASjC;IAED,yCAAyC;IACzC,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAiBvB;CACD"}
@@ -0,0 +1,102 @@
1
+ import { Container, Sprite, TilingSprite } from 'pixi.js';
2
+ /**
3
+ * An animated liquid surface under a tile map: one scrolling tiling quad per liquid cell,
4
+ * so each cell can carry its own visibility tint (`setCellColor`, the same idea as
5
+ * `TileMap.setCellColor`) without showing liquid in cells the player has not seen. `ripple`
6
+ * spawns a ring that grows and fades on a cell. Drive it with `update(dt)` each frame.
7
+ *
8
+ * Every child opts out of pointer events: a decorative layer must never swallow the taps
9
+ * meant for the map beneath it.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { Texture } from 'pixi.js';
14
+ * import { LiquidLayer } from '@datamoc/mw_games/two-d/render';
15
+ *
16
+ * const water = new LiquidLayer({
17
+ * texture: Texture.EMPTY,
18
+ * width: 8,
19
+ * height: 8,
20
+ * isLiquid: (x, y) => y > 5,
21
+ * });
22
+ * water.setCellColor(3, 6, 0xffffff); // lit; a tint of 0 hides the cell
23
+ * water.update(1 / 60);
24
+ * ```
25
+ */
26
+ export class LiquidLayer extends Container {
27
+ constructor(options) {
28
+ super();
29
+ this.cells = new Map();
30
+ this.ripples = [];
31
+ this.offset = 0;
32
+ this.eventMode = 'none';
33
+ this.columns = options.width;
34
+ this.tileSize = options.tileSize ?? 16;
35
+ this.speed = options.speed ?? 5;
36
+ this.rippleTexture = options.rippleTexture;
37
+ this.rippleDuration = options.rippleDuration ?? 0.5;
38
+ for (let y = 0; y < options.height; y++) {
39
+ for (let x = 0; x < options.width; x++) {
40
+ if (!options.isLiquid(x, y))
41
+ continue;
42
+ const tile = new TilingSprite({
43
+ texture: options.texture,
44
+ width: this.tileSize,
45
+ height: this.tileSize,
46
+ });
47
+ tile.eventMode = 'none';
48
+ tile.position.set(x * this.tileSize, y * this.tileSize);
49
+ //the texture is anchored to the map, not the cell, so neighbours line up
50
+ tile.tilePosition.set(-tile.x, -tile.y);
51
+ tile.visible = false;
52
+ this.cells.set(x + y * this.columns, tile);
53
+ this.addChild(tile);
54
+ }
55
+ }
56
+ }
57
+ /** tints one cell; a tint of 0 hides it, and cells start hidden until lit */
58
+ setCellColor(x, y, tint) {
59
+ const tile = this.cells.get(x + y * this.columns);
60
+ if (!tile)
61
+ return;
62
+ tile.tint = tint;
63
+ tile.visible = tint !== 0;
64
+ }
65
+ /** starts a ripple on a visible liquid cell */
66
+ ripple(x, y) {
67
+ if (!this.rippleTexture || !this.cells.get(x + y * this.columns)?.visible)
68
+ return;
69
+ const sprite = new Sprite(this.rippleTexture);
70
+ sprite.eventMode = 'none';
71
+ sprite.anchor.set(0.5);
72
+ sprite.position.set((x + 0.5) * this.tileSize, (y + 0.5) * this.tileSize);
73
+ sprite.scale.set(0);
74
+ this.addChild(sprite);
75
+ this.ripples.push({ sprite, age: 0 });
76
+ }
77
+ /** how many ripples are still growing */
78
+ get rippleCount() {
79
+ return this.ripples.length;
80
+ }
81
+ update(dt) {
82
+ this.offset += this.speed * dt;
83
+ for (const tile of this.cells.values()) {
84
+ if (tile.visible)
85
+ tile.tilePosition.y = -tile.y + this.offset;
86
+ }
87
+ for (let i = this.ripples.length - 1; i >= 0; i--) {
88
+ const ripple = this.ripples[i];
89
+ ripple.age += dt;
90
+ if (ripple.age >= this.rippleDuration) {
91
+ ripple.sprite.destroy();
92
+ this.ripples.splice(i, 1);
93
+ }
94
+ else {
95
+ const progress = ripple.age / this.rippleDuration;
96
+ ripple.sprite.scale.set(progress);
97
+ ripple.sprite.alpha = 1 - progress;
98
+ }
99
+ }
100
+ }
101
+ }
102
+ //# sourceMappingURL=LiquidLayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LiquidLayer.js","sourceRoot":"","sources":["../../../src/two-d/render/LiquidLayer.ts"],"names":[],"mappings":"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"}
@@ -219,6 +219,16 @@ export type AutotileLayout = {
219
219
  format: 'rpgm-mv';
220
220
  slot: RpgmAutotileSlot;
221
221
  table: RpgmAutotileShapeTable;
222
+ /**
223
+ * Picks the shape table per autotile kind (the A4 sheet mixes floor and wall
224
+ * rows); when set it overrides `table` for every cell.
225
+ */
226
+ tableFor?: (kind: number) => RpgmAutotileShapeTable;
227
+ /**
228
+ * Slot 1 only: a cell holds the A2 table tile standing above it, and draws just that
229
+ * tile's front-edge strip (two 24 by 12 pieces along the cell's top), not a tile.
230
+ */
231
+ tableEdge?: boolean;
222
232
  /** kind runs that advance together; a cell whose kind is in no run ignores the frame */
223
233
  cycles: ReadonlyArray<ReadonlyArray<number>>;
224
234
  } | {
@@ -279,4 +289,36 @@ export declare function assertAutotileLayout(layout: AutotileLayout): void;
279
289
  * ```
280
290
  */
281
291
  export declare function autotileCellParts(layout: AutotileLayout, tile: number, frame: number): AutotileCellPart[] | null;
292
+ /** what `rpgmTableEdgeCells` needs from an MV map and its tileset */
293
+ export interface RpgmTableEdgeMap {
294
+ width: number;
295
+ height: number;
296
+ /** map layer 0 (row-major, one tile id per cell), whose A3/A4 tiles suppress an edge */
297
+ ground: ArrayLike<number>;
298
+ /** map layer 1, where tables are placed */
299
+ objects: ArrayLike<number>;
300
+ /** the tileset's passage flags, indexed by tile id (an array or a sparse record) */
301
+ flags: {
302
+ readonly [tile: number]: number | undefined;
303
+ };
304
+ }
305
+ /**
306
+ * The cells that get a table's front-edge strip, in the engine's own rule
307
+ * (`Tilemap._paintTiles`): a cell whose layer-1 neighbour above is an A2 table
308
+ * tile, while its own layer-1 tile is not a table, and whose layer-0 tile is not an
309
+ * A3/A4 wall. Each such cell holds the table tile above it (a raw MV id), every
310
+ * other cell 0, ready for an `addAutotileLayer` set with `tableEdge: true`.
311
+ *
312
+ * @example
313
+ * ```ts
314
+ * import { rpgmTableEdgeCells } from '@datamoc/mw_games/two-d/render';
315
+ *
316
+ * const table = 2816 + 48 * 0 + 47; // an A2 kind with the table flag
317
+ * const flags = { [table]: 0x80 };
318
+ * const cells = rpgmTableEdgeCells({ width: 1, height: 2, ground: [0, 0], objects: [table, 0], flags });
319
+ * console.log(cells[1]); // the table tile above cell 1
320
+ * console.log(cells[0]); // 0 - nothing above the top row
321
+ * ```
322
+ */
323
+ export declare function rpgmTableEdgeCells(map: RpgmTableEdgeMap): Int32Array;
282
324
  //# sourceMappingURL=RpgmAutotile.d.ts.map