@pkmn/engine 0.1.0-dev.30c63015 → 0.1.0-dev.3393edb3

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 +41 -14
  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 -70
  23. package/build/tools/debug.js.map +1 -1
  24. package/build/tools/display/debug.jsx +141 -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 +54 -29
  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 +32 -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 +222 -210
  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 +666 -133
  47. package/src/lib/gen1/chance.zig +375 -266
  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 +89 -538
  51. package/src/lib/gen1/mechanics.zig +461 -372
  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 +1 -3
  56. package/src/lib/gen2/helpers.zig +41 -13
  57. package/src/lib/gen2/mechanics.zig +328 -300
  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,7 +331,7 @@ pub fn Log(comptime Writer: type) type {
320
331
 
321
332
  pub const Error = Writer.Error;
322
333
 
323
- // source: ID, m: anytype, target: ID, from?: anytype
334
+ // source: ID, move: <Move>, target: ID, from?: <Move>
324
335
  pub fn move(self: Self, args: anytype) Error!void {
325
336
  if (!enabled) return;
326
337
 
@@ -337,12 +348,12 @@ pub fn Log(comptime Writer: type) type {
337
348
  &.{ @intFromEnum(Move.From), @intFromEnum(args[3]) });
338
349
  }
339
350
 
340
- // ident: ID, pokemon: anytype
351
+ // ident: ID, pokemon: <Pokemon>
341
352
  pub fn switched(self: Self, args: anytype) Error!void {
342
353
  return switchDrag(self, .Switch, args);
343
354
  }
344
355
 
345
- // ident: ID, pokemon: anytype
356
+ // ident: ID, pokemon: <Pokemon>
346
357
  fn switchDrag(self: Self, arg: ArgType, args: anytype) Error!void {
347
358
  if (!enabled) return;
348
359
 
@@ -356,12 +367,13 @@ pub fn Log(comptime Writer: type) type {
356
367
  } else {
357
368
  try self.writer.writeAll(&.{ @intFromEnum(args[1].species), args[1].level });
358
369
  }
359
- try self.writer.writeIntNative(u16, args[1].hp);
360
- try self.writer.writeIntNative(u16, args[1].stats.hp);
370
+ try self.writer.writeInt(u16, args[1].hp, endian);
371
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
361
372
  try self.writer.writeAll(&.{args[1].status});
362
373
  }
363
374
 
364
- // ident: ID, reason: Cant, m?: anytype
375
+ // ident: ID, reason: Cant
376
+ // ident: ID, reason: .Disable, move: <Move>
365
377
  pub fn cant(self: Self, args: anytype) Error!void {
366
378
  if (!enabled) return;
367
379
 
@@ -369,7 +381,7 @@ pub fn Log(comptime Writer: type) type {
369
381
  try self.writer.writeAll(&.{
370
382
  @intFromEnum(ArgType.Cant),
371
383
  @as(u8, @bitCast(args[0])),
372
- @intFromEnum(args[1]),
384
+ @intFromEnum(@as(Cant, args[1])),
373
385
  });
374
386
  if (args.len == 3) try self.writer.writeByte(@intFromEnum(args[2]));
375
387
  }
@@ -387,7 +399,7 @@ pub fn Log(comptime Writer: type) type {
387
399
  if (!enabled) return;
388
400
 
389
401
  try self.writer.writeByte(@intFromEnum(ArgType.Turn));
390
- try self.writer.writeIntNative(u16, args[0]);
402
+ try self.writer.writeInt(u16, args[0], endian);
391
403
  try self.writer.writeByte(@intFromEnum(ArgType.None));
392
404
  }
393
405
 
@@ -397,7 +409,7 @@ pub fn Log(comptime Writer: type) type {
397
409
 
398
410
  try self.writer.writeAll(&.{
399
411
  @intFromEnum(ArgType.Win),
400
- @intFromEnum(args[0]),
412
+ @intFromEnum(@as(Player, args[0])),
401
413
  @intFromEnum(ArgType.None),
402
414
  });
403
415
  }
@@ -409,34 +421,37 @@ pub fn Log(comptime Writer: type) type {
409
421
  try self.writer.writeAll(&.{ @intFromEnum(ArgType.Tie), @intFromEnum(ArgType.None) });
410
422
  }
411
423
 
412
- // ident: ID, pokemon: anytype, reason: Damage, source?: ID
424
+ // ident: ID, pokemon: <Pokemon>, reason: Damage
425
+ // ident: ID, pokemon: <Pokemon>, reason: .RecoilOf, source: ID
413
426
  pub fn damage(self: Self, args: anytype) Error!void {
414
427
  if (!enabled) return;
415
428
 
416
- assert(@intFromEnum(args[2]) <= @intFromEnum(Damage.LeechSeed) or args.len == 4);
429
+ assert(args[2] != .RecoilOf or args.len == 4);
417
430
  try self.writer.writeAll(&.{
418
431
  @intFromEnum(ArgType.Damage),
419
432
  @as(u8, @bitCast(args[0])),
420
433
  });
421
- try self.writer.writeIntNative(u16, args[1].hp);
422
- try self.writer.writeIntNative(u16, args[1].stats.hp);
423
- try self.writer.writeAll(&.{ args[1].status, @intFromEnum(args[2]) });
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])) });
424
437
  if (args.len == 4) try self.writer.writeByte(@as(u8, @bitCast(args[3])));
425
438
  }
426
439
 
427
- // ident: ID, pokemon: anytype, reason: Heal, target?: ID)
440
+ // ident: ID, pokemon: <Pokemon>, reason: Heal
441
+ // ident: ID, pokemon: <Pokemon>, reason: .Drain, target: ID
428
442
  pub fn heal(self: Self, args: anytype) Error!void {
429
443
  if (!enabled) return;
430
444
 
431
445
  assert(args[2] != .Drain or args.len == 4);
432
446
  try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(args[0])) });
433
- try self.writer.writeIntNative(u16, args[1].hp);
434
- try self.writer.writeIntNative(u16, args[1].stats.hp);
435
- try self.writer.writeAll(&.{ args[1].status, @intFromEnum(args[2]) });
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])) });
436
450
  if (args.len == 4) try self.writer.writeByte(@as(u8, @bitCast(args[3])));
437
451
  }
438
452
 
439
- // ident: ID, value: u8, reason: Status, m?: anytype)
453
+ // ident: ID, value: u8, reason: Status
454
+ // ident: ID, value: u8, reason: .From, m: <Move>
440
455
  pub fn status(self: Self, args: anytype) Error!void {
441
456
  if (!enabled) return;
442
457
 
@@ -445,7 +460,7 @@ pub fn Log(comptime Writer: type) type {
445
460
  @intFromEnum(ArgType.Status),
446
461
  @as(u8, @bitCast(args[0])),
447
462
  args[1],
448
- @intFromEnum(args[2]),
463
+ @intFromEnum(@as(Status, args[2])),
449
464
  });
450
465
  if (args.len == 4) try self.writer.writeByte(@intFromEnum(args[3]));
451
466
  }
@@ -458,7 +473,7 @@ pub fn Log(comptime Writer: type) type {
458
473
  @intFromEnum(ArgType.CureStatus),
459
474
  @as(u8, @bitCast(args[0])),
460
475
  args[1],
461
- @intFromEnum(args[2]),
476
+ @intFromEnum(@as(CureStatus, args[2])),
462
477
  });
463
478
  }
464
479
 
@@ -470,7 +485,7 @@ pub fn Log(comptime Writer: type) type {
470
485
  try self.writer.writeAll(&.{
471
486
  @intFromEnum(ArgType.Boost),
472
487
  @as(u8, @bitCast(args[0])),
473
- @intFromEnum(args[1]),
488
+ @intFromEnum(@as(Boost, args[1])),
474
489
  @as(u8, @intCast(@as(i8, args[2]) + 6)),
475
490
  });
476
491
  }
@@ -489,7 +504,7 @@ pub fn Log(comptime Writer: type) type {
489
504
  try self.writer.writeAll(&.{
490
505
  @intFromEnum(ArgType.Fail),
491
506
  @as(u8, @bitCast(args[0])),
492
- @intFromEnum(args[1]),
507
+ @intFromEnum(@as(Fail, args[1])),
493
508
  });
494
509
  }
495
510
 
@@ -511,7 +526,7 @@ pub fn Log(comptime Writer: type) type {
511
526
  });
512
527
  }
513
528
 
514
- // source: ID, m: anytype
529
+ // source: ID, m: <Move>
515
530
  pub fn prepare(self: Self, args: anytype) Error!void {
516
531
  if (!enabled) return;
517
532
 
@@ -532,38 +547,31 @@ pub fn Log(comptime Writer: type) type {
532
547
  });
533
548
  }
534
549
 
535
- pub fn activate(self: Self, ident: ID, reason: Activate) Error!void {
536
- if (!enabled) return;
537
-
538
- assert(reason != .SubstituteBlock); // TODO
539
- try self.writer.writeAll(&.{
540
- @intFromEnum(ArgType.Activate),
541
- @as(u8, @bitCast(ident)),
542
- @intFromEnum(reason),
543
- });
544
- }
545
-
546
- pub fn activateMove(self: Self, ident: ID, reason: Activate, m: anytype) 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 {
547
555
  if (!enabled) return;
548
556
 
549
- assert(reason == .SubstituteBlock); // TODO
557
+ assert(args.len <= 4);
558
+ const reason: Activate = args[1];
550
559
  try self.writer.writeAll(&.{
551
560
  @intFromEnum(ArgType.Activate),
552
- @as(u8, @bitCast(ident)),
561
+ @as(u8, @bitCast(args[0])),
553
562
  @intFromEnum(reason),
554
- @intFromEnum(m),
555
- });
556
- }
557
-
558
- pub fn magnitude(self: Self, ident: ID, num: u8) Error!void {
559
- if (!enabled) return;
560
-
561
- try self.writer.writeAll(&.{
562
- @intFromEnum(ArgType.Activate),
563
- @as(u8, @bitCast(ident)),
564
- @intFromEnum(Activate.Magnitude),
565
- num,
566
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
+ }
567
575
  }
568
576
 
569
577
  // -
@@ -573,49 +581,40 @@ pub fn Log(comptime Writer: type) type {
573
581
  try self.writer.writeAll(&.{@intFromEnum(ArgType.FieldActivate)});
574
582
  }
575
583
 
576
- pub fn start(self: Self, ident: ID, reason: Start) Error!void {
577
- if (!enabled) return;
578
-
579
- assert(@intFromEnum(reason) < @intFromEnum(Start.TypeChange));
580
- try self.writer.writeAll(&.{
581
- @intFromEnum(ArgType.Start),
582
- @as(u8, @bitCast(ident)),
583
- @intFromEnum(reason),
584
- });
585
- }
586
-
587
- pub fn typechange(self: Self, source: ID, types: anytype, target: ID) Error!void {
588
- if (!enabled) return;
589
-
590
- try self.writer.writeAll(&.{
591
- @intFromEnum(ArgType.Start),
592
- @as(u8, @bitCast(source)),
593
- @intFromEnum(Start.TypeChange),
594
- @as(u8, @bitCast(types)),
595
- @as(u8, @bitCast(target)),
596
- });
597
- }
598
-
599
- pub fn startEffect(self: Self, ident: ID, reason: Start, m: anytype) 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 {
600
588
  if (!enabled) return;
601
589
 
602
- assert(@intFromEnum(reason) > @intFromEnum(Start.TypeChange));
590
+ assert(args.len <= 4);
591
+ const reason: Start = args[1];
603
592
  try self.writer.writeAll(&.{
604
593
  @intFromEnum(ArgType.Start),
605
- @as(u8, @bitCast(ident)),
594
+ @as(u8, @bitCast(args[0])),
606
595
  @intFromEnum(reason),
607
- @intFromEnum(m),
608
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
+ }
609
608
  }
610
609
 
611
- // ident: ID, reason: End)
610
+ // ident: ID, reason: End
612
611
  pub fn end(self: Self, args: anytype) Error!void {
613
612
  if (!enabled) return;
614
613
 
615
614
  try self.writer.writeAll(&.{
616
615
  @intFromEnum(ArgType.End),
617
616
  @as(u8, @bitCast(args[0])),
618
- @intFromEnum(args[1]),
617
+ @intFromEnum(@as(End, args[1])),
619
618
  });
620
619
  }
621
620
 
@@ -660,7 +659,7 @@ pub fn Log(comptime Writer: type) type {
660
659
  try self.writer.writeAll(&.{
661
660
  @intFromEnum(ArgType.Immune),
662
661
  @as(u8, @bitCast(args[0])),
663
- @intFromEnum(args[1]),
662
+ @intFromEnum(@as(Immune, args[1])),
664
663
  });
665
664
  }
666
665
 
@@ -675,12 +674,12 @@ pub fn Log(comptime Writer: type) type {
675
674
  });
676
675
  }
677
676
 
678
- // ident: ID, pokemon: anytype
677
+ // ident: ID, pokemon: <Pokemon>
679
678
  pub fn drag(self: Self, args: anytype) Error!void {
680
679
  return switchDrag(self, .Drag, args);
681
680
  }
682
681
 
683
- // target: ID, i: anytype, source: ID
682
+ // target: ID, item: <Item>, source: ID
684
683
  pub fn item(self: Self, args: anytype) Error!void {
685
684
  if (!enabled) return;
686
685
 
@@ -692,7 +691,7 @@ pub fn Log(comptime Writer: type) type {
692
691
  });
693
692
  }
694
693
 
695
- // ident: ID, i: anytype, reason: EndItem
694
+ // ident: ID, item: <Item>, reason: EndItem
696
695
  pub fn enditem(self: Self, args: anytype) Error!void {
697
696
  if (!enabled) return;
698
697
 
@@ -700,7 +699,7 @@ pub fn Log(comptime Writer: type) type {
700
699
  @intFromEnum(ArgType.EndItem),
701
700
  @as(u8, @bitCast(args[0])),
702
701
  @intFromEnum(args[1]),
703
- @intFromEnum(args[2]),
702
+ @intFromEnum(@as(EndItem, args[2])),
704
703
  });
705
704
  }
706
705
 
@@ -714,15 +713,15 @@ pub fn Log(comptime Writer: type) type {
714
713
  });
715
714
  }
716
715
 
717
- // ident: ID, pokemon: anytype, reason: SetHP
716
+ // ident: ID, pokemon: <Pokemon>, reason: SetHP
718
717
  pub fn sethp(self: Self, args: anytype) Error!void {
719
718
  if (!enabled) return;
720
719
 
721
720
  try self.writer.writeAll(&.{ @intFromEnum(ArgType.SetHP), @as(u8, @bitCast(args[0])) });
722
- try self.writer.writeIntNative(u16, args[1].hp);
723
- try self.writer.writeIntNative(u16, args[1].stats.hp);
721
+ try self.writer.writeInt(u16, args[1].hp, endian);
722
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
724
723
  try self.writer.writeAll(&.{args[1].status});
725
- try self.writer.writeByte(@intFromEnum(args[2]));
724
+ try self.writer.writeByte(@intFromEnum(@as(SetHP, args[2])));
726
725
  }
727
726
 
728
727
  // ident: ID, num: i8
@@ -753,35 +752,36 @@ pub fn Log(comptime Writer: type) type {
753
752
 
754
753
  try self.writer.writeAll(&.{
755
754
  @intFromEnum(ArgType.SideStart),
756
- @intFromEnum(args[0]),
757
- @intFromEnum(args[1]),
755
+ @intFromEnum(@as(Player, args[0])),
756
+ @intFromEnum(@as(Side, args[1])),
758
757
  });
759
758
  }
760
759
 
761
- // player: Player, reason: Side, source?: ID
760
+ // player: Player, reason: Side
761
+ // player: Player, reason: .Spikes, source: ID
762
762
  pub fn sideend(self: Self, args: anytype) Error!void {
763
763
  if (!enabled) return;
764
764
 
765
- assert(@intFromEnum(args[1]) != @intFromEnum(Side.Spikes) or args.len == 3);
765
+ assert(args[1] != .Spikes or args.len == 3);
766
766
  try self.writer.writeAll(&.{
767
767
  @intFromEnum(ArgType.SideEnd),
768
- @intFromEnum(args[0]),
769
- @intFromEnum(args[1]),
768
+ @intFromEnum(@as(Player, args[0])),
769
+ @intFromEnum(@as(Side, args[1])),
770
770
  });
771
771
  if (args.len == 3) try self.writer.writeByte(@as(u8, @bitCast(args[2])));
772
772
  }
773
773
 
774
- // ident: ID, move: anytype
774
+ // ident: ID, move: <Move>
775
775
  pub fn singlemove(self: Self, args: anytype) Error!void {
776
776
  return single(self, .SingleMove, args);
777
777
  }
778
778
 
779
- // ident: ID, m: anytype
779
+ // ident: ID, move: <Move>
780
780
  pub fn singleturn(self: Self, args: anytype) Error!void {
781
781
  return single(self, .SingleTurn, args);
782
782
  }
783
783
 
784
- // ident: ID, move: anytype
784
+ // ident: ID, move: <Move>
785
785
  fn single(self: Self, arg: ArgType, args: anytype) Error!void {
786
786
  if (!enabled) return;
787
787
 
@@ -792,7 +792,7 @@ pub fn Log(comptime Writer: type) type {
792
792
  });
793
793
  }
794
794
 
795
- // w: anytype, reason: Weather
795
+ // weather: <Weather>, reason: Weather
796
796
  pub fn weather(self: Self, args: anytype) Error!void {
797
797
  if (!enabled) return;
798
798
 
@@ -800,7 +800,7 @@ pub fn Log(comptime Writer: type) type {
800
800
  try self.writer.writeAll(&.{
801
801
  @intFromEnum(ArgType.Weather),
802
802
  @intFromEnum(args[0]),
803
- @intFromEnum(args[1]),
803
+ @intFromEnum(@as(Weather, args[1])),
804
804
  });
805
805
  }
806
806
 
@@ -843,10 +843,10 @@ pub const ByteStream = struct {
843
843
  try self.stream.writeByte(byte);
844
844
  }
845
845
 
846
- 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 {
847
847
  // TODO: rework this to write directly to the buffer?
848
- var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
849
- 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);
850
850
  return self.writeAll(&bytes);
851
851
  }
852
852
  };
@@ -869,7 +869,7 @@ pub const ByteStream = struct {
869
869
  pub const Kind = enum { Move, Species, Type, Status, Item, Weather };
870
870
 
871
871
  pub fn format(
872
- comptime gen: anytype,
872
+ gen: anytype,
873
873
  a: []const u8,
874
874
  b: ?[]const u8,
875
875
  color: bool,
@@ -955,19 +955,19 @@ pub fn format(
955
955
  if (a[i] == N(gen.Gender.Unknown)) {
956
956
  i += 1;
957
957
  } else {
958
- 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";
959
959
  printc(", {s}", .{gender}, a, b, &i, 1, color);
960
960
  }
961
961
  }
962
962
  printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
963
963
  switch (endian) {
964
- .Big => {
964
+ big => {
965
965
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
966
966
  printc(" {d}", .{hp}, a, b, &i, 2, color);
967
967
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
968
968
  printc("/{d}", .{hp}, a, b, &i, 2, color);
969
969
  },
970
- .Little => {
970
+ little => {
971
971
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
972
972
  printc(" {d}", .{hp}, a, b, &i, 2, color);
973
973
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -998,8 +998,8 @@ pub fn format(
998
998
  },
999
999
  .Turn => {
1000
1000
  const turn = switch (endian) {
1001
- .Big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
1002
- .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]),
1003
1003
  };
1004
1004
  printc(" {d}", .{turn}, a, b, &i, 2, color);
1005
1005
  },
@@ -1010,13 +1010,13 @@ pub fn format(
1010
1010
  var id = ID.from(@intCast(a[i]));
1011
1011
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1012
1012
  switch (endian) {
1013
- .Big => {
1013
+ big => {
1014
1014
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1015
1015
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1016
1016
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1017
1017
  printc("/{d}", .{hp}, a, b, &i, 2, color);
1018
1018
  },
1019
- .Little => {
1019
+ little => {
1020
1020
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
1021
1021
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1022
1022
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -1081,7 +1081,13 @@ pub fn format(
1081
1081
  .Activate => {
1082
1082
  const id = ID.from(@intCast(a[i]));
1083
1083
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1084
- 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
+ }
1085
1091
  },
1086
1092
  .Start => {
1087
1093
  const id = ID.from(@intCast(a[i]));
@@ -1089,6 +1095,7 @@ pub fn format(
1089
1095
  const reason = a[i];
1090
1096
  printc(" {s}", .{@tagName(@as(Start, @enumFromInt(reason)))}, a, b, &i, 1, color);
1091
1097
  if (@as(Start, @enumFromInt(reason)) == .TypeChange) {
1098
+ // FIXME
1092
1099
  const types = @as(gen1.Types, @bitCast(a[i]));
1093
1100
  const args = .{
1094
1101
  formatter(gen, .Type, @intFromEnum(types.type1)),
@@ -1131,13 +1138,13 @@ pub fn format(
1131
1138
  const id = ID.from(@intCast(a[i]));
1132
1139
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1133
1140
  switch (endian) {
1134
- .Big => {
1141
+ big => {
1135
1142
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1136
1143
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1137
1144
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1138
1145
  printc("/{d}", .{hp}, a, b, &i, 2, color);
1139
1146
  },
1140
- .Little => {
1147
+ little => {
1141
1148
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
1142
1149
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1143
1150
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -1205,14 +1212,11 @@ pub fn expectLog(
1205
1212
  ) !void {
1206
1213
  if (!enabled) return;
1207
1214
 
1208
- const color = color: {
1209
- if (std.process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) {
1210
- break :color true;
1211
- } else if (std.process.hasEnvVarConstant("NO_COLOR")) {
1212
- break :color false;
1213
- } else {
1214
- break :color std.io.getStdErr().supportsAnsiEscapeCodes();
1215
- }
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,
1216
1220
  };
1217
1221
 
1218
1222
  expectEqualBytes(expected, actual, offset) catch |err| switch (err) {
@@ -1244,8 +1248,6 @@ fn expectEqualBytes(expected: []const u8, actual: []const u8, offset: usize) !vo
1244
1248
  }
1245
1249
  }
1246
1250
 
1247
- const endian = builtin.target.cpu.arch.endian();
1248
-
1249
1251
  fn N(e: anytype) u8 {
1250
1252
  return @intFromEnum(e);
1251
1253
  }
@@ -1253,20 +1255,13 @@ fn N(e: anytype) u8 {
1253
1255
  const p1 = Player.P1;
1254
1256
  const p2 = Player.P2;
1255
1257
 
1256
- const gen1 = struct {
1257
- pub usingnamespace @import("../gen1/data.zig");
1258
- pub const helpers = @import("../gen1/helpers.zig");
1259
- };
1260
-
1261
- const gen2 = struct {
1262
- pub usingnamespace @import("../gen2/data.zig");
1263
- pub const helpers = @import("../gen2/helpers.zig");
1264
- };
1265
-
1266
- var buf: [gen1.LOGS_SIZE]u8 = undefined;
1258
+ var buf: [pkmn.LOGS_SIZE]u8 = undefined;
1267
1259
  var stream: ByteStream = .{ .buffer = &buf };
1268
1260
  var log: FixedLog = .{ .writer = stream.writer() };
1269
1261
 
1262
+ const gen1 = pkmn.gen1;
1263
+ const gen2 = pkmn.gen2;
1264
+
1270
1265
  const M1 = gen1.Move;
1271
1266
  const S1 = gen1.Species;
1272
1267
 
@@ -1355,8 +1350,8 @@ test "|switch|" {
1355
1350
  try log.switched(.{ p2.ident(3), &snorlax });
1356
1351
  const par = 0b1000000;
1357
1352
  var expected: []const u8 = switch (endian) {
1358
- .Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
1359
- .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 },
1360
1355
  };
1361
1356
  try expectLog1(expected, buf[0..9]);
1362
1357
  stream.reset();
@@ -1366,8 +1361,8 @@ test "|switch|" {
1366
1361
  snorlax.status = 0;
1367
1362
  try log.switched(.{ p2.ident(3), &snorlax });
1368
1363
  expected = switch (endian) {
1369
- .Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
1370
- .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 },
1371
1366
  };
1372
1367
  try expectLog1(expected, buf[0..9]);
1373
1368
  stream.reset();
@@ -1375,8 +1370,8 @@ test "|switch|" {
1375
1370
  snorlax.hp = 400;
1376
1371
  try log.switched(.{ p2.ident(3), &snorlax });
1377
1372
  expected = switch (endian) {
1378
- .Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
1379
- .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 },
1380
1375
  };
1381
1376
  try expectLog1(expected, buf[0..9]);
1382
1377
  stream.reset();
@@ -1394,19 +1389,19 @@ test "|switch|" {
1394
1389
  N(gen2.Gender.Female),
1395
1390
  91,
1396
1391
  } ++ switch (endian) {
1397
- .Big => .{ 0, 200, 1, 144, par },
1398
- .Little => .{ 200, 0, 144, 1, par },
1392
+ big => .{ 0, 200, 1, 144, par },
1393
+ little => .{ 200, 0, 144, 1, par },
1399
1394
  });
1400
1395
  try expectLog2(expected, buf[0..10]);
1401
1396
  stream.reset();
1402
1397
  }
1403
1398
 
1404
1399
  test "|cant|" {
1405
- try log.cant(.{ p2.ident(6), Cant.Bound });
1400
+ try log.cant(.{ p2.ident(6), .Bound });
1406
1401
  try expectLog1(&.{ N(ArgType.Cant), 0b1110, N(Cant.Bound) }, buf[0..3]);
1407
1402
  stream.reset();
1408
1403
 
1409
- try log.cant(.{ p1.ident(2), Cant.Disable, M1.Earthquake });
1404
+ try log.cant(.{ p1.ident(2), .Disable, M1.Earthquake });
1410
1405
  try expectLog1(&.{ N(ArgType.Cant), 2, N(Cant.Disable), N(M1.Earthquake) }, buf[0..4]);
1411
1406
  stream.reset();
1412
1407
  }
@@ -1423,16 +1418,16 @@ test "|faint|" {
1423
1418
 
1424
1419
  test "|turn|" {
1425
1420
  try log.turn(.{42});
1426
- var expected = switch (endian) {
1427
- .Big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
1428
- .Little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
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) },
1429
1424
  };
1430
1425
  try expectLog1(expected, buf[0..4]);
1431
1426
  stream.reset();
1432
1427
  }
1433
1428
 
1434
1429
  test "|win|" {
1435
- try log.win(.{Player.P2});
1430
+ try log.win(.{.P2});
1436
1431
  try expectLog1(&.{ N(ArgType.Win), 1, N(ArgType.None) }, buf[0..3]);
1437
1432
  stream.reset();
1438
1433
  }
@@ -1447,10 +1442,10 @@ test "|-damage|" {
1447
1442
  var chansey = gen1.helpers.Pokemon.init(.{ .species = .Chansey, .moves = &.{.Splash} });
1448
1443
  chansey.hp = 612;
1449
1444
  chansey.status = gen1.Status.slp(1);
1450
- try log.damage(.{ p2.ident(2), &chansey, Damage.None });
1445
+ try log.damage(.{ p2.ident(2), &chansey, .None });
1451
1446
  var expected: []const u8 = switch (endian) {
1452
- .Big => &.{ N(ArgType.Damage), 0b1010, 2, 100, 2, 191, 1, N(Damage.None) },
1453
- .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) },
1454
1449
  };
1455
1450
  try expectLog1(expected, buf[0..8]);
1456
1451
  stream.reset();
@@ -1458,19 +1453,19 @@ test "|-damage|" {
1458
1453
  chansey.hp = 100;
1459
1454
  chansey.stats.hp = 256;
1460
1455
  chansey.status = 0;
1461
- try log.damage(.{ p2.ident(2), &chansey, Damage.Confusion });
1456
+ try log.damage(.{ p2.ident(2), &chansey, .Confusion });
1462
1457
  expected = switch (endian) {
1463
- .Big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0, N(Damage.Confusion) },
1464
- .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) },
1465
1460
  };
1466
1461
  try expectLog1(expected, buf[0..8]);
1467
1462
  stream.reset();
1468
1463
 
1469
1464
  chansey.status = gen1.Status.init(.PSN);
1470
- try log.damage(.{ p2.ident(2), &chansey, Damage.RecoilOf, p1.ident(1) });
1465
+ try log.damage(.{ p2.ident(2), &chansey, .RecoilOf, p1.ident(1) });
1471
1466
  expected = switch (endian) {
1472
- .Big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0b1000, N(Damage.RecoilOf), 1 },
1473
- .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 },
1474
1469
  };
1475
1470
  try expectLog1(expected, buf[0..9]);
1476
1471
  stream.reset();
@@ -1480,10 +1475,10 @@ test "|-heal|" {
1480
1475
  var chansey = gen1.helpers.Pokemon.init(.{ .species = .Chansey, .moves = &.{.Splash} });
1481
1476
  chansey.hp = 612;
1482
1477
  chansey.status = gen1.Status.slp(1);
1483
- try log.heal(.{ p2.ident(2), &chansey, Heal.None });
1478
+ try log.heal(.{ p2.ident(2), &chansey, .None });
1484
1479
  var expected: []const u8 = switch (endian) {
1485
- .Big => &.{ N(ArgType.Heal), 0b1010, 2, 100, 2, 191, 1, N(Heal.None) },
1486
- .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) },
1487
1482
  };
1488
1483
  try expectLog1(expected, buf[0..8]);
1489
1484
  stream.reset();
@@ -1491,33 +1486,33 @@ test "|-heal|" {
1491
1486
  chansey.hp = 100;
1492
1487
  chansey.stats.hp = 256;
1493
1488
  chansey.status = 0;
1494
- try log.heal(.{ p2.ident(2), &chansey, Heal.Silent });
1489
+ try log.heal(.{ p2.ident(2), &chansey, .Silent });
1495
1490
  expected = switch (endian) {
1496
- .Big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Silent) },
1497
- .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) },
1498
1493
  };
1499
1494
  try expectLog1(expected, buf[0..8]);
1500
1495
  stream.reset();
1501
1496
 
1502
- try log.heal(.{ p2.ident(2), &chansey, Heal.Drain, p1.ident(1) });
1497
+ try log.heal(.{ p2.ident(2), &chansey, .Drain, p1.ident(1) });
1503
1498
  expected = switch (endian) {
1504
- .Big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Drain), 1 },
1505
- .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 },
1506
1501
  };
1507
1502
  try expectLog1(expected, buf[0..9]);
1508
1503
  stream.reset();
1509
1504
  }
1510
1505
 
1511
1506
  test "|-status|" {
1512
- try log.status(.{ p2.ident(6), gen1.Status.init(.BRN), Status.None });
1507
+ try log.status(.{ p2.ident(6), gen1.Status.init(.BRN), .None });
1513
1508
  try expectLog1(&.{ N(ArgType.Status), 0b1110, 0b10000, N(Status.None) }, buf[0..4]);
1514
1509
  stream.reset();
1515
1510
 
1516
- try log.status(.{ p2.ident(2), gen1.Status.init(.PSN), Status.Silent });
1511
+ try log.status(.{ p2.ident(2), gen1.Status.init(.PSN), .Silent });
1517
1512
  try expectLog1(&.{ N(ArgType.Status), 0b1010, 0b1000, N(Status.Silent) }, buf[0..4]);
1518
1513
  stream.reset();
1519
1514
 
1520
- try log.status(.{ p1.ident(1), gen1.Status.init(.PAR), Status.From, M1.BodySlam });
1515
+ try log.status(.{ p1.ident(1), gen1.Status.init(.PAR), .From, M1.BodySlam });
1521
1516
  try expectLog1(
1522
1517
  &.{ N(ArgType.Status), 0b0001, 0b1000000, N(Status.From), N(M1.BodySlam) },
1523
1518
  buf[0..5],
@@ -1526,11 +1521,11 @@ test "|-status|" {
1526
1521
  }
1527
1522
 
1528
1523
  test "|-curestatus|" {
1529
- try log.curestatus(.{ p2.ident(6), gen1.Status.slp(7), CureStatus.Message });
1524
+ try log.curestatus(.{ p2.ident(6), gen1.Status.slp(7), .Message });
1530
1525
  try expectLog1(&.{ N(ArgType.CureStatus), 0b1110, 0b111, N(CureStatus.Message) }, buf[0..4]);
1531
1526
  stream.reset();
1532
1527
 
1533
- try log.curestatus(.{ p1.ident(2), gen1.Status.TOX, CureStatus.Silent });
1528
+ try log.curestatus(.{ p1.ident(2), gen1.Status.TOX, .Silent });
1534
1529
  try expectLog1(&.{
1535
1530
  N(ArgType.CureStatus),
1536
1531
  0b0010,
@@ -1541,15 +1536,15 @@ test "|-curestatus|" {
1541
1536
  }
1542
1537
 
1543
1538
  test "|-boost|" {
1544
- try log.boost(.{ p2.ident(6), Boost.Speed, 2 });
1539
+ try log.boost(.{ p2.ident(6), .Speed, 2 });
1545
1540
  try expectLog1(&.{ N(ArgType.Boost), 0b1110, N(Boost.Speed), 8 }, buf[0..4]);
1546
1541
  stream.reset();
1547
1542
 
1548
- try log.boost(.{ p1.ident(2), Boost.Rage, 1 });
1543
+ try log.boost(.{ p1.ident(2), .Rage, 1 });
1549
1544
  try expectLog1(&.{ N(ArgType.Boost), 0b0010, N(Boost.Rage), 7 }, buf[0..4]);
1550
1545
  stream.reset();
1551
1546
 
1552
- try log.boost(.{ p2.ident(3), Boost.Defense, -2 });
1547
+ try log.boost(.{ p2.ident(3), .Defense, -2 });
1553
1548
  try expectLog1(&.{ N(ArgType.Boost), 0b1011, N(Boost.Defense), 4 }, buf[0..4]);
1554
1549
  stream.reset();
1555
1550
  }
@@ -1561,19 +1556,19 @@ test "|-clearallboost|" {
1561
1556
  }
1562
1557
 
1563
1558
  test "|-fail|" {
1564
- try log.fail(.{ p2.ident(6), Fail.None });
1559
+ try log.fail(.{ p2.ident(6), .None });
1565
1560
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.None) }, buf[0..3]);
1566
1561
  stream.reset();
1567
1562
 
1568
- try log.fail(.{ p2.ident(6), Fail.Sleep });
1563
+ try log.fail(.{ p2.ident(6), .Sleep });
1569
1564
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Sleep) }, buf[0..3]);
1570
1565
  stream.reset();
1571
1566
 
1572
- try log.fail(.{ p2.ident(6), Fail.Substitute });
1567
+ try log.fail(.{ p2.ident(6), .Substitute });
1573
1568
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Substitute) }, buf[0..3]);
1574
1569
  stream.reset();
1575
1570
 
1576
- try log.fail(.{ p2.ident(6), Fail.Weak });
1571
+ try log.fail(.{ p2.ident(6), .Weak });
1577
1572
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Weak) }, buf[0..3]);
1578
1573
  stream.reset();
1579
1574
  }
@@ -1602,25 +1597,32 @@ test "|-mustrecharge|" {
1602
1597
  }
1603
1598
 
1604
1599
  test "|-activate|" {
1605
- try log.activate(p1.ident(2), .Struggle);
1600
+ try log.activate(.{ p1.ident(2), .Struggle });
1606
1601
  try expectLog1(&.{ N(ArgType.Activate), 0b0010, N(Activate.Struggle) }, buf[0..3]);
1607
1602
  stream.reset();
1608
1603
 
1609
- try log.activate(p2.ident(4), .Mist);
1604
+ try log.activate(.{ p2.ident(4), .Mist });
1610
1605
  try expectLog1(&.{ N(ArgType.Activate), 0b1100, N(Activate.Mist) }, buf[0..3]);
1611
1606
  stream.reset();
1612
1607
 
1613
- try log.activate(p2.ident(6), .Substitute);
1608
+ try log.activate(.{ p2.ident(6), .Substitute });
1614
1609
  try expectLog1(&.{ N(ArgType.Activate), 0b1110, N(Activate.Substitute) }, buf[0..3]);
1615
1610
  stream.reset();
1616
1611
 
1617
- try log.activate(p1.ident(2), .Splash);
1612
+ try log.activate(.{ p1.ident(2), .Splash });
1618
1613
  try expectLog1(&.{ N(ArgType.Activate), 0b0010, N(Activate.Splash) }, buf[0..3]);
1619
1614
  stream.reset();
1620
1615
 
1621
- // 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();
1622
1624
 
1623
- try log.magnitude(p1.ident(3), 5);
1625
+ try log.activate(.{ p1.ident(3), .Magnitude, 5 });
1624
1626
  try expectLog1(&.{ N(ArgType.Activate), 0b0011, N(Activate.Magnitude), 5 }, buf[0..4]);
1625
1627
  stream.reset();
1626
1628
  }
@@ -1632,43 +1634,53 @@ test "|-fieldactivate|" {
1632
1634
  }
1633
1635
 
1634
1636
  test "|-start|" {
1635
- try log.start(p2.ident(6), .Bide);
1637
+ try log.start(.{ p2.ident(6), .Bide });
1636
1638
  try expectLog1(&.{ N(ArgType.Start), 0b1110, N(Start.Bide) }, buf[0..3]);
1637
1639
  stream.reset();
1638
1640
 
1639
- try log.start(p1.ident(2), .ConfusionSilent);
1641
+ try log.start(.{ p1.ident(2), .ConfusionSilent });
1640
1642
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.ConfusionSilent) }, buf[0..3]);
1641
1643
  stream.reset();
1642
1644
 
1643
- 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
+ });
1644
1651
  try expectLog1(
1645
1652
  &.{ N(ArgType.Start), 0b1110, N(Start.TypeChange), 0b1000_1000, 0b1101 },
1646
1653
  buf[0..5],
1647
1654
  );
1648
1655
  stream.reset();
1649
1656
 
1650
- 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
+ });
1651
1663
  try expectLog1(
1652
1664
  &.{ N(ArgType.Start), 0b0010, N(Start.TypeChange), 0b0011_0110, 0b1100 },
1653
1665
  buf[0..5],
1654
1666
  );
1655
1667
  stream.reset();
1656
1668
 
1657
- try log.startEffect(p1.ident(2), .Disable, M1.Surf);
1669
+ try log.start(.{ p1.ident(2), .Disable, M1.Surf });
1658
1670
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Disable), N(M1.Surf) }, buf[0..4]);
1659
1671
  stream.reset();
1660
1672
 
1661
- try log.startEffect(p1.ident(2), .Mimic, M1.Surf);
1673
+ try log.start(.{ p1.ident(2), .Mimic, M1.Surf });
1662
1674
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Mimic), N(M1.Surf) }, buf[0..4]);
1663
1675
  stream.reset();
1664
1676
  }
1665
1677
 
1666
1678
  test "|-end|" {
1667
- try log.end(.{ p2.ident(6), End.Bide });
1679
+ try log.end(.{ p2.ident(6), .Bide });
1668
1680
  try expectLog1(&.{ N(ArgType.End), 0b1110, N(End.Bide) }, buf[0..3]);
1669
1681
  stream.reset();
1670
1682
 
1671
- try log.end(.{ p1.ident(2), End.ConfusionSilent });
1683
+ try log.end(.{ p1.ident(2), .ConfusionSilent });
1672
1684
  try expectLog1(&.{ N(ArgType.End), 0b0010, N(End.ConfusionSilent) }, buf[0..3]);
1673
1685
  stream.reset();
1674
1686
  }
@@ -1698,11 +1710,11 @@ test "|-resisted|" {
1698
1710
  }
1699
1711
 
1700
1712
  test "|-immune|" {
1701
- try log.immune(.{ p1.ident(3), Immune.None });
1713
+ try log.immune(.{ p1.ident(3), .None });
1702
1714
  try expectLog1(&.{ N(ArgType.Immune), 0b0011, N(Immune.None) }, buf[0..3]);
1703
1715
  stream.reset();
1704
1716
 
1705
- try log.immune(.{ p2.ident(2), Immune.OHKO });
1717
+ try log.immune(.{ p2.ident(2), .OHKO });
1706
1718
  try expectLog1(&.{ N(ArgType.Immune), 0b1010, N(Immune.OHKO) }, buf[0..3]);
1707
1719
  stream.reset();
1708
1720
  }
@@ -1728,8 +1740,8 @@ test "|drag|" {
1728
1740
  N(gen2.Gender.Female),
1729
1741
  91,
1730
1742
  } ++ switch (endian) {
1731
- .Big => .{ 0, 200, 1, 144, par },
1732
- .Little => .{ 200, 0, 144, 1, par },
1743
+ big => .{ 0, 200, 1, 144, par },
1744
+ little => .{ 200, 0, 144, 1, par },
1733
1745
  });
1734
1746
  try expectLog2(expected, buf[0..10]);
1735
1747
  stream.reset();
@@ -1742,11 +1754,11 @@ test "|-item|" {
1742
1754
  }
1743
1755
 
1744
1756
  test "|-enditem|" {
1745
- try log.enditem(.{ p1.ident(1), I2.BerserkGene, EndItem.None });
1757
+ try log.enditem(.{ p1.ident(1), I2.BerserkGene, .None });
1746
1758
  try expectLog2(&.{ N(ArgType.EndItem), 0b0001, N(I2.BerserkGene), N(EndItem.None) }, buf[0..4]);
1747
1759
  stream.reset();
1748
1760
 
1749
- try log.enditem(.{ p2.ident(4), I2.PRZCureBerry, EndItem.Eat });
1761
+ try log.enditem(.{ p2.ident(4), I2.PRZCureBerry, .Eat });
1750
1762
  try expectLog2(&.{ N(ArgType.EndItem), 0b1100, N(I2.PRZCureBerry), N(EndItem.Eat) }, buf[0..4]);
1751
1763
  stream.reset();
1752
1764
  }
@@ -1760,10 +1772,10 @@ test "|-cureteam|" {
1760
1772
  test "|-sethp|" {
1761
1773
  var blissey = gen2.helpers.Pokemon.init(.{ .species = .Blissey, .moves = &.{.PainSplit} });
1762
1774
  blissey.hp = 612;
1763
- try log.sethp(.{ p2.ident(2), &blissey, SetHP.Silent });
1764
- var expected: []const u8 = switch (endian) {
1765
- .Big => &.{ N(ArgType.SetHP), 0b1010, 2, 100, 2, 201, 0, N(SetHP.Silent) },
1766
- .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) },
1767
1779
  };
1768
1780
  try expectLog2(expected, buf[0..8]);
1769
1781
  stream.reset();
@@ -1786,17 +1798,17 @@ test "|-copyboost|" {
1786
1798
  }
1787
1799
 
1788
1800
  test "|-sidestart|" {
1789
- try log.sidestart(.{ Player.P2, Side.Reflect });
1801
+ try log.sidestart(.{ .P2, .Reflect });
1790
1802
  try expectLog2(&.{ N(ArgType.SideStart), 1, N(Side.Reflect) }, buf[0..3]);
1791
1803
  stream.reset();
1792
1804
  }
1793
1805
 
1794
1806
  test "|-sideend|" {
1795
- try log.sideend(.{ Player.P2, Side.LightScreen });
1807
+ try log.sideend(.{ .P2, .LightScreen });
1796
1808
  try expectLog2(&.{ N(ArgType.SideEnd), 1, N(Side.LightScreen) }, buf[0..3]);
1797
1809
  stream.reset();
1798
1810
 
1799
- try log.sideend(.{ Player.P1, Side.Spikes, p1.ident(3) });
1811
+ try log.sideend(.{ .P1, .Spikes, p1.ident(3) });
1800
1812
  try expectLog2(&.{
1801
1813
  N(ArgType.SideEnd),
1802
1814
  0,
@@ -1819,11 +1831,11 @@ test "|-singleturn|" {
1819
1831
  }
1820
1832
 
1821
1833
  test "|-weather|" {
1822
- try log.weather(.{ W2.Rain, Weather.Upkeep });
1834
+ try log.weather(.{ W2.Rain, .Upkeep });
1823
1835
  try expectLog2(&.{ N(ArgType.Weather), N(W2.Rain), N(Weather.Upkeep) }, buf[0..3]);
1824
1836
  stream.reset();
1825
1837
 
1826
- try log.weather(.{ W2.None, Weather.None });
1838
+ try log.weather(.{ W2.None, .None });
1827
1839
  try expectLog2(&.{ N(ArgType.Weather), N(W2.None), N(Weather.None) }, buf[0..3]);
1828
1840
  stream.reset();
1829
1841
  }