@pkmn/engine 0.1.0-dev.32adfe77 → 0.1.0-dev.36b5d56b

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 (75) hide show
  1. package/README.md +15 -11
  2. package/build/pkg/addon/browser.d.ts +3 -0
  3. package/build/pkg/addon/browser.js +44 -0
  4. package/build/pkg/addon/browser.js.map +1 -0
  5. package/build/pkg/addon/node.d.ts +3 -0
  6. package/build/pkg/addon/node.js +97 -0
  7. package/build/pkg/addon/node.js.map +1 -0
  8. package/build/pkg/addon/wasm.d.ts +2 -0
  9. package/build/pkg/addon/wasm.js +21 -0
  10. package/build/pkg/addon/wasm.js.map +1 -0
  11. package/build/pkg/addon.d.ts +22 -0
  12. package/build/pkg/addon.js +35 -58
  13. package/build/pkg/addon.js.map +1 -1
  14. package/build/pkg/data.d.ts +25 -4
  15. package/build/pkg/data.js.map +1 -1
  16. package/build/pkg/gen1.js +1 -1
  17. package/build/pkg/gen1.js.map +1 -1
  18. package/build/pkg/index.d.ts +22 -9
  19. package/build/pkg/index.js +15 -10
  20. package/build/pkg/index.js.map +1 -1
  21. package/build/pkg/protocol.d.ts +20 -1
  22. package/build/pkg/protocol.js +109 -107
  23. package/build/pkg/protocol.js.map +1 -1
  24. package/build/tools/debug.js +36 -70
  25. package/build/tools/debug.js.map +1 -1
  26. package/build/tools/display/debug.jsx +141 -0
  27. package/build/tools/display/debug.jsx.map +1 -0
  28. package/build/tools/display/index.js +141 -0
  29. package/build/tools/display/index.js.map +1 -0
  30. package/build/tools/display/ui.jsx +349 -0
  31. package/build/tools/display/ui.jsx.map +1 -0
  32. package/build/tools/display/util.js +18 -0
  33. package/build/tools/display/util.js.map +1 -0
  34. package/build.zig +218 -76
  35. package/package.json +53 -33
  36. package/src/bin/install-pkmn-engine +17 -7
  37. package/src/bin/pkmn-debug +1 -1
  38. package/src/lib/common/array.zig +77 -0
  39. package/src/lib/common/data.zig +8 -8
  40. package/src/lib/common/debug.zig +39 -8
  41. package/src/lib/common/js.zig +4 -2
  42. package/src/lib/common/optional.zig +13 -9
  43. package/src/lib/common/options.zig +6 -0
  44. package/src/lib/common/protocol.zig +50 -44
  45. package/src/lib/common/rational.zig +121 -29
  46. package/src/lib/common/rng.zig +5 -7
  47. package/src/lib/common/util.zig +50 -1
  48. package/src/lib/gen1/calc.zig +683 -156
  49. package/src/lib/gen1/chance.zig +415 -290
  50. package/src/lib/gen1/data/moves.zig +2 -4
  51. package/src/lib/gen1/data/species.zig +1 -3
  52. package/src/lib/gen1/data/types.zig +1 -2
  53. package/src/lib/gen1/data.zig +38 -41
  54. package/src/lib/gen1/helpers.zig +92 -548
  55. package/src/lib/gen1/mechanics.zig +325 -235
  56. package/src/lib/gen2/calc.zig +37 -27
  57. package/src/lib/gen2/chance.zig +90 -502
  58. package/src/lib/gen2/data/items.zig +1 -3
  59. package/src/lib/gen2/data/moves.zig +2 -4
  60. package/src/lib/gen2/data/species.zig +1 -3
  61. package/src/lib/gen2/data/types.zig +1 -2
  62. package/src/lib/gen2/data.zig +26 -29
  63. package/src/lib/gen2/generated.zig +18 -23
  64. package/src/lib/gen2/helpers.zig +46 -25
  65. package/src/lib/gen2/mechanics.zig +180 -133
  66. package/src/lib/node.zig +2 -4
  67. package/src/lib/pkmn.zig +14 -16
  68. package/src/lib/wasm.zig +1 -2
  69. package/src/tools/display/dom.ts +96 -0
  70. package/src/tools/display/ui.css +354 -0
  71. package/build/test/display.js +0 -400
  72. package/build/test/display.js.map +0 -1
  73. package/src/lib/gen1/README.md +0 -894
  74. package/src/lib/gen2/README.md +0 -329
  75. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -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: 12, patch: 0, dev: 2036};
13
+ const ZIG_VERSION = {major: 0, minor: 11, 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';
@@ -163,8 +163,10 @@ const install = async () => {
163
163
  }
164
164
 
165
165
  const index = JSON.parse(await fetch(INDEX));
166
- const version = Object.keys(index)[+!ZIG_VERSION.dev];
167
- const release = index[version][`${arch}-${platform}`];
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}`];
168
170
  const url = release.tarball;
169
171
 
170
172
  let base = path.basename(url);
@@ -370,8 +372,10 @@ const downloadImportLib = async () => {
370
372
  const args = ['build', '-p', 'build', ...opts];
371
373
  if (!process.env.DEBUG_PKMN_ENGINE) args.push('-Doptimize=ReleaseFast', '-Dstrip');
372
374
  if (config.type === 'node') {
373
- args.push(`-Dnode-headers=${headers}`);
374
- if (process.platform === 'win32') args.push(`-Dnode-import-library=${lib}`);
375
+ args.push(`-Dnode-headers=${path.relative(ROOT, headers)}`);
376
+ if (process.platform === 'win32') {
377
+ args.push(`-Dnode-import-library=${path.relative(ROOT, lib)}`);
378
+ }
375
379
  } else {
376
380
  args.push('-Dwasm');
377
381
  }
@@ -386,8 +390,14 @@ const downloadImportLib = async () => {
386
390
  const prefix = process.platform === 'win32' ? '' : 'lib';
387
391
  const ext = process.platform === 'darwin'
388
392
  ? '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));
393
+ try {
394
+ const actual = path.join(ROOT, 'build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
395
+ fs.renameSync(actual, artifact);
396
+ } catch (err) {
397
+ // ziglang/zig#19743 changed this path
398
+ const actual = path.join(ROOT, 'build', 'bin', `${prefix}pkmn${suffix}.node.${ext}`);
399
+ fs.renameSync(actual, artifact);
400
+ }
391
401
  }
392
402
  }
393
403
  })().catch(e => {
@@ -15,7 +15,7 @@ const ROOT = resolve(__dirname, '..', '..');
15
15
  const packageJSON = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8'));
16
16
 
17
17
  const missing = [];
18
- for (const dep of ['@pkmn/img', 'html-minifier', 'mustache']) {
18
+ for (const dep of ['@pkmn/img', 'html-minifier', 'esbuild']) {
19
19
  try {
20
20
  require.resolve(dep);
21
21
  } catch (e) {
@@ -0,0 +1,77 @@
1
+ const std = @import("std");
2
+
3
+ const expectEqual = std.testing.expectEqual;
4
+ const assert = std.debug.assert;
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
+ /// Helpers for working with bit-packed arrays of non-powers-of-2 types.
10
+ /// NOTE: ziglang/zig#12547
11
+ pub fn Array(comptime n: comptime_int, comptime U: type) type {
12
+ return struct {
13
+ const size = @bitSizeOf(U);
14
+ const options = .{ .signedness = .unsigned, .bits = size * n };
15
+ pub const T = @Type(if (@hasField(std.builtin.Type, "int"))
16
+ .{ .int = options }
17
+ else
18
+ .{ .Int = options });
19
+
20
+ /// Returns the value stored at index `i` in the array `a`.
21
+ pub fn get(a: T, i: usize) U {
22
+ assert(i < n);
23
+ const shift = i * size;
24
+ const mask: T = (1 << size) - 1;
25
+ const result = (a >> @intCast(shift)) & mask;
26
+ return switch (@typeInfo(U)) {
27
+ Enum => @enumFromInt(result),
28
+ Int => @intCast(result),
29
+ else => unreachable,
30
+ };
31
+ }
32
+
33
+ /// Sets the value at index `i` to `val` in the array `a`.
34
+ pub fn set(a: T, i: usize, val: U) T {
35
+ assert(i < n);
36
+ const v: T = switch (@typeInfo(U)) {
37
+ Enum => @intFromEnum(val),
38
+ Int => @intCast(val),
39
+ else => unreachable,
40
+ };
41
+ const shift = i * size;
42
+ const mask: T = @as(T, @intCast((1 << size) - 1)) << @intCast(shift);
43
+ const result: T = a & ~mask;
44
+ return result | (v << @intCast(shift));
45
+ }
46
+ };
47
+ }
48
+
49
+ test Array {
50
+ const A = Array(5, u8);
51
+ var a: A.T = 0;
52
+ try expectEqual(u40, @TypeOf(a));
53
+
54
+ a = A.set(a, 4, 241);
55
+ try expectEqual(@as(u8, 241), A.get(a, 4));
56
+ a = A.set(a, 4, 1);
57
+ try expectEqual(@as(u8, 1), A.get(a, 4));
58
+
59
+ for (0..5) |i| a = A.set(a, i, @intCast(i));
60
+ for (0..5) |i| try expectEqual(@as(u8, @intCast(i)), A.get(a, i));
61
+
62
+ const Optional = @import("optional.zig").Optional;
63
+
64
+ const B = Array(4, Optional(bool));
65
+ var b: B.T = 0;
66
+ try expectEqual(u8, @TypeOf(b));
67
+
68
+ b = B.set(b, 2, .true);
69
+ try expectEqual(Optional(bool).None, B.get(b, 1));
70
+ try expectEqual(Optional(bool).true, B.get(b, 2));
71
+ try expectEqual(@as(u8, 0b00100000), b);
72
+ b = B.set(b, 2, .None);
73
+ b = B.set(b, 0, .false);
74
+ try expectEqual(Optional(bool).None, B.get(b, 2));
75
+ try expectEqual(Optional(bool).false, B.get(b, 0));
76
+ try expectEqual(@as(u8, 0b0000001), b);
77
+ }
@@ -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(0b0001, @as(u8, @bitCast(Player.P1.ident(1))));
26
- try expectEqual(0b1101, @as(u8, @bitCast(Player.P2.ident(5))));
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))));
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(0b0001, @as(u8, @bitCast(ID{ .player = .P1, .id = 1 })));
50
- try expectEqual(0b1101, @as(u8, @bitCast(ID{ .player = .P2, .id = 5 })));
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 })));
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(0b0001_0001, @as(u8, @bitCast(p1)));
80
- try expectEqual(0b0001_0110, @as(u8, @bitCast(p2)));
79
+ try expectEqual(@as(u8, 0b0001_0001), @as(u8, @bitCast(p1)));
80
+ try expectEqual(@as(u8, 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(0b0101_0000, @as(u8, @bitCast(Result.Default)));
116
- try expectEqual(0b1000_0000, @as(u8, @bitCast(Result{ .p2 = .Switch })));
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 })));
117
117
  }
@@ -3,9 +3,19 @@ const std = @import("std");
3
3
  const debug = std.debug;
4
4
  const io = std.io;
5
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
+
6
13
  pub fn print(value: anytype) void {
7
- debug.getStderrMutex().lock();
8
- defer debug.getStderrMutex().unlock();
14
+ if (@hasDecl(debug, "lockStdErr")) debug.lockStdErr() else debug.getStderrMutex().lock();
15
+ defer if (@hasDecl(debug, "unlockStdErr"))
16
+ debug.unlockStdErr()
17
+ else
18
+ debug.getStderrMutex().unlock();
9
19
  const stderr = io.getStdErr().writer();
10
20
 
11
21
  nosuspend {
@@ -19,7 +29,7 @@ pub fn print(value: anytype) void {
19
29
  }) catch return;
20
30
  } else {
21
31
  switch (@typeInfo(@TypeOf(value))) {
22
- .Struct => |info| {
32
+ Struct => |info| {
23
33
  if (info.is_tuple) {
24
34
  inline for (info.fields, 0..) |f, i| {
25
35
  inspect(@field(value, f.name));
@@ -42,17 +52,17 @@ fn inspect(value: anytype) void {
42
52
  nosuspend {
43
53
  const err = "Unable to format type '" ++ @typeName(@TypeOf(value)) ++ "'";
44
54
  switch (@typeInfo(@TypeOf(value))) {
45
- .Array => |info| {
55
+ Array => |info| {
46
56
  if (info.child == u8) return stderr.print("{s}", .{value}) catch return;
47
57
  @compileError(err);
48
58
  },
49
- .Pointer => |ptr_info| switch (ptr_info.size) {
59
+ Pointer => |ptr_info| switch (ptr_info.size) {
50
60
  .One => switch (@typeInfo(ptr_info.child)) {
51
- .Array => |info| {
61
+ Array => |info| {
52
62
  if (info.child == u8) return stderr.print("{s}", .{value}) catch return;
53
63
  @compileError(err);
54
64
  },
55
- .Enum, .Union, .Struct => return inspect(value.*),
65
+ Enum, Union, Struct => return inspect(value.*),
56
66
  else => @compileError(err),
57
67
  },
58
68
  .Many, .C => {
@@ -67,8 +77,29 @@ fn inspect(value: anytype) void {
67
77
  @compileError(err);
68
78
  },
69
79
  },
70
- .Optional => stderr.print("{?}", .{value}) catch return,
80
+ Optional => stderr.print("{?}", .{value}) catch return,
71
81
  else => stderr.print("{}", .{value}) catch return,
72
82
  }
73
83
  }
74
84
  }
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
+ }
@@ -2,6 +2,8 @@ const std = @import("std");
2
2
 
3
3
  const assert = std.debug.assert;
4
4
 
5
+ const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
6
+
5
7
  const c = @cImport({
6
8
  @cDefine("NAPI_VERSION", "8");
7
9
  @cInclude("node_api.h");
@@ -35,7 +37,7 @@ pub const Number = struct {
35
37
  const T = @TypeOf(value);
36
38
  var result: c.napi_value = undefined;
37
39
  assert(c.napi_ok == switch (@typeInfo(T)) {
38
- .Int => |info| switch (info.bits) {
40
+ Int => |info| switch (info.bits) {
39
41
  0...32 => switch (info.signedness) {
40
42
  .signed => c.napi_create_int32(env, @as(i32, value), &result),
41
43
  .unsigned => c.napi_create_uint32(env, @as(u32, value), &result),
@@ -50,7 +52,7 @@ pub const Number = struct {
50
52
 
51
53
  pub fn get(env: c.napi_env, value: c.napi_value, comptime T: type) T {
52
54
  switch (@typeInfo(T)) {
53
- .Int => |info| switch (info.bits) {
55
+ Int => |info| switch (info.bits) {
54
56
  0...32 => switch (info.signedness) {
55
57
  .signed => {
56
58
  var result: i32 = undefined;
@@ -3,10 +3,12 @@ const std = @import("std");
3
3
  const expect = std.testing.expect;
4
4
  const assert = std.debug.assert;
5
5
 
6
+ const Bool = if (@hasField(std.builtin.Type, "bool")) .bool else .Bool;
7
+
6
8
  // TODO: ziglang/zig#104
7
9
  pub fn Optional(comptime T: type) type {
8
10
  const fields = std.meta.fields(switch (@typeInfo(T)) {
9
- .Bool => enum { false, true },
11
+ Bool => enum { false, true },
10
12
  else => T,
11
13
  });
12
14
 
@@ -23,14 +25,16 @@ pub fn Optional(comptime T: type) type {
23
25
  };
24
26
  }
25
27
 
26
- return @Type(.{
27
- .Enum = .{
28
- .tag_type = std.math.IntFittingRange(0, fields.len),
29
- .fields = &enumFields,
30
- .decls = &decls,
31
- .is_exhaustive = true,
32
- },
33
- });
28
+ const options = .{
29
+ .tag_type = std.math.IntFittingRange(0, fields.len),
30
+ .fields = &enumFields,
31
+ .decls = &decls,
32
+ .is_exhaustive = true,
33
+ };
34
+ return @Type(if (@hasField(std.builtin.Type, "enum"))
35
+ .{ .@"enum" = options }
36
+ else
37
+ .{ .Enum = options });
34
38
  }
35
39
 
36
40
  test Optional {
@@ -7,9 +7,12 @@ pub const Options = struct {
7
7
  log: ?bool = null,
8
8
  chance: ?bool = null,
9
9
  calc: ?bool = null,
10
+ mod: ?bool = null,
10
11
  advance: ?bool = null,
11
12
  ebc: ?bool = null,
12
13
  key: ?bool = null,
14
+ miss: ?bool = null,
15
+ overwrite: ?bool = null,
13
16
  internal: ?bool = null,
14
17
  };
15
18
 
@@ -22,9 +25,12 @@ pub const chance = get("chance", false);
22
25
  /// Whether or not damage calculator support is enabled.
23
26
  pub const calc = get("calc", false);
24
27
 
28
+ pub const mod = showdown or get("mod", false);
25
29
  pub const advance = get("advance", true);
26
30
  pub const ebc = get("ebc", true);
27
31
  pub const key = get("key", false);
32
+ pub const miss = get("miss", true);
33
+ pub const overwrite = get("overwrite", true);
28
34
  pub const internal = get("internal", false);
29
35
 
30
36
  fn get(comptime name: []const u8, default: bool) bool {
@@ -1,20 +1,21 @@
1
- const std = @import("std");
2
1
  const builtin = @import("builtin");
3
-
4
- const pkmn = @import("../pkmn.zig");
5
-
6
2
  const data = @import("data.zig");
7
3
  const options = @import("options.zig");
4
+ const pkmn = @import("../pkmn.zig");
5
+ const std = @import("std");
8
6
 
9
7
  const assert = std.debug.assert;
10
- const print = std.debug.print;
11
-
12
8
  const enabled = options.log;
13
-
14
- const Player = data.Player;
15
9
  const ID = data.ID;
10
+ const Player = data.Player;
11
+ const print = std.debug.print;
16
12
 
17
13
  const endian = builtin.cpu.arch.endian();
14
+ const Endian = std.builtin.Endian;
15
+ const big = if (@hasField(Endian, "big")) Endian.big else Endian.Big;
16
+ const little = if (@hasField(Endian, "little")) Endian.little else Endian.Little;
17
+
18
+ const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
18
19
 
19
20
  pub const ArgType = enum(u8) {
20
21
  None,
@@ -220,6 +221,7 @@ pub const Activate = enum(u8) {
220
221
  BeatUp, // FIXME of
221
222
 
222
223
  Magnitude,
224
+ Spite,
223
225
  };
224
226
 
225
227
  pub const Start = enum(u8) {
@@ -544,6 +546,7 @@ pub fn Log(comptime Writer: type) type {
544
546
  // ident: ID, reason: Activate
545
547
  // ident: ID, reason: .SubstituteBlock, m: <Move>
546
548
  // ident: ID, reason: .Magnitude, num: u8
549
+ // ident: ID, reason: .Spite, m: <Move>, num: u8
547
550
  pub fn activate(self: Self, args: anytype) Error!void {
548
551
  if (!enabled) return;
549
552
 
@@ -561,6 +564,9 @@ pub fn Log(comptime Writer: type) type {
561
564
  assert(reason == .Magnitude);
562
565
  try self.writer.writeByte(args[2]);
563
566
  }
567
+ } else if (args.len == 4) {
568
+ assert(reason == .Spite);
569
+ try self.writer.writeAll(&.{ @intFromEnum(args[2]), args[3] });
564
570
  }
565
571
  }
566
572
 
@@ -835,7 +841,7 @@ pub const ByteStream = struct {
835
841
 
836
842
  pub fn writeInt(self: Writer, comptime T: type, v: T, end: std.builtin.Endian) Error!void {
837
843
  // TODO: rework this to write directly to the buffer?
838
- var bytes: [@divExact(@typeInfo(T).Int.bits, 8)]u8 = undefined;
844
+ var bytes: [@divExact(@field(@typeInfo(T), @tagName(Int)).bits, 8)]u8 = undefined;
839
845
  std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(v)), &bytes, v, end);
840
846
  return self.writeAll(&bytes);
841
847
  }
@@ -859,7 +865,7 @@ pub const ByteStream = struct {
859
865
  pub const Kind = enum { Move, Species, Type, Status, Item, Weather };
860
866
 
861
867
  pub fn format(
862
- comptime gen: anytype,
868
+ gen: anytype,
863
869
  a: []const u8,
864
870
  b: ?[]const u8,
865
871
  color: bool,
@@ -951,13 +957,13 @@ pub fn format(
951
957
  }
952
958
  printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
953
959
  switch (endian) {
954
- .big => {
960
+ big => {
955
961
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
956
962
  printc(" {d}", .{hp}, a, b, &i, 2, color);
957
963
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
958
964
  printc("/{d}", .{hp}, a, b, &i, 2, color);
959
965
  },
960
- .little => {
966
+ little => {
961
967
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
962
968
  printc(" {d}", .{hp}, a, b, &i, 2, color);
963
969
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -988,8 +994,8 @@ pub fn format(
988
994
  },
989
995
  .Turn => {
990
996
  const turn = switch (endian) {
991
- .big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
992
- .little => @as(u16, a[i + 1]) << 8 | @as(u16, a[i]),
997
+ big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
998
+ little => @as(u16, a[i + 1]) << 8 | @as(u16, a[i]),
993
999
  };
994
1000
  printc(" {d}", .{turn}, a, b, &i, 2, color);
995
1001
  },
@@ -1000,13 +1006,13 @@ pub fn format(
1000
1006
  var id = ID.from(@intCast(a[i]));
1001
1007
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1002
1008
  switch (endian) {
1003
- .big => {
1009
+ big => {
1004
1010
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1005
1011
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1006
1012
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1007
1013
  printc("/{d}", .{hp}, a, b, &i, 2, color);
1008
1014
  },
1009
- .little => {
1015
+ little => {
1010
1016
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
1011
1017
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1012
1018
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -1128,13 +1134,13 @@ pub fn format(
1128
1134
  const id = ID.from(@intCast(a[i]));
1129
1135
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1130
1136
  switch (endian) {
1131
- .big => {
1137
+ big => {
1132
1138
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1133
1139
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1134
1140
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1135
1141
  printc("/{d}", .{hp}, a, b, &i, 2, color);
1136
1142
  },
1137
- .little => {
1143
+ little => {
1138
1144
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
1139
1145
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1140
1146
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -1340,8 +1346,8 @@ test "|switch|" {
1340
1346
  try log.switched(.{ p2.ident(3), &snorlax });
1341
1347
  const par = 0b1000000;
1342
1348
  var expected: []const u8 = switch (endian) {
1343
- .big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
1344
- .little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 200, 0, 144, 1, par },
1349
+ big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
1350
+ little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 200, 0, 144, 1, par },
1345
1351
  };
1346
1352
  try expectLog1(expected, buf[0..9]);
1347
1353
  stream.reset();
@@ -1351,8 +1357,8 @@ test "|switch|" {
1351
1357
  snorlax.status = 0;
1352
1358
  try log.switched(.{ p2.ident(3), &snorlax });
1353
1359
  expected = switch (endian) {
1354
- .big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
1355
- .little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 144, 1, 0 },
1360
+ big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
1361
+ little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 144, 1, 0 },
1356
1362
  };
1357
1363
  try expectLog1(expected, buf[0..9]);
1358
1364
  stream.reset();
@@ -1360,8 +1366,8 @@ test "|switch|" {
1360
1366
  snorlax.hp = 400;
1361
1367
  try log.switched(.{ p2.ident(3), &snorlax });
1362
1368
  expected = switch (endian) {
1363
- .big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
1364
- .little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 144, 1, 144, 1, 0 },
1369
+ big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
1370
+ little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 144, 1, 144, 1, 0 },
1365
1371
  };
1366
1372
  try expectLog1(expected, buf[0..9]);
1367
1373
  stream.reset();
@@ -1379,8 +1385,8 @@ test "|switch|" {
1379
1385
  N(gen2.Gender.Female),
1380
1386
  91,
1381
1387
  } ++ switch (endian) {
1382
- .big => .{ 0, 200, 1, 144, par },
1383
- .little => .{ 200, 0, 144, 1, par },
1388
+ big => .{ 0, 200, 1, 144, par },
1389
+ little => .{ 200, 0, 144, 1, par },
1384
1390
  });
1385
1391
  try expectLog2(expected, buf[0..10]);
1386
1392
  stream.reset();
@@ -1409,8 +1415,8 @@ test "|faint|" {
1409
1415
  test "|turn|" {
1410
1416
  try log.turn(.{42});
1411
1417
  const expected = switch (endian) {
1412
- .big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
1413
- .little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
1418
+ big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
1419
+ little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
1414
1420
  };
1415
1421
  try expectLog1(expected, buf[0..4]);
1416
1422
  stream.reset();
@@ -1434,8 +1440,8 @@ test "|-damage|" {
1434
1440
  chansey.status = gen1.Status.slp(1);
1435
1441
  try log.damage(.{ p2.ident(2), &chansey, .None });
1436
1442
  var expected: []const u8 = switch (endian) {
1437
- .big => &.{ N(ArgType.Damage), 0b1010, 2, 100, 2, 191, 1, N(Damage.None) },
1438
- .little => &.{ N(ArgType.Damage), 0b1010, 100, 2, 191, 2, 1, N(Damage.None) },
1443
+ big => &.{ N(ArgType.Damage), 0b1010, 2, 100, 2, 191, 1, N(Damage.None) },
1444
+ little => &.{ N(ArgType.Damage), 0b1010, 100, 2, 191, 2, 1, N(Damage.None) },
1439
1445
  };
1440
1446
  try expectLog1(expected, buf[0..8]);
1441
1447
  stream.reset();
@@ -1445,8 +1451,8 @@ test "|-damage|" {
1445
1451
  chansey.status = 0;
1446
1452
  try log.damage(.{ p2.ident(2), &chansey, .Confusion });
1447
1453
  expected = switch (endian) {
1448
- .big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0, N(Damage.Confusion) },
1449
- .little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0, N(Damage.Confusion) },
1454
+ big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0, N(Damage.Confusion) },
1455
+ little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0, N(Damage.Confusion) },
1450
1456
  };
1451
1457
  try expectLog1(expected, buf[0..8]);
1452
1458
  stream.reset();
@@ -1454,8 +1460,8 @@ test "|-damage|" {
1454
1460
  chansey.status = gen1.Status.init(.PSN);
1455
1461
  try log.damage(.{ p2.ident(2), &chansey, .RecoilOf, p1.ident(1) });
1456
1462
  expected = switch (endian) {
1457
- .big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0b1000, N(Damage.RecoilOf), 1 },
1458
- .little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0b1000, N(Damage.RecoilOf), 1 },
1463
+ big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0b1000, N(Damage.RecoilOf), 1 },
1464
+ little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0b1000, N(Damage.RecoilOf), 1 },
1459
1465
  };
1460
1466
  try expectLog1(expected, buf[0..9]);
1461
1467
  stream.reset();
@@ -1467,8 +1473,8 @@ test "|-heal|" {
1467
1473
  chansey.status = gen1.Status.slp(1);
1468
1474
  try log.heal(.{ p2.ident(2), &chansey, .None });
1469
1475
  var expected: []const u8 = switch (endian) {
1470
- .big => &.{ N(ArgType.Heal), 0b1010, 2, 100, 2, 191, 1, N(Heal.None) },
1471
- .little => &.{ N(ArgType.Heal), 0b1010, 100, 2, 191, 2, 1, N(Heal.None) },
1476
+ big => &.{ N(ArgType.Heal), 0b1010, 2, 100, 2, 191, 1, N(Heal.None) },
1477
+ little => &.{ N(ArgType.Heal), 0b1010, 100, 2, 191, 2, 1, N(Heal.None) },
1472
1478
  };
1473
1479
  try expectLog1(expected, buf[0..8]);
1474
1480
  stream.reset();
@@ -1478,16 +1484,16 @@ test "|-heal|" {
1478
1484
  chansey.status = 0;
1479
1485
  try log.heal(.{ p2.ident(2), &chansey, .Silent });
1480
1486
  expected = switch (endian) {
1481
- .big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Silent) },
1482
- .little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Silent) },
1487
+ big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Silent) },
1488
+ little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Silent) },
1483
1489
  };
1484
1490
  try expectLog1(expected, buf[0..8]);
1485
1491
  stream.reset();
1486
1492
 
1487
1493
  try log.heal(.{ p2.ident(2), &chansey, .Drain, p1.ident(1) });
1488
1494
  expected = switch (endian) {
1489
- .big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Drain), 1 },
1490
- .little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Drain), 1 },
1495
+ big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Drain), 1 },
1496
+ little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Drain), 1 },
1491
1497
  };
1492
1498
  try expectLog1(expected, buf[0..9]);
1493
1499
  stream.reset();
@@ -1730,8 +1736,8 @@ test "|drag|" {
1730
1736
  N(gen2.Gender.Female),
1731
1737
  91,
1732
1738
  } ++ switch (endian) {
1733
- .big => .{ 0, 200, 1, 144, par },
1734
- .little => .{ 200, 0, 144, 1, par },
1739
+ big => .{ 0, 200, 1, 144, par },
1740
+ little => .{ 200, 0, 144, 1, par },
1735
1741
  });
1736
1742
  try expectLog2(expected, buf[0..10]);
1737
1743
  stream.reset();
@@ -1764,8 +1770,8 @@ test "|-sethp|" {
1764
1770
  blissey.hp = 612;
1765
1771
  try log.sethp(.{ p2.ident(2), &blissey, .Silent });
1766
1772
  const expected: []const u8 = switch (endian) {
1767
- .big => &.{ N(ArgType.SetHP), 0b1010, 2, 100, 2, 201, 0, N(SetHP.Silent) },
1768
- .little => &.{ N(ArgType.SetHP), 0b1010, 100, 2, 201, 2, 0, N(SetHP.Silent) },
1773
+ big => &.{ N(ArgType.SetHP), 0b1010, 2, 100, 2, 201, 0, N(SetHP.Silent) },
1774
+ little => &.{ N(ArgType.SetHP), 0b1010, 100, 2, 201, 2, 0, N(SetHP.Silent) },
1769
1775
  };
1770
1776
  try expectLog2(expected, buf[0..8]);
1771
1777
  stream.reset();