@pkmn/engine 0.1.0-dev.29e0e9e1 → 0.1.0-dev.2b11d5c7

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 (83) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +46 -18
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +44 -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 +97 -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 +25 -3
  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 +13 -17
  20. package/build/pkg/gen1.js +6 -10
  21. package/build/pkg/gen1.js.map +1 -1
  22. package/build/pkg/index.d.ts +40 -91
  23. package/build/pkg/index.js +6 -63
  24. package/build/pkg/index.js.map +1 -1
  25. package/build/pkg/protocol.d.ts +20 -1
  26. package/build/pkg/protocol.js +109 -107
  27. package/build/pkg/protocol.js.map +1 -1
  28. package/build/tools/debug.js +36 -71
  29. package/build/tools/debug.js.map +1 -1
  30. package/build/tools/display/debug.jsx +141 -0
  31. package/build/tools/display/debug.jsx.map +1 -0
  32. package/build/tools/display/index.js +142 -0
  33. package/build/tools/display/index.js.map +1 -0
  34. package/build/tools/display/ui.jsx +349 -0
  35. package/build/tools/display/ui.jsx.map +1 -0
  36. package/build/tools/display/util.js +18 -0
  37. package/build/tools/display/util.js.map +1 -0
  38. package/build.zig +294 -90
  39. package/package.json +59 -132
  40. package/src/bin/install-pkmn-engine +30 -20
  41. package/src/bin/pkmn-debug +1 -1
  42. package/src/lib/bindings/c.zig +254 -0
  43. package/src/lib/{binding → bindings}/node.zig +8 -21
  44. package/src/lib/bindings/wasm.zig +59 -0
  45. package/src/lib/common/array.zig +77 -0
  46. package/src/lib/common/data.zig +4 -4
  47. package/src/lib/common/debug.zig +39 -8
  48. package/src/lib/common/js.zig +4 -2
  49. package/src/lib/common/optional.zig +14 -10
  50. package/src/lib/common/options.zig +6 -0
  51. package/src/lib/common/protocol.zig +77 -80
  52. package/src/lib/common/rational.zig +128 -32
  53. package/src/lib/common/rng.zig +7 -9
  54. package/src/lib/common/util.zig +50 -1
  55. package/src/lib/gen1/calc.zig +686 -159
  56. package/src/lib/gen1/chance.zig +405 -280
  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 +1 -2
  60. package/src/lib/gen1/data.zig +24 -27
  61. package/src/lib/gen1/helpers.zig +92 -548
  62. package/src/lib/gen1/mechanics.zig +379 -258
  63. package/src/lib/gen2/calc.zig +37 -27
  64. package/src/lib/gen2/chance.zig +84 -496
  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 +1 -2
  69. package/src/lib/gen2/data.zig +19 -22
  70. package/src/lib/gen2/generated.zig +19 -26
  71. package/src/lib/gen2/helpers.zig +46 -25
  72. package/src/lib/gen2/mechanics.zig +217 -163
  73. package/src/lib/node.zig +18 -0
  74. package/src/lib/pkmn.zig +37 -15
  75. package/src/lib/wasm.zig +17 -0
  76. package/src/tools/display/dom.ts +96 -0
  77. package/src/tools/display/ui.css +354 -0
  78. package/build/test/display.js +0 -400
  79. package/build/test/display.js.map +0 -1
  80. package/src/lib/binding/wasm.zig +0 -12
  81. package/src/lib/gen1/README.md +0 -894
  82. package/src/lib/gen2/README.md +0 -329
  83. 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.29e0e9e1",
3
+ "version": "0.1.0-dev.2b11d5c7",
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,11 @@
62
81
  "src/lib/gen2/generated.zig",
63
82
  "src/lib/gen2/helpers.zig",
64
83
  "src/lib/gen2/mechanics.zig",
84
+ "src/lib/node.zig",
65
85
  "src/lib/pkmn.zig",
66
- "src/test/display/pkmn.html.tmpl"
86
+ "src/lib/wasm.zig",
87
+ "src/tools/display/dom.ts",
88
+ "src/tools/display/ui.css"
67
89
  ],
68
90
  "engines": {
69
91
  "node": ">=16.0.0"
@@ -76,149 +98,54 @@
76
98
  "access": "public"
77
99
  },
78
100
  "dependencies": {
79
- "@pkmn/data": "^0.7.53",
80
- "@pkmn/protocol": "^0.6.16"
101
+ "@pkmn/data": "^0.9.20",
102
+ "@pkmn/protocol": "^0.6.27"
81
103
  },
82
104
  "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.53",
87
- "@types/html-minifier": "^4.0.3",
88
- "@types/jest": "^29.5.5",
89
- "@types/minimist": "^1.2.3",
90
- "@types/mustache": "^4.2.3",
91
- "@types/node": "^20.8.2",
92
- "@vitest/coverage-c8": "^0.33.0",
93
- "binaryen": "^114.0.0",
94
- "eslint": "^8.51.0",
105
+ "@pkmn/eslint-config": "^9.0.0",
106
+ "@pkmn/img": "^0.2.32",
107
+ "@pkmn/sets": "^5.1.2",
108
+ "@pkmn/sim": "0.9.20",
109
+ "@pkmn/smogon": "^0.5.14",
110
+ "@types/html-minifier": "^4.0.5",
111
+ "@types/jest": "^29.5.13",
112
+ "@types/minimist": "^1.2.5",
113
+ "@types/mustache": "^4.2.5",
114
+ "@types/node": "^22.7.6",
115
+ "@types/react": "^18.3.11",
116
+ "@types/semver": "^7.5.8",
117
+ "@types/vscode": "^1.94.0",
118
+ "@vitest/coverage-v8": "^2.1.3",
119
+ "@vscode/vsce": "^3.2.0",
120
+ "binaryen": "^119.0.0",
121
+ "esbuild": "^0.24.0",
122
+ "eslint": "^9.12.0",
95
123
  "html-minifier": "^4.0.0",
96
124
  "json-stringify-pretty-compact": "3.0.0",
97
125
  "minimist": "^1.2.8",
98
126
  "mustache": "^4.2.0",
127
+ "semver": "^7.6.3",
99
128
  "source-map-support": "^0.5.21",
129
+ "table": "^6.8.2",
100
130
  "trakr": "^0.2.0",
101
- "typescript": "^5.2.2",
102
- "vitest": "^0.34.6"
131
+ "typescript": "^5.6.3",
132
+ "vitest": "^2.1.3"
103
133
  },
104
134
  "scripts": {
105
- "lint": "eslint --cache src --ext ts,js && eslint src/bin/*",
106
- "fix": "eslint --fix src --ext ts,js && eslint --fix src/bin/*",
135
+ "lint": "eslint --cache src",
136
+ "fix": "eslint --fix src",
107
137
  "compile": "tsc -p .",
108
138
  "build": "npm run compile",
109
139
  "test": "vitest src/pkg",
110
140
  "test:integration": "vitest src/test",
111
141
  "debug": "npm run compile && node build/tools/debug",
142
+ "demo": "npm run compile && node build/tools/demo",
112
143
  "fuzz": "npm run compile && node build/test/fuzz",
113
144
  "generate": "npm run compile && node build/tools/generate",
114
145
  "release": "npm run compile && node build/tools/release",
115
146
  "benchmark": "npm run compile && node build/test/benchmark",
116
147
  "integration": "npm run compile && node build/test/integration",
148
+ "extension": "npm -C src/tools/vscode run build",
117
149
  "postinstall": "node src/bin/install-pkmn-engine"
118
- },
119
- "eslintConfig": {
120
- "extends": "@pkmn",
121
- "ignorePatterns": [
122
- "dist/",
123
- "node_modules/",
124
- "examples/zig",
125
- "build/"
126
- ],
127
- "env": {
128
- "es6": true,
129
- "node": true,
130
- "browser": true
131
- },
132
- "overrides": [
133
- {
134
- "files": [
135
- "**/*.ts"
136
- ],
137
- "parserOptions": {
138
- "project": [
139
- "./tsconfig.json",
140
- "./examples/js/tsconfig.json"
141
- ]
142
- }
143
- },
144
- {
145
- "files": [
146
- "src/pkg/index.ts",
147
- "src/test/display.ts",
148
- "src/test/integration.ts"
149
- ],
150
- "rules": {
151
- "no-control-regex": "off",
152
- "@typescript-eslint/no-empty-interface": "off",
153
- "@typescript-eslint/no-shadow": "off",
154
- "@typescript-eslint/no-unsafe-declaration-merging": "off"
155
- }
156
- },
157
- {
158
- "files": [
159
- "src/pkg/addon.ts"
160
- ],
161
- "rules": {
162
- "@typescript-eslint/no-var-requires": "off"
163
- }
164
- },
165
- {
166
- "files": [
167
- "src/test/benchmark*.ts"
168
- ],
169
- "rules": {
170
- "@typescript-eslint/no-unused-vars": "off",
171
- "@typescript-eslint/no-redundant-type-constituents": "off"
172
- }
173
- },
174
- {
175
- "files": [
176
- "src/pkg/protocol.test.ts"
177
- ],
178
- "rules": {
179
- "jest/no-standalone-expect": "off",
180
- "jest/no-conditional-expect": "off"
181
- }
182
- },
183
- {
184
- "files": [
185
- "src/test/*.test.ts",
186
- "src/test/regression/*.test.ts"
187
- ],
188
- "rules": {
189
- "jest/no-standalone-expect": "off"
190
- }
191
- },
192
- {
193
- "files": [
194
- "src/test/showdown/**"
195
- ],
196
- "rules": {
197
- "jest/expect-expect": [
198
- "warn",
199
- {
200
- "assertFunctionNames": [
201
- "expect",
202
- "expectLog",
203
- "verify"
204
- ]
205
- }
206
- ]
207
- }
208
- },
209
- {
210
- "files": [
211
- "src/tools/generate.ts"
212
- ],
213
- "rules": {
214
- "@typescript-eslint/restrict-template-expressions": [
215
- "error",
216
- {
217
- "allowBoolean": true
218
- }
219
- ]
220
- }
221
- }
222
- ]
223
150
  }
224
151
  }
@@ -163,8 +163,10 @@ const install = async () => {
163
163
  }
164
164
 
165
165
  const index = JSON.parse(await fetch(INDEX));
166
- const version = Object.keys(index)[+!ZIG_VERSION.dev];
167
- const release = index[version][`${arch}-${platform}`];
166
+ // TODO: ziglang/zig#17768
167
+ // const version = Object.keys(index)[+!ZIG_VERSION.dev];
168
+ const version = VERSION;
169
+ const release = index[VERSION][`${arch}-${platform}`];
168
170
  const url = release.tarball;
169
171
 
170
172
  let base = path.basename(url);
@@ -255,7 +257,7 @@ const downloadImportLib = async () => {
255
257
  }
256
258
 
257
259
  const dir = path.join(ROOT, 'build', 'lib');
258
- const url = new URL('./win-x64/node.lib', process.release.headersUrl).href;
260
+ const url = process.release.libUrl;
259
261
  const dest = path.join(dir, path.basename(url));
260
262
  if (fs.existsSync(path.join(dest))) {
261
263
  log('Node import library:', dest);
@@ -283,19 +285,19 @@ const downloadImportLib = async () => {
283
285
  let error = false;
284
286
  for (let i = 2; i < process.argv.length; i++) {
285
287
  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
- }
288
+ case "--silent": {
289
+ SILENT = true;
290
+ break;
291
+ }
292
+ case "--zig": {
293
+ if (options || only) error = true;
294
+ only = true;
295
+ break;
296
+ }
297
+ default: {
298
+ if (options || only || !process.argv[i].startsWith('--options=')) error = true;
299
+ options = process.argv[i].slice(10).split(' ');
300
+ }
299
301
  }
300
302
  }
301
303
  if (error) {
@@ -370,8 +372,10 @@ const downloadImportLib = async () => {
370
372
  const args = ['build', '-p', 'build', ...opts];
371
373
  if (!process.env.DEBUG_PKMN_ENGINE) args.push('-Doptimize=ReleaseFast', '-Dstrip');
372
374
  if (config.type === 'node') {
373
- args.push(`-Dnode-headers=${headers}`);
374
- if (process.platform === 'win32') args.push(`-Dnode-import-library=${lib}`);
375
+ args.push(`-Dnode-headers=${path.relative(ROOT, headers)}`);
376
+ if (process.platform === 'win32') {
377
+ args.push(`-Dnode-import-library=${path.relative(ROOT, lib)}`);
378
+ }
375
379
  } else {
376
380
  args.push('-Dwasm');
377
381
  }
@@ -386,8 +390,14 @@ const downloadImportLib = async () => {
386
390
  const prefix = process.platform === 'win32' ? '' : 'lib';
387
391
  const ext = process.platform === 'darwin'
388
392
  ? '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));
393
+ try {
394
+ const actual = path.join(ROOT, 'build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
395
+ fs.renameSync(actual, artifact);
396
+ } catch {
397
+ // ziglang/zig#19743 changed this path
398
+ const actual = path.join(ROOT, 'build', 'bin', `${prefix}pkmn${suffix}.node.${ext}`);
399
+ fs.renameSync(actual, artifact);
400
+ }
391
401
  }
392
402
  }
393
403
  })().catch(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,254 @@
1
+ const pkmn = @import("../pkmn.zig");
2
+ const std = @import("std");
3
+
4
+ const assert = std.debug.assert;
5
+
6
+ const ERROR: u8 = 0b1100;
7
+
8
+ const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
9
+
10
+ pub const OPTIONS: extern struct {
11
+ showdown: bool,
12
+ log: bool,
13
+ chance: bool,
14
+ calc: bool,
15
+ } = .{
16
+ .showdown = pkmn.options.showdown,
17
+ .log = pkmn.options.log,
18
+ .chance = pkmn.options.chance,
19
+ .calc = pkmn.options.calc,
20
+ };
21
+
22
+ pub const MAX_CHOICES = pkmn.MAX_CHOICES;
23
+ pub const CHOICES_SIZE = pkmn.CHOICES_SIZE;
24
+ pub const MAX_LOGS = pkmn.MAX_LOGS;
25
+ pub const LOGS_SIZE = pkmn.LOGS_SIZE;
26
+
27
+ pub fn choice_init(choice: u8, data: u8) callconv(.C) u8 {
28
+ assert(choice <= @field(@typeInfo(pkmn.Choice.Type), @tagName(Enum)).fields.len);
29
+ assert(data <= 6);
30
+ return @bitCast(pkmn.Choice{ .type = @enumFromInt(choice), .data = @intCast(data) });
31
+ }
32
+
33
+ pub fn choice_type(choice: u8) callconv(.C) u8 {
34
+ return @intFromEnum(@as(pkmn.Choice, @bitCast(choice)).type);
35
+ }
36
+
37
+ pub fn choice_data(choice: u8) callconv(.C) u8 {
38
+ return @as(u8, @as(pkmn.Choice, @bitCast(choice)).data);
39
+ }
40
+
41
+ pub fn result_type(result: u8) callconv(.C) u8 {
42
+ return @intFromEnum(@as(pkmn.Result, @bitCast(result)).type);
43
+ }
44
+
45
+ pub fn result_p1(result: u8) callconv(.C) u8 {
46
+ assert(!err(result));
47
+ return @intFromEnum(@as(pkmn.Result, @bitCast(result)).p1);
48
+ }
49
+
50
+ pub fn result_p2(result: u8) callconv(.C) u8 {
51
+ assert(!err(result));
52
+ return @intFromEnum(@as(pkmn.Result, @bitCast(result)).p2);
53
+ }
54
+
55
+ pub fn err(result: u8) callconv(.C) bool {
56
+ return result == ERROR;
57
+ }
58
+
59
+ pub fn psrng_init(prng: *pkmn.PSRNG, seed: u64) callconv(.C) void {
60
+ prng.src = .{ .seed = seed };
61
+ }
62
+
63
+ pub fn psrng_next(prng: *pkmn.PSRNG) callconv(.C) u32 {
64
+ return prng.next();
65
+ }
66
+
67
+ pub fn rational_init(rational: *pkmn.Rational(f64)) callconv(.C) void {
68
+ rational.reset();
69
+ }
70
+
71
+ pub fn rational_reduce(rational: *pkmn.Rational(f64)) callconv(.C) void {
72
+ rational.reduce();
73
+ }
74
+
75
+ pub fn rational_numerator(rational: *const pkmn.Rational(f64)) callconv(.C) f64 {
76
+ return rational.p;
77
+ }
78
+
79
+ pub fn rational_denominator(rational: *const pkmn.Rational(f64)) callconv(.C) f64 {
80
+ return rational.q;
81
+ }
82
+
83
+ const log_options = extern struct {
84
+ buf: [*]u8,
85
+ len: usize,
86
+ };
87
+
88
+ pub fn gen(comptime num: comptime_int) type {
89
+ const g = @field(pkmn, "gen" ++ std.fmt.comptimePrint("{d}", .{num}));
90
+
91
+ return struct {
92
+ pub const MAX_CHOICES = g.MAX_CHOICES;
93
+ pub const CHOICES_SIZE = g.CHOICES_SIZE;
94
+ pub const MAX_LOGS = g.MAX_LOGS;
95
+ pub const LOGS_SIZE = g.LOGS_SIZE;
96
+
97
+ const chance_options = extern struct {
98
+ probability: pkmn.Rational(f64),
99
+ actions: g.chance.Actions,
100
+ durations: g.chance.Durations,
101
+ };
102
+
103
+ const calc_options = extern struct {
104
+ overrides: g.chance.Actions,
105
+ };
106
+
107
+ const battle_options = struct {
108
+ stream: pkmn.protocol.ByteStream,
109
+ log: pkmn.protocol.FixedLog,
110
+ chance: g.Chance(pkmn.Rational(f64)),
111
+ calc: g.Calc,
112
+
113
+ comptime {
114
+ assert(@sizeOf(battle_options) <= 128);
115
+ }
116
+ };
117
+
118
+ pub fn battle_options_set(
119
+ options: *battle_options,
120
+ log: ?*const log_options,
121
+ chance: ?*const chance_options,
122
+ calc: ?*const calc_options,
123
+ ) callconv(.C) void {
124
+ if (pkmn.options.log) {
125
+ if (log) |l| {
126
+ options.stream = .{ .buffer = l.buf[0..l.len] };
127
+ options.log = .{ .writer = options.stream.writer() };
128
+ } else {
129
+ options.stream.reset();
130
+ }
131
+ }
132
+ if (pkmn.options.chance) {
133
+ if (chance) |c| {
134
+ options.chance = .{
135
+ .probability = c.probability,
136
+ .actions = c.actions,
137
+ .durations = c.durations,
138
+ };
139
+ } else {
140
+ options.chance.reset();
141
+ }
142
+ }
143
+ if (pkmn.options.calc) {
144
+ if (calc) |c| {
145
+ options.calc = .{ .overrides = c.overrides };
146
+ } else {
147
+ options.calc = .{};
148
+ }
149
+ }
150
+ }
151
+
152
+ pub fn battle_options_chance_probability(
153
+ options: *battle_options,
154
+ ) callconv(.C) *pkmn.Rational(f64) {
155
+ return &options.chance.probability;
156
+ }
157
+
158
+ pub fn battle_options_chance_actions(
159
+ options: *battle_options,
160
+ ) callconv(.C) *g.chance.Actions {
161
+ return &options.chance.actions;
162
+ }
163
+
164
+ pub fn battle_options_chance_durations(
165
+ options: *battle_options,
166
+ ) callconv(.C) *g.chance.Durations {
167
+ return &options.chance.durations;
168
+ }
169
+
170
+ pub fn battle_options_calc_summaries(
171
+ options: *battle_options,
172
+ ) callconv(.C) *g.calc.Summaries {
173
+ return &options.calc.summaries;
174
+ }
175
+
176
+ pub fn battle_update(
177
+ battle: *g.Battle(g.PRNG),
178
+ c1: pkmn.Choice,
179
+ c2: pkmn.Choice,
180
+ opts: ?*battle_options,
181
+ ) callconv(.C) pkmn.Result {
182
+ if ((pkmn.options.log or pkmn.options.chance or pkmn.options.calc) and opts != null) {
183
+ return battle.update(c1, c2, opts.?) catch return @bitCast(ERROR);
184
+ }
185
+ return battle.update(c1, c2, &g.NULL) catch unreachable;
186
+ }
187
+
188
+ pub fn battle_choices(
189
+ battle: *const g.Battle(g.PRNG),
190
+ player: u8,
191
+ request: u8,
192
+ out: [*]u8,
193
+ n: usize,
194
+ ) callconv(.C) u8 {
195
+ assert(player <= @field(@typeInfo(pkmn.Player), @tagName(Enum)).fields.len);
196
+ assert(request <= @field(@typeInfo(pkmn.Choice.Type), @tagName(Enum)).fields.len);
197
+
198
+ assert(!pkmn.options.showdown or n > 0);
199
+ return battle.choices(@enumFromInt(player), @enumFromInt(request), @ptrCast(out[0..n]));
200
+ }
201
+ };
202
+ }
203
+
204
+ pub fn exports() type {
205
+ @export(choice_init, .{ .name = "pkmn_choice_init", .linkage = .Strong });
206
+ @export(choice_type, .{ .name = "pkmn_choice_type", .linkage = .Strong });
207
+ @export(choice_data, .{ .name = "pkmn_choice_data", .linkage = .Strong });
208
+
209
+ @export(result_type, .{ .name = "pkmn_result_type", .linkage = .Strong });
210
+ @export(result_p1, .{ .name = "pkmn_result_p1", .linkage = .Strong });
211
+ @export(result_p2, .{ .name = "pkmn_result_p2", .linkage = .Strong });
212
+
213
+ @export(err, .{ .name = "pkmn_error", .linkage = .Strong });
214
+
215
+ @export(psrng_init, .{ .name = "pkmn_psrng_init", .linkage = .Strong });
216
+ @export(psrng_next, .{ .name = "pkmn_psrng_next", .linkage = .Strong });
217
+
218
+ @export(rational_init, .{ .name = "pkmn_rational_init", .linkage = .Strong });
219
+ @export(rational_reduce, .{ .name = "pkmn_rational_reduce", .linkage = .Strong });
220
+ @export(rational_numerator, .{ .name = "pkmn_rational_numerator", .linkage = .Strong });
221
+ @export(rational_denominator, .{ .name = "pkmn_rational_denominator", .linkage = .Strong });
222
+
223
+ @export(
224
+ gen(1).battle_options_set,
225
+ .{ .name = "pkmn_gen1_battle_options_set", .linkage = .Strong },
226
+ );
227
+ @export(
228
+ gen(1).battle_options_chance_probability,
229
+ .{ .name = "pkmn_gen1_battle_options_chance_probability", .linkage = .Strong },
230
+ );
231
+ @export(
232
+ gen(1).battle_options_chance_actions,
233
+ .{ .name = "pkmn_gen1_battle_options_chance_actions", .linkage = .Strong },
234
+ );
235
+ @export(
236
+ gen(1).battle_options_chance_durations,
237
+ .{ .name = "pkmn_gen1_battle_options_chance_durations", .linkage = .Strong },
238
+ );
239
+ @export(
240
+ gen(1).battle_options_calc_summaries,
241
+ .{ .name = "pkmn_gen1_battle_options_calc_summaries", .linkage = .Strong },
242
+ );
243
+
244
+ @export(
245
+ gen(1).battle_update,
246
+ .{ .name = "pkmn_gen1_battle_update", .linkage = .Strong },
247
+ );
248
+ @export(
249
+ gen(1).battle_choices,
250
+ .{ .name = "pkmn_gen1_battle_choices", .linkage = .Strong },
251
+ );
252
+
253
+ return struct {};
254
+ }
@@ -1,7 +1,6 @@
1
- const std = @import("std");
2
- const pkmn = @import("../pkmn.zig");
3
-
4
1
  const js = @import("../common/js.zig");
2
+ const pkmn = @import("../pkmn.zig");
3
+ const std = @import("std");
5
4
 
6
5
  const assert = std.debug.assert;
7
6
 
@@ -10,16 +9,8 @@ const c = @cImport({
10
9
  @cInclude("node_api.h");
11
10
  });
12
11
 
13
- export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi_value {
14
- const properties = [_]c.napi_property_descriptor{
15
- js.Property.init("engine", .{ .value = register(env) }),
16
- };
17
- assert(c.napi_define_properties(env, exports, properties.len, &properties) == c.napi_ok);
18
- return exports;
19
- }
20
-
21
12
  pub fn register(env: c.napi_env) c.napi_value {
22
- var object = js.Object.init(env);
13
+ const object = js.Object.init(env);
23
14
  const properties = [_]c.napi_property_descriptor{
24
15
  js.Property.init("options", .{ .value = options(env) }),
25
16
  js.Property.init("bindings", .{ .value = bindings(env) }),
@@ -29,7 +20,7 @@ pub fn register(env: c.napi_env) c.napi_value {
29
20
  }
30
21
 
31
22
  fn options(env: c.napi_env) c.napi_value {
32
- var object = js.Object.init(env);
23
+ const object = js.Object.init(env);
33
24
  const properties = [_]c.napi_property_descriptor{
34
25
  js.Property.init("showdown", .{ .value = js.Boolean.init(env, pkmn.options.showdown) }),
35
26
  js.Property.init("log", .{ .value = js.Boolean.init(env, pkmn.options.log) }),
@@ -41,7 +32,7 @@ fn options(env: c.napi_env) c.napi_value {
41
32
  }
42
33
 
43
34
  fn bindings(env: c.napi_env) c.napi_value {
44
- var array = js.Array.init(env, .{ .length = 1 });
35
+ const array = js.Array.init(env, .{ .length = 1 });
45
36
  js.Array.set(env, array, 0, bind(env, pkmn.gen1));
46
37
  return array;
47
38
  }
@@ -49,7 +40,7 @@ fn bindings(env: c.napi_env) c.napi_value {
49
40
  fn bind(env: c.napi_env, gen: anytype) c.napi_value {
50
41
  const choices_size: u32 = @intCast(gen.CHOICES_SIZE);
51
42
  const logs_size: u32 = @intCast(gen.LOGS_SIZE);
52
- var object = js.Object.init(env);
43
+ const object = js.Object.init(env);
53
44
  const properties = [_]c.napi_property_descriptor{
54
45
  js.Property.init("CHOICES_SIZE", .{ .value = js.Number.init(env, choices_size) }),
55
46
  js.Property.init("LOGS_SIZE", .{ .value = js.Number.init(env, logs_size) }),
@@ -72,7 +63,6 @@ fn update(gen: anytype) c.napi_callback {
72
63
  var len: usize = 0;
73
64
  assert(c.napi_get_arraybuffer_info(env, argv[0], &data, &len) == c.napi_ok);
74
65
  assert(len == @sizeOf(gen.Battle(gen.PRNG)));
75
- assert(data != null);
76
66
 
77
67
  var battle: *gen.Battle(gen.PRNG) = @alignCast(@ptrCast(data.?));
78
68
  const c1: pkmn.Choice = @bitCast(js.Number.get(env, argv[1], u8));
@@ -85,9 +75,8 @@ fn update(gen: anytype) c.napi_callback {
85
75
  else => result: {
86
76
  assert(c.napi_get_arraybuffer_info(env, argv[3], &data, &len) == c.napi_ok);
87
77
  assert(len == gen.LOGS_SIZE);
88
- assert(data != null);
89
78
 
90
- var buf = @as([*]u8, @ptrCast(data.?))[0..gen.LOGS_SIZE];
79
+ const buf = @as([*]u8, @ptrCast(data.?))[0..gen.LOGS_SIZE];
91
80
  var stream: pkmn.protocol.ByteStream = .{ .buffer = buf };
92
81
  // TODO: extract out
93
82
  var opts = pkmn.battle.options(
@@ -116,7 +105,6 @@ fn choices(gen: anytype) c.napi_callback {
116
105
  var len: usize = 0;
117
106
  assert(c.napi_get_arraybuffer_info(env, argv[0], &data, &len) == c.napi_ok);
118
107
  assert(len == @sizeOf(gen.Battle(gen.PRNG)));
119
- assert(data != null);
120
108
 
121
109
  var battle: *gen.Battle(gen.PRNG) = @alignCast(@ptrCast(data.?));
122
110
  const player: pkmn.Player = @enumFromInt(js.Number.get(env, argv[1], u8));
@@ -124,9 +112,8 @@ fn choices(gen: anytype) c.napi_callback {
124
112
 
125
113
  assert(c.napi_get_arraybuffer_info(env, argv[3], &data, &len) == c.napi_ok);
126
114
  assert(len == gen.CHOICES_SIZE);
127
- assert(data != null);
128
115
 
129
- var out = @as([*]pkmn.Choice, @ptrCast(data.?))[0..gen.CHOICES_SIZE];
116
+ const out = @as([*]pkmn.Choice, @ptrCast(data.?))[0..gen.CHOICES_SIZE];
130
117
  const n = battle.choices(player, request, out);
131
118
  return js.Number.init(env, @as(u8, @bitCast(n)));
132
119
  }