@pkmn/engine 0.1.0-dev.90d6c14c → 0.1.0-dev.9257876b

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 (48) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +52 -21
  3. package/build/pkg/addon.js.map +1 -1
  4. package/build/pkg/data/ids.json +12 -12
  5. package/build/pkg/data/layout.json +2 -2
  6. package/build/pkg/data/protocol.json +69 -12
  7. package/build/pkg/data.d.ts +3 -2
  8. package/build/pkg/data.js.map +1 -1
  9. package/build/pkg/gen1.js +2 -2
  10. package/build/pkg/gen1.js.map +1 -1
  11. package/build/pkg/index.d.ts +2 -1
  12. package/build/pkg/index.js.map +1 -1
  13. package/build/pkg/protocol.js +57 -38
  14. package/build/pkg/protocol.js.map +1 -1
  15. package/build/test/display.js.map +1 -1
  16. package/build/tools/debug.js +3 -1
  17. package/build/tools/debug.js.map +1 -1
  18. package/build.zig +125 -102
  19. package/package.json +43 -23
  20. package/src/bin/install-pkmn-engine +27 -19
  21. package/src/lib/common/data.zig +12 -24
  22. package/src/lib/common/optional.zig +9 -2
  23. package/src/lib/common/protocol.zig +805 -327
  24. package/src/lib/common/rational.zig +12 -8
  25. package/src/lib/common/rng.zig +26 -17
  26. package/src/lib/gen1/calc.zig +9 -10
  27. package/src/lib/gen1/chance.zig +83 -66
  28. package/src/lib/gen1/data/moves.zig +192 -180
  29. package/src/lib/gen1/data/species.zig +3 -3
  30. package/src/lib/gen1/data/types.zig +7 -7
  31. package/src/lib/gen1/data.zig +60 -67
  32. package/src/lib/gen1/helpers.zig +261 -123
  33. package/src/lib/gen1/mechanics.zig +370 -403
  34. package/src/lib/gen2/calc.zig +143 -0
  35. package/src/lib/gen2/chance.zig +1315 -0
  36. package/src/lib/gen2/data/items.zig +12 -18
  37. package/src/lib/gen2/data/moves.zig +663 -569
  38. package/src/lib/gen2/data/species.zig +1 -1
  39. package/src/lib/gen2/data/types.zig +134 -31
  40. package/src/lib/gen2/data.zig +106 -79
  41. package/src/lib/gen2/generated.zig +806 -0
  42. package/src/lib/gen2/helpers.zig +8 -12
  43. package/src/lib/gen2/mechanics.zig +3587 -9
  44. package/src/lib/{binding/node.zig → node.zig} +10 -13
  45. package/src/lib/pkmn.zig +26 -3
  46. package/src/lib/{binding/wasm.zig → wasm.zig} +2 -1
  47. package/src/lib/gen1/README.md +0 -812
  48. package/src/lib/gen2/README.md +0 -308
@@ -266,7 +266,7 @@ pub const Rolls = struct {
266
266
  const PLAYERS = [_]Optional(Player){ .P1, .P2 };
267
267
 
268
268
  /// Returns a slice with the correct range of values for speed ties given the `action` state.
269
- pub inline fn speedTie(action: Action) []const Optional(Player) {
269
+ pub fn speedTie(action: Action) []const Optional(Player) {
270
270
  return if (@field(action, "speed_tie") == .None) &PLAYER_NONE else &PLAYERS;
271
271
  }
272
272
 
@@ -275,14 +275,14 @@ pub const Rolls = struct {
275
275
 
276
276
  /// Returns a slice with the correct range of values for hits given the `action` state
277
277
  /// and the state of the `parent` (whether the player's Pokémon was fully paralyzed).
278
- pub inline fn hit(action: Action, parent: Optional(bool)) []const Optional(bool) {
278
+ pub fn hit(action: Action, parent: Optional(bool)) []const Optional(bool) {
279
279
  if (parent == .true) return &BOOL_NONE;
280
280
  return if (@field(action, "hit") == .None) &BOOL_NONE else &BOOLS;
281
281
  }
282
282
 
283
283
  /// Returns a slice with the correct range of values for critical hits given the `action` state
284
284
  /// and the state of the `parent` (whether the player's Pokémon's move hit).
285
- pub inline fn criticalHit(
285
+ pub fn criticalHit(
286
286
  action: Action,
287
287
  parent: Optional(bool),
288
288
  ) []const Optional(bool) {
@@ -292,7 +292,7 @@ pub const Rolls = struct {
292
292
 
293
293
  /// Returns a slice with the correct range of values for secondary chances hits given the
294
294
  /// `action` state and the state of the `parent` (whether the player's Pokémon's move hit).
295
- pub inline fn secondaryChance(
295
+ pub fn secondaryChance(
296
296
  action: Action,
297
297
  parent: Optional(bool),
298
298
  ) []const Optional(bool) {
@@ -305,7 +305,7 @@ pub const Rolls = struct {
305
305
 
306
306
  /// Returns the range bounding damage rolls given the `action` state and the state of
307
307
  /// the `parent` (whether the player's Pokémon's move hit).
308
- pub inline fn damage(action: Action, parent: Optional(bool)) Range {
308
+ pub fn damage(action: Action, parent: Optional(bool)) Range {
309
309
  return if (parent == .false or @field(action, "damage") == 0)
310
310
  .{ .min = 0, .max = 1 }
311
311
  else
@@ -314,7 +314,7 @@ pub const Rolls = struct {
314
314
 
315
315
  /// Returns the max damage roll which will produce the same damage as `roll`
316
316
  /// given the base damage in `summaries`.
317
- pub inline fn coalesce(player: Player, roll: u8, summaries: *calc.Summaries, cap: bool) !u8 {
317
+ pub fn coalesce(player: Player, roll: u8, summaries: *calc.Summaries, cap: bool) !u8 {
318
318
  if (roll == 0) return roll;
319
319
 
320
320
  const dmg = summaries.get(player.foe()).damage;
@@ -326,13 +326,13 @@ pub const Rolls = struct {
326
326
 
327
327
  /// Returns a slice with the correct range of values for confused given the `action` state
328
328
  /// and the state of the `parent` (the player's Pokémon's remaining confusion turns).
329
- pub inline fn confused(action: Action, parent: u4) []const Optional(bool) {
329
+ pub fn confused(action: Action, parent: u4) []const Optional(bool) {
330
330
  return if (parent == 0 or @field(action, "confused") == .None) &BOOL_NONE else &BOOLS;
331
331
  }
332
332
 
333
333
  /// Returns a slice with the correct range of values for paralysis given the `action` state
334
334
  /// and the state of the `parent` (whether the player's Pokémon was confused).
335
- pub inline fn paralyzed(action: Action, parent: Optional(bool)) []const Optional(bool) {
335
+ pub fn paralyzed(action: Action, parent: Optional(bool)) []const Optional(bool) {
336
336
  if (parent == .true) return &BOOL_NONE;
337
337
  return if (@field(action, "paralyzed") == .None) &BOOL_NONE else &BOOLS;
338
338
  }
@@ -342,7 +342,7 @@ pub const Rolls = struct {
342
342
 
343
343
  /// Returns a slice with a range of values for duration given the `action` state
344
344
  /// and the state of the `parent` (whether the player's Pokémon's move hit).
345
- pub inline fn duration(action: Action, parent: Optional(bool)) []const u1 {
345
+ pub fn duration(action: Action, parent: Optional(bool)) []const u1 {
346
346
  if (parent == .false) return &DURATION_NONE;
347
347
  return if (@field(action, "duration") == 0) &DURATION_NONE else &DURATION;
348
348
  }
@@ -350,47 +350,65 @@ pub const Rolls = struct {
350
350
  const U3_NONE = [_]u3{0};
351
351
  const U3_FORCED = [_]u3{1};
352
352
 
353
- /// Returns a slice with a range of values for sleep given the `action` state.
353
+ /// Returns a slice with a range of values for sleep given the `action` and `origin` states.
354
354
  pub inline fn sleep(action: Action, origin: Action) []const u3 {
355
- const turns = @field(action.durations, "sleep");
356
- _ = origin;
357
- return if (turns < 1 or turns >= 7) &U3_NONE else &[_]u3{ 0, turns };
355
+ const a = @field(action.durations, "sleep");
356
+ const o = @field(origin.durations, "sleep");
357
+ if (o == a) return if (o == 0) &U3_NONE else &[_]u3{o};
358
+ assert(a == 0 or a == o + 1);
359
+ return if (o >= 7) &U3_NONE else &[_]u3{ 0, o + 1 };
358
360
  }
359
361
 
360
362
  const DISABLE_NONE = [_]u4{0};
361
363
 
362
- /// Returns a slice with a range of values for disable given the `action` state
364
+ /// Returns a slice with a range of values for disable given the `action` and `origin` states
363
365
  /// and the state of the `parent` (the player's Pokémon's remaining sleep turns).
364
366
  pub inline fn disable(action: Action, origin: Action, parent: u4) []const u4 {
365
- const turns = @field(action.durations, "disable");
366
- _ = origin;
367
- return if (parent > 0 or turns < 1 or turns >= 8) &DISABLE_NONE else &[_]u4{ 0, turns };
367
+ if (parent > 0) return &DISABLE_NONE;
368
+ const a = @field(action.durations, "disable");
369
+ const o = @field(origin.durations, "disable");
370
+ if (o == a) return if (o == 0) &DISABLE_NONE else &[_]u4{o};
371
+ assert(a == 0 or a == o + 1);
372
+ return if (o >= 8) &DISABLE_NONE else &[_]u4{ 0, o + 1 };
368
373
  }
369
374
 
370
- /// Returns a slice with a range of values for confusion given the `action` state
375
+ /// Returns a slice with a range of values for confusion given the `action` and `origin` states
371
376
  /// and the state of the `parent` (the player's remaining sleep turns).
372
377
  pub inline fn confusion(action: Action, origin: Action, parent: u4) []const u3 {
373
- const turns = @field(action.durations, "confusion");
374
- _ = origin;
375
- if (parent > 0 or turns < 1 or turns >= 5) return &U3_NONE;
376
- return if (turns < 2) &U3_FORCED else &[_]u3{ 0, turns };
378
+ if (parent > 0) return &U3_NONE;
379
+ const a = @field(action.durations, "confusion");
380
+ const o = @field(origin.durations, "confusion");
381
+ if (o == a) return if (o == 0) &U3_NONE else &[_]u3{o};
382
+ assert(a == 0 or a == o + 1);
383
+ return if (o >= 5) &U3_NONE else if (o < 2)
384
+ if (a == 0) &U3_NONE else &U3_FORCED
385
+ else
386
+ &[_]u3{ 0, o + 1 };
377
387
  }
378
388
 
379
- /// Returns a slice with a range of values for attacking given the `action` state
389
+ /// Returns a slice with a range of values for attacking given the `action` and `origin` states
380
390
  /// and the state of the `parent` (whether the player's Pokémon was fully paralyzed).
381
391
  pub inline fn attacking(action: Action, origin: Action, parent: Optional(bool)) []const u3 {
382
- const turns = @field(action.durations, "attacking");
383
- _ = origin;
384
- if (parent == .true or turns < 1 or turns >= 3) return &U3_NONE;
385
- return if (turns < 2) &U3_FORCED else &[_]u3{ 0, turns };
392
+ if (parent == .true) return &U3_NONE;
393
+ const a = @field(action.durations, "attacking");
394
+ const o = @field(origin.durations, "attacking");
395
+ if (o == a) return if (o == 0) &U3_NONE else &[_]u3{o};
396
+ assert(a == 0 or a == o + 1);
397
+ return if (o >= 3) &U3_NONE else if (o < 2)
398
+ if (a == 0) &U3_NONE else &U3_FORCED
399
+ else
400
+ &[_]u3{ 0, o + 1 };
386
401
  }
387
402
 
388
- /// Returns a slice with a range of values for binding given the `action` state
403
+ /// Returns a slice with a range of values for binding given the `action` and `origin` states
389
404
  /// and the state of the `parent` (whether the player's Pokémon was fully paralyzed).
390
405
  pub inline fn binding(action: Action, origin: Action, parent: Optional(bool)) []const u3 {
391
- const turns = @field(action.durations, "binding");
392
- _ = origin;
393
- return if (parent == .true or turns < 1 or turns >= 4) &U3_NONE else &[_]u3{ 0, turns };
406
+ if (parent == .true) return &U3_NONE;
407
+ const a = @field(action.durations, "binding");
408
+ const o = @field(origin.durations, "binding");
409
+ if (o == a) return if (o == 0) &U3_NONE else &[_]u3{o};
410
+ assert(a == 0 or a == o + 1);
411
+ return if (o >= 4) &U3_NONE else &[_]u3{ 0, o + 1 };
394
412
  }
395
413
 
396
414
  const SLOT_NONE = [_]u4{0};
@@ -400,7 +418,7 @@ pub const Rolls = struct {
400
418
  /// and the state of the `parent` (whether the player's Pokémon's move hit).
401
419
  ///
402
420
  /// These slots may or **may not be valid** as slots may be unset / have 0 PP.
403
- pub inline fn moveSlot(action: Action, parent: Optional(bool)) []const u4 {
421
+ pub fn moveSlot(action: Action, parent: Optional(bool)) []const u4 {
404
422
  if (parent == .false) return &SLOT_NONE;
405
423
  return if (@field(action, "move_slot") == 0) &SLOT_NONE else &SLOT;
406
424
  }
@@ -410,7 +428,7 @@ pub const Rolls = struct {
410
428
 
411
429
  /// Returns a slice with the correct range of values for multi hit given the `action` state
412
430
  /// and the state of the `parent` (whether the player's Pokémon's move hit).
413
- pub inline fn multiHit(action: Action, parent: Optional(bool)) []const u4 {
431
+ pub fn multiHit(action: Action, parent: Optional(bool)) []const u4 {
414
432
  if (parent == .false) return &MULTI_NONE;
415
433
  return if (@field(action, "multi_hit") == 0) &MULTI_NONE else &MULTI;
416
434
  }
@@ -424,7 +442,7 @@ pub const Rolls = struct {
424
442
 
425
443
  /// Returns a slice with the correct range of values for psywave given the `action` state,
426
444
  /// the `side`, and the state of the `parent` (whether the player's Pokémon's move hit).
427
- pub inline fn psywave(
445
+ pub fn psywave(
428
446
  action: Action,
429
447
  side: *data.Side,
430
448
  parent: Optional(bool),
@@ -437,36 +455,21 @@ pub const Rolls = struct {
437
455
  }
438
456
 
439
457
  const MOVE_NONE = [_]Move{.None};
440
- const MOVES = init: {
441
- var moves: [Move.size - 2]Move = undefined;
442
- var i: usize = 0;
443
- for (@typeInfo(Move).Enum.fields) |f| {
444
- if (!(std.mem.eql(u8, f.name, "None") or
445
- std.mem.eql(u8, f.name, "Metronome") or
446
- std.mem.eql(u8, f.name, "Struggle") or
447
- std.mem.eql(u8, f.name, "SKIP_TURN")))
448
- {
449
- moves[i] = @field(Move, f.name);
450
- i += 1;
451
- }
452
- }
453
- break :init moves;
454
- };
455
458
 
456
459
  /// Returns a slice with the correct range of values for metronome given the `action` state.
457
- pub inline fn metronome(action: Action) []const Move {
458
- return if (@field(action, "metronome") == .None) &MOVE_NONE else &MOVES;
460
+ pub fn metronome(action: Action) []const Move {
461
+ return if (@field(action, "metronome") == .None) &MOVE_NONE else &Move.METRONOME;
459
462
  }
460
463
  };
461
464
 
462
465
  test "Rolls.speedTie" {
463
- const actions = Actions{ .p1 = .{ .speed_tie = .P2 } };
466
+ const actions: Actions = .{ .p1 = .{ .speed_tie = .P2 } };
464
467
  try expectEqualSlices(Optional(Player), &.{ .P1, .P2 }, Rolls.speedTie(actions.p1));
465
468
  try expectEqualSlices(Optional(Player), &.{.None}, Rolls.speedTie(actions.p2));
466
469
  }
467
470
 
468
471
  test "Rolls.damage" {
469
- const actions = Actions{ .p2 = .{ .damage = 221 } };
472
+ const actions: Actions = .{ .p2 = .{ .damage = 221 } };
470
473
  try expectEqual(Rolls.Range{ .min = 0, .max = 1 }, Rolls.damage(actions.p1, .None));
471
474
  try expectEqual(Rolls.Range{ .min = 217, .max = 256 }, Rolls.damage(actions.p2, .None));
472
475
  try expectEqual(Rolls.Range{ .min = 0, .max = 1 }, Rolls.damage(actions.p2, .false));
@@ -475,16 +478,16 @@ test "Rolls.damage" {
475
478
  test "Rolls.coalesce" {
476
479
  var summaries =
477
480
  calc.Summaries{ .p1 = .{ .damage = .{ .base = 74, .final = 69, .capped = true } } };
478
- try expectEqual(@as(u8, 0), try Rolls.coalesce(.P2, 0, &summaries, false));
479
- try expectEqual(@as(u8, 241), try Rolls.coalesce(.P2, 238, &summaries, false));
480
- try expectEqual(@as(u8, 255), try Rolls.coalesce(.P2, 238, &summaries, true));
481
+ try expectEqual(0, try Rolls.coalesce(.P2, 0, &summaries, false));
482
+ try expectEqual(241, try Rolls.coalesce(.P2, 238, &summaries, false));
483
+ try expectEqual(255, try Rolls.coalesce(.P2, 238, &summaries, true));
481
484
  summaries.p1.damage.final = 74;
482
- try expectEqual(@as(u8, 217), try Rolls.coalesce(.P2, 217, &summaries, false));
483
- try expectEqual(@as(u8, 255), try Rolls.coalesce(.P2, 217, &summaries, true));
485
+ try expectEqual(217, try Rolls.coalesce(.P2, 217, &summaries, false));
486
+ try expectEqual(255, try Rolls.coalesce(.P2, 217, &summaries, true));
484
487
  }
485
488
 
486
489
  test "Rolls.hit" {
487
- const actions = Actions{ .p2 = .{ .hit = .true } };
490
+ const actions: Actions = .{ .p2 = .{ .hit = .true } };
488
491
  try expectEqualSlices(Optional(bool), &.{.None}, Rolls.hit(actions.p1, .None));
489
492
  try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.hit(actions.p2, .None));
490
493
  try expectEqualSlices(Optional(bool), &.{.None}, Rolls.hit(actions.p2, .true));
@@ -492,7 +495,7 @@ test "Rolls.hit" {
492
495
  }
493
496
 
494
497
  test "Rolls.secondaryChance" {
495
- const actions = Actions{ .p1 = .{ .secondary_chance = .true } };
498
+ const actions: Actions = .{ .p1 = .{ .secondary_chance = .true } };
496
499
  try expectEqualSlices(
497
500
  Optional(bool),
498
501
  &.{ .false, .true },
@@ -503,7 +506,7 @@ test "Rolls.secondaryChance" {
503
506
  }
504
507
 
505
508
  test "Rolls.criticalHit" {
506
- const actions = Actions{ .p1 = .{ .critical_hit = .true } };
509
+ const actions: Actions = .{ .p1 = .{ .critical_hit = .true } };
507
510
  try expectEqualSlices(
508
511
  Optional(bool),
509
512
  &.{ .false, .true },
@@ -514,14 +517,14 @@ test "Rolls.criticalHit" {
514
517
  }
515
518
 
516
519
  test "Rolls.confused" {
517
- const actions = Actions{ .p2 = .{ .confused = .true } };
520
+ const actions: Actions = .{ .p2 = .{ .confused = .true } };
518
521
  try expectEqualSlices(Optional(bool), &.{.None}, Rolls.confused(actions.p1, 1));
519
522
  try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.confused(actions.p2, 1));
520
523
  try expectEqualSlices(Optional(bool), &.{.None}, Rolls.confused(actions.p2, 0));
521
524
  }
522
525
 
523
526
  test "Rolls.paralyzed" {
524
- const actions = Actions{ .p2 = .{ .paralyzed = .true } };
527
+ const actions: Actions = .{ .p2 = .{ .paralyzed = .true } };
525
528
  try expectEqualSlices(Optional(bool), &.{.None}, Rolls.paralyzed(actions.p1, .None));
526
529
  try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.paralyzed(actions.p2, .None));
527
530
  try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.paralyzed(actions.p2, .false));
@@ -529,102 +532,237 @@ test "Rolls.paralyzed" {
529
532
  }
530
533
 
531
534
  test "Rolls.duration" {
532
- const actions = Actions{ .p2 = .{ .duration = 3 } };
535
+ const actions: Actions = .{ .p2 = .{ .duration = 3 } };
533
536
  try expectEqualSlices(u1, &.{0}, Rolls.duration(actions.p1, .None));
534
537
  try expectEqualSlices(u1, &.{1}, Rolls.duration(actions.p2, .None));
535
538
  try expectEqualSlices(u1, &.{0}, Rolls.duration(actions.p2, .false));
536
539
  }
537
540
 
538
- const FIXME: Action = .{};
539
-
540
541
  test "Rolls.sleep" {
541
- try expectEqualSlices(u3, &.{0}, Rolls.sleep(.{ .durations = .{ .sleep = 0 } }, FIXME));
542
- try expectEqualSlices(u3, &.{0}, Rolls.sleep(.{ .durations = .{ .sleep = 7 } }, FIXME));
543
- try expectEqualSlices(u3, &.{ 0, 4 }, Rolls.sleep(.{ .durations = .{ .sleep = 4 } }, FIXME));
542
+ try expectEqualSlices(u3, &.{0}, Rolls.sleep(
543
+ .{ .durations = .{ .sleep = 0 } },
544
+ .{ .durations = .{ .sleep = 0 } },
545
+ ));
546
+ try expectEqualSlices(u3, &.{ 0, 1 }, Rolls.sleep(
547
+ .{ .durations = .{ .sleep = 1 } },
548
+ .{ .durations = .{ .sleep = 0 } },
549
+ ));
550
+ try expectEqualSlices(u3, &.{ 0, 2 }, Rolls.sleep(
551
+ .{ .durations = .{ .sleep = 0 } },
552
+ .{ .durations = .{ .sleep = 1 } },
553
+ ));
554
+ try expectEqualSlices(u3, &.{1}, Rolls.sleep(
555
+ .{ .durations = .{ .sleep = 1 } },
556
+ .{ .durations = .{ .sleep = 1 } },
557
+ ));
558
+ try expectEqualSlices(u3, &.{ 0, 3 }, Rolls.sleep(
559
+ .{ .durations = .{ .sleep = 0 } },
560
+ .{ .durations = .{ .sleep = 2 } },
561
+ ));
562
+ try expectEqualSlices(u3, &.{ 0, 7 }, Rolls.sleep(
563
+ .{ .durations = .{ .sleep = 7 } },
564
+ .{ .durations = .{ .sleep = 6 } },
565
+ ));
566
+ try expectEqualSlices(u3, &.{0}, Rolls.sleep(
567
+ .{ .durations = .{ .sleep = 0 } },
568
+ .{ .durations = .{ .sleep = 7 } },
569
+ ));
544
570
  }
545
571
 
546
572
  test "Rolls.disable" {
547
- try expectEqualSlices(u4, &.{0}, Rolls.disable(.{ .durations = .{ .disable = 0 } }, FIXME, 0));
548
- try expectEqualSlices(u4, &.{0}, Rolls.disable(.{ .durations = .{ .disable = 8 } }, FIXME, 0));
549
- try expectEqualSlices(u4, &.{0}, Rolls.disable(.{ .durations = .{ .disable = 4 } }, FIXME, 1));
550
- try expectEqualSlices(u4, &.{ 0, 4 }, Rolls.disable(.{
551
- .durations = .{ .disable = 4 },
552
- }, FIXME, 0));
573
+ try expectEqualSlices(u4, &.{0}, Rolls.disable(
574
+ .{ .durations = .{ .disable = 0 } },
575
+ .{ .durations = .{ .disable = 0 } },
576
+ 0,
577
+ ));
578
+ try expectEqualSlices(u4, &.{ 0, 1 }, Rolls.disable(
579
+ .{ .durations = .{ .disable = 1 } },
580
+ .{ .durations = .{ .disable = 0 } },
581
+ 0,
582
+ ));
583
+ try expectEqualSlices(u4, &.{ 0, 2 }, Rolls.disable(
584
+ .{ .durations = .{ .disable = 0 } },
585
+ .{ .durations = .{ .disable = 1 } },
586
+ 0,
587
+ ));
588
+ try expectEqualSlices(u4, &.{1}, Rolls.disable(
589
+ .{ .durations = .{ .disable = 1 } },
590
+ .{ .durations = .{ .disable = 1 } },
591
+ 0,
592
+ ));
593
+ try expectEqualSlices(u4, &.{ 0, 3 }, Rolls.disable(
594
+ .{ .durations = .{ .disable = 0 } },
595
+ .{ .durations = .{ .disable = 2 } },
596
+ 0,
597
+ ));
598
+ try expectEqualSlices(u4, &.{0}, Rolls.disable(
599
+ .{ .durations = .{ .disable = 0 } },
600
+ .{ .durations = .{ .disable = 2 } },
601
+ 1,
602
+ ));
603
+ try expectEqualSlices(u4, &.{ 0, 8 }, Rolls.disable(
604
+ .{ .durations = .{ .disable = 8 } },
605
+ .{ .durations = .{ .disable = 7 } },
606
+ 0,
607
+ ));
608
+ try expectEqualSlices(u4, &.{0}, Rolls.disable(
609
+ .{ .durations = .{ .disable = 0 } },
610
+ .{ .durations = .{ .disable = 8 } },
611
+ 0,
612
+ ));
553
613
  }
554
614
 
555
615
  test "Rolls.confusion" {
556
- try expectEqualSlices(u3, &.{0}, Rolls.confusion(.{
557
- .durations = .{ .confusion = 0 },
558
- }, FIXME, 0));
559
- try expectEqualSlices(u3, &.{0}, Rolls.confusion(.{
560
- .durations = .{ .confusion = 5 },
561
- }, FIXME, 0));
562
- try expectEqualSlices(u3, &.{0}, Rolls.confusion(.{
563
- .durations = .{ .confusion = 3 },
564
- }, FIXME, 1));
565
- try expectEqualSlices(u3, &.{1}, Rolls.confusion(.{
566
- .durations = .{ .confusion = 1 },
567
- }, FIXME, 0));
568
- try expectEqualSlices(u3, &.{ 0, 3 }, Rolls.confusion(.{
569
- .durations = .{ .confusion = 3 },
570
- }, FIXME, 0));
616
+ try expectEqualSlices(u3, &.{0}, Rolls.confusion(
617
+ .{ .durations = .{ .confusion = 0 } },
618
+ .{ .durations = .{ .confusion = 0 } },
619
+ 0,
620
+ ));
621
+ try expectEqualSlices(u3, &.{1}, Rolls.confusion(
622
+ .{ .durations = .{ .confusion = 1 } },
623
+ .{ .durations = .{ .confusion = 0 } },
624
+ 0,
625
+ ));
626
+ try expectEqualSlices(u3, &.{0}, Rolls.confusion(
627
+ .{ .durations = .{ .confusion = 0 } },
628
+ .{ .durations = .{ .confusion = 1 } },
629
+ 0,
630
+ ));
631
+ try expectEqualSlices(u3, &.{1}, Rolls.confusion(
632
+ .{ .durations = .{ .confusion = 1 } },
633
+ .{ .durations = .{ .confusion = 1 } },
634
+ 0,
635
+ ));
636
+ try expectEqualSlices(u3, &.{ 0, 3 }, Rolls.confusion(
637
+ .{ .durations = .{ .confusion = 0 } },
638
+ .{ .durations = .{ .confusion = 2 } },
639
+ 0,
640
+ ));
641
+ try expectEqualSlices(u3, &.{0}, Rolls.confusion(
642
+ .{ .durations = .{ .confusion = 0 } },
643
+ .{ .durations = .{ .confusion = 2 } },
644
+ 1,
645
+ ));
646
+ try expectEqualSlices(u3, &.{ 0, 5 }, Rolls.confusion(
647
+ .{ .durations = .{ .confusion = 5 } },
648
+ .{ .durations = .{ .confusion = 4 } },
649
+ 0,
650
+ ));
651
+ try expectEqualSlices(u3, &.{0}, Rolls.confusion(
652
+ .{ .durations = .{ .confusion = 0 } },
653
+ .{ .durations = .{ .confusion = 5 } },
654
+ 0,
655
+ ));
571
656
  }
572
657
 
573
658
  test "Rolls.attacking" {
574
- try expectEqualSlices(u3, &.{0}, Rolls.attacking(.{
575
- .durations = .{ .attacking = 0 },
576
- }, FIXME, .false));
577
- try expectEqualSlices(u3, &.{0}, Rolls.attacking(.{
578
- .durations = .{ .attacking = 3 },
579
- }, FIXME, .false));
580
- try expectEqualSlices(u3, &.{0}, Rolls.attacking(.{
581
- .durations = .{ .attacking = 2 },
582
- }, FIXME, .true));
583
- try expectEqualSlices(u3, &.{1}, Rolls.attacking(.{
584
- .durations = .{ .attacking = 1 },
585
- }, FIXME, .false));
586
- try expectEqualSlices(u3, &.{ 0, 2 }, Rolls.attacking(.{
587
- .durations = .{ .attacking = 2 },
588
- }, FIXME, .false));
659
+ try expectEqualSlices(u3, &.{0}, Rolls.attacking(
660
+ .{ .durations = .{ .attacking = 0 } },
661
+ .{ .durations = .{ .attacking = 0 } },
662
+ .false,
663
+ ));
664
+ try expectEqualSlices(u3, &.{1}, Rolls.attacking(
665
+ .{ .durations = .{ .attacking = 1 } },
666
+ .{ .durations = .{ .attacking = 0 } },
667
+ .false,
668
+ ));
669
+ try expectEqualSlices(u3, &.{0}, Rolls.attacking(
670
+ .{ .durations = .{ .attacking = 0 } },
671
+ .{ .durations = .{ .attacking = 1 } },
672
+ .false,
673
+ ));
674
+ try expectEqualSlices(u3, &.{1}, Rolls.attacking(
675
+ .{ .durations = .{ .attacking = 1 } },
676
+ .{ .durations = .{ .attacking = 1 } },
677
+ .false,
678
+ ));
679
+ try expectEqualSlices(u3, &.{ 0, 3 }, Rolls.attacking(
680
+ .{ .durations = .{ .attacking = 0 } },
681
+ .{ .durations = .{ .attacking = 2 } },
682
+ .false,
683
+ ));
684
+ try expectEqualSlices(u3, &.{0}, Rolls.attacking(
685
+ .{ .durations = .{ .attacking = 0 } },
686
+ .{ .durations = .{ .attacking = 2 } },
687
+ .true,
688
+ ));
689
+ try expectEqualSlices(u3, &.{ 0, 3 }, Rolls.attacking(
690
+ .{ .durations = .{ .attacking = 3 } },
691
+ .{ .durations = .{ .attacking = 2 } },
692
+ .false,
693
+ ));
694
+ try expectEqualSlices(u3, &.{0}, Rolls.attacking(
695
+ .{ .durations = .{ .attacking = 0 } },
696
+ .{ .durations = .{ .attacking = 3 } },
697
+ .false,
698
+ ));
589
699
  }
590
700
 
591
701
  test "Rolls.binding" {
592
- try expectEqualSlices(u3, &.{0}, Rolls.binding(.{
593
- .durations = .{ .binding = 0 },
594
- }, FIXME, .false));
595
- try expectEqualSlices(u3, &.{0}, Rolls.binding(.{
596
- .durations = .{ .binding = 4 },
597
- }, FIXME, .false));
598
- try expectEqualSlices(u3, &.{0}, Rolls.binding(.{
599
- .durations = .{ .binding = 2 },
600
- }, FIXME, .true));
601
- try expectEqualSlices(u3, &.{ 0, 2 }, Rolls.binding(.{
602
- .durations = .{ .binding = 2 },
603
- }, FIXME, .false));
702
+ try expectEqualSlices(u3, &.{0}, Rolls.binding(
703
+ .{ .durations = .{ .binding = 0 } },
704
+ .{ .durations = .{ .binding = 0 } },
705
+ .false,
706
+ ));
707
+ try expectEqualSlices(u3, &.{ 0, 1 }, Rolls.binding(
708
+ .{ .durations = .{ .binding = 1 } },
709
+ .{ .durations = .{ .binding = 0 } },
710
+ .false,
711
+ ));
712
+ try expectEqualSlices(u3, &.{ 0, 2 }, Rolls.binding(
713
+ .{ .durations = .{ .binding = 0 } },
714
+ .{ .durations = .{ .binding = 1 } },
715
+ .false,
716
+ ));
717
+ try expectEqualSlices(u3, &.{1}, Rolls.binding(
718
+ .{ .durations = .{ .binding = 1 } },
719
+ .{ .durations = .{ .binding = 1 } },
720
+ .false,
721
+ ));
722
+ try expectEqualSlices(u3, &.{ 0, 3 }, Rolls.binding(
723
+ .{ .durations = .{ .binding = 0 } },
724
+ .{ .durations = .{ .binding = 2 } },
725
+ .false,
726
+ ));
727
+ try expectEqualSlices(u3, &.{0}, Rolls.binding(
728
+ .{ .durations = .{ .binding = 0 } },
729
+ .{ .durations = .{ .binding = 2 } },
730
+ .true,
731
+ ));
732
+ try expectEqualSlices(u3, &.{ 0, 4 }, Rolls.binding(
733
+ .{ .durations = .{ .binding = 4 } },
734
+ .{ .durations = .{ .binding = 3 } },
735
+ .false,
736
+ ));
737
+ try expectEqualSlices(u3, &.{0}, Rolls.binding(
738
+ .{ .durations = .{ .binding = 0 } },
739
+ .{ .durations = .{ .binding = 4 } },
740
+ .false,
741
+ ));
604
742
  }
605
743
 
606
744
  test "Rolls.moveSlot" {
607
- const actions = Actions{ .p2 = .{ .move_slot = 3 } };
745
+ const actions: Actions = .{ .p2 = .{ .move_slot = 3 } };
608
746
  try expectEqualSlices(u4, &.{0}, Rolls.moveSlot(actions.p1, .None));
609
747
  try expectEqualSlices(u4, &.{ 1, 2, 3, 4 }, Rolls.moveSlot(actions.p2, .None));
610
748
  try expectEqualSlices(u4, &.{0}, Rolls.moveSlot(actions.p2, .false));
611
749
  }
612
750
 
613
751
  test "Rolls.multiHit" {
614
- const actions = Actions{ .p2 = .{ .multi_hit = 3 } };
752
+ const actions: Actions = .{ .p2 = .{ .multi_hit = 3 } };
615
753
  try expectEqualSlices(u4, &.{0}, Rolls.multiHit(actions.p1, .None));
616
754
  try expectEqualSlices(u4, &.{ 2, 3, 4, 5 }, Rolls.multiHit(actions.p2, .None));
617
755
  try expectEqualSlices(u4, &.{0}, Rolls.multiHit(actions.p2, .false));
618
756
  }
619
757
 
620
758
  test "Rolls.metronome" {
621
- const actions = Actions{ .p2 = .{ .metronome = .Surf } };
759
+ const actions: Actions = .{ .p2 = .{ .metronome = .Surf } };
622
760
  try expectEqualSlices(Move, &.{.None}, Rolls.metronome(actions.p1));
623
761
  try expectEqual(@as(Move, @enumFromInt(24)), Rolls.metronome(actions.p2)[23]);
624
762
  }
625
763
 
626
764
  test "Rolls.psywave" {
627
- const actions = Actions{ .p2 = .{ .psywave = 79 } };
765
+ const actions: Actions = .{ .p2 = .{ .psywave = 79 } };
628
766
  var side = Side.init(&[_]Pokemon{.{
629
767
  .species = .Bulbasaur,
630
768
  .level = 100,
@@ -633,9 +771,9 @@ test "Rolls.psywave" {
633
771
 
634
772
  try expectEqualSlices(u8, &.{0}, Rolls.psywave(actions.p1, &side, .None));
635
773
  var rolls = Rolls.psywave(actions.p2, &side, .None);
636
- try expectEqual(@as(u8, 150), rolls[rolls.len - 1]);
774
+ try expectEqual(150, rolls[rolls.len - 1]);
637
775
  side.stored().level = 81;
638
776
  rolls = Rolls.psywave(actions.p2, &side, .None);
639
- try expectEqual(@as(u8, 121), rolls[rolls.len - 1]);
777
+ try expectEqual(121, rolls[rolls.len - 1]);
640
778
  try expectEqualSlices(u8, &.{0}, Rolls.psywave(actions.p2, &side, .false));
641
779
  }