@pkmn/engine 0.1.0-dev.a93847b2 → 0.1.0-dev.abd68573
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 +39 -16
- 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 +90 -76
- package/package.json +31 -23
- package/src/bin/install-pkmn-engine +26 -18
- package/src/lib/common/data.zig +8 -8
- package/src/lib/common/optional.zig +1 -1
- package/src/lib/common/protocol.zig +393 -396
- package/src/lib/common/rational.zig +11 -7
- package/src/lib/common/rng.zig +20 -11
- package/src/lib/gen1/calc.zig +7 -7
- package/src/lib/gen1/chance.zig +31 -30
- package/src/lib/gen1/data/moves.zig +9 -9
- package/src/lib/gen1/data/species.zig +2 -2
- package/src/lib/gen1/data/types.zig +4 -4
- package/src/lib/gen1/data.zig +32 -32
- package/src/lib/gen1/helpers.zig +48 -28
- package/src/lib/gen1/mechanics.zig +277 -255
- package/src/lib/gen2/calc.zig +1 -1
- package/src/lib/gen2/chance.zig +42 -41
- package/src/lib/gen2/data/items.zig +2 -2
- package/src/lib/gen2/data/moves.zig +2 -2
- package/src/lib/gen2/data/types.zig +9 -9
- package/src/lib/gen2/data.zig +23 -21
- package/src/lib/gen2/generated.zig +27 -78
- package/src/lib/gen2/mechanics.zig +1052 -459
- 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/lib/gen1/README.md +0 -894
- package/src/lib/gen2/README.md +0 -330
package/src/lib/gen2/calc.zig
CHANGED
|
@@ -30,7 +30,7 @@ pub const Summaries = extern struct {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/// Returns the `Summary` for the given `player`.
|
|
33
|
-
pub
|
|
33
|
+
pub fn get(self: anytype, player: Player) PointerType(@TypeOf(self), Summary) {
|
|
34
34
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Summaries);
|
|
35
35
|
return if (player == .P1) &self.p1 else &self.p2;
|
|
36
36
|
}
|
package/src/lib/gen2/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
|
p2: Action = .{},
|
|
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.p1)) == @as(u128, @bitCast(b.p1)) and
|
|
54
54
|
@as(u128, @bitCast(a.p2)) == @as(u128, @bitCast(b.p2));
|
|
55
55
|
}
|
|
@@ -97,16 +97,17 @@ pub const Actions = extern struct {
|
|
|
97
97
|
}
|
|
98
98
|
};
|
|
99
99
|
|
|
100
|
+
// TODO: ziglang/zig#19730
|
|
100
101
|
test Actions {
|
|
101
102
|
const a: Actions = .{ .p1 = .{ .hit = .true, .critical_hit = .false, .damage = 245 } };
|
|
102
103
|
const b: Actions = .{ .p1 = .{ .hit = .false, .critical_hit = .true, .damage = 246 } };
|
|
103
104
|
const c: Actions = .{ .p1 = .{ .hit = .true } };
|
|
104
|
-
const d: Actions = .{ .p2 = .{ .hit = .true, .durations = .{ .sleep = 2 } } };
|
|
105
|
-
const e: Actions = .{ .p2 = .{ .hit = .false, .durations = .{ .sleep = 4 } } };
|
|
106
|
-
const f: Actions = .{ .p1 = .{ .hit = .false, .durations = .{ .sleep = 4 } } };
|
|
107
|
-
const g: Actions = .{ .p1 = .{ .hit = .false, .durations = .{ .confusion = 1 } } };
|
|
108
|
-
const h: Actions =
|
|
109
|
-
|
|
105
|
+
// const d: Actions = .{ .p2 = .{ .hit = .true, .durations = .{ .sleep = 2 } } };
|
|
106
|
+
// const e: Actions = .{ .p2 = .{ .hit = .false, .durations = .{ .sleep = 4 } } };
|
|
107
|
+
// const f: Actions = .{ .p1 = .{ .hit = .false, .durations = .{ .sleep = 4 } } };
|
|
108
|
+
// const g: Actions = .{ .p1 = .{ .hit = .false, .durations = .{ .confusion = 1 } } };
|
|
109
|
+
// const h: Actions =
|
|
110
|
+
// .{ .p1 = .{ .hit = .false, .durations = .{ .confusion = 1, .thrash = true } } };
|
|
110
111
|
|
|
111
112
|
try expect(a.eql(a));
|
|
112
113
|
try expect(!a.eql(b));
|
|
@@ -119,10 +120,10 @@ test Actions {
|
|
|
119
120
|
try expect(b.matches(a));
|
|
120
121
|
try expect(!a.matches(c));
|
|
121
122
|
try expect(!c.matches(a));
|
|
122
|
-
try expect(d.matches(e));
|
|
123
|
-
try expect(!d.matches(f));
|
|
124
|
-
try expect(!g.matches(h));
|
|
125
|
-
try expect(h.matches(h));
|
|
123
|
+
// try expect(d.matches(e));
|
|
124
|
+
// try expect(!d.matches(f));
|
|
125
|
+
// try expect(!g.matches(h));
|
|
126
|
+
// try expect(h.matches(h));
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
/// Information about the RNG that was observed during a Generation II battle `update` for a
|
|
@@ -198,7 +199,7 @@ pub const Action = packed struct(u128) {
|
|
|
198
199
|
pub const Field = std.meta.FieldEnum(Action);
|
|
199
200
|
|
|
200
201
|
/// Perform a reset by clearing fields which should not persist across updates.
|
|
201
|
-
pub
|
|
202
|
+
pub fn reset(self: *Action) void {
|
|
202
203
|
self.* = @bitCast(@as(u128, @bitCast(self.*)) & DURATIONS);
|
|
203
204
|
}
|
|
204
205
|
|
|
@@ -699,7 +700,7 @@ test "Chance.damage" {
|
|
|
699
700
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
700
701
|
|
|
701
702
|
try chance.damage(.P1, 217);
|
|
702
|
-
try expectValue(
|
|
703
|
+
try expectValue(217, chance.actions.p1.damage);
|
|
703
704
|
try expectProbability(&chance.probability, 1, 39);
|
|
704
705
|
}
|
|
705
706
|
|
|
@@ -824,7 +825,7 @@ test "Chance.present" {
|
|
|
824
825
|
} else {
|
|
825
826
|
try expectProbability(&chance.probability, 25, 256);
|
|
826
827
|
}
|
|
827
|
-
try expectValue(
|
|
828
|
+
try expectValue(4, chance.actions.p2.present);
|
|
828
829
|
|
|
829
830
|
chance.reset();
|
|
830
831
|
|
|
@@ -834,7 +835,7 @@ test "Chance.present" {
|
|
|
834
835
|
} else {
|
|
835
836
|
try expectProbability(&chance.probability, 51, 256);
|
|
836
837
|
}
|
|
837
|
-
try expectValue(
|
|
838
|
+
try expectValue(1, chance.actions.p1.present);
|
|
838
839
|
}
|
|
839
840
|
|
|
840
841
|
test "Chance.magnitude" {
|
|
@@ -846,7 +847,7 @@ test "Chance.magnitude" {
|
|
|
846
847
|
} else {
|
|
847
848
|
try expectProbability(&chance.probability, 13, 256);
|
|
848
849
|
}
|
|
849
|
-
try expectValue(
|
|
850
|
+
try expectValue(7, chance.actions.p2.magnitude);
|
|
850
851
|
|
|
851
852
|
chance.reset();
|
|
852
853
|
|
|
@@ -856,7 +857,7 @@ test "Chance.magnitude" {
|
|
|
856
857
|
} else {
|
|
857
858
|
try expectProbability(&chance.probability, 51, 256);
|
|
858
859
|
}
|
|
859
|
-
try expectValue(
|
|
860
|
+
try expectValue(5, chance.actions.p1.magnitude);
|
|
860
861
|
}
|
|
861
862
|
|
|
862
863
|
test "Chance.tripleKick" {
|
|
@@ -864,7 +865,7 @@ test "Chance.tripleKick" {
|
|
|
864
865
|
|
|
865
866
|
try chance.tripleKick(.P1, 2);
|
|
866
867
|
try expectProbability(&chance.probability, 1, 3);
|
|
867
|
-
try expectValue(
|
|
868
|
+
try expectValue(2, chance.actions.p1.triple_kick);
|
|
868
869
|
}
|
|
869
870
|
|
|
870
871
|
test "Chance.spite" {
|
|
@@ -872,7 +873,7 @@ test "Chance.spite" {
|
|
|
872
873
|
|
|
873
874
|
try chance.spite(.P1, 3);
|
|
874
875
|
try expectProbability(&chance.probability, 1, 4);
|
|
875
|
-
try expectValue(
|
|
876
|
+
try expectValue(3, chance.actions.p1.spite);
|
|
876
877
|
}
|
|
877
878
|
|
|
878
879
|
test "Chance.conversion2" {
|
|
@@ -899,7 +900,7 @@ test "Chance.psywave" {
|
|
|
899
900
|
|
|
900
901
|
try chance.psywave(.P2, 100, 150);
|
|
901
902
|
try expectProbability(&chance.probability, 1, 150);
|
|
902
|
-
try expectValue(
|
|
903
|
+
try expectValue(100, chance.actions.p2.psywave);
|
|
903
904
|
}
|
|
904
905
|
|
|
905
906
|
test "Chance.metronome" {
|
|
@@ -915,19 +916,19 @@ test "Chance.moveSlot" {
|
|
|
915
916
|
|
|
916
917
|
try chance.moveSlot(.P2, 2, 2);
|
|
917
918
|
try expectProbability(&chance.probability, 1, 2);
|
|
918
|
-
try expectValue(
|
|
919
|
+
try expectValue(2, chance.actions.p2.move_slot);
|
|
919
920
|
|
|
920
921
|
chance.reset();
|
|
921
922
|
|
|
922
923
|
try chance.moveSlot(.P1, 1, 3);
|
|
923
924
|
try expectProbability(&chance.probability, 1, 3);
|
|
924
|
-
try expectValue(
|
|
925
|
+
try expectValue(1, chance.actions.p1.move_slot);
|
|
925
926
|
|
|
926
927
|
chance.reset();
|
|
927
928
|
|
|
928
929
|
try chance.moveSlot(.P1, 4, 1);
|
|
929
930
|
try expectProbability(&chance.probability, 1, 1);
|
|
930
|
-
try expectValue(
|
|
931
|
+
try expectValue(4, chance.actions.p1.move_slot);
|
|
931
932
|
}
|
|
932
933
|
|
|
933
934
|
test "Chance.forceSwitch" {
|
|
@@ -935,19 +936,19 @@ test "Chance.forceSwitch" {
|
|
|
935
936
|
|
|
936
937
|
try chance.forceSwitch(.P2, 2, 2);
|
|
937
938
|
try expectProbability(&chance.probability, 1, 2);
|
|
938
|
-
try expectValue(
|
|
939
|
+
try expectValue(2, chance.actions.p2.force_switch);
|
|
939
940
|
|
|
940
941
|
chance.reset();
|
|
941
942
|
|
|
942
943
|
try chance.forceSwitch(.P1, 1, 3);
|
|
943
944
|
try expectProbability(&chance.probability, 1, 3);
|
|
944
|
-
try expectValue(
|
|
945
|
+
try expectValue(1, chance.actions.p1.force_switch);
|
|
945
946
|
|
|
946
947
|
chance.reset();
|
|
947
948
|
|
|
948
949
|
try chance.forceSwitch(.P1, 4, 1);
|
|
949
950
|
try expectProbability(&chance.probability, 1, 1);
|
|
950
|
-
try expectValue(
|
|
951
|
+
try expectValue(4, chance.actions.p1.force_switch);
|
|
951
952
|
}
|
|
952
953
|
|
|
953
954
|
test "Chance.multiHit" {
|
|
@@ -955,21 +956,21 @@ test "Chance.multiHit" {
|
|
|
955
956
|
|
|
956
957
|
try chance.multiHit(.P1, 3);
|
|
957
958
|
try expectProbability(&chance.probability, 3, 8);
|
|
958
|
-
try expectValue(
|
|
959
|
+
try expectValue(3, chance.actions.p1.multi_hit);
|
|
959
960
|
|
|
960
961
|
chance.reset();
|
|
961
962
|
|
|
962
963
|
try chance.multiHit(.P2, 5);
|
|
963
964
|
try expectProbability(&chance.probability, 1, 8);
|
|
964
|
-
try expectValue(
|
|
965
|
+
try expectValue(5, chance.actions.p2.multi_hit);
|
|
965
966
|
}
|
|
966
967
|
|
|
967
968
|
test "Chance.duration" {
|
|
968
969
|
var chance: Chance(rational.Rational(u64)) = .{ .probability = .{} };
|
|
969
970
|
|
|
970
971
|
chance.duration(.sleep, .P1, .P2, 2);
|
|
971
|
-
try expectValue(
|
|
972
|
-
try expectValue(
|
|
972
|
+
try expectValue(2, chance.actions.p1.duration);
|
|
973
|
+
try expectValue(1, chance.actions.p2.durations.sleep);
|
|
973
974
|
}
|
|
974
975
|
|
|
975
976
|
test "Chance.sleep" {
|
|
@@ -979,7 +980,7 @@ test "Chance.sleep" {
|
|
|
979
980
|
chance.actions.p1.durations.sleep = @intCast(i);
|
|
980
981
|
try chance.sleep(.P1, 0);
|
|
981
982
|
try expectProbability(&chance.probability, 1, d);
|
|
982
|
-
try expectValue(
|
|
983
|
+
try expectValue(0, chance.actions.p1.durations.sleep);
|
|
983
984
|
|
|
984
985
|
chance.reset();
|
|
985
986
|
|
|
@@ -1003,7 +1004,7 @@ test "Chance.confusion" {
|
|
|
1003
1004
|
chance.actions.p2.durations.confusion = @intCast(i);
|
|
1004
1005
|
try chance.confusion(.P2, 0);
|
|
1005
1006
|
try expectProbability(&chance.probability, 1, d);
|
|
1006
|
-
try expectValue(
|
|
1007
|
+
try expectValue(0, chance.actions.p2.durations.confusion);
|
|
1007
1008
|
try expectValue(false, chance.actions.p2.durations.thrash);
|
|
1008
1009
|
|
|
1009
1010
|
chance.reset();
|
|
@@ -1028,7 +1029,7 @@ test "Chance.confusion" {
|
|
|
1028
1029
|
chance.actions.p2.durations.confusion = @intCast(i);
|
|
1029
1030
|
try chance.confusion(.P2, 0);
|
|
1030
1031
|
try expectProbability(&chance.probability, 1, d);
|
|
1031
|
-
try expectValue(
|
|
1032
|
+
try expectValue(0, chance.actions.p2.durations.confusion);
|
|
1032
1033
|
try expectValue(true, chance.actions.p2.durations.thrash);
|
|
1033
1034
|
|
|
1034
1035
|
chance.reset();
|
|
@@ -1054,7 +1055,7 @@ test "Chance.disable" {
|
|
|
1054
1055
|
chance.actions.p2.durations.disable = @intCast(i);
|
|
1055
1056
|
try chance.disable(.P2, 0);
|
|
1056
1057
|
try expectProbability(&chance.probability, 1, d);
|
|
1057
|
-
try expectValue(
|
|
1058
|
+
try expectValue(0, chance.actions.p2.durations.disable);
|
|
1058
1059
|
|
|
1059
1060
|
chance.reset();
|
|
1060
1061
|
}
|
|
@@ -1074,7 +1075,7 @@ test "Chance.disable" {
|
|
|
1074
1075
|
chance.actions.p2.durations.disable = @intCast(i);
|
|
1075
1076
|
try chance.disable(.P2, 0);
|
|
1076
1077
|
try expectProbability(&chance.probability, 1, d);
|
|
1077
|
-
try expectValue(
|
|
1078
|
+
try expectValue(0, chance.actions.p2.durations.disable);
|
|
1078
1079
|
|
|
1079
1080
|
chance.reset();
|
|
1080
1081
|
}
|
|
@@ -1099,7 +1100,7 @@ test "Chance.attacking" {
|
|
|
1099
1100
|
chance.actions.p2.durations.attacking = @intCast(i);
|
|
1100
1101
|
try chance.attacking(.P2, 0);
|
|
1101
1102
|
try expectProbability(&chance.probability, 1, d);
|
|
1102
|
-
try expectValue(
|
|
1103
|
+
try expectValue(0, chance.actions.p2.durations.attacking);
|
|
1103
1104
|
|
|
1104
1105
|
chance.reset();
|
|
1105
1106
|
}
|
|
@@ -1123,7 +1124,7 @@ test "Chance.binding" {
|
|
|
1123
1124
|
chance.actions.p2.durations.binding = @intCast(i);
|
|
1124
1125
|
try chance.binding(.P2, 0);
|
|
1125
1126
|
try expectProbability(&chance.probability, 1, d);
|
|
1126
|
-
try expectValue(
|
|
1127
|
+
try expectValue(0, chance.actions.p2.durations.binding);
|
|
1127
1128
|
|
|
1128
1129
|
chance.reset();
|
|
1129
1130
|
}
|
|
@@ -1147,7 +1148,7 @@ test "Chance.encore" {
|
|
|
1147
1148
|
chance.actions.p2.durations.encore = @intCast(i);
|
|
1148
1149
|
try chance.encore(.P2, 0);
|
|
1149
1150
|
try expectProbability(&chance.probability, 1, d);
|
|
1150
|
-
try expectValue(
|
|
1151
|
+
try expectValue(0, chance.actions.p2.durations.encore);
|
|
1151
1152
|
|
|
1152
1153
|
chance.reset();
|
|
1153
1154
|
}
|
|
@@ -216,14 +216,14 @@ pub const Item = enum(u8) {
|
|
|
216
216
|
pub const size = 196;
|
|
217
217
|
|
|
218
218
|
/// Returns a `Type` boosted by this item or `null` if the item is not a type-boosting item.
|
|
219
|
-
pub
|
|
219
|
+
pub fn boost(item: Item) ?Type {
|
|
220
220
|
assert(item != .None);
|
|
221
221
|
if (item == .PolkadotBow) return .Normal;
|
|
222
222
|
return if (@intFromEnum(item) <= 18) @enumFromInt(@intFromEnum(item) - 1) else null;
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
/// Whether or not this item is Mail.
|
|
226
|
-
pub
|
|
226
|
+
pub fn isMail(item: Item) bool {
|
|
227
227
|
assert(item != .None);
|
|
228
228
|
return @intFromEnum(item) > 60 and @intFromEnum(item) <= 70;
|
|
229
229
|
}
|
|
@@ -2562,7 +2562,7 @@ pub const Move = enum(u8) {
|
|
|
2562
2562
|
}
|
|
2563
2563
|
|
|
2564
2564
|
/// Whether this effect has a high critical rate.
|
|
2565
|
-
pub
|
|
2565
|
+
pub fn isHighCritical(effect: Effect) bool {
|
|
2566
2566
|
return effect == .HighCritical or effect == .RazorWind;
|
|
2567
2567
|
}
|
|
2568
2568
|
};
|
|
@@ -2865,7 +2865,7 @@ pub const Move = enum(u8) {
|
|
|
2865
2865
|
};
|
|
2866
2866
|
|
|
2867
2867
|
/// Returns the `Data` corresponding to the move.
|
|
2868
|
-
pub
|
|
2868
|
+
pub fn get(id: Move) Data {
|
|
2869
2869
|
assert(id != .None);
|
|
2870
2870
|
return DATA[@intFromEnum(id) - 1];
|
|
2871
2871
|
}
|
|
@@ -164,27 +164,27 @@ pub const Type = enum(u8) {
|
|
|
164
164
|
pub const size = 18;
|
|
165
165
|
|
|
166
166
|
/// Whether or not this type is considered to be special as opposed to physical.
|
|
167
|
-
pub
|
|
167
|
+
pub fn special(self: Type) bool {
|
|
168
168
|
return @intFromEnum(self) >= @intFromEnum(Type.Fire);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
/// The `Effectiveness` of type `t2` vs. type `t1`.
|
|
172
|
-
pub
|
|
172
|
+
pub fn effectiveness(t1: Type, t2: Type) Effectiveness {
|
|
173
173
|
return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
/// The precedence order of Type `type`.
|
|
177
|
-
pub
|
|
177
|
+
pub fn precedence(self: Type) u8 {
|
|
178
178
|
return PRECEDENCE[@intFromEnum(self)];
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
/// The internal index of this Type used by Present.
|
|
182
|
-
pub
|
|
182
|
+
pub fn present(self: Type) u8 {
|
|
183
183
|
return INDEXES[@intFromEnum(self)];
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
/// The Type corresponding to a random roll of `num` for Conversion 2.
|
|
187
|
-
pub
|
|
187
|
+
pub fn conversion2(num: u8) Type {
|
|
188
188
|
assert(num != 6);
|
|
189
189
|
assert(num < 10 or num >= 20);
|
|
190
190
|
assert(num <= 27);
|
|
@@ -192,7 +192,7 @@ pub const Type = enum(u8) {
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
/// The Type corresponding to a Hidden Power `index`.
|
|
195
|
-
pub
|
|
195
|
+
pub fn hiddenPower(index: u8) Type {
|
|
196
196
|
return HIDDEN_POWER[index];
|
|
197
197
|
}
|
|
198
198
|
};
|
|
@@ -209,17 +209,17 @@ pub const Types = extern struct {
|
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
/// Whether this typing is immune to type `t`.
|
|
212
|
-
pub
|
|
212
|
+
pub fn immune(self: Types, t: Type) bool {
|
|
213
213
|
return t.effectiveness(self.type1) == I or t.effectiveness(self.type2) == I;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
/// Whether this typing includes type `t`.
|
|
217
|
-
pub
|
|
217
|
+
pub fn includes(self: Types, t: Type) bool {
|
|
218
218
|
return self.type1 == t or self.type2 == t;
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
/// Whether this typing is immune to damage from Sandstorm.
|
|
222
|
-
pub
|
|
222
|
+
pub fn sandstormImmune(self: Types) bool {
|
|
223
223
|
return @intFromEnum(self.type1) <= @intFromEnum(Type.Steel) or
|
|
224
224
|
@intFromEnum(self.type2) <= @intFromEnum(Type.Steel);
|
|
225
225
|
}
|
package/src/lib/gen2/data.zig
CHANGED
|
@@ -62,17 +62,17 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
62
62
|
|
|
63
63
|
_: [padding]u8 = .{0} ** padding,
|
|
64
64
|
|
|
65
|
-
pub
|
|
65
|
+
pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
66
66
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
|
|
67
67
|
return &self.sides[@intFromEnum(player)];
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
pub
|
|
70
|
+
pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
71
71
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
|
|
72
72
|
return &self.sides[@intFromEnum(player.foe())];
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
pub
|
|
75
|
+
pub fn active(self: *const Self, player: Player) ID {
|
|
76
76
|
return player.ident(@intCast(self.side(player).pokemon[0].position));
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -133,7 +133,7 @@ pub const Side = extern struct {
|
|
|
133
133
|
assert(@sizeOf(Side) == 248);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
pub
|
|
136
|
+
pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
|
|
137
137
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
|
|
138
138
|
assert(slot > 0 and slot <= 6);
|
|
139
139
|
const id = self.pokemon[slot - 1].position;
|
|
@@ -141,19 +141,19 @@ pub const Side = extern struct {
|
|
|
141
141
|
return &self.pokemon[id - 1];
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
pub
|
|
144
|
+
pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
|
|
145
145
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
|
|
146
146
|
return self.get(1);
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
pub
|
|
149
|
+
pub fn lastMove(self: anytype, encore: bool) Move {
|
|
150
150
|
assert(self.last_used_move != .None or !self.active.volatiles.dirty);
|
|
151
151
|
if (encore) return self.last_used_move;
|
|
152
152
|
return if (self.active.volatiles.dirty) .None else self.last_used_move;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
// TODO
|
|
156
|
-
// pub
|
|
156
|
+
// pub fn useMove(self: anytype) void {
|
|
157
157
|
// assert(side.last_selected_move != .None);
|
|
158
158
|
// self.last_used_move = side.last_selected_move;
|
|
159
159
|
// self.active.volatiles.dirty = false;
|
|
@@ -175,7 +175,7 @@ pub const ActivePokemon = extern struct {
|
|
|
175
175
|
assert(@sizeOf(ActivePokemon) == 44);
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
pub
|
|
178
|
+
pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
179
179
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
|
|
180
180
|
assert(mslot > 0 and mslot <= 4);
|
|
181
181
|
assert(self.moves[mslot - 1].id != .None);
|
|
@@ -200,7 +200,7 @@ pub const Pokemon = extern struct {
|
|
|
200
200
|
assert(@sizeOf(Pokemon) == 32);
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
pub
|
|
203
|
+
pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
204
204
|
assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
|
|
205
205
|
assert(mslot > 0 and mslot <= 4);
|
|
206
206
|
assert(self.moves[mslot - 1].id != .None);
|
|
@@ -225,7 +225,7 @@ pub const DVs = packed struct(u16) {
|
|
|
225
225
|
return .{ .gender = g, .pow = p, .type = t };
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
-
pub
|
|
228
|
+
pub fn power(dvs: DVs) u8 {
|
|
229
229
|
return @as(u8, dvs.pow) + 30;
|
|
230
230
|
}
|
|
231
231
|
|
|
@@ -239,7 +239,7 @@ pub const DVs = packed struct(u16) {
|
|
|
239
239
|
};
|
|
240
240
|
const p: u6 = @intCast(1 + ((5 * @as(u8, (dvs.atk & 0b1000) | ((dvs.def & 0b1000)) >> 1 |
|
|
241
241
|
((dvs.spe & 0b1000)) >> 2 | ((dvs.spc & 0b1000)) >> 3) + (dvs.spc & 0b0011)) >> 1));
|
|
242
|
-
|
|
242
|
+
const t = @as(u8, dvs.def & 0b0011) + (@as(u8, dvs.atk & 0b0011) << 2);
|
|
243
243
|
return .{ .gender = g, .pow = p, .type = Type.hiddenPower(t) };
|
|
244
244
|
}
|
|
245
245
|
};
|
|
@@ -248,12 +248,12 @@ test DVs {
|
|
|
248
248
|
var dvs = DVs.from(.Mewtwo, .{ .def = 13 });
|
|
249
249
|
try expectEqual(Gender.Unknown, dvs.gender);
|
|
250
250
|
try expectEqual(Type.Ice, dvs.type);
|
|
251
|
-
try expectEqual(
|
|
251
|
+
try expectEqual(70, dvs.power());
|
|
252
252
|
|
|
253
253
|
dvs = DVs.from(.Pikachu, .{ .spc = 14 });
|
|
254
254
|
try expectEqual(Gender.Male, dvs.gender);
|
|
255
255
|
try expectEqual(Type.Dark, dvs.type);
|
|
256
|
-
try expectEqual(
|
|
256
|
+
try expectEqual(69, dvs.power());
|
|
257
257
|
|
|
258
258
|
dvs = DVs.from(.Cyndaquil, .{ .atk = 1, .def = 3, .spe = 10, .spc = 9 });
|
|
259
259
|
try expectEqual(Gender.Female, dvs.gender);
|
|
@@ -314,16 +314,18 @@ pub const Volatiles = packed struct(u128) {
|
|
|
314
314
|
Encore: bool = false,
|
|
315
315
|
LockOn: bool = false,
|
|
316
316
|
DestinyBond: bool = false,
|
|
317
|
+
Trapped: bool = false,
|
|
317
318
|
|
|
318
|
-
trapped: bool = false,
|
|
319
319
|
switched: bool = false,
|
|
320
|
+
// TODO: replace with simply looking at Choice on Battle
|
|
320
321
|
switching: bool = false,
|
|
322
|
+
// TODO: simply store both last moves on side
|
|
321
323
|
dirty: bool = false,
|
|
322
324
|
|
|
323
325
|
frozen: bool = false,
|
|
324
326
|
minimized: bool = false,
|
|
325
327
|
_: u10 = 0,
|
|
326
|
-
// TODO?
|
|
328
|
+
// TODO: is this needed for unmodified stats?
|
|
327
329
|
transform: u4 = 0,
|
|
328
330
|
|
|
329
331
|
bide: u16 = 0,
|
|
@@ -378,9 +380,9 @@ test Stats {
|
|
|
378
380
|
try expectEqual(0, stats.def);
|
|
379
381
|
|
|
380
382
|
var base = Species.get(.Gyarados).stats;
|
|
381
|
-
try expectEqual(
|
|
383
|
+
try expectEqual(127, Stats(u16).calc("hp", base.hp, 0, 5120, 38));
|
|
382
384
|
base = Species.get(.Pidgeot).stats;
|
|
383
|
-
try expectEqual(
|
|
385
|
+
try expectEqual(279, Stats(u16).calc("spe", base.spe, 15, 63001, 100));
|
|
384
386
|
}
|
|
385
387
|
|
|
386
388
|
pub const Boosts = packed struct(u32) {
|
|
@@ -426,8 +428,8 @@ test Move {
|
|
|
426
428
|
try expectEqual(Move.Effect.ConfusionChance, move.effect);
|
|
427
429
|
try expectEqual(rng.Gen12.percent(50), move.accuracy);
|
|
428
430
|
try expectEqual(rng.Gen12.percent(100), move.chance);
|
|
429
|
-
try expectEqual(
|
|
430
|
-
try expectEqual(
|
|
431
|
+
try expectEqual(5, Move.pp(.DynamicPunch));
|
|
432
|
+
try expectEqual(-1, Move.get(.Counter).priority);
|
|
431
433
|
try expect(!move.effect.isHighCritical());
|
|
432
434
|
try expect(Move.get(.KarateChop).effect.isHighCritical());
|
|
433
435
|
try expect(Move.get(.RazorWind).effect.isHighCritical());
|
|
@@ -437,7 +439,7 @@ pub const Species = species.Species;
|
|
|
437
439
|
|
|
438
440
|
test Species {
|
|
439
441
|
try expectEqual(152, @intFromEnum(Species.Chikorita));
|
|
440
|
-
try expectEqual(
|
|
442
|
+
try expectEqual(100, Species.get(.Celebi).stats.spd);
|
|
441
443
|
}
|
|
442
444
|
|
|
443
445
|
pub const Type = types.Type;
|
|
@@ -450,7 +452,7 @@ test Types {
|
|
|
450
452
|
try expect(!Type.Steel.special());
|
|
451
453
|
try expect(Type.Dark.special());
|
|
452
454
|
|
|
453
|
-
try expectEqual(
|
|
455
|
+
try expectEqual(3, Type.Water.precedence());
|
|
454
456
|
try expect(Type.Bug.precedence() > Type.Poison.precedence());
|
|
455
457
|
|
|
456
458
|
try expectEqual(Effectiveness.Super, Type.effectiveness(.Ghost, .Psychic));
|