@pkmn/engine 0.1.0-dev.30c63015 → 0.1.0-dev.3158fa12

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 (82) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +46 -18
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +44 -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 +97 -0
  8. package/build/pkg/addon/node.js.map +1 -0
  9. package/build/pkg/addon/wasm.d.ts +2 -0
  10. package/build/pkg/addon/wasm.js +53 -0
  11. package/build/pkg/addon/wasm.js.map +1 -0
  12. package/build/pkg/addon.d.ts +25 -3
  13. package/build/pkg/addon.js +39 -71
  14. package/build/pkg/addon.js.map +1 -1
  15. package/build/pkg/data/layout.json +15 -2
  16. package/build/pkg/data/protocol.json +23 -9
  17. package/build/pkg/data.d.ts +27 -5
  18. package/build/pkg/data.js.map +1 -1
  19. package/build/pkg/gen1.d.ts +13 -17
  20. package/build/pkg/gen1.js +6 -10
  21. package/build/pkg/gen1.js.map +1 -1
  22. package/build/pkg/index.d.ts +40 -91
  23. package/build/pkg/index.js +6 -63
  24. package/build/pkg/index.js.map +1 -1
  25. package/build/pkg/protocol.d.ts +20 -1
  26. package/build/pkg/protocol.js +109 -107
  27. package/build/pkg/protocol.js.map +1 -1
  28. package/build/tools/debug.js +36 -71
  29. package/build/tools/debug.js.map +1 -1
  30. package/build/tools/display/debug.jsx +141 -0
  31. package/build/tools/display/debug.jsx.map +1 -0
  32. package/build/tools/display/index.js +142 -0
  33. package/build/tools/display/index.js.map +1 -0
  34. package/build/tools/display/ui.jsx +349 -0
  35. package/build/tools/display/ui.jsx.map +1 -0
  36. package/build/tools/display/util.js +18 -0
  37. package/build/tools/display/util.js.map +1 -0
  38. package/build.zig +287 -89
  39. package/package.json +58 -132
  40. package/src/bin/install-pkmn-engine +30 -20
  41. package/src/bin/pkmn-debug +1 -1
  42. package/src/lib/{binding → bindings}/node.zig +8 -21
  43. package/src/lib/bindings/wasm.zig +59 -0
  44. package/src/lib/common/array.zig +77 -0
  45. package/src/lib/common/data.zig +4 -4
  46. package/src/lib/common/debug.zig +39 -8
  47. package/src/lib/common/js.zig +4 -2
  48. package/src/lib/common/optional.zig +14 -10
  49. package/src/lib/common/options.zig +6 -0
  50. package/src/lib/common/protocol.zig +223 -215
  51. package/src/lib/common/rational.zig +128 -32
  52. package/src/lib/common/rng.zig +7 -9
  53. package/src/lib/common/util.zig +50 -1
  54. package/src/lib/gen1/calc.zig +686 -159
  55. package/src/lib/gen1/chance.zig +405 -280
  56. package/src/lib/gen1/data/moves.zig +2 -4
  57. package/src/lib/gen1/data/species.zig +2 -4
  58. package/src/lib/gen1/data/types.zig +1 -2
  59. package/src/lib/gen1/data.zig +24 -27
  60. package/src/lib/gen1/helpers.zig +92 -548
  61. package/src/lib/gen1/mechanics.zig +517 -411
  62. package/src/lib/gen2/calc.zig +37 -27
  63. package/src/lib/gen2/chance.zig +84 -496
  64. package/src/lib/gen2/data/items.zig +1 -3
  65. package/src/lib/gen2/data/moves.zig +2 -4
  66. package/src/lib/gen2/data/species.zig +1 -3
  67. package/src/lib/gen2/data/types.zig +1 -2
  68. package/src/lib/gen2/data.zig +19 -22
  69. package/src/lib/gen2/generated.zig +19 -26
  70. package/src/lib/gen2/helpers.zig +46 -25
  71. package/src/lib/gen2/mechanics.zig +367 -336
  72. package/src/lib/node.zig +18 -0
  73. package/src/lib/pkmn.zig +37 -15
  74. package/src/lib/wasm.zig +17 -0
  75. package/src/tools/display/dom.ts +96 -0
  76. package/src/tools/display/ui.css +354 -0
  77. package/build/test/display.js +0 -400
  78. package/build/test/display.js.map +0 -1
  79. package/src/lib/binding/wasm.zig +0 -12
  80. package/src/lib/gen1/README.md +0 -894
  81. package/src/lib/gen2/README.md +0 -329
  82. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -1,16 +1,21 @@
1
- const std = @import("std");
2
1
  const builtin = @import("builtin");
3
-
4
- const data = @import("./data.zig");
5
- const options = @import("./options.zig");
2
+ const data = @import("data.zig");
3
+ const options = @import("options.zig");
4
+ const pkmn = @import("../pkmn.zig");
5
+ const std = @import("std");
6
6
 
7
7
  const assert = std.debug.assert;
8
+ const enabled = options.log;
9
+ const ID = data.ID;
10
+ const Player = data.Player;
8
11
  const print = std.debug.print;
9
12
 
10
- const enabled = options.log;
13
+ const endian = builtin.cpu.arch.endian();
14
+ const Endian = std.builtin.Endian;
15
+ const big = if (@hasField(Endian, "big")) Endian.big else Endian.Big;
16
+ const little = if (@hasField(Endian, "little")) Endian.little else Endian.Little;
11
17
 
12
- const Player = data.Player;
13
- const ID = data.ID;
18
+ const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
14
19
 
15
20
  pub const ArgType = enum(u8) {
16
21
  None,
@@ -69,7 +74,7 @@ pub const ArgType = enum(u8) {
69
74
  EndAbility,
70
75
  ClearNegativeBoost,
71
76
  FormeChange,
72
- NoTarget,
77
+ LastNoTarget, // FIXME
73
78
 
74
79
  // Gen 4
75
80
  SwapBoost,
@@ -102,6 +107,7 @@ pub const ArgType = enum(u8) {
102
107
  // Gen 8
103
108
  CanDynamax,
104
109
  SwapSideConditions,
110
+ UpdatePoke,
105
111
 
106
112
  // Gen 9
107
113
  Terastallize,
@@ -215,6 +221,7 @@ pub const Activate = enum(u8) {
215
221
  BeatUp, // FIXME of
216
222
 
217
223
  Magnitude,
224
+ Spite,
218
225
  };
219
226
 
220
227
  pub const Start = enum(u8) {
@@ -320,7 +327,7 @@ pub fn Log(comptime Writer: type) type {
320
327
 
321
328
  pub const Error = Writer.Error;
322
329
 
323
- // source: ID, m: anytype, target: ID, from?: anytype
330
+ // source: ID, move: <Move>, target: ID, from?: <Move>
324
331
  pub fn move(self: Self, args: anytype) Error!void {
325
332
  if (!enabled) return;
326
333
 
@@ -337,12 +344,12 @@ pub fn Log(comptime Writer: type) type {
337
344
  &.{ @intFromEnum(Move.From), @intFromEnum(args[3]) });
338
345
  }
339
346
 
340
- // ident: ID, pokemon: anytype
347
+ // ident: ID, pokemon: <Pokemon>
341
348
  pub fn switched(self: Self, args: anytype) Error!void {
342
349
  return switchDrag(self, .Switch, args);
343
350
  }
344
351
 
345
- // ident: ID, pokemon: anytype
352
+ // ident: ID, pokemon: <Pokemon>
346
353
  fn switchDrag(self: Self, arg: ArgType, args: anytype) Error!void {
347
354
  if (!enabled) return;
348
355
 
@@ -356,12 +363,13 @@ pub fn Log(comptime Writer: type) type {
356
363
  } else {
357
364
  try self.writer.writeAll(&.{ @intFromEnum(args[1].species), args[1].level });
358
365
  }
359
- try self.writer.writeIntNative(u16, args[1].hp);
360
- try self.writer.writeIntNative(u16, args[1].stats.hp);
366
+ try self.writer.writeInt(u16, args[1].hp, endian);
367
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
361
368
  try self.writer.writeAll(&.{args[1].status});
362
369
  }
363
370
 
364
- // ident: ID, reason: Cant, m?: anytype
371
+ // ident: ID, reason: Cant
372
+ // ident: ID, reason: .Disable, move: <Move>
365
373
  pub fn cant(self: Self, args: anytype) Error!void {
366
374
  if (!enabled) return;
367
375
 
@@ -369,7 +377,7 @@ pub fn Log(comptime Writer: type) type {
369
377
  try self.writer.writeAll(&.{
370
378
  @intFromEnum(ArgType.Cant),
371
379
  @as(u8, @bitCast(args[0])),
372
- @intFromEnum(args[1]),
380
+ @intFromEnum(@as(Cant, args[1])),
373
381
  });
374
382
  if (args.len == 3) try self.writer.writeByte(@intFromEnum(args[2]));
375
383
  }
@@ -387,7 +395,7 @@ pub fn Log(comptime Writer: type) type {
387
395
  if (!enabled) return;
388
396
 
389
397
  try self.writer.writeByte(@intFromEnum(ArgType.Turn));
390
- try self.writer.writeIntNative(u16, args[0]);
398
+ try self.writer.writeInt(u16, args[0], endian);
391
399
  try self.writer.writeByte(@intFromEnum(ArgType.None));
392
400
  }
393
401
 
@@ -397,7 +405,7 @@ pub fn Log(comptime Writer: type) type {
397
405
 
398
406
  try self.writer.writeAll(&.{
399
407
  @intFromEnum(ArgType.Win),
400
- @intFromEnum(args[0]),
408
+ @intFromEnum(@as(Player, args[0])),
401
409
  @intFromEnum(ArgType.None),
402
410
  });
403
411
  }
@@ -409,34 +417,37 @@ pub fn Log(comptime Writer: type) type {
409
417
  try self.writer.writeAll(&.{ @intFromEnum(ArgType.Tie), @intFromEnum(ArgType.None) });
410
418
  }
411
419
 
412
- // ident: ID, pokemon: anytype, reason: Damage, source?: ID
420
+ // ident: ID, pokemon: <Pokemon>, reason: Damage
421
+ // ident: ID, pokemon: <Pokemon>, reason: .RecoilOf, source: ID
413
422
  pub fn damage(self: Self, args: anytype) Error!void {
414
423
  if (!enabled) return;
415
424
 
416
- assert(@intFromEnum(args[2]) <= @intFromEnum(Damage.LeechSeed) or args.len == 4);
425
+ assert(args[2] != .RecoilOf or args.len == 4);
417
426
  try self.writer.writeAll(&.{
418
427
  @intFromEnum(ArgType.Damage),
419
428
  @as(u8, @bitCast(args[0])),
420
429
  });
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]) });
430
+ try self.writer.writeInt(u16, args[1].hp, endian);
431
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
432
+ try self.writer.writeAll(&.{ args[1].status, @intFromEnum(@as(Damage, args[2])) });
424
433
  if (args.len == 4) try self.writer.writeByte(@as(u8, @bitCast(args[3])));
425
434
  }
426
435
 
427
- // ident: ID, pokemon: anytype, reason: Heal, target?: ID)
436
+ // ident: ID, pokemon: <Pokemon>, reason: Heal
437
+ // ident: ID, pokemon: <Pokemon>, reason: .Drain, target: ID
428
438
  pub fn heal(self: Self, args: anytype) Error!void {
429
439
  if (!enabled) return;
430
440
 
431
441
  assert(args[2] != .Drain or args.len == 4);
432
442
  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]) });
443
+ try self.writer.writeInt(u16, args[1].hp, endian);
444
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
445
+ try self.writer.writeAll(&.{ args[1].status, @intFromEnum(@as(Heal, args[2])) });
436
446
  if (args.len == 4) try self.writer.writeByte(@as(u8, @bitCast(args[3])));
437
447
  }
438
448
 
439
- // ident: ID, value: u8, reason: Status, m?: anytype)
449
+ // ident: ID, value: u8, reason: Status
450
+ // ident: ID, value: u8, reason: .From, m: <Move>
440
451
  pub fn status(self: Self, args: anytype) Error!void {
441
452
  if (!enabled) return;
442
453
 
@@ -445,7 +456,7 @@ pub fn Log(comptime Writer: type) type {
445
456
  @intFromEnum(ArgType.Status),
446
457
  @as(u8, @bitCast(args[0])),
447
458
  args[1],
448
- @intFromEnum(args[2]),
459
+ @intFromEnum(@as(Status, args[2])),
449
460
  });
450
461
  if (args.len == 4) try self.writer.writeByte(@intFromEnum(args[3]));
451
462
  }
@@ -458,7 +469,7 @@ pub fn Log(comptime Writer: type) type {
458
469
  @intFromEnum(ArgType.CureStatus),
459
470
  @as(u8, @bitCast(args[0])),
460
471
  args[1],
461
- @intFromEnum(args[2]),
472
+ @intFromEnum(@as(CureStatus, args[2])),
462
473
  });
463
474
  }
464
475
 
@@ -470,7 +481,7 @@ pub fn Log(comptime Writer: type) type {
470
481
  try self.writer.writeAll(&.{
471
482
  @intFromEnum(ArgType.Boost),
472
483
  @as(u8, @bitCast(args[0])),
473
- @intFromEnum(args[1]),
484
+ @intFromEnum(@as(Boost, args[1])),
474
485
  @as(u8, @intCast(@as(i8, args[2]) + 6)),
475
486
  });
476
487
  }
@@ -489,7 +500,7 @@ pub fn Log(comptime Writer: type) type {
489
500
  try self.writer.writeAll(&.{
490
501
  @intFromEnum(ArgType.Fail),
491
502
  @as(u8, @bitCast(args[0])),
492
- @intFromEnum(args[1]),
503
+ @intFromEnum(@as(Fail, args[1])),
493
504
  });
494
505
  }
495
506
 
@@ -511,7 +522,7 @@ pub fn Log(comptime Writer: type) type {
511
522
  });
512
523
  }
513
524
 
514
- // source: ID, m: anytype
525
+ // source: ID, m: <Move>
515
526
  pub fn prepare(self: Self, args: anytype) Error!void {
516
527
  if (!enabled) return;
517
528
 
@@ -532,38 +543,31 @@ pub fn Log(comptime Writer: type) type {
532
543
  });
533
544
  }
534
545
 
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 {
546
+ // ident: ID, reason: Activate
547
+ // ident: ID, reason: .SubstituteBlock, m: <Move>
548
+ // ident: ID, reason: .Magnitude, num: u8
549
+ // ident: ID, reason: .Spite, m: <Move>, num: u8
550
+ pub fn activate(self: Self, args: anytype) Error!void {
547
551
  if (!enabled) return;
548
552
 
549
- assert(reason == .SubstituteBlock); // TODO
553
+ assert(args.len <= 4);
554
+ const reason: Activate = args[1];
550
555
  try self.writer.writeAll(&.{
551
556
  @intFromEnum(ArgType.Activate),
552
- @as(u8, @bitCast(ident)),
557
+ @as(u8, @bitCast(args[0])),
553
558
  @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
559
  });
560
+ if (args.len == 3) {
561
+ if (reason == .SubstituteBlock) {
562
+ try self.writer.writeByte(@intFromEnum(args[2]));
563
+ } else {
564
+ assert(reason == .Magnitude);
565
+ try self.writer.writeByte(args[2]);
566
+ }
567
+ } else if (args.len == 4) {
568
+ assert(reason == .Spite);
569
+ try self.writer.writeAll(&.{ @intFromEnum(args[2]), args[3] });
570
+ }
567
571
  }
568
572
 
569
573
  // -
@@ -573,49 +577,40 @@ pub fn Log(comptime Writer: type) type {
573
577
  try self.writer.writeAll(&.{@intFromEnum(ArgType.FieldActivate)});
574
578
  }
575
579
 
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 {
580
+ // ident: ID, reason: Start
581
+ // ident: ID, reason: .Disable | .Mimic | .Encore, m: <Move>
582
+ // ident: ID, reason: .TypeChange, types: <Types>, target: ID
583
+ pub fn start(self: Self, args: anytype) Error!void {
600
584
  if (!enabled) return;
601
585
 
602
- assert(@intFromEnum(reason) > @intFromEnum(Start.TypeChange));
586
+ assert(args.len <= 4);
587
+ const reason: Start = args[1];
603
588
  try self.writer.writeAll(&.{
604
589
  @intFromEnum(ArgType.Start),
605
- @as(u8, @bitCast(ident)),
590
+ @as(u8, @bitCast(args[0])),
606
591
  @intFromEnum(reason),
607
- @intFromEnum(m),
608
592
  });
593
+ if (args.len == 3) {
594
+ assert(reason == .Disable or reason == .Mimic or reason == .Encore);
595
+ try self.writer.writeByte(@intFromEnum(args[2]));
596
+ } else if (args.len == 4) {
597
+ assert(reason == .TypeChange);
598
+ // FIXME: u16 types in Generation II
599
+ try self.writer.writeAll(&.{
600
+ @as(u8, @bitCast(args[2])),
601
+ @as(u8, @bitCast(args[3])),
602
+ });
603
+ }
609
604
  }
610
605
 
611
- // ident: ID, reason: End)
606
+ // ident: ID, reason: End
612
607
  pub fn end(self: Self, args: anytype) Error!void {
613
608
  if (!enabled) return;
614
609
 
615
610
  try self.writer.writeAll(&.{
616
611
  @intFromEnum(ArgType.End),
617
612
  @as(u8, @bitCast(args[0])),
618
- @intFromEnum(args[1]),
613
+ @intFromEnum(@as(End, args[1])),
619
614
  });
620
615
  }
621
616
 
@@ -660,7 +655,7 @@ pub fn Log(comptime Writer: type) type {
660
655
  try self.writer.writeAll(&.{
661
656
  @intFromEnum(ArgType.Immune),
662
657
  @as(u8, @bitCast(args[0])),
663
- @intFromEnum(args[1]),
658
+ @intFromEnum(@as(Immune, args[1])),
664
659
  });
665
660
  }
666
661
 
@@ -675,12 +670,12 @@ pub fn Log(comptime Writer: type) type {
675
670
  });
676
671
  }
677
672
 
678
- // ident: ID, pokemon: anytype
673
+ // ident: ID, pokemon: <Pokemon>
679
674
  pub fn drag(self: Self, args: anytype) Error!void {
680
675
  return switchDrag(self, .Drag, args);
681
676
  }
682
677
 
683
- // target: ID, i: anytype, source: ID
678
+ // target: ID, item: <Item>, source: ID
684
679
  pub fn item(self: Self, args: anytype) Error!void {
685
680
  if (!enabled) return;
686
681
 
@@ -692,7 +687,7 @@ pub fn Log(comptime Writer: type) type {
692
687
  });
693
688
  }
694
689
 
695
- // ident: ID, i: anytype, reason: EndItem
690
+ // ident: ID, item: <Item>, reason: EndItem
696
691
  pub fn enditem(self: Self, args: anytype) Error!void {
697
692
  if (!enabled) return;
698
693
 
@@ -700,7 +695,7 @@ pub fn Log(comptime Writer: type) type {
700
695
  @intFromEnum(ArgType.EndItem),
701
696
  @as(u8, @bitCast(args[0])),
702
697
  @intFromEnum(args[1]),
703
- @intFromEnum(args[2]),
698
+ @intFromEnum(@as(EndItem, args[2])),
704
699
  });
705
700
  }
706
701
 
@@ -714,15 +709,15 @@ pub fn Log(comptime Writer: type) type {
714
709
  });
715
710
  }
716
711
 
717
- // ident: ID, pokemon: anytype, reason: SetHP
712
+ // ident: ID, pokemon: <Pokemon>, reason: SetHP
718
713
  pub fn sethp(self: Self, args: anytype) Error!void {
719
714
  if (!enabled) return;
720
715
 
721
716
  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);
717
+ try self.writer.writeInt(u16, args[1].hp, endian);
718
+ try self.writer.writeInt(u16, args[1].stats.hp, endian);
724
719
  try self.writer.writeAll(&.{args[1].status});
725
- try self.writer.writeByte(@intFromEnum(args[2]));
720
+ try self.writer.writeByte(@intFromEnum(@as(SetHP, args[2])));
726
721
  }
727
722
 
728
723
  // ident: ID, num: i8
@@ -753,35 +748,36 @@ pub fn Log(comptime Writer: type) type {
753
748
 
754
749
  try self.writer.writeAll(&.{
755
750
  @intFromEnum(ArgType.SideStart),
756
- @intFromEnum(args[0]),
757
- @intFromEnum(args[1]),
751
+ @intFromEnum(@as(Player, args[0])),
752
+ @intFromEnum(@as(Side, args[1])),
758
753
  });
759
754
  }
760
755
 
761
- // player: Player, reason: Side, source?: ID
756
+ // player: Player, reason: Side
757
+ // player: Player, reason: .Spikes, source: ID
762
758
  pub fn sideend(self: Self, args: anytype) Error!void {
763
759
  if (!enabled) return;
764
760
 
765
- assert(@intFromEnum(args[1]) != @intFromEnum(Side.Spikes) or args.len == 3);
761
+ assert(args[1] != .Spikes or args.len == 3);
766
762
  try self.writer.writeAll(&.{
767
763
  @intFromEnum(ArgType.SideEnd),
768
- @intFromEnum(args[0]),
769
- @intFromEnum(args[1]),
764
+ @intFromEnum(@as(Player, args[0])),
765
+ @intFromEnum(@as(Side, args[1])),
770
766
  });
771
767
  if (args.len == 3) try self.writer.writeByte(@as(u8, @bitCast(args[2])));
772
768
  }
773
769
 
774
- // ident: ID, move: anytype
770
+ // ident: ID, move: <Move>
775
771
  pub fn singlemove(self: Self, args: anytype) Error!void {
776
772
  return single(self, .SingleMove, args);
777
773
  }
778
774
 
779
- // ident: ID, m: anytype
775
+ // ident: ID, move: <Move>
780
776
  pub fn singleturn(self: Self, args: anytype) Error!void {
781
777
  return single(self, .SingleTurn, args);
782
778
  }
783
779
 
784
- // ident: ID, move: anytype
780
+ // ident: ID, move: <Move>
785
781
  fn single(self: Self, arg: ArgType, args: anytype) Error!void {
786
782
  if (!enabled) return;
787
783
 
@@ -792,7 +788,7 @@ pub fn Log(comptime Writer: type) type {
792
788
  });
793
789
  }
794
790
 
795
- // w: anytype, reason: Weather
791
+ // weather: <Weather>, reason: Weather
796
792
  pub fn weather(self: Self, args: anytype) Error!void {
797
793
  if (!enabled) return;
798
794
 
@@ -800,7 +796,7 @@ pub fn Log(comptime Writer: type) type {
800
796
  try self.writer.writeAll(&.{
801
797
  @intFromEnum(ArgType.Weather),
802
798
  @intFromEnum(args[0]),
803
- @intFromEnum(args[1]),
799
+ @intFromEnum(@as(Weather, args[1])),
804
800
  });
805
801
  }
806
802
 
@@ -843,10 +839,10 @@ pub const ByteStream = struct {
843
839
  try self.stream.writeByte(byte);
844
840
  }
845
841
 
846
- pub fn writeIntNative(self: Writer, comptime T: type, value: T) Error!void {
842
+ pub fn writeInt(self: Writer, comptime T: type, v: T, end: std.builtin.Endian) Error!void {
847
843
  // 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);
844
+ var bytes: [@divExact(@field(@typeInfo(T), @tagName(Int)).bits, 8)]u8 = undefined;
845
+ std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(v)), &bytes, v, end);
850
846
  return self.writeAll(&bytes);
851
847
  }
852
848
  };
@@ -869,7 +865,7 @@ pub const ByteStream = struct {
869
865
  pub const Kind = enum { Move, Species, Type, Status, Item, Weather };
870
866
 
871
867
  pub fn format(
872
- comptime gen: anytype,
868
+ gen: anytype,
873
869
  a: []const u8,
874
870
  b: ?[]const u8,
875
871
  color: bool,
@@ -955,19 +951,19 @@ pub fn format(
955
951
  if (a[i] == N(gen.Gender.Unknown)) {
956
952
  i += 1;
957
953
  } else {
958
- var gender = if (a[i] == N(gen.Gender.Male)) "M" else "F";
954
+ const gender = if (a[i] == N(gen.Gender.Male)) "M" else "F";
959
955
  printc(", {s}", .{gender}, a, b, &i, 1, color);
960
956
  }
961
957
  }
962
958
  printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
963
959
  switch (endian) {
964
- .Big => {
960
+ big => {
965
961
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
966
962
  printc(" {d}", .{hp}, a, b, &i, 2, color);
967
963
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
968
964
  printc("/{d}", .{hp}, a, b, &i, 2, color);
969
965
  },
970
- .Little => {
966
+ little => {
971
967
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
972
968
  printc(" {d}", .{hp}, a, b, &i, 2, color);
973
969
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -998,8 +994,8 @@ pub fn format(
998
994
  },
999
995
  .Turn => {
1000
996
  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]),
997
+ big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
998
+ little => @as(u16, a[i + 1]) << 8 | @as(u16, a[i]),
1003
999
  };
1004
1000
  printc(" {d}", .{turn}, a, b, &i, 2, color);
1005
1001
  },
@@ -1010,13 +1006,13 @@ pub fn format(
1010
1006
  var id = ID.from(@intCast(a[i]));
1011
1007
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1012
1008
  switch (endian) {
1013
- .Big => {
1009
+ big => {
1014
1010
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1015
1011
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1016
1012
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1017
1013
  printc("/{d}", .{hp}, a, b, &i, 2, color);
1018
1014
  },
1019
- .Little => {
1015
+ little => {
1020
1016
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
1021
1017
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1022
1018
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -1081,7 +1077,13 @@ pub fn format(
1081
1077
  .Activate => {
1082
1078
  const id = ID.from(@intCast(a[i]));
1083
1079
  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);
1080
+ const reason: Activate = @enumFromInt(a[i]);
1081
+ printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
1082
+ if (reason == .SubstituteBlock) {
1083
+ printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
1084
+ } else if (reason == .Magnitude) {
1085
+ printc(" {d}", .{a[i]}, a, b, &i, 1, color);
1086
+ }
1085
1087
  },
1086
1088
  .Start => {
1087
1089
  const id = ID.from(@intCast(a[i]));
@@ -1089,6 +1091,7 @@ pub fn format(
1089
1091
  const reason = a[i];
1090
1092
  printc(" {s}", .{@tagName(@as(Start, @enumFromInt(reason)))}, a, b, &i, 1, color);
1091
1093
  if (@as(Start, @enumFromInt(reason)) == .TypeChange) {
1094
+ // FIXME
1092
1095
  const types = @as(gen1.Types, @bitCast(a[i]));
1093
1096
  const args = .{
1094
1097
  formatter(gen, .Type, @intFromEnum(types.type1)),
@@ -1131,13 +1134,13 @@ pub fn format(
1131
1134
  const id = ID.from(@intCast(a[i]));
1132
1135
  printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
1133
1136
  switch (endian) {
1134
- .Big => {
1137
+ big => {
1135
1138
  var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1136
1139
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1137
1140
  hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
1138
1141
  printc("/{d}", .{hp}, a, b, &i, 2, color);
1139
1142
  },
1140
- .Little => {
1143
+ little => {
1141
1144
  var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
1142
1145
  printc(" {d}", .{hp}, a, b, &i, 2, color);
1143
1146
  hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
@@ -1205,14 +1208,11 @@ pub fn expectLog(
1205
1208
  ) !void {
1206
1209
  if (!enabled) return;
1207
1210
 
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
- }
1211
+ const color = if (std.process.hasEnvVarConstant("ZIG_DEBUG_COLOR"))
1212
+ true
1213
+ else switch (std.io.tty.detectConfig(std.io.getStdErr())) {
1214
+ .escape_codes => true,
1215
+ else => false,
1216
1216
  };
1217
1217
 
1218
1218
  expectEqualBytes(expected, actual, offset) catch |err| switch (err) {
@@ -1244,8 +1244,6 @@ fn expectEqualBytes(expected: []const u8, actual: []const u8, offset: usize) !vo
1244
1244
  }
1245
1245
  }
1246
1246
 
1247
- const endian = builtin.target.cpu.arch.endian();
1248
-
1249
1247
  fn N(e: anytype) u8 {
1250
1248
  return @intFromEnum(e);
1251
1249
  }
@@ -1253,20 +1251,13 @@ fn N(e: anytype) u8 {
1253
1251
  const p1 = Player.P1;
1254
1252
  const p2 = Player.P2;
1255
1253
 
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;
1254
+ var buf: [pkmn.LOGS_SIZE]u8 = undefined;
1267
1255
  var stream: ByteStream = .{ .buffer = &buf };
1268
1256
  var log: FixedLog = .{ .writer = stream.writer() };
1269
1257
 
1258
+ const gen1 = pkmn.gen1;
1259
+ const gen2 = pkmn.gen2;
1260
+
1270
1261
  const M1 = gen1.Move;
1271
1262
  const S1 = gen1.Species;
1272
1263
 
@@ -1355,8 +1346,8 @@ test "|switch|" {
1355
1346
  try log.switched(.{ p2.ident(3), &snorlax });
1356
1347
  const par = 0b1000000;
1357
1348
  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 },
1349
+ big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
1350
+ little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 200, 0, 144, 1, par },
1360
1351
  };
1361
1352
  try expectLog1(expected, buf[0..9]);
1362
1353
  stream.reset();
@@ -1366,8 +1357,8 @@ test "|switch|" {
1366
1357
  snorlax.status = 0;
1367
1358
  try log.switched(.{ p2.ident(3), &snorlax });
1368
1359
  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 },
1360
+ big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
1361
+ little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 144, 1, 0 },
1371
1362
  };
1372
1363
  try expectLog1(expected, buf[0..9]);
1373
1364
  stream.reset();
@@ -1375,8 +1366,8 @@ test "|switch|" {
1375
1366
  snorlax.hp = 400;
1376
1367
  try log.switched(.{ p2.ident(3), &snorlax });
1377
1368
  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 },
1369
+ big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
1370
+ little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 144, 1, 144, 1, 0 },
1380
1371
  };
1381
1372
  try expectLog1(expected, buf[0..9]);
1382
1373
  stream.reset();
@@ -1394,19 +1385,19 @@ test "|switch|" {
1394
1385
  N(gen2.Gender.Female),
1395
1386
  91,
1396
1387
  } ++ switch (endian) {
1397
- .Big => .{ 0, 200, 1, 144, par },
1398
- .Little => .{ 200, 0, 144, 1, par },
1388
+ big => .{ 0, 200, 1, 144, par },
1389
+ little => .{ 200, 0, 144, 1, par },
1399
1390
  });
1400
1391
  try expectLog2(expected, buf[0..10]);
1401
1392
  stream.reset();
1402
1393
  }
1403
1394
 
1404
1395
  test "|cant|" {
1405
- try log.cant(.{ p2.ident(6), Cant.Bound });
1396
+ try log.cant(.{ p2.ident(6), .Bound });
1406
1397
  try expectLog1(&.{ N(ArgType.Cant), 0b1110, N(Cant.Bound) }, buf[0..3]);
1407
1398
  stream.reset();
1408
1399
 
1409
- try log.cant(.{ p1.ident(2), Cant.Disable, M1.Earthquake });
1400
+ try log.cant(.{ p1.ident(2), .Disable, M1.Earthquake });
1410
1401
  try expectLog1(&.{ N(ArgType.Cant), 2, N(Cant.Disable), N(M1.Earthquake) }, buf[0..4]);
1411
1402
  stream.reset();
1412
1403
  }
@@ -1423,16 +1414,16 @@ test "|faint|" {
1423
1414
 
1424
1415
  test "|turn|" {
1425
1416
  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) },
1417
+ const expected = switch (endian) {
1418
+ big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
1419
+ little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
1429
1420
  };
1430
1421
  try expectLog1(expected, buf[0..4]);
1431
1422
  stream.reset();
1432
1423
  }
1433
1424
 
1434
1425
  test "|win|" {
1435
- try log.win(.{Player.P2});
1426
+ try log.win(.{.P2});
1436
1427
  try expectLog1(&.{ N(ArgType.Win), 1, N(ArgType.None) }, buf[0..3]);
1437
1428
  stream.reset();
1438
1429
  }
@@ -1447,10 +1438,10 @@ test "|-damage|" {
1447
1438
  var chansey = gen1.helpers.Pokemon.init(.{ .species = .Chansey, .moves = &.{.Splash} });
1448
1439
  chansey.hp = 612;
1449
1440
  chansey.status = gen1.Status.slp(1);
1450
- try log.damage(.{ p2.ident(2), &chansey, Damage.None });
1441
+ try log.damage(.{ p2.ident(2), &chansey, .None });
1451
1442
  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) },
1443
+ big => &.{ N(ArgType.Damage), 0b1010, 2, 100, 2, 191, 1, N(Damage.None) },
1444
+ little => &.{ N(ArgType.Damage), 0b1010, 100, 2, 191, 2, 1, N(Damage.None) },
1454
1445
  };
1455
1446
  try expectLog1(expected, buf[0..8]);
1456
1447
  stream.reset();
@@ -1458,19 +1449,19 @@ test "|-damage|" {
1458
1449
  chansey.hp = 100;
1459
1450
  chansey.stats.hp = 256;
1460
1451
  chansey.status = 0;
1461
- try log.damage(.{ p2.ident(2), &chansey, Damage.Confusion });
1452
+ try log.damage(.{ p2.ident(2), &chansey, .Confusion });
1462
1453
  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) },
1454
+ big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0, N(Damage.Confusion) },
1455
+ little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0, N(Damage.Confusion) },
1465
1456
  };
1466
1457
  try expectLog1(expected, buf[0..8]);
1467
1458
  stream.reset();
1468
1459
 
1469
1460
  chansey.status = gen1.Status.init(.PSN);
1470
- try log.damage(.{ p2.ident(2), &chansey, Damage.RecoilOf, p1.ident(1) });
1461
+ try log.damage(.{ p2.ident(2), &chansey, .RecoilOf, p1.ident(1) });
1471
1462
  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 },
1463
+ big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0b1000, N(Damage.RecoilOf), 1 },
1464
+ little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0b1000, N(Damage.RecoilOf), 1 },
1474
1465
  };
1475
1466
  try expectLog1(expected, buf[0..9]);
1476
1467
  stream.reset();
@@ -1480,10 +1471,10 @@ test "|-heal|" {
1480
1471
  var chansey = gen1.helpers.Pokemon.init(.{ .species = .Chansey, .moves = &.{.Splash} });
1481
1472
  chansey.hp = 612;
1482
1473
  chansey.status = gen1.Status.slp(1);
1483
- try log.heal(.{ p2.ident(2), &chansey, Heal.None });
1474
+ try log.heal(.{ p2.ident(2), &chansey, .None });
1484
1475
  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) },
1476
+ big => &.{ N(ArgType.Heal), 0b1010, 2, 100, 2, 191, 1, N(Heal.None) },
1477
+ little => &.{ N(ArgType.Heal), 0b1010, 100, 2, 191, 2, 1, N(Heal.None) },
1487
1478
  };
1488
1479
  try expectLog1(expected, buf[0..8]);
1489
1480
  stream.reset();
@@ -1491,33 +1482,33 @@ test "|-heal|" {
1491
1482
  chansey.hp = 100;
1492
1483
  chansey.stats.hp = 256;
1493
1484
  chansey.status = 0;
1494
- try log.heal(.{ p2.ident(2), &chansey, Heal.Silent });
1485
+ try log.heal(.{ p2.ident(2), &chansey, .Silent });
1495
1486
  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) },
1487
+ big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Silent) },
1488
+ little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Silent) },
1498
1489
  };
1499
1490
  try expectLog1(expected, buf[0..8]);
1500
1491
  stream.reset();
1501
1492
 
1502
- try log.heal(.{ p2.ident(2), &chansey, Heal.Drain, p1.ident(1) });
1493
+ try log.heal(.{ p2.ident(2), &chansey, .Drain, p1.ident(1) });
1503
1494
  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 },
1495
+ big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Drain), 1 },
1496
+ little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Drain), 1 },
1506
1497
  };
1507
1498
  try expectLog1(expected, buf[0..9]);
1508
1499
  stream.reset();
1509
1500
  }
1510
1501
 
1511
1502
  test "|-status|" {
1512
- try log.status(.{ p2.ident(6), gen1.Status.init(.BRN), Status.None });
1503
+ try log.status(.{ p2.ident(6), gen1.Status.init(.BRN), .None });
1513
1504
  try expectLog1(&.{ N(ArgType.Status), 0b1110, 0b10000, N(Status.None) }, buf[0..4]);
1514
1505
  stream.reset();
1515
1506
 
1516
- try log.status(.{ p2.ident(2), gen1.Status.init(.PSN), Status.Silent });
1507
+ try log.status(.{ p2.ident(2), gen1.Status.init(.PSN), .Silent });
1517
1508
  try expectLog1(&.{ N(ArgType.Status), 0b1010, 0b1000, N(Status.Silent) }, buf[0..4]);
1518
1509
  stream.reset();
1519
1510
 
1520
- try log.status(.{ p1.ident(1), gen1.Status.init(.PAR), Status.From, M1.BodySlam });
1511
+ try log.status(.{ p1.ident(1), gen1.Status.init(.PAR), .From, M1.BodySlam });
1521
1512
  try expectLog1(
1522
1513
  &.{ N(ArgType.Status), 0b0001, 0b1000000, N(Status.From), N(M1.BodySlam) },
1523
1514
  buf[0..5],
@@ -1526,11 +1517,11 @@ test "|-status|" {
1526
1517
  }
1527
1518
 
1528
1519
  test "|-curestatus|" {
1529
- try log.curestatus(.{ p2.ident(6), gen1.Status.slp(7), CureStatus.Message });
1520
+ try log.curestatus(.{ p2.ident(6), gen1.Status.slp(7), .Message });
1530
1521
  try expectLog1(&.{ N(ArgType.CureStatus), 0b1110, 0b111, N(CureStatus.Message) }, buf[0..4]);
1531
1522
  stream.reset();
1532
1523
 
1533
- try log.curestatus(.{ p1.ident(2), gen1.Status.TOX, CureStatus.Silent });
1524
+ try log.curestatus(.{ p1.ident(2), gen1.Status.TOX, .Silent });
1534
1525
  try expectLog1(&.{
1535
1526
  N(ArgType.CureStatus),
1536
1527
  0b0010,
@@ -1541,15 +1532,15 @@ test "|-curestatus|" {
1541
1532
  }
1542
1533
 
1543
1534
  test "|-boost|" {
1544
- try log.boost(.{ p2.ident(6), Boost.Speed, 2 });
1535
+ try log.boost(.{ p2.ident(6), .Speed, 2 });
1545
1536
  try expectLog1(&.{ N(ArgType.Boost), 0b1110, N(Boost.Speed), 8 }, buf[0..4]);
1546
1537
  stream.reset();
1547
1538
 
1548
- try log.boost(.{ p1.ident(2), Boost.Rage, 1 });
1539
+ try log.boost(.{ p1.ident(2), .Rage, 1 });
1549
1540
  try expectLog1(&.{ N(ArgType.Boost), 0b0010, N(Boost.Rage), 7 }, buf[0..4]);
1550
1541
  stream.reset();
1551
1542
 
1552
- try log.boost(.{ p2.ident(3), Boost.Defense, -2 });
1543
+ try log.boost(.{ p2.ident(3), .Defense, -2 });
1553
1544
  try expectLog1(&.{ N(ArgType.Boost), 0b1011, N(Boost.Defense), 4 }, buf[0..4]);
1554
1545
  stream.reset();
1555
1546
  }
@@ -1561,19 +1552,19 @@ test "|-clearallboost|" {
1561
1552
  }
1562
1553
 
1563
1554
  test "|-fail|" {
1564
- try log.fail(.{ p2.ident(6), Fail.None });
1555
+ try log.fail(.{ p2.ident(6), .None });
1565
1556
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.None) }, buf[0..3]);
1566
1557
  stream.reset();
1567
1558
 
1568
- try log.fail(.{ p2.ident(6), Fail.Sleep });
1559
+ try log.fail(.{ p2.ident(6), .Sleep });
1569
1560
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Sleep) }, buf[0..3]);
1570
1561
  stream.reset();
1571
1562
 
1572
- try log.fail(.{ p2.ident(6), Fail.Substitute });
1563
+ try log.fail(.{ p2.ident(6), .Substitute });
1573
1564
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Substitute) }, buf[0..3]);
1574
1565
  stream.reset();
1575
1566
 
1576
- try log.fail(.{ p2.ident(6), Fail.Weak });
1567
+ try log.fail(.{ p2.ident(6), .Weak });
1577
1568
  try expectLog1(&.{ N(ArgType.Fail), 0b1110, N(Fail.Weak) }, buf[0..3]);
1578
1569
  stream.reset();
1579
1570
  }
@@ -1602,25 +1593,32 @@ test "|-mustrecharge|" {
1602
1593
  }
1603
1594
 
1604
1595
  test "|-activate|" {
1605
- try log.activate(p1.ident(2), .Struggle);
1596
+ try log.activate(.{ p1.ident(2), .Struggle });
1606
1597
  try expectLog1(&.{ N(ArgType.Activate), 0b0010, N(Activate.Struggle) }, buf[0..3]);
1607
1598
  stream.reset();
1608
1599
 
1609
- try log.activate(p2.ident(4), .Mist);
1600
+ try log.activate(.{ p2.ident(4), .Mist });
1610
1601
  try expectLog1(&.{ N(ArgType.Activate), 0b1100, N(Activate.Mist) }, buf[0..3]);
1611
1602
  stream.reset();
1612
1603
 
1613
- try log.activate(p2.ident(6), .Substitute);
1604
+ try log.activate(.{ p2.ident(6), .Substitute });
1614
1605
  try expectLog1(&.{ N(ArgType.Activate), 0b1110, N(Activate.Substitute) }, buf[0..3]);
1615
1606
  stream.reset();
1616
1607
 
1617
- try log.activate(p1.ident(2), .Splash);
1608
+ try log.activate(.{ p1.ident(2), .Splash });
1618
1609
  try expectLog1(&.{ N(ArgType.Activate), 0b0010, N(Activate.Splash) }, buf[0..3]);
1619
1610
  stream.reset();
1620
1611
 
1621
- // TODO activateMove
1612
+ try log.activate(.{ p1.ident(4), .SubstituteBlock, M2.Spite });
1613
+ try expectLog1(&.{
1614
+ N(ArgType.Activate),
1615
+ 0b0100,
1616
+ N(Activate.SubstituteBlock),
1617
+ N(M2.Spite),
1618
+ }, buf[0..4]);
1619
+ stream.reset();
1622
1620
 
1623
- try log.magnitude(p1.ident(3), 5);
1621
+ try log.activate(.{ p1.ident(3), .Magnitude, 5 });
1624
1622
  try expectLog1(&.{ N(ArgType.Activate), 0b0011, N(Activate.Magnitude), 5 }, buf[0..4]);
1625
1623
  stream.reset();
1626
1624
  }
@@ -1632,43 +1630,53 @@ test "|-fieldactivate|" {
1632
1630
  }
1633
1631
 
1634
1632
  test "|-start|" {
1635
- try log.start(p2.ident(6), .Bide);
1633
+ try log.start(.{ p2.ident(6), .Bide });
1636
1634
  try expectLog1(&.{ N(ArgType.Start), 0b1110, N(Start.Bide) }, buf[0..3]);
1637
1635
  stream.reset();
1638
1636
 
1639
- try log.start(p1.ident(2), .ConfusionSilent);
1637
+ try log.start(.{ p1.ident(2), .ConfusionSilent });
1640
1638
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.ConfusionSilent) }, buf[0..3]);
1641
1639
  stream.reset();
1642
1640
 
1643
- try log.typechange(p2.ident(6), gen1.Types{ .type1 = .Fire, .type2 = .Fire }, p2.ident(5));
1641
+ try log.start(.{
1642
+ p2.ident(6),
1643
+ .TypeChange,
1644
+ gen1.Types{ .type1 = .Fire, .type2 = .Fire },
1645
+ p2.ident(5),
1646
+ });
1644
1647
  try expectLog1(
1645
1648
  &.{ N(ArgType.Start), 0b1110, N(Start.TypeChange), 0b1000_1000, 0b1101 },
1646
1649
  buf[0..5],
1647
1650
  );
1648
1651
  stream.reset();
1649
1652
 
1650
- try log.typechange(p1.ident(2), gen1.Types{ .type1 = .Bug, .type2 = .Poison }, p2.ident(4));
1653
+ try log.start(.{
1654
+ p1.ident(2),
1655
+ .TypeChange,
1656
+ gen1.Types{ .type1 = .Bug, .type2 = .Poison },
1657
+ p2.ident(4),
1658
+ });
1651
1659
  try expectLog1(
1652
1660
  &.{ N(ArgType.Start), 0b0010, N(Start.TypeChange), 0b0011_0110, 0b1100 },
1653
1661
  buf[0..5],
1654
1662
  );
1655
1663
  stream.reset();
1656
1664
 
1657
- try log.startEffect(p1.ident(2), .Disable, M1.Surf);
1665
+ try log.start(.{ p1.ident(2), .Disable, M1.Surf });
1658
1666
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Disable), N(M1.Surf) }, buf[0..4]);
1659
1667
  stream.reset();
1660
1668
 
1661
- try log.startEffect(p1.ident(2), .Mimic, M1.Surf);
1669
+ try log.start(.{ p1.ident(2), .Mimic, M1.Surf });
1662
1670
  try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Mimic), N(M1.Surf) }, buf[0..4]);
1663
1671
  stream.reset();
1664
1672
  }
1665
1673
 
1666
1674
  test "|-end|" {
1667
- try log.end(.{ p2.ident(6), End.Bide });
1675
+ try log.end(.{ p2.ident(6), .Bide });
1668
1676
  try expectLog1(&.{ N(ArgType.End), 0b1110, N(End.Bide) }, buf[0..3]);
1669
1677
  stream.reset();
1670
1678
 
1671
- try log.end(.{ p1.ident(2), End.ConfusionSilent });
1679
+ try log.end(.{ p1.ident(2), .ConfusionSilent });
1672
1680
  try expectLog1(&.{ N(ArgType.End), 0b0010, N(End.ConfusionSilent) }, buf[0..3]);
1673
1681
  stream.reset();
1674
1682
  }
@@ -1698,11 +1706,11 @@ test "|-resisted|" {
1698
1706
  }
1699
1707
 
1700
1708
  test "|-immune|" {
1701
- try log.immune(.{ p1.ident(3), Immune.None });
1709
+ try log.immune(.{ p1.ident(3), .None });
1702
1710
  try expectLog1(&.{ N(ArgType.Immune), 0b0011, N(Immune.None) }, buf[0..3]);
1703
1711
  stream.reset();
1704
1712
 
1705
- try log.immune(.{ p2.ident(2), Immune.OHKO });
1713
+ try log.immune(.{ p2.ident(2), .OHKO });
1706
1714
  try expectLog1(&.{ N(ArgType.Immune), 0b1010, N(Immune.OHKO) }, buf[0..3]);
1707
1715
  stream.reset();
1708
1716
  }
@@ -1728,8 +1736,8 @@ test "|drag|" {
1728
1736
  N(gen2.Gender.Female),
1729
1737
  91,
1730
1738
  } ++ switch (endian) {
1731
- .Big => .{ 0, 200, 1, 144, par },
1732
- .Little => .{ 200, 0, 144, 1, par },
1739
+ big => .{ 0, 200, 1, 144, par },
1740
+ little => .{ 200, 0, 144, 1, par },
1733
1741
  });
1734
1742
  try expectLog2(expected, buf[0..10]);
1735
1743
  stream.reset();
@@ -1742,11 +1750,11 @@ test "|-item|" {
1742
1750
  }
1743
1751
 
1744
1752
  test "|-enditem|" {
1745
- try log.enditem(.{ p1.ident(1), I2.BerserkGene, EndItem.None });
1753
+ try log.enditem(.{ p1.ident(1), I2.BerserkGene, .None });
1746
1754
  try expectLog2(&.{ N(ArgType.EndItem), 0b0001, N(I2.BerserkGene), N(EndItem.None) }, buf[0..4]);
1747
1755
  stream.reset();
1748
1756
 
1749
- try log.enditem(.{ p2.ident(4), I2.PRZCureBerry, EndItem.Eat });
1757
+ try log.enditem(.{ p2.ident(4), I2.PRZCureBerry, .Eat });
1750
1758
  try expectLog2(&.{ N(ArgType.EndItem), 0b1100, N(I2.PRZCureBerry), N(EndItem.Eat) }, buf[0..4]);
1751
1759
  stream.reset();
1752
1760
  }
@@ -1760,10 +1768,10 @@ test "|-cureteam|" {
1760
1768
  test "|-sethp|" {
1761
1769
  var blissey = gen2.helpers.Pokemon.init(.{ .species = .Blissey, .moves = &.{.PainSplit} });
1762
1770
  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) },
1771
+ try log.sethp(.{ p2.ident(2), &blissey, .Silent });
1772
+ const expected: []const u8 = switch (endian) {
1773
+ big => &.{ N(ArgType.SetHP), 0b1010, 2, 100, 2, 201, 0, N(SetHP.Silent) },
1774
+ little => &.{ N(ArgType.SetHP), 0b1010, 100, 2, 201, 2, 0, N(SetHP.Silent) },
1767
1775
  };
1768
1776
  try expectLog2(expected, buf[0..8]);
1769
1777
  stream.reset();
@@ -1786,17 +1794,17 @@ test "|-copyboost|" {
1786
1794
  }
1787
1795
 
1788
1796
  test "|-sidestart|" {
1789
- try log.sidestart(.{ Player.P2, Side.Reflect });
1797
+ try log.sidestart(.{ .P2, .Reflect });
1790
1798
  try expectLog2(&.{ N(ArgType.SideStart), 1, N(Side.Reflect) }, buf[0..3]);
1791
1799
  stream.reset();
1792
1800
  }
1793
1801
 
1794
1802
  test "|-sideend|" {
1795
- try log.sideend(.{ Player.P2, Side.LightScreen });
1803
+ try log.sideend(.{ .P2, .LightScreen });
1796
1804
  try expectLog2(&.{ N(ArgType.SideEnd), 1, N(Side.LightScreen) }, buf[0..3]);
1797
1805
  stream.reset();
1798
1806
 
1799
- try log.sideend(.{ Player.P1, Side.Spikes, p1.ident(3) });
1807
+ try log.sideend(.{ .P1, .Spikes, p1.ident(3) });
1800
1808
  try expectLog2(&.{
1801
1809
  N(ArgType.SideEnd),
1802
1810
  0,
@@ -1819,11 +1827,11 @@ test "|-singleturn|" {
1819
1827
  }
1820
1828
 
1821
1829
  test "|-weather|" {
1822
- try log.weather(.{ W2.Rain, Weather.Upkeep });
1830
+ try log.weather(.{ W2.Rain, .Upkeep });
1823
1831
  try expectLog2(&.{ N(ArgType.Weather), N(W2.Rain), N(Weather.Upkeep) }, buf[0..3]);
1824
1832
  stream.reset();
1825
1833
 
1826
- try log.weather(.{ W2.None, Weather.None });
1834
+ try log.weather(.{ W2.None, .None });
1827
1835
  try expectLog2(&.{ N(ArgType.Weather), N(W2.None), N(Weather.None) }, buf[0..3]);
1828
1836
  stream.reset();
1829
1837
  }