@pkmn/engine 0.1.0-dev.12e7292c → 0.1.0-dev.130de754

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 (84) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +41 -25
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +47 -0
  5. package/build/pkg/addon/browser.js.map +1 -0
  6. package/build/pkg/addon/node.d.ts +3 -0
  7. package/build/pkg/addon/node.js +110 -0
  8. package/build/pkg/addon/node.js.map +1 -0
  9. package/build/pkg/addon/wasm.d.ts +2 -0
  10. package/build/pkg/addon/wasm.js +53 -0
  11. package/build/pkg/addon/wasm.js.map +1 -0
  12. package/build/pkg/addon.d.ts +26 -4
  13. package/build/pkg/addon.js +39 -71
  14. package/build/pkg/addon.js.map +1 -1
  15. package/build/pkg/data/layout.json +15 -2
  16. package/build/pkg/data/protocol.json +23 -9
  17. package/build/pkg/data.d.ts +27 -5
  18. package/build/pkg/data.js.map +1 -1
  19. package/build/pkg/gen1.d.ts +15 -18
  20. package/build/pkg/gen1.js +28 -19
  21. package/build/pkg/gen1.js.map +1 -1
  22. package/build/pkg/index.d.ts +42 -91
  23. package/build/pkg/index.js +23 -70
  24. package/build/pkg/index.js.map +1 -1
  25. package/build/pkg/protocol.d.ts +29 -1
  26. package/build/pkg/protocol.js +109 -107
  27. package/build/pkg/protocol.js.map +1 -1
  28. package/build/tools/debug.js +84 -75
  29. package/build/tools/debug.js.map +1 -1
  30. package/build/tools/display/debug.jsx +66 -0
  31. package/build/tools/display/debug.jsx.map +1 -0
  32. package/build/tools/display/index.js +152 -0
  33. package/build/tools/display/index.js.map +1 -0
  34. package/build/tools/display/ui.jsx +360 -0
  35. package/build/tools/display/ui.jsx.map +1 -0
  36. package/build/tools/display/util.js +157 -0
  37. package/build/tools/display/util.js.map +1 -0
  38. package/build.zig +310 -203
  39. package/package.json +60 -134
  40. package/src/bin/install-pkmn-engine +70 -53
  41. package/src/bin/pkmn-debug +1 -1
  42. package/src/lib/bindings/c.zig +201 -0
  43. package/src/lib/{binding → bindings}/node.zig +15 -32
  44. package/src/lib/bindings/wasm.zig +51 -0
  45. package/src/lib/common/array.zig +70 -0
  46. package/src/lib/common/data.zig +4 -4
  47. package/src/lib/common/debug.zig +46 -30
  48. package/src/lib/common/js.zig +5 -9
  49. package/src/lib/common/optional.zig +21 -22
  50. package/src/lib/common/options.zig +6 -0
  51. package/src/lib/common/protocol.zig +253 -223
  52. package/src/lib/common/rational.zig +340 -254
  53. package/src/lib/common/rng.zig +11 -13
  54. package/src/lib/common/util.zig +53 -1
  55. package/src/lib/gen1/calc.zig +724 -175
  56. package/src/lib/gen1/chance.zig +494 -308
  57. package/src/lib/gen1/data/moves.zig +2 -4
  58. package/src/lib/gen1/data/species.zig +2 -4
  59. package/src/lib/gen1/data/types.zig +3 -4
  60. package/src/lib/gen1/data.zig +49 -49
  61. package/src/lib/gen1/helpers.zig +115 -562
  62. package/src/lib/gen1/mechanics.zig +411 -293
  63. package/src/lib/gen2/calc.zig +35 -28
  64. package/src/lib/gen2/chance.zig +122 -518
  65. package/src/lib/gen2/data/items.zig +1 -3
  66. package/src/lib/gen2/data/moves.zig +2 -4
  67. package/src/lib/gen2/data/species.zig +1 -3
  68. package/src/lib/gen2/data/types.zig +7 -5
  69. package/src/lib/gen2/data.zig +39 -38
  70. package/src/lib/gen2/generated.zig +16 -26
  71. package/src/lib/gen2/helpers.zig +68 -39
  72. package/src/lib/gen2/mechanics.zig +217 -174
  73. package/src/lib/napi.h +2 -0
  74. package/src/lib/node.zig +14 -0
  75. package/src/lib/pkmn.zig +123 -29
  76. package/src/lib/wasm.zig +12 -0
  77. package/src/tools/display/dom.ts +108 -0
  78. package/src/tools/display/ui.css +354 -0
  79. package/build/test/display.js +0 -400
  80. package/build/test/display.js.map +0 -1
  81. package/src/lib/binding/wasm.zig +0 -12
  82. package/src/lib/gen1/README.md +0 -894
  83. package/src/lib/gen2/README.md +0 -329
  84. package/src/test/display/pkmn.html.tmpl +0 -368
package/package.json CHANGED
@@ -1,19 +1,31 @@
1
1
  {
2
2
  "name": "@pkmn/engine",
3
- "version": "0.1.0-dev.12e7292c",
3
+ "version": "0.1.0-dev.130de754",
4
4
  "description": "A minimal, complete, Pokémon battle simulation engine optimized for performance",
5
5
  "repository": "github:pkmn/engine",
6
6
  "license": "MIT",
7
7
  "sideEffects": false,
8
8
  "main": "build/pkg/index.js",
9
9
  "types": "build/pkg/index.d.ts",
10
+ "browser": {
11
+ "./build/pkg/addon/node.js": "./build/pkg/addon/browser.js"
12
+ },
10
13
  "files": [
11
14
  "build.zig",
12
- "build/pkg/data.d.ts",
13
- "build/pkg/data.js.map",
14
15
  "build/pkg/addon.d.ts",
15
16
  "build/pkg/addon.js.map",
16
17
  "build/pkg/addon.js",
18
+ "build/pkg/addon/browser.d.ts",
19
+ "build/pkg/addon/browser.js.map",
20
+ "build/pkg/addon/browser.js",
21
+ "build/pkg/addon/node.d.ts",
22
+ "build/pkg/addon/node.js.map",
23
+ "build/pkg/addon/node.js",
24
+ "build/pkg/addon/wasm.d.ts",
25
+ "build/pkg/addon/wasm.js.map",
26
+ "build/pkg/addon/wasm.js",
27
+ "build/pkg/data.d.ts",
28
+ "build/pkg/data.js.map",
17
29
  "build/pkg/data.js",
18
30
  "build/pkg/data/ids.json",
19
31
  "build/pkg/data/layout.json",
@@ -27,13 +39,20 @@
27
39
  "build/pkg/protocol.d.ts",
28
40
  "build/pkg/protocol.js.map",
29
41
  "build/pkg/protocol.js",
30
- "build/test/display.js.map",
31
- "build/test/display.js",
32
42
  "build/tools/debug.js.map",
33
43
  "build/tools/debug.js",
34
- "src/bin/install-pkmn-engine",
35
- "src/lib/binding/node.zig",
36
- "src/lib/binding/wasm.zig",
44
+ "build/tools/display/index.js.map",
45
+ "build/tools/display/index.js",
46
+ "build/tools/display/debug.jsx.map",
47
+ "build/tools/display/debug.jsx",
48
+ "build/tools/display/ui.jsx.map",
49
+ "build/tools/display/ui.jsx",
50
+ "build/tools/display/util.js.map",
51
+ "build/tools/display/util.js",
52
+ "src/lib/bindings/c.zig",
53
+ "src/lib/bindings/node.zig",
54
+ "src/lib/bindings/wasm.zig",
55
+ "src/lib/common/array.zig",
37
56
  "src/lib/common/battle.zig",
38
57
  "src/lib/common/data.zig",
39
58
  "src/lib/common/debug.zig",
@@ -62,8 +81,12 @@
62
81
  "src/lib/gen2/generated.zig",
63
82
  "src/lib/gen2/helpers.zig",
64
83
  "src/lib/gen2/mechanics.zig",
84
+ "src/lib/napi.h",
85
+ "src/lib/node.zig",
65
86
  "src/lib/pkmn.zig",
66
- "src/test/display/pkmn.html.tmpl"
87
+ "src/lib/wasm.zig",
88
+ "src/tools/display/dom.ts",
89
+ "src/tools/display/ui.css"
67
90
  ],
68
91
  "engines": {
69
92
  "node": ">=16.0.0"
@@ -76,150 +99,53 @@
76
99
  "access": "public"
77
100
  },
78
101
  "dependencies": {
79
- "@pkmn/data": "^0.7.54",
80
- "@pkmn/protocol": "^0.6.16"
102
+ "@pkmn/data": "0.9.35",
103
+ "@pkmn/protocol": "^0.7.3"
81
104
  },
82
105
  "devDependencies": {
83
- "@pkmn/eslint-config": "^5.3.0",
84
- "@pkmn/img": "^0.2.18",
85
- "@pkmn/sets": "^5.1.0",
86
- "@pkmn/sim": "0.7.54",
87
- "@types/html-minifier": "^4.0.4",
88
- "@types/jest": "^29.5.6",
89
- "@types/minimist": "^1.2.4",
90
- "@types/mustache": "^4.2.4",
91
- "@types/node": "^20.8.9",
92
- "@vitest/coverage-c8": "^0.33.0",
93
- "binaryen": "^116.0.0",
94
- "eslint": "^8.52.0",
106
+ "@pkmn/dex-types": "0.9.35",
107
+ "@pkmn/eslint-config": "^10.0.0",
108
+ "@pkmn/img": "^0.3.4",
109
+ "@pkmn/sets": "^5.2.0",
110
+ "@pkmn/sim": "0.9.31",
111
+ "@pkmn/smogon": "0.5.21",
112
+ "@types/html-minifier": "^4.0.6",
113
+ "@types/jest": "^30.0.0",
114
+ "@types/minimist": "^1.2.5",
115
+ "@types/mustache": "^4.2.6",
116
+ "@types/node": "^26.6.3",
117
+ "@types/react": "^19.3.0",
118
+ "@types/vscode": "^1.140.0",
119
+ "@vitest/coverage-v8": "^5.0.3",
120
+ "@vscode/vsce": "^4.0.0",
121
+ "binaryen": "^132.0.0",
122
+ "esbuild": "^0.28.2",
123
+ "eslint": "^10.11.0",
95
124
  "html-minifier": "^4.0.0",
96
- "json-stringify-pretty-compact": "4.0.0",
125
+ "json-stringify-pretty-compact": "3.0.0",
97
126
  "minimist": "^1.2.8",
98
127
  "mustache": "^4.2.0",
99
128
  "source-map-support": "^0.5.21",
100
- "table": "^6.8.1",
129
+ "table": "^6.9.0",
101
130
  "trakr": "^0.2.0",
102
- "typescript": "^5.2.2",
103
- "vitest": "^0.34.6"
131
+ "typescript": "^6.0.3",
132
+ "vitest": "^5.0.3"
104
133
  },
105
134
  "scripts": {
106
- "lint": "eslint --cache src --ext ts,js && eslint src/bin/*",
107
- "fix": "eslint --fix src --ext ts,js && eslint --fix src/bin/*",
135
+ "lint": "eslint --cache src",
136
+ "fix": "eslint --fix src",
108
137
  "compile": "tsc -p .",
109
138
  "build": "npm run compile",
110
139
  "test": "vitest src/pkg",
111
140
  "test:integration": "vitest src/test",
112
141
  "debug": "npm run compile && node build/tools/debug",
142
+ "demo": "npm run compile && node build/tools/demo",
113
143
  "fuzz": "npm run compile && node build/test/fuzz",
114
144
  "generate": "npm run compile && node build/tools/generate",
115
145
  "release": "npm run compile && node build/tools/release",
116
146
  "benchmark": "npm run compile && node build/test/benchmark",
117
147
  "integration": "npm run compile && node build/test/integration",
148
+ "extension": "npm -C src/tools/vscode run build",
118
149
  "postinstall": "node src/bin/install-pkmn-engine"
119
- },
120
- "eslintConfig": {
121
- "extends": "@pkmn",
122
- "ignorePatterns": [
123
- "dist/",
124
- "node_modules/",
125
- "examples/zig",
126
- "build/"
127
- ],
128
- "env": {
129
- "es6": true,
130
- "node": true,
131
- "browser": true
132
- },
133
- "overrides": [
134
- {
135
- "files": [
136
- "**/*.ts"
137
- ],
138
- "parserOptions": {
139
- "project": [
140
- "./tsconfig.json",
141
- "./examples/js/tsconfig.json"
142
- ]
143
- }
144
- },
145
- {
146
- "files": [
147
- "src/pkg/index.ts",
148
- "src/test/display.ts",
149
- "src/test/integration.ts"
150
- ],
151
- "rules": {
152
- "no-control-regex": "off",
153
- "@typescript-eslint/no-empty-interface": "off",
154
- "@typescript-eslint/no-shadow": "off",
155
- "@typescript-eslint/no-unsafe-declaration-merging": "off"
156
- }
157
- },
158
- {
159
- "files": [
160
- "src/pkg/addon.ts"
161
- ],
162
- "rules": {
163
- "@typescript-eslint/no-var-requires": "off"
164
- }
165
- },
166
- {
167
- "files": [
168
- "src/test/benchmark*.ts"
169
- ],
170
- "rules": {
171
- "@typescript-eslint/no-unused-vars": "off",
172
- "@typescript-eslint/no-redundant-type-constituents": "off"
173
- }
174
- },
175
- {
176
- "files": [
177
- "src/pkg/protocol.test.ts"
178
- ],
179
- "rules": {
180
- "jest/no-standalone-expect": "off",
181
- "jest/no-conditional-expect": "off"
182
- }
183
- },
184
- {
185
- "files": [
186
- "src/test/*.test.ts",
187
- "src/test/regression/*.test.ts"
188
- ],
189
- "rules": {
190
- "jest/no-standalone-expect": "off"
191
- }
192
- },
193
- {
194
- "files": [
195
- "src/test/showdown/**"
196
- ],
197
- "rules": {
198
- "jest/expect-expect": [
199
- "warn",
200
- {
201
- "assertFunctionNames": [
202
- "expect",
203
- "expectLog",
204
- "verify"
205
- ]
206
- }
207
- ]
208
- }
209
- },
210
- {
211
- "files": [
212
- "src/tools/generate.ts"
213
- ],
214
- "rules": {
215
- "@typescript-eslint/restrict-template-expressions": [
216
- "error",
217
- {
218
- "allowBoolean": true
219
- }
220
- ]
221
- }
222
- }
223
- ]
224
150
  }
225
151
  }
@@ -10,7 +10,7 @@ const path = require('path');
10
10
  const {pipeline} = require('stream/promises');
11
11
  const tty = require('tty');
12
12
 
13
- const ZIG_VERSION = {major: 0, minor: 11, patch: 0};
13
+ const ZIG_VERSION = {major: 0, minor: 16, patch: 0};
14
14
  const DEV = ZIG_VERSION.dev ? `-dev.${ZIG_VERSION.dev}` : '';
15
15
  const VERSION = `${ZIG_VERSION.major}.${ZIG_VERSION.minor}.${ZIG_VERSION.patch}${DEV}`;
16
16
  const INDEX = 'https://ziglang.org/download/index.json';
@@ -111,15 +111,31 @@ const unpack = async (input, output) => {
111
111
  }
112
112
  };
113
113
 
114
+ const parse = s => {
115
+ try {
116
+ return JSON.parse(s);
117
+ } catch (e) {
118
+ if (!(e instanceof SyntaxError)) throw e;
119
+ const json = s
120
+ // "key": -> "key": (ensures keys are quoted)
121
+ .replace(/\.([a-zA-Z_][a-zA-Z0-9_]*)\s*=/g, '"$1":')
122
+ // .{ -> { (converts ZON struct to JSON object)
123
+ .replace(/\.\{/g, '{')
124
+ // Remove trailing commas, which are invalid in JSON
125
+ .replace(/,\s*([}\]])/g, '$1');
126
+ return JSON.parse(json);
127
+ }
128
+ };
129
+
114
130
  const find = zig => {
115
131
  try {
116
- const {zig_exe, version} = JSON.parse(sh(zig, ['env']));
117
- const [major, minor, patch, dev] = version.split('.').map(n => parseInt(n));
132
+ const {zig_exe, version} = parse(sh(zig, ['env']));
133
+ const [major, minor, patch, dev] = version.split('.').map(n => parseInt(n, 10));
118
134
 
119
135
  const compatible = major > ZIG_VERSION.major ||
120
136
  (major >= ZIG_VERSION.major && minor > ZIG_VERSION.minor) ||
121
137
  (major >= ZIG_VERSION.major && minor >= ZIG_VERSION.minor && patch >= ZIG_VERSION.patch &&
122
- (!ZIG_VERSION.dev || (dev && dev >= ZIG_VERSION.dev)));
138
+ (!ZIG_VERSION.dev || (dev && dev >= parseInt(ZIG_VERSION.dev, 10))));
123
139
 
124
140
  if (compatible) {
125
141
  log('Found existing compatible Zig executable:', zig_exe);
@@ -164,6 +180,7 @@ const install = async () => {
164
180
 
165
181
  const index = JSON.parse(await fetch(INDEX));
166
182
  const version = Object.keys(index)[+!ZIG_VERSION.dev];
183
+ // const version = VERSION; // TODO
167
184
  const release = index[version][`${arch}-${platform}`];
168
185
  const url = release.tarball;
169
186
 
@@ -249,15 +266,15 @@ const downloadHeaders = async () => {
249
266
 
250
267
  const downloadImportLib = async () => {
251
268
  const library = path.resolve(process.execPath, '..', 'node.lib');
252
- if (fs.existsSync(path.join(library, 'node.h'))) {
269
+ if (fs.existsSync(library)) {
253
270
  log('Node import library:', library);
254
271
  return library;
255
272
  }
256
273
 
257
274
  const dir = path.join(ROOT, 'build', 'lib');
258
- const url = new URL('./win-x64/node.lib', process.release.headersUrl).href;
275
+ const url = process.release.libUrl;
259
276
  const dest = path.join(dir, path.basename(url));
260
- if (fs.existsSync(path.join(dest))) {
277
+ if (fs.existsSync(dest)) {
261
278
  log('Node import library:', dest);
262
279
  return dest;
263
280
  } else {
@@ -283,19 +300,19 @@ const downloadImportLib = async () => {
283
300
  let error = false;
284
301
  for (let i = 2; i < process.argv.length; i++) {
285
302
  switch (process.argv[i]) {
286
- case "--silent": {
287
- SILENT = true;
288
- break;
289
- }
290
- case "--zig": {
291
- if (options || only) error = true;
292
- only = true;
293
- break;
294
- }
295
- default: {
296
- if (options || only || !process.argv[i].startsWith('--options=')) error = true;
297
- options = process.argv[i].slice(10).split(' ');
298
- }
303
+ case "--silent": {
304
+ SILENT = true;
305
+ break;
306
+ }
307
+ case "--zig": {
308
+ if (options || only) error = true;
309
+ only = true;
310
+ break;
311
+ }
312
+ default: {
313
+ if (options || only || !process.argv[i].startsWith('--options=')) error = true;
314
+ options = process.argv[i].slice(10).split(' ');
315
+ }
299
316
  }
300
317
  }
301
318
  if (error) {
@@ -306,14 +323,6 @@ const downloadImportLib = async () => {
306
323
  const zig = await install();
307
324
  if (only) process.exit(0);
308
325
 
309
- let tmp;
310
- try {
311
- tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'pkmn-'));
312
- } catch {
313
- console.error('Unable to create temporary directory');
314
- process.exit(1);
315
- }
316
-
317
326
  // Determine which configurations to build based on prior runs (see below for
318
327
  // if there were no previous runs) - try to build the same configurations as
319
328
  // before (unless --options overridden). We also track whether any of the
@@ -322,32 +331,46 @@ const downloadImportLib = async () => {
322
331
  const configs = new Map();
323
332
  const libs = path.join(ROOT, 'build', 'lib');
324
333
  if (fs.existsSync(libs)) {
334
+ let tmp;
335
+ if (!options) {
336
+ try {
337
+ tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'pkmn-'));
338
+ process.on('exit', () => {
339
+ try { fs.rmSync(tmp, {force: true, recursive: true}); } catch {}
340
+ });
341
+ } catch {
342
+ console.error('Unable to create temporary directory');
343
+ process.exit(1);
344
+ }
345
+ }
346
+
325
347
  for (const file of fs.readdirSync(libs)) {
348
+ if (!file.startsWith('pkmn')) continue;
326
349
  const type = path.extname(file).slice(1);
327
350
  if (type !== 'node' && type !== 'wasm') continue;
328
- // If we don't copy the addon before loading it Windows will return an
329
- // EBUSY error when we later attempt to clobber it (Linux and macOS don't
330
- // seem to care)
331
- const copy = path.join(tmp, file);
332
- fs.copyFileSync(path.join(libs, file), copy);
351
+ if (type === 'node') node = true;
333
352
 
334
353
  const opts = options || [];
335
- if (type === 'node') {
336
- node = true;
337
- if (!options) {
354
+ if (!options) {
355
+ // If we don't copy the addon before loading it Windows will return an EBUSY error
356
+ // when we later attempt to clobber it (Linux and macOS don't seem to care)
357
+ const copy = path.join(tmp, file);
358
+ fs.copyFileSync(path.join(libs, file), copy);
359
+
360
+ if (type === 'node') {
338
361
  const addon = require(copy);
339
362
  if (addon.engine.options.showdown) opts.push('-Dshowdown');
340
363
  if (addon.engine.options.log) opts.push('-Dlog');
341
364
  if (addon.engine.options.chance) opts.push('-Dchance');
342
365
  if (addon.engine.options.calc) opts.push('-Dcalc');
366
+ } else {
367
+ const addon = await WebAssembly.instantiate(fs.readFileSync(copy));
368
+ const values = new Uint8Array(addon.instance.exports.memory.buffer);
369
+ if (values[addon.instance.exports.SHOWDOWN.value]) opts.push('-Dshowdown');
370
+ if (values[addon.instance.exports.LOG.value]) opts.push('-Dlog');
371
+ if (values[addon.instance.exports.CHANCE.value]) opts.push('-Dchance');
372
+ if (values[addon.instance.exports.CALC.value]) opts.push('-Dcalc');
343
373
  }
344
- } else if (!options) {
345
- const addon = await WebAssembly.instantiate(fs.readFileSync(copy));
346
- const values = new Uint8Array(addon.instance.exports.memory.buffer);
347
- if (values[addon.instance.exports.SHOWDOWN.value]) opts.push('-Dshowdown');
348
- if (values[addon.instance.exports.LOG.value]) opts.push('-Dlog');
349
- if (values[addon.instance.exports.CHANCE.value]) opts.push('-Dchance');
350
- if (values[addon.instance.exports.CALC.value]) opts.push('-Dcalc');
351
374
  }
352
375
  const key = `${type} ${opts.sort().join(' ')}`;
353
376
  if (!configs.has(key)) configs.set(key, {type, options: opts});
@@ -370,8 +393,10 @@ const downloadImportLib = async () => {
370
393
  const args = ['build', '-p', 'build', ...opts];
371
394
  if (!process.env.DEBUG_PKMN_ENGINE) args.push('-Doptimize=ReleaseFast', '-Dstrip');
372
395
  if (config.type === 'node') {
373
- args.push(`-Dnode-headers=${headers}`);
374
- if (process.platform === 'win32') args.push(`-Dnode-import-library=${lib}`);
396
+ args.push(`-Dnode-headers=${path.relative(ROOT, headers)}`);
397
+ if (process.platform === 'win32') {
398
+ args.push(`-Dnode-import-library=${path.relative(ROOT, lib)}`);
399
+ }
375
400
  } else {
376
401
  args.push('-Dwasm');
377
402
  }
@@ -381,14 +406,6 @@ const downloadImportLib = async () => {
381
406
  const artifact = path.join('build', 'lib', `pkmn${suffix}.${config.type}`);
382
407
  log(`Building ${artifact}${flags}`);
383
408
  sh(zig, args);
384
- // TODO: ziglang/zig#14647 broke emit_to so we get to rename the file ourselves...
385
- if (config.type === 'node') {
386
- const prefix = process.platform === 'win32' ? '' : 'lib';
387
- const ext = process.platform === 'darwin'
388
- ? 'dylib' : process.platform === 'win32' ? 'dll' : 'so';
389
- const actual = path.join('build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
390
- fs.renameSync(path.join(ROOT, actual), path.join(ROOT, artifact));
391
- }
392
409
  }
393
410
  })().catch(e => {
394
411
  console.error(e);
@@ -15,7 +15,7 @@ const ROOT = resolve(__dirname, '..', '..');
15
15
  const packageJSON = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8'));
16
16
 
17
17
  const missing = [];
18
- for (const dep of ['@pkmn/img', 'html-minifier', 'mustache']) {
18
+ for (const dep of ['@pkmn/img', 'html-minifier', 'esbuild']) {
19
19
  try {
20
20
  require.resolve(dep);
21
21
  } catch (e) {
@@ -0,0 +1,201 @@
1
+ const pkmn = @import("../pkmn.zig");
2
+ const std = @import("std");
3
+ const util = @import("../common/util.zig");
4
+
5
+ const assert = std.debug.assert;
6
+
7
+ const ERROR: u8 = 0b1100;
8
+
9
+ pub const OPTIONS: extern struct {
10
+ showdown: bool,
11
+ log: bool,
12
+ chance: bool,
13
+ calc: bool,
14
+ } = .{
15
+ .showdown = pkmn.options.showdown,
16
+ .log = pkmn.options.log,
17
+ .chance = pkmn.options.chance,
18
+ .calc = pkmn.options.calc,
19
+ };
20
+
21
+ pub const MAX_CHOICES = pkmn.MAX_CHOICES;
22
+ pub const CHOICES_SIZE = pkmn.CHOICES_SIZE;
23
+ pub const MAX_LOGS = pkmn.MAX_LOGS;
24
+ pub const LOGS_SIZE = pkmn.LOGS_SIZE;
25
+
26
+ pub fn choice_init(choice: u8, data: u8) callconv(.c) u8 {
27
+ assert(choice <= util.EnumFieldsLen(pkmn.Choice.Type));
28
+ assert(data <= 6);
29
+ return @bitCast(pkmn.Choice{ .type = @enumFromInt(choice), .data = @intCast(data) });
30
+ }
31
+
32
+ pub fn choice_type(choice: u8) callconv(.c) u8 {
33
+ return @intFromEnum(@as(pkmn.Choice, @bitCast(choice)).type);
34
+ }
35
+
36
+ pub fn choice_data(choice: u8) callconv(.c) u8 {
37
+ return @as(u8, @as(pkmn.Choice, @bitCast(choice)).data);
38
+ }
39
+
40
+ pub fn result_type(result: u8) callconv(.c) u8 {
41
+ return @intFromEnum(@as(pkmn.Result, @bitCast(result)).type);
42
+ }
43
+
44
+ pub fn result_p1(result: u8) callconv(.c) u8 {
45
+ assert(!err(result));
46
+ return @intFromEnum(@as(pkmn.Result, @bitCast(result)).p1);
47
+ }
48
+
49
+ pub fn result_p2(result: u8) callconv(.c) u8 {
50
+ assert(!err(result));
51
+ return @intFromEnum(@as(pkmn.Result, @bitCast(result)).p2);
52
+ }
53
+
54
+ pub fn err(result: u8) callconv(.c) bool {
55
+ return result == ERROR;
56
+ }
57
+
58
+ pub fn psrng_init(prng: *pkmn.PSRNG, seed: u64) callconv(.c) void {
59
+ prng.src = .{ .seed = seed };
60
+ }
61
+
62
+ pub fn psrng_next(prng: *pkmn.PSRNG) callconv(.c) u32 {
63
+ return prng.next();
64
+ }
65
+
66
+ pub fn rational_init(rational: *pkmn.Rational(f64)) callconv(.c) void {
67
+ rational.reset();
68
+ }
69
+
70
+ pub fn rational_reduce(rational: *pkmn.Rational(f64)) callconv(.c) void {
71
+ rational.reduce();
72
+ }
73
+
74
+ pub fn rational_numerator(rational: *const pkmn.Rational(f64)) callconv(.c) f64 {
75
+ return rational.p;
76
+ }
77
+
78
+ pub fn rational_denominator(rational: *const pkmn.Rational(f64)) callconv(.c) f64 {
79
+ return rational.q;
80
+ }
81
+
82
+ const log_options = extern struct {
83
+ buf: [*]u8,
84
+ len: usize,
85
+ };
86
+
87
+ pub fn gen(comptime num: comptime_int) type {
88
+ const g = @field(pkmn, "gen" ++ std.fmt.comptimePrint("{d}", .{num}));
89
+
90
+ return struct {
91
+ pub const MAX_CHOICES = g.MAX_CHOICES;
92
+ pub const CHOICES_SIZE = g.CHOICES_SIZE;
93
+ pub const MAX_LOGS = g.MAX_LOGS;
94
+ pub const LOGS_SIZE = g.LOGS_SIZE;
95
+
96
+ const chance_options = extern struct {
97
+ probability: pkmn.Rational(f64),
98
+ actions: g.chance.Actions,
99
+ durations: g.chance.Durations,
100
+ };
101
+
102
+ const calc_options = extern struct {
103
+ overrides: g.chance.Actions,
104
+ };
105
+
106
+ const battle_options = struct {
107
+ writer: pkmn.protocol.Writer,
108
+ log: pkmn.protocol.FixedLog,
109
+ chance: g.Chance(pkmn.Rational(f64)),
110
+ calc: g.Calc,
111
+
112
+ comptime {
113
+ assert(@sizeOf(battle_options) <= 128);
114
+ }
115
+ };
116
+
117
+ pub fn battle_options_set(
118
+ options: *battle_options,
119
+ log: ?*const log_options,
120
+ chance: ?*const chance_options,
121
+ calc: ?*const calc_options,
122
+ ) callconv(.c) void {
123
+ if (pkmn.options.log) {
124
+ if (log) |l| {
125
+ options.writer = .{ .buffer = l.buf[0..l.len] };
126
+ options.log = .{ .writer = &options.writer };
127
+ } else {
128
+ options.writer.reset();
129
+ }
130
+ }
131
+ if (pkmn.options.chance) {
132
+ if (chance) |c| {
133
+ options.chance = .{
134
+ .probability = c.probability,
135
+ .actions = c.actions,
136
+ .durations = c.durations,
137
+ };
138
+ } else {
139
+ options.chance.reset();
140
+ }
141
+ }
142
+ if (pkmn.options.calc) {
143
+ if (calc) |c| {
144
+ options.calc = .{ .overrides = c.overrides };
145
+ } else {
146
+ options.calc = .{};
147
+ }
148
+ }
149
+ }
150
+
151
+ pub fn battle_options_chance_probability(
152
+ options: *battle_options,
153
+ ) callconv(.c) *pkmn.Rational(f64) {
154
+ return &options.chance.probability;
155
+ }
156
+
157
+ pub fn battle_options_chance_actions(
158
+ options: *battle_options,
159
+ ) callconv(.c) *g.chance.Actions {
160
+ return &options.chance.actions;
161
+ }
162
+
163
+ pub fn battle_options_chance_durations(
164
+ options: *battle_options,
165
+ ) callconv(.c) *g.chance.Durations {
166
+ return &options.chance.durations;
167
+ }
168
+
169
+ pub fn battle_options_calc_summaries(
170
+ options: *battle_options,
171
+ ) callconv(.c) *g.calc.Summaries {
172
+ return &options.calc.summaries;
173
+ }
174
+
175
+ pub fn battle_update(
176
+ battle: *g.Battle(g.PRNG),
177
+ c1: pkmn.Choice,
178
+ c2: pkmn.Choice,
179
+ opts: ?*battle_options,
180
+ ) callconv(.c) pkmn.Result {
181
+ if ((pkmn.options.log or pkmn.options.chance or pkmn.options.calc) and opts != null) {
182
+ return battle.update(c1, c2, opts.?) catch return @bitCast(ERROR);
183
+ }
184
+ return battle.update(c1, c2, &g.NULL) catch unreachable;
185
+ }
186
+
187
+ pub fn battle_choices(
188
+ battle: *const g.Battle(g.PRNG),
189
+ player: u8,
190
+ request: u8,
191
+ out: [*]u8,
192
+ n: usize,
193
+ ) callconv(.c) u8 {
194
+ assert(player <= util.EnumFieldsLen(pkmn.Player));
195
+ assert(request <= util.EnumFieldsLen(pkmn.Choice.Type));
196
+
197
+ assert(!pkmn.options.showdown or n > 0);
198
+ return battle.choices(@enumFromInt(player), @enumFromInt(request), @ptrCast(out[0..n]));
199
+ }
200
+ };
201
+ }