@pkmn/engine 0.1.0-dev.b05836cd → 0.1.0-dev.b14f2221

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