@pkmn/engine 0.1.0-dev.207fa86a → 0.1.0-dev.20de8262
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/LICENSE +1 -1
- package/README.md +133 -71
- package/build/pkg/addon.d.ts +7 -0
- package/build/pkg/addon.js +112 -0
- package/build/pkg/addon.js.map +1 -0
- package/build/pkg/data/ids.json +12 -12
- package/build/pkg/data/layout.json +27 -5
- package/build/pkg/data/protocol.json +69 -12
- package/build/pkg/data.d.ts +4 -4
- package/build/pkg/data.js +3 -5
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.d.ts +5 -4
- package/build/pkg/gen1.js +49 -33
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +18 -14
- package/build/pkg/index.js +1 -1
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +4 -2
- package/build/pkg/protocol.js +61 -40
- package/build/pkg/protocol.js.map +1 -1
- package/build/test/display.js +400 -0
- package/build/test/display.js.map +1 -0
- package/build/tools/debug.js +135 -0
- package/build/tools/debug.js.map +1 -0
- package/build.zig +166 -136
- package/package.json +87 -45
- package/src/bin/install-pkmn-engine +68 -36
- package/src/bin/pkmn-debug +62 -0
- package/src/lib/common/battle.zig +17 -0
- package/src/lib/common/data.zig +19 -31
- package/src/lib/common/debug.zig +74 -0
- package/src/lib/common/js.zig +118 -0
- package/src/lib/common/optional.zig +67 -0
- package/src/lib/common/options.zig +12 -3
- package/src/lib/common/protocol.zig +932 -395
- package/src/lib/common/rational.zig +357 -0
- package/src/lib/common/rng.zig +29 -20
- package/src/lib/common/util.zig +12 -0
- package/src/lib/gen1/README.md +309 -192
- package/src/lib/gen1/calc.zig +426 -0
- package/src/lib/gen1/chance.zig +1060 -0
- package/src/lib/gen1/data/moves.zig +202 -190
- package/src/lib/gen1/data/species.zig +4 -4
- package/src/lib/gen1/data/types.zig +10 -10
- package/src/lib/gen1/data.zig +107 -93
- package/src/lib/gen1/helpers.zig +577 -36
- package/src/lib/gen1/mechanics.zig +1222 -834
- package/src/lib/gen2/README.md +105 -85
- package/src/lib/gen2/calc.zig +143 -0
- package/src/lib/gen2/chance.zig +1314 -0
- package/src/lib/gen2/data/items.zig +14 -20
- package/src/lib/gen2/data/moves.zig +664 -570
- package/src/lib/gen2/data/species.zig +2 -2
- package/src/lib/gen2/data/types.zig +137 -34
- package/src/lib/gen2/data.zig +134 -96
- package/src/lib/gen2/generated.zig +806 -0
- package/src/lib/gen2/helpers.zig +16 -22
- package/src/lib/gen2/mechanics.zig +3506 -12
- package/src/lib/node.zig +131 -0
- package/src/lib/pkmn.zig +91 -9
- package/src/lib/wasm.zig +13 -0
- package/src/test/display/pkmn.html.tmpl +368 -0
- package/src/lib/binding/node.zig +0 -229
- package/src/lib/binding/wasm.zig +0 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pkmn/engine",
|
|
3
|
-
"version": "0.1.0-dev.
|
|
3
|
+
"version": "0.1.0-dev.20de8262",
|
|
4
4
|
"description": "A minimal, complete, Pokémon battle simulation engine optimized for performance",
|
|
5
5
|
"repository": "github:pkmn/engine",
|
|
6
6
|
"license": "MIT",
|
|
@@ -9,85 +9,107 @@
|
|
|
9
9
|
"types": "build/pkg/index.d.ts",
|
|
10
10
|
"files": [
|
|
11
11
|
"build.zig",
|
|
12
|
+
"build/pkg/data.d.ts",
|
|
13
|
+
"build/pkg/data.js.map",
|
|
14
|
+
"build/pkg/addon.d.ts",
|
|
15
|
+
"build/pkg/addon.js.map",
|
|
16
|
+
"build/pkg/addon.js",
|
|
17
|
+
"build/pkg/data.js",
|
|
18
|
+
"build/pkg/data/ids.json",
|
|
19
|
+
"build/pkg/data/layout.json",
|
|
20
|
+
"build/pkg/data/protocol.json",
|
|
21
|
+
"build/pkg/gen1.d.ts",
|
|
22
|
+
"build/pkg/gen1.js.map",
|
|
23
|
+
"build/pkg/gen1.js",
|
|
24
|
+
"build/pkg/index.d.ts",
|
|
25
|
+
"build/pkg/index.js.map",
|
|
26
|
+
"build/pkg/index.js",
|
|
27
|
+
"build/pkg/protocol.d.ts",
|
|
28
|
+
"build/pkg/protocol.js.map",
|
|
29
|
+
"build/pkg/protocol.js",
|
|
30
|
+
"build/test/display.js.map",
|
|
31
|
+
"build/test/display.js",
|
|
32
|
+
"build/tools/debug.js.map",
|
|
33
|
+
"build/tools/debug.js",
|
|
12
34
|
"src/bin/install-pkmn-engine",
|
|
13
|
-
"src/lib/
|
|
14
|
-
"src/lib/binding/wasm.zig",
|
|
35
|
+
"src/lib/common/battle.zig",
|
|
15
36
|
"src/lib/common/data.zig",
|
|
37
|
+
"src/lib/common/debug.zig",
|
|
38
|
+
"src/lib/common/js.zig",
|
|
39
|
+
"src/lib/common/optional.zig",
|
|
16
40
|
"src/lib/common/options.zig",
|
|
17
41
|
"src/lib/common/protocol.zig",
|
|
42
|
+
"src/lib/common/rational.zig",
|
|
18
43
|
"src/lib/common/rng.zig",
|
|
44
|
+
"src/lib/common/util.zig",
|
|
45
|
+
"src/lib/gen1/calc.zig",
|
|
46
|
+
"src/lib/gen1/chance.zig",
|
|
47
|
+
"src/lib/gen1/data.zig",
|
|
19
48
|
"src/lib/gen1/data/moves.zig",
|
|
20
49
|
"src/lib/gen1/data/species.zig",
|
|
21
50
|
"src/lib/gen1/data/types.zig",
|
|
22
|
-
"src/lib/gen1/data.zig",
|
|
23
51
|
"src/lib/gen1/helpers.zig",
|
|
24
52
|
"src/lib/gen1/mechanics.zig",
|
|
53
|
+
"src/lib/gen2/calc.zig",
|
|
54
|
+
"src/lib/gen2/chance.zig",
|
|
55
|
+
"src/lib/gen2/data.zig",
|
|
25
56
|
"src/lib/gen2/data/items.zig",
|
|
26
57
|
"src/lib/gen2/data/moves.zig",
|
|
27
58
|
"src/lib/gen2/data/species.zig",
|
|
28
59
|
"src/lib/gen2/data/types.zig",
|
|
29
|
-
"src/lib/gen2/
|
|
60
|
+
"src/lib/gen2/generated.zig",
|
|
30
61
|
"src/lib/gen2/helpers.zig",
|
|
31
62
|
"src/lib/gen2/mechanics.zig",
|
|
63
|
+
"src/lib/node.zig",
|
|
32
64
|
"src/lib/pkmn.zig",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"build/pkg/data/protocol.json",
|
|
36
|
-
"build/pkg/data.d.ts",
|
|
37
|
-
"build/pkg/data.js",
|
|
38
|
-
"build/pkg/data.js.map",
|
|
39
|
-
"build/pkg/gen1.d.ts",
|
|
40
|
-
"build/pkg/gen1.js",
|
|
41
|
-
"build/pkg/gen1.js.map",
|
|
42
|
-
"build/pkg/index.d.ts",
|
|
43
|
-
"build/pkg/index.js",
|
|
44
|
-
"build/pkg/index.js.map",
|
|
45
|
-
"build/pkg/protocol.d.ts",
|
|
46
|
-
"build/pkg/protocol.js",
|
|
47
|
-
"build/pkg/protocol.js.map"
|
|
65
|
+
"src/lib/wasm.zig",
|
|
66
|
+
"src/test/display/pkmn.html.tmpl"
|
|
48
67
|
],
|
|
49
68
|
"engines": {
|
|
50
69
|
"node": ">=16.0.0"
|
|
51
70
|
},
|
|
52
71
|
"bin": {
|
|
53
|
-
"install-pkmn-engine": "src/bin/install-pkmn-engine"
|
|
72
|
+
"install-pkmn-engine": "src/bin/install-pkmn-engine",
|
|
73
|
+
"pkmn-debug": "src/bin/pkmn-debug"
|
|
54
74
|
},
|
|
55
75
|
"publishConfig": {
|
|
56
76
|
"access": "public"
|
|
57
77
|
},
|
|
58
78
|
"dependencies": {
|
|
59
|
-
"@pkmn/data": "^0.
|
|
60
|
-
"@pkmn/protocol": "^0.6.
|
|
79
|
+
"@pkmn/data": "^0.8.4",
|
|
80
|
+
"@pkmn/protocol": "^0.6.19"
|
|
61
81
|
},
|
|
62
82
|
"devDependencies": {
|
|
63
|
-
"@pkmn/eslint-config": "^
|
|
64
|
-
"@pkmn/img": "^0.2.
|
|
65
|
-
"@pkmn/sets": "^5.0
|
|
66
|
-
"@pkmn/sim": "0.
|
|
67
|
-
"@types/html-minifier": "^4.0.
|
|
68
|
-
"@types/jest": "^29.5.
|
|
69
|
-
"@types/minimist": "^1.2.
|
|
70
|
-
"@types/mustache": "^4.2.
|
|
71
|
-
"@types/node": "^
|
|
72
|
-
"@vitest/coverage-
|
|
73
|
-
"binaryen": "^
|
|
74
|
-
"eslint": "^8.
|
|
83
|
+
"@pkmn/eslint-config": "^6.5.0",
|
|
84
|
+
"@pkmn/img": "^0.2.22",
|
|
85
|
+
"@pkmn/sets": "^5.1.0",
|
|
86
|
+
"@pkmn/sim": "0.8.4",
|
|
87
|
+
"@types/html-minifier": "^4.0.5",
|
|
88
|
+
"@types/jest": "^29.5.11",
|
|
89
|
+
"@types/minimist": "^1.2.5",
|
|
90
|
+
"@types/mustache": "^4.2.5",
|
|
91
|
+
"@types/node": "^20.11.3",
|
|
92
|
+
"@vitest/coverage-v8": "^1.2.0",
|
|
93
|
+
"binaryen": "^116.0.0",
|
|
94
|
+
"eslint": "^8.56.0",
|
|
75
95
|
"html-minifier": "^4.0.0",
|
|
76
96
|
"json-stringify-pretty-compact": "3.0.0",
|
|
77
97
|
"minimist": "^1.2.8",
|
|
78
98
|
"mustache": "^4.2.0",
|
|
79
99
|
"source-map-support": "^0.5.21",
|
|
100
|
+
"table": "^6.8.1",
|
|
80
101
|
"trakr": "^0.2.0",
|
|
81
|
-
"typescript": "^5.
|
|
82
|
-
"vitest": "^
|
|
102
|
+
"typescript": "^5.3.3",
|
|
103
|
+
"vitest": "^1.2.0"
|
|
83
104
|
},
|
|
84
105
|
"scripts": {
|
|
85
|
-
"lint": "eslint --cache src --ext ts,js && eslint src/bin
|
|
86
|
-
"fix": "eslint --fix src --ext ts,js && eslint --fix src/bin
|
|
106
|
+
"lint": "eslint --cache src --ext ts,js && eslint src/bin/*",
|
|
107
|
+
"fix": "eslint --fix src --ext ts,js && eslint --fix src/bin/*",
|
|
87
108
|
"compile": "tsc -p .",
|
|
88
109
|
"build": "npm run compile",
|
|
89
110
|
"test": "vitest src/pkg",
|
|
90
111
|
"test:integration": "vitest src/test",
|
|
112
|
+
"debug": "npm run compile && node build/tools/debug",
|
|
91
113
|
"fuzz": "npm run compile && node build/test/fuzz",
|
|
92
114
|
"generate": "npm run compile && node build/tools/generate",
|
|
93
115
|
"release": "npm run compile && node build/tools/release",
|
|
@@ -100,7 +122,7 @@
|
|
|
100
122
|
"ignorePatterns": [
|
|
101
123
|
"dist/",
|
|
102
124
|
"node_modules/",
|
|
103
|
-
"
|
|
125
|
+
"examples/zig",
|
|
104
126
|
"build/"
|
|
105
127
|
],
|
|
106
128
|
"env": {
|
|
@@ -116,10 +138,18 @@
|
|
|
116
138
|
"parserOptions": {
|
|
117
139
|
"project": [
|
|
118
140
|
"./tsconfig.json",
|
|
119
|
-
"./
|
|
141
|
+
"./examples/js/tsconfig.json"
|
|
120
142
|
]
|
|
121
143
|
}
|
|
122
144
|
},
|
|
145
|
+
{
|
|
146
|
+
"files": [
|
|
147
|
+
"src/test/display.ts"
|
|
148
|
+
],
|
|
149
|
+
"rules": {
|
|
150
|
+
"@typescript-eslint/no-unnecessary-type-assertion": "off"
|
|
151
|
+
}
|
|
152
|
+
},
|
|
123
153
|
{
|
|
124
154
|
"files": [
|
|
125
155
|
"src/pkg/index.ts",
|
|
@@ -129,7 +159,8 @@
|
|
|
129
159
|
"rules": {
|
|
130
160
|
"no-control-regex": "off",
|
|
131
161
|
"@typescript-eslint/no-empty-interface": "off",
|
|
132
|
-
"@typescript-eslint/no-shadow": "off"
|
|
162
|
+
"@typescript-eslint/no-shadow": "off",
|
|
163
|
+
"@typescript-eslint/no-unsafe-declaration-merging": "off"
|
|
133
164
|
}
|
|
134
165
|
},
|
|
135
166
|
{
|
|
@@ -145,12 +176,23 @@
|
|
|
145
176
|
"src/test/benchmark*.ts"
|
|
146
177
|
],
|
|
147
178
|
"rules": {
|
|
148
|
-
"@typescript-eslint/no-unused-vars": "off"
|
|
179
|
+
"@typescript-eslint/no-unused-vars": "off",
|
|
180
|
+
"@typescript-eslint/no-redundant-type-constituents": "off"
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"files": [
|
|
185
|
+
"src/pkg/protocol.test.ts"
|
|
186
|
+
],
|
|
187
|
+
"rules": {
|
|
188
|
+
"jest/no-standalone-expect": "off",
|
|
189
|
+
"jest/no-conditional-expect": "off"
|
|
149
190
|
}
|
|
150
191
|
},
|
|
151
192
|
{
|
|
152
193
|
"files": [
|
|
153
|
-
"src/test/*.test.ts"
|
|
194
|
+
"src/test/*.test.ts",
|
|
195
|
+
"src/test/regression/*.test.ts"
|
|
154
196
|
],
|
|
155
197
|
"rules": {
|
|
156
198
|
"jest/no-standalone-expect": "off"
|
|
@@ -188,4 +230,4 @@
|
|
|
188
230
|
}
|
|
189
231
|
]
|
|
190
232
|
}
|
|
191
|
-
}
|
|
233
|
+
}
|
|
@@ -10,13 +10,15 @@ 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: 12, patch: 0, dev: 2036};
|
|
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';
|
|
17
17
|
const ROOT = path.resolve(__dirname, '..', '..');
|
|
18
|
+
let SILENT = false;
|
|
18
19
|
|
|
19
20
|
const sh = (cmd, args) => execFileSync(cmd, args, {encoding: 'utf8', cwd: ROOT});
|
|
21
|
+
const log = (...args) => { if (!SILENT) console.log(...args); };
|
|
20
22
|
|
|
21
23
|
// This is hardly the browser fetch API, but it works for our primitive needs
|
|
22
24
|
const fetch = url => new Promise((resolve, reject) => {
|
|
@@ -61,7 +63,7 @@ const unpack7 = (input, output) => new Promise((resolve, reject) => {
|
|
|
61
63
|
require.resolve('7zip-min');
|
|
62
64
|
} catch (err) {
|
|
63
65
|
if (err.code !== 'MODULE_NOT_FOUND') throw err;
|
|
64
|
-
|
|
66
|
+
log('Installing 7zip-min package locally to unpack the archive...');
|
|
65
67
|
sh('npm', ['install', '7zip-min', '--no-audit', '--no-save']);
|
|
66
68
|
}
|
|
67
69
|
|
|
@@ -83,7 +85,7 @@ const unpack = async (input, output) => {
|
|
|
83
85
|
sh('tar', ['xf', input, '-C', output]);
|
|
84
86
|
return;
|
|
85
87
|
} catch {
|
|
86
|
-
|
|
88
|
+
log('tar command not found, falling back to 7z');
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
91
|
// Try to use a 7z binary if we can, and only install 7zip-min as a last resort
|
|
@@ -120,10 +122,10 @@ const find = zig => {
|
|
|
120
122
|
(!ZIG_VERSION.dev || (dev && dev >= ZIG_VERSION.dev)));
|
|
121
123
|
|
|
122
124
|
if (compatible) {
|
|
123
|
-
|
|
125
|
+
log('Found existing compatible Zig executable:', zig_exe);
|
|
124
126
|
return zig_exe;
|
|
125
127
|
} else {
|
|
126
|
-
|
|
128
|
+
log(`Existing Zig executable is not compatible (${version} < ${VERSION}):`, zig_exe);
|
|
127
129
|
}
|
|
128
130
|
} catch (err) {
|
|
129
131
|
if (err.code !== 'ENOENT') throw err;
|
|
@@ -168,11 +170,11 @@ const install = async () => {
|
|
|
168
170
|
let base = path.basename(url);
|
|
169
171
|
const archive = path.join(dir, path.basename(url));
|
|
170
172
|
|
|
171
|
-
|
|
173
|
+
log(`Downloading Zig tarball from ${url} to ${archive}`);
|
|
172
174
|
try {
|
|
173
175
|
await download(url, archive, release.shasum);
|
|
174
176
|
|
|
175
|
-
|
|
177
|
+
log(`Extracting tarball and installing to ${dir}`);
|
|
176
178
|
await unpack(archive, dir);
|
|
177
179
|
if (archive.endsWith('.zip')) {
|
|
178
180
|
base = base.slice(0, -4);
|
|
@@ -187,17 +189,17 @@ const install = async () => {
|
|
|
187
189
|
} catch (err) {
|
|
188
190
|
if (err.code !== 'ENOENT') throw err;
|
|
189
191
|
}
|
|
190
|
-
|
|
192
|
+
log(`Zig${version === 'master' ? '' : ` v${version}`} executable:`, zig,
|
|
191
193
|
'(this version of Zig will be retained to speed up future updates)');
|
|
192
194
|
const [pre, post] = tty.isatty(1) ? ['\x1b[1m\x1b[35m', '\x1b[0m'] : ['', ''];
|
|
193
|
-
|
|
195
|
+
log(
|
|
194
196
|
`${pre}Consider moving the ${path.dirname(zig)} directory and adding it to your PATH`,
|
|
195
197
|
`to use Zig on other projects, or delete this if you wish to save space.${post}`
|
|
196
198
|
);
|
|
197
199
|
|
|
198
200
|
return zig;
|
|
199
201
|
} finally {
|
|
200
|
-
|
|
202
|
+
log(`Cleaning up ${archive}`);
|
|
201
203
|
try { fs.rmSync(archive); } catch {}
|
|
202
204
|
}
|
|
203
205
|
};
|
|
@@ -206,17 +208,17 @@ const install = async () => {
|
|
|
206
208
|
const downloadHeaders = async () => {
|
|
207
209
|
const include = path.resolve(process.execPath, '..', '..', 'include', 'node');
|
|
208
210
|
if (fs.existsSync(path.join(include, 'node.h'))) {
|
|
209
|
-
|
|
211
|
+
log('Node headers:', include);
|
|
210
212
|
return include;
|
|
211
213
|
}
|
|
212
214
|
|
|
213
215
|
const dir = path.join(ROOT, 'build', 'include');
|
|
214
|
-
const dest = path.join(dir,
|
|
216
|
+
const dest = path.join(dir, 'node');
|
|
215
217
|
if (fs.existsSync(path.join(dest, 'node.h'))) {
|
|
216
|
-
|
|
218
|
+
log('Node headers:', dest);
|
|
217
219
|
return dest;
|
|
218
220
|
} else {
|
|
219
|
-
|
|
221
|
+
log(`Could not find Node headers at ${include}, downloading...`);
|
|
220
222
|
}
|
|
221
223
|
|
|
222
224
|
try {
|
|
@@ -227,20 +229,28 @@ const downloadHeaders = async () => {
|
|
|
227
229
|
|
|
228
230
|
const url = process.release.headersUrl;
|
|
229
231
|
const targz = path.join(dir, path.basename(url));
|
|
232
|
+
const unpacked = path.join(dir, `node-${process.version}`, 'include');
|
|
230
233
|
|
|
231
|
-
|
|
232
|
-
await download(url, targz);
|
|
233
|
-
await unpack(targz, dir);
|
|
234
|
+
log(`Downloading Node headers from ${url} to ${targz}`);
|
|
234
235
|
|
|
235
|
-
|
|
236
|
+
try {
|
|
237
|
+
await download(url, targz);
|
|
238
|
+
await unpack(targz, dir);
|
|
239
|
+
fs.renameSync(path.join(unpacked, 'node'), dest);
|
|
236
240
|
|
|
237
|
-
|
|
241
|
+
log('Node headers:', dest);
|
|
242
|
+
|
|
243
|
+
return dest;
|
|
244
|
+
} finally {
|
|
245
|
+
try { fs.rmSync(targz); } catch {}
|
|
246
|
+
try { fs.rmSync(unpacked, {recursive: true}); } catch {}
|
|
247
|
+
}
|
|
238
248
|
};
|
|
239
249
|
|
|
240
250
|
const downloadImportLib = async () => {
|
|
241
251
|
const library = path.resolve(process.execPath, '..', 'node.lib');
|
|
242
252
|
if (fs.existsSync(path.join(library, 'node.h'))) {
|
|
243
|
-
|
|
253
|
+
log('Node import library:', library);
|
|
244
254
|
return library;
|
|
245
255
|
}
|
|
246
256
|
|
|
@@ -248,10 +258,10 @@ const downloadImportLib = async () => {
|
|
|
248
258
|
const url = new URL('./win-x64/node.lib', process.release.headersUrl).href;
|
|
249
259
|
const dest = path.join(dir, path.basename(url));
|
|
250
260
|
if (fs.existsSync(path.join(dest))) {
|
|
251
|
-
|
|
261
|
+
log('Node import library:', dest);
|
|
252
262
|
return dest;
|
|
253
263
|
} else {
|
|
254
|
-
|
|
264
|
+
log(`Could not find Node import library at ${library}, downloading...`);
|
|
255
265
|
}
|
|
256
266
|
|
|
257
267
|
try {
|
|
@@ -260,24 +270,41 @@ const downloadImportLib = async () => {
|
|
|
260
270
|
if (err.code !== 'EEXIST') throw err;
|
|
261
271
|
}
|
|
262
272
|
|
|
263
|
-
|
|
273
|
+
log(`Downloading Node import library from ${url} to ${dest}`);
|
|
264
274
|
await download(url, dest);
|
|
265
|
-
|
|
275
|
+
log('Node import library:', dest);
|
|
266
276
|
|
|
267
277
|
return dest;
|
|
268
278
|
};
|
|
269
279
|
|
|
270
280
|
(async () => {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
281
|
+
let only = false;
|
|
282
|
+
let options = undefined;
|
|
283
|
+
let error = false;
|
|
284
|
+
for (let i = 2; i < process.argv.length; i++) {
|
|
285
|
+
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
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (error) {
|
|
275
302
|
console.error('Invalid arguments');
|
|
276
303
|
process.exit(1);
|
|
277
304
|
}
|
|
278
305
|
|
|
279
306
|
const zig = await install();
|
|
280
|
-
if (
|
|
307
|
+
if (only) process.exit(0);
|
|
281
308
|
|
|
282
309
|
let tmp;
|
|
283
310
|
try {
|
|
@@ -309,14 +336,18 @@ const downloadImportLib = async () => {
|
|
|
309
336
|
node = true;
|
|
310
337
|
if (!options) {
|
|
311
338
|
const addon = require(copy);
|
|
312
|
-
if (addon.options.showdown) opts.push('-Dshowdown');
|
|
313
|
-
if (addon.options.
|
|
339
|
+
if (addon.engine.options.showdown) opts.push('-Dshowdown');
|
|
340
|
+
if (addon.engine.options.log) opts.push('-Dlog');
|
|
341
|
+
if (addon.engine.options.chance) opts.push('-Dchance');
|
|
342
|
+
if (addon.engine.options.calc) opts.push('-Dcalc');
|
|
314
343
|
}
|
|
315
344
|
} else if (!options) {
|
|
316
345
|
const addon = await WebAssembly.instantiate(fs.readFileSync(copy));
|
|
317
346
|
const values = new Uint8Array(addon.instance.exports.memory.buffer);
|
|
318
347
|
if (values[addon.instance.exports.SHOWDOWN.value]) opts.push('-Dshowdown');
|
|
319
|
-
if (values[addon.instance.exports.
|
|
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');
|
|
320
351
|
}
|
|
321
352
|
const key = `${type} ${opts.sort().join(' ')}`;
|
|
322
353
|
if (!configs.has(key)) configs.set(key, {type, options: opts});
|
|
@@ -327,8 +358,9 @@ const downloadImportLib = async () => {
|
|
|
327
358
|
// either the default options or whatever was passed in
|
|
328
359
|
if (!configs.size) {
|
|
329
360
|
node = true;
|
|
330
|
-
|
|
331
|
-
configs.set('
|
|
361
|
+
const DEFAULT = ['-Dshowdown'];
|
|
362
|
+
configs.set('node', {type: 'node', options: options || DEFAULT});
|
|
363
|
+
configs.set('wasm', {type: 'wasm', options: options || DEFAULT});
|
|
332
364
|
}
|
|
333
365
|
|
|
334
366
|
const headers = node ? await downloadHeaders() : undefined;
|
|
@@ -347,7 +379,7 @@ const downloadImportLib = async () => {
|
|
|
347
379
|
opts.includes('-Dshowdown') || opts.includes('-Dshowdown=true') ? '-showdown' : '';
|
|
348
380
|
const flags = opts.length ? ` (${opts.join(' ')})` : '';
|
|
349
381
|
const artifact = path.join('build', 'lib', `pkmn${suffix}.${config.type}`);
|
|
350
|
-
|
|
382
|
+
log(`Building ${artifact}${flags}`);
|
|
351
383
|
sh(zig, args);
|
|
352
384
|
// TODO: ziglang/zig#14647 broke emit_to so we get to rename the file ourselves...
|
|
353
385
|
if (config.type === 'node') {
|
|
@@ -355,7 +387,7 @@ const downloadImportLib = async () => {
|
|
|
355
387
|
const ext = process.platform === 'darwin'
|
|
356
388
|
? 'dylib' : process.platform === 'win32' ? 'dll' : 'so';
|
|
357
389
|
const actual = path.join('build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
|
|
358
|
-
fs.renameSync(actual, artifact);
|
|
390
|
+
fs.renameSync(path.join(ROOT, actual), path.join(ROOT, artifact));
|
|
359
391
|
}
|
|
360
392
|
}
|
|
361
393
|
})().catch(e => {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
try {
|
|
5
|
+
require('source-map-support').install();
|
|
6
|
+
} catch (err) {
|
|
7
|
+
if (err.code !== 'MODULE_NOT_FOUND') throw err;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const {execFileSync} = require('child_process');
|
|
11
|
+
const {readFileSync} = require('fs');
|
|
12
|
+
const {join, resolve} = require('path');
|
|
13
|
+
|
|
14
|
+
const ROOT = resolve(__dirname, '..', '..');
|
|
15
|
+
const packageJSON = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8'));
|
|
16
|
+
|
|
17
|
+
const missing = [];
|
|
18
|
+
for (const dep of ['@pkmn/img', 'html-minifier', 'mustache']) {
|
|
19
|
+
try {
|
|
20
|
+
require.resolve(dep);
|
|
21
|
+
} catch (e) {
|
|
22
|
+
if (e.code !== 'MODULE_NOT_FOUND') throw e;
|
|
23
|
+
missing.push(`${dep}@${packageJSON.devDependencies[dep]}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let Dex = undefined;
|
|
28
|
+
try {
|
|
29
|
+
Dex = require('@pkmn/sim').Dex;
|
|
30
|
+
} catch (err) {
|
|
31
|
+
if (err.code !== 'MODULE_NOT_FOUND') throw err;
|
|
32
|
+
try {
|
|
33
|
+
Dex = require('@pkmn/dex').Dex;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
if (e.code !== 'MODULE_NOT_FOUND') throw e;
|
|
36
|
+
missing.push(`@pkmn/dex@${packageJSON.dependencies['@pkmn/data']}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (missing.length) {
|
|
41
|
+
if (+/^v(\d+)/.exec(process.version)[1] < 16) {
|
|
42
|
+
console.error('pkmn-debug requires Node v16+');
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
execFileSync('npm', ['install', ...missing, '--global'], {encoding: 'utf8'});
|
|
47
|
+
|
|
48
|
+
const node_modules = execFileSync('npm', ['root', '--global'], {encoding: 'utf8'}).trim();
|
|
49
|
+
if (!process.env.NODE_PATH || !process.env.NODE_PATH.includes(node_modules)) {
|
|
50
|
+
console.error(`NODE_PATH must include npm's global node_modules directory: '${node_modules}'`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const {Generations} = require('@pkmn/data');
|
|
56
|
+
|
|
57
|
+
const {run} = require('../../build/tools/debug');
|
|
58
|
+
|
|
59
|
+
run(new Generations(Dex)).catch(err => {
|
|
60
|
+
console.error(err.message);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// Stores state required by optional features to the engine that can be passed to a generation's
|
|
2
|
+
/// `Battle.update` function. All generations generically support protocol logging (enabled via
|
|
3
|
+
/// `-Dlog`), chance actions and probability tracking (enabled via `-Dchance`), and damage
|
|
4
|
+
/// computation and chance overrides (`-Dcalc`), though the concrete types for these features are
|
|
5
|
+
/// generation dependent.
|
|
6
|
+
pub fn Options(comptime Log: type, comptime Chance: type, comptime Calc: type) type {
|
|
7
|
+
return struct { log: Log, chance: Chance, calc: Calc };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/// Helper to create a battle `Options` object with the provided `log`, `chance`, and `calc`.
|
|
11
|
+
pub fn options(
|
|
12
|
+
log: anytype,
|
|
13
|
+
chance: anytype,
|
|
14
|
+
calc: anytype,
|
|
15
|
+
) Options(@TypeOf(log), @TypeOf(chance), @TypeOf(calc)) {
|
|
16
|
+
return .{ .log = log, .chance = chance, .calc = calc };
|
|
17
|
+
}
|
package/src/lib/common/data.zig
CHANGED
|
@@ -9,12 +9,12 @@ pub const Player = enum(u1) {
|
|
|
9
9
|
P2,
|
|
10
10
|
|
|
11
11
|
/// Returns a player's opponent.
|
|
12
|
-
pub
|
|
13
|
-
return @
|
|
12
|
+
pub fn foe(self: Player) Player {
|
|
13
|
+
return @enumFromInt(~@intFromEnum(self));
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/// Return's an identifier for the player's Pokémon at the one-indexed `id`.
|
|
17
|
-
pub
|
|
17
|
+
pub fn ident(self: Player, id: u3) ID {
|
|
18
18
|
assert(id > 0 and id <= 6);
|
|
19
19
|
return .{ .id = id, .player = self };
|
|
20
20
|
}
|
|
@@ -22,42 +22,38 @@ pub const Player = enum(u1) {
|
|
|
22
22
|
|
|
23
23
|
test Player {
|
|
24
24
|
try expectEqual(Player.P2, Player.P1.foe());
|
|
25
|
-
try expectEqual(@as(u8,
|
|
26
|
-
try expectEqual(@as(u8,
|
|
25
|
+
try expectEqual(0b0001, @as(u8, @bitCast(Player.P1.ident(1))));
|
|
26
|
+
try expectEqual(0b1101, @as(u8, @bitCast(Player.P2.ident(5))));
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/// An identifier for a specific Pokémon in battle.
|
|
30
|
-
pub const ID = packed struct {
|
|
30
|
+
pub const ID = packed struct(u8) {
|
|
31
31
|
/// The one-indexed team slot of the Pokémon
|
|
32
32
|
id: u3 = 0,
|
|
33
33
|
/// The Pokémon's trainer.
|
|
34
34
|
player: Player = .P1,
|
|
35
35
|
_: u4 = 0,
|
|
36
36
|
|
|
37
|
-
comptime {
|
|
38
|
-
assert(@sizeOf(ID) == 1);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
37
|
/// Converts the identifier into a number.
|
|
42
|
-
pub
|
|
43
|
-
return @intCast(
|
|
38
|
+
pub fn int(self: ID) u4 {
|
|
39
|
+
return @intCast(@as(u8, @bitCast(self)));
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
/// Decodes the identifier from a number.
|
|
47
|
-
pub
|
|
48
|
-
return @bitCast(
|
|
43
|
+
pub fn from(id: u4) ID {
|
|
44
|
+
return @bitCast(@as(u8, id));
|
|
49
45
|
}
|
|
50
46
|
};
|
|
51
47
|
|
|
52
48
|
test ID {
|
|
53
|
-
try expectEqual(@as(u8,
|
|
54
|
-
try expectEqual(@as(u8,
|
|
55
|
-
const id =
|
|
49
|
+
try expectEqual(0b0001, @as(u8, @bitCast(ID{ .player = .P1, .id = 1 })));
|
|
50
|
+
try expectEqual(0b1101, @as(u8, @bitCast(ID{ .player = .P2, .id = 5 })));
|
|
51
|
+
const id: ID = .{ .player = .P2, .id = 4 };
|
|
56
52
|
try expectEqual(id, ID.from(id.int()));
|
|
57
53
|
}
|
|
58
54
|
|
|
59
55
|
/// A choice made by a player during battle.
|
|
60
|
-
pub const Choice = packed struct {
|
|
56
|
+
pub const Choice = packed struct(u8) {
|
|
61
57
|
/// The choice type.
|
|
62
58
|
type: Choice.Type = .Pass,
|
|
63
59
|
/// The choice data:
|
|
@@ -73,10 +69,6 @@ pub const Choice = packed struct {
|
|
|
73
69
|
Move,
|
|
74
70
|
Switch,
|
|
75
71
|
};
|
|
76
|
-
|
|
77
|
-
comptime {
|
|
78
|
-
assert(@sizeOf(Choice) == 1);
|
|
79
|
-
}
|
|
80
72
|
};
|
|
81
73
|
|
|
82
74
|
test Choice {
|
|
@@ -84,12 +76,12 @@ test Choice {
|
|
|
84
76
|
const p2: Choice = .{ .type = .Switch, .data = 5 };
|
|
85
77
|
try expectEqual(5, p2.data);
|
|
86
78
|
try expectEqual(Choice.Type.Move, p1.type);
|
|
87
|
-
try expectEqual(0b0001_0001, @
|
|
88
|
-
try expectEqual(0b0001_0110, @
|
|
79
|
+
try expectEqual(0b0001_0001, @as(u8, @bitCast(p1)));
|
|
80
|
+
try expectEqual(0b0001_0110, @as(u8, @bitCast(p2)));
|
|
89
81
|
}
|
|
90
82
|
|
|
91
83
|
/// The result of the battle - all results other than 'None' should be considered terminal.
|
|
92
|
-
pub const Result = packed struct {
|
|
84
|
+
pub const Result = packed struct(u8) {
|
|
93
85
|
/// The type of result from the perspective of Player 1.
|
|
94
86
|
/// `Error` is not possible when in Pokémon Showdown compatibility mode.
|
|
95
87
|
type: Result.Type = .None,
|
|
@@ -117,13 +109,9 @@ pub const Result = packed struct {
|
|
|
117
109
|
pub const Error: Result = .{ .type = .Error };
|
|
118
110
|
/// The default result.
|
|
119
111
|
pub const Default: Result = .{ .p1 = .Move, .p2 = .Move };
|
|
120
|
-
|
|
121
|
-
comptime {
|
|
122
|
-
assert(@sizeOf(Result) == 1);
|
|
123
|
-
}
|
|
124
112
|
};
|
|
125
113
|
|
|
126
114
|
test Result {
|
|
127
|
-
try expectEqual(0b0101_0000, @
|
|
128
|
-
try expectEqual(0b1000_0000, @
|
|
115
|
+
try expectEqual(0b0101_0000, @as(u8, @bitCast(Result.Default)));
|
|
116
|
+
try expectEqual(0b1000_0000, @as(u8, @bitCast(Result{ .p2 = .Switch })));
|
|
129
117
|
}
|