@pkmn/engine 0.1.0-dev.dc33f678 → 0.1.0-dev.deda8593
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/LICENSE +1 -3
- package/README.md +44 -19
- package/build/pkg/addon.js +6 -7
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data.d.ts +4 -4
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +2 -1
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.js +5 -5
- package/build/pkg/protocol.js.map +1 -1
- package/build/test/display.js +2 -2
- package/build/test/display.js.map +1 -1
- package/build/tools/debug.js +5 -4
- package/build/tools/debug.js.map +1 -1
- package/build.zig +100 -102
- package/package.json +33 -22
- package/src/bin/install-pkmn-engine +26 -18
- package/src/lib/common/data.zig +8 -8
- package/src/lib/common/debug.zig +2 -2
- package/src/lib/common/optional.zig +1 -1
- package/src/lib/common/options.zig +2 -0
- package/src/lib/common/protocol.zig +397 -384
- package/src/lib/common/rational.zig +11 -8
- package/src/lib/common/rng.zig +20 -11
- package/src/lib/gen1/calc.zig +217 -47
- package/src/lib/gen1/chance.zig +91 -92
- package/src/lib/gen1/data/moves.zig +10 -10
- package/src/lib/gen1/data/species.zig +3 -3
- package/src/lib/gen1/data/types.zig +5 -5
- package/src/lib/gen1/data.zig +35 -35
- package/src/lib/gen1/helpers.zig +136 -55
- package/src/lib/gen1/mechanics.zig +333 -312
- package/src/lib/gen2/calc.zig +143 -0
- package/src/lib/gen2/chance.zig +1315 -0
- package/src/lib/gen2/data/items.zig +3 -3
- package/src/lib/gen2/data/moves.zig +5 -5
- package/src/lib/gen2/data/species.zig +1 -1
- package/src/lib/gen2/data/types.zig +10 -10
- package/src/lib/gen2/data.zig +27 -37
- package/src/lib/gen2/generated.zig +806 -0
- package/src/lib/gen2/helpers.zig +37 -7
- package/src/lib/gen2/mechanics.zig +1621 -456
- package/src/lib/{binding/node.zig → node.zig} +9 -12
- package/src/lib/pkmn.zig +27 -12
- package/src/lib/{binding/wasm.zig → wasm.zig} +2 -1
- package/src/test/display/pkmn.html.tmpl +5 -5
- package/src/lib/gen1/README.md +0 -894
- package/src/lib/gen2/README.md +0 -330
package/src/lib/gen1/chance.zig
CHANGED
|
@@ -14,7 +14,7 @@ const util = @import("../common/util.zig");
|
|
|
14
14
|
const Player = @import("../common/data.zig").Player;
|
|
15
15
|
const Optional = @import("../common/optional.zig").Optional;
|
|
16
16
|
|
|
17
|
-
const data = @import("
|
|
17
|
+
const data = @import("data.zig");
|
|
18
18
|
|
|
19
19
|
const enabled = options.chance;
|
|
20
20
|
const showdown = options.showdown;
|
|
@@ -37,19 +37,19 @@ pub const Actions = extern struct {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/// Returns the `Action` for the given `player`.
|
|
40
|
-
pub
|
|
40
|
+
pub fn get(self: anytype, player: Player) util.PointerType(@TypeOf(self), Action) {
|
|
41
41
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Actions);
|
|
42
42
|
return if (player == .P1) &self.p1 else &self.p2;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/// Perform a reset by clearing fields which should not persist across updates.
|
|
46
|
-
pub
|
|
46
|
+
pub fn reset(self: *Actions) void {
|
|
47
47
|
self.p1.reset();
|
|
48
48
|
self.p2.reset();
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/// Returns true if `a` is equal to `b`.
|
|
52
|
-
pub
|
|
52
|
+
pub fn eql(a: Actions, b: Actions) bool {
|
|
53
53
|
return @as(u128, @bitCast(a)) == @as(u128, @bitCast(b));
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -92,13 +92,14 @@ pub const Actions = extern struct {
|
|
|
92
92
|
}
|
|
93
93
|
};
|
|
94
94
|
|
|
95
|
+
// TODO: ziglang/zig#19730
|
|
95
96
|
test Actions {
|
|
96
97
|
const a: Actions = .{ .p1 = .{ .hit = .true, .critical_hit = .false, .damage = 245 } };
|
|
97
98
|
const b: Actions = .{ .p1 = .{ .hit = .false, .critical_hit = .true, .damage = 246 } };
|
|
98
99
|
const c: Actions = .{ .p1 = .{ .hit = .true } };
|
|
99
|
-
const d: Actions = .{ .p2 = .{ .hit = .true, .durations = .{ .sleep = 2 } } };
|
|
100
|
-
const e: Actions = .{ .p2 = .{ .hit = .false, .durations = .{ .sleep = 4 } } };
|
|
101
|
-
const f: Actions = .{ .p1 = .{ .hit = .false, .durations = .{ .sleep = 4 } } };
|
|
100
|
+
// const d: Actions = .{ .p2 = .{ .hit = .true, .durations = .{ .sleep = 2 } } };
|
|
101
|
+
// const e: Actions = .{ .p2 = .{ .hit = .false, .durations = .{ .sleep = 4 } } };
|
|
102
|
+
// const f: Actions = .{ .p1 = .{ .hit = .false, .durations = .{ .sleep = 4 } } };
|
|
102
103
|
|
|
103
104
|
try expect(a.eql(a));
|
|
104
105
|
try expect(!a.eql(b));
|
|
@@ -111,8 +112,8 @@ test Actions {
|
|
|
111
112
|
try expect(b.matches(a));
|
|
112
113
|
try expect(!a.matches(c));
|
|
113
114
|
try expect(!c.matches(a));
|
|
114
|
-
try expect(d.matches(e));
|
|
115
|
-
try expect(!d.matches(f));
|
|
115
|
+
// try expect(d.matches(e));
|
|
116
|
+
// try expect(!d.matches(f));
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
/// Information about the RNG that was observed during a Generation I battle `update` for a
|
|
@@ -159,7 +160,7 @@ pub const Action = packed struct(u64) {
|
|
|
159
160
|
pub const Field = std.meta.FieldEnum(Action);
|
|
160
161
|
|
|
161
162
|
/// Perform a reset by clearing fields which should not persist across updates.
|
|
162
|
-
pub
|
|
163
|
+
pub fn reset(self: *Action) void {
|
|
163
164
|
self.* = @bitCast(@as(u64, @bitCast(self.*)) & DURATIONS);
|
|
164
165
|
}
|
|
165
166
|
|
|
@@ -254,6 +255,8 @@ pub const Duration = packed struct(u16) {
|
|
|
254
255
|
|
|
255
256
|
pub const Commit = enum { hit, miss, binding };
|
|
256
257
|
|
|
258
|
+
const uN = if (options.miss) u8 else u9;
|
|
259
|
+
|
|
257
260
|
/// Tracks chance actions and their associated probability during a Generation I battle update when
|
|
258
261
|
/// `options.chance` is enabled.
|
|
259
262
|
pub fn Chance(comptime Rational: type) type {
|
|
@@ -290,15 +293,12 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
290
293
|
//
|
|
291
294
|
// Finally, because each player's actions are processed sequentially we only need a single
|
|
292
295
|
// shared structure to track this information (though it needs to be cleared appropriately)
|
|
293
|
-
pending: if (showdown) struct {
|
|
294
|
-
hit: bool = false,
|
|
295
|
-
hit_probablity: u8 = 0,
|
|
296
|
-
} else struct {
|
|
296
|
+
pending: if (showdown) struct {} else struct {
|
|
297
297
|
crit: bool = false,
|
|
298
298
|
crit_probablity: u8 = 0,
|
|
299
299
|
damage_roll: u8 = 0,
|
|
300
300
|
hit: bool = false,
|
|
301
|
-
hit_probablity:
|
|
301
|
+
hit_probablity: uN = 0,
|
|
302
302
|
binding: u8 = 0,
|
|
303
303
|
} = .{},
|
|
304
304
|
|
|
@@ -307,25 +307,29 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
307
307
|
|
|
308
308
|
/// Convenience helper to clear fields which typically should be cleared between updates.
|
|
309
309
|
pub fn reset(self: *Self) void {
|
|
310
|
+
if (!enabled) return;
|
|
311
|
+
|
|
310
312
|
self.probability.reset();
|
|
311
313
|
self.actions.reset();
|
|
312
314
|
self.pending = .{};
|
|
313
315
|
}
|
|
314
316
|
|
|
315
317
|
pub fn commit(self: *Self, player: Player, kind: Commit) Error!void {
|
|
318
|
+
if (!enabled) return;
|
|
319
|
+
|
|
320
|
+
assert(!showdown);
|
|
321
|
+
|
|
316
322
|
var action = self.actions.get(player);
|
|
317
323
|
|
|
318
324
|
// We need to handle binding specially because we still need to commit it when attacking
|
|
319
325
|
// into a Pokémon that is immune
|
|
320
|
-
if (
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
if (kind == .binding) return;
|
|
328
|
-
} else assert(kind != .binding);
|
|
326
|
+
if (kind != .miss and self.pending.binding != 0) {
|
|
327
|
+
assert(action.duration == 0);
|
|
328
|
+
action.duration = @intCast(self.pending.binding);
|
|
329
|
+
assert(action.durations.binding == 0);
|
|
330
|
+
action.durations.binding = 1;
|
|
331
|
+
}
|
|
332
|
+
if (kind == .binding) return;
|
|
329
333
|
|
|
330
334
|
// Always commit the hit result if we make it here (commit won't be called at all if the
|
|
331
335
|
// target is immune/behind a sub/etc)
|
|
@@ -334,19 +338,19 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
334
338
|
action.hit = if (self.pending.hit) .true else .false;
|
|
335
339
|
}
|
|
336
340
|
|
|
337
|
-
|
|
341
|
+
// If the move actually lands we can commit any past critical hit / damage rolls. Note
|
|
342
|
+
// we can't rely on the presence or absence of a damage roll to determine whether a
|
|
343
|
+
// "critical hit" was spurious or not as moves that do 1 or less damage don't rol for
|
|
344
|
+
// damage but can still crit (instead, whether or not a roll is deemed to be a no-op is
|
|
345
|
+
// passed to the critical hit helper)
|
|
346
|
+
if (kind != .hit) return assert(!self.pending.crit or self.pending.crit_probablity > 0);
|
|
338
347
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
assert(!self.pending.crit or self.pending.crit_probablity > 0);
|
|
344
|
-
|
|
345
|
-
if (self.pending.crit_probablity != 0) {
|
|
346
|
-
try self.probability.update(self.pending.crit_probablity, 256);
|
|
347
|
-
action.critical_hit = if (self.pending.crit) .true else .false;
|
|
348
|
-
}
|
|
348
|
+
if (self.pending.crit_probablity != 0) {
|
|
349
|
+
try self.probability.update(self.pending.crit_probablity, 256);
|
|
350
|
+
action.critical_hit = if (self.pending.crit) .true else .false;
|
|
351
|
+
}
|
|
349
352
|
|
|
353
|
+
if (self.pending.damage_roll > 0) {
|
|
350
354
|
try self.probability.update(1, 39);
|
|
351
355
|
action.damage = self.pending.damage_roll;
|
|
352
356
|
}
|
|
@@ -397,12 +401,17 @@ pub fn Chance(comptime Rational: type) type {
|
|
|
397
401
|
self.actions.p2.speed_tie = self.actions.p1.speed_tie;
|
|
398
402
|
}
|
|
399
403
|
|
|
400
|
-
pub fn hit(self: *Self, ok: bool, accuracy:
|
|
404
|
+
pub fn hit(self: *Self, player: Player, ok: bool, accuracy: uN) Error!void {
|
|
401
405
|
if (!enabled) return;
|
|
402
406
|
|
|
403
407
|
const p = if (ok) accuracy else @as(u8, @intCast(256 - @as(u9, accuracy)));
|
|
404
|
-
|
|
405
|
-
|
|
408
|
+
if (showdown) {
|
|
409
|
+
try self.probability.update(p, 256);
|
|
410
|
+
self.actions.get(player).hit = if (ok) .true else .false;
|
|
411
|
+
} else {
|
|
412
|
+
self.pending.hit = ok;
|
|
413
|
+
self.pending.hit_probablity = p;
|
|
414
|
+
}
|
|
406
415
|
}
|
|
407
416
|
|
|
408
417
|
pub fn criticalHit(self: *Self, player: Player, crit: bool, rate: u8) Error!void {
|
|
@@ -620,19 +629,25 @@ test "Chance.speedTie" {
|
|
|
620
629
|
test "Chance.hit" {
|
|
621
630
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
622
631
|
|
|
623
|
-
chance.hit(true, 229);
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
632
|
+
try chance.hit(.P1, true, 229);
|
|
633
|
+
if (!showdown) {
|
|
634
|
+
try expectProbability(&chance.probability, 1, 1);
|
|
635
|
+
try expectValue(Optional(bool).None, chance.actions.p1.hit);
|
|
636
|
+
|
|
637
|
+
try chance.commit(.P1, .hit);
|
|
638
|
+
}
|
|
627
639
|
try expectValue(Optional(bool).true, chance.actions.p1.hit);
|
|
628
640
|
try expectProbability(&chance.probability, 229, 256);
|
|
629
641
|
|
|
630
642
|
chance.reset();
|
|
631
643
|
|
|
632
|
-
chance.hit(false, 255);
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
644
|
+
try chance.hit(.P2, false, 255);
|
|
645
|
+
if (!showdown) {
|
|
646
|
+
try expectProbability(&chance.probability, 1, 1);
|
|
647
|
+
try expectValue(Optional(bool).None, chance.actions.p2.hit);
|
|
648
|
+
|
|
649
|
+
try chance.commit(.P2, .miss);
|
|
650
|
+
}
|
|
636
651
|
try expectValue(Optional(bool).false, chance.actions.p2.hit);
|
|
637
652
|
try expectProbability(&chance.probability, 1, 256);
|
|
638
653
|
}
|
|
@@ -648,26 +663,18 @@ test "Chance.criticalHit" {
|
|
|
648
663
|
try expectProbability(&chance.probability, 1, 1);
|
|
649
664
|
try expectValue(Optional(bool).None, chance.actions.p1.critical_hit);
|
|
650
665
|
|
|
651
|
-
try chance.
|
|
652
|
-
try expectProbability(&chance.probability, 1, 1);
|
|
653
|
-
try expectValue(Optional(bool).None, chance.actions.p1.critical_hit);
|
|
654
|
-
|
|
655
|
-
chance.hit(true, 128);
|
|
666
|
+
try chance.hit(.P1, true, 128);
|
|
656
667
|
|
|
657
|
-
try chance.
|
|
658
|
-
try expectProbability(&chance.probability, 1, 2);
|
|
668
|
+
try expectProbability(&chance.probability, 1, 1);
|
|
659
669
|
try expectValue(Optional(bool).None, chance.actions.p1.critical_hit);
|
|
660
670
|
|
|
661
|
-
chance.probability.reset();
|
|
662
671
|
try chance.damage(.P1, 217);
|
|
663
672
|
|
|
664
|
-
try chance.
|
|
665
|
-
try expectProbability(&chance.probability, 1, 2);
|
|
673
|
+
try expectProbability(&chance.probability, 1, 1);
|
|
666
674
|
try expectValue(Optional(bool).None, chance.actions.p1.critical_hit);
|
|
667
675
|
|
|
668
|
-
chance.probability.reset();
|
|
669
|
-
|
|
670
676
|
try chance.commit(.P1, .hit);
|
|
677
|
+
|
|
671
678
|
try expectProbability(&chance.probability, 17, 19968); // (1/2) * (17/256) * (1/39)
|
|
672
679
|
try expectValue(Optional(bool).true, chance.actions.p1.critical_hit);
|
|
673
680
|
}
|
|
@@ -682,20 +689,14 @@ test "Chance.criticalHit" {
|
|
|
682
689
|
try expectProbability(&chance.probability, 1, 1);
|
|
683
690
|
try expectValue(Optional(bool).None, chance.actions.p1.critical_hit);
|
|
684
691
|
|
|
685
|
-
try chance.
|
|
686
|
-
try expectProbability(&chance.probability, 1, 1);
|
|
687
|
-
try expectValue(Optional(bool).None, chance.actions.p1.critical_hit);
|
|
688
|
-
|
|
689
|
-
chance.hit(true, 128);
|
|
692
|
+
try chance.hit(.P1, true, 128);
|
|
690
693
|
|
|
691
|
-
try chance.
|
|
692
|
-
try expectProbability(&chance.probability, 1, 2);
|
|
694
|
+
try expectProbability(&chance.probability, 1, 1);
|
|
693
695
|
try expectValue(Optional(bool).None, chance.actions.p1.critical_hit);
|
|
694
696
|
|
|
695
|
-
chance.probability.reset();
|
|
696
697
|
try chance.damage(.P1, 217);
|
|
697
|
-
|
|
698
698
|
try chance.commit(.P1, .hit);
|
|
699
|
+
|
|
699
700
|
try expectProbability(&chance.probability, 251, 19968); // (1/2) * (251/256) * (1/39)
|
|
700
701
|
try expectValue(Optional(bool).false, chance.actions.p1.critical_hit);
|
|
701
702
|
}
|
|
@@ -706,19 +707,16 @@ test "Chance.damage" {
|
|
|
706
707
|
|
|
707
708
|
try chance.damage(.P1, 217);
|
|
708
709
|
if (showdown) {
|
|
709
|
-
try expectValue(
|
|
710
|
+
try expectValue(217, chance.actions.p1.damage);
|
|
710
711
|
try expectProbability(&chance.probability, 1, 39);
|
|
711
712
|
} else {
|
|
712
713
|
try expectProbability(&chance.probability, 1, 1);
|
|
713
|
-
try expectValue(
|
|
714
|
-
|
|
715
|
-
try chance.commit(.P1, .miss);
|
|
716
|
-
try expectProbability(&chance.probability, 1, 1);
|
|
717
|
-
try expectValue(@as(u8, 0), chance.actions.p1.damage);
|
|
714
|
+
try expectValue(0, chance.actions.p1.damage);
|
|
718
715
|
|
|
719
716
|
try chance.commit(.P1, .hit);
|
|
717
|
+
|
|
720
718
|
try expectProbability(&chance.probability, 1, 39);
|
|
721
|
-
try expectValue(
|
|
719
|
+
try expectValue(217, chance.actions.p1.damage);
|
|
722
720
|
}
|
|
723
721
|
}
|
|
724
722
|
|
|
@@ -770,13 +768,13 @@ test "Chance.moveSlot" {
|
|
|
770
768
|
|
|
771
769
|
try chance.moveSlot(.P2, 2, &ms, 2);
|
|
772
770
|
try expectProbability(&chance.probability, 1, 2);
|
|
773
|
-
try expectValue(
|
|
771
|
+
try expectValue(2, chance.actions.p2.move_slot);
|
|
774
772
|
|
|
775
773
|
chance.reset();
|
|
776
774
|
|
|
777
775
|
try chance.moveSlot(.P1, 1, &ms, 0);
|
|
778
776
|
try expectProbability(&chance.probability, 1, 3);
|
|
779
|
-
try expectValue(
|
|
777
|
+
try expectValue(1, chance.actions.p1.move_slot);
|
|
780
778
|
}
|
|
781
779
|
|
|
782
780
|
test "Chance.multiHit" {
|
|
@@ -784,32 +782,33 @@ test "Chance.multiHit" {
|
|
|
784
782
|
|
|
785
783
|
try chance.multiHit(.P1, 3);
|
|
786
784
|
try expectProbability(&chance.probability, 3, 8);
|
|
787
|
-
try expectValue(
|
|
785
|
+
try expectValue(3, chance.actions.p1.multi_hit);
|
|
788
786
|
|
|
789
787
|
chance.reset();
|
|
790
788
|
|
|
791
789
|
try chance.multiHit(.P2, 5);
|
|
792
790
|
try expectProbability(&chance.probability, 1, 8);
|
|
793
|
-
try expectValue(
|
|
791
|
+
try expectValue(5, chance.actions.p2.multi_hit);
|
|
794
792
|
}
|
|
795
793
|
|
|
796
794
|
test "Chance.duration" {
|
|
797
795
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
798
796
|
|
|
799
797
|
chance.duration(.sleep, .P1, .P2, 2);
|
|
800
|
-
try expectValue(
|
|
801
|
-
try expectValue(
|
|
798
|
+
try expectValue(2, chance.actions.p1.duration);
|
|
799
|
+
try expectValue(1, chance.actions.p2.durations.sleep);
|
|
802
800
|
|
|
803
801
|
chance.reset();
|
|
804
802
|
|
|
805
803
|
chance.duration(.binding, .P2, .P2, 4);
|
|
806
804
|
if (!showdown) {
|
|
807
|
-
try expectValue(
|
|
808
|
-
try expectValue(
|
|
805
|
+
try expectValue(0, chance.actions.p2.duration);
|
|
806
|
+
try expectValue(0, chance.actions.p2.durations.binding);
|
|
807
|
+
|
|
809
808
|
try chance.commit(.P2, .hit);
|
|
810
809
|
}
|
|
811
|
-
try expectValue(
|
|
812
|
-
try expectValue(
|
|
810
|
+
try expectValue(4, chance.actions.p2.duration);
|
|
811
|
+
try expectValue(1, chance.actions.p2.durations.binding);
|
|
813
812
|
}
|
|
814
813
|
|
|
815
814
|
test "Chance.sleep" {
|
|
@@ -819,7 +818,7 @@ test "Chance.sleep" {
|
|
|
819
818
|
chance.actions.p1.durations.sleep = @intCast(i);
|
|
820
819
|
try chance.sleep(.P1, 0);
|
|
821
820
|
try expectProbability(&chance.probability, 1, d);
|
|
822
|
-
try expectValue(
|
|
821
|
+
try expectValue(0, chance.actions.p1.durations.sleep);
|
|
823
822
|
|
|
824
823
|
chance.reset();
|
|
825
824
|
|
|
@@ -842,7 +841,7 @@ test "Chance.confusion" {
|
|
|
842
841
|
chance.actions.p2.durations.confusion = @intCast(i);
|
|
843
842
|
try chance.confusion(.P2, 0);
|
|
844
843
|
try expectProbability(&chance.probability, 1, d);
|
|
845
|
-
try expectValue(
|
|
844
|
+
try expectValue(0, chance.actions.p2.durations.confusion);
|
|
846
845
|
|
|
847
846
|
chance.reset();
|
|
848
847
|
}
|
|
@@ -865,7 +864,7 @@ test "Chance.disable" {
|
|
|
865
864
|
chance.actions.p1.durations.disable = @intCast(i);
|
|
866
865
|
try chance.disable(.P1, 0);
|
|
867
866
|
try expectProbability(&chance.probability, 1, d);
|
|
868
|
-
try expectValue(
|
|
867
|
+
try expectValue(0, chance.actions.p1.durations.disable);
|
|
869
868
|
|
|
870
869
|
chance.reset();
|
|
871
870
|
|
|
@@ -888,7 +887,7 @@ test "Chance.attacking" {
|
|
|
888
887
|
chance.actions.p2.durations.attacking = @intCast(i);
|
|
889
888
|
try chance.attacking(.P2, 0);
|
|
890
889
|
try expectProbability(&chance.probability, 1, d);
|
|
891
|
-
try expectValue(
|
|
890
|
+
try expectValue(0, chance.actions.p2.durations.attacking);
|
|
892
891
|
|
|
893
892
|
chance.reset();
|
|
894
893
|
}
|
|
@@ -914,7 +913,7 @@ test "Chance.binding" {
|
|
|
914
913
|
chance.actions.p1.durations.binding = @intCast(i);
|
|
915
914
|
try chance.binding(.P1, 0);
|
|
916
915
|
try expectProbability(&chance.probability, p, q);
|
|
917
|
-
try expectValue(
|
|
916
|
+
try expectValue(0, chance.actions.p1.durations.binding);
|
|
918
917
|
|
|
919
918
|
chance.reset();
|
|
920
919
|
|
|
@@ -934,7 +933,7 @@ test "Chance.psywave" {
|
|
|
934
933
|
|
|
935
934
|
try chance.psywave(.P2, 100, 150);
|
|
936
935
|
try expectProbability(&chance.probability, 1, 150);
|
|
937
|
-
try expectValue(
|
|
936
|
+
try expectValue(101, chance.actions.p2.psywave);
|
|
938
937
|
}
|
|
939
938
|
|
|
940
939
|
test "Chance.metronome" {
|
|
@@ -988,8 +987,8 @@ const Null = struct {
|
|
|
988
987
|
_ = .{ self, p1 };
|
|
989
988
|
}
|
|
990
989
|
|
|
991
|
-
pub fn hit(self: Null, ok: bool, accuracy:
|
|
992
|
-
_ = .{ self, ok, accuracy };
|
|
990
|
+
pub fn hit(self: Null, player: Player, ok: bool, accuracy: uN) Error!void {
|
|
991
|
+
_ = .{ self, player, ok, accuracy };
|
|
993
992
|
}
|
|
994
993
|
|
|
995
994
|
pub fn criticalHit(self: Null, player: Player, crit: bool, rate: u8) Error!void {
|
|
@@ -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
|
|
|
@@ -1599,43 +1599,43 @@ pub const Move = enum(u8) {
|
|
|
1599
1599
|
}
|
|
1600
1600
|
|
|
1601
1601
|
/// Whether this effect activates during the "begin" step of move execution.
|
|
1602
|
-
pub
|
|
1602
|
+
pub fn onBegin(effect: Effect) bool {
|
|
1603
1603
|
return @intFromEnum(effect) > 0 and @intFromEnum(effect) <= 16;
|
|
1604
1604
|
}
|
|
1605
1605
|
|
|
1606
1606
|
/// Whether this effect lowers stats.
|
|
1607
|
-
pub
|
|
1607
|
+
pub fn isStatDown(effect: Effect) bool {
|
|
1608
1608
|
return @intFromEnum(effect) > 16 and @intFromEnum(effect) <= 21;
|
|
1609
1609
|
}
|
|
1610
1610
|
|
|
1611
1611
|
/// Whether this effect activates during the "end" step of move execution.
|
|
1612
|
-
pub
|
|
1612
|
+
pub fn onEnd(effect: Effect) bool {
|
|
1613
1613
|
return @intFromEnum(effect) > 16 and @intFromEnum(effect) <= 31;
|
|
1614
1614
|
}
|
|
1615
1615
|
|
|
1616
1616
|
/// Whether this effect is considered to "always happen".
|
|
1617
|
-
pub
|
|
1617
|
+
pub fn alwaysHappens(effect: Effect) bool {
|
|
1618
1618
|
return @intFromEnum(effect) > 31 and @intFromEnum(effect) <= 38;
|
|
1619
1619
|
}
|
|
1620
1620
|
|
|
1621
1621
|
/// Whether this effect is handled specially by the engine.
|
|
1622
|
-
pub
|
|
1622
|
+
pub fn isSpecial(effect: Effect) bool {
|
|
1623
1623
|
// NB: isSpecial includes isMulti up to Twineedle
|
|
1624
1624
|
return @intFromEnum(effect) > 31 and @intFromEnum(effect) <= 46;
|
|
1625
1625
|
}
|
|
1626
1626
|
|
|
1627
1627
|
/// Whether this effect is a multi-hit effect.
|
|
1628
|
-
pub
|
|
1628
|
+
pub fn isMulti(effect: Effect) bool {
|
|
1629
1629
|
return @intFromEnum(effect) > 44 and @intFromEnum(effect) <= 47;
|
|
1630
1630
|
}
|
|
1631
1631
|
|
|
1632
1632
|
/// Whether this effect is has chance of lowering stats.
|
|
1633
|
-
pub
|
|
1633
|
+
pub fn isStatDownChance(effect: Effect) bool {
|
|
1634
1634
|
return @intFromEnum(effect) > 47 and @intFromEnum(effect) <= 51;
|
|
1635
1635
|
}
|
|
1636
1636
|
|
|
1637
1637
|
/// Whether this effect has a secondary chance.
|
|
1638
|
-
pub
|
|
1638
|
+
pub fn isSecondaryChance(effect: Effect) bool {
|
|
1639
1639
|
// NB: isSecondaryChance includes isStatDownChance as well as Twineedle
|
|
1640
1640
|
return (@intFromEnum(effect) > 46 and @intFromEnum(effect) <= 61);
|
|
1641
1641
|
}
|
|
@@ -1853,7 +1853,7 @@ pub const Move = enum(u8) {
|
|
|
1853
1853
|
};
|
|
1854
1854
|
|
|
1855
1855
|
/// Returns the `Data` corresponding to the move.
|
|
1856
|
-
pub
|
|
1856
|
+
pub fn get(id: Move) Data {
|
|
1857
1857
|
assert(id != .None and id != .SKIP_TURN);
|
|
1858
1858
|
return DATA[@intFromEnum(id) - 1];
|
|
1859
1859
|
}
|
|
@@ -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
|
|
|
@@ -1091,8 +1091,8 @@ pub const Species = enum(u8) {
|
|
|
1091
1091
|
/// The number of Pokémon species in this generation.
|
|
1092
1092
|
pub const size = 151;
|
|
1093
1093
|
|
|
1094
|
-
/// The Pokémon's critical hit
|
|
1095
|
-
pub
|
|
1094
|
+
/// The Pokémon's critical hit ratio out of 256.
|
|
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
|
|
|
@@ -90,12 +90,12 @@ 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
|
|
|
@@ -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
|
};
|