@pkmn/engine 0.1.0-dev.305a932f → 0.1.0-dev.30895c5a

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