@pkmn/engine 0.1.0-dev.d56bdadd → 0.1.0-dev.d952b7c9

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