@pkmn/engine 0.1.0-dev.bcb16a6c → 0.1.0-dev.bce6e8a5

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 (83) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +51 -23
  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 +25 -3
  13. package/build/pkg/addon.js +39 -71
  14. package/build/pkg/addon.js.map +1 -1
  15. package/build/pkg/data/layout.json +17 -4
  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 +30 -21
  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 +53 -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 +344 -101
  39. package/package.json +62 -132
  40. package/src/bin/install-pkmn-engine +31 -20
  41. package/src/bin/pkmn-debug +1 -1
  42. package/src/lib/bindings/c.zig +255 -0
  43. package/src/lib/{binding → bindings}/node.zig +8 -21
  44. package/src/lib/bindings/wasm.zig +59 -0
  45. package/src/lib/common/array.zig +77 -0
  46. package/src/lib/common/data.zig +8 -8
  47. package/src/lib/common/debug.zig +39 -8
  48. package/src/lib/common/js.zig +4 -2
  49. package/src/lib/common/optional.zig +17 -15
  50. package/src/lib/common/options.zig +6 -0
  51. package/src/lib/common/protocol.zig +414 -389
  52. package/src/lib/common/rational.zig +131 -35
  53. package/src/lib/common/rng.zig +16 -9
  54. package/src/lib/common/util.zig +50 -1
  55. package/src/lib/gen1/calc.zig +687 -160
  56. package/src/lib/gen1/chance.zig +430 -303
  57. package/src/lib/gen1/data/moves.zig +26 -14
  58. package/src/lib/gen1/data/species.zig +4 -6
  59. package/src/lib/gen1/data/types.zig +6 -7
  60. package/src/lib/gen1/data.zig +44 -47
  61. package/src/lib/gen1/helpers.zig +91 -562
  62. package/src/lib/gen1/mechanics.zig +642 -565
  63. package/src/lib/gen2/calc.zig +153 -0
  64. package/src/lib/gen2/chance.zig +902 -0
  65. package/src/lib/gen2/data/items.zig +4 -6
  66. package/src/lib/gen2/data/moves.zig +34 -19
  67. package/src/lib/gen2/data/species.zig +2 -4
  68. package/src/lib/gen2/data/types.zig +13 -13
  69. package/src/lib/gen2/data.zig +45 -54
  70. package/src/lib/gen2/generated.zig +801 -0
  71. package/src/lib/gen2/helpers.zig +46 -25
  72. package/src/lib/gen2/mechanics.zig +2483 -452
  73. package/src/lib/node.zig +18 -0
  74. package/src/lib/pkmn.zig +37 -15
  75. package/src/lib/wasm.zig +17 -0
  76. package/src/tools/display/dom.ts +93 -0
  77. package/src/tools/display/ui.css +354 -0
  78. package/build/test/display.js +0 -400
  79. package/build/test/display.js.map +0 -1
  80. package/src/lib/binding/wasm.zig +0 -12
  81. package/src/lib/gen1/README.md +0 -894
  82. package/src/lib/gen2/README.md +0 -330
  83. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -1,16 +1,21 @@
1
- const std = @import("std");
2
1
  const builtin = @import("builtin");
3
-
4
- const data = @import("./data.zig");
5
- const options = @import("./options.zig");
2
+ const data = @import("data.zig");
3
+ const options = @import("options.zig");
4
+ const pkmn = @import("../pkmn.zig");
5
+ const std = @import("std");
6
6
 
7
7
  const assert = std.debug.assert;
8
+ const enabled = options.log;
9
+ const ID = data.ID;
10
+ const Player = data.Player;
8
11
  const print = std.debug.print;
9
12
 
10
- const enabled = options.log;
13
+ const endian = builtin.cpu.arch.endian();
14
+ const Endian = std.builtin.Endian;
15
+ const big = if (@hasField(Endian, "big")) Endian.big else Endian.Big;
16
+ const little = if (@hasField(Endian, "little")) Endian.little else Endian.Little;
11
17
 
12
- const Player = data.Player;
13
- const ID = data.ID;
18
+ const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
14
19
 
15
20
  pub const ArgType = enum(u8) {
16
21
  None,
@@ -69,7 +74,7 @@ pub const ArgType = enum(u8) {
69
74
  EndAbility,
70
75
  ClearNegativeBoost,
71
76
  FormeChange,
72
- NoTarget,
77
+ LastNoTarget, // FIXME
73
78
 
74
79
  // Gen 4
75
80
  SwapBoost,
@@ -102,6 +107,7 @@ pub const ArgType = enum(u8) {
102
107
  // Gen 8
103
108
  CanDynamax,
104
109
  SwapSideConditions,
110
+ UpdatePoke,
105
111
 
106
112
  // Gen 9
107
113
  Terastallize,
@@ -150,6 +156,10 @@ pub const Damage = enum(u8) {
150
156
  Clamp,
151
157
  Whirlpool,
152
158
  Spikes,
159
+
160
+ Nightmare,
161
+ Curse,
162
+ Sandstorm,
153
163
  };
154
164
 
155
165
  pub const Status = enum(u8) {
@@ -192,9 +202,11 @@ pub const Activate = enum(u8) {
192
202
  Haze,
193
203
  Mist,
194
204
  Struggle,
195
- Substitute,
205
+ Substitute, // FIXME SubstituteDamage
196
206
  Splash,
197
207
 
208
+ Rage, // TODO
209
+
198
210
  Attract,
199
211
  LockOn,
200
212
  Bind,
@@ -202,8 +214,14 @@ pub const Activate = enum(u8) {
202
214
  FireSpin,
203
215
  Clamp,
204
216
  Whirlpool,
217
+ SubstituteBlock,
218
+
219
+ DestinyBond,
205
220
 
206
221
  BeatUp, // FIXME of
222
+
223
+ Magnitude,
224
+ Spite,
207
225
  };
208
226
 
209
227
  pub const Start = enum(u8) {
@@ -222,6 +240,7 @@ pub const Start = enum(u8) {
222
240
  Disable,
223
241
  Mimic,
224
242
 
243
+ Attract,
225
244
  Nightmare,
226
245
  Curse,
227
246
  Foresight,
@@ -247,6 +266,7 @@ pub const End = enum(u8) {
247
266
  Encore,
248
267
  FutureSight,
249
268
  LeechSeed,
269
+
250
270
  Bind,
251
271
  Wrap,
252
272
  FireSpin,
@@ -262,6 +282,8 @@ pub const End = enum(u8) {
262
282
  LightScreenSilent,
263
283
  ReflectSilent,
264
284
  BideSilent,
285
+
286
+ LeechSeedFrom,
265
287
  };
266
288
 
267
289
  pub const Immune = enum(u8) {
@@ -305,501 +327,488 @@ pub fn Log(comptime Writer: type) type {
305
327
 
306
328
  pub const Error = Writer.Error;
307
329
 
308
- pub fn move(self: Self, source: ID, m: anytype, target: ID, from: anytype) Error!void {
330
+ // source: ID, move: <Move>, target: ID, from?: <Move>
331
+ pub fn move(self: Self, args: anytype) Error!void {
309
332
  if (!enabled) return;
310
333
 
311
- assert(m != .None);
334
+ assert(args[1] != .None);
312
335
  try self.writer.writeAll(&.{
313
336
  @intFromEnum(ArgType.Move),
314
- @as(u8, @bitCast(source)),
315
- @intFromEnum(m),
316
- @as(u8, @bitCast(target)),
317
- });
318
- const none = &[_]u8{@intFromEnum(Move.None)};
319
- try self.writer.writeAll(switch (@typeInfo(@TypeOf(from))) {
320
- .Null => none,
321
- .Optional => if (from) |f| blk: {
322
- assert(@intFromEnum(f) != 0);
323
- break :blk &[_]u8{ @intFromEnum(Move.From), @intFromEnum(f) };
324
- } else none,
325
- else => blk: {
326
- assert(@intFromEnum(from) != 0);
327
- break :blk &[_]u8{ @intFromEnum(Move.From), @intFromEnum(from) };
328
- },
337
+ @as(u8, @bitCast(args[0])),
338
+ @intFromEnum(args[1]),
339
+ @as(u8, @bitCast(args[2])),
329
340
  });
341
+ try self.writer.writeAll(if (args.len < 4 or @intFromEnum(args[3]) == 0)
342
+ &.{@intFromEnum(Move.None)}
343
+ else
344
+ &.{ @intFromEnum(Move.From), @intFromEnum(args[3]) });
330
345
  }
331
346
 
332
- pub fn switched(self: Self, ident: ID, pokemon: anytype) Error!void {
333
- return switchDrag(self, .Switch, ident, pokemon);
347
+ // ident: ID, pokemon: <Pokemon>
348
+ pub fn switched(self: Self, args: anytype) Error!void {
349
+ return switchDrag(self, .Switch, args);
334
350
  }
335
351
 
336
- fn switchDrag(self: Self, arg: ArgType, ident: ID, pokemon: anytype) Error!void {
352
+ // ident: ID, pokemon: <Pokemon>
353
+ fn switchDrag(self: Self, arg: ArgType, args: anytype) Error!void {
337
354
  if (!enabled) return;
338
355
 
339
- try self.writer.writeAll(&.{ @intFromEnum(arg), @as(u8, @bitCast(ident)) });
340
- if (@hasField(@TypeOf(pokemon.*), "dvs")) {
356
+ try self.writer.writeAll(&.{ @intFromEnum(arg), @as(u8, @bitCast(args[0])) });
357
+ if (@hasField(@TypeOf(args[1].*), "dvs")) {
341
358
  try self.writer.writeAll(&.{
342
- @intFromEnum(pokemon.species),
343
- @intFromEnum(pokemon.dvs.gender),
344
- pokemon.level,
359
+ @intFromEnum(args[1].species),
360
+ @intFromEnum(args[1].dvs.gender),
361
+ args[1].level,
345
362
  });
346
363
  } else {
347
- try self.writer.writeAll(&.{ @intFromEnum(pokemon.species), pokemon.level });
364
+ try self.writer.writeAll(&.{ @intFromEnum(args[1].species), args[1].level });
348
365
  }
349
- try self.writer.writeIntNative(u16, pokemon.hp);
350
- try self.writer.writeIntNative(u16, pokemon.stats.hp);
351
- try self.writer.writeAll(&.{pokemon.status});
366
+ try self.writer.writeInt(u16, args[1].hp, endian);
367
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
368
+ try self.writer.writeAll(&.{args[1].status});
352
369
  }
353
370
 
354
- pub fn cant(self: Self, ident: ID, reason: Cant) Error!void {
371
+ // ident: ID, reason: Cant
372
+ // ident: ID, reason: .Disable, move: <Move>
373
+ pub fn cant(self: Self, args: anytype) Error!void {
355
374
  if (!enabled) return;
356
375
 
357
- assert(reason != .Disable);
376
+ assert(args[1] != .Disable or args.len == 3);
358
377
  try self.writer.writeAll(&.{
359
378
  @intFromEnum(ArgType.Cant),
360
- @as(u8, @bitCast(ident)),
361
- @intFromEnum(reason),
379
+ @as(u8, @bitCast(args[0])),
380
+ @intFromEnum(@as(Cant, args[1])),
362
381
  });
382
+ if (args.len == 3) try self.writer.writeByte(@intFromEnum(args[2]));
363
383
  }
364
384
 
365
- pub fn disabled(self: Self, ident: ID, m: anytype) Error!void {
385
+ // ident: ID, done: bool
386
+ pub fn faint(self: Self, args: anytype) Error!void {
366
387
  if (!enabled) return;
367
388
 
368
- try self.writer.writeAll(&.{
369
- @intFromEnum(ArgType.Cant),
370
- @as(u8, @bitCast(ident)),
371
- @intFromEnum(Cant.Disable),
372
- @intFromEnum(m),
373
- });
389
+ try self.writer.writeAll(&.{ @intFromEnum(ArgType.Faint), @as(u8, @bitCast(args[0])) });
390
+ if (args[1]) try self.writer.writeByte(@intFromEnum(ArgType.None));
374
391
  }
375
392
 
376
- pub fn faint(self: Self, ident: ID, done: bool) Error!void {
377
- if (!enabled) return;
378
-
379
- try self.writer.writeAll(&.{ @intFromEnum(ArgType.Faint), @as(u8, @bitCast(ident)) });
380
- if (done) try self.writer.writeByte(@intFromEnum(ArgType.None));
381
- }
382
-
383
- pub fn turn(self: Self, num: u16) Error!void {
393
+ // num: u16
394
+ pub fn turn(self: Self, args: anytype) Error!void {
384
395
  if (!enabled) return;
385
396
 
386
397
  try self.writer.writeByte(@intFromEnum(ArgType.Turn));
387
- try self.writer.writeIntNative(u16, num);
398
+ try self.writer.writeInt(u16, args[0], endian);
388
399
  try self.writer.writeByte(@intFromEnum(ArgType.None));
389
400
  }
390
401
 
391
- pub fn win(self: Self, player: Player) Error!void {
402
+ // player: Player
403
+ pub fn win(self: Self, args: anytype) Error!void {
392
404
  if (!enabled) return;
393
405
 
394
406
  try self.writer.writeAll(&.{
395
407
  @intFromEnum(ArgType.Win),
396
- @intFromEnum(player),
408
+ @intFromEnum(@as(Player, args[0])),
397
409
  @intFromEnum(ArgType.None),
398
410
  });
399
411
  }
400
412
 
401
- pub fn tie(self: Self) Error!void {
413
+ // -
414
+ pub fn tie(self: Self, _: anytype) Error!void {
402
415
  if (!enabled) return;
403
416
 
404
417
  try self.writer.writeAll(&.{ @intFromEnum(ArgType.Tie), @intFromEnum(ArgType.None) });
405
418
  }
406
419
 
407
- pub fn damage(self: Self, ident: ID, pokemon: anytype, reason: Damage) Error!void {
408
- if (!enabled) return;
409
-
410
- assert(@intFromEnum(reason) <= @intFromEnum(Damage.LeechSeed));
411
- try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @as(u8, @bitCast(ident)) });
412
- try self.writer.writeIntNative(u16, pokemon.hp);
413
- try self.writer.writeIntNative(u16, pokemon.stats.hp);
414
- try self.writer.writeAll(&.{ pokemon.status, @intFromEnum(reason) });
415
- }
416
-
417
- pub fn damageOf(
418
- self: Self,
419
- ident: ID,
420
- pokemon: anytype,
421
- reason: Damage,
422
- source: ID,
423
- ) Error!void {
424
- if (!enabled) return;
425
-
426
- assert(@intFromEnum(reason) == @intFromEnum(Damage.RecoilOf));
427
- try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @as(u8, @bitCast(ident)) });
428
- try self.writer.writeIntNative(u16, pokemon.hp);
429
- try self.writer.writeIntNative(u16, pokemon.stats.hp);
430
- try self.writer.writeAll(&.{
431
- pokemon.status,
432
- @intFromEnum(reason),
433
- @as(u8, @bitCast(source)),
434
- });
435
- }
436
-
437
- pub fn heal(self: Self, ident: ID, pokemon: anytype, reason: Heal) Error!void {
438
- if (!enabled) return;
439
-
440
- assert(reason != .Drain);
441
- try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(ident)) });
442
- try self.writer.writeIntNative(u16, pokemon.hp);
443
- try self.writer.writeIntNative(u16, pokemon.stats.hp);
444
- try self.writer.writeAll(&.{ pokemon.status, @intFromEnum(reason) });
445
- }
446
-
447
- pub fn drain(self: Self, source: ID, pokemon: anytype, target: ID) Error!void {
420
+ // ident: ID, pokemon: <Pokemon>, reason: Damage
421
+ // ident: ID, pokemon: <Pokemon>, reason: .RecoilOf, source: ID
422
+ pub fn damage(self: Self, args: anytype) Error!void {
448
423
  if (!enabled) return;
449
424
 
450
- try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(source)) });
451
- try self.writer.writeIntNative(u16, pokemon.hp);
452
- try self.writer.writeIntNative(u16, pokemon.stats.hp);
425
+ assert(args[2] != .RecoilOf or args.len == 4);
453
426
  try self.writer.writeAll(&.{
454
- pokemon.status,
455
- @intFromEnum(Heal.Drain),
456
- @as(u8, @bitCast(target)),
427
+ @intFromEnum(ArgType.Damage),
428
+ @as(u8, @bitCast(args[0])),
457
429
  });
430
+ try self.writer.writeInt(u16, args[1].hp, endian);
431
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
432
+ try self.writer.writeAll(&.{ args[1].status, @intFromEnum(@as(Damage, args[2])) });
433
+ if (args.len == 4) try self.writer.writeByte(@as(u8, @bitCast(args[3])));
458
434
  }
459
435
 
460
- pub fn status(self: Self, ident: ID, value: u8, reason: Status) Error!void {
436
+ // ident: ID, pokemon: <Pokemon>, reason: Heal
437
+ // ident: ID, pokemon: <Pokemon>, reason: .Drain, target: ID
438
+ pub fn heal(self: Self, args: anytype) Error!void {
461
439
  if (!enabled) return;
462
440
 
463
- assert(reason != .From);
464
- try self.writer.writeAll(&.{
465
- @intFromEnum(ArgType.Status),
466
- @as(u8, @bitCast(ident)),
467
- value,
468
- @intFromEnum(reason),
469
- });
441
+ assert(args[2] != .Drain or args.len == 4);
442
+ try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(args[0])) });
443
+ try self.writer.writeInt(u16, args[1].hp, endian);
444
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
445
+ try self.writer.writeAll(&.{ args[1].status, @intFromEnum(@as(Heal, args[2])) });
446
+ if (args.len == 4) try self.writer.writeByte(@as(u8, @bitCast(args[3])));
470
447
  }
471
448
 
472
- pub fn statusFrom(self: Self, ident: ID, value: u8, m: anytype) Error!void {
449
+ // ident: ID, value: u8, reason: Status
450
+ // ident: ID, value: u8, reason: .From, m: <Move>
451
+ pub fn status(self: Self, args: anytype) Error!void {
473
452
  if (!enabled) return;
474
453
 
454
+ assert(args[2] != .From or args.len == 4);
475
455
  try self.writer.writeAll(&.{
476
456
  @intFromEnum(ArgType.Status),
477
- @as(u8, @bitCast(ident)),
478
- value,
479
- @intFromEnum(Status.From),
480
- @intFromEnum(m),
457
+ @as(u8, @bitCast(args[0])),
458
+ args[1],
459
+ @intFromEnum(@as(Status, args[2])),
481
460
  });
461
+ if (args.len == 4) try self.writer.writeByte(@intFromEnum(args[3]));
482
462
  }
483
463
 
484
- pub fn curestatus(self: Self, ident: ID, value: u8, reason: CureStatus) Error!void {
464
+ // ident: ID, value: u8, reason: CureStatus
465
+ pub fn curestatus(self: Self, args: anytype) Error!void {
485
466
  if (!enabled) return;
486
467
 
487
468
  try self.writer.writeAll(&.{
488
469
  @intFromEnum(ArgType.CureStatus),
489
- @as(u8, @bitCast(ident)),
490
- value,
491
- @intFromEnum(reason),
470
+ @as(u8, @bitCast(args[0])),
471
+ args[1],
472
+ @intFromEnum(@as(CureStatus, args[2])),
492
473
  });
493
474
  }
494
475
 
495
- pub fn boost(self: Self, ident: ID, reason: Boost, num: i8) Error!void {
476
+ // ident: ID, reason: Boost, num: i8
477
+ pub fn boost(self: Self, args: anytype) Error!void {
496
478
  if (!enabled) return;
497
479
 
498
- assert(num != 0 and (reason != .Rage or num > 0));
480
+ assert(args[2] != 0 and (args[1] != .Rage or args[2] > 0));
499
481
  try self.writer.writeAll(&.{
500
482
  @intFromEnum(ArgType.Boost),
501
- @as(u8, @bitCast(ident)),
502
- @intFromEnum(reason),
503
- @as(u8, @intCast(num + 6)),
483
+ @as(u8, @bitCast(args[0])),
484
+ @intFromEnum(@as(Boost, args[1])),
485
+ @as(u8, @intCast(@as(i8, args[2]) + 6)),
504
486
  });
505
487
  }
506
488
 
507
- pub fn clearallboost(self: Self) Error!void {
489
+ // -
490
+ pub fn clearallboost(self: Self, _: anytype) Error!void {
508
491
  if (!enabled) return;
509
492
 
510
493
  try self.writer.writeAll(&.{@intFromEnum(ArgType.ClearAllBoost)});
511
494
  }
512
495
 
513
- pub fn fail(self: Self, ident: ID, reason: Fail) Error!void {
496
+ // ident: ID, reason: Fail
497
+ pub fn fail(self: Self, args: anytype) Error!void {
514
498
  if (!enabled) return;
515
499
 
516
500
  try self.writer.writeAll(&.{
517
501
  @intFromEnum(ArgType.Fail),
518
- @as(u8, @bitCast(ident)),
519
- @intFromEnum(reason),
502
+ @as(u8, @bitCast(args[0])),
503
+ @intFromEnum(@as(Fail, args[1])),
520
504
  });
521
505
  }
522
506
 
523
- pub fn miss(self: Self, source: ID) Error!void {
507
+ // source: ID
508
+ pub fn miss(self: Self, args: anytype) Error!void {
524
509
  if (!enabled) return;
525
510
 
526
- try self.writer.writeAll(&.{ @intFromEnum(ArgType.Miss), @as(u8, @bitCast(source)) });
511
+ try self.writer.writeAll(&.{ @intFromEnum(ArgType.Miss), @as(u8, @bitCast(args[0])) });
527
512
  }
528
513
 
529
- pub fn hitcount(self: Self, ident: ID, num: u8) Error!void {
514
+ // ident: ID, num: u8
515
+ pub fn hitcount(self: Self, args: anytype) Error!void {
530
516
  if (!enabled) return;
531
517
 
532
518
  try self.writer.writeAll(&.{
533
519
  @intFromEnum(ArgType.HitCount),
534
- @as(u8, @bitCast(ident)),
535
- num,
520
+ @as(u8, @bitCast(args[0])),
521
+ args[1],
536
522
  });
537
523
  }
538
524
 
539
- pub fn prepare(self: Self, source: ID, m: anytype) Error!void {
525
+ // source: ID, m: <Move>
526
+ pub fn prepare(self: Self, args: anytype) Error!void {
540
527
  if (!enabled) return;
541
528
 
542
529
  try self.writer.writeAll(&.{
543
530
  @intFromEnum(ArgType.Prepare),
544
- @as(u8, @bitCast(source)),
545
- @intFromEnum(m),
531
+ @as(u8, @bitCast(args[0])),
532
+ @intFromEnum(args[1]),
546
533
  });
547
534
  }
548
535
 
549
- pub fn mustrecharge(self: Self, ident: ID) Error!void {
536
+ // ident: ID
537
+ pub fn mustrecharge(self: Self, args: anytype) Error!void {
550
538
  if (!enabled) return;
551
539
 
552
540
  try self.writer.writeAll(&.{
553
541
  @intFromEnum(ArgType.MustRecharge),
554
- @as(u8, @bitCast(ident)),
542
+ @as(u8, @bitCast(args[0])),
555
543
  });
556
544
  }
557
545
 
558
- pub fn activate(self: Self, ident: ID, reason: Activate) Error!void {
546
+ // ident: ID, reason: Activate
547
+ // ident: ID, reason: .SubstituteBlock, m: <Move>
548
+ // ident: ID, reason: .Magnitude, num: u8
549
+ // ident: ID, reason: .Spite, m: <Move>, num: u8
550
+ pub fn activate(self: Self, args: anytype) Error!void {
559
551
  if (!enabled) return;
560
552
 
553
+ assert(args.len <= 4);
554
+ const reason: Activate = args[1];
561
555
  try self.writer.writeAll(&.{
562
556
  @intFromEnum(ArgType.Activate),
563
- @as(u8, @bitCast(ident)),
557
+ @as(u8, @bitCast(args[0])),
564
558
  @intFromEnum(reason),
565
559
  });
560
+ if (args.len == 3) {
561
+ if (reason == .SubstituteBlock) {
562
+ try self.writer.writeByte(@intFromEnum(args[2]));
563
+ } else {
564
+ assert(reason == .Magnitude);
565
+ try self.writer.writeByte(args[2]);
566
+ }
567
+ } else if (args.len == 4) {
568
+ assert(reason == .Spite);
569
+ try self.writer.writeAll(&.{ @intFromEnum(args[2]), args[3] });
570
+ }
566
571
  }
567
572
 
568
- pub fn fieldactivate(self: Self) Error!void {
573
+ // -
574
+ pub fn fieldactivate(self: Self, _: anytype) Error!void {
569
575
  if (!enabled) return;
570
576
 
571
577
  try self.writer.writeAll(&.{@intFromEnum(ArgType.FieldActivate)});
572
578
  }
573
579
 
574
- pub fn start(self: Self, ident: ID, reason: Start) Error!void {
580
+ // ident: ID, reason: Start
581
+ // ident: ID, reason: .Disable | .Mimic | .Encore, m: <Move>
582
+ // ident: ID, reason: .TypeChange, types: <Types>, target: ID
583
+ pub fn start(self: Self, args: anytype) Error!void {
575
584
  if (!enabled) return;
576
585
 
577
- assert(@intFromEnum(reason) < @intFromEnum(Start.TypeChange));
586
+ assert(args.len <= 4);
587
+ const reason: Start = args[1];
578
588
  try self.writer.writeAll(&.{
579
589
  @intFromEnum(ArgType.Start),
580
- @as(u8, @bitCast(ident)),
590
+ @as(u8, @bitCast(args[0])),
581
591
  @intFromEnum(reason),
582
592
  });
593
+ if (args.len == 3) {
594
+ assert(reason == .Disable or reason == .Mimic or reason == .Encore);
595
+ try self.writer.writeByte(@intFromEnum(args[2]));
596
+ } else if (args.len == 4) {
597
+ assert(reason == .TypeChange);
598
+ // FIXME: u16 types in Generation II
599
+ try self.writer.writeAll(&.{
600
+ @as(u8, @bitCast(args[2])),
601
+ @as(u8, @bitCast(args[3])),
602
+ });
603
+ }
583
604
  }
584
605
 
585
- pub fn typechange(self: Self, source: ID, types: anytype, target: ID) Error!void {
586
- if (!enabled) return;
587
-
588
- try self.writer.writeAll(&.{
589
- @intFromEnum(ArgType.Start),
590
- @as(u8, @bitCast(source)),
591
- @intFromEnum(Start.TypeChange),
592
- @as(u8, @bitCast(types)),
593
- @as(u8, @bitCast(target)),
594
- });
595
- }
596
-
597
- pub fn startEffect(self: Self, ident: ID, reason: Start, m: anytype) Error!void {
598
- if (!enabled) return;
599
-
600
- assert(@intFromEnum(reason) > @intFromEnum(Start.TypeChange));
601
- try self.writer.writeAll(&.{
602
- @intFromEnum(ArgType.Start),
603
- @as(u8, @bitCast(ident)),
604
- @intFromEnum(reason),
605
- @intFromEnum(m),
606
- });
607
- }
608
-
609
- pub fn end(self: Self, ident: ID, reason: End) Error!void {
606
+ // ident: ID, reason: End
607
+ pub fn end(self: Self, args: anytype) Error!void {
610
608
  if (!enabled) return;
611
609
 
612
610
  try self.writer.writeAll(&.{
613
611
  @intFromEnum(ArgType.End),
614
- @as(u8, @bitCast(ident)),
615
- @intFromEnum(reason),
612
+ @as(u8, @bitCast(args[0])),
613
+ @intFromEnum(@as(End, args[1])),
616
614
  });
617
615
  }
618
616
 
619
- pub fn ohko(self: Self) Error!void {
617
+ // -
618
+ pub fn ohko(self: Self, _: anytype) Error!void {
620
619
  if (!enabled) return;
621
620
 
622
621
  try self.writer.writeAll(&.{@intFromEnum(ArgType.OHKO)});
623
622
  }
624
623
 
625
- pub fn crit(self: Self, ident: ID) Error!void {
624
+ // ident: ID
625
+ pub fn crit(self: Self, args: anytype) Error!void {
626
626
  if (!enabled) return;
627
627
 
628
- try self.writer.writeAll(&.{ @intFromEnum(ArgType.Crit), @as(u8, @bitCast(ident)) });
628
+ try self.writer.writeAll(&.{ @intFromEnum(ArgType.Crit), @as(u8, @bitCast(args[0])) });
629
629
  }
630
630
 
631
- pub fn supereffective(self: Self, ident: ID) Error!void {
631
+ // ident: ID
632
+ pub fn supereffective(self: Self, args: anytype) Error!void {
632
633
  if (!enabled) return;
633
634
 
634
635
  try self.writer.writeAll(&.{
635
636
  @intFromEnum(ArgType.SuperEffective),
636
- @as(u8, @bitCast(ident)),
637
+ @as(u8, @bitCast(args[0])),
637
638
  });
638
639
  }
639
640
 
640
- pub fn resisted(self: Self, ident: ID) Error!void {
641
+ // ident: ID
642
+ pub fn resisted(self: Self, args: anytype) Error!void {
641
643
  if (!enabled) return;
642
644
 
643
645
  try self.writer.writeAll(&.{
644
646
  @intFromEnum(ArgType.Resisted),
645
- @as(u8, @bitCast(ident)),
647
+ @as(u8, @bitCast(args[0])),
646
648
  });
647
649
  }
648
650
 
649
- pub fn immune(self: Self, ident: ID, reason: Immune) Error!void {
651
+ // ident: ID, reason: Immune
652
+ pub fn immune(self: Self, args: anytype) Error!void {
650
653
  if (!enabled) return;
651
654
 
652
655
  try self.writer.writeAll(&.{
653
656
  @intFromEnum(ArgType.Immune),
654
- @as(u8, @bitCast(ident)),
655
- @intFromEnum(reason),
657
+ @as(u8, @bitCast(args[0])),
658
+ @intFromEnum(@as(Immune, args[1])),
656
659
  });
657
660
  }
658
661
 
659
- pub fn transform(self: Self, source: ID, target: ID) Error!void {
662
+ // source: ID, target: ID
663
+ pub fn transform(self: Self, args: anytype) Error!void {
660
664
  if (!enabled) return;
661
665
 
662
666
  try self.writer.writeAll(&.{
663
667
  @intFromEnum(ArgType.Transform),
664
- @as(u8, @bitCast(source)),
665
- @as(u8, @bitCast(target)),
668
+ @as(u8, @bitCast(args[0])),
669
+ @as(u8, @bitCast(args[1])),
666
670
  });
667
671
  }
668
672
 
669
- pub fn drag(self: Self, ident: ID, pokemon: anytype) Error!void {
670
- return switchDrag(self, .Drag, ident, pokemon);
673
+ // ident: ID, pokemon: <Pokemon>
674
+ pub fn drag(self: Self, args: anytype) Error!void {
675
+ return switchDrag(self, .Drag, args);
671
676
  }
672
677
 
673
- pub fn item(self: Self, target: ID, i: anytype, source: ID) Error!void {
678
+ // target: ID, item: <Item>, source: ID
679
+ pub fn item(self: Self, args: anytype) Error!void {
674
680
  if (!enabled) return;
675
681
 
676
682
  try self.writer.writeAll(&.{
677
683
  @intFromEnum(ArgType.Item),
678
- @as(u8, @bitCast(target)),
679
- @intFromEnum(i),
680
- @as(u8, @bitCast(source)),
684
+ @as(u8, @bitCast(args[0])),
685
+ @intFromEnum(args[1]),
686
+ @as(u8, @bitCast(args[2])),
681
687
  });
682
688
  }
683
689
 
684
- pub fn enditem(self: Self, ident: ID, i: anytype, reason: EndItem) Error!void {
690
+ // ident: ID, item: <Item>, reason: EndItem
691
+ pub fn enditem(self: Self, args: anytype) Error!void {
685
692
  if (!enabled) return;
686
693
 
687
694
  try self.writer.writeAll(&.{
688
695
  @intFromEnum(ArgType.EndItem),
689
- @as(u8, @bitCast(ident)),
690
- @intFromEnum(i),
691
- @intFromEnum(reason),
696
+ @as(u8, @bitCast(args[0])),
697
+ @intFromEnum(args[1]),
698
+ @intFromEnum(@as(EndItem, args[2])),
692
699
  });
693
700
  }
694
701
 
695
- pub fn cureteam(self: Self, source: ID) Error!void {
702
+ // source: ID
703
+ pub fn cureteam(self: Self, args: anytype) Error!void {
696
704
  if (!enabled) return;
697
705
 
698
706
  try self.writer.writeAll(&.{
699
707
  @intFromEnum(ArgType.CureTeam),
700
- @as(u8, @bitCast(source)),
708
+ @as(u8, @bitCast(args[0])),
701
709
  });
702
710
  }
703
711
 
704
- pub fn sethp(self: Self, ident: ID, pokemon: anytype, reason: SetHP) Error!void {
712
+ // ident: ID, pokemon: <Pokemon>, reason: SetHP
713
+ pub fn sethp(self: Self, args: anytype) Error!void {
705
714
  if (!enabled) return;
706
715
 
707
- try self.writer.writeAll(&.{ @intFromEnum(ArgType.SetHP), @as(u8, @bitCast(ident)) });
708
- try self.writer.writeIntNative(u16, pokemon.hp);
709
- try self.writer.writeIntNative(u16, pokemon.stats.hp);
710
- try self.writer.writeAll(&.{pokemon.status});
711
- try self.writer.writeByte(@intFromEnum(reason));
716
+ try self.writer.writeAll(&.{ @intFromEnum(ArgType.SetHP), @as(u8, @bitCast(args[0])) });
717
+ try self.writer.writeInt(u16, args[1].hp, endian);
718
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
719
+ try self.writer.writeAll(&.{args[1].status});
720
+ try self.writer.writeByte(@intFromEnum(@as(SetHP, args[2])));
712
721
  }
713
722
 
714
- pub fn setboost(self: Self, ident: ID, num: i8) Error!void {
723
+ // ident: ID, num: i8
724
+ pub fn setboost(self: Self, args: anytype) Error!void {
715
725
  if (!enabled) return;
716
726
 
717
727
  try self.writer.writeAll(&.{
718
728
  @intFromEnum(ArgType.SetBoost),
719
- @as(u8, @bitCast(ident)),
720
- @as(u8, @intCast(num + 6)),
729
+ @as(u8, @bitCast(args[0])),
730
+ @as(u8, @intCast(args[1] + 6)),
721
731
  });
722
732
  }
723
733
 
724
- pub fn copyboost(self: Self, source: ID, target: ID) Error!void {
734
+ // source: ID, target: ID
735
+ pub fn copyboost(self: Self, args: anytype) Error!void {
725
736
  if (!enabled) return;
726
737
 
727
738
  try self.writer.writeAll(&.{
728
739
  @intFromEnum(ArgType.CopyBoost),
729
- @as(u8, @bitCast(source)),
730
- @as(u8, @bitCast(target)),
740
+ @as(u8, @bitCast(args[0])),
741
+ @as(u8, @bitCast(args[1])),
731
742
  });
732
743
  }
733
744
 
734
- pub fn sidestart(self: Self, player: Player, reason: Side) Error!void {
745
+ // player: Player, reason: Side
746
+ pub fn sidestart(self: Self, args: anytype) Error!void {
735
747
  if (!enabled) return;
736
748
 
737
749
  try self.writer.writeAll(&.{
738
750
  @intFromEnum(ArgType.SideStart),
739
- @intFromEnum(player),
740
- @intFromEnum(reason),
741
- });
742
- }
743
-
744
- pub fn sideend(self: Self, player: Player, reason: Side) Error!void {
745
- if (!enabled) return;
746
-
747
- assert(@intFromEnum(reason) != @intFromEnum(Side.Spikes));
748
- try self.writer.writeAll(&.{
749
- @intFromEnum(ArgType.SideEnd),
750
- @intFromEnum(player),
751
- @intFromEnum(reason),
751
+ @intFromEnum(@as(Player, args[0])),
752
+ @intFromEnum(@as(Side, args[1])),
752
753
  });
753
754
  }
754
755
 
755
- pub fn spikesend(self: Self, player: Player, m: anytype, source: ID) Error!void {
756
+ // player: Player, reason: Side
757
+ // player: Player, reason: .Spikes, source: ID
758
+ pub fn sideend(self: Self, args: anytype) Error!void {
756
759
  if (!enabled) return;
757
760
 
761
+ assert(args[1] != .Spikes or args.len == 3);
758
762
  try self.writer.writeAll(&.{
759
763
  @intFromEnum(ArgType.SideEnd),
760
- @intFromEnum(player),
761
- @intFromEnum(Side.Spikes),
762
- @intFromEnum(m),
763
- @as(u8, @bitCast(source)),
764
+ @intFromEnum(@as(Player, args[0])),
765
+ @intFromEnum(@as(Side, args[1])),
764
766
  });
767
+ if (args.len == 3) try self.writer.writeByte(@as(u8, @bitCast(args[2])));
765
768
  }
766
769
 
767
- pub fn singlemove(self: Self, ident: ID, m: anytype) Error!void {
768
- return single(self, .SingleMove, ident, m);
770
+ // ident: ID, move: <Move>
771
+ pub fn singlemove(self: Self, args: anytype) Error!void {
772
+ return single(self, .SingleMove, args);
769
773
  }
770
774
 
771
- pub fn singleturn(self: Self, ident: ID, m: anytype) Error!void {
772
- return single(self, .SingleTurn, ident, m);
775
+ // ident: ID, move: <Move>
776
+ pub fn singleturn(self: Self, args: anytype) Error!void {
777
+ return single(self, .SingleTurn, args);
773
778
  }
774
779
 
775
- fn single(self: Self, arg: ArgType, ident: ID, m: anytype) Error!void {
780
+ // ident: ID, move: <Move>
781
+ fn single(self: Self, arg: ArgType, args: anytype) Error!void {
776
782
  if (!enabled) return;
777
783
 
778
784
  try self.writer.writeAll(&.{
779
785
  @intFromEnum(arg),
780
- @as(u8, @bitCast(ident)),
781
- @intFromEnum(m),
786
+ @as(u8, @bitCast(args[0])),
787
+ @intFromEnum(args[1]),
782
788
  });
783
789
  }
784
790
 
785
- pub fn weather(self: Self, w: anytype, reason: Weather) Error!void {
791
+ // weather: <Weather>, reason: Weather
792
+ pub fn weather(self: Self, args: anytype) Error!void {
786
793
  if (!enabled) return;
787
794
 
788
- assert(!(w == .None and reason == .Upkeep));
795
+ assert(!(args[0] == .None and args[1] == .Upkeep));
789
796
  try self.writer.writeAll(&.{
790
797
  @intFromEnum(ArgType.Weather),
791
- @intFromEnum(w),
792
- @intFromEnum(reason),
798
+ @intFromEnum(args[0]),
799
+ @intFromEnum(@as(Weather, args[1])),
793
800
  });
794
801
  }
795
802
 
796
- pub fn laststill(self: Self) Error!void {
803
+ // -
804
+ pub fn laststill(self: Self, _: anytype) Error!void {
797
805
  if (!enabled) return;
798
806
 
799
807
  try self.writer.writeAll(&.{@intFromEnum(ArgType.LastStill)});
800
808
  }
801
809
 
802
- pub fn lastmiss(self: Self) Error!void {
810
+ // -
811
+ pub fn lastmiss(self: Self, _: anytype) Error!void {
803
812
  if (!enabled) return;
804
813
 
805
814
  try self.writer.writeAll(&.{@intFromEnum(ArgType.LastMiss)});
@@ -830,10 +839,10 @@ pub const ByteStream = struct {
830
839
  try self.stream.writeByte(byte);
831
840
  }
832
841
 
833
- pub fn writeIntNative(self: Writer, comptime T: type, value: T) Error!void {
842
+ pub fn writeInt(self: Writer, comptime T: type, v: T, end: std.builtin.Endian) Error!void {
834
843
  // TODO: rework this to write directly to the buffer?
835
- var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
836
- std.mem.writeIntNative(T, &bytes, value);
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);
837
846
  return self.writeAll(&bytes);
838
847
  }
839
848
  };
@@ -856,7 +865,7 @@ pub const ByteStream = struct {
856
865
  pub const Kind = enum { Move, Species, Type, Status, Item, Weather };
857
866
 
858
867
  pub fn format(
859
- comptime gen: anytype,
868
+ gen: anytype,
860
869
  a: []const u8,
861
870
  b: ?[]const u8,
862
871
  color: bool,
@@ -942,19 +951,19 @@ pub fn format(
942
951
  if (a[i] == N(gen.Gender.Unknown)) {
943
952
  i += 1;
944
953
  } else {
945
- var gender = if (a[i] == N(gen.Gender.Male)) "M" else "F";
954
+ const gender = if (a[i] == N(gen.Gender.Male)) "M" else "F";
946
955
  printc(", {s}", .{gender}, a, b, &i, 1, color);
947
956
  }
948
957
  }
949
958
  printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
950
959
  switch (endian) {
951
- .Big => {
960
+ big => {
952
961
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
953
962
  printc(" {d}", .{hp}, a, b, &i, 2, color);
954
963
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
955
964
  printc("/{d}", .{hp}, a, b, &i, 2, color);
956
965
  },
957
- .Little => {
966
+ little => {
958
967
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
959
968
  printc(" {d}", .{hp}, a, b, &i, 2, color);
960
969
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -985,8 +994,8 @@ pub fn format(
985
994
  },
986
995
  .Turn => {
987
996
  const turn = switch (endian) {
988
- .Big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
989
- .Little => @as(u16, a[i + 1]) << 8 | @as(u16, a[i]),
997
+ big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
998
+ little => @as(u16, a[i + 1]) << 8 | @as(u16, a[i]),
990
999
  };
991
1000
  printc(" {d}", .{turn}, a, b, &i, 2, color);
992
1001
  },
@@ -997,13 +1006,13 @@ pub fn format(
997
1006
  var id = ID.from(@intCast(a[i]));
998
1007
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
999
1008
  switch (endian) {
1000
- .Big => {
1009
+ big => {
1001
1010
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1002
1011
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1003
1012
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1004
1013
  printc("/{d}", .{hp}, a, b, &i, 2, color);
1005
1014
  },
1006
- .Little => {
1015
+ little => {
1007
1016
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
1008
1017
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1009
1018
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -1068,7 +1077,13 @@ pub fn format(
1068
1077
  .Activate => {
1069
1078
  const id = ID.from(@intCast(a[i]));
1070
1079
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1071
- printc(" {s}", .{@tagName(@as(Activate, @enumFromInt(a[i])))}, a, b, &i, 1, color);
1080
+ const reason: Activate = @enumFromInt(a[i]);
1081
+ printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
1082
+ if (reason == .SubstituteBlock) {
1083
+ printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
1084
+ } else if (reason == .Magnitude) {
1085
+ printc(" {d}", .{a[i]}, a, b, &i, 1, color);
1086
+ }
1072
1087
  },
1073
1088
  .Start => {
1074
1089
  const id = ID.from(@intCast(a[i]));
@@ -1076,6 +1091,7 @@ pub fn format(
1076
1091
  const reason = a[i];
1077
1092
  printc(" {s}", .{@tagName(@as(Start, @enumFromInt(reason)))}, a, b, &i, 1, color);
1078
1093
  if (@as(Start, @enumFromInt(reason)) == .TypeChange) {
1094
+ // FIXME
1079
1095
  const types = @as(gen1.Types, @bitCast(a[i]));
1080
1096
  const args = .{
1081
1097
  formatter(gen, .Type, @intFromEnum(types.type1)),
@@ -1118,13 +1134,13 @@ pub fn format(
1118
1134
  const id = ID.from(@intCast(a[i]));
1119
1135
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1120
1136
  switch (endian) {
1121
- .Big => {
1137
+ big => {
1122
1138
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1123
1139
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1124
1140
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1125
1141
  printc("/{d}", .{hp}, a, b, &i, 2, color);
1126
1142
  },
1127
- .Little => {
1143
+ little => {
1128
1144
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
1129
1145
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1130
1146
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -1192,14 +1208,11 @@ pub fn expectLog(
1192
1208
  ) !void {
1193
1209
  if (!enabled) return;
1194
1210
 
1195
- const color = color: {
1196
- if (std.process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) {
1197
- break :color true;
1198
- } else if (std.process.hasEnvVarConstant("NO_COLOR")) {
1199
- break :color false;
1200
- } else {
1201
- break :color std.io.getStdErr().supportsAnsiEscapeCodes();
1202
- }
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,
1203
1216
  };
1204
1217
 
1205
1218
  expectEqualBytes(expected, actual, offset) catch |err| switch (err) {
@@ -1231,8 +1244,6 @@ fn expectEqualBytes(expected: []const u8, actual: []const u8, offset: usize) !vo
1231
1244
  }
1232
1245
  }
1233
1246
 
1234
- const endian = builtin.target.cpu.arch.endian();
1235
-
1236
1247
  fn N(e: anytype) u8 {
1237
1248
  return @intFromEnum(e);
1238
1249
  }
@@ -1240,20 +1251,13 @@ fn N(e: anytype) u8 {
1240
1251
  const p1 = Player.P1;
1241
1252
  const p2 = Player.P2;
1242
1253
 
1243
- const gen1 = struct {
1244
- pub usingnamespace @import("../gen1/data.zig");
1245
- pub const helpers = @import("../gen1/helpers.zig");
1246
- };
1247
-
1248
- const gen2 = struct {
1249
- pub usingnamespace @import("../gen2/data.zig");
1250
- pub const helpers = @import("../gen2/helpers.zig");
1251
- };
1252
-
1253
- var buf: [gen1.LOGS_SIZE]u8 = undefined;
1254
+ var buf: [pkmn.LOGS_SIZE]u8 = undefined;
1254
1255
  var stream: ByteStream = .{ .buffer = &buf };
1255
1256
  var log: FixedLog = .{ .writer = stream.writer() };
1256
1257
 
1258
+ const gen1 = pkmn.gen1;
1259
+ const gen2 = pkmn.gen2;
1260
+
1257
1261
  const M1 = gen1.Move;
1258
1262
  const S1 = gen1.Species;
1259
1263
 
@@ -1288,23 +1292,22 @@ fn formatter(comptime gen: anytype, kind: Kind, byte: u8) []const u8 {
1288
1292
  }
1289
1293
 
1290
1294
  test "|move|" {
1291
- try log.move(p2.ident(4), M1.Thunderbolt, p1.ident(5), null);
1295
+ try log.move(.{ p2.ident(4), M1.Thunderbolt, p1.ident(5) });
1292
1296
  try expectLog1(
1293
1297
  &.{ N(ArgType.Move), 0b1100, N(M1.Thunderbolt), 0b0101, N(Move.None) },
1294
1298
  buf[0..5],
1295
1299
  );
1296
1300
  stream.reset();
1297
1301
 
1298
- try log.move(p2.ident(4), M1.Wrap, p1.ident(5), M1.Wrap);
1299
- const wrap = N(M1.Wrap);
1302
+ try log.move(.{ p2.ident(4), M1.Pound, p1.ident(5), M1.Metronome });
1300
1303
  try expectLog1(
1301
- &.{ N(ArgType.Move), 0b1100, wrap, 0b0101, N(Move.From), wrap },
1304
+ &.{ N(ArgType.Move), 0b1100, N(M1.Pound), 0b0101, N(Move.From), N(M1.Metronome) },
1302
1305
  buf[0..6],
1303
1306
  );
1304
1307
  stream.reset();
1305
1308
 
1306
- try log.move(p2.ident(4), M1.SkullBash, .{}, null);
1307
- try log.laststill();
1309
+ try log.move(.{ p2.ident(4), M1.SkullBash, ID{} });
1310
+ try log.laststill(.{});
1308
1311
  try expectLog1(
1309
1312
  &.{
1310
1313
  N(ArgType.Move),
@@ -1318,8 +1321,8 @@ test "|move|" {
1318
1321
  );
1319
1322
  stream.reset();
1320
1323
 
1321
- try log.move(p2.ident(4), M1.Tackle, p1.ident(5), null);
1322
- try log.lastmiss();
1324
+ try log.move(.{ p2.ident(4), M1.Tackle, p1.ident(5) });
1325
+ try log.lastmiss(.{});
1323
1326
  try expectLog1(
1324
1327
  &.{
1325
1328
  N(ArgType.Move),
@@ -1340,11 +1343,11 @@ test "|switch|" {
1340
1343
  snorlax.hp = 200;
1341
1344
  snorlax.stats.hp = 400;
1342
1345
  snorlax.status = gen1.Status.init(.PAR);
1343
- try log.switched(p2.ident(3), &snorlax);
1346
+ try log.switched(.{ p2.ident(3), &snorlax });
1344
1347
  const par = 0b1000000;
1345
1348
  var expected: []const u8 = switch (endian) {
1346
- .Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
1347
- .Little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 200, 0, 144, 1, par },
1349
+ big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
1350
+ little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 200, 0, 144, 1, par },
1348
1351
  };
1349
1352
  try expectLog1(expected, buf[0..9]);
1350
1353
  stream.reset();
@@ -1352,19 +1355,19 @@ test "|switch|" {
1352
1355
  snorlax.level = 100;
1353
1356
  snorlax.hp = 0;
1354
1357
  snorlax.status = 0;
1355
- try log.switched(p2.ident(3), &snorlax);
1358
+ try log.switched(.{ p2.ident(3), &snorlax });
1356
1359
  expected = switch (endian) {
1357
- .Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
1358
- .Little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 144, 1, 0 },
1360
+ big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
1361
+ little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 144, 1, 0 },
1359
1362
  };
1360
1363
  try expectLog1(expected, buf[0..9]);
1361
1364
  stream.reset();
1362
1365
 
1363
1366
  snorlax.hp = 400;
1364
- try log.switched(p2.ident(3), &snorlax);
1367
+ try log.switched(.{ p2.ident(3), &snorlax });
1365
1368
  expected = switch (endian) {
1366
- .Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
1367
- .Little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 144, 1, 144, 1, 0 },
1369
+ big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
1370
+ little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 144, 1, 144, 1, 0 },
1368
1371
  };
1369
1372
  try expectLog1(expected, buf[0..9]);
1370
1373
  stream.reset();
@@ -1374,7 +1377,7 @@ test "|switch|" {
1374
1377
  blissey.hp = 200;
1375
1378
  blissey.stats.hp = 400;
1376
1379
  blissey.status = gen2.Status.init(.PAR);
1377
- try log.switched(p2.ident(3), &blissey);
1380
+ try log.switched(.{ p2.ident(3), &blissey });
1378
1381
  expected = &(.{
1379
1382
  N(ArgType.Switch),
1380
1383
  0b1011,
@@ -1382,51 +1385,51 @@ test "|switch|" {
1382
1385
  N(gen2.Gender.Female),
1383
1386
  91,
1384
1387
  } ++ switch (endian) {
1385
- .Big => .{ 0, 200, 1, 144, par },
1386
- .Little => .{ 200, 0, 144, 1, par },
1388
+ big => .{ 0, 200, 1, 144, par },
1389
+ little => .{ 200, 0, 144, 1, par },
1387
1390
  });
1388
1391
  try expectLog2(expected, buf[0..10]);
1389
1392
  stream.reset();
1390
1393
  }
1391
1394
 
1392
1395
  test "|cant|" {
1393
- try log.cant(p2.ident(6), .Bound);
1396
+ try log.cant(.{ p2.ident(6), .Bound });
1394
1397
  try expectLog1(&.{ N(ArgType.Cant), 0b1110, N(Cant.Bound) }, buf[0..3]);
1395
1398
  stream.reset();
1396
1399
 
1397
- try log.disabled(p1.ident(2), M1.Earthquake);
1400
+ try log.cant(.{ p1.ident(2), .Disable, M1.Earthquake });
1398
1401
  try expectLog1(&.{ N(ArgType.Cant), 2, N(Cant.Disable), N(M1.Earthquake) }, buf[0..4]);
1399
1402
  stream.reset();
1400
1403
  }
1401
1404
 
1402
1405
  test "|faint|" {
1403
- try log.faint(p2.ident(2), false);
1406
+ try log.faint(.{ p2.ident(2), false });
1404
1407
  try expectLog1(&.{ N(ArgType.Faint), 0b1010 }, buf[0..2]);
1405
1408
  stream.reset();
1406
1409
 
1407
- try log.faint(p2.ident(2), true);
1410
+ try log.faint(.{ p2.ident(2), true });
1408
1411
  try expectLog1(&.{ N(ArgType.Faint), 0b1010, N(ArgType.None) }, buf[0..3]);
1409
1412
  stream.reset();
1410
1413
  }
1411
1414
 
1412
1415
  test "|turn|" {
1413
- try log.turn(42);
1414
- var expected = switch (endian) {
1415
- .Big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
1416
- .Little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
1416
+ try log.turn(.{42});
1417
+ const expected = switch (endian) {
1418
+ big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
1419
+ little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
1417
1420
  };
1418
1421
  try expectLog1(expected, buf[0..4]);
1419
1422
  stream.reset();
1420
1423
  }
1421
1424
 
1422
1425
  test "|win|" {
1423
- try log.win(.P2);
1426
+ try log.win(.{.P2});
1424
1427
  try expectLog1(&.{ N(ArgType.Win), 1, N(ArgType.None) }, buf[0..3]);
1425
1428
  stream.reset();
1426
1429
  }
1427
1430
 
1428
1431
  test "|tie|" {
1429
- try log.tie();
1432
+ try log.tie(.{});
1430
1433
  try expectLog1(&.{ N(ArgType.Tie), N(ArgType.None) }, buf[0..2]);
1431
1434
  stream.reset();
1432
1435
  }
@@ -1435,10 +1438,10 @@ test "|-damage|" {
1435
1438
  var chansey = gen1.helpers.Pokemon.init(.{ .species = .Chansey, .moves = &.{.Splash} });
1436
1439
  chansey.hp = 612;
1437
1440
  chansey.status = gen1.Status.slp(1);
1438
- try log.damage(p2.ident(2), &chansey, .None);
1441
+ try log.damage(.{ p2.ident(2), &chansey, .None });
1439
1442
  var expected: []const u8 = switch (endian) {
1440
- .Big => &.{ N(ArgType.Damage), 0b1010, 2, 100, 2, 191, 1, N(Damage.None) },
1441
- .Little => &.{ N(ArgType.Damage), 0b1010, 100, 2, 191, 2, 1, N(Damage.None) },
1443
+ big => &.{ N(ArgType.Damage), 0b1010, 2, 100, 2, 191, 1, N(Damage.None) },
1444
+ little => &.{ N(ArgType.Damage), 0b1010, 100, 2, 191, 2, 1, N(Damage.None) },
1442
1445
  };
1443
1446
  try expectLog1(expected, buf[0..8]);
1444
1447
  stream.reset();
@@ -1446,19 +1449,19 @@ test "|-damage|" {
1446
1449
  chansey.hp = 100;
1447
1450
  chansey.stats.hp = 256;
1448
1451
  chansey.status = 0;
1449
- try log.damage(p2.ident(2), &chansey, .Confusion);
1452
+ try log.damage(.{ p2.ident(2), &chansey, .Confusion });
1450
1453
  expected = switch (endian) {
1451
- .Big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0, N(Damage.Confusion) },
1452
- .Little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0, N(Damage.Confusion) },
1454
+ big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0, N(Damage.Confusion) },
1455
+ little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0, N(Damage.Confusion) },
1453
1456
  };
1454
1457
  try expectLog1(expected, buf[0..8]);
1455
1458
  stream.reset();
1456
1459
 
1457
1460
  chansey.status = gen1.Status.init(.PSN);
1458
- try log.damageOf(p2.ident(2), &chansey, .RecoilOf, p1.ident(1));
1461
+ try log.damage(.{ p2.ident(2), &chansey, .RecoilOf, p1.ident(1) });
1459
1462
  expected = switch (endian) {
1460
- .Big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0b1000, N(Damage.RecoilOf), 1 },
1461
- .Little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0b1000, N(Damage.RecoilOf), 1 },
1463
+ big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0b1000, N(Damage.RecoilOf), 1 },
1464
+ little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0b1000, N(Damage.RecoilOf), 1 },
1462
1465
  };
1463
1466
  try expectLog1(expected, buf[0..9]);
1464
1467
  stream.reset();
@@ -1468,10 +1471,10 @@ test "|-heal|" {
1468
1471
  var chansey = gen1.helpers.Pokemon.init(.{ .species = .Chansey, .moves = &.{.Splash} });
1469
1472
  chansey.hp = 612;
1470
1473
  chansey.status = gen1.Status.slp(1);
1471
- try log.heal(p2.ident(2), &chansey, .None);
1474
+ try log.heal(.{ p2.ident(2), &chansey, .None });
1472
1475
  var expected: []const u8 = switch (endian) {
1473
- .Big => &.{ N(ArgType.Heal), 0b1010, 2, 100, 2, 191, 1, N(Heal.None) },
1474
- .Little => &.{ N(ArgType.Heal), 0b1010, 100, 2, 191, 2, 1, N(Heal.None) },
1476
+ big => &.{ N(ArgType.Heal), 0b1010, 2, 100, 2, 191, 1, N(Heal.None) },
1477
+ little => &.{ N(ArgType.Heal), 0b1010, 100, 2, 191, 2, 1, N(Heal.None) },
1475
1478
  };
1476
1479
  try expectLog1(expected, buf[0..8]);
1477
1480
  stream.reset();
@@ -1479,33 +1482,33 @@ test "|-heal|" {
1479
1482
  chansey.hp = 100;
1480
1483
  chansey.stats.hp = 256;
1481
1484
  chansey.status = 0;
1482
- try log.heal(p2.ident(2), &chansey, .Silent);
1485
+ try log.heal(.{ p2.ident(2), &chansey, .Silent });
1483
1486
  expected = switch (endian) {
1484
- .Big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Silent) },
1485
- .Little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Silent) },
1487
+ big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Silent) },
1488
+ little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Silent) },
1486
1489
  };
1487
1490
  try expectLog1(expected, buf[0..8]);
1488
1491
  stream.reset();
1489
1492
 
1490
- try log.drain(p2.ident(2), &chansey, p1.ident(1));
1493
+ try log.heal(.{ p2.ident(2), &chansey, .Drain, p1.ident(1) });
1491
1494
  expected = switch (endian) {
1492
- .Big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Drain), 1 },
1493
- .Little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Drain), 1 },
1495
+ big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Drain), 1 },
1496
+ little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Drain), 1 },
1494
1497
  };
1495
1498
  try expectLog1(expected, buf[0..9]);
1496
1499
  stream.reset();
1497
1500
  }
1498
1501
 
1499
1502
  test "|-status|" {
1500
- try log.status(p2.ident(6), gen1.Status.init(.BRN), .None);
1503
+ try log.status(.{ p2.ident(6), gen1.Status.init(.BRN), .None });
1501
1504
  try expectLog1(&.{ N(ArgType.Status), 0b1110, 0b10000, N(Status.None) }, buf[0..4]);
1502
1505
  stream.reset();
1503
1506
 
1504
- try log.status(p2.ident(2), gen1.Status.init(.PSN), .Silent);
1507
+ try log.status(.{ p2.ident(2), gen1.Status.init(.PSN), .Silent });
1505
1508
  try expectLog1(&.{ N(ArgType.Status), 0b1010, 0b1000, N(Status.Silent) }, buf[0..4]);
1506
1509
  stream.reset();
1507
1510
 
1508
- try log.statusFrom(p1.ident(1), gen1.Status.init(.PAR), M1.BodySlam);
1511
+ try log.status(.{ p1.ident(1), gen1.Status.init(.PAR), .From, M1.BodySlam });
1509
1512
  try expectLog1(
1510
1513
  &.{ N(ArgType.Status), 0b0001, 0b1000000, N(Status.From), N(M1.BodySlam) },
1511
1514
  buf[0..5],
@@ -1514,11 +1517,11 @@ test "|-status|" {
1514
1517
  }
1515
1518
 
1516
1519
  test "|-curestatus|" {
1517
- try log.curestatus(p2.ident(6), gen1.Status.slp(7), .Message);
1520
+ try log.curestatus(.{ p2.ident(6), gen1.Status.slp(7), .Message });
1518
1521
  try expectLog1(&.{ N(ArgType.CureStatus), 0b1110, 0b111, N(CureStatus.Message) }, buf[0..4]);
1519
1522
  stream.reset();
1520
1523
 
1521
- try log.curestatus(p1.ident(2), gen1.Status.TOX, .Silent);
1524
+ try log.curestatus(.{ p1.ident(2), gen1.Status.TOX, .Silent });
1522
1525
  try expectLog1(&.{
1523
1526
  N(ArgType.CureStatus),
1524
1527
  0b0010,
@@ -1529,168 +1532,191 @@ test "|-curestatus|" {
1529
1532
  }
1530
1533
 
1531
1534
  test "|-boost|" {
1532
- try log.boost(p2.ident(6), .Speed, 2);
1535
+ try log.boost(.{ p2.ident(6), .Speed, 2 });
1533
1536
  try expectLog1(&.{ N(ArgType.Boost), 0b1110, N(Boost.Speed), 8 }, buf[0..4]);
1534
1537
  stream.reset();
1535
1538
 
1536
- try log.boost(p1.ident(2), .Rage, 1);
1539
+ try log.boost(.{ p1.ident(2), .Rage, 1 });
1537
1540
  try expectLog1(&.{ N(ArgType.Boost), 0b0010, N(Boost.Rage), 7 }, buf[0..4]);
1538
1541
  stream.reset();
1539
1542
 
1540
- try log.boost(p2.ident(3), .Defense, -2);
1543
+ try log.boost(.{ p2.ident(3), .Defense, -2 });
1541
1544
  try expectLog1(&.{ N(ArgType.Boost), 0b1011, N(Boost.Defense), 4 }, buf[0..4]);
1542
1545
  stream.reset();
1543
1546
  }
1544
1547
 
1545
1548
  test "|-clearallboost|" {
1546
- try log.clearallboost();
1549
+ try log.clearallboost(.{});
1547
1550
  try expectLog1(&.{N(ArgType.ClearAllBoost)}, buf[0..1]);
1548
1551
  stream.reset();
1549
1552
  }
1550
1553
 
1551
1554
  test "|-fail|" {
1552
- try log.fail(p2.ident(6), .None);
1555
+ try log.fail(.{ p2.ident(6), .None });
1553
1556
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.None) }, buf[0..3]);
1554
1557
  stream.reset();
1555
1558
 
1556
- try log.fail(p2.ident(6), .Sleep);
1559
+ try log.fail(.{ p2.ident(6), .Sleep });
1557
1560
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Sleep) }, buf[0..3]);
1558
1561
  stream.reset();
1559
1562
 
1560
- try log.fail(p2.ident(6), .Substitute);
1563
+ try log.fail(.{ p2.ident(6), .Substitute });
1561
1564
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Substitute) }, buf[0..3]);
1562
1565
  stream.reset();
1563
1566
 
1564
- try log.fail(p2.ident(6), .Weak);
1567
+ try log.fail(.{ p2.ident(6), .Weak });
1565
1568
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Weak) }, buf[0..3]);
1566
1569
  stream.reset();
1567
1570
  }
1568
1571
 
1569
1572
  test "|-miss|" {
1570
- try log.miss(p2.ident(4));
1573
+ try log.miss(.{p2.ident(4)});
1571
1574
  try expectLog1(&.{ N(ArgType.Miss), 0b1100 }, buf[0..2]);
1572
1575
  stream.reset();
1573
1576
  }
1574
1577
  test "|-hitcount|" {
1575
- try log.hitcount(p2.ident(1), 5);
1578
+ try log.hitcount(.{ p2.ident(1), 5 });
1576
1579
  try expectLog1(&.{ N(ArgType.HitCount), 0b1001, 5 }, buf[0..3]);
1577
1580
  stream.reset();
1578
1581
  }
1579
1582
 
1580
1583
  test "|-prepare|" {
1581
- try log.prepare(p2.ident(2), M1.Dig);
1584
+ try log.prepare(.{ p2.ident(2), M1.Dig });
1582
1585
  try expectLog1(&.{ N(ArgType.Prepare), 0b1010, N(M1.Dig) }, buf[0..3]);
1583
1586
  stream.reset();
1584
1587
  }
1585
1588
 
1586
1589
  test "|-mustrecharge|" {
1587
- try log.mustrecharge(p1.ident(6));
1590
+ try log.mustrecharge(.{p1.ident(6)});
1588
1591
  try expectLog1(&.{ N(ArgType.MustRecharge), 0b0110 }, buf[0..2]);
1589
1592
  stream.reset();
1590
1593
  }
1591
1594
 
1592
1595
  test "|-activate|" {
1593
- try log.activate(p1.ident(2), .Struggle);
1596
+ try log.activate(.{ p1.ident(2), .Struggle });
1594
1597
  try expectLog1(&.{ N(ArgType.Activate), 0b0010, N(Activate.Struggle) }, buf[0..3]);
1595
1598
  stream.reset();
1596
1599
 
1597
- try log.activate(p2.ident(4), .Mist);
1600
+ try log.activate(.{ p2.ident(4), .Mist });
1598
1601
  try expectLog1(&.{ N(ArgType.Activate), 0b1100, N(Activate.Mist) }, buf[0..3]);
1599
1602
  stream.reset();
1600
1603
 
1601
- try log.activate(p2.ident(6), .Substitute);
1604
+ try log.activate(.{ p2.ident(6), .Substitute });
1602
1605
  try expectLog1(&.{ N(ArgType.Activate), 0b1110, N(Activate.Substitute) }, buf[0..3]);
1603
1606
  stream.reset();
1604
1607
 
1605
- try log.activate(p1.ident(2), .Splash);
1608
+ try log.activate(.{ p1.ident(2), .Splash });
1606
1609
  try expectLog1(&.{ N(ArgType.Activate), 0b0010, N(Activate.Splash) }, buf[0..3]);
1607
1610
  stream.reset();
1611
+
1612
+ try log.activate(.{ p1.ident(4), .SubstituteBlock, M2.Spite });
1613
+ try expectLog1(&.{
1614
+ N(ArgType.Activate),
1615
+ 0b0100,
1616
+ N(Activate.SubstituteBlock),
1617
+ N(M2.Spite),
1618
+ }, buf[0..4]);
1619
+ stream.reset();
1620
+
1621
+ try log.activate(.{ p1.ident(3), .Magnitude, 5 });
1622
+ try expectLog1(&.{ N(ArgType.Activate), 0b0011, N(Activate.Magnitude), 5 }, buf[0..4]);
1623
+ stream.reset();
1608
1624
  }
1609
1625
 
1610
1626
  test "|-fieldactivate|" {
1611
- try log.fieldactivate();
1627
+ try log.fieldactivate(.{});
1612
1628
  try expectLog1(&.{N(ArgType.FieldActivate)}, buf[0..1]);
1613
1629
  stream.reset();
1614
1630
  }
1615
1631
 
1616
1632
  test "|-start|" {
1617
- try log.start(p2.ident(6), .Bide);
1633
+ try log.start(.{ p2.ident(6), .Bide });
1618
1634
  try expectLog1(&.{ N(ArgType.Start), 0b1110, N(Start.Bide) }, buf[0..3]);
1619
1635
  stream.reset();
1620
1636
 
1621
- try log.start(p1.ident(2), .ConfusionSilent);
1637
+ try log.start(.{ p1.ident(2), .ConfusionSilent });
1622
1638
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.ConfusionSilent) }, buf[0..3]);
1623
1639
  stream.reset();
1624
1640
 
1625
- try log.typechange(p2.ident(6), gen1.Types{ .type1 = .Fire, .type2 = .Fire }, p2.ident(5));
1641
+ try log.start(.{
1642
+ p2.ident(6),
1643
+ .TypeChange,
1644
+ gen1.Types{ .type1 = .Fire, .type2 = .Fire },
1645
+ p2.ident(5),
1646
+ });
1626
1647
  try expectLog1(
1627
1648
  &.{ N(ArgType.Start), 0b1110, N(Start.TypeChange), 0b1000_1000, 0b1101 },
1628
1649
  buf[0..5],
1629
1650
  );
1630
1651
  stream.reset();
1631
1652
 
1632
- try log.typechange(p1.ident(2), gen1.Types{ .type1 = .Bug, .type2 = .Poison }, p2.ident(4));
1653
+ try log.start(.{
1654
+ p1.ident(2),
1655
+ .TypeChange,
1656
+ gen1.Types{ .type1 = .Bug, .type2 = .Poison },
1657
+ p2.ident(4),
1658
+ });
1633
1659
  try expectLog1(
1634
1660
  &.{ N(ArgType.Start), 0b0010, N(Start.TypeChange), 0b0011_0110, 0b1100 },
1635
1661
  buf[0..5],
1636
1662
  );
1637
1663
  stream.reset();
1638
1664
 
1639
- try log.startEffect(p1.ident(2), .Disable, M1.Surf);
1665
+ try log.start(.{ p1.ident(2), .Disable, M1.Surf });
1640
1666
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Disable), N(M1.Surf) }, buf[0..4]);
1641
1667
  stream.reset();
1642
1668
 
1643
- try log.startEffect(p1.ident(2), .Mimic, M1.Surf);
1669
+ try log.start(.{ p1.ident(2), .Mimic, M1.Surf });
1644
1670
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Mimic), N(M1.Surf) }, buf[0..4]);
1645
1671
  stream.reset();
1646
1672
  }
1647
1673
 
1648
1674
  test "|-end|" {
1649
- try log.end(p2.ident(6), .Bide);
1675
+ try log.end(.{ p2.ident(6), .Bide });
1650
1676
  try expectLog1(&.{ N(ArgType.End), 0b1110, N(End.Bide) }, buf[0..3]);
1651
1677
  stream.reset();
1652
1678
 
1653
- try log.end(p1.ident(2), .ConfusionSilent);
1679
+ try log.end(.{ p1.ident(2), .ConfusionSilent });
1654
1680
  try expectLog1(&.{ N(ArgType.End), 0b0010, N(End.ConfusionSilent) }, buf[0..3]);
1655
1681
  stream.reset();
1656
1682
  }
1657
1683
 
1658
1684
  test "|-ohko|" {
1659
- try log.ohko();
1685
+ try log.ohko(.{});
1660
1686
  try expectLog1(&.{N(ArgType.OHKO)}, buf[0..1]);
1661
1687
  stream.reset();
1662
1688
  }
1663
1689
 
1664
1690
  test "|-crit|" {
1665
- try log.crit(p2.ident(5));
1691
+ try log.crit(.{p2.ident(5)});
1666
1692
  try expectLog1(&.{ N(ArgType.Crit), 0b1101 }, buf[0..2]);
1667
1693
  stream.reset();
1668
1694
  }
1669
1695
 
1670
1696
  test "|-supereffective|" {
1671
- try log.supereffective(p1.ident(1));
1697
+ try log.supereffective(.{p1.ident(1)});
1672
1698
  try expectLog1(&.{ N(ArgType.SuperEffective), 0b0001 }, buf[0..2]);
1673
1699
  stream.reset();
1674
1700
  }
1675
1701
 
1676
1702
  test "|-resisted|" {
1677
- try log.resisted(p2.ident(2));
1703
+ try log.resisted(.{p2.ident(2)});
1678
1704
  try expectLog1(&.{ N(ArgType.Resisted), 0b1010 }, buf[0..2]);
1679
1705
  stream.reset();
1680
1706
  }
1681
1707
 
1682
1708
  test "|-immune|" {
1683
- try log.immune(p1.ident(3), .None);
1709
+ try log.immune(.{ p1.ident(3), .None });
1684
1710
  try expectLog1(&.{ N(ArgType.Immune), 0b0011, N(Immune.None) }, buf[0..3]);
1685
1711
  stream.reset();
1686
1712
 
1687
- try log.immune(p2.ident(2), .OHKO);
1713
+ try log.immune(.{ p2.ident(2), .OHKO });
1688
1714
  try expectLog1(&.{ N(ArgType.Immune), 0b1010, N(Immune.OHKO) }, buf[0..3]);
1689
1715
  stream.reset();
1690
1716
  }
1691
1717
 
1692
1718
  test "|-transform|" {
1693
- try log.transform(p2.ident(4), p1.ident(5));
1719
+ try log.transform(.{ p2.ident(4), p1.ident(5) });
1694
1720
  try expectLog1(&.{ N(ArgType.Transform), 0b1100, 0b0101 }, buf[0..3]);
1695
1721
  stream.reset();
1696
1722
  }
@@ -1701,7 +1727,7 @@ test "|drag|" {
1701
1727
  blissey.hp = 200;
1702
1728
  blissey.stats.hp = 400;
1703
1729
  blissey.status = gen2.Status.init(.PAR);
1704
- try log.drag(p2.ident(3), &blissey);
1730
+ try log.drag(.{ p2.ident(3), &blissey });
1705
1731
  const par = 0b1000000;
1706
1732
  const expected = &(.{
1707
1733
  N(ArgType.Drag),
@@ -1710,31 +1736,31 @@ test "|drag|" {
1710
1736
  N(gen2.Gender.Female),
1711
1737
  91,
1712
1738
  } ++ switch (endian) {
1713
- .Big => .{ 0, 200, 1, 144, par },
1714
- .Little => .{ 200, 0, 144, 1, par },
1739
+ big => .{ 0, 200, 1, 144, par },
1740
+ little => .{ 200, 0, 144, 1, par },
1715
1741
  });
1716
1742
  try expectLog2(expected, buf[0..10]);
1717
1743
  stream.reset();
1718
1744
  }
1719
1745
 
1720
1746
  test "|-item|" {
1721
- try log.item(p2.ident(2), I2.GoldBerry, p1.ident(4));
1747
+ try log.item(.{ p2.ident(2), I2.GoldBerry, p1.ident(4) });
1722
1748
  try expectLog2(&.{ N(ArgType.Item), 0b1010, N(I2.GoldBerry), 0b0100 }, buf[0..4]);
1723
1749
  stream.reset();
1724
1750
  }
1725
1751
 
1726
1752
  test "|-enditem|" {
1727
- try log.enditem(p1.ident(1), I2.BerserkGene, .None);
1753
+ try log.enditem(.{ p1.ident(1), I2.BerserkGene, .None });
1728
1754
  try expectLog2(&.{ N(ArgType.EndItem), 0b0001, N(I2.BerserkGene), N(EndItem.None) }, buf[0..4]);
1729
1755
  stream.reset();
1730
1756
 
1731
- try log.enditem(p2.ident(4), I2.PRZCureBerry, .Eat);
1757
+ try log.enditem(.{ p2.ident(4), I2.PRZCureBerry, .Eat });
1732
1758
  try expectLog2(&.{ N(ArgType.EndItem), 0b1100, N(I2.PRZCureBerry), N(EndItem.Eat) }, buf[0..4]);
1733
1759
  stream.reset();
1734
1760
  }
1735
1761
 
1736
1762
  test "|-cureteam|" {
1737
- try log.cureteam(p2.ident(5));
1763
+ try log.cureteam(.{p2.ident(5)});
1738
1764
  try expectLog2(&.{ N(ArgType.CureTeam), 0b1101 }, buf[0..2]);
1739
1765
  stream.reset();
1740
1766
  }
@@ -1742,71 +1768,70 @@ test "|-cureteam|" {
1742
1768
  test "|-sethp|" {
1743
1769
  var blissey = gen2.helpers.Pokemon.init(.{ .species = .Blissey, .moves = &.{.PainSplit} });
1744
1770
  blissey.hp = 612;
1745
- try log.sethp(p2.ident(2), &blissey, .Silent);
1746
- var expected: []const u8 = switch (endian) {
1747
- .Big => &.{ N(ArgType.SetHP), 0b1010, 2, 100, 2, 201, 0, N(SetHP.Silent) },
1748
- .Little => &.{ N(ArgType.SetHP), 0b1010, 100, 2, 201, 2, 0, N(SetHP.Silent) },
1771
+ try log.sethp(.{ p2.ident(2), &blissey, .Silent });
1772
+ 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) },
1749
1775
  };
1750
1776
  try expectLog2(expected, buf[0..8]);
1751
1777
  stream.reset();
1752
1778
  }
1753
1779
 
1754
1780
  test "|-setboost|" {
1755
- try log.setboost(p2.ident(6), 6);
1781
+ try log.setboost(.{ p2.ident(6), 6 });
1756
1782
  try expectLog2(&.{ N(ArgType.SetBoost), 0b1110, 12 }, buf[0..3]);
1757
1783
  stream.reset();
1758
1784
 
1759
- try log.setboost(p2.ident(3), 2);
1785
+ try log.setboost(.{ p2.ident(3), 2 });
1760
1786
  try expectLog2(&.{ N(ArgType.SetBoost), 0b1011, 8 }, buf[0..3]);
1761
1787
  stream.reset();
1762
1788
  }
1763
1789
 
1764
1790
  test "|-copyboost|" {
1765
- try log.copyboost(p2.ident(3), p1.ident(6));
1791
+ try log.copyboost(.{ p2.ident(3), p1.ident(6) });
1766
1792
  try expectLog2(&.{ N(ArgType.CopyBoost), 0b1011, 0b0110 }, buf[0..3]);
1767
1793
  stream.reset();
1768
1794
  }
1769
1795
 
1770
1796
  test "|-sidestart|" {
1771
- try log.sidestart(.P2, .Reflect);
1797
+ try log.sidestart(.{ .P2, .Reflect });
1772
1798
  try expectLog2(&.{ N(ArgType.SideStart), 1, N(Side.Reflect) }, buf[0..3]);
1773
1799
  stream.reset();
1774
1800
  }
1775
1801
 
1776
1802
  test "|-sideend|" {
1777
- try log.sideend(.P2, .LightScreen);
1803
+ try log.sideend(.{ .P2, .LightScreen });
1778
1804
  try expectLog2(&.{ N(ArgType.SideEnd), 1, N(Side.LightScreen) }, buf[0..3]);
1779
1805
  stream.reset();
1780
1806
 
1781
- try log.spikesend(.P1, M2.RapidSpin, p1.ident(3));
1807
+ try log.sideend(.{ .P1, .Spikes, p1.ident(3) });
1782
1808
  try expectLog2(&.{
1783
1809
  N(ArgType.SideEnd),
1784
1810
  0,
1785
1811
  N(Side.Spikes),
1786
- N(M2.RapidSpin),
1787
1812
  0b0011,
1788
- }, buf[0..5]);
1813
+ }, buf[0..4]);
1789
1814
  stream.reset();
1790
1815
  }
1791
1816
 
1792
1817
  test "|-singlemove|" {
1793
- try log.singlemove(p2.ident(2), M2.DestinyBond);
1818
+ try log.singlemove(.{ p2.ident(2), M2.DestinyBond });
1794
1819
  try expectLog2(&.{ N(ArgType.SingleMove), 0b1010, N(M2.DestinyBond) }, buf[0..3]);
1795
1820
  stream.reset();
1796
1821
  }
1797
1822
 
1798
1823
  test "|-singleturn|" {
1799
- try log.singleturn(p1.ident(3), M2.Protect);
1824
+ try log.singleturn(.{ p1.ident(3), M2.Protect });
1800
1825
  try expectLog2(&.{ N(ArgType.SingleTurn), 0b0011, N(M2.Protect) }, buf[0..3]);
1801
1826
  stream.reset();
1802
1827
  }
1803
1828
 
1804
1829
  test "|-weather|" {
1805
- try log.weather(W2.Rain, .Upkeep);
1830
+ try log.weather(.{ W2.Rain, .Upkeep });
1806
1831
  try expectLog2(&.{ N(ArgType.Weather), N(W2.Rain), N(Weather.Upkeep) }, buf[0..3]);
1807
1832
  stream.reset();
1808
1833
 
1809
- try log.weather(W2.None, .None);
1834
+ try log.weather(.{ W2.None, .None });
1810
1835
  try expectLog2(&.{ N(ArgType.Weather), N(W2.None), N(Weather.None) }, buf[0..3]);
1811
1836
  stream.reset();
1812
1837
  }