@pkmn/engine 0.1.0-dev.46307385 → 0.1.0-dev.46850a3d

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 (50) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +39 -16
  3. package/build/pkg/addon.js +6 -7
  4. package/build/pkg/addon.js.map +1 -1
  5. package/build/pkg/data/ids.json +12 -12
  6. package/build/pkg/data/layout.json +2 -2
  7. package/build/pkg/data/protocol.json +69 -12
  8. package/build/pkg/data.d.ts +4 -4
  9. package/build/pkg/data.js.map +1 -1
  10. package/build/pkg/gen1.js +2 -2
  11. package/build/pkg/gen1.js.map +1 -1
  12. package/build/pkg/index.d.ts +2 -1
  13. package/build/pkg/index.js.map +1 -1
  14. package/build/pkg/protocol.js +61 -42
  15. package/build/pkg/protocol.js.map +1 -1
  16. package/build/test/display.js +2 -2
  17. package/build/test/display.js.map +1 -1
  18. package/build/tools/debug.js +5 -4
  19. package/build/tools/debug.js.map +1 -1
  20. package/build.zig +98 -80
  21. package/package.json +43 -23
  22. package/src/bin/install-pkmn-engine +26 -18
  23. package/src/lib/common/data.zig +12 -24
  24. package/src/lib/common/optional.zig +9 -2
  25. package/src/lib/common/protocol.zig +802 -327
  26. package/src/lib/common/rational.zig +12 -8
  27. package/src/lib/common/rng.zig +26 -17
  28. package/src/lib/gen1/calc.zig +9 -10
  29. package/src/lib/gen1/chance.zig +80 -63
  30. package/src/lib/gen1/data/moves.zig +192 -180
  31. package/src/lib/gen1/data/species.zig +3 -3
  32. package/src/lib/gen1/data/types.zig +7 -7
  33. package/src/lib/gen1/data.zig +47 -59
  34. package/src/lib/gen1/helpers.zig +33 -48
  35. package/src/lib/gen1/mechanics.zig +354 -369
  36. package/src/lib/gen2/calc.zig +143 -0
  37. package/src/lib/gen2/chance.zig +1315 -0
  38. package/src/lib/gen2/data/items.zig +12 -18
  39. package/src/lib/gen2/data/moves.zig +663 -569
  40. package/src/lib/gen2/data/species.zig +1 -1
  41. package/src/lib/gen2/data/types.zig +134 -31
  42. package/src/lib/gen2/data.zig +106 -79
  43. package/src/lib/gen2/generated.zig +806 -0
  44. package/src/lib/gen2/helpers.zig +8 -12
  45. package/src/lib/gen2/mechanics.zig +3587 -9
  46. package/src/lib/{binding/node.zig → node.zig} +10 -13
  47. package/src/lib/pkmn.zig +26 -3
  48. package/src/lib/{binding/wasm.zig → wasm.zig} +2 -1
  49. package/src/lib/gen1/README.md +0 -892
  50. package/src/lib/gen2/README.md +0 -308
package/build.zig CHANGED
@@ -16,8 +16,8 @@ pub fn module(b: *std.Build, options: Options) *std.Build.Module {
16
16
  build_options.addOption(?bool, "chance", options.chance);
17
17
  build_options.addOption(?bool, "calc", options.calc);
18
18
  return b.createModule(.{
19
- .source_file = .{ .path = dirname ++ "/src/lib/pkmn.zig" },
20
- .dependencies = &.{.{ .name = "build_options", .module = build_options.createModule() }},
19
+ .root_source_file = .{ .cwd_relative = dirname ++ "/src/lib/pkmn.zig" },
20
+ .imports = &.{.{ .name = "build_options", .module = build_options.createModule() }},
21
21
  });
22
22
  }
23
23
 
@@ -32,8 +32,8 @@ pub fn build(b: *std.Build) !void {
32
32
  const wasm_stack_size =
33
33
  b.option(u64, "wasm-stack-size", "The size of WASM stack") orelse std.wasm.page_size;
34
34
  const dynamic = b.option(bool, "dynamic", "Build a dynamic library") orelse false;
35
- const strip = b.option(bool, "strip", "Strip debugging symbols from binary") orelse false;
36
- const pic = b.option(bool, "pic", "Force position independent code") orelse false;
35
+ const strip = b.option(bool, "strip", "Strip debugging symbols from binary");
36
+ const pic = b.option(bool, "pic", "Force position independent code");
37
37
  const emit_asm = b.option(bool, "emit-asm", "Output .s (assembly code)") orelse false;
38
38
  const emit_ll = b.option(bool, "emit-ll", "Output .ll (LLVM IR)") orelse false;
39
39
 
@@ -44,7 +44,7 @@ pub fn build(b: *std.Build) !void {
44
44
  defer parsed.deinit();
45
45
  const version = parsed.value.object.get("version").?.string;
46
46
  const description = parsed.value.object.get("description").?.string;
47
- var repository = std.mem.split(u8, parsed.value.object.get("repository").?.string, ":");
47
+ var repository = std.mem.splitSequence(u8, parsed.value.object.get("repository").?.string, ":");
48
48
  std.debug.assert(std.mem.eql(u8, repository.first(), "github"));
49
49
 
50
50
  const showdown =
@@ -66,25 +66,25 @@ pub fn build(b: *std.Build) !void {
66
66
  const addon = b.fmt("{s}.node", .{name});
67
67
  const lib = b.addSharedLibrary(.{
68
68
  .name = addon,
69
- .main_pkg_path = .{ .path = "." },
70
- .root_source_file = .{ .path = "src/lib/binding/node.zig" },
69
+ .root_source_file = b.path("src/lib/node.zig"),
71
70
  .optimize = optimize,
72
71
  .target = target,
72
+ .strip = strip,
73
+ .pic = pic,
73
74
  });
74
- lib.addOptions("build_options", options);
75
- lib.addSystemIncludePath(.{ .path = headers });
75
+ lib.root_module.addOptions("build_options", options);
76
+ lib.addSystemIncludePath(b.path(headers));
76
77
  lib.linkLibC();
77
78
  if (node_import_lib) |il| {
78
- lib.addObjectFile(.{ .path = il });
79
- } else if ((try std.zig.system.NativeTargetInfo.detect(target)).target.os.tag == .windows) {
79
+ lib.addObjectFile(b.path(il));
80
+ } else if (target.result.os.tag == .windows) {
80
81
  try std.io.getStdErr().writeAll("Must provide --node-import-library path on Windows\n");
81
82
  std.process.exit(1);
82
83
  }
83
84
  lib.linker_allow_shlib_undefined = true;
84
85
  maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
85
- if (pic) lib.force_pic = pic;
86
86
  // Always emit to build/lib because this is where the driver code expects to find it
87
- // TODO(ziglang/zig#2231): using the following used to work (though was hacky):
87
+ // TODO: ziglang/zig#2231 - using the following used to work (though was hacky):
88
88
  //
89
89
  // lib.emit_bin = .{ .emit_to = b.fmt("build/lib/{s}", .{addon}) };
90
90
  // b.getInstallStep().dependOn(&lib.step);
@@ -93,59 +93,69 @@ pub fn build(b: *std.Build) !void {
93
93
  // rename the file ourself in install-pkmn-engine
94
94
  b.installArtifact(lib);
95
95
  } else if (wasm) {
96
- const lib = b.addSharedLibrary(.{
96
+ const exe = b.addExecutable(.{
97
97
  .name = name,
98
- .main_pkg_path = .{ .path = "." },
99
- .root_source_file = .{ .path = "src/lib/binding/wasm.zig" },
98
+ .root_source_file = b.path("src/lib/wasm.zig"),
100
99
  .optimize = switch (optimize) {
101
100
  .ReleaseFast, .ReleaseSafe => .ReleaseSmall,
102
101
  else => optimize,
103
102
  },
104
- .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
103
+ .target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
104
+ .strip = strip,
105
+ .pic = pic,
105
106
  });
106
- lib.addOptions("build_options", options);
107
- lib.stack_size = wasm_stack_size;
108
- lib.rdynamic = true;
109
- lib.strip = strip;
110
- if (pic) lib.force_pic = pic;
107
+ exe.root_module.addOptions("build_options", options);
108
+ exe.root_module.export_symbol_names = &[_][]const u8{
109
+ "SHOWDOWN",
110
+ "LOG",
111
+ "CHANCE",
112
+ "CALC",
113
+ "GEN1_CHOICES_SIZE",
114
+ "GEN1_LOGS_SIZE",
115
+ };
116
+ exe.entry = .disabled;
117
+ exe.stack_size = wasm_stack_size;
111
118
  const opt = b.findProgram(&.{"wasm-opt"}, &.{"./node_modules/.bin"}) catch null;
112
119
  if (optimize != .Debug and opt != null) {
113
120
  const out = b.fmt("build/lib/{s}.wasm", .{name});
114
121
  const sh = b.addSystemCommand(&.{ opt.?, "-O4" });
115
- sh.addArtifactArg(lib);
122
+ sh.addArtifactArg(exe);
116
123
  sh.addArg("-o");
117
- sh.addFileSourceArg(.{ .path = out });
124
+ sh.addFileArg(b.path(out));
118
125
  b.getInstallStep().dependOn(&sh.step);
126
+ } else {
127
+ b.getInstallStep().dependOn(&b.addInstallArtifact(exe, .{
128
+ .dest_dir = .{ .override = std.Build.InstallDir{ .lib = {} } },
129
+ }).step);
119
130
  }
120
- b.installArtifact(lib);
121
131
  } else if (dynamic) {
122
132
  const lib = b.addSharedLibrary(.{
123
133
  .name = name,
124
- .main_pkg_path = .{ .path = "." },
125
- .root_source_file = .{ .path = "src/lib/binding/c.zig" },
134
+ .root_source_file = b.path("src/lib/c.zig"),
126
135
  .version = try std.SemanticVersion.parse(version),
127
136
  .optimize = optimize,
128
137
  .target = target,
138
+ .strip = strip,
139
+ .pic = pic,
129
140
  });
130
- lib.addOptions("build_options", options);
131
- lib.addIncludePath(.{ .path = "src/include" });
141
+ lib.root_module.addOptions("build_options", options);
142
+ lib.addIncludePath(b.path("src/include"));
132
143
  maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
133
- if (pic) lib.force_pic = pic;
134
144
  b.installArtifact(lib);
135
145
  c = true;
136
146
  } else {
137
147
  const lib = b.addStaticLibrary(.{
138
148
  .name = name,
139
- .main_pkg_path = .{ .path = "." },
140
- .root_source_file = .{ .path = "src/lib/binding/c.zig" },
149
+ .root_source_file = b.path("src/lib/c.zig"),
141
150
  .optimize = optimize,
142
151
  .target = target,
152
+ .strip = strip,
153
+ .pic = pic,
143
154
  });
144
- lib.addOptions("build_options", options);
145
- lib.addIncludePath(.{ .path = "src/include" });
155
+ lib.root_module.addOptions("build_options", options);
156
+ lib.addIncludePath(b.path("src/include"));
146
157
  lib.bundle_compiler_rt = true;
147
158
  maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
148
- if (pic) lib.force_pic = pic;
149
159
  if (emit_asm) {
150
160
  b.getInstallStep().dependOn(&b.addInstallFileWithDir(
151
161
  lib.getEmittedAsm(),
@@ -166,14 +176,18 @@ pub fn build(b: *std.Build) !void {
166
176
 
167
177
  if (c) {
168
178
  const header = b.addInstallFileWithDir(
169
- .{ .path = "src/include/pkmn.h" },
179
+ b.path("src/include/pkmn.h"),
170
180
  .header,
171
181
  "pkmn.h",
172
182
  );
173
183
  b.getInstallStep().dependOn(&header.step);
174
184
 
175
185
  const pc = b.fmt("lib{s}.pc", .{name});
176
- const file = try b.cache_root.join(b.allocator, &.{pc});
186
+ const file = try std.fs.path.relative(
187
+ b.allocator,
188
+ try std.process.getCwdAlloc(b.allocator),
189
+ try b.cache_root.join(b.allocator, &.{pc}),
190
+ );
177
191
  const pkgconfig_file = try std.fs.cwd().createFile(file, .{});
178
192
 
179
193
  const dirname = comptime std.fs.path.dirname(@src().file) orelse ".";
@@ -206,7 +220,7 @@ pub fn build(b: *std.Build) !void {
206
220
  // TODO: tests can be run multiple times due to @imports
207
221
  const tests = TestStep.create(b, options, config);
208
222
 
209
- var exes = std.ArrayList(*std.Build.CompileStep).init(b.allocator);
223
+ var exes = std.ArrayList(*std.Build.Step.Compile).init(b.allocator);
210
224
  const tools: ToolConfig = .{
211
225
  .options = .{
212
226
  .showdown = showdown,
@@ -224,37 +238,42 @@ pub fn build(b: *std.Build) !void {
224
238
  var benchmark_config = tools;
225
239
  benchmark_config.general.optimize = .ReleaseFast;
226
240
  benchmark_config.general.strip = true;
227
- const benchmark = tool(b, "src/test/benchmark.zig", benchmark_config);
241
+ const benchmark = try tool(b, "src/test/benchmark.zig", benchmark_config);
228
242
 
229
243
  var fuzz_config = tools;
230
244
  fuzz_config.general.strip = false;
231
245
  fuzz_config.tool.name = "fuzz";
232
- const fuzz = tool(b, "src/test/fuzz.zig", fuzz_config);
233
-
234
- const analyze = tool(b, "src/tools/analyze.zig", tools);
235
- const dump = tool(b, "src/tools/dump.zig", tools);
236
- const serde = tool(b, "src/tools/serde.zig", tools);
237
- const transitions = tool(b, "src/tools/transitions.zig", tools);
238
-
239
- b.step("analyze", "Run LLVM analysis tool").dependOn(&analyze.step);
240
- b.step("benchmark", "Run benchmark code").dependOn(&benchmark.step);
241
- b.step("dump", "Run protocol dump tool").dependOn(&dump.step);
242
- b.step("fuzz", "Run fuzz tester").dependOn(&fuzz.step);
243
- b.step("serde", "Run serialization/deserialization tool").dependOn(&serde.step);
246
+ const fuzz = try tool(b, "src/test/fuzz.zig", fuzz_config);
247
+
248
+ const analyze = try tool(b, "src/tools/analyze.zig", tools);
249
+ const dump = try tool(b, "src/tools/dump.zig", tools);
250
+ const transitions = try tool(b, "src/tools/transitions.zig", tools);
251
+
252
+ // FIXME: serde randomly fails to build in some release configurations
253
+ var hack = tools;
254
+ if (optimize != .Debug) hack.tool.tests = null;
255
+ const serde = try tool(b, "src/tools/serde.zig", hack);
256
+
257
+ if (analyze) |t| b.step("analyze", "Run LLVM analysis tool").dependOn(&t.step);
258
+ if (benchmark) |t| b.step("benchmark", "Run benchmark code").dependOn(&t.step);
259
+ if (dump) |t| b.step("dump", "Run protocol dump tool").dependOn(&t.step);
260
+ if (fuzz) |t| b.step("fuzz", "Run fuzz tester").dependOn(&t.step);
261
+ if (serde) |t| b.step("serde", "Run serialization/deserialization tool").dependOn(&t.step);
244
262
  b.step("test", "Run all tests").dependOn(&tests.step);
245
263
  b.step("tools", "Install tools").dependOn(&ToolsStep.create(b, &exes).step);
246
- b.step("transitions", "Visualize transitions algorithm search").dependOn(&transitions.step);
264
+ if (transitions) |t| {
265
+ b.step("transitions", "Visualize transitions algorithm search").dependOn(&t.step);
266
+ }
247
267
  }
248
268
 
249
269
  fn maybeStrip(
250
270
  b: *std.Build,
251
- artifact: *std.Build.CompileStep,
271
+ artifact: *std.Build.Step.Compile,
252
272
  step: *std.Build.Step,
253
- strip: bool,
273
+ strip: ?bool,
254
274
  cmd: ?[]const u8,
255
275
  ) void {
256
- artifact.strip = strip;
257
- if (!strip or cmd == null) return;
276
+ if (!(strip orelse false) or cmd == null) return;
258
277
  // Using `strip -r -u` for dynamic libraries is supposed to work on macOS but doesn't...
259
278
  const mac = builtin.os.tag == .macos;
260
279
  if (mac and artifact.isDynamicLibrary()) return;
@@ -266,10 +285,10 @@ fn maybeStrip(
266
285
  }
267
286
 
268
287
  const Config = struct {
269
- target: std.zig.CrossTarget,
288
+ target: std.Build.ResolvedTarget,
270
289
  optimize: std.builtin.OptimizeMode,
271
- pic: bool,
272
- strip: bool,
290
+ pic: ?bool,
291
+ strip: ?bool,
273
292
  cmd: ?[]const u8,
274
293
  };
275
294
 
@@ -277,32 +296,26 @@ const TestStep = struct {
277
296
  step: std.Build.Step,
278
297
  build: bool,
279
298
 
280
- pub fn create(b: *std.Build, options: *std.Build.OptionsStep, config: Config) *TestStep {
299
+ pub fn create(b: *std.Build, options: *std.Build.Step.Options, config: Config) *TestStep {
281
300
  const coverage = b.option([]const u8, "test-coverage", "Generate test coverage");
282
- const test_file = b.option([]const u8, "test-file", "Input file for test");
283
301
  const test_filter =
284
302
  b.option([]const u8, "test-filter", "Skip tests that do not match filter");
285
303
 
286
304
  const self = b.allocator.create(TestStep) catch @panic("OOM");
287
305
  const step = std.Build.Step.init(.{ .id = .custom, .name = "Run all tests", .owner = b });
288
- self.* = TestStep{ .step = step, .build = test_filter == null };
306
+ self.* = .{ .step = step, .build = test_filter == null };
289
307
 
290
- const path = test_file orelse "src/lib/test.zig";
291
308
  const tests = b.addTest(.{
292
- .name = b.fmt("{s}-{s}", .{
293
- std.fs.path.basename(std.fs.path.dirname(path).?),
294
- std.fs.path.stem(std.fs.path.basename(path)),
295
- }),
296
- .main_pkg_path = .{ .path = "." },
297
- .root_source_file = .{ .path = path },
309
+ .root_source_file = b.path("src/lib/test.zig"),
298
310
  .optimize = config.optimize,
299
311
  .target = config.target,
300
312
  .filter = test_filter,
313
+ .single_threaded = true,
314
+ .strip = config.strip,
315
+ .pic = config.pic,
301
316
  });
302
- tests.addOptions("build_options", options);
303
- tests.single_threaded = true;
317
+ tests.root_module.addOptions("build_options", options);
304
318
  maybeStrip(b, tests, &tests.step, config.strip, config.cmd);
305
- if (config.pic) tests.force_pic = config.pic;
306
319
  if (coverage) |c| {
307
320
  tests.setExecCmd(&.{ "kcov", "--include-pattern=src/lib", c, null });
308
321
  }
@@ -318,11 +331,15 @@ const ToolConfig = struct {
318
331
  tool: struct {
319
332
  tests: ?*TestStep,
320
333
  name: ?[]const u8 = null,
321
- exes: *std.ArrayList(*std.Build.CompileStep),
334
+ exes: *std.ArrayList(*std.Build.Step.Compile),
322
335
  },
323
336
  };
324
337
 
325
- fn tool(b: *std.Build, path: []const u8, config: ToolConfig) *std.Build.RunStep {
338
+ fn tool(b: *std.Build, path: []const u8, config: ToolConfig) !?*std.Build.Step.Run {
339
+ std.fs.cwd().access(path, .{}) catch |err| switch (err) {
340
+ error.FileNotFound => return null,
341
+ else => |e| return e,
342
+ };
326
343
  var name = config.tool.name orelse std.fs.path.basename(path);
327
344
  const index = std.mem.lastIndexOfScalar(u8, name, '.');
328
345
  if (index) |i| name = name[0..i];
@@ -330,14 +347,15 @@ fn tool(b: *std.Build, path: []const u8, config: ToolConfig) *std.Build.RunStep
330
347
 
331
348
  const exe = b.addExecutable(.{
332
349
  .name = name,
333
- .root_source_file = .{ .path = path },
350
+ .root_source_file = b.path(path),
334
351
  .target = config.general.target,
335
352
  .optimize = config.general.optimize,
353
+ .single_threaded = true,
354
+ .strip = config.general.strip,
355
+ .pic = config.general.pic,
336
356
  });
337
- exe.addModule("pkmn", module(b, config.options));
357
+ exe.root_module.addImport("pkmn", module(b, config.options));
338
358
 
339
- exe.single_threaded = true;
340
- if (config.general.pic) exe.force_pic = config.general.pic;
341
359
  if (config.tool.tests) |ts| ts.step.dependOn(&exe.step);
342
360
  config.tool.exes.append(exe) catch @panic("OOM");
343
361
 
@@ -351,10 +369,10 @@ fn tool(b: *std.Build, path: []const u8, config: ToolConfig) *std.Build.RunStep
351
369
  const ToolsStep = struct {
352
370
  step: std.Build.Step,
353
371
 
354
- pub fn create(b: *std.Build, exes: *std.ArrayList(*std.Build.CompileStep)) *ToolsStep {
372
+ pub fn create(b: *std.Build, exes: *std.ArrayList(*std.Build.Step.Compile)) *ToolsStep {
355
373
  const self = b.allocator.create(ToolsStep) catch @panic("OOM");
356
374
  const step = std.Build.Step.init(.{ .id = .custom, .name = "Install tools", .owner = b });
357
- self.* = ToolsStep{ .step = step };
375
+ self.* = .{ .step = step };
358
376
  for (exes.items) |t| self.step.dependOn(&b.addInstallArtifact(t, .{}).step);
359
377
  return self;
360
378
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pkmn/engine",
3
- "version": "0.1.0-dev.46307385",
3
+ "version": "0.1.0-dev.46850a3d",
4
4
  "description": "A minimal, complete, Pokémon battle simulation engine optimized for performance",
5
5
  "repository": "github:pkmn/engine",
6
6
  "license": "MIT",
@@ -31,9 +31,6 @@
31
31
  "build/test/display.js",
32
32
  "build/tools/debug.js.map",
33
33
  "build/tools/debug.js",
34
- "src/bin/install-pkmn-engine",
35
- "src/lib/binding/node.zig",
36
- "src/lib/binding/wasm.zig",
37
34
  "src/lib/common/battle.zig",
38
35
  "src/lib/common/data.zig",
39
36
  "src/lib/common/debug.zig",
@@ -52,14 +49,19 @@
52
49
  "src/lib/gen1/data/types.zig",
53
50
  "src/lib/gen1/helpers.zig",
54
51
  "src/lib/gen1/mechanics.zig",
52
+ "src/lib/gen2/calc.zig",
53
+ "src/lib/gen2/chance.zig",
55
54
  "src/lib/gen2/data.zig",
56
55
  "src/lib/gen2/data/items.zig",
57
56
  "src/lib/gen2/data/moves.zig",
58
57
  "src/lib/gen2/data/species.zig",
59
58
  "src/lib/gen2/data/types.zig",
59
+ "src/lib/gen2/generated.zig",
60
60
  "src/lib/gen2/helpers.zig",
61
61
  "src/lib/gen2/mechanics.zig",
62
+ "src/lib/node.zig",
62
63
  "src/lib/pkmn.zig",
64
+ "src/lib/wasm.zig",
63
65
  "src/test/display/pkmn.html.tmpl"
64
66
  ],
65
67
  "engines": {
@@ -73,30 +75,31 @@
73
75
  "access": "public"
74
76
  },
75
77
  "dependencies": {
76
- "@pkmn/data": "^0.7.46",
77
- "@pkmn/protocol": "^0.6.12"
78
+ "@pkmn/data": "^0.9.9",
79
+ "@pkmn/protocol": "^0.6.25"
78
80
  },
79
81
  "devDependencies": {
80
- "@pkmn/eslint-config": "^5.0.0",
81
- "@pkmn/img": "^0.2.13",
82
- "@pkmn/sets": "^5.0.4",
83
- "@pkmn/sim": "0.7.46",
84
- "@types/html-minifier": "^4.0.2",
85
- "@types/jest": "^29.5.3",
86
- "@types/minimist": "^1.2.2",
87
- "@types/mustache": "^4.2.2",
88
- "@types/node": "^20.4.2",
89
- "@vitest/coverage-c8": "^0.33.0",
90
- "binaryen": "^114.0.0",
91
- "eslint": "^8.44.0",
82
+ "@pkmn/eslint-config": "^7.5.0",
83
+ "@pkmn/img": "^0.2.30",
84
+ "@pkmn/sets": "^5.1.2",
85
+ "@pkmn/sim": "0.9.9",
86
+ "@types/html-minifier": "^4.0.5",
87
+ "@types/jest": "^29.5.12",
88
+ "@types/minimist": "^1.2.5",
89
+ "@types/mustache": "^4.2.5",
90
+ "@types/node": "^20.14.10",
91
+ "@vitest/coverage-v8": "^2.0.2",
92
+ "binaryen": "^118.0.0",
93
+ "eslint": "<=8",
92
94
  "html-minifier": "^4.0.0",
93
- "json-stringify-pretty-compact": "3.0.0",
95
+ "json-stringify-pretty-compact": "4.0.0",
94
96
  "minimist": "^1.2.8",
95
97
  "mustache": "^4.2.0",
96
98
  "source-map-support": "^0.5.21",
99
+ "table": "^6.8.2",
97
100
  "trakr": "^0.2.0",
98
- "typescript": "^5.1.6",
99
- "vitest": "^0.33.0"
101
+ "typescript": "^5.5.3",
102
+ "vitest": "^2.0.2"
100
103
  },
101
104
  "scripts": {
102
105
  "lint": "eslint --cache src --ext ts,js && eslint src/bin/*",
@@ -118,7 +121,7 @@
118
121
  "ignorePatterns": [
119
122
  "dist/",
120
123
  "node_modules/",
121
- "src/examples/zig",
124
+ "examples/zig",
122
125
  "build/"
123
126
  ],
124
127
  "env": {
@@ -134,10 +137,18 @@
134
137
  "parserOptions": {
135
138
  "project": [
136
139
  "./tsconfig.json",
137
- "./src/examples/js/tsconfig.json"
140
+ "./examples/js/tsconfig.json"
138
141
  ]
139
142
  }
140
143
  },
144
+ {
145
+ "files": [
146
+ "src/test/display.ts"
147
+ ],
148
+ "rules": {
149
+ "@typescript-eslint/no-unnecessary-type-assertion": "off"
150
+ }
151
+ },
141
152
  {
142
153
  "files": [
143
154
  "src/pkg/index.ts",
@@ -168,6 +179,15 @@
168
179
  "@typescript-eslint/no-redundant-type-constituents": "off"
169
180
  }
170
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
+ },
171
191
  {
172
192
  "files": [
173
193
  "src/test/*.test.ts",
@@ -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: 13, 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';
@@ -283,19 +283,19 @@ const downloadImportLib = async () => {
283
283
  let error = false;
284
284
  for (let i = 2; i < process.argv.length; i++) {
285
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
- }
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
299
  }
300
300
  }
301
301
  if (error) {
@@ -370,8 +370,10 @@ const downloadImportLib = async () => {
370
370
  const args = ['build', '-p', 'build', ...opts];
371
371
  if (!process.env.DEBUG_PKMN_ENGINE) args.push('-Doptimize=ReleaseFast', '-Dstrip');
372
372
  if (config.type === 'node') {
373
- args.push(`-Dnode-headers=${headers}`);
374
- if (process.platform === 'win32') args.push(`-Dnode-import-library=${lib}`);
373
+ args.push(`-Dnode-headers=${path.relative(ROOT, headers)}`);
374
+ if (process.platform === 'win32') {
375
+ args.push(`-Dnode-import-library=${path.relative(ROOT, lib)}`);
376
+ }
375
377
  } else {
376
378
  args.push('-Dwasm');
377
379
  }
@@ -386,8 +388,14 @@ const downloadImportLib = async () => {
386
388
  const prefix = process.platform === 'win32' ? '' : 'lib';
387
389
  const ext = process.platform === 'darwin'
388
390
  ? 'dylib' : process.platform === 'win32' ? 'dll' : 'so';
389
- const actual = path.join('build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
390
- fs.renameSync(path.join(ROOT, actual), path.join(ROOT, artifact));
391
+ try {
392
+ const actual = path.join('build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
393
+ fs.renameSync(actual, artifact);
394
+ } catch (err) {
395
+ // ziglang/zig#19743 changed this path
396
+ const actual = path.join('build', 'bin', `${prefix}pkmn${suffix}.node.${ext}`);
397
+ fs.renameSync(actual, artifact);
398
+ }
391
399
  }
392
400
  }
393
401
  })().catch(e => {
@@ -9,12 +9,12 @@ pub const Player = enum(u1) {
9
9
  P2,
10
10
 
11
11
  /// Returns a player's opponent.
12
- pub inline fn foe(self: Player) Player {
12
+ pub fn foe(self: Player) Player {
13
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 inline fn ident(self: Player, id: u3) ID {
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, 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.
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 inline fn int(self: ID) u4 {
38
+ pub fn int(self: ID) u4 {
43
39
  return @intCast(@as(u8, @bitCast(self)));
44
40
  }
45
41
 
46
42
  /// Decodes the identifier from a number.
47
- pub inline fn from(id: u4) ID {
43
+ pub fn from(id: u4) ID {
48
44
  return @bitCast(@as(u8, id));
49
45
  }
50
46
  };
51
47
 
52
48
  test ID {
53
- try expectEqual(@as(u8, 0b0001), @as(u8, @bitCast(ID{ .player = .P1, .id = 1 })));
54
- try expectEqual(@as(u8, 0b1101), @as(u8, @bitCast(ID{ .player = .P2, .id = 5 })));
55
- const id = ID{ .player = .P2, .id = 4 };
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 {
@@ -89,7 +81,7 @@ test Choice {
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,10 +109,6 @@ 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 {