@pkmn/engine 0.1.0-dev.a93847b2 → 0.1.0-dev.ac652f4e

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