@pkmn/engine 0.1.0-dev.bcb16a6c → 0.1.0-dev.bce6e8a5

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 (83) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +51 -23
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +47 -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 +110 -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 +25 -3
  13. package/build/pkg/addon.js +39 -71
  14. package/build/pkg/addon.js.map +1 -1
  15. package/build/pkg/data/layout.json +17 -4
  16. package/build/pkg/data/protocol.json +23 -9
  17. package/build/pkg/data.d.ts +27 -5
  18. package/build/pkg/data.js.map +1 -1
  19. package/build/pkg/gen1.d.ts +15 -18
  20. package/build/pkg/gen1.js +30 -21
  21. package/build/pkg/gen1.js.map +1 -1
  22. package/build/pkg/index.d.ts +42 -91
  23. package/build/pkg/index.js +23 -70
  24. package/build/pkg/index.js.map +1 -1
  25. package/build/pkg/protocol.d.ts +20 -1
  26. package/build/pkg/protocol.js +109 -107
  27. package/build/pkg/protocol.js.map +1 -1
  28. package/build/tools/debug.js +53 -76
  29. package/build/tools/debug.js.map +1 -1
  30. package/build/tools/display/debug.jsx +152 -0
  31. package/build/tools/display/debug.jsx.map +1 -0
  32. package/build/tools/display/index.js +152 -0
  33. package/build/tools/display/index.js.map +1 -0
  34. package/build/tools/display/ui.jsx +359 -0
  35. package/build/tools/display/ui.jsx.map +1 -0
  36. package/build/tools/display/util.js +33 -0
  37. package/build/tools/display/util.js.map +1 -0
  38. package/build.zig +344 -101
  39. package/package.json +62 -132
  40. package/src/bin/install-pkmn-engine +31 -20
  41. package/src/bin/pkmn-debug +1 -1
  42. package/src/lib/bindings/c.zig +255 -0
  43. package/src/lib/{binding → bindings}/node.zig +8 -21
  44. package/src/lib/bindings/wasm.zig +59 -0
  45. package/src/lib/common/array.zig +77 -0
  46. package/src/lib/common/data.zig +8 -8
  47. package/src/lib/common/debug.zig +39 -8
  48. package/src/lib/common/js.zig +4 -2
  49. package/src/lib/common/optional.zig +17 -15
  50. package/src/lib/common/options.zig +6 -0
  51. package/src/lib/common/protocol.zig +414 -389
  52. package/src/lib/common/rational.zig +131 -35
  53. package/src/lib/common/rng.zig +16 -9
  54. package/src/lib/common/util.zig +50 -1
  55. package/src/lib/gen1/calc.zig +687 -160
  56. package/src/lib/gen1/chance.zig +430 -303
  57. package/src/lib/gen1/data/moves.zig +26 -14
  58. package/src/lib/gen1/data/species.zig +4 -6
  59. package/src/lib/gen1/data/types.zig +6 -7
  60. package/src/lib/gen1/data.zig +44 -47
  61. package/src/lib/gen1/helpers.zig +91 -562
  62. package/src/lib/gen1/mechanics.zig +642 -565
  63. package/src/lib/gen2/calc.zig +153 -0
  64. package/src/lib/gen2/chance.zig +902 -0
  65. package/src/lib/gen2/data/items.zig +4 -6
  66. package/src/lib/gen2/data/moves.zig +34 -19
  67. package/src/lib/gen2/data/species.zig +2 -4
  68. package/src/lib/gen2/data/types.zig +13 -13
  69. package/src/lib/gen2/data.zig +45 -54
  70. package/src/lib/gen2/generated.zig +801 -0
  71. package/src/lib/gen2/helpers.zig +46 -25
  72. package/src/lib/gen2/mechanics.zig +2483 -452
  73. package/src/lib/node.zig +18 -0
  74. package/src/lib/pkmn.zig +37 -15
  75. package/src/lib/wasm.zig +17 -0
  76. package/src/tools/display/dom.ts +93 -0
  77. package/src/tools/display/ui.css +354 -0
  78. package/build/test/display.js +0 -400
  79. package/build/test/display.js.map +0 -1
  80. package/src/lib/binding/wasm.zig +0 -12
  81. package/src/lib/gen1/README.md +0 -894
  82. package/src/lib/gen2/README.md +0 -330
  83. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -1,11 +1,9 @@
1
- //! Code generated by `tools/generate` - manual edits will be overwritten
2
-
3
- const std = @import("std");
1
+ //! Code generated by `tools/generate` - manual edits will be overwritten.
4
2
 
5
3
  const data = @import("../../gen2/data.zig");
4
+ const std = @import("std");
6
5
 
7
6
  const assert = std.debug.assert;
8
-
9
7
  const Type = data.Type;
10
8
 
11
9
  /// Representation of a held item in Generation II Pokémon.
@@ -216,14 +214,14 @@ pub const Item = enum(u8) {
216
214
  pub const size = 196;
217
215
 
218
216
  /// 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 {
217
+ pub fn boost(item: Item) ?Type {
220
218
  assert(item != .None);
221
219
  if (item == .PolkadotBow) return .Normal;
222
220
  return if (@intFromEnum(item) <= 18) @enumFromInt(@intFromEnum(item) - 1) else null;
223
221
  }
224
222
 
225
223
  /// Whether or not this item is Mail.
226
- pub inline fn isMail(item: Item) bool {
224
+ pub fn isMail(item: Item) bool {
227
225
  assert(item != .None);
228
226
  return @intFromEnum(item) > 60 and @intFromEnum(item) <= 70;
229
227
  }
@@ -1,12 +1,10 @@
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
- const std = @import("std");
4
-
5
- const rng = @import("../../common/rng.zig");
6
3
  const gen2 = @import("../../gen2/data.zig");
4
+ const rng = @import("../../common/rng.zig");
5
+ const std = @import("std");
7
6
 
8
7
  const assert = std.debug.assert;
9
-
10
8
  const percent = rng.Gen12.percent;
11
9
  const Type = gen2.Type;
12
10
 
@@ -288,6 +286,8 @@ pub const Move = enum(u8) {
288
286
  const Extra = packed struct(u8) {
289
287
  /// Whether this move can be called via Metronome.
290
288
  metronome: bool = true,
289
+ /// Whether this move can be called via Sleep Talk.
290
+ sleep_talk: bool = true,
291
291
  /// Whether this move is considered to be "continuous".
292
292
  continuous: bool = false,
293
293
  /// Whether this move can hit a flying target.
@@ -295,7 +295,7 @@ pub const Move = enum(u8) {
295
295
  /// Whether this move can hit an underground target.
296
296
  underground: bool = false,
297
297
  /// Protocol reason offset associated with this move.
298
- protocol: u4 = 0,
298
+ protocol: u3 = 0,
299
299
  };
300
300
 
301
301
  comptime {
@@ -410,7 +410,7 @@ pub const Move = enum(u8) {
410
410
  .type = .Normal,
411
411
  .accuracy = percent(75),
412
412
  .target = .Foes,
413
- .extra = .{ .continuous = true },
413
+ .extra = .{ .sleep_talk = false, .continuous = true },
414
414
  },
415
415
  // SwordsDance
416
416
  .{
@@ -457,12 +457,12 @@ pub const Move = enum(u8) {
457
457
  },
458
458
  // Fly
459
459
  .{
460
- .effect = .Fly,
460
+ .effect = .FlyDig,
461
461
  .bp = 70,
462
462
  .type = .Flying,
463
463
  .accuracy = percent(95),
464
464
  .target = .Any,
465
- .extra = .{ .continuous = true },
465
+ .extra = .{ .sleep_talk = false, .continuous = true },
466
466
  },
467
467
  // Bind
468
468
  .{
@@ -936,12 +936,12 @@ pub const Move = enum(u8) {
936
936
  },
937
937
  // SolarBeam
938
938
  .{
939
- .effect = .Solarbeam,
939
+ .effect = .SolarBeam,
940
940
  .bp = 120,
941
941
  .type = .Grass,
942
942
  .accuracy = percent(100),
943
943
  .target = .Other,
944
- .extra = .{ .continuous = true },
944
+ .extra = .{ .sleep_talk = false, .continuous = true },
945
945
  },
946
946
  // PoisonPowder
947
947
  .{
@@ -1065,11 +1065,12 @@ pub const Move = enum(u8) {
1065
1065
  },
1066
1066
  // Dig
1067
1067
  .{
1068
- .effect = .Fly,
1068
+ .effect = .FlyDig,
1069
1069
  .bp = 60,
1070
1070
  .type = .Ground,
1071
1071
  .accuracy = percent(100),
1072
1072
  .target = .Other,
1073
+ .extra = .{ .sleep_talk = false },
1073
1074
  },
1074
1075
  // Toxic
1075
1076
  .{
@@ -1282,7 +1283,7 @@ pub const Move = enum(u8) {
1282
1283
  .type = .Normal,
1283
1284
  .accuracy = percent(100),
1284
1285
  .target = .Self,
1285
- .extra = .{ .continuous = true },
1286
+ .extra = .{ .sleep_talk = false, .continuous = true },
1286
1287
  },
1287
1288
  // Metronome
1288
1289
  .{
@@ -1394,7 +1395,7 @@ pub const Move = enum(u8) {
1394
1395
  .type = .Normal,
1395
1396
  .accuracy = percent(100),
1396
1397
  .target = .Other,
1397
- .extra = .{ .continuous = true },
1398
+ .extra = .{ .sleep_talk = false, .continuous = true },
1398
1399
  },
1399
1400
  // SpikeCannon
1400
1401
  .{
@@ -1500,7 +1501,7 @@ pub const Move = enum(u8) {
1500
1501
  .type = .Flying,
1501
1502
  .accuracy = percent(90),
1502
1503
  .target = .Any,
1503
- .extra = .{ .continuous = true },
1504
+ .extra = .{ .sleep_talk = false, .continuous = true },
1504
1505
  },
1505
1506
  // Transform
1506
1507
  .{
@@ -2463,7 +2464,7 @@ pub const Move = enum(u8) {
2463
2464
  FixedDamage,
2464
2465
  FlameWheel,
2465
2466
  FlinchChance,
2466
- Fly,
2467
+ FlyDig,
2467
2468
  FocusEnergy,
2468
2469
  ForceSwitch,
2469
2470
  Foresight,
@@ -2526,7 +2527,7 @@ pub const Move = enum(u8) {
2526
2527
  Sleep,
2527
2528
  SleepTalk,
2528
2529
  Snore,
2529
- Solarbeam,
2530
+ SolarBeam,
2530
2531
  SpAtkUp1,
2531
2532
  SpDefDownChance,
2532
2533
  SpDefUp2,
@@ -2559,7 +2560,7 @@ pub const Move = enum(u8) {
2559
2560
  }
2560
2561
 
2561
2562
  /// Whether this effect has a high critical rate.
2562
- pub inline fn isHighCritical(effect: Effect) bool {
2563
+ pub fn isHighCritical(effect: Effect) bool {
2563
2564
  return effect == .HighCritical or effect == .RazorWind;
2564
2565
  }
2565
2566
  };
@@ -2847,8 +2848,22 @@ pub const Move = enum(u8) {
2847
2848
  /// The number of Pokémon moves in this generation.
2848
2849
  pub const size = 251;
2849
2850
 
2851
+ /// Pokémon moves that can be called by Metronome in this generation.
2852
+ pub const METRONOME = init: {
2853
+ var num = 0;
2854
+ var moves: [239]Move = undefined;
2855
+ for (1..Move.size + 1) |i| {
2856
+ if (Move.get(@enumFromInt(i)).extra.metronome) {
2857
+ moves[num] = @enumFromInt(i);
2858
+ num += 1;
2859
+ }
2860
+ }
2861
+ assert(num == moves.len);
2862
+ break :init moves;
2863
+ };
2864
+
2850
2865
  /// Returns the `Data` corresponding to the move.
2851
- pub inline fn get(id: Move) Data {
2866
+ pub fn get(id: Move) Data {
2852
2867
  assert(id != .None);
2853
2868
  return DATA[@intFromEnum(id) - 1];
2854
2869
  }
@@ -1,11 +1,9 @@
1
- //! Code generated by `tools/generate` - manual edits will be overwritten
2
-
3
- const std = @import("std");
1
+ //! Code generated by `tools/generate` - manual edits will be overwritten.
4
2
 
5
3
  const gen2 = @import("../../gen2/data.zig");
4
+ const std = @import("std");
6
5
 
7
6
  const assert = std.debug.assert;
8
-
9
7
  const Stats = gen2.Stats;
10
8
  const Types = gen2.Types;
11
9
 
@@ -1,8 +1,7 @@
1
- //! Code generated by `tools/generate` - manual edits will be overwritten
2
-
3
- const std = @import("std");
1
+ //! Code generated by `tools/generate` - manual edits will be overwritten.
4
2
 
5
3
  const gen1 = @import("../../gen1/data.zig");
4
+ const std = @import("std");
6
5
 
7
6
  const assert = std.debug.assert;
8
7
  const Effectiveness = gen1.Effectiveness;
@@ -164,27 +163,27 @@ pub const Type = enum(u8) {
164
163
  pub const size = 18;
165
164
 
166
165
  /// Whether or not this type is considered to be special as opposed to physical.
167
- pub inline fn special(self: Type) bool {
166
+ pub fn special(self: Type) bool {
168
167
  return @intFromEnum(self) >= @intFromEnum(Type.Fire);
169
168
  }
170
169
 
171
170
  /// The `Effectiveness` of type `t2` vs. type `t1`.
172
- pub inline fn effectiveness(t1: Type, t2: Type) Effectiveness {
171
+ pub fn effectiveness(t1: Type, t2: Type) Effectiveness {
173
172
  return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
174
173
  }
175
174
 
176
175
  /// The precedence order of Type `type`.
177
- pub inline fn precedence(self: Type) u8 {
176
+ pub fn precedence(self: Type) u8 {
178
177
  return PRECEDENCE[@intFromEnum(self)];
179
178
  }
180
179
 
181
180
  /// The internal index of this Type used by Present.
182
- pub inline fn present(self: Type) u8 {
181
+ pub fn present(self: Type) u8 {
183
182
  return INDEXES[@intFromEnum(self)];
184
183
  }
185
184
 
186
185
  /// The Type corresponding to a random roll of `num` for Conversion 2.
187
- pub inline fn conversion2(num: u8) Type {
186
+ pub fn conversion2(num: u8) Type {
188
187
  assert(num != 6);
189
188
  assert(num < 10 or num >= 20);
190
189
  assert(num <= 27);
@@ -192,7 +191,7 @@ pub const Type = enum(u8) {
192
191
  }
193
192
 
194
193
  /// The Type corresponding to a Hidden Power `index`.
195
- pub inline fn hiddenPower(index: u8) Type {
194
+ pub fn hiddenPower(index: u8) Type {
196
195
  return HIDDEN_POWER[index];
197
196
  }
198
197
  };
@@ -209,17 +208,18 @@ pub const Types = extern struct {
209
208
  }
210
209
 
211
210
  /// Whether this typing is immune to type `t`.
212
- pub inline fn immune(self: Types, t: Type) bool {
211
+ pub fn immune(self: Types, t: Type) bool {
213
212
  return t.effectiveness(self.type1) == I or t.effectiveness(self.type2) == I;
214
213
  }
215
214
 
216
215
  /// Whether this typing includes type `t`.
217
- pub inline fn includes(self: Types, t: Type) bool {
216
+ pub fn includes(self: Types, t: Type) bool {
218
217
  return self.type1 == t or self.type2 == t;
219
218
  }
220
219
 
221
220
  /// Whether this typing is immune to damage from Sandstorm.
222
- pub inline fn sandstormImmune(self: Types) u8 {
223
- return self.type1 <= @intFromEnum(Type.Steel) or self.type2 <= @intFromEnum(Type.Steel);
221
+ pub fn sandstormImmune(self: Types) bool {
222
+ return @intFromEnum(self.type1) <= @intFromEnum(Type.Steel) or
223
+ @intFromEnum(self.type2) <= @intFromEnum(Type.Steel);
224
224
  }
225
225
  };
@@ -1,24 +1,20 @@
1
- const std = @import("std");
2
- const builtin = @import("builtin");
3
-
4
- const pkmn = @import("../pkmn.zig");
5
-
6
- const data = @import("../common/data.zig");
7
1
  const DEBUG = @import("../common/debug.zig").print;
8
- const protocol = @import("../common/protocol.zig");
9
- const rng = @import("../common/rng.zig");
10
- const util = @import("../common/util.zig");
11
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");
12
8
  const items = @import("data/items.zig");
9
+ const mechanics = @import("mechanics.zig");
13
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");
14
14
  const species = @import("data/species.zig");
15
+ const std = @import("std");
15
16
  const types = @import("data/types.zig");
16
-
17
- const gen1 = @import("../gen1/data.zig");
18
-
19
- const calc = @import("calc.zig");
20
- const chance = @import("chance.zig");
21
- const mechanics = @import("mechanics.zig");
17
+ const util = @import("../common/util.zig");
22
18
 
23
19
  const assert = std.debug.assert;
24
20
  const expectEqual = std.testing.expectEqual;
@@ -45,6 +41,7 @@ const Player = data.Player;
45
41
  const Result = data.Result;
46
42
 
47
43
  const PointerType = util.PointerType;
44
+ const isPointerTo = util.isPointerTo;
48
45
 
49
46
  const showdown = pkmn.options.showdown;
50
47
 
@@ -62,17 +59,17 @@ pub fn Battle(comptime RNG: anytype) type {
62
59
 
63
60
  _: [padding]u8 = .{0} ** padding,
64
61
 
65
- pub inline fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
66
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
62
+ pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
63
+ assert(isPointerTo(self, Self));
67
64
  return &self.sides[@intFromEnum(player)];
68
65
  }
69
66
 
70
- pub inline fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
71
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
67
+ pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
68
+ assert(isPointerTo(self, Self));
72
69
  return &self.sides[@intFromEnum(player.foe())];
73
70
  }
74
71
 
75
- pub inline fn active(self: *const Self, player: Player) ID {
72
+ pub fn active(self: *const Self, player: Player) ID {
76
73
  return player.ident(@intCast(self.side(player).pokemon[0].position));
77
74
  }
78
75
 
@@ -133,27 +130,27 @@ pub const Side = extern struct {
133
130
  assert(@sizeOf(Side) == 248);
134
131
  }
135
132
 
136
- pub inline fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
137
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
133
+ pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
134
+ assert(isPointerTo(self, Side));
138
135
  assert(slot > 0 and slot <= 6);
139
136
  const id = self.pokemon[slot - 1].position;
140
137
  assert(id > 0 and id <= 6);
141
138
  return &self.pokemon[id - 1];
142
139
  }
143
140
 
144
- pub inline fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
145
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
141
+ pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
142
+ assert(isPointerTo(self, Side));
146
143
  return self.get(1);
147
144
  }
148
145
 
149
- pub inline fn lastMove(self: anytype, encore: bool) Move {
146
+ pub fn lastMove(self: anytype, encore: bool) Move {
150
147
  assert(self.last_used_move != .None or !self.active.volatiles.dirty);
151
148
  if (encore) return self.last_used_move;
152
149
  return if (self.active.volatiles.dirty) .None else self.last_used_move;
153
150
  }
154
151
 
155
152
  // TODO
156
- // pub inline fn useMove(self: anytype) void {
153
+ // pub fn useMove(self: anytype) void {
157
154
  // assert(side.last_selected_move != .None);
158
155
  // self.last_used_move = side.last_selected_move;
159
156
  // self.active.volatiles.dirty = false;
@@ -175,8 +172,8 @@ pub const ActivePokemon = extern struct {
175
172
  assert(@sizeOf(ActivePokemon) == 44);
176
173
  }
177
174
 
178
- pub inline fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
179
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
175
+ pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
176
+ assert(isPointerTo(self, Pokemon));
180
177
  assert(mslot > 0 and mslot <= 4);
181
178
  assert(self.moves[mslot - 1].id != .None);
182
179
  return &self.moves[mslot - 1];
@@ -200,8 +197,8 @@ pub const Pokemon = extern struct {
200
197
  assert(@sizeOf(Pokemon) == 32);
201
198
  }
202
199
 
203
- pub inline fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
204
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
200
+ pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
201
+ assert(isPointerTo(self, Pokemon));
205
202
  assert(mslot > 0 and mslot <= 4);
206
203
  assert(self.moves[mslot - 1].id != .None);
207
204
  return &self.moves[mslot - 1];
@@ -225,7 +222,7 @@ pub const DVs = packed struct(u16) {
225
222
  return .{ .gender = g, .pow = p, .type = t };
226
223
  }
227
224
 
228
- pub inline fn power(dvs: DVs) u8 {
225
+ pub fn power(dvs: DVs) u8 {
229
226
  return @as(u8, dvs.pow) + 30;
230
227
  }
231
228
 
@@ -239,7 +236,7 @@ pub const DVs = packed struct(u16) {
239
236
  };
240
237
  const p: u6 = @intCast(1 + ((5 * @as(u8, (dvs.atk & 0b1000) | ((dvs.def & 0b1000)) >> 1 |
241
238
  ((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);
239
+ const t = @as(u8, dvs.def & 0b0011) + (@as(u8, dvs.atk & 0b0011) << 2);
243
240
  return .{ .gender = g, .pow = p, .type = Type.hiddenPower(t) };
244
241
  }
245
242
  };
@@ -280,22 +277,7 @@ pub const MoveSlot = extern struct {
280
277
  pub const Status = gen1.Status;
281
278
 
282
279
  /// TODO
283
- pub const TriAttack = enum(u2) {
284
- PAR,
285
- FRZ,
286
- BRN,
287
-
288
- /// TODO
289
- pub inline fn status(self: TriAttack) u8 {
290
- return Status.init(@enumFromInt(6 - @as(u8, @intFromEnum(self))));
291
- }
292
- };
293
-
294
- test TriAttack {
295
- try expectEqual(Status.init(.PAR), TriAttack.PAR.status());
296
- try expectEqual(Status.init(.FRZ), TriAttack.FRZ.status());
297
- try expectEqual(Status.init(.BRN), TriAttack.BRN.status());
298
- }
280
+ pub const TriAttack = enum(u2) { PAR, FRZ, BRN };
299
281
 
300
282
  pub const Volatiles = packed struct(u128) {
301
283
  Bide: bool = false,
@@ -329,19 +311,23 @@ pub const Volatiles = packed struct(u128) {
329
311
  Encore: bool = false,
330
312
  LockOn: bool = false,
331
313
  DestinyBond: bool = false,
314
+ Trapped: bool = false,
332
315
 
333
- trapped: bool = false,
334
316
  switched: bool = false,
317
+ // TODO: replace with simply looking at Choice on Battle
335
318
  switching: bool = false,
319
+ // TODO: simply store both last moves on side
336
320
  dirty: bool = false,
337
321
 
338
322
  frozen: bool = false,
339
- _: u15 = 0,
323
+ minimized: bool = false,
324
+ _: u10 = 0,
325
+ // TODO: is this needed for unmodified stats?
326
+ transform: u4 = 0,
340
327
 
341
- bind_reason: u4 = 0,
342
- bind: u4 = 0,
343
328
  bide: u16 = 0,
344
- disabled: Disabled = .{},
329
+ bind: Bind = .{},
330
+ disable: Disable = .{},
345
331
  rage: u8 = 0,
346
332
  substitute: u8 = 0,
347
333
  toxic: u8 = 0,
@@ -353,7 +339,12 @@ pub const Volatiles = packed struct(u128) {
353
339
  protect: u4 = 0,
354
340
  attacks: u4 = 0, // bide/thrashing/rollout turns
355
341
 
356
- const Disabled = packed struct(u8) {
342
+ const Bind = packed struct(u8) {
343
+ duration: u4 = 0,
344
+ reason: u4 = 0,
345
+ };
346
+
347
+ const Disable = packed struct(u8) {
357
348
  move: u4 = 0,
358
349
  duration: u4 = 0,
359
350
  };