@pkmn/engine 0.1.0-dev.deda8593 → 0.1.0-dev.e0a786f8
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.
- package/README.md +9 -6
- package/build/pkg/addon/browser.d.ts +3 -0
- package/build/pkg/addon/browser.js +47 -0
- package/build/pkg/addon/browser.js.map +1 -0
- package/build/pkg/addon/node.d.ts +3 -0
- package/build/pkg/addon/node.js +110 -0
- package/build/pkg/addon/node.js.map +1 -0
- package/build/pkg/addon/wasm.d.ts +2 -0
- package/build/pkg/addon/wasm.js +53 -0
- package/build/pkg/addon/wasm.js.map +1 -0
- package/build/pkg/addon.d.ts +25 -3
- package/build/pkg/addon.js +34 -65
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/layout.json +15 -2
- package/build/pkg/data/protocol.json +23 -9
- package/build/pkg/data.d.ts +23 -1
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.d.ts +15 -18
- package/build/pkg/gen1.js +28 -19
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +40 -90
- package/build/pkg/index.js +23 -70
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +20 -1
- package/build/pkg/protocol.js +105 -103
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +52 -76
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/debug.jsx +152 -0
- package/build/tools/display/debug.jsx.map +1 -0
- package/build/tools/display/index.js +152 -0
- package/build/tools/display/index.js.map +1 -0
- package/build/tools/display/ui.jsx +359 -0
- package/build/tools/display/ui.jsx.map +1 -0
- package/build/tools/display/util.js +33 -0
- package/build/tools/display/util.js.map +1 -0
- package/build.zig +330 -85
- package/package.json +54 -135
- package/src/bin/install-pkmn-engine +10 -7
- package/src/bin/pkmn-debug +1 -1
- package/src/lib/bindings/c.zig +255 -0
- package/src/lib/bindings/node.zig +121 -0
- package/src/lib/bindings/wasm.zig +59 -0
- package/src/lib/common/array.zig +77 -0
- package/src/lib/common/data.zig +8 -8
- package/src/lib/common/debug.zig +39 -8
- package/src/lib/common/js.zig +4 -2
- package/src/lib/common/optional.zig +13 -9
- package/src/lib/common/options.zig +4 -0
- package/src/lib/common/protocol.zig +45 -44
- package/src/lib/common/rational.zig +323 -157
- package/src/lib/common/rng.zig +5 -7
- package/src/lib/common/util.zig +60 -1
- package/src/lib/gen1/calc.zig +527 -161
- package/src/lib/gen1/chance.zig +366 -240
- package/src/lib/gen1/data/moves.zig +2 -4
- package/src/lib/gen1/data/species.zig +1 -3
- package/src/lib/gen1/data/types.zig +1 -2
- package/src/lib/gen1/data.zig +35 -38
- package/src/lib/gen1/helpers.zig +17 -554
- package/src/lib/gen1/mechanics.zig +280 -193
- package/src/lib/gen2/calc.zig +37 -27
- package/src/lib/gen2/chance.zig +90 -503
- package/src/lib/gen2/data/items.zig +1 -3
- package/src/lib/gen2/data/moves.zig +2 -4
- package/src/lib/gen2/data/species.zig +1 -3
- package/src/lib/gen2/data/types.zig +1 -2
- package/src/lib/gen2/data.zig +26 -29
- package/src/lib/gen2/generated.zig +18 -23
- package/src/lib/gen2/helpers.zig +9 -18
- package/src/lib/gen2/mechanics.zig +88 -115
- package/src/lib/node.zig +3 -116
- package/src/lib/pkmn.zig +14 -7
- package/src/lib/wasm.zig +13 -9
- package/src/tools/display/dom.ts +93 -0
- package/src/tools/display/ui.css +354 -0
- package/build/test/display.js +0 -400
- package/build/test/display.js.map +0 -1
- 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.
|
|
3
|
+
"version": "0.1.0-dev.e0a786f8",
|
|
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,10 +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",
|
|
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",
|
|
34
56
|
"src/lib/common/battle.zig",
|
|
35
57
|
"src/lib/common/data.zig",
|
|
36
58
|
"src/lib/common/debug.zig",
|
|
@@ -62,7 +84,8 @@
|
|
|
62
84
|
"src/lib/node.zig",
|
|
63
85
|
"src/lib/pkmn.zig",
|
|
64
86
|
"src/lib/wasm.zig",
|
|
65
|
-
"src/
|
|
87
|
+
"src/tools/display/dom.ts",
|
|
88
|
+
"src/tools/display/ui.css"
|
|
66
89
|
],
|
|
67
90
|
"engines": {
|
|
68
91
|
"node": ">=16.0.0"
|
|
@@ -75,158 +98,54 @@
|
|
|
75
98
|
"access": "public"
|
|
76
99
|
},
|
|
77
100
|
"dependencies": {
|
|
78
|
-
"@pkmn/data": "^0.9.
|
|
79
|
-
"@pkmn/protocol": "^0.6.
|
|
101
|
+
"@pkmn/data": "^0.9.27",
|
|
102
|
+
"@pkmn/protocol": "^0.6.30"
|
|
80
103
|
},
|
|
81
104
|
"devDependencies": {
|
|
82
|
-
"@pkmn/eslint-config": "^
|
|
83
|
-
"@pkmn/img": "^0.2.
|
|
105
|
+
"@pkmn/eslint-config": "^9.5.0",
|
|
106
|
+
"@pkmn/img": "^0.2.34",
|
|
84
107
|
"@pkmn/sets": "^5.1.2",
|
|
85
|
-
"@pkmn/sim": "0.9.
|
|
108
|
+
"@pkmn/sim": "0.9.27",
|
|
109
|
+
"@pkmn/smogon": "^0.5.17",
|
|
86
110
|
"@types/html-minifier": "^4.0.5",
|
|
87
|
-
"@types/jest": "^29.5.
|
|
111
|
+
"@types/jest": "^29.5.14",
|
|
88
112
|
"@types/minimist": "^1.2.5",
|
|
89
113
|
"@types/mustache": "^4.2.5",
|
|
90
|
-
"@types/node": "^22.
|
|
91
|
-
"@
|
|
92
|
-
"
|
|
93
|
-
"
|
|
114
|
+
"@types/node": "^22.10.6",
|
|
115
|
+
"@types/react": "^18.3.12",
|
|
116
|
+
"@types/semver": "^7.5.8",
|
|
117
|
+
"@types/vscode": "^1.96.0",
|
|
118
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
119
|
+
"@vscode/vsce": "^3.2.1",
|
|
120
|
+
"binaryen": "^121.0.0",
|
|
121
|
+
"esbuild": "^0.24.2",
|
|
122
|
+
"eslint": "^9.18.0",
|
|
94
123
|
"html-minifier": "^4.0.0",
|
|
95
|
-
"json-stringify-pretty-compact": "
|
|
124
|
+
"json-stringify-pretty-compact": "3.0.0",
|
|
96
125
|
"minimist": "^1.2.8",
|
|
97
126
|
"mustache": "^4.2.0",
|
|
127
|
+
"semver": "^7.6.3",
|
|
98
128
|
"source-map-support": "^0.5.21",
|
|
99
|
-
"table": "^6.
|
|
129
|
+
"table": "^6.9.0",
|
|
100
130
|
"trakr": "^0.2.0",
|
|
101
|
-
"typescript": "^5.
|
|
102
|
-
"vitest": "^2.
|
|
131
|
+
"typescript": "^5.7.3",
|
|
132
|
+
"vitest": "^2.1.8"
|
|
103
133
|
},
|
|
104
134
|
"scripts": {
|
|
105
|
-
"lint": "eslint --cache src
|
|
106
|
-
"fix": "eslint --fix src
|
|
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/test/display.ts"
|
|
147
|
-
],
|
|
148
|
-
"rules": {
|
|
149
|
-
"@typescript-eslint/no-unnecessary-type-assertion": "off"
|
|
150
|
-
}
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
"files": [
|
|
154
|
-
"src/pkg/index.ts",
|
|
155
|
-
"src/test/display.ts",
|
|
156
|
-
"src/test/integration.ts"
|
|
157
|
-
],
|
|
158
|
-
"rules": {
|
|
159
|
-
"no-control-regex": "off",
|
|
160
|
-
"@typescript-eslint/no-empty-interface": "off",
|
|
161
|
-
"@typescript-eslint/no-shadow": "off",
|
|
162
|
-
"@typescript-eslint/no-unsafe-declaration-merging": "off"
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
"files": [
|
|
167
|
-
"src/pkg/addon.ts"
|
|
168
|
-
],
|
|
169
|
-
"rules": {
|
|
170
|
-
"@typescript-eslint/no-var-requires": "off"
|
|
171
|
-
}
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
"files": [
|
|
175
|
-
"src/test/benchmark*.ts"
|
|
176
|
-
],
|
|
177
|
-
"rules": {
|
|
178
|
-
"@typescript-eslint/no-unused-vars": "off",
|
|
179
|
-
"@typescript-eslint/no-redundant-type-constituents": "off"
|
|
180
|
-
}
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
"files": [
|
|
184
|
-
"src/pkg/protocol.test.ts"
|
|
185
|
-
],
|
|
186
|
-
"rules": {
|
|
187
|
-
"jest/no-standalone-expect": "off",
|
|
188
|
-
"jest/no-conditional-expect": "off"
|
|
189
|
-
}
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
"files": [
|
|
193
|
-
"src/test/*.test.ts",
|
|
194
|
-
"src/test/regression/*.test.ts"
|
|
195
|
-
],
|
|
196
|
-
"rules": {
|
|
197
|
-
"jest/no-standalone-expect": "off"
|
|
198
|
-
}
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
"files": [
|
|
202
|
-
"src/test/showdown/**"
|
|
203
|
-
],
|
|
204
|
-
"rules": {
|
|
205
|
-
"jest/expect-expect": [
|
|
206
|
-
"warn",
|
|
207
|
-
{
|
|
208
|
-
"assertFunctionNames": [
|
|
209
|
-
"expect",
|
|
210
|
-
"expectLog",
|
|
211
|
-
"verify"
|
|
212
|
-
]
|
|
213
|
-
}
|
|
214
|
-
]
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
"files": [
|
|
219
|
-
"src/tools/generate.ts"
|
|
220
|
-
],
|
|
221
|
-
"rules": {
|
|
222
|
-
"@typescript-eslint/restrict-template-expressions": [
|
|
223
|
-
"error",
|
|
224
|
-
{
|
|
225
|
-
"allowBoolean": true
|
|
226
|
-
}
|
|
227
|
-
]
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
]
|
|
231
150
|
}
|
|
232
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:
|
|
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
|
-
|
|
167
|
-
const
|
|
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 =
|
|
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);
|
|
@@ -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
|
|
@@ -389,11 +392,11 @@ const downloadImportLib = async () => {
|
|
|
389
392
|
const ext = process.platform === 'darwin'
|
|
390
393
|
? 'dylib' : process.platform === 'win32' ? 'dll' : 'so';
|
|
391
394
|
try {
|
|
392
|
-
const actual = path.join('build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
|
|
395
|
+
const actual = path.join(ROOT, 'build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
|
|
393
396
|
fs.renameSync(actual, artifact);
|
|
394
|
-
} catch
|
|
397
|
+
} catch {
|
|
395
398
|
// ziglang/zig#19743 changed this path
|
|
396
|
-
const actual = path.join('build', 'bin', `${prefix}pkmn${suffix}.node.${ext}`);
|
|
399
|
+
const actual = path.join(ROOT, 'build', 'bin', `${prefix}pkmn${suffix}.node.${ext}`);
|
|
397
400
|
fs.renameSync(actual, artifact);
|
|
398
401
|
}
|
|
399
402
|
}
|
package/src/bin/pkmn-debug
CHANGED
|
@@ -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', '
|
|
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
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const js = @import("../common/js.zig");
|
|
2
|
+
const pkmn = @import("../pkmn.zig");
|
|
3
|
+
const std = @import("std");
|
|
4
|
+
|
|
5
|
+
const assert = std.debug.assert;
|
|
6
|
+
|
|
7
|
+
const c = @cImport({
|
|
8
|
+
@cDefine("NAPI_VERSION", "8");
|
|
9
|
+
@cInclude("node_api.h");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
pub fn register(env: c.napi_env) c.napi_value {
|
|
13
|
+
const object = js.Object.init(env);
|
|
14
|
+
const properties = [_]c.napi_property_descriptor{
|
|
15
|
+
js.Property.init("options", .{ .value = options(env) }),
|
|
16
|
+
js.Property.init("bindings", .{ .value = bindings(env) }),
|
|
17
|
+
};
|
|
18
|
+
assert(c.napi_define_properties(env, object, properties.len, &properties) == c.napi_ok);
|
|
19
|
+
return object;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
fn options(env: c.napi_env) c.napi_value {
|
|
23
|
+
const object = js.Object.init(env);
|
|
24
|
+
const properties = [_]c.napi_property_descriptor{
|
|
25
|
+
js.Property.init("showdown", .{ .value = js.Boolean.init(env, pkmn.options.showdown) }),
|
|
26
|
+
js.Property.init("log", .{ .value = js.Boolean.init(env, pkmn.options.log) }),
|
|
27
|
+
js.Property.init("chance", .{ .value = js.Boolean.init(env, pkmn.options.chance) }),
|
|
28
|
+
js.Property.init("calc", .{ .value = js.Boolean.init(env, pkmn.options.calc) }),
|
|
29
|
+
};
|
|
30
|
+
assert(c.napi_define_properties(env, object, properties.len, &properties) == c.napi_ok);
|
|
31
|
+
return object;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
fn bindings(env: c.napi_env) c.napi_value {
|
|
35
|
+
const array = js.Array.init(env, .{ .length = 1 });
|
|
36
|
+
js.Array.set(env, array, 0, bind(env, pkmn.gen1));
|
|
37
|
+
return array;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fn bind(env: c.napi_env, gen: anytype) c.napi_value {
|
|
41
|
+
const choices_size: u32 = @intCast(gen.CHOICES_SIZE);
|
|
42
|
+
const logs_size: u32 = @intCast(gen.LOGS_SIZE);
|
|
43
|
+
const object = js.Object.init(env);
|
|
44
|
+
const properties = [_]c.napi_property_descriptor{
|
|
45
|
+
js.Property.init("CHOICES_SIZE", .{ .value = js.Number.init(env, choices_size) }),
|
|
46
|
+
js.Property.init("LOGS_SIZE", .{ .value = js.Number.init(env, logs_size) }),
|
|
47
|
+
js.Property.init("update", .{ .method = update(gen) }),
|
|
48
|
+
js.Property.init("choices", .{ .method = choices(gen) }),
|
|
49
|
+
};
|
|
50
|
+
assert(c.napi_define_properties(env, object, properties.len, &properties) == c.napi_ok);
|
|
51
|
+
return object;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fn update(gen: anytype) c.napi_callback {
|
|
55
|
+
return struct {
|
|
56
|
+
fn call(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
|
|
57
|
+
var argc: usize = 4;
|
|
58
|
+
var argv: [4]c.napi_value = undefined;
|
|
59
|
+
assert(c.napi_get_cb_info(env, info, &argc, &argv, null, null) == c.napi_ok);
|
|
60
|
+
assert(argc == 4);
|
|
61
|
+
|
|
62
|
+
var data: ?*anyopaque = undefined;
|
|
63
|
+
var len: usize = 0;
|
|
64
|
+
assert(c.napi_get_arraybuffer_info(env, argv[0], &data, &len) == c.napi_ok);
|
|
65
|
+
assert(len == @sizeOf(gen.Battle(gen.PRNG)));
|
|
66
|
+
|
|
67
|
+
var battle: *gen.Battle(gen.PRNG) = @alignCast(@ptrCast(data.?));
|
|
68
|
+
const c1: pkmn.Choice = @bitCast(js.Number.get(env, argv[1], u8));
|
|
69
|
+
const c2: pkmn.Choice = @bitCast(js.Number.get(env, argv[2], u8));
|
|
70
|
+
|
|
71
|
+
var vtype: c.napi_valuetype = undefined;
|
|
72
|
+
assert(c.napi_typeof(env, argv[3], &vtype) == c.napi_ok);
|
|
73
|
+
const result = switch (vtype) {
|
|
74
|
+
c.napi_undefined, c.napi_null => battle.update(c1, c2, &gen.NULL),
|
|
75
|
+
else => result: {
|
|
76
|
+
assert(c.napi_get_arraybuffer_info(env, argv[3], &data, &len) == c.napi_ok);
|
|
77
|
+
assert(len == gen.LOGS_SIZE);
|
|
78
|
+
|
|
79
|
+
const buf = @as([*]u8, @ptrCast(data.?))[0..gen.LOGS_SIZE];
|
|
80
|
+
var stream: pkmn.protocol.ByteStream = .{ .buffer = buf };
|
|
81
|
+
// TODO: extract out
|
|
82
|
+
var opts = pkmn.battle.options(
|
|
83
|
+
pkmn.protocol.FixedLog{ .writer = stream.writer() },
|
|
84
|
+
gen.chance.NULL,
|
|
85
|
+
gen.calc.NULL,
|
|
86
|
+
);
|
|
87
|
+
break :result battle.update(c1, c2, &opts);
|
|
88
|
+
},
|
|
89
|
+
} catch unreachable;
|
|
90
|
+
|
|
91
|
+
return js.Number.init(env, @as(u8, @bitCast(result)));
|
|
92
|
+
}
|
|
93
|
+
}.call;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
fn choices(gen: anytype) c.napi_callback {
|
|
97
|
+
return struct {
|
|
98
|
+
fn call(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
|
|
99
|
+
var argc: usize = 4;
|
|
100
|
+
var argv: [4]c.napi_value = undefined;
|
|
101
|
+
assert(c.napi_get_cb_info(env, info, &argc, &argv, null, null) == c.napi_ok);
|
|
102
|
+
assert(argc == 4);
|
|
103
|
+
|
|
104
|
+
var data: ?*anyopaque = undefined;
|
|
105
|
+
var len: usize = 0;
|
|
106
|
+
assert(c.napi_get_arraybuffer_info(env, argv[0], &data, &len) == c.napi_ok);
|
|
107
|
+
assert(len == @sizeOf(gen.Battle(gen.PRNG)));
|
|
108
|
+
|
|
109
|
+
var battle: *gen.Battle(gen.PRNG) = @alignCast(@ptrCast(data.?));
|
|
110
|
+
const player: pkmn.Player = @enumFromInt(js.Number.get(env, argv[1], u8));
|
|
111
|
+
const request: pkmn.Choice.Type = @enumFromInt(js.Number.get(env, argv[2], u8));
|
|
112
|
+
|
|
113
|
+
assert(c.napi_get_arraybuffer_info(env, argv[3], &data, &len) == c.napi_ok);
|
|
114
|
+
assert(len == gen.CHOICES_SIZE);
|
|
115
|
+
|
|
116
|
+
const out = @as([*]pkmn.Choice, @ptrCast(data.?))[0..gen.CHOICES_SIZE];
|
|
117
|
+
const n = battle.choices(player, request, out);
|
|
118
|
+
return js.Number.init(env, @as(u8, @bitCast(n)));
|
|
119
|
+
}
|
|
120
|
+
}.call;
|
|
121
|
+
}
|