@pkmn/engine 0.1.0-dev.80019d10 → 0.1.0-dev.8058a1d0

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 (84) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +59 -24
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +47 -0
  5. package/build/pkg/addon/browser.js.map +1 -0
  6. package/build/pkg/addon/node.d.ts +3 -0
  7. package/build/pkg/addon/node.js +110 -0
  8. package/build/pkg/addon/node.js.map +1 -0
  9. package/build/pkg/addon/wasm.d.ts +2 -0
  10. package/build/pkg/addon/wasm.js +53 -0
  11. package/build/pkg/addon/wasm.js.map +1 -0
  12. package/build/pkg/addon.d.ts +26 -4
  13. package/build/pkg/addon.js +39 -71
  14. package/build/pkg/addon.js.map +1 -1
  15. package/build/pkg/data/layout.json +15 -2
  16. package/build/pkg/data/protocol.json +23 -9
  17. package/build/pkg/data.d.ts +27 -5
  18. package/build/pkg/data.js.map +1 -1
  19. package/build/pkg/gen1.d.ts +15 -18
  20. package/build/pkg/gen1.js +28 -19
  21. package/build/pkg/gen1.js.map +1 -1
  22. package/build/pkg/index.d.ts +42 -91
  23. package/build/pkg/index.js +23 -70
  24. package/build/pkg/index.js.map +1 -1
  25. package/build/pkg/protocol.d.ts +29 -1
  26. package/build/pkg/protocol.js +109 -107
  27. package/build/pkg/protocol.js.map +1 -1
  28. package/build/tools/debug.js +84 -75
  29. package/build/tools/debug.js.map +1 -1
  30. package/build/tools/display/debug.jsx +66 -0
  31. package/build/tools/display/debug.jsx.map +1 -0
  32. package/build/tools/display/index.js +152 -0
  33. package/build/tools/display/index.js.map +1 -0
  34. package/build/tools/display/ui.jsx +360 -0
  35. package/build/tools/display/ui.jsx.map +1 -0
  36. package/build/tools/display/util.js +157 -0
  37. package/build/tools/display/util.js.map +1 -0
  38. package/build.zig +259 -112
  39. package/package.json +61 -132
  40. package/src/bin/install-pkmn-engine +47 -21
  41. package/src/bin/pkmn-debug +1 -1
  42. package/src/lib/bindings/c.zig +200 -0
  43. package/src/lib/{binding → bindings}/node.zig +15 -32
  44. package/src/lib/bindings/wasm.zig +50 -0
  45. package/src/lib/common/array.zig +70 -0
  46. package/src/lib/common/data.zig +4 -4
  47. package/src/lib/common/debug.zig +33 -28
  48. package/src/lib/common/js.zig +3 -7
  49. package/src/lib/common/optional.zig +12 -18
  50. package/src/lib/common/options.zig +6 -0
  51. package/src/lib/common/protocol.zig +256 -224
  52. package/src/lib/common/rational.zig +340 -253
  53. package/src/lib/common/rng.zig +7 -9
  54. package/src/lib/common/util.zig +33 -1
  55. package/src/lib/gen1/calc.zig +724 -175
  56. package/src/lib/gen1/chance.zig +453 -291
  57. package/src/lib/gen1/data/moves.zig +2 -4
  58. package/src/lib/gen1/data/species.zig +2 -4
  59. package/src/lib/gen1/data/types.zig +3 -4
  60. package/src/lib/gen1/data.zig +29 -32
  61. package/src/lib/gen1/helpers.zig +91 -549
  62. package/src/lib/gen1/mechanics.zig +417 -294
  63. package/src/lib/gen2/calc.zig +35 -28
  64. package/src/lib/gen2/chance.zig +85 -503
  65. package/src/lib/gen2/data/items.zig +1 -3
  66. package/src/lib/gen2/data/moves.zig +2 -4
  67. package/src/lib/gen2/data/species.zig +1 -3
  68. package/src/lib/gen2/data/types.zig +7 -5
  69. package/src/lib/gen2/data.zig +27 -29
  70. package/src/lib/gen2/generated.zig +19 -26
  71. package/src/lib/gen2/helpers.zig +45 -26
  72. package/src/lib/gen2/mechanics.zig +234 -180
  73. package/src/lib/napi.h +2 -0
  74. package/src/lib/node.zig +14 -0
  75. package/src/lib/pkmn.zig +125 -29
  76. package/src/lib/wasm.zig +13 -0
  77. package/src/tools/display/dom.ts +108 -0
  78. package/src/tools/display/ui.css +354 -0
  79. package/build/test/display.js +0 -400
  80. package/build/test/display.js.map +0 -1
  81. package/src/lib/binding/wasm.zig +0 -12
  82. package/src/lib/gen1/README.md +0 -894
  83. package/src/lib/gen2/README.md +0 -329
  84. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -1,18 +1,17 @@
1
- const std = @import("std");
2
1
  const builtin = @import("builtin");
3
-
2
+ const data = @import("data.zig");
3
+ const options = @import("options.zig");
4
4
  const pkmn = @import("../pkmn.zig");
5
-
6
- const data = @import("./data.zig");
7
- const options = @import("./options.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;
12
+
13
+ const endian = builtin.cpu.arch.endian();
14
+ const Endian = std.builtin.Endian;
16
15
 
17
16
  pub const ArgType = enum(u8) {
18
17
  None,
@@ -71,7 +70,7 @@ pub const ArgType = enum(u8) {
71
70
  EndAbility,
72
71
  ClearNegativeBoost,
73
72
  FormeChange,
74
- NoTarget,
73
+ LastNoTarget, // FIXME
75
74
 
76
75
  // Gen 4
77
76
  SwapBoost,
@@ -218,6 +217,7 @@ pub const Activate = enum(u8) {
218
217
  BeatUp, // FIXME of
219
218
 
220
219
  Magnitude,
220
+ Spite,
221
221
  };
222
222
 
223
223
  pub const Start = enum(u8) {
@@ -309,19 +309,29 @@ pub const Weather = enum(u8) {
309
309
  Upkeep,
310
310
  };
311
311
 
312
- /// Null object pattern implementation of `Log` backed by a `std.io.null_writer`.
313
- /// Ignores anything sent to it, though protocol logging should additionally be turned off
314
- /// entirely with `options.log`.
315
- pub const NULL = Log(@TypeOf(std.io.null_writer)){ .writer = std.io.null_writer };
316
-
317
- /// Logs protocol information to its `Writer` during a battle update when `options.log` is enabled.
318
- pub fn Log(comptime Writer: type) type {
312
+ /// Logs protocol information to its `WriterT` during a battle update when `options.log` is enabled.
313
+ pub fn Log(comptime WriterT: type) type {
319
314
  return struct {
320
315
  const Self = @This();
321
316
 
322
- writer: Writer,
317
+ writer: WriterT,
323
318
 
324
- pub const Error = Writer.Error;
319
+ pub const Error = err(WriterT);
320
+
321
+ fn err(comptime T: type) type {
322
+ const msg = "Invalid Writer type " ++ @typeName(T) ++ "'";
323
+ return switch (@typeInfo(T)) {
324
+ .pointer => |ptr_info| switch (ptr_info.size) {
325
+ .one => switch (@typeInfo(ptr_info.child)) {
326
+ .@"struct" => err(ptr_info.child),
327
+ else => @compileError(msg),
328
+ },
329
+ else => @compileError(msg),
330
+ },
331
+ .@"struct" => if (@hasDecl(T, "Error")) T.Error else @compileError(msg),
332
+ else => @compileError(msg),
333
+ };
334
+ }
325
335
 
326
336
  // source: ID, move: <Move>, target: ID, from?: <Move>
327
337
  pub fn move(self: Self, args: anytype) Error!void {
@@ -359,8 +369,8 @@ pub fn Log(comptime Writer: type) type {
359
369
  } else {
360
370
  try self.writer.writeAll(&.{ @intFromEnum(args[1].species), args[1].level });
361
371
  }
362
- try self.writer.writeIntNative(u16, args[1].hp);
363
- try self.writer.writeIntNative(u16, args[1].stats.hp);
372
+ try self.writer.writeInt(u16, args[1].hp, endian);
373
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
364
374
  try self.writer.writeAll(&.{args[1].status});
365
375
  }
366
376
 
@@ -391,7 +401,7 @@ pub fn Log(comptime Writer: type) type {
391
401
  if (!enabled) return;
392
402
 
393
403
  try self.writer.writeByte(@intFromEnum(ArgType.Turn));
394
- try self.writer.writeIntNative(u16, args[0]);
404
+ try self.writer.writeInt(u16, args[0], endian);
395
405
  try self.writer.writeByte(@intFromEnum(ArgType.None));
396
406
  }
397
407
 
@@ -423,8 +433,8 @@ pub fn Log(comptime Writer: type) type {
423
433
  @intFromEnum(ArgType.Damage),
424
434
  @as(u8, @bitCast(args[0])),
425
435
  });
426
- try self.writer.writeIntNative(u16, args[1].hp);
427
- try self.writer.writeIntNative(u16, args[1].stats.hp);
436
+ try self.writer.writeInt(u16, args[1].hp, endian);
437
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
428
438
  try self.writer.writeAll(&.{ args[1].status, @intFromEnum(@as(Damage, args[2])) });
429
439
  if (args.len == 4) try self.writer.writeByte(@as(u8, @bitCast(args[3])));
430
440
  }
@@ -436,8 +446,8 @@ pub fn Log(comptime Writer: type) type {
436
446
 
437
447
  assert(args[2] != .Drain or args.len == 4);
438
448
  try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(args[0])) });
439
- try self.writer.writeIntNative(u16, args[1].hp);
440
- try self.writer.writeIntNative(u16, args[1].stats.hp);
449
+ try self.writer.writeInt(u16, args[1].hp, endian);
450
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
441
451
  try self.writer.writeAll(&.{ args[1].status, @intFromEnum(@as(Heal, args[2])) });
442
452
  if (args.len == 4) try self.writer.writeByte(@as(u8, @bitCast(args[3])));
443
453
  }
@@ -542,6 +552,7 @@ pub fn Log(comptime Writer: type) type {
542
552
  // ident: ID, reason: Activate
543
553
  // ident: ID, reason: .SubstituteBlock, m: <Move>
544
554
  // ident: ID, reason: .Magnitude, num: u8
555
+ // ident: ID, reason: .Spite, m: <Move>, num: u8
545
556
  pub fn activate(self: Self, args: anytype) Error!void {
546
557
  if (!enabled) return;
547
558
 
@@ -559,6 +570,9 @@ pub fn Log(comptime Writer: type) type {
559
570
  assert(reason == .Magnitude);
560
571
  try self.writer.writeByte(args[2]);
561
572
  }
573
+ } else if (args.len == 4) {
574
+ assert(reason == .Spite);
575
+ try self.writer.writeAll(&.{ @intFromEnum(args[2]), args[3] });
562
576
  }
563
577
  }
564
578
 
@@ -706,8 +720,8 @@ pub fn Log(comptime Writer: type) type {
706
720
  if (!enabled) return;
707
721
 
708
722
  try self.writer.writeAll(&.{ @intFromEnum(ArgType.SetHP), @as(u8, @bitCast(args[0])) });
709
- try self.writer.writeIntNative(u16, args[1].hp);
710
- try self.writer.writeIntNative(u16, args[1].stats.hp);
723
+ try self.writer.writeInt(u16, args[1].hp, endian);
724
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
711
725
  try self.writer.writeAll(&.{args[1].status});
712
726
  try self.writer.writeByte(@intFromEnum(@as(SetHP, args[2])));
713
727
  }
@@ -808,56 +822,68 @@ pub fn Log(comptime Writer: type) type {
808
822
  };
809
823
  }
810
824
 
811
- /// `Log` type backed by the optimized `ByteStream.Writer`.
812
- pub const FixedLog = Log(ByteStream.Writer);
825
+ /// `Log` type backed by the optimized `Writer`.
826
+ pub const FixedLog = Log(*Writer);
813
827
 
814
- /// Stripped down version of `std.io.FixedBufferStream` optimized for efficiently writing the
815
- /// individual protocol bytes. Note that the `ByteStream.Writer` is **not** a `std.io.Writer` and
816
- /// should not be used for general purpose writing.
817
- pub const ByteStream = struct {
828
+ /// Minimal logging helper optimized for efficiently writing the individual protocol bytes into a
829
+ /// fixed buffer. Note that this is **not** a `std.Io.Writer` and should not be used for general
830
+ /// purpose writing.
831
+ pub const Writer = struct {
818
832
  buffer: []u8,
819
833
  pos: usize = 0,
820
834
 
821
- pub const Writer = struct {
822
- stream: *ByteStream,
835
+ pub const Error = error{NoSpaceLeft};
823
836
 
824
- pub const Error = error{NoSpaceLeft};
837
+ pub fn writeByte(self: *Writer, byte: u8) Error!void {
838
+ if (self.pos >= self.buffer.len) return error.NoSpaceLeft;
839
+ self.buffer[self.pos] = byte;
840
+ self.pos += 1;
841
+ }
825
842
 
826
- pub fn writeAll(self: Writer, bytes: []const u8) Error!void {
827
- for (bytes) |b| try self.writeByte(b);
828
- }
843
+ pub fn writeAll(self: *Writer, bytes: []const u8) Error!void {
844
+ const npos = self.pos + bytes.len;
845
+ if (npos > self.buffer.len) return error.NoSpaceLeft;
846
+ @memcpy(self.buffer[self.pos..npos], bytes);
847
+ self.pos = npos;
848
+ }
829
849
 
830
- pub fn writeByte(self: Writer, byte: u8) Error!void {
831
- try self.stream.writeByte(byte);
832
- }
850
+ pub fn writeInt(self: *Writer, comptime T: type, v: T, end: std.builtin.Endian) Error!void {
851
+ const bytes = @divExact(@typeInfo(T).int.bits, 8);
852
+ const npos = self.pos + bytes;
853
+ if (npos > self.buffer.len) return error.NoSpaceLeft;
854
+ std.mem.writeInt(T, self.buffer[self.pos..][0..bytes], v, end);
855
+ self.pos = npos;
856
+ }
833
857
 
834
- pub fn writeIntNative(self: Writer, comptime T: type, value: T) Error!void {
835
- // TODO: rework this to write directly to the buffer?
836
- var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
837
- std.mem.writeIntNative(T, &bytes, value);
838
- return self.writeAll(&bytes);
839
- }
840
- };
858
+ pub fn reset(self: *Writer) void {
859
+ self.pos = 0;
860
+ }
861
+ };
862
+
863
+ /// Null object pattern implementation of `Log` backed by a null writer. Ignores anything sent to
864
+ /// it, though protocol logging should additionally be turned off entirely with `options.log`.
865
+ pub const NULL = Log(NullWriter){ .writer = .{} };
841
866
 
842
- pub fn writer(self: *ByteStream) Writer {
843
- return .{ .stream = self };
867
+ const NullWriter = struct {
868
+ pub const Error = error{};
869
+
870
+ pub fn writeByte(self: NullWriter, byte: u8) Error!void {
871
+ _ = .{ self, byte };
844
872
  }
845
873
 
846
- pub fn writeByte(self: *ByteStream, byte: u8) Writer.Error!void {
847
- if (self.pos >= self.buffer.len) return error.NoSpaceLeft;
848
- self.buffer[self.pos] = byte;
849
- self.pos += 1;
874
+ pub fn writeAll(self: NullWriter, bytes: []const u8) Error!void {
875
+ _ = .{ self, bytes };
850
876
  }
851
877
 
852
- pub fn reset(self: *ByteStream) void {
853
- self.pos = 0;
878
+ pub fn writeInt(self: NullWriter, comptime T: type, v: T, end: std.builtin.Endian) Error!void {
879
+ _ = .{ self, T, v, end };
854
880
  }
855
881
  };
856
882
 
857
883
  pub const Kind = enum { Move, Species, Type, Status, Item, Weather };
858
884
 
859
885
  pub fn format(
860
- comptime gen: anytype,
886
+ gen: anytype,
861
887
  a: []const u8,
862
888
  b: ?[]const u8,
863
889
  color: bool,
@@ -924,10 +950,10 @@ pub fn format(
924
950
  .OHKO,
925
951
  => {},
926
952
  .Move => {
927
- const source = ID.from(@intCast(a[i]));
953
+ const source: ID = .from(@intCast(a[i]));
928
954
  printc(" {s}({d})", .{ @tagName(source.player), source.id }, a, b, &i, 1, color);
929
955
  printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
930
- const target = ID.from(@intCast(a[i]));
956
+ const target: ID = .from(@intCast(a[i]));
931
957
  printc(" {s}({d})", .{ @tagName(target.player), target.id }, a, b, &i, 1, color);
932
958
  const reason: Move = @enumFromInt(a[i]);
933
959
  printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
@@ -936,26 +962,26 @@ pub fn format(
936
962
  }
937
963
  },
938
964
  .Switch, .Drag => {
939
- const id = ID.from(@intCast(a[i]));
965
+ const id: ID = .from(@intCast(a[i]));
940
966
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
941
967
  printc(" {s}", .{formatter(gen, .Species, a[i])}, a, b, &i, 1, color);
942
968
  if (@hasDecl(gen, "Gender")) {
943
969
  if (a[i] == N(gen.Gender.Unknown)) {
944
970
  i += 1;
945
971
  } else {
946
- var gender = if (a[i] == N(gen.Gender.Male)) "M" else "F";
972
+ const gender = if (a[i] == N(gen.Gender.Male)) "M" else "F";
947
973
  printc(", {s}", .{gender}, a, b, &i, 1, color);
948
974
  }
949
975
  }
950
976
  printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
951
977
  switch (endian) {
952
- .Big => {
978
+ .big => {
953
979
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
954
980
  printc(" {d}", .{hp}, a, b, &i, 2, color);
955
981
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
956
982
  printc("/{d}", .{hp}, a, b, &i, 2, color);
957
983
  },
958
- .Little => {
984
+ .little => {
959
985
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
960
986
  printc(" {d}", .{hp}, a, b, &i, 2, color);
961
987
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -965,7 +991,7 @@ pub fn format(
965
991
  printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
966
992
  },
967
993
  .Cant => {
968
- const id = ID.from(@intCast(a[i]));
994
+ const id: ID = .from(@intCast(a[i]));
969
995
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
970
996
  const reason: Cant = @enumFromInt(a[i]);
971
997
  printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
@@ -981,13 +1007,13 @@ pub fn format(
981
1007
  .Resisted,
982
1008
  .CureTeam,
983
1009
  => {
984
- const id = ID.from(@intCast(a[i]));
1010
+ const id: ID = .from(@intCast(a[i]));
985
1011
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
986
1012
  },
987
1013
  .Turn => {
988
1014
  const turn = switch (endian) {
989
- .Big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
990
- .Little => @as(u16, a[i + 1]) << 8 | @as(u16, a[i]),
1015
+ .big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
1016
+ .little => @as(u16, a[i + 1]) << 8 | @as(u16, a[i]),
991
1017
  };
992
1018
  printc(" {d}", .{turn}, a, b, &i, 2, color);
993
1019
  },
@@ -995,16 +1021,16 @@ pub fn format(
995
1021
  printc(" {s}", .{@tagName(@as(Player, @enumFromInt(a[i])))}, a, b, &i, 1, color);
996
1022
  },
997
1023
  .Damage, .Heal => {
998
- var id = ID.from(@intCast(a[i]));
1024
+ var id: ID = .from(@intCast(a[i]));
999
1025
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1000
1026
  switch (endian) {
1001
- .Big => {
1027
+ .big => {
1002
1028
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1003
1029
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1004
1030
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1005
1031
  printc("/{d}", .{hp}, a, b, &i, 2, color);
1006
1032
  },
1007
- .Little => {
1033
+ .little => {
1008
1034
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
1009
1035
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1010
1036
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -1016,20 +1042,20 @@ pub fn format(
1016
1042
  const reason: Damage = @enumFromInt(a[i]);
1017
1043
  printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
1018
1044
  if (reason == .RecoilOf) {
1019
- id = ID.from(@intCast(a[i]));
1045
+ id = .from(@intCast(a[i]));
1020
1046
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1021
1047
  }
1022
1048
  } else {
1023
1049
  const reason: Heal = @enumFromInt(a[i]);
1024
1050
  printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
1025
1051
  if (reason == .Drain) {
1026
- id = ID.from(@intCast(a[i]));
1052
+ id = .from(@intCast(a[i]));
1027
1053
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1028
1054
  }
1029
1055
  }
1030
1056
  },
1031
1057
  .Status => {
1032
- const id = ID.from(@intCast(a[i]));
1058
+ const id: ID = .from(@intCast(a[i]));
1033
1059
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1034
1060
  printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
1035
1061
  const reason: Status = @enumFromInt(a[i]);
@@ -1039,35 +1065,35 @@ pub fn format(
1039
1065
  }
1040
1066
  },
1041
1067
  .CureStatus => {
1042
- const id = ID.from(@intCast(a[i]));
1068
+ const id: ID = .from(@intCast(a[i]));
1043
1069
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1044
1070
  printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
1045
1071
  const reason: CureStatus = @enumFromInt(a[i]);
1046
1072
  printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
1047
1073
  },
1048
1074
  .Boost => {
1049
- const id = ID.from(@intCast(a[i]));
1075
+ const id: ID = .from(@intCast(a[i]));
1050
1076
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1051
1077
  printc(" {s}", .{@tagName(@as(Boost, @enumFromInt(a[i])))}, a, b, &i, 1, color);
1052
1078
  printc(" {d}", .{a[i]}, a, b, &i, 1, color);
1053
1079
  },
1054
1080
  .Fail => {
1055
- const id = ID.from(@intCast(a[i]));
1081
+ const id: ID = .from(@intCast(a[i]));
1056
1082
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1057
1083
  printc(" {s}", .{@tagName(@as(Fail, @enumFromInt(a[i])))}, a, b, &i, 1, color);
1058
1084
  },
1059
1085
  .HitCount, .SetBoost => {
1060
- const id = ID.from(@intCast(a[i]));
1086
+ const id: ID = .from(@intCast(a[i]));
1061
1087
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1062
1088
  printc(" {d}", .{a[i]}, a, b, &i, 1, color);
1063
1089
  },
1064
1090
  .Prepare, .SingleMove, .SingleTurn => {
1065
- const id = ID.from(@intCast(a[i]));
1091
+ const id: ID = .from(@intCast(a[i]));
1066
1092
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1067
1093
  printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
1068
1094
  },
1069
1095
  .Activate => {
1070
- const id = ID.from(@intCast(a[i]));
1096
+ const id: ID = .from(@intCast(a[i]));
1071
1097
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1072
1098
  const reason: Activate = @enumFromInt(a[i]);
1073
1099
  printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
@@ -1078,12 +1104,13 @@ pub fn format(
1078
1104
  }
1079
1105
  },
1080
1106
  .Start => {
1081
- const id = ID.from(@intCast(a[i]));
1107
+ const id: ID = .from(@intCast(a[i]));
1082
1108
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1083
1109
  const reason = a[i];
1084
1110
  printc(" {s}", .{@tagName(@as(Start, @enumFromInt(reason)))}, a, b, &i, 1, color);
1085
1111
  if (@as(Start, @enumFromInt(reason)) == .TypeChange) {
1086
- const types = @as(gen.Types, @bitCast(a[i]));
1112
+ // FIXME
1113
+ const types = @as(gen1.Types, @bitCast(a[i]));
1087
1114
  const args = .{
1088
1115
  formatter(gen, .Type, @intFromEnum(types.type1)),
1089
1116
  formatter(gen, .Type, @intFromEnum(types.type2)),
@@ -1094,27 +1121,27 @@ pub fn format(
1094
1121
  }
1095
1122
  },
1096
1123
  .End => {
1097
- const id = ID.from(@intCast(a[i]));
1124
+ const id: ID = .from(@intCast(a[i]));
1098
1125
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1099
1126
  printc(" {s}", .{@tagName(@as(End, @enumFromInt(a[i])))}, a, b, &i, 1, color);
1100
1127
  },
1101
1128
  .Immune => {
1102
- const id = ID.from(@intCast(a[i]));
1129
+ const id: ID = .from(@intCast(a[i]));
1103
1130
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1104
1131
  printc(" {s}", .{@tagName(@as(Immune, @enumFromInt(a[i])))}, a, b, &i, 1, color);
1105
1132
  },
1106
1133
  .Transform, .CopyBoost => {
1107
- const source = ID.from(@intCast(a[i]));
1134
+ const source: ID = .from(@intCast(a[i]));
1108
1135
  printc(" {s}({d})", .{ @tagName(source.player), source.id }, a, b, &i, 1, color);
1109
- const target = ID.from(@intCast(a[i]));
1136
+ const target: ID = .from(@intCast(a[i]));
1110
1137
  printc(" {s}({d})", .{ @tagName(target.player), target.id }, a, b, &i, 1, color);
1111
1138
  },
1112
1139
  .Item, .EndItem => {
1113
- var id = ID.from(@intCast(a[i]));
1140
+ var id: ID = .from(@intCast(a[i]));
1114
1141
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1115
1142
  printc(" {s}", .{formatter(gen, .Item, a[i])}, a, b, &i, 1, color);
1116
1143
  if (arg == .Item) {
1117
- id = ID.from(@intCast(a[i]));
1144
+ id = .from(@intCast(a[i]));
1118
1145
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1119
1146
  } else {
1120
1147
  const reason: EndItem = @enumFromInt(a[i]);
@@ -1122,16 +1149,16 @@ pub fn format(
1122
1149
  }
1123
1150
  },
1124
1151
  .SetHP => {
1125
- const id = ID.from(@intCast(a[i]));
1152
+ const id: ID = .from(@intCast(a[i]));
1126
1153
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1127
1154
  switch (endian) {
1128
- .Big => {
1155
+ .big => {
1129
1156
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1130
1157
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1131
1158
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1132
1159
  printc("/{d}", .{hp}, a, b, &i, 2, color);
1133
1160
  },
1134
- .Little => {
1161
+ .little => {
1135
1162
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
1136
1163
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1137
1164
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -1142,18 +1169,18 @@ pub fn format(
1142
1169
  printc(" {s}", .{@tagName(@as(SetHP, @enumFromInt(a[i])))}, a, b, &i, 1, color);
1143
1170
  },
1144
1171
  .SideStart => {
1145
- const id = ID.from(@intCast(a[i]));
1172
+ const id: ID = .from(@intCast(a[i]));
1146
1173
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1147
1174
  printc(" {s}", .{@tagName(@as(Side, @enumFromInt(a[i])))}, a, b, &i, 1, color);
1148
1175
  },
1149
1176
  .SideEnd => {
1150
- var id = ID.from(@intCast(a[i]));
1177
+ var id: ID = .from(@intCast(a[i]));
1151
1178
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1152
1179
  const reason: Side = @enumFromInt(a[i]);
1153
1180
  printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
1154
1181
  if (reason == .Spikes) {
1155
1182
  printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
1156
- id = ID.from(@intCast(a[i]));
1183
+ id = .from(@intCast(a[i]));
1157
1184
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1158
1185
  }
1159
1186
  },
@@ -1199,15 +1226,7 @@ pub fn expectLog(
1199
1226
  ) !void {
1200
1227
  if (!enabled) return;
1201
1228
 
1202
- const color = color: {
1203
- if (std.process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) {
1204
- break :color true;
1205
- } else if (std.process.hasEnvVarConstant("NO_COLOR")) {
1206
- break :color false;
1207
- } else {
1208
- break :color std.io.getStdErr().supportsAnsiEscapeCodes();
1209
- }
1210
- };
1229
+ const color = detect();
1211
1230
 
1212
1231
  expectEqualBytes(expected, actual, offset) catch |err| switch (err) {
1213
1232
  error.TestExpectedEqual => {
@@ -1215,7 +1234,29 @@ pub fn expectLog(
1215
1234
  format(gen, actual, expected, color);
1216
1235
  return err;
1217
1236
  },
1218
- else => return err,
1237
+ };
1238
+ }
1239
+
1240
+ fn detect() bool {
1241
+ const io = std.testing.io;
1242
+ var env = std.testing.environ.createMap(std.testing.allocator) catch unreachable;
1243
+ defer env.deinit();
1244
+
1245
+ const val = env.get("ZIG_DEBUG_COLOR");
1246
+ if (val != null and val.?.len != 0) return true;
1247
+
1248
+ const NO_COLOR = std.zig.EnvVar.NO_COLOR.isSet(&env);
1249
+ const CLICOLOR_FORCE = std.zig.EnvVar.CLICOLOR_FORCE.isSet(&env);
1250
+
1251
+ const stderr = std.Io.File.stderr().writer(io, &.{});
1252
+ return switch (std.Io.Terminal.Mode.detect(
1253
+ io,
1254
+ stderr.file,
1255
+ NO_COLOR,
1256
+ CLICOLOR_FORCE,
1257
+ ) catch unreachable) {
1258
+ .escape_codes => true,
1259
+ else => false,
1219
1260
  };
1220
1261
  }
1221
1262
 
@@ -1223,7 +1264,7 @@ fn expectEqualBytes(expected: []const u8, actual: []const u8, offset: usize) !vo
1223
1264
  for (offset..@min(expected.len, actual.len)) |i| {
1224
1265
  if (expected[i] != actual[i]) {
1225
1266
  print(
1226
- "index {} incorrect. expected 0x{X:0>2}, found 0x{X:0>2}\n",
1267
+ "index {d} incorrect. expected 0x{X:0>2}, found 0x{X:0>2}\n",
1227
1268
  .{ i, expected[i], actual[i] },
1228
1269
  );
1229
1270
  return error.TestExpectedEqual;
@@ -1238,8 +1279,6 @@ fn expectEqualBytes(expected: []const u8, actual: []const u8, offset: usize) !vo
1238
1279
  }
1239
1280
  }
1240
1281
 
1241
- const endian = builtin.target.cpu.arch.endian();
1242
-
1243
1282
  fn N(e: anytype) u8 {
1244
1283
  return @intFromEnum(e);
1245
1284
  }
@@ -1247,19 +1286,12 @@ fn N(e: anytype) u8 {
1247
1286
  const p1 = Player.P1;
1248
1287
  const p2 = Player.P2;
1249
1288
 
1250
- const gen1 = struct {
1251
- pub usingnamespace @import("../gen1/data.zig");
1252
- pub const helpers = @import("../gen1/helpers.zig");
1253
- };
1254
-
1255
- const gen2 = struct {
1256
- pub usingnamespace @import("../gen2/data.zig");
1257
- pub const helpers = @import("../gen2/helpers.zig");
1258
- };
1259
-
1260
1289
  var buf: [pkmn.LOGS_SIZE]u8 = undefined;
1261
- var stream: ByteStream = .{ .buffer = &buf };
1262
- var log: FixedLog = .{ .writer = stream.writer() };
1290
+ var writer: Writer = .{ .buffer = &buf };
1291
+ var log: FixedLog = .{ .writer = &writer };
1292
+
1293
+ const gen1 = pkmn.gen1;
1294
+ const gen2 = pkmn.gen2;
1263
1295
 
1264
1296
  const M1 = gen1.Move;
1265
1297
  const S1 = gen1.Species;
@@ -1300,14 +1332,14 @@ test "|move|" {
1300
1332
  &.{ N(ArgType.Move), 0b1100, N(M1.Thunderbolt), 0b0101, N(Move.None) },
1301
1333
  buf[0..5],
1302
1334
  );
1303
- stream.reset();
1335
+ writer.reset();
1304
1336
 
1305
1337
  try log.move(.{ p2.ident(4), M1.Pound, p1.ident(5), M1.Metronome });
1306
1338
  try expectLog1(
1307
1339
  &.{ N(ArgType.Move), 0b1100, N(M1.Pound), 0b0101, N(Move.From), N(M1.Metronome) },
1308
1340
  buf[0..6],
1309
1341
  );
1310
- stream.reset();
1342
+ writer.reset();
1311
1343
 
1312
1344
  try log.move(.{ p2.ident(4), M1.SkullBash, ID{} });
1313
1345
  try log.laststill(.{});
@@ -1322,7 +1354,7 @@ test "|move|" {
1322
1354
  },
1323
1355
  buf[0..6],
1324
1356
  );
1325
- stream.reset();
1357
+ writer.reset();
1326
1358
 
1327
1359
  try log.move(.{ p2.ident(4), M1.Tackle, p1.ident(5) });
1328
1360
  try log.lastmiss(.{});
@@ -1337,7 +1369,7 @@ test "|move|" {
1337
1369
  },
1338
1370
  buf[0..6],
1339
1371
  );
1340
- stream.reset();
1372
+ writer.reset();
1341
1373
  }
1342
1374
 
1343
1375
  test "|switch|" {
@@ -1349,31 +1381,31 @@ test "|switch|" {
1349
1381
  try log.switched(.{ p2.ident(3), &snorlax });
1350
1382
  const par = 0b1000000;
1351
1383
  var expected: []const u8 = switch (endian) {
1352
- .Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
1353
- .Little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 200, 0, 144, 1, par },
1384
+ .big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
1385
+ .little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 200, 0, 144, 1, par },
1354
1386
  };
1355
1387
  try expectLog1(expected, buf[0..9]);
1356
- stream.reset();
1388
+ writer.reset();
1357
1389
 
1358
1390
  snorlax.level = 100;
1359
1391
  snorlax.hp = 0;
1360
1392
  snorlax.status = 0;
1361
1393
  try log.switched(.{ p2.ident(3), &snorlax });
1362
1394
  expected = switch (endian) {
1363
- .Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
1364
- .Little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 144, 1, 0 },
1395
+ .big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
1396
+ .little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 144, 1, 0 },
1365
1397
  };
1366
1398
  try expectLog1(expected, buf[0..9]);
1367
- stream.reset();
1399
+ writer.reset();
1368
1400
 
1369
1401
  snorlax.hp = 400;
1370
1402
  try log.switched(.{ p2.ident(3), &snorlax });
1371
1403
  expected = switch (endian) {
1372
- .Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
1373
- .Little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 144, 1, 144, 1, 0 },
1404
+ .big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
1405
+ .little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 144, 1, 144, 1, 0 },
1374
1406
  };
1375
1407
  try expectLog1(expected, buf[0..9]);
1376
- stream.reset();
1408
+ writer.reset();
1377
1409
 
1378
1410
  var blissey = gen2.helpers.Pokemon.init(.{ .species = .Blissey, .moves = &.{.Splash} });
1379
1411
  blissey.level = 91;
@@ -1388,53 +1420,53 @@ test "|switch|" {
1388
1420
  N(gen2.Gender.Female),
1389
1421
  91,
1390
1422
  } ++ switch (endian) {
1391
- .Big => .{ 0, 200, 1, 144, par },
1392
- .Little => .{ 200, 0, 144, 1, par },
1423
+ .big => .{ 0, 200, 1, 144, par },
1424
+ .little => .{ 200, 0, 144, 1, par },
1393
1425
  });
1394
1426
  try expectLog2(expected, buf[0..10]);
1395
- stream.reset();
1427
+ writer.reset();
1396
1428
  }
1397
1429
 
1398
1430
  test "|cant|" {
1399
1431
  try log.cant(.{ p2.ident(6), .Bound });
1400
1432
  try expectLog1(&.{ N(ArgType.Cant), 0b1110, N(Cant.Bound) }, buf[0..3]);
1401
- stream.reset();
1433
+ writer.reset();
1402
1434
 
1403
1435
  try log.cant(.{ p1.ident(2), .Disable, M1.Earthquake });
1404
1436
  try expectLog1(&.{ N(ArgType.Cant), 2, N(Cant.Disable), N(M1.Earthquake) }, buf[0..4]);
1405
- stream.reset();
1437
+ writer.reset();
1406
1438
  }
1407
1439
 
1408
1440
  test "|faint|" {
1409
1441
  try log.faint(.{ p2.ident(2), false });
1410
1442
  try expectLog1(&.{ N(ArgType.Faint), 0b1010 }, buf[0..2]);
1411
- stream.reset();
1443
+ writer.reset();
1412
1444
 
1413
1445
  try log.faint(.{ p2.ident(2), true });
1414
1446
  try expectLog1(&.{ N(ArgType.Faint), 0b1010, N(ArgType.None) }, buf[0..3]);
1415
- stream.reset();
1447
+ writer.reset();
1416
1448
  }
1417
1449
 
1418
1450
  test "|turn|" {
1419
1451
  try log.turn(.{42});
1420
- var expected = switch (endian) {
1421
- .Big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
1422
- .Little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
1452
+ const expected = switch (endian) {
1453
+ .big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
1454
+ .little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
1423
1455
  };
1424
1456
  try expectLog1(expected, buf[0..4]);
1425
- stream.reset();
1457
+ writer.reset();
1426
1458
  }
1427
1459
 
1428
1460
  test "|win|" {
1429
1461
  try log.win(.{.P2});
1430
1462
  try expectLog1(&.{ N(ArgType.Win), 1, N(ArgType.None) }, buf[0..3]);
1431
- stream.reset();
1463
+ writer.reset();
1432
1464
  }
1433
1465
 
1434
1466
  test "|tie|" {
1435
1467
  try log.tie(.{});
1436
1468
  try expectLog1(&.{ N(ArgType.Tie), N(ArgType.None) }, buf[0..2]);
1437
- stream.reset();
1469
+ writer.reset();
1438
1470
  }
1439
1471
 
1440
1472
  test "|-damage|" {
@@ -1443,31 +1475,31 @@ test "|-damage|" {
1443
1475
  chansey.status = gen1.Status.slp(1);
1444
1476
  try log.damage(.{ p2.ident(2), &chansey, .None });
1445
1477
  var expected: []const u8 = switch (endian) {
1446
- .Big => &.{ N(ArgType.Damage), 0b1010, 2, 100, 2, 191, 1, N(Damage.None) },
1447
- .Little => &.{ N(ArgType.Damage), 0b1010, 100, 2, 191, 2, 1, N(Damage.None) },
1478
+ .big => &.{ N(ArgType.Damage), 0b1010, 2, 100, 2, 191, 1, N(Damage.None) },
1479
+ .little => &.{ N(ArgType.Damage), 0b1010, 100, 2, 191, 2, 1, N(Damage.None) },
1448
1480
  };
1449
1481
  try expectLog1(expected, buf[0..8]);
1450
- stream.reset();
1482
+ writer.reset();
1451
1483
 
1452
1484
  chansey.hp = 100;
1453
1485
  chansey.stats.hp = 256;
1454
1486
  chansey.status = 0;
1455
1487
  try log.damage(.{ p2.ident(2), &chansey, .Confusion });
1456
1488
  expected = switch (endian) {
1457
- .Big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0, N(Damage.Confusion) },
1458
- .Little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0, N(Damage.Confusion) },
1489
+ .big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0, N(Damage.Confusion) },
1490
+ .little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0, N(Damage.Confusion) },
1459
1491
  };
1460
1492
  try expectLog1(expected, buf[0..8]);
1461
- stream.reset();
1493
+ writer.reset();
1462
1494
 
1463
1495
  chansey.status = gen1.Status.init(.PSN);
1464
1496
  try log.damage(.{ p2.ident(2), &chansey, .RecoilOf, p1.ident(1) });
1465
1497
  expected = switch (endian) {
1466
- .Big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0b1000, N(Damage.RecoilOf), 1 },
1467
- .Little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0b1000, N(Damage.RecoilOf), 1 },
1498
+ .big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0b1000, N(Damage.RecoilOf), 1 },
1499
+ .little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0b1000, N(Damage.RecoilOf), 1 },
1468
1500
  };
1469
1501
  try expectLog1(expected, buf[0..9]);
1470
- stream.reset();
1502
+ writer.reset();
1471
1503
  }
1472
1504
 
1473
1505
  test "|-heal|" {
@@ -1476,53 +1508,53 @@ test "|-heal|" {
1476
1508
  chansey.status = gen1.Status.slp(1);
1477
1509
  try log.heal(.{ p2.ident(2), &chansey, .None });
1478
1510
  var expected: []const u8 = switch (endian) {
1479
- .Big => &.{ N(ArgType.Heal), 0b1010, 2, 100, 2, 191, 1, N(Heal.None) },
1480
- .Little => &.{ N(ArgType.Heal), 0b1010, 100, 2, 191, 2, 1, N(Heal.None) },
1511
+ .big => &.{ N(ArgType.Heal), 0b1010, 2, 100, 2, 191, 1, N(Heal.None) },
1512
+ .little => &.{ N(ArgType.Heal), 0b1010, 100, 2, 191, 2, 1, N(Heal.None) },
1481
1513
  };
1482
1514
  try expectLog1(expected, buf[0..8]);
1483
- stream.reset();
1515
+ writer.reset();
1484
1516
 
1485
1517
  chansey.hp = 100;
1486
1518
  chansey.stats.hp = 256;
1487
1519
  chansey.status = 0;
1488
1520
  try log.heal(.{ p2.ident(2), &chansey, .Silent });
1489
1521
  expected = switch (endian) {
1490
- .Big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Silent) },
1491
- .Little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Silent) },
1522
+ .big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Silent) },
1523
+ .little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Silent) },
1492
1524
  };
1493
1525
  try expectLog1(expected, buf[0..8]);
1494
- stream.reset();
1526
+ writer.reset();
1495
1527
 
1496
1528
  try log.heal(.{ p2.ident(2), &chansey, .Drain, p1.ident(1) });
1497
1529
  expected = switch (endian) {
1498
- .Big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Drain), 1 },
1499
- .Little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Drain), 1 },
1530
+ .big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Drain), 1 },
1531
+ .little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Drain), 1 },
1500
1532
  };
1501
1533
  try expectLog1(expected, buf[0..9]);
1502
- stream.reset();
1534
+ writer.reset();
1503
1535
  }
1504
1536
 
1505
1537
  test "|-status|" {
1506
1538
  try log.status(.{ p2.ident(6), gen1.Status.init(.BRN), .None });
1507
1539
  try expectLog1(&.{ N(ArgType.Status), 0b1110, 0b10000, N(Status.None) }, buf[0..4]);
1508
- stream.reset();
1540
+ writer.reset();
1509
1541
 
1510
1542
  try log.status(.{ p2.ident(2), gen1.Status.init(.PSN), .Silent });
1511
1543
  try expectLog1(&.{ N(ArgType.Status), 0b1010, 0b1000, N(Status.Silent) }, buf[0..4]);
1512
- stream.reset();
1544
+ writer.reset();
1513
1545
 
1514
1546
  try log.status(.{ p1.ident(1), gen1.Status.init(.PAR), .From, M1.BodySlam });
1515
1547
  try expectLog1(
1516
1548
  &.{ N(ArgType.Status), 0b0001, 0b1000000, N(Status.From), N(M1.BodySlam) },
1517
1549
  buf[0..5],
1518
1550
  );
1519
- stream.reset();
1551
+ writer.reset();
1520
1552
  }
1521
1553
 
1522
1554
  test "|-curestatus|" {
1523
1555
  try log.curestatus(.{ p2.ident(6), gen1.Status.slp(7), .Message });
1524
1556
  try expectLog1(&.{ N(ArgType.CureStatus), 0b1110, 0b111, N(CureStatus.Message) }, buf[0..4]);
1525
- stream.reset();
1557
+ writer.reset();
1526
1558
 
1527
1559
  try log.curestatus(.{ p1.ident(2), gen1.Status.TOX, .Silent });
1528
1560
  try expectLog1(&.{
@@ -1531,86 +1563,86 @@ test "|-curestatus|" {
1531
1563
  0b10001000,
1532
1564
  N(CureStatus.Silent),
1533
1565
  }, buf[0..4]);
1534
- stream.reset();
1566
+ writer.reset();
1535
1567
  }
1536
1568
 
1537
1569
  test "|-boost|" {
1538
1570
  try log.boost(.{ p2.ident(6), .Speed, 2 });
1539
1571
  try expectLog1(&.{ N(ArgType.Boost), 0b1110, N(Boost.Speed), 8 }, buf[0..4]);
1540
- stream.reset();
1572
+ writer.reset();
1541
1573
 
1542
1574
  try log.boost(.{ p1.ident(2), .Rage, 1 });
1543
1575
  try expectLog1(&.{ N(ArgType.Boost), 0b0010, N(Boost.Rage), 7 }, buf[0..4]);
1544
- stream.reset();
1576
+ writer.reset();
1545
1577
 
1546
1578
  try log.boost(.{ p2.ident(3), .Defense, -2 });
1547
1579
  try expectLog1(&.{ N(ArgType.Boost), 0b1011, N(Boost.Defense), 4 }, buf[0..4]);
1548
- stream.reset();
1580
+ writer.reset();
1549
1581
  }
1550
1582
 
1551
1583
  test "|-clearallboost|" {
1552
1584
  try log.clearallboost(.{});
1553
1585
  try expectLog1(&.{N(ArgType.ClearAllBoost)}, buf[0..1]);
1554
- stream.reset();
1586
+ writer.reset();
1555
1587
  }
1556
1588
 
1557
1589
  test "|-fail|" {
1558
1590
  try log.fail(.{ p2.ident(6), .None });
1559
1591
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.None) }, buf[0..3]);
1560
- stream.reset();
1592
+ writer.reset();
1561
1593
 
1562
1594
  try log.fail(.{ p2.ident(6), .Sleep });
1563
1595
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Sleep) }, buf[0..3]);
1564
- stream.reset();
1596
+ writer.reset();
1565
1597
 
1566
1598
  try log.fail(.{ p2.ident(6), .Substitute });
1567
1599
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Substitute) }, buf[0..3]);
1568
- stream.reset();
1600
+ writer.reset();
1569
1601
 
1570
1602
  try log.fail(.{ p2.ident(6), .Weak });
1571
1603
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Weak) }, buf[0..3]);
1572
- stream.reset();
1604
+ writer.reset();
1573
1605
  }
1574
1606
 
1575
1607
  test "|-miss|" {
1576
1608
  try log.miss(.{p2.ident(4)});
1577
1609
  try expectLog1(&.{ N(ArgType.Miss), 0b1100 }, buf[0..2]);
1578
- stream.reset();
1610
+ writer.reset();
1579
1611
  }
1580
1612
  test "|-hitcount|" {
1581
1613
  try log.hitcount(.{ p2.ident(1), 5 });
1582
1614
  try expectLog1(&.{ N(ArgType.HitCount), 0b1001, 5 }, buf[0..3]);
1583
- stream.reset();
1615
+ writer.reset();
1584
1616
  }
1585
1617
 
1586
1618
  test "|-prepare|" {
1587
1619
  try log.prepare(.{ p2.ident(2), M1.Dig });
1588
1620
  try expectLog1(&.{ N(ArgType.Prepare), 0b1010, N(M1.Dig) }, buf[0..3]);
1589
- stream.reset();
1621
+ writer.reset();
1590
1622
  }
1591
1623
 
1592
1624
  test "|-mustrecharge|" {
1593
1625
  try log.mustrecharge(.{p1.ident(6)});
1594
1626
  try expectLog1(&.{ N(ArgType.MustRecharge), 0b0110 }, buf[0..2]);
1595
- stream.reset();
1627
+ writer.reset();
1596
1628
  }
1597
1629
 
1598
1630
  test "|-activate|" {
1599
1631
  try log.activate(.{ p1.ident(2), .Struggle });
1600
1632
  try expectLog1(&.{ N(ArgType.Activate), 0b0010, N(Activate.Struggle) }, buf[0..3]);
1601
- stream.reset();
1633
+ writer.reset();
1602
1634
 
1603
1635
  try log.activate(.{ p2.ident(4), .Mist });
1604
1636
  try expectLog1(&.{ N(ArgType.Activate), 0b1100, N(Activate.Mist) }, buf[0..3]);
1605
- stream.reset();
1637
+ writer.reset();
1606
1638
 
1607
1639
  try log.activate(.{ p2.ident(6), .Substitute });
1608
1640
  try expectLog1(&.{ N(ArgType.Activate), 0b1110, N(Activate.Substitute) }, buf[0..3]);
1609
- stream.reset();
1641
+ writer.reset();
1610
1642
 
1611
1643
  try log.activate(.{ p1.ident(2), .Splash });
1612
1644
  try expectLog1(&.{ N(ArgType.Activate), 0b0010, N(Activate.Splash) }, buf[0..3]);
1613
- stream.reset();
1645
+ writer.reset();
1614
1646
 
1615
1647
  try log.activate(.{ p1.ident(4), .SubstituteBlock, M2.Spite });
1616
1648
  try expectLog1(&.{
@@ -1619,27 +1651,27 @@ test "|-activate|" {
1619
1651
  N(Activate.SubstituteBlock),
1620
1652
  N(M2.Spite),
1621
1653
  }, buf[0..4]);
1622
- stream.reset();
1654
+ writer.reset();
1623
1655
 
1624
1656
  try log.activate(.{ p1.ident(3), .Magnitude, 5 });
1625
1657
  try expectLog1(&.{ N(ArgType.Activate), 0b0011, N(Activate.Magnitude), 5 }, buf[0..4]);
1626
- stream.reset();
1658
+ writer.reset();
1627
1659
  }
1628
1660
 
1629
1661
  test "|-fieldactivate|" {
1630
1662
  try log.fieldactivate(.{});
1631
1663
  try expectLog1(&.{N(ArgType.FieldActivate)}, buf[0..1]);
1632
- stream.reset();
1664
+ writer.reset();
1633
1665
  }
1634
1666
 
1635
1667
  test "|-start|" {
1636
1668
  try log.start(.{ p2.ident(6), .Bide });
1637
1669
  try expectLog1(&.{ N(ArgType.Start), 0b1110, N(Start.Bide) }, buf[0..3]);
1638
- stream.reset();
1670
+ writer.reset();
1639
1671
 
1640
1672
  try log.start(.{ p1.ident(2), .ConfusionSilent });
1641
1673
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.ConfusionSilent) }, buf[0..3]);
1642
- stream.reset();
1674
+ writer.reset();
1643
1675
 
1644
1676
  try log.start(.{
1645
1677
  p2.ident(6),
@@ -1651,7 +1683,7 @@ test "|-start|" {
1651
1683
  &.{ N(ArgType.Start), 0b1110, N(Start.TypeChange), 0b1000_1000, 0b1101 },
1652
1684
  buf[0..5],
1653
1685
  );
1654
- stream.reset();
1686
+ writer.reset();
1655
1687
 
1656
1688
  try log.start(.{
1657
1689
  p1.ident(2),
@@ -1663,65 +1695,65 @@ test "|-start|" {
1663
1695
  &.{ N(ArgType.Start), 0b0010, N(Start.TypeChange), 0b0011_0110, 0b1100 },
1664
1696
  buf[0..5],
1665
1697
  );
1666
- stream.reset();
1698
+ writer.reset();
1667
1699
 
1668
1700
  try log.start(.{ p1.ident(2), .Disable, M1.Surf });
1669
1701
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Disable), N(M1.Surf) }, buf[0..4]);
1670
- stream.reset();
1702
+ writer.reset();
1671
1703
 
1672
1704
  try log.start(.{ p1.ident(2), .Mimic, M1.Surf });
1673
1705
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Mimic), N(M1.Surf) }, buf[0..4]);
1674
- stream.reset();
1706
+ writer.reset();
1675
1707
  }
1676
1708
 
1677
1709
  test "|-end|" {
1678
1710
  try log.end(.{ p2.ident(6), .Bide });
1679
1711
  try expectLog1(&.{ N(ArgType.End), 0b1110, N(End.Bide) }, buf[0..3]);
1680
- stream.reset();
1712
+ writer.reset();
1681
1713
 
1682
1714
  try log.end(.{ p1.ident(2), .ConfusionSilent });
1683
1715
  try expectLog1(&.{ N(ArgType.End), 0b0010, N(End.ConfusionSilent) }, buf[0..3]);
1684
- stream.reset();
1716
+ writer.reset();
1685
1717
  }
1686
1718
 
1687
1719
  test "|-ohko|" {
1688
1720
  try log.ohko(.{});
1689
1721
  try expectLog1(&.{N(ArgType.OHKO)}, buf[0..1]);
1690
- stream.reset();
1722
+ writer.reset();
1691
1723
  }
1692
1724
 
1693
1725
  test "|-crit|" {
1694
1726
  try log.crit(.{p2.ident(5)});
1695
1727
  try expectLog1(&.{ N(ArgType.Crit), 0b1101 }, buf[0..2]);
1696
- stream.reset();
1728
+ writer.reset();
1697
1729
  }
1698
1730
 
1699
1731
  test "|-supereffective|" {
1700
1732
  try log.supereffective(.{p1.ident(1)});
1701
1733
  try expectLog1(&.{ N(ArgType.SuperEffective), 0b0001 }, buf[0..2]);
1702
- stream.reset();
1734
+ writer.reset();
1703
1735
  }
1704
1736
 
1705
1737
  test "|-resisted|" {
1706
1738
  try log.resisted(.{p2.ident(2)});
1707
1739
  try expectLog1(&.{ N(ArgType.Resisted), 0b1010 }, buf[0..2]);
1708
- stream.reset();
1740
+ writer.reset();
1709
1741
  }
1710
1742
 
1711
1743
  test "|-immune|" {
1712
1744
  try log.immune(.{ p1.ident(3), .None });
1713
1745
  try expectLog1(&.{ N(ArgType.Immune), 0b0011, N(Immune.None) }, buf[0..3]);
1714
- stream.reset();
1746
+ writer.reset();
1715
1747
 
1716
1748
  try log.immune(.{ p2.ident(2), .OHKO });
1717
1749
  try expectLog1(&.{ N(ArgType.Immune), 0b1010, N(Immune.OHKO) }, buf[0..3]);
1718
- stream.reset();
1750
+ writer.reset();
1719
1751
  }
1720
1752
 
1721
1753
  test "|-transform|" {
1722
1754
  try log.transform(.{ p2.ident(4), p1.ident(5) });
1723
1755
  try expectLog1(&.{ N(ArgType.Transform), 0b1100, 0b0101 }, buf[0..3]);
1724
- stream.reset();
1756
+ writer.reset();
1725
1757
  }
1726
1758
 
1727
1759
  test "|drag|" {
@@ -1739,73 +1771,73 @@ test "|drag|" {
1739
1771
  N(gen2.Gender.Female),
1740
1772
  91,
1741
1773
  } ++ switch (endian) {
1742
- .Big => .{ 0, 200, 1, 144, par },
1743
- .Little => .{ 200, 0, 144, 1, par },
1774
+ .big => .{ 0, 200, 1, 144, par },
1775
+ .little => .{ 200, 0, 144, 1, par },
1744
1776
  });
1745
1777
  try expectLog2(expected, buf[0..10]);
1746
- stream.reset();
1778
+ writer.reset();
1747
1779
  }
1748
1780
 
1749
1781
  test "|-item|" {
1750
1782
  try log.item(.{ p2.ident(2), I2.GoldBerry, p1.ident(4) });
1751
1783
  try expectLog2(&.{ N(ArgType.Item), 0b1010, N(I2.GoldBerry), 0b0100 }, buf[0..4]);
1752
- stream.reset();
1784
+ writer.reset();
1753
1785
  }
1754
1786
 
1755
1787
  test "|-enditem|" {
1756
1788
  try log.enditem(.{ p1.ident(1), I2.BerserkGene, .None });
1757
1789
  try expectLog2(&.{ N(ArgType.EndItem), 0b0001, N(I2.BerserkGene), N(EndItem.None) }, buf[0..4]);
1758
- stream.reset();
1790
+ writer.reset();
1759
1791
 
1760
1792
  try log.enditem(.{ p2.ident(4), I2.PRZCureBerry, .Eat });
1761
1793
  try expectLog2(&.{ N(ArgType.EndItem), 0b1100, N(I2.PRZCureBerry), N(EndItem.Eat) }, buf[0..4]);
1762
- stream.reset();
1794
+ writer.reset();
1763
1795
  }
1764
1796
 
1765
1797
  test "|-cureteam|" {
1766
1798
  try log.cureteam(.{p2.ident(5)});
1767
1799
  try expectLog2(&.{ N(ArgType.CureTeam), 0b1101 }, buf[0..2]);
1768
- stream.reset();
1800
+ writer.reset();
1769
1801
  }
1770
1802
 
1771
1803
  test "|-sethp|" {
1772
1804
  var blissey = gen2.helpers.Pokemon.init(.{ .species = .Blissey, .moves = &.{.PainSplit} });
1773
1805
  blissey.hp = 612;
1774
1806
  try log.sethp(.{ p2.ident(2), &blissey, .Silent });
1775
- var expected: []const u8 = switch (endian) {
1776
- .Big => &.{ N(ArgType.SetHP), 0b1010, 2, 100, 2, 201, 0, N(SetHP.Silent) },
1777
- .Little => &.{ N(ArgType.SetHP), 0b1010, 100, 2, 201, 2, 0, N(SetHP.Silent) },
1807
+ const expected: []const u8 = switch (endian) {
1808
+ .big => &.{ N(ArgType.SetHP), 0b1010, 2, 100, 2, 201, 0, N(SetHP.Silent) },
1809
+ .little => &.{ N(ArgType.SetHP), 0b1010, 100, 2, 201, 2, 0, N(SetHP.Silent) },
1778
1810
  };
1779
1811
  try expectLog2(expected, buf[0..8]);
1780
- stream.reset();
1812
+ writer.reset();
1781
1813
  }
1782
1814
 
1783
1815
  test "|-setboost|" {
1784
1816
  try log.setboost(.{ p2.ident(6), 6 });
1785
1817
  try expectLog2(&.{ N(ArgType.SetBoost), 0b1110, 12 }, buf[0..3]);
1786
- stream.reset();
1818
+ writer.reset();
1787
1819
 
1788
1820
  try log.setboost(.{ p2.ident(3), 2 });
1789
1821
  try expectLog2(&.{ N(ArgType.SetBoost), 0b1011, 8 }, buf[0..3]);
1790
- stream.reset();
1822
+ writer.reset();
1791
1823
  }
1792
1824
 
1793
1825
  test "|-copyboost|" {
1794
1826
  try log.copyboost(.{ p2.ident(3), p1.ident(6) });
1795
1827
  try expectLog2(&.{ N(ArgType.CopyBoost), 0b1011, 0b0110 }, buf[0..3]);
1796
- stream.reset();
1828
+ writer.reset();
1797
1829
  }
1798
1830
 
1799
1831
  test "|-sidestart|" {
1800
1832
  try log.sidestart(.{ .P2, .Reflect });
1801
1833
  try expectLog2(&.{ N(ArgType.SideStart), 1, N(Side.Reflect) }, buf[0..3]);
1802
- stream.reset();
1834
+ writer.reset();
1803
1835
  }
1804
1836
 
1805
1837
  test "|-sideend|" {
1806
1838
  try log.sideend(.{ .P2, .LightScreen });
1807
1839
  try expectLog2(&.{ N(ArgType.SideEnd), 1, N(Side.LightScreen) }, buf[0..3]);
1808
- stream.reset();
1840
+ writer.reset();
1809
1841
 
1810
1842
  try log.sideend(.{ .P1, .Spikes, p1.ident(3) });
1811
1843
  try expectLog2(&.{
@@ -1814,27 +1846,27 @@ test "|-sideend|" {
1814
1846
  N(Side.Spikes),
1815
1847
  0b0011,
1816
1848
  }, buf[0..4]);
1817
- stream.reset();
1849
+ writer.reset();
1818
1850
  }
1819
1851
 
1820
1852
  test "|-singlemove|" {
1821
1853
  try log.singlemove(.{ p2.ident(2), M2.DestinyBond });
1822
1854
  try expectLog2(&.{ N(ArgType.SingleMove), 0b1010, N(M2.DestinyBond) }, buf[0..3]);
1823
- stream.reset();
1855
+ writer.reset();
1824
1856
  }
1825
1857
 
1826
1858
  test "|-singleturn|" {
1827
1859
  try log.singleturn(.{ p1.ident(3), M2.Protect });
1828
1860
  try expectLog2(&.{ N(ArgType.SingleTurn), 0b0011, N(M2.Protect) }, buf[0..3]);
1829
- stream.reset();
1861
+ writer.reset();
1830
1862
  }
1831
1863
 
1832
1864
  test "|-weather|" {
1833
1865
  try log.weather(.{ W2.Rain, .Upkeep });
1834
1866
  try expectLog2(&.{ N(ArgType.Weather), N(W2.Rain), N(Weather.Upkeep) }, buf[0..3]);
1835
- stream.reset();
1867
+ writer.reset();
1836
1868
 
1837
1869
  try log.weather(.{ W2.None, .None });
1838
1870
  try expectLog2(&.{ N(ArgType.Weather), N(W2.None), N(Weather.None) }, buf[0..3]);
1839
- stream.reset();
1871
+ writer.reset();
1840
1872
  }