@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.
Files changed (44) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +39 -16
  3. package/build/pkg/addon.js +6 -7
  4. package/build/pkg/addon.js.map +1 -1
  5. package/build/pkg/data.d.ts +4 -4
  6. package/build/pkg/data.js.map +1 -1
  7. package/build/pkg/gen1.js.map +1 -1
  8. package/build/pkg/index.d.ts +2 -1
  9. package/build/pkg/index.js.map +1 -1
  10. package/build/pkg/protocol.js +5 -5
  11. package/build/pkg/protocol.js.map +1 -1
  12. package/build/test/display.js +2 -2
  13. package/build/test/display.js.map +1 -1
  14. package/build/tools/debug.js +5 -4
  15. package/build/tools/debug.js.map +1 -1
  16. package/build.zig +90 -76
  17. package/package.json +31 -23
  18. package/src/bin/install-pkmn-engine +26 -18
  19. package/src/lib/common/data.zig +8 -8
  20. package/src/lib/common/optional.zig +1 -1
  21. package/src/lib/common/protocol.zig +393 -396
  22. package/src/lib/common/rational.zig +11 -7
  23. package/src/lib/common/rng.zig +20 -11
  24. package/src/lib/gen1/calc.zig +7 -7
  25. package/src/lib/gen1/chance.zig +31 -30
  26. package/src/lib/gen1/data/moves.zig +9 -9
  27. package/src/lib/gen1/data/species.zig +2 -2
  28. package/src/lib/gen1/data/types.zig +4 -4
  29. package/src/lib/gen1/data.zig +32 -32
  30. package/src/lib/gen1/helpers.zig +48 -28
  31. package/src/lib/gen1/mechanics.zig +277 -255
  32. package/src/lib/gen2/calc.zig +1 -1
  33. package/src/lib/gen2/chance.zig +42 -41
  34. package/src/lib/gen2/data/items.zig +2 -2
  35. package/src/lib/gen2/data/moves.zig +2 -2
  36. package/src/lib/gen2/data/types.zig +9 -9
  37. package/src/lib/gen2/data.zig +23 -21
  38. package/src/lib/gen2/generated.zig +27 -78
  39. package/src/lib/gen2/mechanics.zig +1052 -459
  40. package/src/lib/{binding/node.zig → node.zig} +9 -12
  41. package/src/lib/pkmn.zig +27 -12
  42. package/src/lib/{binding/wasm.zig → wasm.zig} +2 -1
  43. package/src/lib/gen1/README.md +0 -894
  44. package/src/lib/gen2/README.md +0 -330
@@ -30,7 +30,7 @@ pub const Summaries = extern struct {
30
30
  }
31
31
 
32
32
  /// Returns the `Summary` for the given `player`.
33
- pub inline fn get(self: anytype, player: Player) PointerType(@TypeOf(self), Summary) {
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
  }
@@ -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("./data.zig");
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 inline fn get(self: anytype, player: Player) util.PointerType(@TypeOf(self), Action) {
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 inline fn reset(self: *Actions) void {
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 inline fn eql(a: Actions, b: Actions) bool {
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
- .{ .p1 = .{ .hit = .false, .durations = .{ .confusion = 1, .thrash = true } } };
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 inline fn reset(self: *Action) void {
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(@as(u8, 217), chance.actions.p1.damage);
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(@as(u3, 4), chance.actions.p2.present);
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(@as(u3, 1), chance.actions.p1.present);
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(@as(u3, 7), chance.actions.p2.magnitude);
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(@as(u3, 5), chance.actions.p1.magnitude);
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(@as(u2, 2), chance.actions.p1.triple_kick);
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(@as(u3, 3), chance.actions.p1.spite);
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(@as(u8, 100), chance.actions.p2.psywave);
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(@as(u4, 2), chance.actions.p2.move_slot);
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(@as(u4, 1), chance.actions.p1.move_slot);
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(@as(u4, 4), chance.actions.p1.move_slot);
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(@as(u4, 2), chance.actions.p2.force_switch);
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(@as(u4, 1), chance.actions.p1.force_switch);
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(@as(u4, 4), chance.actions.p1.force_switch);
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(@as(u4, 3), chance.actions.p1.multi_hit);
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(@as(u4, 5), chance.actions.p2.multi_hit);
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(@as(u4, 2), chance.actions.p1.duration);
972
- try expectValue(@as(u3, 1), chance.actions.p2.durations.sleep);
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(@as(u3, 0), chance.actions.p1.durations.sleep);
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(@as(u3, 0), chance.actions.p2.durations.confusion);
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(@as(u3, 0), chance.actions.p2.durations.confusion);
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(@as(u4, 0), chance.actions.p2.durations.disable);
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(@as(u4, 0), chance.actions.p2.durations.disable);
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(@as(u3, 0), chance.actions.p2.durations.attacking);
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(@as(u3, 0), chance.actions.p2.durations.binding);
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(@as(u3, 0), chance.actions.p2.durations.encore);
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 inline fn boost(item: Item) ?Type {
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 inline fn isMail(item: Item) bool {
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 inline fn isHighCritical(effect: Effect) bool {
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 inline fn get(id: Move) Data {
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 inline fn special(self: Type) bool {
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 inline fn effectiveness(t1: Type, t2: Type) Effectiveness {
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 inline fn precedence(self: Type) u8 {
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 inline fn present(self: Type) u8 {
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 inline fn conversion2(num: u8) Type {
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 inline fn hiddenPower(index: u8) Type {
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 inline fn immune(self: Types, t: Type) bool {
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 inline fn includes(self: Types, t: Type) bool {
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 inline fn sandstormImmune(self: Types) bool {
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
  }
@@ -62,17 +62,17 @@ pub fn Battle(comptime RNG: anytype) type {
62
62
 
63
63
  _: [padding]u8 = .{0} ** padding,
64
64
 
65
- pub inline fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
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 inline fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
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 inline fn active(self: *const Self, player: Player) ID {
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 inline fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
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 inline fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
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 inline fn lastMove(self: anytype, encore: bool) Move {
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 inline fn useMove(self: anytype) void {
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 inline fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
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 inline fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
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 inline fn power(dvs: DVs) u8 {
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
- var t = @as(u8, dvs.def & 0b0011) + (@as(u8, dvs.atk & 0b0011) << 2);
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(@as(u8, 70), dvs.power());
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(@as(u8, 69), dvs.power());
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(@as(u16, 127), Stats(u16).calc("hp", base.hp, 0, 5120, 38));
383
+ try expectEqual(127, Stats(u16).calc("hp", base.hp, 0, 5120, 38));
382
384
  base = Species.get(.Pidgeot).stats;
383
- try expectEqual(@as(u16, 279), Stats(u16).calc("spe", base.spe, 15, 63001, 100));
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(@as(u8, 5), Move.pp(.DynamicPunch));
430
- try expectEqual(@as(i8, -1), Move.get(.Counter).priority);
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(@as(u8, 100), Species.get(.Celebi).stats.spd);
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(@as(u8, 3), Type.Water.precedence());
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));