@pkmn/engine 0.1.0-dev.9f75c7ae → 0.1.0-dev.a0167a9d

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