@pkmn/engine 0.1.0-dev.fb5bf955 → 0.1.0-dev.fb6653d6

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 (85) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +115 -76
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +44 -0
  5. package/build/pkg/addon/browser.js.map +1 -0
  6. package/build/pkg/addon/node.d.ts +3 -0
  7. package/build/pkg/addon/node.js +97 -0
  8. package/build/pkg/addon/node.js.map +1 -0
  9. package/build/pkg/addon/wasm.d.ts +2 -0
  10. package/build/pkg/addon/wasm.js +53 -0
  11. package/build/pkg/addon/wasm.js.map +1 -0
  12. package/build/pkg/addon.d.ts +27 -5
  13. package/build/pkg/addon.js +42 -73
  14. package/build/pkg/addon.js.map +1 -1
  15. package/build/pkg/data/ids.json +12 -12
  16. package/build/pkg/data/layout.json +40 -5
  17. package/build/pkg/data/protocol.json +84 -13
  18. package/build/pkg/data.d.ts +27 -5
  19. package/build/pkg/data.js.map +1 -1
  20. package/build/pkg/gen1.d.ts +16 -19
  21. package/build/pkg/gen1.js +54 -42
  22. package/build/pkg/gen1.js.map +1 -1
  23. package/build/pkg/index.d.ts +55 -103
  24. package/build/pkg/index.js +6 -63
  25. package/build/pkg/index.js.map +1 -1
  26. package/build/pkg/protocol.d.ts +24 -3
  27. package/build/pkg/protocol.js +127 -104
  28. package/build/pkg/protocol.js.map +1 -1
  29. package/build/tools/debug.js +36 -69
  30. package/build/tools/debug.js.map +1 -1
  31. package/build/tools/display/debug.jsx +141 -0
  32. package/build/tools/display/debug.jsx.map +1 -0
  33. package/build/tools/display/index.js +142 -0
  34. package/build/tools/display/index.js.map +1 -0
  35. package/build/tools/display/ui.jsx +349 -0
  36. package/build/tools/display/ui.jsx.map +1 -0
  37. package/build/tools/display/util.js +18 -0
  38. package/build/tools/display/util.js.map +1 -0
  39. package/build.zig +373 -152
  40. package/package.json +68 -120
  41. package/src/bin/install-pkmn-engine +41 -26
  42. package/src/bin/pkmn-debug +29 -6
  43. package/src/lib/bindings/node.zig +121 -0
  44. package/src/lib/bindings/wasm.zig +58 -0
  45. package/src/lib/common/array.zig +77 -0
  46. package/src/lib/common/battle.zig +17 -0
  47. package/src/lib/common/data.zig +19 -31
  48. package/src/lib/common/debug.zig +58 -17
  49. package/src/lib/common/js.zig +120 -0
  50. package/src/lib/common/optional.zig +71 -0
  51. package/src/lib/common/options.zig +18 -3
  52. package/src/lib/common/protocol.zig +947 -407
  53. package/src/lib/common/rational.zig +449 -0
  54. package/src/lib/common/rng.zig +31 -24
  55. package/src/lib/common/util.zig +61 -0
  56. package/src/lib/gen1/calc.zig +953 -0
  57. package/src/lib/gen1/chance.zig +1185 -0
  58. package/src/lib/gen1/data/moves.zig +203 -193
  59. package/src/lib/gen1/data/species.zig +6 -8
  60. package/src/lib/gen1/data/types.zig +11 -12
  61. package/src/lib/gen1/data.zig +100 -89
  62. package/src/lib/gen1/helpers.zig +139 -50
  63. package/src/lib/gen1/mechanics.zig +1344 -907
  64. package/src/lib/gen2/calc.zig +153 -0
  65. package/src/lib/gen2/chance.zig +902 -0
  66. package/src/lib/gen2/data/items.zig +15 -23
  67. package/src/lib/gen2/data/moves.zig +665 -573
  68. package/src/lib/gen2/data/species.zig +3 -5
  69. package/src/lib/gen2/data/types.zig +138 -36
  70. package/src/lib/gen2/data.zig +134 -99
  71. package/src/lib/gen2/generated.zig +801 -0
  72. package/src/lib/gen2/helpers.zig +59 -44
  73. package/src/lib/gen2/mechanics.zig +3582 -30
  74. package/src/lib/node.zig +18 -0
  75. package/src/lib/pkmn.zig +93 -12
  76. package/src/lib/wasm.zig +17 -0
  77. package/src/tools/display/dom.ts +96 -0
  78. package/src/tools/display/ui.css +354 -0
  79. package/build/test/display.js +0 -382
  80. package/build/test/display.js.map +0 -1
  81. package/src/lib/binding/node.zig +0 -229
  82. package/src/lib/binding/wasm.zig +0 -10
  83. package/src/lib/gen1/README.md +0 -784
  84. package/src/lib/gen2/README.md +0 -309
  85. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -1,46 +1,54 @@
1
- const std = @import("std");
2
- const builtin = @import("builtin");
3
-
4
- const data = @import("../common/data.zig");
5
1
  const DEBUG = @import("../common/debug.zig").print;
6
- const options = @import("../common/options.zig");
7
- const rng = @import("../common/rng.zig");
8
2
 
3
+ const builtin = @import("builtin");
4
+ const calc = @import("calc.zig");
5
+ const chance = @import("chance.zig");
6
+ const data = @import("../common/data.zig");
7
+ const gen1 = @import("../gen1/data.zig");
9
8
  const items = @import("data/items.zig");
9
+ const mechanics = @import("mechanics.zig");
10
10
  const moves = @import("data/moves.zig");
11
+ const pkmn = @import("../pkmn.zig");
12
+ const protocol = @import("../common/protocol.zig");
13
+ const rng = @import("../common/rng.zig");
11
14
  const species = @import("data/species.zig");
15
+ const std = @import("std");
12
16
  const types = @import("data/types.zig");
13
-
14
- const gen1 = @import("../gen1/data.zig");
15
-
16
- const mechanics = @import("mechanics.zig");
17
+ const util = @import("../common/util.zig");
17
18
 
18
19
  const assert = std.debug.assert;
19
20
  const expectEqual = std.testing.expectEqual;
20
21
  const expect = std.testing.expect;
21
22
 
22
- pub const MAX_OPTIONS: usize = 9; // move 1..4, switch 2..6
23
+ pub const MAX_CHOICES: usize = 9; // move 1..4, switch 2..6
23
24
  pub const MAX_LOGS: usize = 180; // TODO
24
25
 
25
- pub const OPTIONS_SIZE = if (builtin.mode == .ReleaseSmall)
26
- MAX_OPTIONS
26
+ pub const CHOICES_SIZE = if (builtin.mode == .ReleaseSmall)
27
+ MAX_CHOICES
27
28
  else
28
- std.math.ceilPowerOfTwo(usize, MAX_OPTIONS) catch unreachable;
29
+ std.math.ceilPowerOfTwo(usize, MAX_CHOICES) catch unreachable;
29
30
  pub const LOGS_SIZE = if (builtin.mode == .ReleaseSmall)
30
31
  MAX_LOGS
31
32
  else
32
33
  std.math.ceilPowerOfTwo(usize, MAX_LOGS) catch unreachable;
33
34
 
35
+ /// Null object pattern implementation of pkmn.battle.Options for Generation II.
36
+ pub const NULL = pkmn.battle.options(protocol.NULL, chance.NULL, calc.NULL);
37
+
34
38
  const Choice = data.Choice;
35
39
  const ID = data.ID;
36
40
  const Player = data.Player;
37
41
  const Result = data.Result;
38
42
 
39
- const showdown = options.showdown;
43
+ const PointerType = util.PointerType;
44
+ const isPointerTo = util.isPointerTo;
45
+
46
+ const showdown = pkmn.options.showdown;
40
47
 
41
48
  pub const PRNG = rng.PRNG(2);
42
49
 
43
50
  pub fn Battle(comptime RNG: anytype) type {
51
+ const padding = if (!showdown) 3 else 5;
44
52
  return extern struct {
45
53
  const Self = @This();
46
54
 
@@ -49,20 +57,24 @@ pub fn Battle(comptime RNG: anytype) type {
49
57
  turn: u16 = 0,
50
58
  field: Field = .{},
51
59
 
52
- pub inline fn side(self: *Self, player: Player) *Side {
53
- return &self.sides[@enumToInt(player)];
60
+ _: [padding]u8 = .{0} ** padding,
61
+
62
+ pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
63
+ assert(isPointerTo(self, Self));
64
+ return &self.sides[@intFromEnum(player)];
54
65
  }
55
66
 
56
- pub inline fn foe(self: *Self, player: Player) *Side {
57
- return &self.sides[@enumToInt(player.foe())];
67
+ pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
68
+ assert(isPointerTo(self, Self));
69
+ return &self.sides[@intFromEnum(player.foe())];
58
70
  }
59
71
 
60
- pub inline fn active(self: *Self, player: Player) ID {
61
- return player.ident(@intCast(u3, self.side(player).pokemon[0].position));
72
+ pub fn active(self: *const Self, player: Player) ID {
73
+ return player.ident(@intCast(self.side(player).pokemon[0].position));
62
74
  }
63
75
 
64
- pub fn update(self: *Self, c1: Choice, c2: Choice, log: anytype) !Result {
65
- return mechanics.update(self, c1, c2, log);
76
+ pub fn update(self: *Self, c1: Choice, c2: Choice, options: anytype) !Result {
77
+ return mechanics.update(self, c1, c2, options);
66
78
  }
67
79
 
68
80
  pub fn choices(self: *Self, player: Player, request: Choice.Type, out: []Choice) u8 {
@@ -71,35 +83,32 @@ pub fn Battle(comptime RNG: anytype) type {
71
83
  };
72
84
  }
73
85
 
74
- // TODO
75
86
  test Battle {
76
- try expectEqual(496, @sizeOf(Battle(PRNG)));
87
+ try expectEqual(512, @sizeOf(Battle(PRNG)));
77
88
  }
78
89
 
79
- const Field = packed struct {
90
+ pub const Field = packed struct(u8) {
80
91
  weather: Weather = .None,
81
92
  weather_duration: u4 = 0,
82
-
83
- comptime {
84
- assert(@sizeOf(Field) == 1);
85
- }
86
93
  };
87
94
 
88
- const Weather = enum(u4) {
95
+ pub const Weather = enum(u4) {
89
96
  None,
90
97
  Rain,
91
98
  Sun,
92
99
  Sandstorm,
93
100
  };
94
101
 
95
- const Side = extern struct {
102
+ pub const Side = extern struct {
96
103
  pokemon: [6]Pokemon = [_]Pokemon{.{}} ** 6,
97
- active: ActivePokemon = .{},
98
- conditions: Conditions,
104
+ active: ActivePokemon align(8) = .{},
105
+ conditions: Conditions = .{},
106
+ // NB: wLastPlayerCounterMove / wLastEnemyCounterMove (wLastPlayerMove / wLastEnemyMove)
99
107
  last_used_move: Move = .None,
100
- _: u8 = 0,
101
108
 
102
- const Conditions = packed struct {
109
+ _: [7]u8 = .{0} ** 7,
110
+
111
+ const Conditions = packed struct(u32) {
103
112
  Spikes: bool = false,
104
113
  Safeguard: bool = false,
105
114
  LightScreen: bool = false,
@@ -109,50 +118,69 @@ const Side = extern struct {
109
118
  light_screen: u4 = 0,
110
119
  reflect: u4 = 0,
111
120
 
112
- comptime {
113
- assert(@sizeOf(Conditions) == 2);
114
- }
121
+ future_sight: FutureSight = .{},
122
+
123
+ const FutureSight = packed struct(u16) {
124
+ damage: u12 = 0,
125
+ count: u4 = 0,
126
+ };
115
127
  };
116
128
 
117
129
  comptime {
118
- assert(@sizeOf(Side) == 240);
130
+ assert(@sizeOf(Side) == 248);
119
131
  }
120
132
 
121
- pub inline fn get(self: *const Side, slot: u8) *Pokemon {
133
+ pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
134
+ assert(isPointerTo(self, Side));
122
135
  assert(slot > 0 and slot <= 6);
123
136
  const id = self.pokemon[slot - 1].position;
124
137
  assert(id > 0 and id <= 6);
125
138
  return &self.pokemon[id - 1];
126
139
  }
127
140
 
128
- pub inline fn stored(self: *Side) *Pokemon {
141
+ pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
142
+ assert(isPointerTo(self, Side));
129
143
  return self.get(1);
130
144
  }
145
+
146
+ pub fn lastMove(self: anytype, encore: bool) Move {
147
+ assert(self.last_used_move != .None or !self.active.volatiles.dirty);
148
+ if (encore) return self.last_used_move;
149
+ return if (self.active.volatiles.dirty) .None else self.last_used_move;
150
+ }
151
+
152
+ // TODO
153
+ // pub fn useMove(self: anytype) void {
154
+ // assert(side.last_selected_move != .None);
155
+ // self.last_used_move = side.last_selected_move;
156
+ // self.active.volatiles.dirty = false;
157
+ // }
131
158
  };
132
159
 
133
160
  // NOTE: DVs (Gender & Hidden Power) and Happiness are stored only in Pokemon
134
- const ActivePokemon = extern struct {
135
- volatiles: Volatile align(4) = .{},
161
+ pub const ActivePokemon = extern struct {
162
+ volatiles: Volatiles align(4) = .{},
136
163
  stats: Stats(u16) = .{},
137
164
  moves: [4]MoveSlot = [_]MoveSlot{.{}} ** 4,
138
165
  boosts: Boosts = .{},
166
+ types: Types = .{},
139
167
  species: Species = .None,
140
- item: Item = .None,
141
- last_move: Move = .None,
168
+
142
169
  _: u8 = 0,
143
170
 
144
171
  comptime {
145
172
  assert(@sizeOf(ActivePokemon) == 44);
146
173
  }
147
174
 
148
- pub inline fn move(self: *ActivePokemon, mslot: u8) *MoveSlot {
175
+ pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
176
+ assert(isPointerTo(self, Pokemon));
149
177
  assert(mslot > 0 and mslot <= 4);
150
178
  assert(self.moves[mslot - 1].id != .None);
151
179
  return &self.moves[mslot - 1];
152
180
  }
153
181
  };
154
182
 
155
- const Pokemon = extern struct {
183
+ pub const Pokemon = extern struct {
156
184
  stats: Stats(u16) = .{},
157
185
  moves: [4]MoveSlot = [_]MoveSlot{.{}} ** 4,
158
186
  types: Types = .{},
@@ -169,7 +197,8 @@ const Pokemon = extern struct {
169
197
  assert(@sizeOf(Pokemon) == 32);
170
198
  }
171
199
 
172
- pub inline fn move(self: *Pokemon, mslot: u8) *MoveSlot {
200
+ pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
201
+ assert(isPointerTo(self, Pokemon));
173
202
  assert(mslot > 0 and mslot <= 4);
174
203
  assert(self.moves[mslot - 1].id != .None);
175
204
  return &self.moves[mslot - 1];
@@ -182,7 +211,7 @@ pub const Gender = enum(u2) {
182
211
  Unknown,
183
212
  };
184
213
 
185
- const DVs = packed struct {
214
+ pub const DVs = packed struct(u16) {
186
215
  gender: Gender = .Male,
187
216
  pow: u6 = 40,
188
217
  type: Type = .Dark,
@@ -190,10 +219,10 @@ const DVs = packed struct {
190
219
  pub fn init(g: Gender, p: u6, t: Type) DVs {
191
220
  assert(p >= 1 and p <= 40);
192
221
  assert(t != .Normal and t != .@"???");
193
- return DVs{ .gender = g, .pow = p, .type = t };
222
+ return .{ .gender = g, .pow = p, .type = t };
194
223
  }
195
224
 
196
- pub inline fn power(dvs: DVs) u8 {
225
+ pub fn power(dvs: DVs) u8 {
197
226
  return @as(u8, dvs.pow) + 30;
198
227
  }
199
228
 
@@ -205,15 +234,10 @@ const DVs = packed struct {
205
234
  0xFF => .Unknown,
206
235
  else => if ((@as(u8, dvs.atk) << 4 | dvs.spe) < ratio) Gender.Female else Gender.Male,
207
236
  };
208
- const p = @intCast(u6, 1 + ((5 * @as(u8, (dvs.atk & 0b1000) | ((dvs.def & 0b1000)) >> 1 |
237
+ const p: u6 = @intCast(1 + ((5 * @as(u8, (dvs.atk & 0b1000) | ((dvs.def & 0b1000)) >> 1 |
209
238
  ((dvs.spe & 0b1000)) >> 2 | ((dvs.spc & 0b1000)) >> 3) + (dvs.spc & 0b0011)) >> 1));
210
- var t = @as(u8, dvs.def & 0b0011) + (@as(u8, dvs.atk & 0b0011) << 2) + 1;
211
- if (t >= @enumToInt(Type.@"???")) t = t + 1;
212
- return DVs{ .gender = g, .pow = p, .type = @intToEnum(Type, t) };
213
- }
214
-
215
- comptime {
216
- assert(@sizeOf(DVs) == 2);
239
+ const t = @as(u8, dvs.def & 0b0011) + (@as(u8, dvs.atk & 0b0011) << 2);
240
+ return .{ .gender = g, .pow = p, .type = Type.hiddenPower(t) };
217
241
  }
218
242
  };
219
243
 
@@ -238,10 +262,12 @@ test DVs {
238
262
  try expectEqual(Gender.Female, dvs.gender);
239
263
  }
240
264
 
241
- const MoveSlot = packed struct {
265
+ /// Representation of a Generation II Pokémon's move slot in a battle.
266
+ pub const MoveSlot = extern struct {
267
+ /// The identifier for the move.
242
268
  id: Move = .None,
243
- pp_ups: u2 = 3,
244
- pp: u6 = 0,
269
+ /// The remaining PP of the move.
270
+ pp: u8 = 0,
245
271
 
246
272
  comptime {
247
273
  assert(@sizeOf(MoveSlot) == 2);
@@ -250,14 +276,19 @@ const MoveSlot = packed struct {
250
276
 
251
277
  pub const Status = gen1.Status;
252
278
 
253
- const Volatile = packed struct {
279
+ /// TODO
280
+ pub const TriAttack = enum(u2) { PAR, FRZ, BRN };
281
+
282
+ pub const Volatiles = packed struct(u128) {
254
283
  Bide: bool = false,
255
284
  Thrashing: bool = false,
285
+ BeatUp: bool = false,
256
286
  Flinch: bool = false,
257
287
  Charging: bool = false,
258
288
  Underground: bool = false,
259
289
  Flying: bool = false,
260
290
  Confusion: bool = false,
291
+
261
292
  Mist: bool = false,
262
293
  FocusEnergy: bool = false,
263
294
  Substitute: bool = false,
@@ -268,52 +299,55 @@ const Volatile = packed struct {
268
299
  Transform: bool = false,
269
300
 
270
301
  Nightmare: bool = false,
271
- Cure: bool = false,
302
+ Curse: bool = false,
272
303
  Protect: bool = false,
273
304
  Foresight: bool = false,
274
305
  PerishSong: bool = false,
275
306
  Endure: bool = false,
276
307
  Rollout: bool = false,
277
308
  Attract: bool = false,
309
+
278
310
  DefenseCurl: bool = false,
279
311
  Encore: bool = false,
280
312
  LockOn: bool = false,
281
313
  DestinyBond: bool = false,
282
- BeatUp: bool = false,
314
+ Trapped: bool = false,
283
315
 
284
- trapped: bool = false,
285
316
  switched: bool = false,
317
+ // TODO: replace with simply looking at Choice on Battle
286
318
  switching: bool = false,
319
+ // TODO: simply store both last moves on side
320
+ dirty: bool = false,
287
321
 
288
- _: u5 = 0,
322
+ frozen: bool = false,
323
+ minimized: bool = false,
324
+ _: u10 = 0,
325
+ // TODO: is this needed for unmodified stats?
326
+ transform: u4 = 0,
289
327
 
290
- bind: u4 = 0,
291
- future_sight: FutureSight = .{},
292
328
  bide: u16 = 0,
293
- disabled: Disabled = .{},
329
+ bind: Bind = .{},
330
+ disable: Disable = .{},
294
331
  rage: u8 = 0,
295
332
  substitute: u8 = 0,
296
333
  toxic: u8 = 0,
297
334
  confusion: u4 = 0,
298
335
  encore: u4 = 0,
336
+ // TODO merge with attacks (ie rollout/thrashing)? need to be zeroed at same time
299
337
  fury_cutter: u4 = 0,
300
338
  perish_song: u4 = 0,
301
339
  protect: u4 = 0,
302
- rollout: u4 = 0,
340
+ attacks: u4 = 0, // bide/thrashing/rollout turns
303
341
 
304
- const Disabled = packed struct {
305
- move: u4 = 0,
342
+ const Bind = packed struct(u8) {
306
343
  duration: u4 = 0,
344
+ reason: u4 = 0,
307
345
  };
308
346
 
309
- const FutureSight = packed struct {
310
- damage: u12 = 0,
311
- count: u4 = 0,
347
+ const Disable = packed struct(u8) {
348
+ move: u4 = 0,
349
+ duration: u4 = 0,
312
350
  };
313
-
314
- comptime {
315
- assert(@sizeOf(Volatile) == 16);
316
- }
317
351
  };
318
352
 
319
353
  pub fn Stats(comptime T: type) type {
@@ -327,10 +361,11 @@ pub fn Stats(comptime T: type) type {
327
361
 
328
362
  pub fn calc(comptime stat: []const u8, base: T, dv: u4, exp: u16, level: u8) T {
329
363
  assert(level > 0 and level <= 100);
330
- const evs = @min(255, @floatToInt(u16, @ceil(@sqrt(@intToFloat(f32, exp)))));
364
+ const float: f32 = @floatFromInt(exp);
365
+ const evs: u16 = @min(255, @as(u16, @intFromFloat(@ceil(@sqrt(float)))));
331
366
  const core: u32 = (2 *% (@as(u32, base) +% dv)) +% (evs / 4);
332
367
  const factor: u32 = if (std.mem.eql(u8, stat, "hp")) level + 10 else 5;
333
- return @intCast(T, core *% @as(u32, level) / 100 +% factor);
368
+ return @intCast(core *% @as(u32, level) / 100 +% factor);
334
369
  }
335
370
  };
336
371
  }
@@ -347,7 +382,7 @@ test Stats {
347
382
  try expectEqual(@as(u16, 279), Stats(u16).calc("spe", base.spe, 15, 63001, 100));
348
383
  }
349
384
 
350
- pub const Boosts = packed struct {
385
+ pub const Boosts = packed struct(u32) {
351
386
  atk: i4 = 0,
352
387
  def: i4 = 0,
353
388
  spe: i4 = 0,
@@ -363,7 +398,7 @@ pub const Boosts = packed struct {
363
398
  };
364
399
 
365
400
  test Boosts {
366
- const boosts = Boosts{ .spd = -6 };
401
+ const boosts: Boosts = .{ .spd = -6 };
367
402
  try expectEqual(0, boosts.atk);
368
403
  try expectEqual(-6, boosts.spd);
369
404
  }
@@ -376,31 +411,31 @@ test Item {
376
411
  try expectEqual(Type.Normal, Item.boost(.PolkadotBow).?);
377
412
  try expectEqual(Type.Dark, Item.boost(.BlackGlasses).?);
378
413
 
379
- try expect(!Item.mail(.UpGrade));
380
- try expect(Item.mail(.FlowerMail));
381
- try expect(Item.mail(.MirageMail));
382
- try expect(!Item.mail(.TownMap));
383
-
384
- try expect(!Item.berry(.LightBall));
385
- try expect(Item.berry(.PSNCureBerry));
386
- try expect(Item.berry(.GoldBerry));
387
- try expect(!Item.berry(.MasterBall));
414
+ try expect(!Item.isMail(.UpGrade));
415
+ try expect(Item.isMail(.FlowerMail));
416
+ try expect(Item.isMail(.MirageMail));
417
+ try expect(!Item.isMail(.TownMap));
388
418
  }
389
419
 
390
420
  pub const Move = moves.Move;
391
421
 
392
422
  test Move {
393
- try expectEqual(251, @enumToInt(Move.BeatUp));
423
+ try expectEqual(251, @intFromEnum(Move.BeatUp));
394
424
  const move = Move.get(.DynamicPunch);
395
425
  try expectEqual(Move.Effect.ConfusionChance, move.effect);
396
- try expectEqual(@as(u8, 50), move.accuracy);
397
- try expectEqual(@as(u8, 5), move.pp);
426
+ try expectEqual(rng.Gen12.percent(50), move.accuracy);
427
+ try expectEqual(rng.Gen12.percent(100), move.chance);
428
+ try expectEqual(@as(u8, 5), Move.pp(.DynamicPunch));
429
+ try expectEqual(@as(i8, -1), Move.get(.Counter).priority);
430
+ try expect(!move.effect.isHighCritical());
431
+ try expect(Move.get(.KarateChop).effect.isHighCritical());
432
+ try expect(Move.get(.RazorWind).effect.isHighCritical());
398
433
  }
399
434
 
400
435
  pub const Species = species.Species;
401
436
 
402
437
  test Species {
403
- try expectEqual(152, @enumToInt(Species.Chikorita));
438
+ try expectEqual(152, @intFromEnum(Species.Chikorita));
404
439
  try expectEqual(@as(u8, 100), Species.get(.Celebi).stats.spd);
405
440
  }
406
441
 
@@ -409,7 +444,7 @@ pub const Types = types.Types;
409
444
  pub const Effectiveness = gen1.Effectiveness;
410
445
 
411
446
  test Types {
412
- try expectEqual(13, @enumToInt(Type.Electric));
447
+ try expectEqual(13, @intFromEnum(Type.Electric));
413
448
 
414
449
  try expect(!Type.Steel.special());
415
450
  try expect(Type.Dark.special());