@pkmn/engine 0.1.0-dev.305a932f → 0.1.0-dev.32adfe77

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 (45) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +37 -14
  3. package/build/pkg/addon.js.map +1 -1
  4. package/build/pkg/data/layout.json +2 -2
  5. package/build/pkg/data.d.ts +3 -2
  6. package/build/pkg/data.js.map +1 -1
  7. package/build/pkg/gen1.js +2 -2
  8. package/build/pkg/gen1.js.map +1 -1
  9. package/build/pkg/index.d.ts +2 -1
  10. package/build/pkg/index.js.map +1 -1
  11. package/build/pkg/protocol.js +1 -1
  12. package/build/pkg/protocol.js.map +1 -1
  13. package/build/test/display.js.map +1 -1
  14. package/build/tools/debug.js +3 -1
  15. package/build/tools/debug.js.map +1 -1
  16. package/build.zig +78 -68
  17. package/package.json +34 -23
  18. package/src/bin/install-pkmn-engine +14 -14
  19. package/src/lib/common/data.zig +8 -8
  20. package/src/lib/common/optional.zig +9 -2
  21. package/src/lib/common/protocol.zig +402 -383
  22. package/src/lib/common/rational.zig +11 -7
  23. package/src/lib/common/rng.zig +20 -11
  24. package/src/lib/gen1/README.md +28 -28
  25. package/src/lib/gen1/calc.zig +7 -7
  26. package/src/lib/gen1/chance.zig +70 -68
  27. package/src/lib/gen1/data/moves.zig +24 -10
  28. package/src/lib/gen1/data/species.zig +3 -3
  29. package/src/lib/gen1/data/types.zig +5 -5
  30. package/src/lib/gen1/data.zig +36 -36
  31. package/src/lib/gen1/helpers.zig +21 -36
  32. package/src/lib/gen1/mechanics.zig +333 -344
  33. package/src/lib/gen2/README.md +1 -2
  34. package/src/lib/gen2/calc.zig +143 -0
  35. package/src/lib/gen2/chance.zig +1314 -0
  36. package/src/lib/gen2/data/items.zig +3 -3
  37. package/src/lib/gen2/data/moves.zig +32 -15
  38. package/src/lib/gen2/data/species.zig +1 -1
  39. package/src/lib/gen2/data/types.zig +75 -28
  40. package/src/lib/gen2/data.zig +37 -25
  41. package/src/lib/gen2/generated.zig +806 -0
  42. package/src/lib/gen2/mechanics.zig +2612 -349
  43. package/src/lib/{binding/node.zig → node.zig} +9 -12
  44. package/src/lib/pkmn.zig +26 -3
  45. package/src/lib/{binding/wasm.zig → wasm.zig} +2 -1
@@ -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
 
@@ -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
  }
@@ -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
 
@@ -288,6 +288,8 @@ pub const Move = enum(u8) {
288
288
  const Extra = packed struct(u8) {
289
289
  /// Whether this move can be called via Metronome.
290
290
  metronome: bool = true,
291
+ /// Whether this move can be called via Sleep Talk.
292
+ sleep_talk: bool = true,
291
293
  /// Whether this move is considered to be "continuous".
292
294
  continuous: bool = false,
293
295
  /// Whether this move can hit a flying target.
@@ -295,7 +297,7 @@ pub const Move = enum(u8) {
295
297
  /// Whether this move can hit an underground target.
296
298
  underground: bool = false,
297
299
  /// Protocol reason offset associated with this move.
298
- protocol: u4 = 0,
300
+ protocol: u3 = 0,
299
301
  };
300
302
 
301
303
  comptime {
@@ -410,7 +412,7 @@ pub const Move = enum(u8) {
410
412
  .type = .Normal,
411
413
  .accuracy = percent(75),
412
414
  .target = .Foes,
413
- .extra = .{ .continuous = true },
415
+ .extra = .{ .sleep_talk = false, .continuous = true },
414
416
  },
415
417
  // SwordsDance
416
418
  .{
@@ -457,12 +459,12 @@ pub const Move = enum(u8) {
457
459
  },
458
460
  // Fly
459
461
  .{
460
- .effect = .Fly,
462
+ .effect = .FlyDig,
461
463
  .bp = 70,
462
464
  .type = .Flying,
463
465
  .accuracy = percent(95),
464
466
  .target = .Any,
465
- .extra = .{ .continuous = true },
467
+ .extra = .{ .sleep_talk = false, .continuous = true },
466
468
  },
467
469
  // Bind
468
470
  .{
@@ -936,12 +938,12 @@ pub const Move = enum(u8) {
936
938
  },
937
939
  // SolarBeam
938
940
  .{
939
- .effect = .Solarbeam,
941
+ .effect = .SolarBeam,
940
942
  .bp = 120,
941
943
  .type = .Grass,
942
944
  .accuracy = percent(100),
943
945
  .target = .Other,
944
- .extra = .{ .continuous = true },
946
+ .extra = .{ .sleep_talk = false, .continuous = true },
945
947
  },
946
948
  // PoisonPowder
947
949
  .{
@@ -1065,11 +1067,12 @@ pub const Move = enum(u8) {
1065
1067
  },
1066
1068
  // Dig
1067
1069
  .{
1068
- .effect = .Fly,
1070
+ .effect = .FlyDig,
1069
1071
  .bp = 60,
1070
1072
  .type = .Ground,
1071
1073
  .accuracy = percent(100),
1072
1074
  .target = .Other,
1075
+ .extra = .{ .sleep_talk = false },
1073
1076
  },
1074
1077
  // Toxic
1075
1078
  .{
@@ -1282,7 +1285,7 @@ pub const Move = enum(u8) {
1282
1285
  .type = .Normal,
1283
1286
  .accuracy = percent(100),
1284
1287
  .target = .Self,
1285
- .extra = .{ .continuous = true },
1288
+ .extra = .{ .sleep_talk = false, .continuous = true },
1286
1289
  },
1287
1290
  // Metronome
1288
1291
  .{
@@ -1394,7 +1397,7 @@ pub const Move = enum(u8) {
1394
1397
  .type = .Normal,
1395
1398
  .accuracy = percent(100),
1396
1399
  .target = .Other,
1397
- .extra = .{ .continuous = true },
1400
+ .extra = .{ .sleep_talk = false, .continuous = true },
1398
1401
  },
1399
1402
  // SpikeCannon
1400
1403
  .{
@@ -1500,7 +1503,7 @@ pub const Move = enum(u8) {
1500
1503
  .type = .Flying,
1501
1504
  .accuracy = percent(90),
1502
1505
  .target = .Any,
1503
- .extra = .{ .continuous = true },
1506
+ .extra = .{ .sleep_talk = false, .continuous = true },
1504
1507
  },
1505
1508
  // Transform
1506
1509
  .{
@@ -2463,7 +2466,7 @@ pub const Move = enum(u8) {
2463
2466
  FixedDamage,
2464
2467
  FlameWheel,
2465
2468
  FlinchChance,
2466
- Fly,
2469
+ FlyDig,
2467
2470
  FocusEnergy,
2468
2471
  ForceSwitch,
2469
2472
  Foresight,
@@ -2526,7 +2529,7 @@ pub const Move = enum(u8) {
2526
2529
  Sleep,
2527
2530
  SleepTalk,
2528
2531
  Snore,
2529
- Solarbeam,
2532
+ SolarBeam,
2530
2533
  SpAtkUp1,
2531
2534
  SpDefDownChance,
2532
2535
  SpDefUp2,
@@ -2559,7 +2562,7 @@ pub const Move = enum(u8) {
2559
2562
  }
2560
2563
 
2561
2564
  /// Whether this effect has a high critical rate.
2562
- pub inline fn isHighCritical(effect: Effect) bool {
2565
+ pub fn isHighCritical(effect: Effect) bool {
2563
2566
  return effect == .HighCritical or effect == .RazorWind;
2564
2567
  }
2565
2568
  };
@@ -2847,8 +2850,22 @@ pub const Move = enum(u8) {
2847
2850
  /// The number of Pokémon moves in this generation.
2848
2851
  pub const size = 251;
2849
2852
 
2853
+ /// Pokémon moves that can be called by Metronome in this generation.
2854
+ pub const METRONOME = init: {
2855
+ var num = 0;
2856
+ var moves: [239]Move = undefined;
2857
+ for (1..Move.size + 1) |i| {
2858
+ if (Move.get(@enumFromInt(i)).extra.metronome) {
2859
+ moves[num] = @enumFromInt(i);
2860
+ num += 1;
2861
+ }
2862
+ }
2863
+ assert(num == moves.len);
2864
+ break :init moves;
2865
+ };
2866
+
2850
2867
  /// Returns the `Data` corresponding to the move.
2851
- pub inline fn get(id: Move) Data {
2868
+ pub fn get(id: Move) Data {
2852
2869
  assert(id != .None);
2853
2870
  return DATA[@intFromEnum(id) - 1];
2854
2871
  }
@@ -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
 
@@ -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
 
@@ -96,23 +96,58 @@ pub const Type = enum(u8) {
96
96
  27, // Dark
97
97
  };
98
98
 
99
- const HIDDEN_POWER = [_]u8{
100
- 4, // Fighting
101
- 5, // Flying
102
- 6, // Poison
103
- 0, // Ground
104
- 1, // Rock
105
- 7, // Bug
106
- 8, // Ghost
107
- 2, // Steel
108
- 10, // Fire
109
- 11, // Water
110
- 12, // Grass
111
- 13, // Electric
112
- 14, // Psychic
113
- 15, // Ice
114
- 16, // Dragon
115
- 17, // Dark
99
+ const CONVERSION_2 = [_]Type{
100
+ .Normal,
101
+ .Fighting,
102
+ .Flying,
103
+ .Poison,
104
+ .Ground,
105
+ .Rock,
106
+ .@"???", // placeholder
107
+ .Bug,
108
+ .Ghost,
109
+ .Steel,
110
+ };
111
+
112
+ const HIDDEN_POWER = [_]Type{
113
+ .Fighting,
114
+ .Flying,
115
+ .Poison,
116
+ .Ground,
117
+ .Rock,
118
+ .Bug,
119
+ .Ghost,
120
+ .Steel,
121
+ .Fire,
122
+ .Water,
123
+ .Grass,
124
+ .Electric,
125
+ .Psychic,
126
+ .Ice,
127
+ .Dragon,
128
+ .Dark,
129
+ };
130
+
131
+ /// Order of Pokémon Showdown's types.
132
+ pub const SHOWDOWN = [_]Type{
133
+ .Fire,
134
+ .Ice,
135
+ .Steel,
136
+ .Electric,
137
+ .Ghost,
138
+ .Grass,
139
+ .Dark,
140
+ .Bug,
141
+ .Dragon,
142
+ .Fighting,
143
+ .Flying,
144
+ .Ground,
145
+ .Normal,
146
+ .Poison,
147
+ .Psychic,
148
+ .Rock,
149
+ .Water,
150
+ .@"???",
116
151
  };
117
152
 
118
153
  comptime {
@@ -120,34 +155,45 @@ pub const Type = enum(u8) {
120
155
  assert(@sizeOf(@TypeOf(CHART)) == 324);
121
156
  assert(@sizeOf(@TypeOf(PRECEDENCE)) == 18);
122
157
  assert(@sizeOf(@TypeOf(INDEXES)) == 18);
158
+ assert(@sizeOf(@TypeOf(CONVERSION_2)) == 10);
123
159
  assert(@sizeOf(@TypeOf(HIDDEN_POWER)) == 16);
160
+ assert(@sizeOf(@TypeOf(SHOWDOWN)) == 18);
124
161
  }
125
162
 
126
163
  /// The number of types in this generation.
127
164
  pub const size = 18;
128
165
 
129
166
  /// Whether or not this type is considered to be special as opposed to physical.
130
- pub inline fn special(self: Type) bool {
167
+ pub fn special(self: Type) bool {
131
168
  return @intFromEnum(self) >= @intFromEnum(Type.Fire);
132
169
  }
133
170
 
134
171
  /// The `Effectiveness` of type `t2` vs. type `t1`.
135
- pub inline fn effectiveness(t1: Type, t2: Type) Effectiveness {
172
+ pub fn effectiveness(t1: Type, t2: Type) Effectiveness {
136
173
  return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
137
174
  }
138
175
 
139
176
  /// The precedence order of Type `type`.
140
- pub inline fn precedence(self: Type) u8 {
177
+ pub fn precedence(self: Type) u8 {
141
178
  return PRECEDENCE[@intFromEnum(self)];
142
179
  }
180
+
143
181
  /// The internal index of this Type used by Present.
144
- pub inline fn present(self: Type) u8 {
182
+ pub fn present(self: Type) u8 {
145
183
  return INDEXES[@intFromEnum(self)];
146
184
  }
147
185
 
186
+ /// The Type corresponding to a random roll of `num` for Conversion 2.
187
+ pub fn conversion2(num: u8) Type {
188
+ assert(num != 6);
189
+ assert(num < 10 or num >= 20);
190
+ assert(num <= 27);
191
+ return if (num < 10) CONVERSION_2[num] else @enumFromInt(num - 10);
192
+ }
193
+
148
194
  /// The Type corresponding to a Hidden Power `index`.
149
- pub inline fn hiddenPower(index: u8) Type {
150
- return @enumFromInt(HIDDEN_POWER[index]);
195
+ pub fn hiddenPower(index: u8) Type {
196
+ return HIDDEN_POWER[index];
151
197
  }
152
198
  };
153
199
 
@@ -163,17 +209,18 @@ pub const Types = extern struct {
163
209
  }
164
210
 
165
211
  /// Whether this typing is immune to type `t`.
166
- pub inline fn immune(self: Types, t: Type) bool {
212
+ pub fn immune(self: Types, t: Type) bool {
167
213
  return t.effectiveness(self.type1) == I or t.effectiveness(self.type2) == I;
168
214
  }
169
215
 
170
216
  /// Whether this typing includes type `t`.
171
- pub inline fn includes(self: Types, t: Type) bool {
217
+ pub fn includes(self: Types, t: Type) bool {
172
218
  return self.type1 == t or self.type2 == t;
173
219
  }
174
220
 
175
221
  /// Whether this typing is immune to damage from Sandstorm.
176
- pub inline fn sandstormImmune(self: Types) u8 {
177
- return self.type1 <= @intFromEnum(Type.Steel) or self.type2 <= @intFromEnum(Type.Steel);
222
+ pub fn sandstormImmune(self: Types) bool {
223
+ return @intFromEnum(self.type1) <= @intFromEnum(Type.Steel) or
224
+ @intFromEnum(self.type2) <= @intFromEnum(Type.Steel);
178
225
  }
179
226
  };
@@ -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);
@@ -279,6 +279,9 @@ pub const MoveSlot = extern struct {
279
279
 
280
280
  pub const Status = gen1.Status;
281
281
 
282
+ /// TODO
283
+ pub const TriAttack = enum(u2) { PAR, FRZ, BRN };
284
+
282
285
  pub const Volatiles = packed struct(u128) {
283
286
  Bide: bool = false,
284
287
  Thrashing: bool = false,
@@ -311,19 +314,23 @@ pub const Volatiles = packed struct(u128) {
311
314
  Encore: bool = false,
312
315
  LockOn: bool = false,
313
316
  DestinyBond: bool = false,
317
+ Trapped: bool = false,
314
318
 
315
- trapped: bool = false,
316
319
  switched: bool = false,
320
+ // TODO: replace with simply looking at Choice on Battle
317
321
  switching: bool = false,
322
+ // TODO: simply store both last moves on side
318
323
  dirty: bool = false,
319
324
 
320
325
  frozen: bool = false,
321
- _: u15 = 0,
326
+ minimized: bool = false,
327
+ _: u10 = 0,
328
+ // TODO: is this needed for unmodified stats?
329
+ transform: u4 = 0,
322
330
 
323
- bind_reason: u4 = 0,
324
- bind: u4 = 0,
325
331
  bide: u16 = 0,
326
- disabled: Disabled = .{},
332
+ bind: Bind = .{},
333
+ disable: Disable = .{},
327
334
  rage: u8 = 0,
328
335
  substitute: u8 = 0,
329
336
  toxic: u8 = 0,
@@ -335,7 +342,12 @@ pub const Volatiles = packed struct(u128) {
335
342
  protect: u4 = 0,
336
343
  attacks: u4 = 0, // bide/thrashing/rollout turns
337
344
 
338
- const Disabled = packed struct(u8) {
345
+ const Bind = packed struct(u8) {
346
+ duration: u4 = 0,
347
+ reason: u4 = 0,
348
+ };
349
+
350
+ const Disable = packed struct(u8) {
339
351
  move: u4 = 0,
340
352
  duration: u4 = 0,
341
353
  };
@@ -368,9 +380,9 @@ test Stats {
368
380
  try expectEqual(0, stats.def);
369
381
 
370
382
  var base = Species.get(.Gyarados).stats;
371
- 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));
372
384
  base = Species.get(.Pidgeot).stats;
373
- 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));
374
386
  }
375
387
 
376
388
  pub const Boosts = packed struct(u32) {
@@ -416,8 +428,8 @@ test Move {
416
428
  try expectEqual(Move.Effect.ConfusionChance, move.effect);
417
429
  try expectEqual(rng.Gen12.percent(50), move.accuracy);
418
430
  try expectEqual(rng.Gen12.percent(100), move.chance);
419
- try expectEqual(@as(u8, 5), Move.pp(.DynamicPunch));
420
- try expectEqual(@as(i8, -1), Move.get(.Counter).priority);
431
+ try expectEqual(5, Move.pp(.DynamicPunch));
432
+ try expectEqual(-1, Move.get(.Counter).priority);
421
433
  try expect(!move.effect.isHighCritical());
422
434
  try expect(Move.get(.KarateChop).effect.isHighCritical());
423
435
  try expect(Move.get(.RazorWind).effect.isHighCritical());
@@ -427,7 +439,7 @@ pub const Species = species.Species;
427
439
 
428
440
  test Species {
429
441
  try expectEqual(152, @intFromEnum(Species.Chikorita));
430
- try expectEqual(@as(u8, 100), Species.get(.Celebi).stats.spd);
442
+ try expectEqual(100, Species.get(.Celebi).stats.spd);
431
443
  }
432
444
 
433
445
  pub const Type = types.Type;
@@ -440,7 +452,7 @@ test Types {
440
452
  try expect(!Type.Steel.special());
441
453
  try expect(Type.Dark.special());
442
454
 
443
- try expectEqual(@as(u8, 3), Type.Water.precedence());
455
+ try expectEqual(3, Type.Water.precedence());
444
456
  try expect(Type.Bug.precedence() > Type.Poison.precedence());
445
457
 
446
458
  try expectEqual(Effectiveness.Super, Type.effectiveness(.Ghost, .Psychic));