@pkmn/engine 0.1.0-dev.2c13d3ec → 0.1.0-dev.305a932f
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.
- package/README.md +45 -37
- package/build/pkg/data/ids.json +12 -12
- package/build/pkg/data/protocol.json +69 -12
- package/build/pkg/data.d.ts +2 -2
- package/build/pkg/protocol.js +56 -37
- package/build/pkg/protocol.js.map +1 -1
- package/build.zig +53 -44
- package/package.json +33 -15
- package/src/bin/install-pkmn-engine +2 -2
- package/src/lib/binding/node.zig +1 -1
- package/src/lib/common/battle.zig +17 -0
- package/src/lib/common/data.zig +4 -16
- package/src/lib/common/js.zig +118 -0
- package/src/lib/common/optional.zig +60 -0
- package/src/lib/common/protocol.zig +520 -66
- package/src/lib/common/rational.zig +353 -0
- package/src/lib/common/rng.zig +6 -6
- package/src/lib/common/util.zig +12 -0
- package/src/lib/gen1/README.md +246 -166
- package/src/lib/gen1/calc.zig +426 -0
- package/src/lib/gen1/chance.zig +1058 -0
- package/src/lib/gen1/data/moves.zig +168 -170
- package/src/lib/gen1/data/types.zig +2 -2
- package/src/lib/gen1/data.zig +25 -32
- package/src/lib/gen1/helpers.zig +240 -87
- package/src/lib/gen1/mechanics.zig +50 -72
- package/src/lib/gen2/README.md +106 -85
- package/src/lib/gen2/data/items.zig +10 -16
- package/src/lib/gen2/data/moves.zig +639 -562
- package/src/lib/gen2/data/types.zig +81 -25
- package/src/lib/gen2/data.zig +78 -63
- package/src/lib/gen2/helpers.zig +8 -12
- package/src/lib/gen2/mechanics.zig +1237 -7
|
@@ -30,7 +30,7 @@ pub const Type = enum(u4) {
|
|
|
30
30
|
Ice,
|
|
31
31
|
Dragon,
|
|
32
32
|
|
|
33
|
-
const CHART
|
|
33
|
+
const CHART: [15][15]Effectiveness = .{
|
|
34
34
|
[_]Effectiveness{ N, N, N, N, N, R, N, I, N, N, N, N, N, N, N }, // Normal
|
|
35
35
|
[_]Effectiveness{ S, N, R, R, N, S, R, I, N, N, N, N, R, S, N }, // Fighting
|
|
36
36
|
[_]Effectiveness{ N, S, N, N, N, R, S, N, N, N, S, R, N, N, N }, // Flying
|
|
@@ -99,7 +99,7 @@ pub const Type = enum(u4) {
|
|
|
99
99
|
return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
/// The precedence order of
|
|
102
|
+
/// The precedence order of Type `t2` vs. Type `t1`.
|
|
103
103
|
pub fn precedence(t1: Type, t2: Type) u8 {
|
|
104
104
|
for (PRECEDENCE, 0..) |matchup, i| {
|
|
105
105
|
if (matchup.type1 == t1 and matchup.type2 == t2) return @intCast(i);
|
package/src/lib/gen1/data.zig
CHANGED
|
@@ -65,7 +65,7 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
65
65
|
/// The last damage dealt by either side.
|
|
66
66
|
last_damage: u16 = 0,
|
|
67
67
|
/// Details about the last move selected/used by each player required to detect desyncs.
|
|
68
|
-
last_moves: MoveDetails = .{},
|
|
68
|
+
last_moves: [2]MoveDetails = [_]MoveDetails{.{}} ** 2,
|
|
69
69
|
/// The pseudo random number generator.
|
|
70
70
|
rng: RNG,
|
|
71
71
|
|
|
@@ -86,6 +86,15 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
86
86
|
return player.ident(@intCast(self.side(player).order[0]));
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/// Returns the `MoveDetails` for the given `player`.
|
|
90
|
+
pub inline fn lastMove(
|
|
91
|
+
self: anytype,
|
|
92
|
+
player: Player,
|
|
93
|
+
) PointerType(@TypeOf(self), MoveDetails) {
|
|
94
|
+
assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
|
|
95
|
+
return &self.last_moves[@intFromEnum(player)];
|
|
96
|
+
}
|
|
97
|
+
|
|
89
98
|
/// Returns the result of applying Player 1's choice `c1` and Player 2's choice `c2` to the
|
|
90
99
|
/// battle, optionally writing protocol message logs to `options.log` if `pkmn.options.log`
|
|
91
100
|
/// is enabled.
|
|
@@ -205,7 +214,7 @@ pub const Pokemon = extern struct {
|
|
|
205
214
|
}
|
|
206
215
|
};
|
|
207
216
|
|
|
208
|
-
/// Representation of a Generation I
|
|
217
|
+
/// Representation of a Generation I Pokémon's move slot in a battle.
|
|
209
218
|
pub const MoveSlot = extern struct {
|
|
210
219
|
/// The identifier for the move.
|
|
211
220
|
id: Move = .None,
|
|
@@ -213,24 +222,16 @@ pub const MoveSlot = extern struct {
|
|
|
213
222
|
pp: u8 = 0,
|
|
214
223
|
|
|
215
224
|
comptime {
|
|
216
|
-
assert(@sizeOf(MoveSlot) ==
|
|
225
|
+
assert(@sizeOf(MoveSlot) == 2);
|
|
217
226
|
}
|
|
218
227
|
};
|
|
219
228
|
|
|
220
229
|
/// Details required to detect desyncs based on the move last selected/executed by players.
|
|
221
|
-
pub const MoveDetails = packed struct {
|
|
222
|
-
/// The move slot index of the last move selected in the battle menu
|
|
223
|
-
|
|
224
|
-
/// Whether the last move executed
|
|
225
|
-
|
|
226
|
-
/// The move slot index of the last move selected in the battle menu by Player 2
|
|
227
|
-
p2_index: if (showdown) u8 else u4 = 0,
|
|
228
|
-
/// Whether the last move executed by Player 2 was counterable.
|
|
229
|
-
p2_counterable: if (showdown) u8 else u4 = 0,
|
|
230
|
-
|
|
231
|
-
comptime {
|
|
232
|
-
assert(@sizeOf(MoveDetails) == if (showdown) 4 else 2);
|
|
233
|
-
}
|
|
230
|
+
pub const MoveDetails = packed struct(if (showdown) u16 else u8) {
|
|
231
|
+
/// The move slot index of the last move selected in the battle menu.
|
|
232
|
+
index: if (showdown) u8 else u4 = 0,
|
|
233
|
+
/// Whether the last move executed was counterable.
|
|
234
|
+
counterable: if (showdown) u8 else u4 = 0,
|
|
234
235
|
};
|
|
235
236
|
|
|
236
237
|
/// Bitfield representation of a Generation I & II Pokémon's major status condition.
|
|
@@ -324,7 +325,7 @@ test Status {
|
|
|
324
325
|
}
|
|
325
326
|
|
|
326
327
|
/// Bitfield representation of volatile statuses and associated data in Generation I.
|
|
327
|
-
pub const Volatiles = packed struct {
|
|
328
|
+
pub const Volatiles = packed struct(u64) {
|
|
328
329
|
/// Whether the "Bide" volatile status is present.
|
|
329
330
|
Bide: bool = false,
|
|
330
331
|
/// Whether the "Thrashing" volatile status is present.
|
|
@@ -382,14 +383,10 @@ pub const Volatiles = packed struct {
|
|
|
382
383
|
disabled_move: u3 = 0,
|
|
383
384
|
/// The number of turns toxic damage has been accumulating.
|
|
384
385
|
toxic: u5 = 0,
|
|
385
|
-
|
|
386
|
-
comptime {
|
|
387
|
-
assert(@sizeOf(Volatiles) == 8);
|
|
388
|
-
}
|
|
389
386
|
};
|
|
390
387
|
|
|
391
388
|
test Volatiles {
|
|
392
|
-
var volatiles =
|
|
389
|
+
var volatiles: Volatiles = .{};
|
|
393
390
|
volatiles.Confusion = true;
|
|
394
391
|
volatiles.confusion = 2;
|
|
395
392
|
volatiles.Thrashing = true;
|
|
@@ -451,7 +448,7 @@ test Stats {
|
|
|
451
448
|
}
|
|
452
449
|
|
|
453
450
|
/// Representation of a Pokémon's boosts in Generation I.
|
|
454
|
-
pub const Boosts = packed struct {
|
|
451
|
+
pub const Boosts = packed struct(u32) {
|
|
455
452
|
/// A Pokémon's Attack boosts.
|
|
456
453
|
atk: i4 = 0,
|
|
457
454
|
/// A Pokémon's Defense boosts.
|
|
@@ -466,14 +463,10 @@ pub const Boosts = packed struct {
|
|
|
466
463
|
evasion: i4 = 0,
|
|
467
464
|
|
|
468
465
|
_: u8 = 0,
|
|
469
|
-
|
|
470
|
-
comptime {
|
|
471
|
-
assert(@sizeOf(Boosts) == 4);
|
|
472
|
-
}
|
|
473
466
|
};
|
|
474
467
|
|
|
475
468
|
test Boosts {
|
|
476
|
-
const boosts =
|
|
469
|
+
const boosts: Boosts = .{ .spc = -6 };
|
|
477
470
|
try expectEqual(0, boosts.atk);
|
|
478
471
|
try expectEqual(-6, boosts.spc);
|
|
479
472
|
}
|
|
@@ -485,7 +478,7 @@ test Move {
|
|
|
485
478
|
try expectEqual(2, @intFromEnum(Move.KarateChop));
|
|
486
479
|
const move = Move.get(.Fissure);
|
|
487
480
|
try expectEqual(Move.Effect.OHKO, move.effect);
|
|
488
|
-
try expectEqual(
|
|
481
|
+
try expectEqual(rng.Gen12.percent(30), move.accuracy);
|
|
489
482
|
try expectEqual(Type.Ground, move.type);
|
|
490
483
|
|
|
491
484
|
try expect(!Move.Effect.onBegin(.None));
|
|
@@ -623,16 +616,16 @@ pub const DVs = struct {
|
|
|
623
616
|
};
|
|
624
617
|
|
|
625
618
|
test DVs {
|
|
626
|
-
var dvs =
|
|
619
|
+
var dvs: DVs = .{ .spc = 15, .spe = 15 };
|
|
627
620
|
try expectEqual(@as(u4, 15), dvs.hp());
|
|
628
|
-
dvs =
|
|
621
|
+
dvs = .{
|
|
629
622
|
.atk = 5,
|
|
630
623
|
.def = 15,
|
|
631
624
|
.spe = 13,
|
|
632
625
|
.spc = 13,
|
|
633
626
|
};
|
|
634
627
|
try expectEqual(@as(u4, 15), dvs.hp());
|
|
635
|
-
dvs =
|
|
628
|
+
dvs = .{
|
|
636
629
|
.def = 3,
|
|
637
630
|
.spe = 10,
|
|
638
631
|
.spc = 11,
|
package/src/lib/gen1/helpers.zig
CHANGED
|
@@ -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`
|
|
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
|
|
356
|
-
|
|
357
|
-
|
|
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`
|
|
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
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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`
|
|
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
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
return if (
|
|
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`
|
|
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
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
return if (
|
|
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`
|
|
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
|
-
|
|
392
|
-
|
|
393
|
-
|
|
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};
|
|
@@ -460,13 +478,13 @@ pub const Rolls = struct {
|
|
|
460
478
|
};
|
|
461
479
|
|
|
462
480
|
test "Rolls.speedTie" {
|
|
463
|
-
const actions =
|
|
481
|
+
const actions: Actions = .{ .p1 = .{ .speed_tie = .P2 } };
|
|
464
482
|
try expectEqualSlices(Optional(Player), &.{ .P1, .P2 }, Rolls.speedTie(actions.p1));
|
|
465
483
|
try expectEqualSlices(Optional(Player), &.{.None}, Rolls.speedTie(actions.p2));
|
|
466
484
|
}
|
|
467
485
|
|
|
468
486
|
test "Rolls.damage" {
|
|
469
|
-
const actions =
|
|
487
|
+
const actions: Actions = .{ .p2 = .{ .damage = 221 } };
|
|
470
488
|
try expectEqual(Rolls.Range{ .min = 0, .max = 1 }, Rolls.damage(actions.p1, .None));
|
|
471
489
|
try expectEqual(Rolls.Range{ .min = 217, .max = 256 }, Rolls.damage(actions.p2, .None));
|
|
472
490
|
try expectEqual(Rolls.Range{ .min = 0, .max = 1 }, Rolls.damage(actions.p2, .false));
|
|
@@ -484,7 +502,7 @@ test "Rolls.coalesce" {
|
|
|
484
502
|
}
|
|
485
503
|
|
|
486
504
|
test "Rolls.hit" {
|
|
487
|
-
const actions =
|
|
505
|
+
const actions: Actions = .{ .p2 = .{ .hit = .true } };
|
|
488
506
|
try expectEqualSlices(Optional(bool), &.{.None}, Rolls.hit(actions.p1, .None));
|
|
489
507
|
try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.hit(actions.p2, .None));
|
|
490
508
|
try expectEqualSlices(Optional(bool), &.{.None}, Rolls.hit(actions.p2, .true));
|
|
@@ -492,7 +510,7 @@ test "Rolls.hit" {
|
|
|
492
510
|
}
|
|
493
511
|
|
|
494
512
|
test "Rolls.secondaryChance" {
|
|
495
|
-
const actions =
|
|
513
|
+
const actions: Actions = .{ .p1 = .{ .secondary_chance = .true } };
|
|
496
514
|
try expectEqualSlices(
|
|
497
515
|
Optional(bool),
|
|
498
516
|
&.{ .false, .true },
|
|
@@ -503,7 +521,7 @@ test "Rolls.secondaryChance" {
|
|
|
503
521
|
}
|
|
504
522
|
|
|
505
523
|
test "Rolls.criticalHit" {
|
|
506
|
-
const actions =
|
|
524
|
+
const actions: Actions = .{ .p1 = .{ .critical_hit = .true } };
|
|
507
525
|
try expectEqualSlices(
|
|
508
526
|
Optional(bool),
|
|
509
527
|
&.{ .false, .true },
|
|
@@ -514,14 +532,14 @@ test "Rolls.criticalHit" {
|
|
|
514
532
|
}
|
|
515
533
|
|
|
516
534
|
test "Rolls.confused" {
|
|
517
|
-
const actions =
|
|
535
|
+
const actions: Actions = .{ .p2 = .{ .confused = .true } };
|
|
518
536
|
try expectEqualSlices(Optional(bool), &.{.None}, Rolls.confused(actions.p1, 1));
|
|
519
537
|
try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.confused(actions.p2, 1));
|
|
520
538
|
try expectEqualSlices(Optional(bool), &.{.None}, Rolls.confused(actions.p2, 0));
|
|
521
539
|
}
|
|
522
540
|
|
|
523
541
|
test "Rolls.paralyzed" {
|
|
524
|
-
const actions =
|
|
542
|
+
const actions: Actions = .{ .p2 = .{ .paralyzed = .true } };
|
|
525
543
|
try expectEqualSlices(Optional(bool), &.{.None}, Rolls.paralyzed(actions.p1, .None));
|
|
526
544
|
try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.paralyzed(actions.p2, .None));
|
|
527
545
|
try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.paralyzed(actions.p2, .false));
|
|
@@ -529,102 +547,237 @@ test "Rolls.paralyzed" {
|
|
|
529
547
|
}
|
|
530
548
|
|
|
531
549
|
test "Rolls.duration" {
|
|
532
|
-
const actions =
|
|
550
|
+
const actions: Actions = .{ .p2 = .{ .duration = 3 } };
|
|
533
551
|
try expectEqualSlices(u1, &.{0}, Rolls.duration(actions.p1, .None));
|
|
534
552
|
try expectEqualSlices(u1, &.{1}, Rolls.duration(actions.p2, .None));
|
|
535
553
|
try expectEqualSlices(u1, &.{0}, Rolls.duration(actions.p2, .false));
|
|
536
554
|
}
|
|
537
555
|
|
|
538
|
-
const FIXME: Action = .{};
|
|
539
|
-
|
|
540
556
|
test "Rolls.sleep" {
|
|
541
|
-
try expectEqualSlices(u3, &.{0}, Rolls.sleep(
|
|
542
|
-
|
|
543
|
-
|
|
557
|
+
try expectEqualSlices(u3, &.{0}, Rolls.sleep(
|
|
558
|
+
.{ .durations = .{ .sleep = 0 } },
|
|
559
|
+
.{ .durations = .{ .sleep = 0 } },
|
|
560
|
+
));
|
|
561
|
+
try expectEqualSlices(u3, &.{ 0, 1 }, Rolls.sleep(
|
|
562
|
+
.{ .durations = .{ .sleep = 1 } },
|
|
563
|
+
.{ .durations = .{ .sleep = 0 } },
|
|
564
|
+
));
|
|
565
|
+
try expectEqualSlices(u3, &.{ 0, 2 }, Rolls.sleep(
|
|
566
|
+
.{ .durations = .{ .sleep = 0 } },
|
|
567
|
+
.{ .durations = .{ .sleep = 1 } },
|
|
568
|
+
));
|
|
569
|
+
try expectEqualSlices(u3, &.{1}, Rolls.sleep(
|
|
570
|
+
.{ .durations = .{ .sleep = 1 } },
|
|
571
|
+
.{ .durations = .{ .sleep = 1 } },
|
|
572
|
+
));
|
|
573
|
+
try expectEqualSlices(u3, &.{ 0, 3 }, Rolls.sleep(
|
|
574
|
+
.{ .durations = .{ .sleep = 0 } },
|
|
575
|
+
.{ .durations = .{ .sleep = 2 } },
|
|
576
|
+
));
|
|
577
|
+
try expectEqualSlices(u3, &.{ 0, 7 }, Rolls.sleep(
|
|
578
|
+
.{ .durations = .{ .sleep = 7 } },
|
|
579
|
+
.{ .durations = .{ .sleep = 6 } },
|
|
580
|
+
));
|
|
581
|
+
try expectEqualSlices(u3, &.{0}, Rolls.sleep(
|
|
582
|
+
.{ .durations = .{ .sleep = 0 } },
|
|
583
|
+
.{ .durations = .{ .sleep = 7 } },
|
|
584
|
+
));
|
|
544
585
|
}
|
|
545
586
|
|
|
546
587
|
test "Rolls.disable" {
|
|
547
|
-
try expectEqualSlices(u4, &.{0}, Rolls.disable(
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
588
|
+
try expectEqualSlices(u4, &.{0}, Rolls.disable(
|
|
589
|
+
.{ .durations = .{ .disable = 0 } },
|
|
590
|
+
.{ .durations = .{ .disable = 0 } },
|
|
591
|
+
0,
|
|
592
|
+
));
|
|
593
|
+
try expectEqualSlices(u4, &.{ 0, 1 }, Rolls.disable(
|
|
594
|
+
.{ .durations = .{ .disable = 1 } },
|
|
595
|
+
.{ .durations = .{ .disable = 0 } },
|
|
596
|
+
0,
|
|
597
|
+
));
|
|
598
|
+
try expectEqualSlices(u4, &.{ 0, 2 }, Rolls.disable(
|
|
599
|
+
.{ .durations = .{ .disable = 0 } },
|
|
600
|
+
.{ .durations = .{ .disable = 1 } },
|
|
601
|
+
0,
|
|
602
|
+
));
|
|
603
|
+
try expectEqualSlices(u4, &.{1}, Rolls.disable(
|
|
604
|
+
.{ .durations = .{ .disable = 1 } },
|
|
605
|
+
.{ .durations = .{ .disable = 1 } },
|
|
606
|
+
0,
|
|
607
|
+
));
|
|
608
|
+
try expectEqualSlices(u4, &.{ 0, 3 }, Rolls.disable(
|
|
609
|
+
.{ .durations = .{ .disable = 0 } },
|
|
610
|
+
.{ .durations = .{ .disable = 2 } },
|
|
611
|
+
0,
|
|
612
|
+
));
|
|
613
|
+
try expectEqualSlices(u4, &.{0}, Rolls.disable(
|
|
614
|
+
.{ .durations = .{ .disable = 0 } },
|
|
615
|
+
.{ .durations = .{ .disable = 2 } },
|
|
616
|
+
1,
|
|
617
|
+
));
|
|
618
|
+
try expectEqualSlices(u4, &.{ 0, 8 }, Rolls.disable(
|
|
619
|
+
.{ .durations = .{ .disable = 8 } },
|
|
620
|
+
.{ .durations = .{ .disable = 7 } },
|
|
621
|
+
0,
|
|
622
|
+
));
|
|
623
|
+
try expectEqualSlices(u4, &.{0}, Rolls.disable(
|
|
624
|
+
.{ .durations = .{ .disable = 0 } },
|
|
625
|
+
.{ .durations = .{ .disable = 8 } },
|
|
626
|
+
0,
|
|
627
|
+
));
|
|
553
628
|
}
|
|
554
629
|
|
|
555
630
|
test "Rolls.confusion" {
|
|
556
|
-
try expectEqualSlices(u3, &.{0}, Rolls.confusion(
|
|
557
|
-
.durations = .{ .confusion = 0 },
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
.durations = .{ .confusion =
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
631
|
+
try expectEqualSlices(u3, &.{0}, Rolls.confusion(
|
|
632
|
+
.{ .durations = .{ .confusion = 0 } },
|
|
633
|
+
.{ .durations = .{ .confusion = 0 } },
|
|
634
|
+
0,
|
|
635
|
+
));
|
|
636
|
+
try expectEqualSlices(u3, &.{1}, Rolls.confusion(
|
|
637
|
+
.{ .durations = .{ .confusion = 1 } },
|
|
638
|
+
.{ .durations = .{ .confusion = 0 } },
|
|
639
|
+
0,
|
|
640
|
+
));
|
|
641
|
+
try expectEqualSlices(u3, &.{0}, Rolls.confusion(
|
|
642
|
+
.{ .durations = .{ .confusion = 0 } },
|
|
643
|
+
.{ .durations = .{ .confusion = 1 } },
|
|
644
|
+
0,
|
|
645
|
+
));
|
|
646
|
+
try expectEqualSlices(u3, &.{1}, Rolls.confusion(
|
|
647
|
+
.{ .durations = .{ .confusion = 1 } },
|
|
648
|
+
.{ .durations = .{ .confusion = 1 } },
|
|
649
|
+
0,
|
|
650
|
+
));
|
|
651
|
+
try expectEqualSlices(u3, &.{ 0, 3 }, Rolls.confusion(
|
|
652
|
+
.{ .durations = .{ .confusion = 0 } },
|
|
653
|
+
.{ .durations = .{ .confusion = 2 } },
|
|
654
|
+
0,
|
|
655
|
+
));
|
|
656
|
+
try expectEqualSlices(u3, &.{0}, Rolls.confusion(
|
|
657
|
+
.{ .durations = .{ .confusion = 0 } },
|
|
658
|
+
.{ .durations = .{ .confusion = 2 } },
|
|
659
|
+
1,
|
|
660
|
+
));
|
|
661
|
+
try expectEqualSlices(u3, &.{ 0, 5 }, Rolls.confusion(
|
|
662
|
+
.{ .durations = .{ .confusion = 5 } },
|
|
663
|
+
.{ .durations = .{ .confusion = 4 } },
|
|
664
|
+
0,
|
|
665
|
+
));
|
|
666
|
+
try expectEqualSlices(u3, &.{0}, Rolls.confusion(
|
|
667
|
+
.{ .durations = .{ .confusion = 0 } },
|
|
668
|
+
.{ .durations = .{ .confusion = 5 } },
|
|
669
|
+
0,
|
|
670
|
+
));
|
|
571
671
|
}
|
|
572
672
|
|
|
573
673
|
test "Rolls.attacking" {
|
|
574
|
-
try expectEqualSlices(u3, &.{0}, Rolls.attacking(
|
|
575
|
-
.durations = .{ .attacking = 0 },
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
.durations = .{ .attacking =
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
.
|
|
588
|
-
|
|
674
|
+
try expectEqualSlices(u3, &.{0}, Rolls.attacking(
|
|
675
|
+
.{ .durations = .{ .attacking = 0 } },
|
|
676
|
+
.{ .durations = .{ .attacking = 0 } },
|
|
677
|
+
.false,
|
|
678
|
+
));
|
|
679
|
+
try expectEqualSlices(u3, &.{1}, Rolls.attacking(
|
|
680
|
+
.{ .durations = .{ .attacking = 1 } },
|
|
681
|
+
.{ .durations = .{ .attacking = 0 } },
|
|
682
|
+
.false,
|
|
683
|
+
));
|
|
684
|
+
try expectEqualSlices(u3, &.{0}, Rolls.attacking(
|
|
685
|
+
.{ .durations = .{ .attacking = 0 } },
|
|
686
|
+
.{ .durations = .{ .attacking = 1 } },
|
|
687
|
+
.false,
|
|
688
|
+
));
|
|
689
|
+
try expectEqualSlices(u3, &.{1}, Rolls.attacking(
|
|
690
|
+
.{ .durations = .{ .attacking = 1 } },
|
|
691
|
+
.{ .durations = .{ .attacking = 1 } },
|
|
692
|
+
.false,
|
|
693
|
+
));
|
|
694
|
+
try expectEqualSlices(u3, &.{ 0, 3 }, Rolls.attacking(
|
|
695
|
+
.{ .durations = .{ .attacking = 0 } },
|
|
696
|
+
.{ .durations = .{ .attacking = 2 } },
|
|
697
|
+
.false,
|
|
698
|
+
));
|
|
699
|
+
try expectEqualSlices(u3, &.{0}, Rolls.attacking(
|
|
700
|
+
.{ .durations = .{ .attacking = 0 } },
|
|
701
|
+
.{ .durations = .{ .attacking = 2 } },
|
|
702
|
+
.true,
|
|
703
|
+
));
|
|
704
|
+
try expectEqualSlices(u3, &.{ 0, 3 }, Rolls.attacking(
|
|
705
|
+
.{ .durations = .{ .attacking = 3 } },
|
|
706
|
+
.{ .durations = .{ .attacking = 2 } },
|
|
707
|
+
.false,
|
|
708
|
+
));
|
|
709
|
+
try expectEqualSlices(u3, &.{0}, Rolls.attacking(
|
|
710
|
+
.{ .durations = .{ .attacking = 0 } },
|
|
711
|
+
.{ .durations = .{ .attacking = 3 } },
|
|
712
|
+
.false,
|
|
713
|
+
));
|
|
589
714
|
}
|
|
590
715
|
|
|
591
716
|
test "Rolls.binding" {
|
|
592
|
-
try expectEqualSlices(u3, &.{0}, Rolls.binding(
|
|
593
|
-
.durations = .{ .binding = 0 },
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
.durations = .{ .binding =
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
717
|
+
try expectEqualSlices(u3, &.{0}, Rolls.binding(
|
|
718
|
+
.{ .durations = .{ .binding = 0 } },
|
|
719
|
+
.{ .durations = .{ .binding = 0 } },
|
|
720
|
+
.false,
|
|
721
|
+
));
|
|
722
|
+
try expectEqualSlices(u3, &.{ 0, 1 }, Rolls.binding(
|
|
723
|
+
.{ .durations = .{ .binding = 1 } },
|
|
724
|
+
.{ .durations = .{ .binding = 0 } },
|
|
725
|
+
.false,
|
|
726
|
+
));
|
|
727
|
+
try expectEqualSlices(u3, &.{ 0, 2 }, Rolls.binding(
|
|
728
|
+
.{ .durations = .{ .binding = 0 } },
|
|
729
|
+
.{ .durations = .{ .binding = 1 } },
|
|
730
|
+
.false,
|
|
731
|
+
));
|
|
732
|
+
try expectEqualSlices(u3, &.{1}, Rolls.binding(
|
|
733
|
+
.{ .durations = .{ .binding = 1 } },
|
|
734
|
+
.{ .durations = .{ .binding = 1 } },
|
|
735
|
+
.false,
|
|
736
|
+
));
|
|
737
|
+
try expectEqualSlices(u3, &.{ 0, 3 }, Rolls.binding(
|
|
738
|
+
.{ .durations = .{ .binding = 0 } },
|
|
739
|
+
.{ .durations = .{ .binding = 2 } },
|
|
740
|
+
.false,
|
|
741
|
+
));
|
|
742
|
+
try expectEqualSlices(u3, &.{0}, Rolls.binding(
|
|
743
|
+
.{ .durations = .{ .binding = 0 } },
|
|
744
|
+
.{ .durations = .{ .binding = 2 } },
|
|
745
|
+
.true,
|
|
746
|
+
));
|
|
747
|
+
try expectEqualSlices(u3, &.{ 0, 4 }, Rolls.binding(
|
|
748
|
+
.{ .durations = .{ .binding = 4 } },
|
|
749
|
+
.{ .durations = .{ .binding = 3 } },
|
|
750
|
+
.false,
|
|
751
|
+
));
|
|
752
|
+
try expectEqualSlices(u3, &.{0}, Rolls.binding(
|
|
753
|
+
.{ .durations = .{ .binding = 0 } },
|
|
754
|
+
.{ .durations = .{ .binding = 4 } },
|
|
755
|
+
.false,
|
|
756
|
+
));
|
|
604
757
|
}
|
|
605
758
|
|
|
606
759
|
test "Rolls.moveSlot" {
|
|
607
|
-
const actions =
|
|
760
|
+
const actions: Actions = .{ .p2 = .{ .move_slot = 3 } };
|
|
608
761
|
try expectEqualSlices(u4, &.{0}, Rolls.moveSlot(actions.p1, .None));
|
|
609
762
|
try expectEqualSlices(u4, &.{ 1, 2, 3, 4 }, Rolls.moveSlot(actions.p2, .None));
|
|
610
763
|
try expectEqualSlices(u4, &.{0}, Rolls.moveSlot(actions.p2, .false));
|
|
611
764
|
}
|
|
612
765
|
|
|
613
766
|
test "Rolls.multiHit" {
|
|
614
|
-
const actions =
|
|
767
|
+
const actions: Actions = .{ .p2 = .{ .multi_hit = 3 } };
|
|
615
768
|
try expectEqualSlices(u4, &.{0}, Rolls.multiHit(actions.p1, .None));
|
|
616
769
|
try expectEqualSlices(u4, &.{ 2, 3, 4, 5 }, Rolls.multiHit(actions.p2, .None));
|
|
617
770
|
try expectEqualSlices(u4, &.{0}, Rolls.multiHit(actions.p2, .false));
|
|
618
771
|
}
|
|
619
772
|
|
|
620
773
|
test "Rolls.metronome" {
|
|
621
|
-
const actions =
|
|
774
|
+
const actions: Actions = .{ .p2 = .{ .metronome = .Surf } };
|
|
622
775
|
try expectEqualSlices(Move, &.{.None}, Rolls.metronome(actions.p1));
|
|
623
776
|
try expectEqual(@as(Move, @enumFromInt(24)), Rolls.metronome(actions.p2)[23]);
|
|
624
777
|
}
|
|
625
778
|
|
|
626
779
|
test "Rolls.psywave" {
|
|
627
|
-
const actions =
|
|
780
|
+
const actions: Actions = .{ .p2 = .{ .psywave = 79 } };
|
|
628
781
|
var side = Side.init(&[_]Pokemon{.{
|
|
629
782
|
.species = .Bulbasaur,
|
|
630
783
|
.level = 100,
|