@pkmn/engine 0.1.0-dev.8b83af6b → 0.1.0-dev.8c935a85

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 (86) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +100 -61
  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 +25 -3
  13. package/build/pkg/addon.js +39 -70
  14. package/build/pkg/addon.js.map +1 -1
  15. package/build/pkg/data/ids.json +12 -12
  16. package/build/pkg/data/layout.json +39 -4
  17. package/build/pkg/data/protocol.json +84 -13
  18. package/build/pkg/data.d.ts +27 -5
  19. package/build/pkg/data.js.map +1 -1
  20. package/build/pkg/gen1.d.ts +15 -18
  21. package/build/pkg/gen1.js +43 -37
  22. package/build/pkg/gen1.js.map +1 -1
  23. package/build/pkg/index.d.ts +42 -91
  24. package/build/pkg/index.js +23 -70
  25. package/build/pkg/index.js.map +1 -1
  26. package/build/pkg/protocol.d.ts +20 -1
  27. package/build/pkg/protocol.js +123 -102
  28. package/build/pkg/protocol.js.map +1 -1
  29. package/build/tools/debug.js +53 -76
  30. package/build/tools/debug.js.map +1 -1
  31. package/build/tools/display/debug.jsx +152 -0
  32. package/build/tools/display/debug.jsx.map +1 -0
  33. package/build/tools/display/index.js +152 -0
  34. package/build/tools/display/index.js.map +1 -0
  35. package/build/tools/display/ui.jsx +359 -0
  36. package/build/tools/display/ui.jsx.map +1 -0
  37. package/build/tools/display/util.js +33 -0
  38. package/build/tools/display/util.js.map +1 -0
  39. package/build.zig +400 -132
  40. package/package.json +69 -121
  41. package/src/bin/install-pkmn-engine +41 -25
  42. package/src/bin/pkmn-debug +1 -1
  43. package/src/lib/bindings/c.zig +255 -0
  44. package/src/lib/bindings/node.zig +121 -0
  45. package/src/lib/bindings/wasm.zig +59 -0
  46. package/src/lib/common/array.zig +77 -0
  47. package/src/lib/common/battle.zig +17 -0
  48. package/src/lib/common/data.zig +12 -24
  49. package/src/lib/common/debug.zig +58 -18
  50. package/src/lib/common/js.zig +120 -0
  51. package/src/lib/common/optional.zig +71 -0
  52. package/src/lib/common/options.zig +15 -0
  53. package/src/lib/common/protocol.zig +851 -327
  54. package/src/lib/common/rational.zig +522 -0
  55. package/src/lib/common/rng.zig +26 -19
  56. package/src/lib/common/util.zig +71 -0
  57. package/src/lib/gen1/calc.zig +962 -0
  58. package/src/lib/gen1/chance.zig +1185 -0
  59. package/src/lib/gen1/data/moves.zig +193 -183
  60. package/src/lib/gen1/data/species.zig +4 -6
  61. package/src/lib/gen1/data/types.zig +8 -9
  62. package/src/lib/gen1/data.zig +79 -73
  63. package/src/lib/gen1/helpers.zig +130 -30
  64. package/src/lib/gen1/mechanics.zig +1137 -786
  65. package/src/lib/gen2/calc.zig +153 -0
  66. package/src/lib/gen2/chance.zig +902 -0
  67. package/src/lib/gen2/data/items.zig +13 -21
  68. package/src/lib/gen2/data/moves.zig +664 -572
  69. package/src/lib/gen2/data/species.zig +2 -4
  70. package/src/lib/gen2/data/types.zig +135 -33
  71. package/src/lib/gen2/data.zig +121 -87
  72. package/src/lib/gen2/generated.zig +801 -0
  73. package/src/lib/gen2/helpers.zig +54 -39
  74. package/src/lib/gen2/mechanics.zig +3582 -30
  75. package/src/lib/node.zig +18 -0
  76. package/src/lib/pkmn.zig +86 -5
  77. package/src/lib/wasm.zig +17 -0
  78. package/src/tools/display/dom.ts +93 -0
  79. package/src/tools/display/ui.css +354 -0
  80. package/build/test/display.js +0 -400
  81. package/build/test/display.js.map +0 -1
  82. package/src/lib/binding/node.zig +0 -226
  83. package/src/lib/binding/wasm.zig +0 -10
  84. package/src/lib/gen1/README.md +0 -814
  85. package/src/lib/gen2/README.md +0 -309
  86. 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.8b83af6b",
3
+ "version": "0.1.0-dev.8c935a85",
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,33 +39,53 @@
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",
56
+ "src/lib/common/battle.zig",
37
57
  "src/lib/common/data.zig",
38
58
  "src/lib/common/debug.zig",
59
+ "src/lib/common/js.zig",
60
+ "src/lib/common/optional.zig",
39
61
  "src/lib/common/options.zig",
40
62
  "src/lib/common/protocol.zig",
63
+ "src/lib/common/rational.zig",
41
64
  "src/lib/common/rng.zig",
65
+ "src/lib/common/util.zig",
66
+ "src/lib/gen1/calc.zig",
67
+ "src/lib/gen1/chance.zig",
42
68
  "src/lib/gen1/data.zig",
43
69
  "src/lib/gen1/data/moves.zig",
44
70
  "src/lib/gen1/data/species.zig",
45
71
  "src/lib/gen1/data/types.zig",
46
72
  "src/lib/gen1/helpers.zig",
47
73
  "src/lib/gen1/mechanics.zig",
74
+ "src/lib/gen2/calc.zig",
75
+ "src/lib/gen2/chance.zig",
48
76
  "src/lib/gen2/data.zig",
49
77
  "src/lib/gen2/data/items.zig",
50
78
  "src/lib/gen2/data/moves.zig",
51
79
  "src/lib/gen2/data/species.zig",
52
80
  "src/lib/gen2/data/types.zig",
81
+ "src/lib/gen2/generated.zig",
53
82
  "src/lib/gen2/helpers.zig",
54
83
  "src/lib/gen2/mechanics.zig",
84
+ "src/lib/node.zig",
55
85
  "src/lib/pkmn.zig",
56
- "src/test/display/pkmn.html.tmpl"
86
+ "src/lib/wasm.zig",
87
+ "src/tools/display/dom.ts",
88
+ "src/tools/display/ui.css"
57
89
  ],
58
90
  "engines": {
59
91
  "node": ">=16.0.0"
@@ -66,138 +98,54 @@
66
98
  "access": "public"
67
99
  },
68
100
  "dependencies": {
69
- "@pkmn/data": "^0.7.44",
70
- "@pkmn/protocol": "^0.6.12"
101
+ "@pkmn/data": "^0.9.28",
102
+ "@pkmn/protocol": "^0.6.30"
71
103
  },
72
104
  "devDependencies": {
73
- "@pkmn/eslint-config": "^3.2.0",
74
- "@pkmn/img": "^0.2.12",
75
- "@pkmn/sets": "^5.0.4",
76
- "@pkmn/sim": "0.7.44",
77
- "@types/html-minifier": "^4.0.2",
78
- "@types/jest": "^29.5.2",
79
- "@types/minimist": "^1.2.2",
80
- "@types/mustache": "^4.2.2",
81
- "@types/node": "^20.3.1",
82
- "@vitest/coverage-c8": "^0.32.2",
83
- "binaryen": "^113.0.0",
84
- "eslint": "^8.43.0",
105
+ "@pkmn/eslint-config": "^9.6.0",
106
+ "@pkmn/img": "^0.2.34",
107
+ "@pkmn/sets": "^5.1.2",
108
+ "@pkmn/sim": "0.9.28",
109
+ "@pkmn/smogon": "^0.5.18",
110
+ "@types/html-minifier": "^4.0.5",
111
+ "@types/jest": "^29.5.14",
112
+ "@types/minimist": "^1.2.5",
113
+ "@types/mustache": "^4.2.5",
114
+ "@types/node": "^22.13.0",
115
+ "@types/react": "<=18",
116
+ "@types/semver": "^7.5.8",
117
+ "@types/vscode": "^1.96.0",
118
+ "@vitest/coverage-v8": "^3.0.5",
119
+ "@vscode/vsce": "^3.2.2",
120
+ "binaryen": "^122.0.0",
121
+ "esbuild": "^0.24.2",
122
+ "eslint": "^9.19.0",
85
123
  "html-minifier": "^4.0.0",
86
124
  "json-stringify-pretty-compact": "3.0.0",
87
125
  "minimist": "^1.2.8",
88
126
  "mustache": "^4.2.0",
127
+ "semver": "^7.7.0",
89
128
  "source-map-support": "^0.5.21",
129
+ "table": "^6.9.0",
90
130
  "trakr": "^0.2.0",
91
- "typescript": "^5.1.3",
92
- "vitest": "^0.32.2"
131
+ "typescript": "^5.7.3",
132
+ "vitest": "^3.0.5"
93
133
  },
94
134
  "scripts": {
95
- "lint": "eslint --cache src --ext ts,js && eslint src/bin/*",
96
- "fix": "eslint --fix src --ext ts,js && eslint --fix src/bin/*",
135
+ "lint": "eslint --cache src",
136
+ "fix": "eslint --fix src",
97
137
  "compile": "tsc -p .",
98
138
  "build": "npm run compile",
99
139
  "test": "vitest src/pkg",
100
140
  "test:integration": "vitest src/test",
101
141
  "debug": "npm run compile && node build/tools/debug",
142
+ "demo": "npm run compile && node build/tools/demo",
102
143
  "fuzz": "npm run compile && node build/test/fuzz",
103
144
  "generate": "npm run compile && node build/tools/generate",
104
145
  "release": "npm run compile && node build/tools/release",
105
146
  "benchmark": "npm run compile && node build/test/benchmark",
106
147
  "integration": "npm run compile && node build/test/integration",
148
+ "extension": "npm -C src/tools/vscode run build",
107
149
  "postinstall": "node src/bin/install-pkmn-engine"
108
- },
109
- "eslintConfig": {
110
- "extends": "@pkmn",
111
- "ignorePatterns": [
112
- "dist/",
113
- "node_modules/",
114
- "src/examples/zig",
115
- "build/"
116
- ],
117
- "env": {
118
- "es6": true,
119
- "node": true,
120
- "browser": true
121
- },
122
- "overrides": [
123
- {
124
- "files": [
125
- "**/*.ts"
126
- ],
127
- "parserOptions": {
128
- "project": [
129
- "./tsconfig.json",
130
- "./src/examples/js/tsconfig.json"
131
- ]
132
- }
133
- },
134
- {
135
- "files": [
136
- "src/pkg/index.ts",
137
- "src/test/display.ts",
138
- "src/test/integration.ts"
139
- ],
140
- "rules": {
141
- "no-control-regex": "off",
142
- "@typescript-eslint/no-empty-interface": "off",
143
- "@typescript-eslint/no-shadow": "off"
144
- }
145
- },
146
- {
147
- "files": [
148
- "src/pkg/addon.ts"
149
- ],
150
- "rules": {
151
- "@typescript-eslint/no-var-requires": "off"
152
- }
153
- },
154
- {
155
- "files": [
156
- "src/test/benchmark*.ts"
157
- ],
158
- "rules": {
159
- "@typescript-eslint/no-unused-vars": "off"
160
- }
161
- },
162
- {
163
- "files": [
164
- "src/test/*.test.ts",
165
- "src/test/regression/*.test.ts"
166
- ],
167
- "rules": {
168
- "jest/no-standalone-expect": "off"
169
- }
170
- },
171
- {
172
- "files": [
173
- "src/test/showdown/**"
174
- ],
175
- "rules": {
176
- "jest/expect-expect": [
177
- "warn",
178
- {
179
- "assertFunctionNames": [
180
- "expect",
181
- "expectLog",
182
- "verify"
183
- ]
184
- }
185
- ]
186
- }
187
- },
188
- {
189
- "files": [
190
- "src/tools/generate.ts"
191
- ],
192
- "rules": {
193
- "@typescript-eslint/restrict-template-expressions": [
194
- "error",
195
- {
196
- "allowBoolean": true
197
- }
198
- ]
199
- }
200
- }
201
- ]
202
150
  }
203
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, dev: 3859};
13
+ const ZIG_VERSION = {major: 0, minor: 11, 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';
@@ -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) {
@@ -323,6 +325,7 @@ const downloadImportLib = async () => {
323
325
  const libs = path.join(ROOT, 'build', 'lib');
324
326
  if (fs.existsSync(libs)) {
325
327
  for (const file of fs.readdirSync(libs)) {
328
+ if (!file.startsWith('pkmn')) continue;
326
329
  const type = path.extname(file).slice(1);
327
330
  if (type !== 'node' && type !== 'wasm') continue;
328
331
  // If we don't copy the addon before loading it Windows will return an
@@ -336,14 +339,18 @@ const downloadImportLib = async () => {
336
339
  node = true;
337
340
  if (!options) {
338
341
  const addon = require(copy);
339
- if (addon.options.showdown) opts.push('-Dshowdown');
340
- if (addon.options.log) opts.push('-Dlog');
342
+ if (addon.engine.options.showdown) opts.push('-Dshowdown');
343
+ if (addon.engine.options.log) opts.push('-Dlog');
344
+ if (addon.engine.options.chance) opts.push('-Dchance');
345
+ if (addon.engine.options.calc) opts.push('-Dcalc');
341
346
  }
342
347
  } else if (!options) {
343
348
  const addon = await WebAssembly.instantiate(fs.readFileSync(copy));
344
349
  const values = new Uint8Array(addon.instance.exports.memory.buffer);
345
350
  if (values[addon.instance.exports.SHOWDOWN.value]) opts.push('-Dshowdown');
346
351
  if (values[addon.instance.exports.LOG.value]) opts.push('-Dlog');
352
+ if (values[addon.instance.exports.CHANCE.value]) opts.push('-Dchance');
353
+ if (values[addon.instance.exports.CALC.value]) opts.push('-Dcalc');
347
354
  }
348
355
  const key = `${type} ${opts.sort().join(' ')}`;
349
356
  if (!configs.has(key)) configs.set(key, {type, options: opts});
@@ -354,8 +361,9 @@ const downloadImportLib = async () => {
354
361
  // either the default options or whatever was passed in
355
362
  if (!configs.size) {
356
363
  node = true;
357
- configs.set('node', {type: 'node', options: options || ['-Dshowdown']});
358
- configs.set('wasm', {type: 'wasm', options: options || ['-Dshowdown']});
364
+ const DEFAULT = ['-Dshowdown'];
365
+ configs.set('node', {type: 'node', options: options || DEFAULT});
366
+ configs.set('wasm', {type: 'wasm', options: options || DEFAULT});
359
367
  }
360
368
 
361
369
  const headers = node ? await downloadHeaders() : undefined;
@@ -365,8 +373,10 @@ const downloadImportLib = async () => {
365
373
  const args = ['build', '-p', 'build', ...opts];
366
374
  if (!process.env.DEBUG_PKMN_ENGINE) args.push('-Doptimize=ReleaseFast', '-Dstrip');
367
375
  if (config.type === 'node') {
368
- args.push(`-Dnode-headers=${headers}`);
369
- if (process.platform === 'win32') args.push(`-Dnode-import-library=${lib}`);
376
+ args.push(`-Dnode-headers=${path.relative(ROOT, headers)}`);
377
+ if (process.platform === 'win32') {
378
+ args.push(`-Dnode-import-library=${path.relative(ROOT, lib)}`);
379
+ }
370
380
  } else {
371
381
  args.push('-Dwasm');
372
382
  }
@@ -381,8 +391,14 @@ const downloadImportLib = async () => {
381
391
  const prefix = process.platform === 'win32' ? '' : 'lib';
382
392
  const ext = process.platform === 'darwin'
383
393
  ? 'dylib' : process.platform === 'win32' ? 'dll' : 'so';
384
- const actual = path.join('build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
385
- fs.renameSync(path.join(ROOT, actual), path.join(ROOT, artifact));
394
+ try {
395
+ const actual = path.join(ROOT, 'build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
396
+ fs.renameSync(actual, artifact);
397
+ } catch {
398
+ // ziglang/zig#19743 changed this path
399
+ const actual = path.join(ROOT, 'build', 'bin', `${prefix}pkmn${suffix}.node.${ext}`);
400
+ fs.renameSync(actual, artifact);
401
+ }
386
402
  }
387
403
  }
388
404
  })().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,255 @@
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
+ const Strong = if (@hasField(std.builtin.GlobalLinkage, "strong")) .strong else .Strong;
10
+
11
+ pub const OPTIONS: extern struct {
12
+ showdown: bool,
13
+ log: bool,
14
+ chance: bool,
15
+ calc: bool,
16
+ } = .{
17
+ .showdown = pkmn.options.showdown,
18
+ .log = pkmn.options.log,
19
+ .chance = pkmn.options.chance,
20
+ .calc = pkmn.options.calc,
21
+ };
22
+
23
+ pub const MAX_CHOICES = pkmn.MAX_CHOICES;
24
+ pub const CHOICES_SIZE = pkmn.CHOICES_SIZE;
25
+ pub const MAX_LOGS = pkmn.MAX_LOGS;
26
+ pub const LOGS_SIZE = pkmn.LOGS_SIZE;
27
+
28
+ pub fn choice_init(choice: u8, data: u8) callconv(.C) u8 {
29
+ assert(choice <= @field(@typeInfo(pkmn.Choice.Type), @tagName(Enum)).fields.len);
30
+ assert(data <= 6);
31
+ return @bitCast(pkmn.Choice{ .type = @enumFromInt(choice), .data = @intCast(data) });
32
+ }
33
+
34
+ pub fn choice_type(choice: u8) callconv(.C) u8 {
35
+ return @intFromEnum(@as(pkmn.Choice, @bitCast(choice)).type);
36
+ }
37
+
38
+ pub fn choice_data(choice: u8) callconv(.C) u8 {
39
+ return @as(u8, @as(pkmn.Choice, @bitCast(choice)).data);
40
+ }
41
+
42
+ pub fn result_type(result: u8) callconv(.C) u8 {
43
+ return @intFromEnum(@as(pkmn.Result, @bitCast(result)).type);
44
+ }
45
+
46
+ pub fn result_p1(result: u8) callconv(.C) u8 {
47
+ assert(!err(result));
48
+ return @intFromEnum(@as(pkmn.Result, @bitCast(result)).p1);
49
+ }
50
+
51
+ pub fn result_p2(result: u8) callconv(.C) u8 {
52
+ assert(!err(result));
53
+ return @intFromEnum(@as(pkmn.Result, @bitCast(result)).p2);
54
+ }
55
+
56
+ pub fn err(result: u8) callconv(.C) bool {
57
+ return result == ERROR;
58
+ }
59
+
60
+ pub fn psrng_init(prng: *pkmn.PSRNG, seed: u64) callconv(.C) void {
61
+ prng.src = .{ .seed = seed };
62
+ }
63
+
64
+ pub fn psrng_next(prng: *pkmn.PSRNG) callconv(.C) u32 {
65
+ return prng.next();
66
+ }
67
+
68
+ pub fn rational_init(rational: *pkmn.Rational(f64)) callconv(.C) void {
69
+ rational.reset();
70
+ }
71
+
72
+ pub fn rational_reduce(rational: *pkmn.Rational(f64)) callconv(.C) void {
73
+ rational.reduce();
74
+ }
75
+
76
+ pub fn rational_numerator(rational: *const pkmn.Rational(f64)) callconv(.C) f64 {
77
+ return rational.p;
78
+ }
79
+
80
+ pub fn rational_denominator(rational: *const pkmn.Rational(f64)) callconv(.C) f64 {
81
+ return rational.q;
82
+ }
83
+
84
+ const log_options = extern struct {
85
+ buf: [*]u8,
86
+ len: usize,
87
+ };
88
+
89
+ pub fn gen(comptime num: comptime_int) type {
90
+ const g = @field(pkmn, "gen" ++ std.fmt.comptimePrint("{d}", .{num}));
91
+
92
+ return struct {
93
+ pub const MAX_CHOICES = g.MAX_CHOICES;
94
+ pub const CHOICES_SIZE = g.CHOICES_SIZE;
95
+ pub const MAX_LOGS = g.MAX_LOGS;
96
+ pub const LOGS_SIZE = g.LOGS_SIZE;
97
+
98
+ const chance_options = extern struct {
99
+ probability: pkmn.Rational(f64),
100
+ actions: g.chance.Actions,
101
+ durations: g.chance.Durations,
102
+ };
103
+
104
+ const calc_options = extern struct {
105
+ overrides: g.chance.Actions,
106
+ };
107
+
108
+ const battle_options = struct {
109
+ stream: pkmn.protocol.ByteStream,
110
+ log: pkmn.protocol.FixedLog,
111
+ chance: g.Chance(pkmn.Rational(f64)),
112
+ calc: g.Calc,
113
+
114
+ comptime {
115
+ assert(@sizeOf(battle_options) <= 128);
116
+ }
117
+ };
118
+
119
+ pub fn battle_options_set(
120
+ options: *battle_options,
121
+ log: ?*const log_options,
122
+ chance: ?*const chance_options,
123
+ calc: ?*const calc_options,
124
+ ) callconv(.C) void {
125
+ if (pkmn.options.log) {
126
+ if (log) |l| {
127
+ options.stream = .{ .buffer = l.buf[0..l.len] };
128
+ options.log = .{ .writer = options.stream.writer() };
129
+ } else {
130
+ options.stream.reset();
131
+ }
132
+ }
133
+ if (pkmn.options.chance) {
134
+ if (chance) |c| {
135
+ options.chance = .{
136
+ .probability = c.probability,
137
+ .actions = c.actions,
138
+ .durations = c.durations,
139
+ };
140
+ } else {
141
+ options.chance.reset();
142
+ }
143
+ }
144
+ if (pkmn.options.calc) {
145
+ if (calc) |c| {
146
+ options.calc = .{ .overrides = c.overrides };
147
+ } else {
148
+ options.calc = .{};
149
+ }
150
+ }
151
+ }
152
+
153
+ pub fn battle_options_chance_probability(
154
+ options: *battle_options,
155
+ ) callconv(.C) *pkmn.Rational(f64) {
156
+ return &options.chance.probability;
157
+ }
158
+
159
+ pub fn battle_options_chance_actions(
160
+ options: *battle_options,
161
+ ) callconv(.C) *g.chance.Actions {
162
+ return &options.chance.actions;
163
+ }
164
+
165
+ pub fn battle_options_chance_durations(
166
+ options: *battle_options,
167
+ ) callconv(.C) *g.chance.Durations {
168
+ return &options.chance.durations;
169
+ }
170
+
171
+ pub fn battle_options_calc_summaries(
172
+ options: *battle_options,
173
+ ) callconv(.C) *g.calc.Summaries {
174
+ return &options.calc.summaries;
175
+ }
176
+
177
+ pub fn battle_update(
178
+ battle: *g.Battle(g.PRNG),
179
+ c1: pkmn.Choice,
180
+ c2: pkmn.Choice,
181
+ opts: ?*battle_options,
182
+ ) callconv(.C) pkmn.Result {
183
+ if ((pkmn.options.log or pkmn.options.chance or pkmn.options.calc) and opts != null) {
184
+ return battle.update(c1, c2, opts.?) catch return @bitCast(ERROR);
185
+ }
186
+ return battle.update(c1, c2, &g.NULL) catch unreachable;
187
+ }
188
+
189
+ pub fn battle_choices(
190
+ battle: *const g.Battle(g.PRNG),
191
+ player: u8,
192
+ request: u8,
193
+ out: [*]u8,
194
+ n: usize,
195
+ ) callconv(.C) u8 {
196
+ assert(player <= @field(@typeInfo(pkmn.Player), @tagName(Enum)).fields.len);
197
+ assert(request <= @field(@typeInfo(pkmn.Choice.Type), @tagName(Enum)).fields.len);
198
+
199
+ assert(!pkmn.options.showdown or n > 0);
200
+ return battle.choices(@enumFromInt(player), @enumFromInt(request), @ptrCast(out[0..n]));
201
+ }
202
+ };
203
+ }
204
+
205
+ pub fn exports() type {
206
+ @export(choice_init, .{ .name = "pkmn_choice_init", .linkage = Strong });
207
+ @export(choice_type, .{ .name = "pkmn_choice_type", .linkage = Strong });
208
+ @export(choice_data, .{ .name = "pkmn_choice_data", .linkage = Strong });
209
+
210
+ @export(result_type, .{ .name = "pkmn_result_type", .linkage = Strong });
211
+ @export(result_p1, .{ .name = "pkmn_result_p1", .linkage = Strong });
212
+ @export(result_p2, .{ .name = "pkmn_result_p2", .linkage = Strong });
213
+
214
+ @export(err, .{ .name = "pkmn_error", .linkage = Strong });
215
+
216
+ @export(psrng_init, .{ .name = "pkmn_psrng_init", .linkage = Strong });
217
+ @export(psrng_next, .{ .name = "pkmn_psrng_next", .linkage = Strong });
218
+
219
+ @export(rational_init, .{ .name = "pkmn_rational_init", .linkage = Strong });
220
+ @export(rational_reduce, .{ .name = "pkmn_rational_reduce", .linkage = Strong });
221
+ @export(rational_numerator, .{ .name = "pkmn_rational_numerator", .linkage = Strong });
222
+ @export(rational_denominator, .{ .name = "pkmn_rational_denominator", .linkage = Strong });
223
+
224
+ @export(
225
+ gen(1).battle_options_set,
226
+ .{ .name = "pkmn_gen1_battle_options_set", .linkage = Strong },
227
+ );
228
+ @export(
229
+ gen(1).battle_options_chance_probability,
230
+ .{ .name = "pkmn_gen1_battle_options_chance_probability", .linkage = Strong },
231
+ );
232
+ @export(
233
+ gen(1).battle_options_chance_actions,
234
+ .{ .name = "pkmn_gen1_battle_options_chance_actions", .linkage = Strong },
235
+ );
236
+ @export(
237
+ gen(1).battle_options_chance_durations,
238
+ .{ .name = "pkmn_gen1_battle_options_chance_durations", .linkage = Strong },
239
+ );
240
+ @export(
241
+ gen(1).battle_options_calc_summaries,
242
+ .{ .name = "pkmn_gen1_battle_options_calc_summaries", .linkage = Strong },
243
+ );
244
+
245
+ @export(
246
+ gen(1).battle_update,
247
+ .{ .name = "pkmn_gen1_battle_update", .linkage = Strong },
248
+ );
249
+ @export(
250
+ gen(1).battle_choices,
251
+ .{ .name = "pkmn_gen1_battle_choices", .linkage = Strong },
252
+ );
253
+
254
+ return struct {};
255
+ }