@pkmn/engine 0.1.0-dev.b3197aa3 → 0.1.0-dev.b396399c
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 +17 -53
- package/build/pkg/addon/wasm.js.map +1 -1
- package/build/pkg/addon.d.ts +4 -4
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/protocol.d.ts +11 -2
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +37 -3
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/debug.jsx +1 -87
- package/build/tools/display/debug.jsx.map +1 -1
- package/build/tools/display/ui.jsx +3 -2
- package/build/tools/display/ui.jsx.map +1 -1
- package/build/tools/display/util.js +125 -1
- package/build/tools/display/util.js.map +1 -1
- package/build.zig +141 -232
- package/package.json +22 -21
- package/src/bin/install-pkmn-engine +22 -7
- package/src/lib/bindings/c.zig +27 -82
- package/src/lib/bindings/node.zig +7 -7
- package/src/lib/bindings/wasm.zig +6 -15
- package/src/lib/common/array.zig +5 -12
- package/src/lib/common/debug.zig +33 -59
- package/src/lib/common/js.zig +3 -5
- package/src/lib/common/optional.zig +11 -21
- package/src/lib/common/protocol.zig +224 -189
- package/src/lib/common/rational.zig +18 -38
- package/src/lib/common/util.zig +14 -46
- package/src/lib/gen1/calc.zig +121 -108
- package/src/lib/gen1/chance.zig +112 -75
- package/src/lib/gen1/data/types.zig +1 -1
- package/src/lib/gen1/data.zig +5 -5
- package/src/lib/gen1/helpers.zig +8 -10
- package/src/lib/gen1/mechanics.zig +31 -31
- package/src/lib/gen2/calc.zig +3 -6
- package/src/lib/gen2/chance.zig +12 -18
- package/src/lib/gen2/data.zig +5 -5
- package/src/lib/gen2/helpers.zig +4 -6
- package/src/lib/gen2/mechanics.zig +16 -16
- package/src/lib/napi.h +2 -0
- package/src/lib/node.zig +1 -1
- package/src/lib/pkmn.zig +91 -17
- package/src/lib/wasm.zig +2 -6
- package/src/tools/display/dom.ts +40 -25
- package/src/lib/common/napi.zig +0 -4
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.b396399c",
|
|
4
4
|
"description": "A minimal, complete, Pokémon battle simulation engine optimized for performance",
|
|
5
5
|
"repository": "github:pkmn/engine",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,7 +57,6 @@
|
|
|
57
57
|
"src/lib/common/data.zig",
|
|
58
58
|
"src/lib/common/debug.zig",
|
|
59
59
|
"src/lib/common/js.zig",
|
|
60
|
-
"src/lib/common/napi.zig",
|
|
61
60
|
"src/lib/common/optional.zig",
|
|
62
61
|
"src/lib/common/options.zig",
|
|
63
62
|
"src/lib/common/protocol.zig",
|
|
@@ -82,6 +81,7 @@
|
|
|
82
81
|
"src/lib/gen2/generated.zig",
|
|
83
82
|
"src/lib/gen2/helpers.zig",
|
|
84
83
|
"src/lib/gen2/mechanics.zig",
|
|
84
|
+
"src/lib/napi.h",
|
|
85
85
|
"src/lib/node.zig",
|
|
86
86
|
"src/lib/pkmn.zig",
|
|
87
87
|
"src/lib/wasm.zig",
|
|
@@ -99,38 +99,39 @@
|
|
|
99
99
|
"access": "public"
|
|
100
100
|
},
|
|
101
101
|
"dependencies": {
|
|
102
|
-
"@pkmn/data": "
|
|
103
|
-
"@pkmn/protocol": "^0.
|
|
102
|
+
"@pkmn/data": "0.9.35",
|
|
103
|
+
"@pkmn/protocol": "^0.7.2"
|
|
104
104
|
},
|
|
105
105
|
"devDependencies": {
|
|
106
|
-
"@pkmn/
|
|
107
|
-
"@pkmn/
|
|
108
|
-
"@pkmn/
|
|
106
|
+
"@pkmn/dex-types": "0.9.35",
|
|
107
|
+
"@pkmn/eslint-config": "^9.27.0",
|
|
108
|
+
"@pkmn/img": "^0.3.3",
|
|
109
|
+
"@pkmn/sets": "^5.2.0",
|
|
109
110
|
"@pkmn/sim": "0.9.31",
|
|
110
|
-
"@pkmn/smogon": "
|
|
111
|
-
"@types/html-minifier": "^4.0.
|
|
111
|
+
"@pkmn/smogon": "0.5.21",
|
|
112
|
+
"@types/html-minifier": "^4.0.6",
|
|
112
113
|
"@types/jest": "^30.0.0",
|
|
113
114
|
"@types/minimist": "^1.2.5",
|
|
114
115
|
"@types/mustache": "^4.2.6",
|
|
115
|
-
"@types/node": "^
|
|
116
|
-
"@types/react": "
|
|
117
|
-
"@types/semver": "^7.7.
|
|
118
|
-
"@types/vscode": "^1.
|
|
119
|
-
"@vitest/coverage-v8": "^
|
|
120
|
-
"@vscode/vsce": "^3.
|
|
121
|
-
"binaryen": "^
|
|
122
|
-
"esbuild": "^0.
|
|
123
|
-
"eslint": "
|
|
116
|
+
"@types/node": "^25.6.0",
|
|
117
|
+
"@types/react": "^19.2.14",
|
|
118
|
+
"@types/semver": "^7.7.1",
|
|
119
|
+
"@types/vscode": "^1.118.0",
|
|
120
|
+
"@vitest/coverage-v8": "^4.1.5",
|
|
121
|
+
"@vscode/vsce": "^3.9.1",
|
|
122
|
+
"binaryen": "^129.0.0",
|
|
123
|
+
"esbuild": "^0.28.0",
|
|
124
|
+
"eslint": "<10",
|
|
124
125
|
"html-minifier": "^4.0.0",
|
|
125
126
|
"json-stringify-pretty-compact": "3.0.0",
|
|
126
127
|
"minimist": "^1.2.8",
|
|
127
128
|
"mustache": "^4.2.0",
|
|
128
|
-
"semver": "^7.7.
|
|
129
|
+
"semver": "^7.7.4",
|
|
129
130
|
"source-map-support": "^0.5.21",
|
|
130
131
|
"table": "^6.9.0",
|
|
131
132
|
"trakr": "^0.2.0",
|
|
132
|
-
"typescript": "^
|
|
133
|
-
"vitest": "^
|
|
133
|
+
"typescript": "^6.0.3",
|
|
134
|
+
"vitest": "^4.1.5"
|
|
134
135
|
},
|
|
135
136
|
"scripts": {
|
|
136
137
|
"lint": "eslint --cache src",
|
|
@@ -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: 16, patch: 0};
|
|
14
14
|
const DEV = ZIG_VERSION.dev ? `-dev.${ZIG_VERSION.dev}` : '';
|
|
15
15
|
const VERSION = `${ZIG_VERSION.major}.${ZIG_VERSION.minor}.${ZIG_VERSION.patch}${DEV}`;
|
|
16
16
|
const INDEX = 'https://ziglang.org/download/index.json';
|
|
@@ -111,15 +111,31 @@ const unpack = async (input, output) => {
|
|
|
111
111
|
}
|
|
112
112
|
};
|
|
113
113
|
|
|
114
|
+
const parse = s => {
|
|
115
|
+
try {
|
|
116
|
+
return JSON.parse(s);
|
|
117
|
+
} catch (e) {
|
|
118
|
+
if (!(e instanceof SyntaxError)) throw e;
|
|
119
|
+
const json = s
|
|
120
|
+
// "key": -> "key": (ensures keys are quoted)
|
|
121
|
+
.replace(/\.([a-zA-Z_][a-zA-Z0-9_]*)\s*=/g, '"$1":')
|
|
122
|
+
// .{ -> { (converts ZON struct to JSON object)
|
|
123
|
+
.replace(/\.\{/g, '{')
|
|
124
|
+
// Remove trailing commas, which are invalid in JSON
|
|
125
|
+
.replace(/,\s*([}\]])/g, '$1');
|
|
126
|
+
return JSON.parse(json);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
114
130
|
const find = zig => {
|
|
115
131
|
try {
|
|
116
|
-
const {zig_exe, version} =
|
|
132
|
+
const {zig_exe, version} = parse(sh(zig, ['env']));
|
|
117
133
|
const [major, minor, patch, dev] = version.split('.').map(n => parseInt(n));
|
|
118
134
|
|
|
119
135
|
const compatible = major > ZIG_VERSION.major ||
|
|
120
136
|
(major >= ZIG_VERSION.major && minor > ZIG_VERSION.minor) ||
|
|
121
137
|
(major >= ZIG_VERSION.major && minor >= ZIG_VERSION.minor && patch >= ZIG_VERSION.patch &&
|
|
122
|
-
(!ZIG_VERSION.dev || (dev && dev >= ZIG_VERSION.dev)));
|
|
138
|
+
(!ZIG_VERSION.dev || (dev && dev >= parseInt(ZIG_VERSION.dev))));
|
|
123
139
|
|
|
124
140
|
if (compatible) {
|
|
125
141
|
log('Found existing compatible Zig executable:', zig_exe);
|
|
@@ -163,10 +179,9 @@ const install = async () => {
|
|
|
163
179
|
}
|
|
164
180
|
|
|
165
181
|
const index = JSON.parse(await fetch(INDEX));
|
|
166
|
-
|
|
167
|
-
// const version =
|
|
168
|
-
const
|
|
169
|
-
const release = index[VERSION][`${arch}-${platform}`];
|
|
182
|
+
const version = Object.keys(index)[+!ZIG_VERSION.dev];
|
|
183
|
+
// const version = VERSION; // TODO
|
|
184
|
+
const release = index[version][`${arch}-${platform}`];
|
|
170
185
|
const url = release.tarball;
|
|
171
186
|
|
|
172
187
|
let base = path.basename(url);
|
package/src/lib/bindings/c.zig
CHANGED
|
@@ -5,9 +5,6 @@ const assert = std.debug.assert;
|
|
|
5
5
|
|
|
6
6
|
const ERROR: u8 = 0b1100;
|
|
7
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
8
|
pub const OPTIONS: extern struct {
|
|
12
9
|
showdown: bool,
|
|
13
10
|
log: bool,
|
|
@@ -25,59 +22,59 @@ pub const CHOICES_SIZE = pkmn.CHOICES_SIZE;
|
|
|
25
22
|
pub const MAX_LOGS = pkmn.MAX_LOGS;
|
|
26
23
|
pub const LOGS_SIZE = pkmn.LOGS_SIZE;
|
|
27
24
|
|
|
28
|
-
pub fn choice_init(choice: u8, data: u8) callconv(.
|
|
29
|
-
assert(choice <= @
|
|
25
|
+
pub fn choice_init(choice: u8, data: u8) callconv(.c) u8 {
|
|
26
|
+
assert(choice <= @typeInfo(pkmn.Choice.Type).@"enum".fields.len);
|
|
30
27
|
assert(data <= 6);
|
|
31
28
|
return @bitCast(pkmn.Choice{ .type = @enumFromInt(choice), .data = @intCast(data) });
|
|
32
29
|
}
|
|
33
30
|
|
|
34
|
-
pub fn choice_type(choice: u8) callconv(.
|
|
31
|
+
pub fn choice_type(choice: u8) callconv(.c) u8 {
|
|
35
32
|
return @intFromEnum(@as(pkmn.Choice, @bitCast(choice)).type);
|
|
36
33
|
}
|
|
37
34
|
|
|
38
|
-
pub fn choice_data(choice: u8) callconv(.
|
|
35
|
+
pub fn choice_data(choice: u8) callconv(.c) u8 {
|
|
39
36
|
return @as(u8, @as(pkmn.Choice, @bitCast(choice)).data);
|
|
40
37
|
}
|
|
41
38
|
|
|
42
|
-
pub fn result_type(result: u8) callconv(.
|
|
39
|
+
pub fn result_type(result: u8) callconv(.c) u8 {
|
|
43
40
|
return @intFromEnum(@as(pkmn.Result, @bitCast(result)).type);
|
|
44
41
|
}
|
|
45
42
|
|
|
46
|
-
pub fn result_p1(result: u8) callconv(.
|
|
43
|
+
pub fn result_p1(result: u8) callconv(.c) u8 {
|
|
47
44
|
assert(!err(result));
|
|
48
45
|
return @intFromEnum(@as(pkmn.Result, @bitCast(result)).p1);
|
|
49
46
|
}
|
|
50
47
|
|
|
51
|
-
pub fn result_p2(result: u8) callconv(.
|
|
48
|
+
pub fn result_p2(result: u8) callconv(.c) u8 {
|
|
52
49
|
assert(!err(result));
|
|
53
50
|
return @intFromEnum(@as(pkmn.Result, @bitCast(result)).p2);
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
pub fn err(result: u8) callconv(.
|
|
53
|
+
pub fn err(result: u8) callconv(.c) bool {
|
|
57
54
|
return result == ERROR;
|
|
58
55
|
}
|
|
59
56
|
|
|
60
|
-
pub fn psrng_init(prng: *pkmn.PSRNG, seed: u64) callconv(.
|
|
57
|
+
pub fn psrng_init(prng: *pkmn.PSRNG, seed: u64) callconv(.c) void {
|
|
61
58
|
prng.src = .{ .seed = seed };
|
|
62
59
|
}
|
|
63
60
|
|
|
64
|
-
pub fn psrng_next(prng: *pkmn.PSRNG) callconv(.
|
|
61
|
+
pub fn psrng_next(prng: *pkmn.PSRNG) callconv(.c) u32 {
|
|
65
62
|
return prng.next();
|
|
66
63
|
}
|
|
67
64
|
|
|
68
|
-
pub fn rational_init(rational: *pkmn.Rational(f64)) callconv(.
|
|
65
|
+
pub fn rational_init(rational: *pkmn.Rational(f64)) callconv(.c) void {
|
|
69
66
|
rational.reset();
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
pub fn rational_reduce(rational: *pkmn.Rational(f64)) callconv(.
|
|
69
|
+
pub fn rational_reduce(rational: *pkmn.Rational(f64)) callconv(.c) void {
|
|
73
70
|
rational.reduce();
|
|
74
71
|
}
|
|
75
72
|
|
|
76
|
-
pub fn rational_numerator(rational: *const pkmn.Rational(f64)) callconv(.
|
|
73
|
+
pub fn rational_numerator(rational: *const pkmn.Rational(f64)) callconv(.c) f64 {
|
|
77
74
|
return rational.p;
|
|
78
75
|
}
|
|
79
76
|
|
|
80
|
-
pub fn rational_denominator(rational: *const pkmn.Rational(f64)) callconv(.
|
|
77
|
+
pub fn rational_denominator(rational: *const pkmn.Rational(f64)) callconv(.c) f64 {
|
|
81
78
|
return rational.q;
|
|
82
79
|
}
|
|
83
80
|
|
|
@@ -106,7 +103,7 @@ pub fn gen(comptime num: comptime_int) type {
|
|
|
106
103
|
};
|
|
107
104
|
|
|
108
105
|
const battle_options = struct {
|
|
109
|
-
|
|
106
|
+
writer: pkmn.protocol.Writer,
|
|
110
107
|
log: pkmn.protocol.FixedLog,
|
|
111
108
|
chance: g.Chance(pkmn.Rational(f64)),
|
|
112
109
|
calc: g.Calc,
|
|
@@ -121,13 +118,13 @@ pub fn gen(comptime num: comptime_int) type {
|
|
|
121
118
|
log: ?*const log_options,
|
|
122
119
|
chance: ?*const chance_options,
|
|
123
120
|
calc: ?*const calc_options,
|
|
124
|
-
) callconv(.
|
|
121
|
+
) callconv(.c) void {
|
|
125
122
|
if (pkmn.options.log) {
|
|
126
123
|
if (log) |l| {
|
|
127
|
-
options.
|
|
128
|
-
options.log = .{ .writer = options.
|
|
124
|
+
options.writer = .{ .buffer = l.buf[0..l.len] };
|
|
125
|
+
options.log = .{ .writer = &options.writer };
|
|
129
126
|
} else {
|
|
130
|
-
options.
|
|
127
|
+
options.writer.reset();
|
|
131
128
|
}
|
|
132
129
|
}
|
|
133
130
|
if (pkmn.options.chance) {
|
|
@@ -152,25 +149,25 @@ pub fn gen(comptime num: comptime_int) type {
|
|
|
152
149
|
|
|
153
150
|
pub fn battle_options_chance_probability(
|
|
154
151
|
options: *battle_options,
|
|
155
|
-
) callconv(.
|
|
152
|
+
) callconv(.c) *pkmn.Rational(f64) {
|
|
156
153
|
return &options.chance.probability;
|
|
157
154
|
}
|
|
158
155
|
|
|
159
156
|
pub fn battle_options_chance_actions(
|
|
160
157
|
options: *battle_options,
|
|
161
|
-
) callconv(.
|
|
158
|
+
) callconv(.c) *g.chance.Actions {
|
|
162
159
|
return &options.chance.actions;
|
|
163
160
|
}
|
|
164
161
|
|
|
165
162
|
pub fn battle_options_chance_durations(
|
|
166
163
|
options: *battle_options,
|
|
167
|
-
) callconv(.
|
|
164
|
+
) callconv(.c) *g.chance.Durations {
|
|
168
165
|
return &options.chance.durations;
|
|
169
166
|
}
|
|
170
167
|
|
|
171
168
|
pub fn battle_options_calc_summaries(
|
|
172
169
|
options: *battle_options,
|
|
173
|
-
) callconv(.
|
|
170
|
+
) callconv(.c) *g.calc.Summaries {
|
|
174
171
|
return &options.calc.summaries;
|
|
175
172
|
}
|
|
176
173
|
|
|
@@ -179,7 +176,7 @@ pub fn gen(comptime num: comptime_int) type {
|
|
|
179
176
|
c1: pkmn.Choice,
|
|
180
177
|
c2: pkmn.Choice,
|
|
181
178
|
opts: ?*battle_options,
|
|
182
|
-
) callconv(.
|
|
179
|
+
) callconv(.c) pkmn.Result {
|
|
183
180
|
if ((pkmn.options.log or pkmn.options.chance or pkmn.options.calc) and opts != null) {
|
|
184
181
|
return battle.update(c1, c2, opts.?) catch return @bitCast(ERROR);
|
|
185
182
|
}
|
|
@@ -192,64 +189,12 @@ pub fn gen(comptime num: comptime_int) type {
|
|
|
192
189
|
request: u8,
|
|
193
190
|
out: [*]u8,
|
|
194
191
|
n: usize,
|
|
195
|
-
) callconv(.
|
|
196
|
-
assert(player <= @
|
|
197
|
-
assert(request <= @
|
|
192
|
+
) callconv(.c) u8 {
|
|
193
|
+
assert(player <= @typeInfo(pkmn.Player).@"enum".fields.len);
|
|
194
|
+
assert(request <= @typeInfo(pkmn.Choice.Type).@"enum".fields.len);
|
|
198
195
|
|
|
199
196
|
assert(!pkmn.options.showdown or n > 0);
|
|
200
197
|
return battle.choices(@enumFromInt(player), @enumFromInt(request), @ptrCast(out[0..n]));
|
|
201
198
|
}
|
|
202
199
|
};
|
|
203
200
|
}
|
|
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
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const c = @import("
|
|
1
|
+
const c = @import("napi");
|
|
2
2
|
const js = @import("../common/js.zig");
|
|
3
3
|
const pkmn = @import("../pkmn.zig");
|
|
4
4
|
const std = @import("std");
|
|
@@ -49,7 +49,7 @@ fn bind(env: c.napi_env, gen: anytype) c.napi_value {
|
|
|
49
49
|
|
|
50
50
|
fn update(gen: anytype) c.napi_callback {
|
|
51
51
|
return struct {
|
|
52
|
-
fn call(env: c.napi_env, info: c.napi_callback_info) callconv(.
|
|
52
|
+
fn call(env: c.napi_env, info: c.napi_callback_info) callconv(.c) c.napi_value {
|
|
53
53
|
var argc: usize = 4;
|
|
54
54
|
var argv: [4]c.napi_value = undefined;
|
|
55
55
|
assert(c.napi_get_cb_info(env, info, &argc, &argv, null, null) == c.napi_ok);
|
|
@@ -60,7 +60,7 @@ fn update(gen: anytype) c.napi_callback {
|
|
|
60
60
|
assert(c.napi_get_arraybuffer_info(env, argv[0], &data, &len) == c.napi_ok);
|
|
61
61
|
assert(len == @sizeOf(gen.Battle(gen.PRNG)));
|
|
62
62
|
|
|
63
|
-
var battle: *gen.Battle(gen.PRNG) = @
|
|
63
|
+
var battle: *gen.Battle(gen.PRNG) = @ptrCast(@alignCast(data.?));
|
|
64
64
|
const c1: pkmn.Choice = @bitCast(js.Number.get(env, argv[1], u8));
|
|
65
65
|
const c2: pkmn.Choice = @bitCast(js.Number.get(env, argv[2], u8));
|
|
66
66
|
|
|
@@ -73,10 +73,10 @@ fn update(gen: anytype) c.napi_callback {
|
|
|
73
73
|
assert(len == gen.LOGS_SIZE);
|
|
74
74
|
|
|
75
75
|
const buf = @as([*]u8, @ptrCast(data.?))[0..gen.LOGS_SIZE];
|
|
76
|
-
var
|
|
76
|
+
var writer: pkmn.protocol.Writer = .{ .buffer = buf };
|
|
77
77
|
// TODO: extract out
|
|
78
78
|
var opts = pkmn.battle.options(
|
|
79
|
-
pkmn.protocol.FixedLog{ .writer =
|
|
79
|
+
pkmn.protocol.FixedLog{ .writer = &writer },
|
|
80
80
|
gen.chance.NULL,
|
|
81
81
|
gen.calc.NULL,
|
|
82
82
|
);
|
|
@@ -91,7 +91,7 @@ fn update(gen: anytype) c.napi_callback {
|
|
|
91
91
|
|
|
92
92
|
fn choices(gen: anytype) c.napi_callback {
|
|
93
93
|
return struct {
|
|
94
|
-
fn call(env: c.napi_env, info: c.napi_callback_info) callconv(.
|
|
94
|
+
fn call(env: c.napi_env, info: c.napi_callback_info) callconv(.c) c.napi_value {
|
|
95
95
|
var argc: usize = 4;
|
|
96
96
|
var argv: [4]c.napi_value = undefined;
|
|
97
97
|
assert(c.napi_get_cb_info(env, info, &argc, &argv, null, null) == c.napi_ok);
|
|
@@ -102,7 +102,7 @@ fn choices(gen: anytype) c.napi_callback {
|
|
|
102
102
|
assert(c.napi_get_arraybuffer_info(env, argv[0], &data, &len) == c.napi_ok);
|
|
103
103
|
assert(len == @sizeOf(gen.Battle(gen.PRNG)));
|
|
104
104
|
|
|
105
|
-
var battle: *gen.Battle(gen.PRNG) = @
|
|
105
|
+
var battle: *gen.Battle(gen.PRNG) = @ptrCast(@alignCast(data.?));
|
|
106
106
|
const player: pkmn.Player = @enumFromInt(js.Number.get(env, argv[1], u8));
|
|
107
107
|
const request: pkmn.Choice.Type = @enumFromInt(js.Number.get(env, argv[2], u8));
|
|
108
108
|
|
|
@@ -3,9 +3,6 @@ const std = @import("std");
|
|
|
3
3
|
|
|
4
4
|
const assert = std.debug.assert;
|
|
5
5
|
|
|
6
|
-
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
7
|
-
const Strong = if (@hasField(std.builtin.GlobalLinkage, "strong")) .strong else .Strong;
|
|
8
|
-
|
|
9
6
|
pub const options = pkmn.options;
|
|
10
7
|
|
|
11
8
|
pub fn gen(comptime num: comptime_int) type {
|
|
@@ -19,13 +16,13 @@ pub fn gen(comptime num: comptime_int) type {
|
|
|
19
16
|
c1: pkmn.Choice,
|
|
20
17
|
c2: pkmn.Choice,
|
|
21
18
|
options_: ?[*]u8,
|
|
22
|
-
) callconv(.
|
|
19
|
+
) callconv(.c) pkmn.Result {
|
|
23
20
|
return (if (options_) |o| result: {
|
|
24
21
|
const buf = @as([*]u8, @ptrCast(o))[0..g.LOGS_SIZE];
|
|
25
|
-
var
|
|
22
|
+
var writer: pkmn.protocol.Writer = .{ .buffer = buf };
|
|
26
23
|
// TODO: extract out
|
|
27
24
|
var opts = pkmn.battle.options(
|
|
28
|
-
pkmn.protocol.FixedLog{ .writer =
|
|
25
|
+
pkmn.protocol.FixedLog{ .writer = &writer },
|
|
29
26
|
g.chance.NULL,
|
|
30
27
|
g.calc.NULL,
|
|
31
28
|
);
|
|
@@ -38,9 +35,9 @@ pub fn gen(comptime num: comptime_int) type {
|
|
|
38
35
|
player: u8,
|
|
39
36
|
request: u8,
|
|
40
37
|
buf: [*]u8,
|
|
41
|
-
) callconv(.
|
|
42
|
-
assert(player <= @
|
|
43
|
-
assert(request <= @
|
|
38
|
+
) callconv(.c) u8 {
|
|
39
|
+
assert(player <= @typeInfo(pkmn.Player).@"enum".fields.len);
|
|
40
|
+
assert(request <= @typeInfo(pkmn.Choice.Type).@"enum".fields.len);
|
|
44
41
|
|
|
45
42
|
const n = CHOICES_SIZE;
|
|
46
43
|
return battle.choices(@enumFromInt(player), @enumFromInt(request), @ptrCast(buf[0..n]));
|
|
@@ -48,12 +45,6 @@ pub fn gen(comptime num: comptime_int) type {
|
|
|
48
45
|
};
|
|
49
46
|
}
|
|
50
47
|
|
|
51
|
-
pub fn exports() type {
|
|
52
|
-
@export(gen(1).update, .{ .name = "GEN1_update", .linkage = Strong });
|
|
53
|
-
@export(gen(1).choices, .{ .name = "GEN1_choices", .linkage = Strong });
|
|
54
|
-
return struct {};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
48
|
fn size(n: usize) u32 {
|
|
58
49
|
return std.math.ceilPowerOfTwo(u32, @as(u32, @intCast(n))) catch unreachable;
|
|
59
50
|
}
|
package/src/lib/common/array.zig
CHANGED
|
@@ -3,19 +3,12 @@ const std = @import("std");
|
|
|
3
3
|
const expectEqual = std.testing.expectEqual;
|
|
4
4
|
const assert = std.debug.assert;
|
|
5
5
|
|
|
6
|
-
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
7
|
-
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
8
|
-
|
|
9
6
|
/// Helpers for working with bit-packed arrays of non-powers-of-2 types.
|
|
10
7
|
/// NOTE: ziglang/zig#12547
|
|
11
8
|
pub fn Array(comptime n: comptime_int, comptime U: type) type {
|
|
12
9
|
return struct {
|
|
13
10
|
const size = @bitSizeOf(U);
|
|
14
|
-
const
|
|
15
|
-
pub const T = @Type(if (@hasField(std.builtin.Type, "int"))
|
|
16
|
-
.{ .int = options }
|
|
17
|
-
else
|
|
18
|
-
.{ .Int = options });
|
|
11
|
+
pub const T = @Int(.unsigned, size * n);
|
|
19
12
|
|
|
20
13
|
/// Returns the value stored at index `i` in the array `a`.
|
|
21
14
|
pub fn get(a: T, i: usize) U {
|
|
@@ -24,8 +17,8 @@ pub fn Array(comptime n: comptime_int, comptime U: type) type {
|
|
|
24
17
|
const mask: T = (1 << size) - 1;
|
|
25
18
|
const result = (a >> @intCast(shift)) & mask;
|
|
26
19
|
return switch (@typeInfo(U)) {
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
.@"enum" => @enumFromInt(result),
|
|
21
|
+
.int => @intCast(result),
|
|
29
22
|
else => unreachable,
|
|
30
23
|
};
|
|
31
24
|
}
|
|
@@ -34,8 +27,8 @@ pub fn Array(comptime n: comptime_int, comptime U: type) type {
|
|
|
34
27
|
pub fn set(a: T, i: usize, val: U) T {
|
|
35
28
|
assert(i < n);
|
|
36
29
|
const v: T = switch (@typeInfo(U)) {
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
.@"enum" => @intFromEnum(val),
|
|
31
|
+
.int => @intCast(val),
|
|
39
32
|
else => unreachable,
|
|
40
33
|
};
|
|
41
34
|
const shift = i * size;
|
package/src/lib/common/debug.zig
CHANGED
|
@@ -1,27 +1,20 @@
|
|
|
1
|
+
const builtin = @import("builtin");
|
|
1
2
|
const std = @import("std");
|
|
2
3
|
|
|
3
4
|
const debug = std.debug;
|
|
4
|
-
const io = std.io;
|
|
5
|
-
|
|
6
|
-
const Array = if (@hasField(std.builtin.Type, "array")) .array else .Array;
|
|
7
|
-
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
8
|
-
const Optional = if (@hasField(std.builtin.Type, "optional")) .optional else .Optional;
|
|
9
|
-
const Pointer = if (@hasField(std.builtin.Type, "pointer")) .pointer else .Pointer;
|
|
10
|
-
const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
|
|
11
|
-
const Union = if (@hasField(std.builtin.Type, "union")) .@"union" else .Union;
|
|
12
5
|
|
|
13
6
|
pub fn print(value: anytype) void {
|
|
14
|
-
if (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
if (builtin.target.os.tag == .freestanding) return;
|
|
8
|
+
|
|
9
|
+
var buffer: [4096]u8 = undefined;
|
|
10
|
+
const stderr = debug.lockStderr(&buffer);
|
|
11
|
+
defer debug.unlockStderr();
|
|
12
|
+
var fw = stderr.file_writer;
|
|
20
13
|
|
|
21
14
|
nosuspend {
|
|
22
|
-
|
|
15
|
+
fw.interface.writeAll("\x1b[41m") catch return;
|
|
23
16
|
if (@TypeOf(@src()) == @TypeOf(value)) {
|
|
24
|
-
|
|
17
|
+
fw.interface.print("{s} ({s}:{d}:{d})", .{
|
|
25
18
|
value.fn_name,
|
|
26
19
|
value.file,
|
|
27
20
|
value.line,
|
|
@@ -29,77 +22,58 @@ pub fn print(value: anytype) void {
|
|
|
29
22
|
}) catch return;
|
|
30
23
|
} else {
|
|
31
24
|
switch (@typeInfo(@TypeOf(value))) {
|
|
32
|
-
|
|
25
|
+
.@"struct" => |info| {
|
|
33
26
|
if (info.is_tuple) {
|
|
34
27
|
inline for (info.fields, 0..) |f, i| {
|
|
35
|
-
inspect(@field(value, f.name));
|
|
36
|
-
if (i < info.fields.len - 1)
|
|
28
|
+
inspect(fw, @field(value, f.name));
|
|
29
|
+
if (i < info.fields.len - 1) fw.interface.writeAll(" ") catch return;
|
|
37
30
|
}
|
|
38
31
|
} else {
|
|
39
|
-
inspect(value);
|
|
32
|
+
inspect(fw, value);
|
|
40
33
|
}
|
|
41
34
|
},
|
|
42
|
-
else => inspect(value),
|
|
35
|
+
else => inspect(fw, value),
|
|
43
36
|
}
|
|
44
37
|
}
|
|
45
|
-
|
|
38
|
+
fw.interface.writeAll("\x1b[K\x1b[0m\n") catch return;
|
|
46
39
|
}
|
|
47
40
|
}
|
|
48
41
|
|
|
49
|
-
fn inspect(value: anytype) void {
|
|
50
|
-
const stderr = io.getStdErr().writer();
|
|
51
|
-
|
|
42
|
+
fn inspect(w: anytype, value: anytype) void {
|
|
52
43
|
nosuspend {
|
|
53
44
|
const err = "Unable to format type '" ++ @typeName(@TypeOf(value)) ++ "'";
|
|
54
45
|
switch (@typeInfo(@TypeOf(value))) {
|
|
55
|
-
|
|
56
|
-
if (info.child == u8) return
|
|
46
|
+
.array => |info| {
|
|
47
|
+
if (info.child == u8) return w.interface.print("{s}", .{value}) catch return;
|
|
57
48
|
@compileError(err);
|
|
58
49
|
},
|
|
59
|
-
|
|
60
|
-
.
|
|
61
|
-
|
|
62
|
-
if (info.child == u8)
|
|
50
|
+
.pointer => |ptr_info| switch (ptr_info.size) {
|
|
51
|
+
.one => switch (@typeInfo(ptr_info.child)) {
|
|
52
|
+
.array => |info| {
|
|
53
|
+
if (info.child == u8) {
|
|
54
|
+
return w.interface.print("{s}", .{value}) catch return;
|
|
55
|
+
}
|
|
63
56
|
@compileError(err);
|
|
64
57
|
},
|
|
65
|
-
|
|
58
|
+
.@"enum", .@"union", .@"struct" => return inspect(value.*),
|
|
66
59
|
else => @compileError(err),
|
|
67
60
|
},
|
|
68
|
-
.
|
|
61
|
+
.many, .c => {
|
|
69
62
|
if (ptr_info.sentinel) |_| return inspect(std.mem.span(value));
|
|
70
63
|
if (ptr_info.child == u8) {
|
|
71
|
-
return
|
|
64
|
+
return w.interface.print("{s}", .{std.mem.span(value)}) catch return;
|
|
72
65
|
}
|
|
73
66
|
@compileError(err);
|
|
74
67
|
},
|
|
75
|
-
.
|
|
76
|
-
if (ptr_info.child == u8)
|
|
68
|
+
.slice => {
|
|
69
|
+
if (ptr_info.child == u8) {
|
|
70
|
+
return w.interface.print("{s}", .{value}) catch return;
|
|
71
|
+
}
|
|
77
72
|
@compileError(err);
|
|
78
73
|
},
|
|
79
74
|
},
|
|
80
|
-
|
|
81
|
-
else =>
|
|
75
|
+
.optional => w.interface.print("{?}", .{value}) catch return,
|
|
76
|
+
else => w.interface.print("{}", .{value}) catch return,
|
|
82
77
|
}
|
|
83
78
|
}
|
|
84
79
|
}
|
|
85
|
-
|
|
86
|
-
const showdown = @import("./options.zig").showdown;
|
|
87
|
-
const Result = @import("./data.zig").Result;
|
|
88
|
-
const Choice = @import("./data.zig").Choice;
|
|
89
|
-
|
|
90
|
-
pub fn dump(gen: u8, battle: anytype, frame: ?struct { Result, Choice, Choice }) void {
|
|
91
|
-
const file = std.fs.cwd().createFile("logs/dump.bin", .{}) catch return;
|
|
92
|
-
defer file.close();
|
|
93
|
-
var w = file.writer();
|
|
94
|
-
w.writeByte(@intFromBool(showdown)) catch return;
|
|
95
|
-
w.writeByte(gen) catch return;
|
|
96
|
-
w.writeInt(i16, 0, .little) catch return;
|
|
97
|
-
w.writeInt(i32, 0, .little) catch return;
|
|
98
|
-
w.writeStruct(battle) catch return;
|
|
99
|
-
w.writeStruct(battle) catch return;
|
|
100
|
-
if (frame) |f| {
|
|
101
|
-
w.writeStruct(f[0]) catch return;
|
|
102
|
-
w.writeStruct(f[1]) catch return;
|
|
103
|
-
w.writeStruct(f[2]) catch return;
|
|
104
|
-
}
|
|
105
|
-
}
|