@datamoc/mw_games 0.19.0 → 0.22.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 (141) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/dist/ai/index.d.ts +2 -2
  3. package/dist/ai/index.d.ts.map +1 -1
  4. package/dist/ai/index.js +1 -1
  5. package/dist/ai/index.js.map +1 -1
  6. package/dist/ai/search.d.ts +49 -0
  7. package/dist/ai/search.d.ts.map +1 -1
  8. package/dist/ai/search.js +48 -0
  9. package/dist/ai/search.js.map +1 -1
  10. package/dist/audio/Channels.d.ts +19 -0
  11. package/dist/audio/Channels.d.ts.map +1 -1
  12. package/dist/audio/Channels.js +33 -4
  13. package/dist/audio/Channels.js.map +1 -1
  14. package/dist/audio/LoopTags.d.ts +37 -0
  15. package/dist/audio/LoopTags.d.ts.map +1 -0
  16. package/dist/audio/LoopTags.js +116 -0
  17. package/dist/audio/LoopTags.js.map +1 -0
  18. package/dist/audio/Midi.d.ts +5 -0
  19. package/dist/audio/Midi.d.ts.map +1 -1
  20. package/dist/audio/Midi.js +9 -1
  21. package/dist/audio/Midi.js.map +1 -1
  22. package/dist/audio/MidiRender.d.ts +42 -4
  23. package/dist/audio/MidiRender.d.ts.map +1 -1
  24. package/dist/audio/MidiRender.js +286 -199
  25. package/dist/audio/MidiRender.js.map +1 -1
  26. package/dist/audio/index.d.ts +5 -3
  27. package/dist/audio/index.d.ts.map +1 -1
  28. package/dist/audio/index.js +2 -1
  29. package/dist/audio/index.js.map +1 -1
  30. package/dist/board/Engine.d.ts +33 -0
  31. package/dist/board/Engine.d.ts.map +1 -1
  32. package/dist/board/Engine.js +448 -1
  33. package/dist/board/Engine.js.map +1 -1
  34. package/dist/board/bitboard.d.ts +132 -0
  35. package/dist/board/bitboard.d.ts.map +1 -0
  36. package/dist/board/bitboard.js +495 -0
  37. package/dist/board/bitboard.js.map +1 -0
  38. package/dist/board/chess.d.ts +16 -0
  39. package/dist/board/chess.d.ts.map +1 -1
  40. package/dist/board/chess.js +43 -0
  41. package/dist/board/chess.js.map +1 -1
  42. package/dist/board/index.d.ts +11 -3
  43. package/dist/board/index.d.ts.map +1 -1
  44. package/dist/board/index.js +6 -2
  45. package/dist/board/index.js.map +1 -1
  46. package/dist/board/openings.d.ts +58 -0
  47. package/dist/board/openings.d.ts.map +1 -0
  48. package/dist/board/openings.js +45 -0
  49. package/dist/board/openings.js.map +1 -0
  50. package/dist/board/tablebase.d.ts +118 -0
  51. package/dist/board/tablebase.d.ts.map +1 -0
  52. package/dist/board/tablebase.js +414 -0
  53. package/dist/board/tablebase.js.map +1 -0
  54. package/dist/board/tourney.d.ts +90 -0
  55. package/dist/board/tourney.d.ts.map +1 -0
  56. package/dist/board/tourney.js +1013 -0
  57. package/dist/board/tourney.js.map +1 -0
  58. package/dist/core/JavaRandom.d.ts +55 -0
  59. package/dist/core/JavaRandom.d.ts.map +1 -0
  60. package/dist/core/JavaRandom.js +81 -0
  61. package/dist/core/JavaRandom.js.map +1 -0
  62. package/dist/core/index.d.ts +2 -0
  63. package/dist/core/index.d.ts.map +1 -1
  64. package/dist/core/index.js +1 -0
  65. package/dist/core/index.js.map +1 -1
  66. package/dist/mw_games.global.js +123 -116
  67. package/dist/rpg/EventRunner.d.ts +7 -0
  68. package/dist/rpg/EventRunner.d.ts.map +1 -1
  69. package/dist/rpg/EventRunner.js +6 -0
  70. package/dist/rpg/EventRunner.js.map +1 -1
  71. package/dist/threads/index.d.ts +3 -0
  72. package/dist/threads/index.d.ts.map +1 -0
  73. package/dist/threads/index.js +2 -0
  74. package/dist/threads/index.js.map +1 -0
  75. package/dist/threads/spawn.d.ts +41 -0
  76. package/dist/threads/spawn.d.ts.map +1 -0
  77. package/dist/threads/spawn.js +143 -0
  78. package/dist/threads/spawn.js.map +1 -0
  79. package/dist/threads/worker.d.ts +51 -0
  80. package/dist/threads/worker.d.ts.map +1 -0
  81. package/dist/threads/worker.js +84 -0
  82. package/dist/threads/worker.js.map +1 -0
  83. package/dist/two-d/render/FogLayer.d.ts +68 -0
  84. package/dist/two-d/render/FogLayer.d.ts.map +1 -0
  85. package/dist/two-d/render/FogLayer.js +83 -0
  86. package/dist/two-d/render/FogLayer.js.map +1 -0
  87. package/dist/two-d/render/LiquidLayer.d.ts +62 -0
  88. package/dist/two-d/render/LiquidLayer.d.ts.map +1 -0
  89. package/dist/two-d/render/LiquidLayer.js +102 -0
  90. package/dist/two-d/render/LiquidLayer.js.map +1 -0
  91. package/dist/two-d/render/RpgmAutotile.d.ts +5 -0
  92. package/dist/two-d/render/RpgmAutotile.d.ts.map +1 -1
  93. package/dist/two-d/render/RpgmAutotile.js +4 -3
  94. package/dist/two-d/render/RpgmAutotile.js.map +1 -1
  95. package/dist/two-d/render/TileMap.d.ts +14 -2
  96. package/dist/two-d/render/TileMap.d.ts.map +1 -1
  97. package/dist/two-d/render/TileMap.js +32 -2
  98. package/dist/two-d/render/TileMap.js.map +1 -1
  99. package/dist/two-d/render/index.d.ts +4 -0
  100. package/dist/two-d/render/index.d.ts.map +1 -1
  101. package/dist/two-d/render/index.js +2 -0
  102. package/dist/two-d/render/index.js.map +1 -1
  103. package/dist/two-d/ui/Label.d.ts.map +1 -1
  104. package/dist/two-d/ui/Label.js +11 -2
  105. package/dist/two-d/ui/Label.js.map +1 -1
  106. package/dist/two-d/ui/ListView.d.ts +24 -0
  107. package/dist/two-d/ui/ListView.d.ts.map +1 -1
  108. package/dist/two-d/ui/ListView.js +97 -4
  109. package/dist/two-d/ui/ListView.js.map +1 -1
  110. package/dist/two-d/ui/MessageLog.d.ts +62 -0
  111. package/dist/two-d/ui/MessageLog.d.ts.map +1 -0
  112. package/dist/two-d/ui/MessageLog.js +114 -0
  113. package/dist/two-d/ui/MessageLog.js.map +1 -0
  114. package/dist/two-d/ui/RadioGroup.d.ts +68 -0
  115. package/dist/two-d/ui/RadioGroup.d.ts.map +1 -0
  116. package/dist/two-d/ui/RadioGroup.js +177 -0
  117. package/dist/two-d/ui/RadioGroup.js.map +1 -0
  118. package/dist/two-d/ui/TextModel.d.ts +26 -1
  119. package/dist/two-d/ui/TextModel.d.ts.map +1 -1
  120. package/dist/two-d/ui/TextModel.js +56 -7
  121. package/dist/two-d/ui/TextModel.js.map +1 -1
  122. package/dist/two-d/ui/TextSharpness.d.ts +33 -0
  123. package/dist/two-d/ui/TextSharpness.d.ts.map +1 -0
  124. package/dist/two-d/ui/TextSharpness.js +56 -0
  125. package/dist/two-d/ui/TextSharpness.js.map +1 -0
  126. package/dist/two-d/ui/index.d.ts +5 -0
  127. package/dist/two-d/ui/index.d.ts.map +1 -1
  128. package/dist/two-d/ui/index.js +3 -0
  129. package/dist/two-d/ui/index.js.map +1 -1
  130. package/dist/version.d.ts +1 -1
  131. package/dist/version.js +1 -1
  132. package/package.json +19 -2
  133. package/sbom.cdx.json +54 -28
  134. package/tools/build-tablebases.d.mts +22 -0
  135. package/tools/build-tablebases.mjs +549 -0
  136. package/tools/compile-openings.d.mts +20 -0
  137. package/tools/compile-openings.mjs +130 -0
  138. package/tools/compress-dist.d.mts +8 -0
  139. package/tools/compress-dist.mjs +76 -30
  140. package/tools/play-uci.d.mts +26 -0
  141. 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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"}
@@ -0,0 +1,3 @@
1
+ export { spawn } from './spawn.ts';
2
+ export type { SpawnOptions } from './spawn.ts';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/threads/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { spawn } from './spawn.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/threads/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,41 @@
1
+ export interface SpawnOptions {
2
+ /** buffers posted to the task instead of copied: each is detached from this thread when spawn runs */
3
+ transfer?: Transferable[];
4
+ /** abandons the task after this many milliseconds; there is no default, because a render can legitimately take minutes */
5
+ timeout?: number;
6
+ /** aborting rejects the promise with the signal's reason and terminates the task's worker */
7
+ signal?: AbortSignal;
8
+ }
9
+ /**
10
+ * Runs `fn` on a worker thread and resolves with its value, keeping the caller's thread
11
+ * free: the one synchronous block a game can never get back is the frame it spends waiting.
12
+ *
13
+ * The task is serialized with `Function.prototype.toString` and rehydrated in the worker,
14
+ * so it must be **self-contained** - no closures over module scope, no imports, no bound or
15
+ * native functions. Everything it needs arrives as `args`, structured-cloned in; buffers
16
+ * listed in `options.transfer` are moved instead, detached from the caller's thread. The
17
+ * result comes back structured-cloned, with every ArrayBuffer inside it transferred rather
18
+ * than copied (the worker is finished with them). A task that throws, closes over
19
+ * something the worker cannot see, or exits its worker without answering rejects the
20
+ * promise - it never hangs - and `timeout` or `signal` abandon a task that never returns.
21
+ *
22
+ * One worker per task: construction costs a few milliseconds, which is nothing next to the
23
+ * work worth moving off the main thread (T161 measured break-even at roughly 10 ms per
24
+ * task in a batch, and far less against a dropped frame).
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { spawn } from '@datamoc/mw_games/threads';
29
+ *
30
+ * const sum = await spawn((a: number, b: number) => a + b, [40, 2]);
31
+ * console.log(sum); // 42
32
+ *
33
+ * //a task that never returns is abandoned rather than hanging the caller
34
+ * const controller = new AbortController();
35
+ * const pending = spawn(() => new Promise(() => {}), [], { signal: controller.signal });
36
+ * controller.abort();
37
+ * pending.catch((error: Error) => console.log(error.name)); // 'AbortError'
38
+ * ```
39
+ */
40
+ export declare function spawn<Args extends readonly unknown[], Result>(fn: (...args: Args) => Result, args?: Args, options?: SpawnOptions): Promise<Awaited<Result>>;
41
+ //# sourceMappingURL=spawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../../src/threads/spawn.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC5B,sGAAsG;IACtG,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B,0HAA0H;IAC1H,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAsED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,KAAK,CAAC,IAAI,SAAS,SAAS,OAAO,EAAE,EAAE,MAAM,EAC5D,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,MAAM,EAC7B,IAAI,CAAC,EAAE,IAAI,EACX,OAAO,GAAE,YAAiB,GACxB,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CA0D1B"}
@@ -0,0 +1,143 @@
1
+ import { nodeThreads, workerMain } from './worker.js';
2
+ const browserWorker = (events) => {
3
+ if (typeof Worker === 'undefined' ||
4
+ typeof Blob === 'undefined' ||
5
+ typeof URL === 'undefined' ||
6
+ typeof URL.createObjectURL !== 'function') {
7
+ return null;
8
+ }
9
+ //a blob worker, because the shipped file:// page allows worker-src blob: and because a
10
+ //file:// module worker is blocked by CORS whatever the policy says
11
+ const url = URL.createObjectURL(new Blob([`(${workerMain.toString()})()`], { type: 'text/javascript' }));
12
+ let worker;
13
+ try {
14
+ worker = new Worker(url);
15
+ }
16
+ catch (error) {
17
+ URL.revokeObjectURL(url);
18
+ throw error;
19
+ }
20
+ worker.onmessage = (event) => events.reply(event.data);
21
+ worker.onerror = (event) => events.fail(new Error(event.message || 'the worker failed to run'));
22
+ worker.onmessageerror = () => events.fail(new Error('the worker sent a reply that could not be deserialized'));
23
+ return {
24
+ post: (message, transfer) => worker.postMessage(message, transfer),
25
+ terminate: () => {
26
+ worker.terminate();
27
+ URL.revokeObjectURL(url);
28
+ },
29
+ };
30
+ };
31
+ const nodeWorker = (events) => {
32
+ const threads = nodeThreads();
33
+ if (!threads)
34
+ return null;
35
+ //the same source string as the browser path, executed as CJS by Node's eval mode
36
+ const worker = new threads.Worker(`(${workerMain.toString()})()`, { eval: true });
37
+ worker.on('message', (reply) => events.reply(reply));
38
+ worker.on('error', (error) => events.fail(error instanceof Error ? error : new Error(String(error))));
39
+ worker.on('messageerror', () => events.fail(new Error('the worker sent a reply that could not be deserialized')));
40
+ //a task that kills its worker without answering must reject rather than hang forever -
41
+ //the failure the multithreading package's pool never reports (T161)
42
+ worker.on('exit', (code) => events.fail(new Error(`the worker exited with code ${code} before answering`)));
43
+ return {
44
+ post: (message, transfer) => worker.postMessage(message, transfer),
45
+ terminate: () => void worker.terminate(),
46
+ };
47
+ };
48
+ /** the error a failed reply carries, with the worker-side stack where there was one */
49
+ function taskError(reply) {
50
+ const error = new Error(reply.message);
51
+ if (reply.stack)
52
+ error.stack = reply.stack;
53
+ return error;
54
+ }
55
+ /**
56
+ * Runs `fn` on a worker thread and resolves with its value, keeping the caller's thread
57
+ * free: the one synchronous block a game can never get back is the frame it spends waiting.
58
+ *
59
+ * The task is serialized with `Function.prototype.toString` and rehydrated in the worker,
60
+ * so it must be **self-contained** - no closures over module scope, no imports, no bound or
61
+ * native functions. Everything it needs arrives as `args`, structured-cloned in; buffers
62
+ * listed in `options.transfer` are moved instead, detached from the caller's thread. The
63
+ * result comes back structured-cloned, with every ArrayBuffer inside it transferred rather
64
+ * than copied (the worker is finished with them). A task that throws, closes over
65
+ * something the worker cannot see, or exits its worker without answering rejects the
66
+ * promise - it never hangs - and `timeout` or `signal` abandon a task that never returns.
67
+ *
68
+ * One worker per task: construction costs a few milliseconds, which is nothing next to the
69
+ * work worth moving off the main thread (T161 measured break-even at roughly 10 ms per
70
+ * task in a batch, and far less against a dropped frame).
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * import { spawn } from '@datamoc/mw_games/threads';
75
+ *
76
+ * const sum = await spawn((a: number, b: number) => a + b, [40, 2]);
77
+ * console.log(sum); // 42
78
+ *
79
+ * //a task that never returns is abandoned rather than hanging the caller
80
+ * const controller = new AbortController();
81
+ * const pending = spawn(() => new Promise(() => {}), [], { signal: controller.signal });
82
+ * controller.abort();
83
+ * pending.catch((error: Error) => console.log(error.name)); // 'AbortError'
84
+ * ```
85
+ */
86
+ export function spawn(fn, args, options = {}) {
87
+ return new Promise((resolve, reject) => {
88
+ if (options.signal?.aborted) {
89
+ reject(options.signal.reason);
90
+ return;
91
+ }
92
+ let settled = false;
93
+ let timer;
94
+ let worker;
95
+ const settle = (finish) => {
96
+ if (settled)
97
+ return;
98
+ settled = true;
99
+ if (timer !== undefined)
100
+ clearTimeout(timer);
101
+ options.signal?.removeEventListener('abort', onAbort);
102
+ //one worker per task: whatever settled it, the worker is done
103
+ worker?.terminate();
104
+ finish();
105
+ };
106
+ function onAbort() {
107
+ settle(() => reject(options.signal.reason));
108
+ }
109
+ const events = {
110
+ reply: (reply) => settle(() => {
111
+ if (reply.ok)
112
+ resolve(reply.value);
113
+ else
114
+ reject(taskError(reply));
115
+ }),
116
+ fail: (error) => settle(() => reject(error)),
117
+ };
118
+ try {
119
+ //each host returns null when its environment is absent, so they are tried in order
120
+ worker = browserWorker(events) ?? nodeWorker(events);
121
+ }
122
+ catch (error) {
123
+ reject(error);
124
+ return;
125
+ }
126
+ if (!worker) {
127
+ reject(new Error('spawn() needs Web Workers or node:worker_threads, and this environment offers neither'));
128
+ return;
129
+ }
130
+ if (options.timeout !== undefined && options.timeout > 0) {
131
+ timer = setTimeout(() => settle(() => reject(new Error(`the task did not answer within ${options.timeout} ms`))), options.timeout);
132
+ }
133
+ options.signal?.addEventListener('abort', onAbort, { once: true });
134
+ try {
135
+ worker.post({ code: fn.toString(), args: args ?? [] }, options.transfer ?? []);
136
+ }
137
+ catch (error) {
138
+ //unclonable arguments, or a transfer list that does not match the message
139
+ settle(() => reject(error));
140
+ }
141
+ });
142
+ }
143
+ //# sourceMappingURL=spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../src/threads/spawn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /** what the main thread posts to a fresh worker: the task's source and its arguments */
2
+ export interface WorkerRequest {
3
+ /** the stringified task function, rehydrated in the worker with `new Function` */
4
+ code: string;
5
+ args: readonly unknown[];
6
+ }
7
+ /** what the worker posts back: the value, or the failure that stopped it */
8
+ export type WorkerReply = {
9
+ ok: true;
10
+ value: unknown;
11
+ } | {
12
+ ok: false;
13
+ message: string;
14
+ stack?: string;
15
+ };
16
+ /**
17
+ * The slice of `node:worker_threads` this module uses, described structurally: `src/`
18
+ * compiles in a browser-only config (the `@example` fence compiler runs with `types: []`),
19
+ * so nothing here may name `process` or a `node:` type directly.
20
+ */
21
+ export interface NodeThreads {
22
+ parentPort: {
23
+ on(event: 'message', listener: (request: WorkerRequest) => void): void;
24
+ postMessage(message: WorkerReply, transfer?: ArrayBuffer[]): void;
25
+ } | null;
26
+ Worker: new (code: string, options: {
27
+ eval: true;
28
+ }) => {
29
+ on(event: 'message', listener: (reply: WorkerReply) => void): void;
30
+ on(event: 'error', listener: (error: unknown) => void): void;
31
+ on(event: 'messageerror', listener: () => void): void;
32
+ on(event: 'exit', listener: (code: number) => void): void;
33
+ postMessage(message: WorkerRequest, transfer?: readonly unknown[]): void;
34
+ terminate(): Promise<number> | void;
35
+ };
36
+ }
37
+ /** `node:worker_threads` reached through `globalThis`, so nothing here needs @types/node */
38
+ export declare function nodeThreads(): NodeThreads | undefined;
39
+ /**
40
+ * The worker half of `threads.spawn`: receives one task, runs it, replies, and goes no
41
+ * further (spawn terminates it as soon as the reply settles).
42
+ *
43
+ * **This function must stay self-contained.** `spawn` ships it to a worker with
44
+ * `workerMain.toString()`, so it may not reference imports, module-scope helpers or any
45
+ * outer binding - everything it needs is either a language global or nested inside it.
46
+ * The same body runs in both transports: a classic blob worker in the browser (where the
47
+ * shipped `file://` CSP allows only `worker-src blob:` and `new Function`, per the T161
48
+ * probe) and an eval'd `node:worker_threads` worker in Node, which has no `self`.
49
+ */
50
+ export declare function workerMain(): void;
51
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/threads/worker.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,MAAM,WAAW,aAAa;IAC7B,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC;CACzB;AAED,4EAA4E;AAC5E,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExG;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC3B,UAAU,EAAE;QACX,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI,CAAC;QACvE,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;KAClE,GAAG,IAAI,CAAC;IACT,MAAM,EAAE,KACP,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,KACnB;QACJ,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI,CAAC;QACnE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;QAC7D,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;QACtD,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;QAC1D,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,CAAC;QACzE,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;KACpC,CAAC;CACF;AAED,4FAA4F;AAC5F,wBAAgB,WAAW,IAAI,WAAW,GAAG,SAAS,CAMrD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAoEjC"}
@@ -0,0 +1,84 @@
1
+ /** `node:worker_threads` reached through `globalThis`, so nothing here needs @types/node */
2
+ export function nodeThreads() {
3
+ return globalThis.process?.getBuiltinModule?.('node:worker_threads');
4
+ }
5
+ /**
6
+ * The worker half of `threads.spawn`: receives one task, runs it, replies, and goes no
7
+ * further (spawn terminates it as soon as the reply settles).
8
+ *
9
+ * **This function must stay self-contained.** `spawn` ships it to a worker with
10
+ * `workerMain.toString()`, so it may not reference imports, module-scope helpers or any
11
+ * outer binding - everything it needs is either a language global or nested inside it.
12
+ * The same body runs in both transports: a classic blob worker in the browser (where the
13
+ * shipped `file://` CSP allows only `worker-src blob:` and `new Function`, per the T161
14
+ * probe) and an eval'd `node:worker_threads` worker in Node, which has no `self`.
15
+ */
16
+ export function workerMain() {
17
+ //the same chain as nodeThreads(), inlined because workerMain is stringified into the
18
+ //worker and may not call anything module-scoped; the cast is a type, erased before then
19
+ const nodePort = globalThis.process?.getBuiltinModule?.('node:worker_threads')?.parentPort ?? null;
20
+ const scope = globalThis;
21
+ /** every ArrayBuffer reachable through plain objects and arrays, listed once each */
22
+ const transferablesOf = (value) => {
23
+ const out = [];
24
+ const seen = new Set();
25
+ const visit = (item) => {
26
+ if (item === null || typeof item !== 'object')
27
+ return;
28
+ if (seen.has(item))
29
+ return;
30
+ seen.add(item);
31
+ if (ArrayBuffer.isView(item)) {
32
+ //a view transfers its whole buffer; a SharedArrayBuffer cannot transfer, so it
33
+ //stays a copy (and does not exist in the shipped file:// target at all)
34
+ const buffer = item.buffer;
35
+ if (buffer instanceof ArrayBuffer && !out.includes(buffer))
36
+ out.push(buffer);
37
+ return;
38
+ }
39
+ if (item instanceof ArrayBuffer) {
40
+ if (!out.includes(item))
41
+ out.push(item);
42
+ return;
43
+ }
44
+ if (Array.isArray(item)) {
45
+ for (const entry of item)
46
+ visit(entry);
47
+ return;
48
+ }
49
+ const prototype = Object.getPrototypeOf(item);
50
+ if (prototype === Object.prototype || prototype === null) {
51
+ for (const entry of Object.values(item))
52
+ visit(entry);
53
+ }
54
+ };
55
+ visit(value);
56
+ return out;
57
+ };
58
+ const reply = (message, transfer = []) => {
59
+ if (nodePort)
60
+ nodePort.postMessage(message, transfer);
61
+ else
62
+ scope.postMessage(message, transfer);
63
+ };
64
+ const onRequest = async (request) => {
65
+ try {
66
+ const task = new Function(`return (${request.code});`)();
67
+ const value = await task(...request.args);
68
+ reply({ ok: true, value }, transferablesOf(value));
69
+ }
70
+ catch (error) {
71
+ const failure = error;
72
+ reply({
73
+ ok: false,
74
+ message: String(failure?.message ?? error),
75
+ stack: typeof failure?.stack === 'string' ? failure.stack : undefined,
76
+ });
77
+ }
78
+ };
79
+ if (nodePort)
80
+ nodePort.on('message', (request) => void onRequest(request));
81
+ else
82
+ scope.onmessage = (event) => void onRequest(event.data);
83
+ }
84
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/threads/worker.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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"}