@pkmn/engine 0.1.0-dev.645b4750 → 0.1.0-dev.6b383c80

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 (53) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +22 -61
  3. package/build/pkg/addon/browser.js +2 -2
  4. package/build/pkg/addon/browser.js.map +1 -1
  5. package/build/pkg/addon/node.js +3 -3
  6. package/build/pkg/addon/node.js.map +1 -1
  7. package/build/pkg/addon/wasm.js.map +1 -1
  8. package/build/pkg/addon.d.ts +4 -4
  9. package/build/pkg/addon.js.map +1 -1
  10. package/build/pkg/data.js.map +1 -1
  11. package/build/pkg/gen1.js.map +1 -1
  12. package/build/pkg/protocol.d.ts +11 -2
  13. package/build/pkg/protocol.js.map +1 -1
  14. package/build/tools/debug.js +37 -3
  15. package/build/tools/debug.js.map +1 -1
  16. package/build/tools/display/debug.jsx +1 -87
  17. package/build/tools/display/debug.jsx.map +1 -1
  18. package/build/tools/display/ui.jsx +3 -2
  19. package/build/tools/display/ui.jsx.map +1 -1
  20. package/build/tools/display/util.js +125 -1
  21. package/build/tools/display/util.js.map +1 -1
  22. package/build.zig +224 -350
  23. package/package.json +22 -22
  24. package/src/bin/install-pkmn-engine +23 -22
  25. package/src/lib/bindings/c.zig +28 -82
  26. package/src/lib/bindings/node.zig +7 -11
  27. package/src/lib/bindings/wasm.zig +7 -15
  28. package/src/lib/common/array.zig +9 -16
  29. package/src/lib/common/data.zig +8 -8
  30. package/src/lib/common/debug.zig +46 -61
  31. package/src/lib/common/js.zig +3 -9
  32. package/src/lib/common/optional.zig +20 -25
  33. package/src/lib/common/protocol.zig +224 -189
  34. package/src/lib/common/rational.zig +91 -173
  35. package/src/lib/common/rng.zig +4 -4
  36. package/src/lib/common/util.zig +34 -46
  37. package/src/lib/gen1/calc.zig +128 -115
  38. package/src/lib/gen1/chance.zig +162 -101
  39. package/src/lib/gen1/data/types.zig +2 -2
  40. package/src/lib/gen1/data.zig +27 -24
  41. package/src/lib/gen1/helpers.zig +36 -26
  42. package/src/lib/gen1/mechanics.zig +42 -38
  43. package/src/lib/gen2/calc.zig +3 -6
  44. package/src/lib/gen2/chance.zig +55 -43
  45. package/src/lib/gen2/data/types.zig +6 -3
  46. package/src/lib/gen2/data.zig +20 -16
  47. package/src/lib/gen2/helpers.zig +27 -19
  48. package/src/lib/gen2/mechanics.zig +25 -36
  49. package/src/lib/napi.h +2 -0
  50. package/src/lib/node.zig +1 -5
  51. package/src/lib/pkmn.zig +91 -17
  52. package/src/lib/wasm.zig +2 -6
  53. package/src/tools/display/dom.ts +40 -25
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pkmn/engine",
3
- "version": "0.1.0-dev.645b4750",
3
+ "version": "0.1.0-dev.6b383c80",
4
4
  "description": "A minimal, complete, Pokémon battle simulation engine optimized for performance",
5
5
  "repository": "github:pkmn/engine",
6
6
  "license": "MIT",
@@ -81,6 +81,7 @@
81
81
  "src/lib/gen2/generated.zig",
82
82
  "src/lib/gen2/helpers.zig",
83
83
  "src/lib/gen2/mechanics.zig",
84
+ "src/lib/napi.h",
84
85
  "src/lib/node.zig",
85
86
  "src/lib/pkmn.zig",
86
87
  "src/lib/wasm.zig",
@@ -98,38 +99,37 @@
98
99
  "access": "public"
99
100
  },
100
101
  "dependencies": {
101
- "@pkmn/data": "^0.9.31",
102
- "@pkmn/protocol": "^0.6.31"
102
+ "@pkmn/data": "0.9.35",
103
+ "@pkmn/protocol": "^0.7.3"
103
104
  },
104
105
  "devDependencies": {
105
- "@pkmn/eslint-config": "^9.7.0",
106
- "@pkmn/img": "^0.2.36",
107
- "@pkmn/sets": "^5.1.2",
106
+ "@pkmn/dex-types": "0.9.35",
107
+ "@pkmn/eslint-config": "^10.0.0",
108
+ "@pkmn/img": "^0.3.4",
109
+ "@pkmn/sets": "^5.2.0",
108
110
  "@pkmn/sim": "0.9.31",
109
- "@pkmn/smogon": "^0.5.19",
110
- "@types/html-minifier": "^4.0.5",
111
- "@types/jest": "^29.5.14",
111
+ "@pkmn/smogon": "0.5.21",
112
+ "@types/html-minifier": "^4.0.6",
113
+ "@types/jest": "^30.0.0",
112
114
  "@types/minimist": "^1.2.5",
113
- "@types/mustache": "^4.2.5",
114
- "@types/node": "^22.13.9",
115
- "@types/react": "<=18",
116
- "@types/semver": "^7.5.8",
117
- "@types/vscode": "^1.97.0",
118
- "@vitest/coverage-v8": "^3.0.7",
119
- "@vscode/vsce": "^3.2.2",
120
- "binaryen": "^122.0.0",
121
- "esbuild": "^0.25.0",
122
- "eslint": "^9.21.0",
115
+ "@types/mustache": "^4.2.6",
116
+ "@types/node": "^26.6.3",
117
+ "@types/react": "^19.3.0",
118
+ "@types/vscode": "^1.140.0",
119
+ "@vitest/coverage-v8": "^5.0.3",
120
+ "@vscode/vsce": "^4.0.0",
121
+ "binaryen": "^132.0.0",
122
+ "esbuild": "^0.28.2",
123
+ "eslint": "^10.11.0",
123
124
  "html-minifier": "^4.0.0",
124
125
  "json-stringify-pretty-compact": "3.0.0",
125
126
  "minimist": "^1.2.8",
126
127
  "mustache": "^4.2.0",
127
- "semver": "^7.7.1",
128
128
  "source-map-support": "^0.5.21",
129
129
  "table": "^6.9.0",
130
130
  "trakr": "^0.2.0",
131
- "typescript": "^5.8.2",
132
- "vitest": "^3.0.7"
131
+ "typescript": "^6.0.3",
132
+ "vitest": "^5.0.3"
133
133
  },
134
134
  "scripts": {
135
135
  "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: 11, patch: 0};
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} = JSON.parse(sh(zig, ['env']));
117
- const [major, minor, patch, dev] = version.split('.').map(n => parseInt(n));
132
+ const {zig_exe, version} = parse(sh(zig, ['env']));
133
+ const [major, minor, patch, dev] = version.split('.').map(n => parseInt(n, 10));
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, 10))));
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
- // TODO: ziglang/zig#17768
167
- // const version = Object.keys(index)[+!ZIG_VERSION.dev];
168
- const version = VERSION;
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);
@@ -386,20 +401,6 @@ const downloadImportLib = async () => {
386
401
  const artifact = path.join('build', 'lib', `pkmn${suffix}.${config.type}`);
387
402
  log(`Building ${artifact}${flags}`);
388
403
  sh(zig, args);
389
- // TODO: ziglang/zig#14647 broke emit_to so we get to rename the file ourselves...
390
- if (config.type === 'node') {
391
- const prefix = process.platform === 'win32' ? '' : 'lib';
392
- const ext = process.platform === 'darwin'
393
- ? 'dylib' : process.platform === 'win32' ? 'dll' : 'so';
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
- }
402
- }
403
404
  }
404
405
  })().catch(e => {
405
406
  console.error(e);
@@ -1,13 +1,11 @@
1
1
  const pkmn = @import("../pkmn.zig");
2
2
  const std = @import("std");
3
+ const util = @import("../common/util.zig");
3
4
 
4
5
  const assert = std.debug.assert;
5
6
 
6
7
  const ERROR: u8 = 0b1100;
7
8
 
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
9
  pub const OPTIONS: extern struct {
12
10
  showdown: bool,
13
11
  log: bool,
@@ -25,59 +23,59 @@ pub const CHOICES_SIZE = pkmn.CHOICES_SIZE;
25
23
  pub const MAX_LOGS = pkmn.MAX_LOGS;
26
24
  pub const LOGS_SIZE = pkmn.LOGS_SIZE;
27
25
 
28
- pub fn choice_init(choice: u8, data: u8) callconv(.C) u8 {
29
- assert(choice <= @field(@typeInfo(pkmn.Choice.Type), @tagName(Enum)).fields.len);
26
+ pub fn choice_init(choice: u8, data: u8) callconv(.c) u8 {
27
+ assert(choice <= util.EnumFieldsLen(pkmn.Choice.Type));
30
28
  assert(data <= 6);
31
29
  return @bitCast(pkmn.Choice{ .type = @enumFromInt(choice), .data = @intCast(data) });
32
30
  }
33
31
 
34
- pub fn choice_type(choice: u8) callconv(.C) u8 {
32
+ pub fn choice_type(choice: u8) callconv(.c) u8 {
35
33
  return @intFromEnum(@as(pkmn.Choice, @bitCast(choice)).type);
36
34
  }
37
35
 
38
- pub fn choice_data(choice: u8) callconv(.C) u8 {
36
+ pub fn choice_data(choice: u8) callconv(.c) u8 {
39
37
  return @as(u8, @as(pkmn.Choice, @bitCast(choice)).data);
40
38
  }
41
39
 
42
- pub fn result_type(result: u8) callconv(.C) u8 {
40
+ pub fn result_type(result: u8) callconv(.c) u8 {
43
41
  return @intFromEnum(@as(pkmn.Result, @bitCast(result)).type);
44
42
  }
45
43
 
46
- pub fn result_p1(result: u8) callconv(.C) u8 {
44
+ pub fn result_p1(result: u8) callconv(.c) u8 {
47
45
  assert(!err(result));
48
46
  return @intFromEnum(@as(pkmn.Result, @bitCast(result)).p1);
49
47
  }
50
48
 
51
- pub fn result_p2(result: u8) callconv(.C) u8 {
49
+ pub fn result_p2(result: u8) callconv(.c) u8 {
52
50
  assert(!err(result));
53
51
  return @intFromEnum(@as(pkmn.Result, @bitCast(result)).p2);
54
52
  }
55
53
 
56
- pub fn err(result: u8) callconv(.C) bool {
54
+ pub fn err(result: u8) callconv(.c) bool {
57
55
  return result == ERROR;
58
56
  }
59
57
 
60
- pub fn psrng_init(prng: *pkmn.PSRNG, seed: u64) callconv(.C) void {
58
+ pub fn psrng_init(prng: *pkmn.PSRNG, seed: u64) callconv(.c) void {
61
59
  prng.src = .{ .seed = seed };
62
60
  }
63
61
 
64
- pub fn psrng_next(prng: *pkmn.PSRNG) callconv(.C) u32 {
62
+ pub fn psrng_next(prng: *pkmn.PSRNG) callconv(.c) u32 {
65
63
  return prng.next();
66
64
  }
67
65
 
68
- pub fn rational_init(rational: *pkmn.Rational(f64)) callconv(.C) void {
66
+ pub fn rational_init(rational: *pkmn.Rational(f64)) callconv(.c) void {
69
67
  rational.reset();
70
68
  }
71
69
 
72
- pub fn rational_reduce(rational: *pkmn.Rational(f64)) callconv(.C) void {
70
+ pub fn rational_reduce(rational: *pkmn.Rational(f64)) callconv(.c) void {
73
71
  rational.reduce();
74
72
  }
75
73
 
76
- pub fn rational_numerator(rational: *const pkmn.Rational(f64)) callconv(.C) f64 {
74
+ pub fn rational_numerator(rational: *const pkmn.Rational(f64)) callconv(.c) f64 {
77
75
  return rational.p;
78
76
  }
79
77
 
80
- pub fn rational_denominator(rational: *const pkmn.Rational(f64)) callconv(.C) f64 {
78
+ pub fn rational_denominator(rational: *const pkmn.Rational(f64)) callconv(.c) f64 {
81
79
  return rational.q;
82
80
  }
83
81
 
@@ -106,7 +104,7 @@ pub fn gen(comptime num: comptime_int) type {
106
104
  };
107
105
 
108
106
  const battle_options = struct {
109
- stream: pkmn.protocol.ByteStream,
107
+ writer: pkmn.protocol.Writer,
110
108
  log: pkmn.protocol.FixedLog,
111
109
  chance: g.Chance(pkmn.Rational(f64)),
112
110
  calc: g.Calc,
@@ -121,13 +119,13 @@ pub fn gen(comptime num: comptime_int) type {
121
119
  log: ?*const log_options,
122
120
  chance: ?*const chance_options,
123
121
  calc: ?*const calc_options,
124
- ) callconv(.C) void {
122
+ ) callconv(.c) void {
125
123
  if (pkmn.options.log) {
126
124
  if (log) |l| {
127
- options.stream = .{ .buffer = l.buf[0..l.len] };
128
- options.log = .{ .writer = options.stream.writer() };
125
+ options.writer = .{ .buffer = l.buf[0..l.len] };
126
+ options.log = .{ .writer = &options.writer };
129
127
  } else {
130
- options.stream.reset();
128
+ options.writer.reset();
131
129
  }
132
130
  }
133
131
  if (pkmn.options.chance) {
@@ -152,25 +150,25 @@ pub fn gen(comptime num: comptime_int) type {
152
150
 
153
151
  pub fn battle_options_chance_probability(
154
152
  options: *battle_options,
155
- ) callconv(.C) *pkmn.Rational(f64) {
153
+ ) callconv(.c) *pkmn.Rational(f64) {
156
154
  return &options.chance.probability;
157
155
  }
158
156
 
159
157
  pub fn battle_options_chance_actions(
160
158
  options: *battle_options,
161
- ) callconv(.C) *g.chance.Actions {
159
+ ) callconv(.c) *g.chance.Actions {
162
160
  return &options.chance.actions;
163
161
  }
164
162
 
165
163
  pub fn battle_options_chance_durations(
166
164
  options: *battle_options,
167
- ) callconv(.C) *g.chance.Durations {
165
+ ) callconv(.c) *g.chance.Durations {
168
166
  return &options.chance.durations;
169
167
  }
170
168
 
171
169
  pub fn battle_options_calc_summaries(
172
170
  options: *battle_options,
173
- ) callconv(.C) *g.calc.Summaries {
171
+ ) callconv(.c) *g.calc.Summaries {
174
172
  return &options.calc.summaries;
175
173
  }
176
174
 
@@ -179,7 +177,7 @@ pub fn gen(comptime num: comptime_int) type {
179
177
  c1: pkmn.Choice,
180
178
  c2: pkmn.Choice,
181
179
  opts: ?*battle_options,
182
- ) callconv(.C) pkmn.Result {
180
+ ) callconv(.c) pkmn.Result {
183
181
  if ((pkmn.options.log or pkmn.options.chance or pkmn.options.calc) and opts != null) {
184
182
  return battle.update(c1, c2, opts.?) catch return @bitCast(ERROR);
185
183
  }
@@ -192,64 +190,12 @@ pub fn gen(comptime num: comptime_int) type {
192
190
  request: u8,
193
191
  out: [*]u8,
194
192
  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);
193
+ ) callconv(.c) u8 {
194
+ assert(player <= util.EnumFieldsLen(pkmn.Player));
195
+ assert(request <= util.EnumFieldsLen(pkmn.Choice.Type));
198
196
 
199
197
  assert(!pkmn.options.showdown or n > 0);
200
198
  return battle.choices(@enumFromInt(player), @enumFromInt(request), @ptrCast(out[0..n]));
201
199
  }
202
200
  };
203
201
  }
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,14 +1,10 @@
1
+ const c = @import("napi");
1
2
  const js = @import("../common/js.zig");
2
3
  const pkmn = @import("../pkmn.zig");
3
4
  const std = @import("std");
4
5
 
5
6
  const assert = std.debug.assert;
6
7
 
7
- const c = @cImport({
8
- @cDefine("NAPI_VERSION", "8");
9
- @cInclude("node_api.h");
10
- });
11
-
12
8
  pub fn register(env: c.napi_env) c.napi_value {
13
9
  const object = js.Object.init(env);
14
10
  const properties = [_]c.napi_property_descriptor{
@@ -53,7 +49,7 @@ fn bind(env: c.napi_env, gen: anytype) c.napi_value {
53
49
 
54
50
  fn update(gen: anytype) c.napi_callback {
55
51
  return struct {
56
- fn call(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
52
+ fn call(env: c.napi_env, info: c.napi_callback_info) callconv(.c) c.napi_value {
57
53
  var argc: usize = 4;
58
54
  var argv: [4]c.napi_value = undefined;
59
55
  assert(c.napi_get_cb_info(env, info, &argc, &argv, null, null) == c.napi_ok);
@@ -64,7 +60,7 @@ fn update(gen: anytype) c.napi_callback {
64
60
  assert(c.napi_get_arraybuffer_info(env, argv[0], &data, &len) == c.napi_ok);
65
61
  assert(len == @sizeOf(gen.Battle(gen.PRNG)));
66
62
 
67
- var battle: *gen.Battle(gen.PRNG) = @alignCast(@ptrCast(data.?));
63
+ var battle: *gen.Battle(gen.PRNG) = @ptrCast(@alignCast(data.?));
68
64
  const c1: pkmn.Choice = @bitCast(js.Number.get(env, argv[1], u8));
69
65
  const c2: pkmn.Choice = @bitCast(js.Number.get(env, argv[2], u8));
70
66
 
@@ -77,10 +73,10 @@ fn update(gen: anytype) c.napi_callback {
77
73
  assert(len == gen.LOGS_SIZE);
78
74
 
79
75
  const buf = @as([*]u8, @ptrCast(data.?))[0..gen.LOGS_SIZE];
80
- var stream: pkmn.protocol.ByteStream = .{ .buffer = buf };
76
+ var writer: pkmn.protocol.Writer = .{ .buffer = buf };
81
77
  // TODO: extract out
82
78
  var opts = pkmn.battle.options(
83
- pkmn.protocol.FixedLog{ .writer = stream.writer() },
79
+ pkmn.protocol.FixedLog{ .writer = &writer },
84
80
  gen.chance.NULL,
85
81
  gen.calc.NULL,
86
82
  );
@@ -95,7 +91,7 @@ fn update(gen: anytype) c.napi_callback {
95
91
 
96
92
  fn choices(gen: anytype) c.napi_callback {
97
93
  return struct {
98
- fn call(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value {
94
+ fn call(env: c.napi_env, info: c.napi_callback_info) callconv(.c) c.napi_value {
99
95
  var argc: usize = 4;
100
96
  var argv: [4]c.napi_value = undefined;
101
97
  assert(c.napi_get_cb_info(env, info, &argc, &argv, null, null) == c.napi_ok);
@@ -106,7 +102,7 @@ fn choices(gen: anytype) c.napi_callback {
106
102
  assert(c.napi_get_arraybuffer_info(env, argv[0], &data, &len) == c.napi_ok);
107
103
  assert(len == @sizeOf(gen.Battle(gen.PRNG)));
108
104
 
109
- var battle: *gen.Battle(gen.PRNG) = @alignCast(@ptrCast(data.?));
105
+ var battle: *gen.Battle(gen.PRNG) = @ptrCast(@alignCast(data.?));
110
106
  const player: pkmn.Player = @enumFromInt(js.Number.get(env, argv[1], u8));
111
107
  const request: pkmn.Choice.Type = @enumFromInt(js.Number.get(env, argv[2], u8));
112
108
 
@@ -1,11 +1,9 @@
1
1
  const pkmn = @import("../pkmn.zig");
2
2
  const std = @import("std");
3
+ const util = @import("../common/util.zig");
3
4
 
4
5
  const assert = std.debug.assert;
5
6
 
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
7
  pub const options = pkmn.options;
10
8
 
11
9
  pub fn gen(comptime num: comptime_int) type {
@@ -19,13 +17,13 @@ pub fn gen(comptime num: comptime_int) type {
19
17
  c1: pkmn.Choice,
20
18
  c2: pkmn.Choice,
21
19
  options_: ?[*]u8,
22
- ) callconv(.C) pkmn.Result {
20
+ ) callconv(.c) pkmn.Result {
23
21
  return (if (options_) |o| result: {
24
22
  const buf = @as([*]u8, @ptrCast(o))[0..g.LOGS_SIZE];
25
- var stream: pkmn.protocol.ByteStream = .{ .buffer = buf };
23
+ var writer: pkmn.protocol.Writer = .{ .buffer = buf };
26
24
  // TODO: extract out
27
25
  var opts = pkmn.battle.options(
28
- pkmn.protocol.FixedLog{ .writer = stream.writer() },
26
+ pkmn.protocol.FixedLog{ .writer = &writer },
29
27
  g.chance.NULL,
30
28
  g.calc.NULL,
31
29
  );
@@ -38,9 +36,9 @@ pub fn gen(comptime num: comptime_int) type {
38
36
  player: u8,
39
37
  request: u8,
40
38
  buf: [*]u8,
41
- ) callconv(.C) u8 {
42
- assert(player <= @field(@typeInfo(pkmn.Player), @tagName(Enum)).fields.len);
43
- assert(request <= @field(@typeInfo(pkmn.Choice.Type), @tagName(Enum)).fields.len);
39
+ ) callconv(.c) u8 {
40
+ assert(player <= util.EnumFieldsLen(pkmn.Player));
41
+ assert(request <= util.EnumFieldsLen(pkmn.Choice.Type));
44
42
 
45
43
  const n = CHOICES_SIZE;
46
44
  return battle.choices(@enumFromInt(player), @enumFromInt(request), @ptrCast(buf[0..n]));
@@ -48,12 +46,6 @@ pub fn gen(comptime num: comptime_int) type {
48
46
  };
49
47
  }
50
48
 
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
49
  fn size(n: usize) u32 {
58
50
  return std.math.ceilPowerOfTwo(u32, @as(u32, @intCast(n))) catch unreachable;
59
51
  }
@@ -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 options: std.builtin.Type.Int = .{ .signedness = .unsigned, .bits = size * n };
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
- Enum => @enumFromInt(result),
28
- Int => @intCast(result),
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
- Enum => @intFromEnum(val),
38
- Int => @intCast(val),
30
+ .@"enum" => @intFromEnum(val),
31
+ .int => @intCast(val),
39
32
  else => unreachable,
40
33
  };
41
34
  const shift = i * size;
@@ -52,9 +45,9 @@ test Array {
52
45
  try expectEqual(u40, @TypeOf(a));
53
46
 
54
47
  a = A.set(a, 4, 241);
55
- try expectEqual(@as(u8, 241), A.get(a, 4));
48
+ try expectEqual(241, A.get(a, 4));
56
49
  a = A.set(a, 4, 1);
57
- try expectEqual(@as(u8, 1), A.get(a, 4));
50
+ try expectEqual(1, A.get(a, 4));
58
51
 
59
52
  for (0..5) |i| a = A.set(a, i, @intCast(i));
60
53
  for (0..5) |i| try expectEqual(@as(u8, @intCast(i)), A.get(a, i));
@@ -68,10 +61,10 @@ test Array {
68
61
  b = B.set(b, 2, .true);
69
62
  try expectEqual(Optional(bool).None, B.get(b, 1));
70
63
  try expectEqual(Optional(bool).true, B.get(b, 2));
71
- try expectEqual(@as(u8, 0b00100000), b);
64
+ try expectEqual(0b00100000, b);
72
65
  b = B.set(b, 2, .None);
73
66
  b = B.set(b, 0, .false);
74
67
  try expectEqual(Optional(bool).None, B.get(b, 2));
75
68
  try expectEqual(Optional(bool).false, B.get(b, 0));
76
- try expectEqual(@as(u8, 0b0000001), b);
69
+ try expectEqual(0b0000001, b);
77
70
  }
@@ -22,8 +22,8 @@ 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, 0b0001), @as(u8, @bitCast(Player.P1.ident(1))));
26
- try expectEqual(@as(u8, 0b1101), @as(u8, @bitCast(Player.P2.ident(5))));
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.
@@ -46,8 +46,8 @@ pub const ID = packed struct(u8) {
46
46
  };
47
47
 
48
48
  test ID {
49
- try expectEqual(@as(u8, 0b0001), @as(u8, @bitCast(ID{ .player = .P1, .id = 1 })));
50
- try expectEqual(@as(u8, 0b1101), @as(u8, @bitCast(ID{ .player = .P2, .id = 5 })));
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
51
  const id: ID = .{ .player = .P2, .id = 4 };
52
52
  try expectEqual(id, ID.from(id.int()));
53
53
  }
@@ -76,8 +76,8 @@ test Choice {
76
76
  const p2: Choice = .{ .type = .Switch, .data = 5 };
77
77
  try expectEqual(5, p2.data);
78
78
  try expectEqual(Choice.Type.Move, p1.type);
79
- try expectEqual(@as(u8, 0b0001_0001), @as(u8, @bitCast(p1)));
80
- try expectEqual(@as(u8, 0b0001_0110), @as(u8, @bitCast(p2)));
79
+ try expectEqual(0b0001_0001, @as(u8, @bitCast(p1)));
80
+ try expectEqual(0b0001_0110, @as(u8, @bitCast(p2)));
81
81
  }
82
82
 
83
83
  /// The result of the battle - all results other than 'None' should be considered terminal.
@@ -112,6 +112,6 @@ pub const Result = packed struct(u8) {
112
112
  };
113
113
 
114
114
  test Result {
115
- try expectEqual(@as(u8, 0b0101_0000), @as(u8, @bitCast(Result.Default)));
116
- try expectEqual(@as(u8, 0b1000_0000), @as(u8, @bitCast(Result{ .p2 = .Switch })));
115
+ try expectEqual(0b0101_0000, @as(u8, @bitCast(Result.Default)));
116
+ try expectEqual(0b1000_0000, @as(u8, @bitCast(Result{ .p2 = .Switch })));
117
117
  }