@pkmn/engine 0.1.0-dev.b9fb6eab → 0.1.0-dev.cf6f5d2c

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/build.zig CHANGED
@@ -1,13 +1,13 @@
1
1
  const std = @import("std");
2
2
  const builtin = @import("builtin");
3
3
 
4
- pub const Options = struct { showdown: ?bool = null, trace: ?bool = null };
4
+ pub const Options = struct { showdown: ?bool = null, log: ?bool = null };
5
5
 
6
6
  pub fn module(b: *std.Build, options: Options) *std.Build.Module {
7
7
  const dirname = comptime std.fs.path.dirname(@src().file) orelse ".";
8
8
  const build_options = b.addOptions();
9
9
  build_options.addOption(?bool, "showdown", options.showdown);
10
- build_options.addOption(?bool, "trace", options.trace);
10
+ build_options.addOption(?bool, "log", options.log);
11
11
  return b.createModule(.{
12
12
  .source_file = .{ .path = dirname ++ "/src/lib/pkmn.zig" },
13
13
  .dependencies = &.{.{ .name = "build_options", .module = build_options.createModule() }},
@@ -27,6 +27,7 @@ pub fn build(b: *std.Build) !void {
27
27
  const dynamic = b.option(bool, "dynamic", "Build a dynamic library") orelse false;
28
28
  const strip = b.option(bool, "strip", "Strip debugging symbols from binary") orelse false;
29
29
  const pic = b.option(bool, "pic", "Force position independent code") orelse false;
30
+ const emit_asm = b.option(bool, "emit-asm", "Output .s (assembly code)") orelse false;
30
31
 
31
32
  const cmd = b.findProgram(&.{"strip"}, &.{}) catch null;
32
33
 
@@ -41,11 +42,11 @@ pub fn build(b: *std.Build) !void {
41
42
 
42
43
  const showdown =
43
44
  b.option(bool, "showdown", "Enable Pokémon Showdown compatibility mode") orelse false;
44
- const trace = b.option(bool, "trace", "Enable trace logs") orelse false;
45
+ const log = b.option(bool, "log", "Enable protocol message logging") orelse false;
45
46
 
46
47
  const options = b.addOptions();
47
48
  options.addOption(?bool, "showdown", showdown);
48
- options.addOption(?bool, "trace", trace);
49
+ options.addOption(?bool, "log", log);
49
50
 
50
51
  const name = if (showdown) "pkmn-showdown" else "pkmn";
51
52
 
@@ -79,7 +80,7 @@ pub fn build(b: *std.Build) !void {
79
80
  //
80
81
  // But ziglang/zig#14647 broke this so we now need to do an install() and then manually
81
82
  // rename the file ourself in install-pkmn-engine
82
- lib.install();
83
+ b.installArtifact(lib);
83
84
  } else if (wasm) {
84
85
  const lib = b.addSharedLibrary(.{
85
86
  .name = name,
@@ -105,7 +106,7 @@ pub fn build(b: *std.Build) !void {
105
106
  sh.addFileSourceArg(.{ .path = out });
106
107
  b.getInstallStep().dependOn(&sh.step);
107
108
  }
108
- lib.install();
109
+ b.installArtifact(lib);
109
110
  } else if (dynamic) {
110
111
  const lib = b.addSharedLibrary(.{
111
112
  .name = name,
@@ -119,7 +120,7 @@ pub fn build(b: *std.Build) !void {
119
120
  lib.addIncludePath("src/include");
120
121
  maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
121
122
  if (pic) lib.force_pic = pic;
122
- lib.install();
123
+ b.installArtifact(lib);
123
124
  c = true;
124
125
  } else {
125
126
  const lib = b.addStaticLibrary(.{
@@ -134,7 +135,8 @@ pub fn build(b: *std.Build) !void {
134
135
  lib.bundle_compiler_rt = true;
135
136
  maybeStrip(b, lib, b.getInstallStep(), strip, cmd);
136
137
  if (pic) lib.force_pic = pic;
137
- lib.install();
138
+ if (emit_asm) lib.emit_asm = .emit;
139
+ b.installArtifact(lib);
138
140
  c = true;
139
141
  }
140
142
 
@@ -183,7 +185,7 @@ pub fn build(b: *std.Build) !void {
183
185
  .general = config,
184
186
  .tool = .{
185
187
  .showdown = showdown,
186
- .trace = trace,
188
+ .log = log,
187
189
  .tests = if (tests.build) tests else null,
188
190
  .exes = &exes,
189
191
  },
@@ -205,7 +207,7 @@ pub fn build(b: *std.Build) !void {
205
207
  const lint_exe =
206
208
  b.addExecutable(.{ .name = "lint", .root_source_file = .{ .path = "src/tools/lint.zig" } });
207
209
  if (tests.build) tests.step.dependOn(&lint_exe.step);
208
- const lint = lint_exe.run();
210
+ const lint = b.addRunArtifact(lint_exe);
209
211
 
210
212
  b.step("benchmark", "Run benchmark code").dependOn(&benchmark.step);
211
213
  b.step("fuzz", "Run fuzz tester").dependOn(&fuzz.step);
@@ -256,11 +258,8 @@ const TestStep = struct {
256
258
  pub fn create(b: *std.Build, options: *std.Build.OptionsStep, config: Config) *TestStep {
257
259
  const coverage = b.option([]const u8, "test-coverage", "Generate test coverage");
258
260
  const test_file = b.option([]const u8, "test-file", "Input file for test");
259
- const test_bin = b.option([]const u8, "test-bin", "Emit test binary to");
260
261
  const test_filter =
261
262
  b.option([]const u8, "test-filter", "Skip tests that do not match filter");
262
- const test_no_exec =
263
- b.option(bool, "test-no-exec", "Compiles test binary without running it") orelse false;
264
263
 
265
264
  const self = b.allocator.create(TestStep) catch @panic("OOM");
266
265
  const step = std.Build.Step.init(.{ .id = .custom, .name = "Run all tests", .owner = b });
@@ -274,21 +273,17 @@ const TestStep = struct {
274
273
  .root_source_file = .{ .path = path },
275
274
  .optimize = config.optimize,
276
275
  .target = config.target,
276
+ .filter = test_filter,
277
277
  });
278
278
  tests.setMainPkgPath("./");
279
- tests.setFilter(test_filter);
280
279
  tests.addOptions("build_options", options);
281
280
  tests.single_threaded = true;
282
281
  maybeStrip(b, tests, &tests.step, config.strip, config.cmd);
283
282
  if (config.pic) tests.force_pic = config.pic;
284
- if (test_bin) |bin| {
285
- tests.name = std.fs.path.basename(bin);
286
- if (std.fs.path.dirname(bin)) |dir| tests.setOutputDir(dir);
287
- }
288
283
  if (coverage) |c| {
289
284
  tests.setExecCmd(&.{ "kcov", "--include-pattern=src/lib", c, null });
290
285
  }
291
- self.step.dependOn(if (test_no_exec) &tests.step else &tests.run().step);
286
+ self.step.dependOn(&b.addRunArtifact(tests).step);
292
287
  }
293
288
  return self;
294
289
  }
@@ -298,7 +293,7 @@ const ToolConfig = struct {
298
293
  general: Config,
299
294
  tool: struct {
300
295
  showdown: bool,
301
- trace: bool,
296
+ log: bool,
302
297
  tests: ?*TestStep,
303
298
  name: ?[]const u8 = null,
304
299
  exes: *std.ArrayList(*std.Build.CompileStep),
@@ -319,14 +314,14 @@ fn tool(b: *std.Build, path: []const u8, config: ToolConfig) *std.Build.RunStep
319
314
  });
320
315
  exe.addModule("pkmn", module(b, .{
321
316
  .showdown = config.tool.showdown,
322
- .trace = config.tool.trace,
317
+ .log = config.tool.log,
323
318
  }));
324
319
  exe.single_threaded = true;
325
320
  if (config.general.pic) exe.force_pic = config.general.pic;
326
321
  if (config.tool.tests) |ts| ts.step.dependOn(&exe.step);
327
322
  config.tool.exes.append(exe) catch @panic("OOM");
328
323
 
329
- const run = exe.run();
324
+ const run = b.addRunArtifact(exe);
330
325
  maybeStrip(b, exe, &run.step, config.general.strip, config.general.cmd);
331
326
  if (b.args) |args| run.addArgs(args);
332
327
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pkmn/engine",
3
- "version": "0.1.0-dev.b9fb6eab",
3
+ "version": "0.1.0-dev.cf6f5d2c",
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,6 +9,28 @@
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
35
  "src/lib/binding/node.zig",
14
36
  "src/lib/binding/wasm.zig",
@@ -17,78 +39,66 @@
17
39
  "src/lib/common/options.zig",
18
40
  "src/lib/common/protocol.zig",
19
41
  "src/lib/common/rng.zig",
42
+ "src/lib/gen1/data.zig",
20
43
  "src/lib/gen1/data/moves.zig",
21
44
  "src/lib/gen1/data/species.zig",
22
45
  "src/lib/gen1/data/types.zig",
23
- "src/lib/gen1/data.zig",
24
46
  "src/lib/gen1/helpers.zig",
25
47
  "src/lib/gen1/mechanics.zig",
48
+ "src/lib/gen2/data.zig",
26
49
  "src/lib/gen2/data/items.zig",
27
50
  "src/lib/gen2/data/moves.zig",
28
51
  "src/lib/gen2/data/species.zig",
29
52
  "src/lib/gen2/data/types.zig",
30
- "src/lib/gen2/data.zig",
31
53
  "src/lib/gen2/helpers.zig",
32
54
  "src/lib/gen2/mechanics.zig",
33
55
  "src/lib/pkmn.zig",
34
- "build/pkg/data/ids.json",
35
- "build/pkg/data/layout.json",
36
- "build/pkg/data/protocol.json",
37
- "build/pkg/data.d.ts",
38
- "build/pkg/data.js",
39
- "build/pkg/data.js.map",
40
- "build/pkg/gen1.d.ts",
41
- "build/pkg/gen1.js",
42
- "build/pkg/gen1.js.map",
43
- "build/pkg/index.d.ts",
44
- "build/pkg/index.js",
45
- "build/pkg/index.js.map",
46
- "build/pkg/protocol.d.ts",
47
- "build/pkg/protocol.js",
48
- "build/pkg/protocol.js.map"
56
+ "src/test/display/pkmn.html.tmpl"
49
57
  ],
50
58
  "engines": {
51
59
  "node": ">=16.0.0"
52
60
  },
53
61
  "bin": {
54
- "install-pkmn-engine": "src/bin/install-pkmn-engine"
62
+ "install-pkmn-engine": "src/bin/install-pkmn-engine",
63
+ "pkmn-debug": "src/bin/pkmn-debug"
55
64
  },
56
65
  "publishConfig": {
57
66
  "access": "public"
58
67
  },
59
68
  "dependencies": {
60
- "@pkmn/data": "^0.7.35",
69
+ "@pkmn/data": "^0.7.38",
61
70
  "@pkmn/protocol": "^0.6.11"
62
71
  },
63
72
  "devDependencies": {
64
73
  "@pkmn/eslint-config": "^3.0.0",
65
74
  "@pkmn/img": "^0.2.8",
66
75
  "@pkmn/sets": "^5.0.4",
67
- "@pkmn/sim": "0.7.35",
76
+ "@pkmn/sim": "0.7.38",
68
77
  "@types/html-minifier": "^4.0.2",
69
78
  "@types/jest": "^29.5.0",
70
79
  "@types/minimist": "^1.2.2",
71
80
  "@types/mustache": "^4.2.2",
72
81
  "@types/node": "^18.15.11",
73
- "@vitest/coverage-c8": "^0.29.8",
82
+ "@vitest/coverage-c8": "^0.30.1",
74
83
  "binaryen": "^112.0.0",
75
- "eslint": "^8.37.0",
84
+ "eslint": "^8.38.0",
76
85
  "html-minifier": "^4.0.0",
77
- "json-stringify-pretty-compact": "3.0.0",
86
+ "json-stringify-pretty-compact": "4.0.0",
78
87
  "minimist": "^1.2.8",
79
88
  "mustache": "^4.2.0",
80
89
  "source-map-support": "^0.5.21",
81
90
  "trakr": "^0.2.0",
82
- "typescript": "^5.0.3",
83
- "vitest": "^0.29.8"
91
+ "typescript": "^5.0.4",
92
+ "vitest": "^0.30.1"
84
93
  },
85
94
  "scripts": {
86
- "lint": "eslint --cache src --ext ts,js && eslint src/bin/install-pkmn-engine",
87
- "fix": "eslint --fix src --ext ts,js && eslint --fix src/bin/install-pkmn-engine",
95
+ "lint": "eslint --cache src --ext ts,js && eslint src/bin/*",
96
+ "fix": "eslint --fix src --ext ts,js && eslint --fix src/bin/*",
88
97
  "compile": "tsc -p .",
89
98
  "build": "npm run compile",
90
99
  "test": "vitest src/pkg",
91
100
  "test:integration": "vitest src/test",
101
+ "debug": "npm run compile && node build/tools/debug",
92
102
  "fuzz": "npm run compile && node build/test/fuzz",
93
103
  "generate": "npm run compile && node build/tools/generate",
94
104
  "release": "npm run compile && node build/tools/release",
@@ -151,7 +161,8 @@
151
161
  },
152
162
  {
153
163
  "files": [
154
- "src/test/*.test.ts"
164
+ "src/test/*.test.ts",
165
+ "src/test/regression/*.test.ts"
155
166
  ],
156
167
  "rules": {
157
168
  "jest/no-standalone-expect": "off"
@@ -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, dev: 2168};
13
+ const ZIG_VERSION = {major: 0, minor: 11, patch: 0, dev: 2750};
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';
@@ -337,13 +337,13 @@ const downloadImportLib = async () => {
337
337
  if (!options) {
338
338
  const addon = require(copy);
339
339
  if (addon.options.showdown) opts.push('-Dshowdown');
340
- if (addon.options.trace) opts.push('-Dtrace');
340
+ if (addon.options.log) opts.push('-Dlog');
341
341
  }
342
342
  } else if (!options) {
343
343
  const addon = await WebAssembly.instantiate(fs.readFileSync(copy));
344
344
  const values = new Uint8Array(addon.instance.exports.memory.buffer);
345
345
  if (values[addon.instance.exports.SHOWDOWN.value]) opts.push('-Dshowdown');
346
- if (values[addon.instance.exports.TRACE.value]) opts.push('-Dtrace');
346
+ if (values[addon.instance.exports.LOG.value]) opts.push('-Dlog');
347
347
  }
348
348
  const key = `${type} ${opts.sort().join(' ')}`;
349
349
  if (!configs.has(key)) configs.set(key, {type, options: opts});
@@ -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
+ });
@@ -21,7 +21,7 @@ fn options(env: c.napi_env) c.napi_value {
21
21
  var object = Object.init(env);
22
22
  const properties = [_]c.napi_property_descriptor{
23
23
  Property.init("showdown", .{ .value = Boolean.init(env, pkmn.options.showdown) }),
24
- Property.init("trace", .{ .value = Boolean.init(env, pkmn.options.trace) }),
24
+ Property.init("log", .{ .value = Boolean.init(env, pkmn.options.log) }),
25
25
  };
26
26
  assert(c.napi_define_properties(env, object, properties.len, &properties) == c.napi_ok);
27
27
  return object;
@@ -34,11 +34,11 @@ fn bindings(env: c.napi_env) c.napi_value {
34
34
  }
35
35
 
36
36
  fn bind(env: c.napi_env, gen: anytype) c.napi_value {
37
- const options_size = @intCast(u32, gen.OPTIONS_SIZE);
37
+ const choices_size = @intCast(u32, gen.CHOICES_SIZE);
38
38
  const logs_size = @intCast(u32, gen.LOGS_SIZE);
39
39
  var object = Object.init(env);
40
40
  const properties = [_]c.napi_property_descriptor{
41
- Property.init("OPTIONS_SIZE", .{ .value = Number.init(env, options_size) }),
41
+ Property.init("CHOICES_SIZE", .{ .value = Number.init(env, choices_size) }),
42
42
  Property.init("LOGS_SIZE", .{ .value = Number.init(env, logs_size) }),
43
43
  Property.init("update", .{ .method = update(gen) }),
44
44
  Property.init("choices", .{ .method = choices(gen) }),
@@ -108,10 +108,10 @@ fn choices(gen: anytype) c.napi_callback {
108
108
  const request = @intToEnum(pkmn.Choice.Type, Number.get(env, argv[2], u8));
109
109
 
110
110
  assert(c.napi_get_arraybuffer_info(env, argv[3], &data, &len) == c.napi_ok);
111
- assert(len == gen.OPTIONS_SIZE);
111
+ assert(len == gen.CHOICES_SIZE);
112
112
  assert(data != null);
113
113
 
114
- var out = @ptrCast([*]pkmn.Choice, data.?)[0..gen.OPTIONS_SIZE];
114
+ var out = @ptrCast([*]pkmn.Choice, data.?)[0..gen.CHOICES_SIZE];
115
115
  const n = battle.choices(player, request, out);
116
116
  return Number.init(env, @bitCast(u8, n));
117
117
  }
@@ -2,9 +2,9 @@ const std = @import("std");
2
2
  const pkmn = @import("../pkmn.zig");
3
3
 
4
4
  export const SHOWDOWN = pkmn.options.showdown;
5
- export const TRACE = pkmn.options.trace;
5
+ export const LOG = pkmn.options.log;
6
6
 
7
- export const GEN1_OPTIONS_SIZE =
8
- std.math.ceilPowerOfTwo(u32, @intCast(u32, pkmn.gen1.OPTIONS_SIZE)) catch unreachable;
7
+ export const GEN1_CHOICES_SIZE =
8
+ std.math.ceilPowerOfTwo(u32, @intCast(u32, pkmn.gen1.CHOICES_SIZE)) catch unreachable;
9
9
  export const GEN1_LOGS_SIZE =
10
10
  std.math.ceilPowerOfTwo(u32, @intCast(u32, pkmn.gen1.LOGS_SIZE)) catch unreachable;
@@ -58,6 +58,7 @@ fn inspect(value: anytype) void {
58
58
  @compileError(err);
59
59
  },
60
60
  },
61
+ .Optional => stderr.print("{?}", .{value}) catch return,
61
62
  else => stderr.print("{}", .{value}) catch return,
62
63
  }
63
64
  }
@@ -3,7 +3,7 @@ const root = @import("root");
3
3
 
4
4
  pub const Options = struct {
5
5
  showdown: ?bool = null,
6
- trace: ?bool = null,
6
+ log: ?bool = null,
7
7
  advance: ?bool = null,
8
8
  ebc: ?bool = null,
9
9
  internal: ?bool = null,
@@ -11,8 +11,8 @@ pub const Options = struct {
11
11
 
12
12
  /// Whether or not Pokémon Showdown compatibility mode is enabled.
13
13
  pub const showdown = get("showdown", false);
14
- /// Whether or not protocol trace logging is enabled.
15
- pub const trace = get("trace", false);
14
+ /// Whether or not protocol message logging is enabled.
15
+ pub const log = get("log", false);
16
16
 
17
17
  pub const advance = get("advance", true);
18
18
  pub const ebc = get("ebc", true);