@pkmn/engine 0.1.0-dev.dd5b9081 → 0.1.0-dev.e0e37c1b
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 +5 -5
- package/build/pkg/data/ids.json +12 -12
- package/build/pkg/data/layout.json +2 -2
- package/build/pkg/data/protocol.json +69 -12
- package/build/pkg/data.d.ts +2 -2
- package/build/pkg/gen1.js +2 -2
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/protocol.js +56 -37
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +3 -1
- package/build/tools/debug.js.map +1 -1
- package/build.zig +21 -15
- package/package.json +28 -16
- package/src/lib/binding/node.zig +1 -1
- package/src/lib/common/data.zig +5 -5
- package/src/lib/common/optional.zig +8 -1
- package/src/lib/common/protocol.zig +695 -270
- package/src/lib/common/rational.zig +5 -5
- package/src/lib/common/rng.zig +14 -5
- package/src/lib/gen1/README.md +28 -28
- package/src/lib/gen1/calc.zig +4 -4
- package/src/lib/gen1/chance.zig +53 -29
- package/src/lib/gen1/data/moves.zig +190 -176
- package/src/lib/gen1/data/species.zig +2 -2
- package/src/lib/gen1/data/types.zig +7 -7
- package/src/lib/gen1/data.zig +25 -25
- package/src/lib/gen1/helpers.zig +26 -41
- package/src/lib/gen1/mechanics.zig +283 -324
- package/src/lib/gen2/README.md +18 -72
- package/src/lib/gen2/calc.zig +143 -0
- package/src/lib/gen2/chance.zig +1314 -0
- package/src/lib/gen2/data/items.zig +12 -18
- package/src/lib/gen2/data/moves.zig +377 -344
- package/src/lib/gen2/data/species.zig +1 -1
- package/src/lib/gen2/data/types.zig +134 -31
- package/src/lib/gen2/data.zig +44 -36
- package/src/lib/gen2/generated.zig +808 -0
- package/src/lib/gen2/mechanics.zig +3000 -206
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//! Code generated by `tools/generate` - manual edits will be overwritten
|
|
1
|
+
//! Code generated by `tools/generate` - manual edits will be overwritten.
|
|
2
2
|
|
|
3
3
|
const std = @import("std");
|
|
4
4
|
|
|
@@ -1092,7 +1092,7 @@ pub const Species = enum(u8) {
|
|
|
1092
1092
|
pub const size = 151;
|
|
1093
1093
|
|
|
1094
1094
|
/// The Pokémon's critical hit rate=io out of 256.
|
|
1095
|
-
pub
|
|
1095
|
+
pub fn chance(id: Species) u8 {
|
|
1096
1096
|
assert(id != .None);
|
|
1097
1097
|
return CHANCES[@intFromEnum(id) - 1];
|
|
1098
1098
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//! Code generated by `tools/generate` - manual edits will be overwritten
|
|
1
|
+
//! Code generated by `tools/generate` - manual edits will be overwritten.
|
|
2
2
|
|
|
3
3
|
const std = @import("std");
|
|
4
4
|
|
|
@@ -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
|
|
@@ -90,16 +90,16 @@ pub const Type = enum(u4) {
|
|
|
90
90
|
pub const size = 15;
|
|
91
91
|
|
|
92
92
|
/// Whether or not this type is considered to be special as opposed to physical.
|
|
93
|
-
pub
|
|
93
|
+
pub fn special(self: Type) bool {
|
|
94
94
|
return @intFromEnum(self) >= @intFromEnum(Type.Fire);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
/// The `Effectiveness` of type `t2` vs. type `t1`.
|
|
98
|
-
pub
|
|
98
|
+
pub fn effectiveness(t1: Type, t2: Type) Effectiveness {
|
|
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);
|
|
@@ -120,12 +120,12 @@ pub const Types = packed struct {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/// Whether this typing is immune to type `t`.
|
|
123
|
-
pub
|
|
123
|
+
pub fn immune(self: Types, t: Type) bool {
|
|
124
124
|
return t.effectiveness(self.type1) == I or t.effectiveness(self.type2) == I;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
/// Whether this typing includes type `t`.
|
|
128
|
-
pub
|
|
128
|
+
pub fn includes(self: Types, t: Type) bool {
|
|
129
129
|
return self.type1 == t or self.type2 == t;
|
|
130
130
|
}
|
|
131
131
|
};
|
package/src/lib/gen1/data.zig
CHANGED
|
@@ -70,24 +70,24 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
70
70
|
rng: RNG,
|
|
71
71
|
|
|
72
72
|
/// Returns the `Side` for the given `player`.
|
|
73
|
-
pub
|
|
73
|
+
pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
74
74
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
|
|
75
75
|
return &self.sides[@intFromEnum(player)];
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/// Returns the `Side` of the opponent for the given `player`
|
|
79
|
-
pub
|
|
79
|
+
pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
80
80
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
|
|
81
81
|
return &self.sides[@intFromEnum(player.foe())];
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/// Returns an identifier for the active Pokémon of `player`.
|
|
85
|
-
pub
|
|
85
|
+
pub fn active(self: *const Self, player: Player) ID {
|
|
86
86
|
return player.ident(@intCast(self.side(player).order[0]));
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
/// Returns the `MoveDetails` for the given `player`.
|
|
90
|
-
pub
|
|
90
|
+
pub fn lastMove(
|
|
91
91
|
self: anytype,
|
|
92
92
|
player: Player,
|
|
93
93
|
) PointerType(@TypeOf(self), MoveDetails) {
|
|
@@ -141,7 +141,7 @@ pub const Side = extern struct {
|
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
/// Returns the stored `Pokemon` corresponding to the one-indexed party `slot`.
|
|
144
|
-
pub
|
|
144
|
+
pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
|
|
145
145
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
|
|
146
146
|
assert(slot > 0 and slot <= 6);
|
|
147
147
|
const id = self.order[slot - 1];
|
|
@@ -150,7 +150,7 @@ pub const Side = extern struct {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
/// Returns the stored `Pokemon` corresponding to the `active` Pokémon (slot 1).
|
|
153
|
-
pub
|
|
153
|
+
pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
|
|
154
154
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
|
|
155
155
|
return self.get(1);
|
|
156
156
|
}
|
|
@@ -176,7 +176,7 @@ pub const ActivePokemon = extern struct {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
/// Returns the active Pokémon's current move slot located at the one-indexed `mslot`.
|
|
179
|
-
pub
|
|
179
|
+
pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
180
180
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == ActivePokemon);
|
|
181
181
|
assert(mslot > 0 and mslot <= 4);
|
|
182
182
|
assert(self.moves[mslot - 1].id != .None);
|
|
@@ -206,7 +206,7 @@ pub const Pokemon = extern struct {
|
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
/// Returns the Pokémon's original move slot located at the one-indexed `mslot`.
|
|
209
|
-
pub
|
|
209
|
+
pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
210
210
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
|
|
211
211
|
assert(mslot > 0 and mslot <= 4);
|
|
212
212
|
assert(self.moves[mslot - 1].id != .None);
|
|
@@ -258,36 +258,36 @@ pub const Status = enum(u8) {
|
|
|
258
258
|
const SLP = 0b111;
|
|
259
259
|
|
|
260
260
|
/// Whether or not the status `num` is the same as `status`.
|
|
261
|
-
pub
|
|
261
|
+
pub fn is(num: u8, status: Status) bool {
|
|
262
262
|
if (status == .SLP) return Status.duration(num) > 0;
|
|
263
263
|
return ((num >> @intCast(@intFromEnum(status))) & 1) != 0;
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
/// Initializes a non-sleep `status`. Use `slp` or `slf` to initialize a sleep status.
|
|
267
|
-
pub
|
|
267
|
+
pub fn init(status: Status) u8 {
|
|
268
268
|
assert(status != .SLP and status != .EXT);
|
|
269
269
|
return @as(u8, 1) << @intCast(@intFromEnum(status));
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
/// Initializes a non self-inflicted sleep status with duration `dur`.
|
|
273
|
-
pub
|
|
273
|
+
pub fn slp(dur: u3) u8 {
|
|
274
274
|
assert(dur > 0);
|
|
275
275
|
return @as(u8, dur);
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
/// Initializes a self-inflicted sleep status with duration `dur`.
|
|
279
|
-
pub
|
|
279
|
+
pub fn slf(dur: u3) u8 {
|
|
280
280
|
assert(dur > 0);
|
|
281
281
|
return 0x80 | slp(dur);
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
/// Returns the duration of a sleep status.
|
|
285
|
-
pub
|
|
285
|
+
pub fn duration(num: u8) u3 {
|
|
286
286
|
return @intCast(num & SLP);
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
/// Returns whether `num` reflects any status.
|
|
290
|
-
pub
|
|
290
|
+
pub fn any(num: u8) bool {
|
|
291
291
|
return num > 0;
|
|
292
292
|
}
|
|
293
293
|
|
|
@@ -378,15 +378,15 @@ pub const Volatiles = packed struct(u64) {
|
|
|
378
378
|
/// The identity of whom the active Pokémon is transformed into.
|
|
379
379
|
transform: u4 = 0,
|
|
380
380
|
/// The remaining turns the move is disabled.
|
|
381
|
-
|
|
381
|
+
disable_duration: u4 = 0,
|
|
382
382
|
/// The move slot (1-4) that is disabled.
|
|
383
|
-
|
|
383
|
+
disable_move: u3 = 0,
|
|
384
384
|
/// The number of turns toxic damage has been accumulating.
|
|
385
385
|
toxic: u5 = 0,
|
|
386
386
|
};
|
|
387
387
|
|
|
388
388
|
test Volatiles {
|
|
389
|
-
var volatiles =
|
|
389
|
+
var volatiles: Volatiles = .{};
|
|
390
390
|
volatiles.Confusion = true;
|
|
391
391
|
volatiles.confusion = 2;
|
|
392
392
|
volatiles.Thrashing = true;
|
|
@@ -395,8 +395,8 @@ test Volatiles {
|
|
|
395
395
|
volatiles.Substitute = true;
|
|
396
396
|
volatiles.substitute = 42;
|
|
397
397
|
volatiles.toxic = 4;
|
|
398
|
-
volatiles.
|
|
399
|
-
volatiles.
|
|
398
|
+
volatiles.disable_move = 2;
|
|
399
|
+
volatiles.disable_duration = 4;
|
|
400
400
|
|
|
401
401
|
try expect(volatiles.Confusion);
|
|
402
402
|
try expect(volatiles.Thrashing);
|
|
@@ -407,8 +407,8 @@ test Volatiles {
|
|
|
407
407
|
|
|
408
408
|
try expectEqual(@as(u16, 235), volatiles.state);
|
|
409
409
|
try expectEqual(@as(u8, 42), volatiles.substitute);
|
|
410
|
-
try expectEqual(@as(u4, 2), volatiles.
|
|
411
|
-
try expectEqual(@as(u4, 4), volatiles.
|
|
410
|
+
try expectEqual(@as(u4, 2), volatiles.disable_move);
|
|
411
|
+
try expectEqual(@as(u4, 4), volatiles.disable_duration);
|
|
412
412
|
try expectEqual(@as(u4, 2), volatiles.confusion);
|
|
413
413
|
try expectEqual(@as(u5, 4), volatiles.toxic);
|
|
414
414
|
try expectEqual(@as(u4, 3), volatiles.attacks);
|
|
@@ -466,7 +466,7 @@ pub const Boosts = packed struct(u32) {
|
|
|
466
466
|
};
|
|
467
467
|
|
|
468
468
|
test Boosts {
|
|
469
|
-
const boosts =
|
|
469
|
+
const boosts: Boosts = .{ .spc = -6 };
|
|
470
470
|
try expectEqual(0, boosts.atk);
|
|
471
471
|
try expectEqual(-6, boosts.spc);
|
|
472
472
|
}
|
|
@@ -616,16 +616,16 @@ pub const DVs = struct {
|
|
|
616
616
|
};
|
|
617
617
|
|
|
618
618
|
test DVs {
|
|
619
|
-
var dvs =
|
|
619
|
+
var dvs: DVs = .{ .spc = 15, .spe = 15 };
|
|
620
620
|
try expectEqual(@as(u4, 15), dvs.hp());
|
|
621
|
-
dvs =
|
|
621
|
+
dvs = .{
|
|
622
622
|
.atk = 5,
|
|
623
623
|
.def = 15,
|
|
624
624
|
.spe = 13,
|
|
625
625
|
.spc = 13,
|
|
626
626
|
};
|
|
627
627
|
try expectEqual(@as(u4, 15), dvs.hp());
|
|
628
|
-
dvs =
|
|
628
|
+
dvs = .{
|
|
629
629
|
.def = 3,
|
|
630
630
|
.spe = 10,
|
|
631
631
|
.spc = 11,
|
package/src/lib/gen1/helpers.zig
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
}
|
|
@@ -418,7 +418,7 @@ pub const Rolls = struct {
|
|
|
418
418
|
/// and the state of the `parent` (whether the player's Pokémon's move hit).
|
|
419
419
|
///
|
|
420
420
|
/// These slots may or **may not be valid** as slots may be unset / have 0 PP.
|
|
421
|
-
pub
|
|
421
|
+
pub fn moveSlot(action: Action, parent: Optional(bool)) []const u4 {
|
|
422
422
|
if (parent == .false) return &SLOT_NONE;
|
|
423
423
|
return if (@field(action, "move_slot") == 0) &SLOT_NONE else &SLOT;
|
|
424
424
|
}
|
|
@@ -428,7 +428,7 @@ pub const Rolls = struct {
|
|
|
428
428
|
|
|
429
429
|
/// Returns a slice with the correct range of values for multi hit given the `action` state
|
|
430
430
|
/// and the state of the `parent` (whether the player's Pokémon's move hit).
|
|
431
|
-
pub
|
|
431
|
+
pub fn multiHit(action: Action, parent: Optional(bool)) []const u4 {
|
|
432
432
|
if (parent == .false) return &MULTI_NONE;
|
|
433
433
|
return if (@field(action, "multi_hit") == 0) &MULTI_NONE else &MULTI;
|
|
434
434
|
}
|
|
@@ -442,7 +442,7 @@ pub const Rolls = struct {
|
|
|
442
442
|
|
|
443
443
|
/// Returns a slice with the correct range of values for psywave given the `action` state,
|
|
444
444
|
/// the `side`, and the state of the `parent` (whether the player's Pokémon's move hit).
|
|
445
|
-
pub
|
|
445
|
+
pub fn psywave(
|
|
446
446
|
action: Action,
|
|
447
447
|
side: *data.Side,
|
|
448
448
|
parent: Optional(bool),
|
|
@@ -455,36 +455,21 @@ pub const Rolls = struct {
|
|
|
455
455
|
}
|
|
456
456
|
|
|
457
457
|
const MOVE_NONE = [_]Move{.None};
|
|
458
|
-
const MOVES = init: {
|
|
459
|
-
var moves: [Move.size - 2]Move = undefined;
|
|
460
|
-
var i: usize = 0;
|
|
461
|
-
for (@typeInfo(Move).Enum.fields) |f| {
|
|
462
|
-
if (!(std.mem.eql(u8, f.name, "None") or
|
|
463
|
-
std.mem.eql(u8, f.name, "Metronome") or
|
|
464
|
-
std.mem.eql(u8, f.name, "Struggle") or
|
|
465
|
-
std.mem.eql(u8, f.name, "SKIP_TURN")))
|
|
466
|
-
{
|
|
467
|
-
moves[i] = @field(Move, f.name);
|
|
468
|
-
i += 1;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
break :init moves;
|
|
472
|
-
};
|
|
473
458
|
|
|
474
459
|
/// Returns a slice with the correct range of values for metronome given the `action` state.
|
|
475
|
-
pub
|
|
476
|
-
return if (@field(action, "metronome") == .None) &MOVE_NONE else &
|
|
460
|
+
pub fn metronome(action: Action) []const Move {
|
|
461
|
+
return if (@field(action, "metronome") == .None) &MOVE_NONE else &Move.METRONOME;
|
|
477
462
|
}
|
|
478
463
|
};
|
|
479
464
|
|
|
480
465
|
test "Rolls.speedTie" {
|
|
481
|
-
const actions =
|
|
466
|
+
const actions: Actions = .{ .p1 = .{ .speed_tie = .P2 } };
|
|
482
467
|
try expectEqualSlices(Optional(Player), &.{ .P1, .P2 }, Rolls.speedTie(actions.p1));
|
|
483
468
|
try expectEqualSlices(Optional(Player), &.{.None}, Rolls.speedTie(actions.p2));
|
|
484
469
|
}
|
|
485
470
|
|
|
486
471
|
test "Rolls.damage" {
|
|
487
|
-
const actions =
|
|
472
|
+
const actions: Actions = .{ .p2 = .{ .damage = 221 } };
|
|
488
473
|
try expectEqual(Rolls.Range{ .min = 0, .max = 1 }, Rolls.damage(actions.p1, .None));
|
|
489
474
|
try expectEqual(Rolls.Range{ .min = 217, .max = 256 }, Rolls.damage(actions.p2, .None));
|
|
490
475
|
try expectEqual(Rolls.Range{ .min = 0, .max = 1 }, Rolls.damage(actions.p2, .false));
|
|
@@ -502,7 +487,7 @@ test "Rolls.coalesce" {
|
|
|
502
487
|
}
|
|
503
488
|
|
|
504
489
|
test "Rolls.hit" {
|
|
505
|
-
const actions =
|
|
490
|
+
const actions: Actions = .{ .p2 = .{ .hit = .true } };
|
|
506
491
|
try expectEqualSlices(Optional(bool), &.{.None}, Rolls.hit(actions.p1, .None));
|
|
507
492
|
try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.hit(actions.p2, .None));
|
|
508
493
|
try expectEqualSlices(Optional(bool), &.{.None}, Rolls.hit(actions.p2, .true));
|
|
@@ -510,7 +495,7 @@ test "Rolls.hit" {
|
|
|
510
495
|
}
|
|
511
496
|
|
|
512
497
|
test "Rolls.secondaryChance" {
|
|
513
|
-
const actions =
|
|
498
|
+
const actions: Actions = .{ .p1 = .{ .secondary_chance = .true } };
|
|
514
499
|
try expectEqualSlices(
|
|
515
500
|
Optional(bool),
|
|
516
501
|
&.{ .false, .true },
|
|
@@ -521,7 +506,7 @@ test "Rolls.secondaryChance" {
|
|
|
521
506
|
}
|
|
522
507
|
|
|
523
508
|
test "Rolls.criticalHit" {
|
|
524
|
-
const actions =
|
|
509
|
+
const actions: Actions = .{ .p1 = .{ .critical_hit = .true } };
|
|
525
510
|
try expectEqualSlices(
|
|
526
511
|
Optional(bool),
|
|
527
512
|
&.{ .false, .true },
|
|
@@ -532,14 +517,14 @@ test "Rolls.criticalHit" {
|
|
|
532
517
|
}
|
|
533
518
|
|
|
534
519
|
test "Rolls.confused" {
|
|
535
|
-
const actions =
|
|
520
|
+
const actions: Actions = .{ .p2 = .{ .confused = .true } };
|
|
536
521
|
try expectEqualSlices(Optional(bool), &.{.None}, Rolls.confused(actions.p1, 1));
|
|
537
522
|
try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.confused(actions.p2, 1));
|
|
538
523
|
try expectEqualSlices(Optional(bool), &.{.None}, Rolls.confused(actions.p2, 0));
|
|
539
524
|
}
|
|
540
525
|
|
|
541
526
|
test "Rolls.paralyzed" {
|
|
542
|
-
const actions =
|
|
527
|
+
const actions: Actions = .{ .p2 = .{ .paralyzed = .true } };
|
|
543
528
|
try expectEqualSlices(Optional(bool), &.{.None}, Rolls.paralyzed(actions.p1, .None));
|
|
544
529
|
try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.paralyzed(actions.p2, .None));
|
|
545
530
|
try expectEqualSlices(Optional(bool), &.{ .false, .true }, Rolls.paralyzed(actions.p2, .false));
|
|
@@ -547,7 +532,7 @@ test "Rolls.paralyzed" {
|
|
|
547
532
|
}
|
|
548
533
|
|
|
549
534
|
test "Rolls.duration" {
|
|
550
|
-
const actions =
|
|
535
|
+
const actions: Actions = .{ .p2 = .{ .duration = 3 } };
|
|
551
536
|
try expectEqualSlices(u1, &.{0}, Rolls.duration(actions.p1, .None));
|
|
552
537
|
try expectEqualSlices(u1, &.{1}, Rolls.duration(actions.p2, .None));
|
|
553
538
|
try expectEqualSlices(u1, &.{0}, Rolls.duration(actions.p2, .false));
|
|
@@ -757,27 +742,27 @@ test "Rolls.binding" {
|
|
|
757
742
|
}
|
|
758
743
|
|
|
759
744
|
test "Rolls.moveSlot" {
|
|
760
|
-
const actions =
|
|
745
|
+
const actions: Actions = .{ .p2 = .{ .move_slot = 3 } };
|
|
761
746
|
try expectEqualSlices(u4, &.{0}, Rolls.moveSlot(actions.p1, .None));
|
|
762
747
|
try expectEqualSlices(u4, &.{ 1, 2, 3, 4 }, Rolls.moveSlot(actions.p2, .None));
|
|
763
748
|
try expectEqualSlices(u4, &.{0}, Rolls.moveSlot(actions.p2, .false));
|
|
764
749
|
}
|
|
765
750
|
|
|
766
751
|
test "Rolls.multiHit" {
|
|
767
|
-
const actions =
|
|
752
|
+
const actions: Actions = .{ .p2 = .{ .multi_hit = 3 } };
|
|
768
753
|
try expectEqualSlices(u4, &.{0}, Rolls.multiHit(actions.p1, .None));
|
|
769
754
|
try expectEqualSlices(u4, &.{ 2, 3, 4, 5 }, Rolls.multiHit(actions.p2, .None));
|
|
770
755
|
try expectEqualSlices(u4, &.{0}, Rolls.multiHit(actions.p2, .false));
|
|
771
756
|
}
|
|
772
757
|
|
|
773
758
|
test "Rolls.metronome" {
|
|
774
|
-
const actions =
|
|
759
|
+
const actions: Actions = .{ .p2 = .{ .metronome = .Surf } };
|
|
775
760
|
try expectEqualSlices(Move, &.{.None}, Rolls.metronome(actions.p1));
|
|
776
761
|
try expectEqual(@as(Move, @enumFromInt(24)), Rolls.metronome(actions.p2)[23]);
|
|
777
762
|
}
|
|
778
763
|
|
|
779
764
|
test "Rolls.psywave" {
|
|
780
|
-
const actions =
|
|
765
|
+
const actions: Actions = .{ .p2 = .{ .psywave = 79 } };
|
|
781
766
|
var side = Side.init(&[_]Pokemon{.{
|
|
782
767
|
.species = .Bulbasaur,
|
|
783
768
|
.level = 100,
|