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