@pkmn/engine 0.1.0-dev.305a932f → 0.1.0-dev.30895c5a

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 (51) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +44 -19
  3. package/build/pkg/addon.js +6 -7
  4. package/build/pkg/addon.js.map +1 -1
  5. package/build/pkg/data/layout.json +2 -2
  6. package/build/pkg/data.d.ts +4 -4
  7. package/build/pkg/data.js.map +1 -1
  8. package/build/pkg/gen1.js +2 -2
  9. package/build/pkg/gen1.js.map +1 -1
  10. package/build/pkg/index.d.ts +3 -2
  11. package/build/pkg/index.js.map +1 -1
  12. package/build/pkg/protocol.js +5 -5
  13. package/build/pkg/protocol.js.map +1 -1
  14. package/build/test/display.js +8 -3
  15. package/build/test/display.js.map +1 -1
  16. package/build/tools/debug.js +5 -4
  17. package/build/tools/debug.js.map +1 -1
  18. package/build.zig +100 -102
  19. package/package.json +34 -23
  20. package/src/bin/install-pkmn-engine +26 -18
  21. package/src/lib/common/data.zig +8 -8
  22. package/src/lib/common/debug.zig +2 -2
  23. package/src/lib/common/optional.zig +9 -2
  24. package/src/lib/common/options.zig +2 -0
  25. package/src/lib/common/protocol.zig +408 -384
  26. package/src/lib/common/rational.zig +119 -18
  27. package/src/lib/common/rng.zig +20 -11
  28. package/src/lib/gen1/calc.zig +506 -130
  29. package/src/lib/gen1/chance.zig +395 -299
  30. package/src/lib/gen1/data/moves.zig +24 -10
  31. package/src/lib/gen1/data/species.zig +3 -3
  32. package/src/lib/gen1/data/types.zig +5 -5
  33. package/src/lib/gen1/data.zig +39 -39
  34. package/src/lib/gen1/helpers.zig +89 -548
  35. package/src/lib/gen1/mechanics.zig +551 -492
  36. package/src/lib/gen2/calc.zig +135 -0
  37. package/src/lib/gen2/chance.zig +882 -0
  38. package/src/lib/gen2/data/items.zig +3 -3
  39. package/src/lib/gen2/data/moves.zig +32 -15
  40. package/src/lib/gen2/data/species.zig +1 -1
  41. package/src/lib/gen2/data/types.zig +75 -28
  42. package/src/lib/gen2/data.zig +37 -25
  43. package/src/lib/gen2/generated.zig +806 -0
  44. package/src/lib/gen2/helpers.zig +37 -7
  45. package/src/lib/gen2/mechanics.zig +2679 -358
  46. package/src/lib/{binding/node.zig → node.zig} +9 -12
  47. package/src/lib/pkmn.zig +27 -15
  48. package/src/lib/{binding/wasm.zig → wasm.zig} +2 -1
  49. package/src/test/display/pkmn.html.tmpl +5 -5
  50. package/src/lib/gen1/README.md +0 -894
  51. package/src/lib/gen2/README.md +0 -330
@@ -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
 
@@ -1599,43 +1599,43 @@ pub const Move = enum(u8) {
1599
1599
  }
1600
1600
 
1601
1601
  /// Whether this effect activates during the "begin" step of move execution.
1602
- pub inline fn onBegin(effect: Effect) bool {
1602
+ pub fn onBegin(effect: Effect) bool {
1603
1603
  return @intFromEnum(effect) > 0 and @intFromEnum(effect) <= 16;
1604
1604
  }
1605
1605
 
1606
1606
  /// Whether this effect lowers stats.
1607
- pub inline fn isStatDown(effect: Effect) bool {
1607
+ pub fn isStatDown(effect: Effect) bool {
1608
1608
  return @intFromEnum(effect) > 16 and @intFromEnum(effect) <= 21;
1609
1609
  }
1610
1610
 
1611
1611
  /// Whether this effect activates during the "end" step of move execution.
1612
- pub inline fn onEnd(effect: Effect) bool {
1612
+ pub fn onEnd(effect: Effect) bool {
1613
1613
  return @intFromEnum(effect) > 16 and @intFromEnum(effect) <= 31;
1614
1614
  }
1615
1615
 
1616
1616
  /// Whether this effect is considered to "always happen".
1617
- pub inline fn alwaysHappens(effect: Effect) bool {
1617
+ pub fn alwaysHappens(effect: Effect) bool {
1618
1618
  return @intFromEnum(effect) > 31 and @intFromEnum(effect) <= 38;
1619
1619
  }
1620
1620
 
1621
1621
  /// Whether this effect is handled specially by the engine.
1622
- pub inline fn isSpecial(effect: Effect) bool {
1622
+ pub fn isSpecial(effect: Effect) bool {
1623
1623
  // NB: isSpecial includes isMulti up to Twineedle
1624
1624
  return @intFromEnum(effect) > 31 and @intFromEnum(effect) <= 46;
1625
1625
  }
1626
1626
 
1627
1627
  /// Whether this effect is a multi-hit effect.
1628
- pub inline fn isMulti(effect: Effect) bool {
1628
+ pub fn isMulti(effect: Effect) bool {
1629
1629
  return @intFromEnum(effect) > 44 and @intFromEnum(effect) <= 47;
1630
1630
  }
1631
1631
 
1632
1632
  /// Whether this effect is has chance of lowering stats.
1633
- pub inline fn isStatDownChance(effect: Effect) bool {
1633
+ pub fn isStatDownChance(effect: Effect) bool {
1634
1634
  return @intFromEnum(effect) > 47 and @intFromEnum(effect) <= 51;
1635
1635
  }
1636
1636
 
1637
1637
  /// Whether this effect has a secondary chance.
1638
- pub inline fn isSecondaryChance(effect: Effect) bool {
1638
+ pub fn isSecondaryChance(effect: Effect) bool {
1639
1639
  // NB: isSecondaryChance includes isStatDownChance as well as Twineedle
1640
1640
  return (@intFromEnum(effect) > 46 and @intFromEnum(effect) <= 61);
1641
1641
  }
@@ -1838,8 +1838,22 @@ pub const Move = enum(u8) {
1838
1838
  /// The number of Pokémon moves in this generation.
1839
1839
  pub const size = 165;
1840
1840
 
1841
+ /// Pokémon moves that can be called by Metronome in this generation.
1842
+ pub const METRONOME = init: {
1843
+ var num = 0;
1844
+ var moves: [163]Move = undefined;
1845
+ for (1..Move.size) |i| {
1846
+ if (i != @intFromEnum(Move.Metronome)) {
1847
+ moves[num] = @enumFromInt(i);
1848
+ num += 1;
1849
+ }
1850
+ }
1851
+ assert(num == moves.len);
1852
+ break :init moves;
1853
+ };
1854
+
1841
1855
  /// Returns the `Data` corresponding to the move.
1842
- pub inline fn get(id: Move) Data {
1856
+ pub fn get(id: Move) Data {
1843
1857
  assert(id != .None and id != .SKIP_TURN);
1844
1858
  return DATA[@intFromEnum(id) - 1];
1845
1859
  }
@@ -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
 
@@ -1091,8 +1091,8 @@ pub const Species = enum(u8) {
1091
1091
  /// The number of Pokémon species in this generation.
1092
1092
  pub const size = 151;
1093
1093
 
1094
- /// The Pokémon's critical hit rate=io out of 256.
1095
- pub inline fn chance(id: Species) u8 {
1094
+ /// The Pokémon's critical hit ratio out of 256.
1095
+ pub fn chance(id: Species) u8 {
1096
1096
  assert(id != .None);
1097
1097
  return CHANCES[@intFromEnum(id) - 1];
1098
1098
  }
@@ -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
 
@@ -90,12 +90,12 @@ pub const Type = enum(u4) {
90
90
  pub const size = 15;
91
91
 
92
92
  /// Whether or not this type is considered to be special as opposed to physical.
93
- pub inline fn special(self: Type) bool {
93
+ pub fn special(self: Type) bool {
94
94
  return @intFromEnum(self) >= @intFromEnum(Type.Fire);
95
95
  }
96
96
 
97
97
  /// The `Effectiveness` of type `t2` vs. type `t1`.
98
- pub inline fn effectiveness(t1: Type, t2: Type) Effectiveness {
98
+ pub fn effectiveness(t1: Type, t2: Type) Effectiveness {
99
99
  return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
100
100
  }
101
101
 
@@ -120,12 +120,12 @@ pub const Types = packed struct {
120
120
  }
121
121
 
122
122
  /// Whether this typing is immune to type `t`.
123
- pub inline fn immune(self: Types, t: Type) bool {
123
+ pub fn immune(self: Types, t: Type) bool {
124
124
  return t.effectiveness(self.type1) == I or t.effectiveness(self.type2) == I;
125
125
  }
126
126
 
127
127
  /// Whether this typing includes type `t`.
128
- pub inline fn includes(self: Types, t: Type) bool {
128
+ pub fn includes(self: Types, t: Type) bool {
129
129
  return self.type1 == t or self.type2 == t;
130
130
  }
131
131
  };
@@ -22,11 +22,11 @@ const expect = std.testing.expect;
22
22
 
23
23
  /// The minimum size in bytes required to hold all Generation I choice options.
24
24
  pub const MAX_CHOICES: usize = 9; // move 1..4, switch 2..6
25
- /// The optimal size in bytes required to hold all Generation I choice options.
26
- /// At least as large as MAX_CHOICES.
25
+ /// The maximum number of bytes possibly logged by a single Generation I update.
27
26
  pub const MAX_LOGS: usize = 180;
28
27
 
29
- /// The maximum number of bytes possibly logged by a single Generation I update.
28
+ /// The optimal size in bytes required to hold all Generation I choice options.
29
+ /// At least as large as MAX_CHOICES.
30
30
  pub const CHOICES_SIZE = if (builtin.mode == .ReleaseSmall)
31
31
  MAX_CHOICES
32
32
  else
@@ -70,24 +70,24 @@ pub fn Battle(comptime RNG: anytype) type {
70
70
  rng: RNG,
71
71
 
72
72
  /// Returns the `Side` for the given `player`.
73
- pub inline fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
73
+ pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
74
74
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
75
75
  return &self.sides[@intFromEnum(player)];
76
76
  }
77
77
 
78
78
  /// Returns the `Side` of the opponent for the given `player`
79
- pub inline fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
79
+ pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
80
80
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
81
81
  return &self.sides[@intFromEnum(player.foe())];
82
82
  }
83
83
 
84
84
  /// Returns an identifier for the active Pokémon of `player`.
85
- pub inline fn active(self: *const Self, player: Player) ID {
85
+ pub fn active(self: *const Self, player: Player) ID {
86
86
  return player.ident(@intCast(self.side(player).order[0]));
87
87
  }
88
88
 
89
89
  /// Returns the `MoveDetails` for the given `player`.
90
- pub inline fn lastMove(
90
+ pub fn lastMove(
91
91
  self: anytype,
92
92
  player: Player,
93
93
  ) PointerType(@TypeOf(self), MoveDetails) {
@@ -112,7 +112,7 @@ pub fn Battle(comptime RNG: anytype) type {
112
112
  /// make (i.e. on the cartridge a soft-lock occurs).
113
113
  ///
114
114
  /// This function will always return choices > 0 if `pkmn.options.showdown` is true.
115
- pub fn choices(self: *Self, player: Player, request: Choice.Type, out: []Choice) u8 {
115
+ pub fn choices(self: *const Self, player: Player, request: Choice.Type, out: []Choice) u8 {
116
116
  return mechanics.choices(self, player, request, out);
117
117
  }
118
118
  };
@@ -141,7 +141,7 @@ pub const Side = extern struct {
141
141
  }
142
142
 
143
143
  /// Returns the stored `Pokemon` corresponding to the one-indexed party `slot`.
144
- pub inline fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
144
+ pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
145
145
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
146
146
  assert(slot > 0 and slot <= 6);
147
147
  const id = self.order[slot - 1];
@@ -150,7 +150,7 @@ pub const Side = extern struct {
150
150
  }
151
151
 
152
152
  /// Returns the stored `Pokemon` corresponding to the `active` Pokémon (slot 1).
153
- pub inline fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
153
+ pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
154
154
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
155
155
  return self.get(1);
156
156
  }
@@ -176,7 +176,7 @@ pub const ActivePokemon = extern struct {
176
176
  }
177
177
 
178
178
  /// Returns the active Pokémon's current move slot located at the one-indexed `mslot`.
179
- pub inline fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
179
+ pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
180
180
  assert(@typeInfo(@TypeOf(self)).Pointer.child == ActivePokemon);
181
181
  assert(mslot > 0 and mslot <= 4);
182
182
  assert(self.moves[mslot - 1].id != .None);
@@ -206,7 +206,7 @@ pub const Pokemon = extern struct {
206
206
  }
207
207
 
208
208
  /// Returns the Pokémon's original move slot located at the one-indexed `mslot`.
209
- pub inline fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
209
+ pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
210
210
  assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
211
211
  assert(mslot > 0 and mslot <= 4);
212
212
  assert(self.moves[mslot - 1].id != .None);
@@ -258,36 +258,36 @@ pub const Status = enum(u8) {
258
258
  const SLP = 0b111;
259
259
 
260
260
  /// Whether or not the status `num` is the same as `status`.
261
- pub inline fn is(num: u8, status: Status) bool {
261
+ pub fn is(num: u8, status: Status) bool {
262
262
  if (status == .SLP) return Status.duration(num) > 0;
263
263
  return ((num >> @intCast(@intFromEnum(status))) & 1) != 0;
264
264
  }
265
265
 
266
266
  /// Initializes a non-sleep `status`. Use `slp` or `slf` to initialize a sleep status.
267
- pub inline fn init(status: Status) u8 {
267
+ pub fn init(status: Status) u8 {
268
268
  assert(status != .SLP and status != .EXT);
269
269
  return @as(u8, 1) << @intCast(@intFromEnum(status));
270
270
  }
271
271
 
272
272
  /// Initializes a non self-inflicted sleep status with duration `dur`.
273
- pub inline fn slp(dur: u3) u8 {
273
+ pub fn slp(dur: u3) u8 {
274
274
  assert(dur > 0);
275
275
  return @as(u8, dur);
276
276
  }
277
277
 
278
278
  /// Initializes a self-inflicted sleep status with duration `dur`.
279
- pub inline fn slf(dur: u3) u8 {
279
+ pub fn slf(dur: u3) u8 {
280
280
  assert(dur > 0);
281
281
  return 0x80 | slp(dur);
282
282
  }
283
283
 
284
284
  /// Returns the duration of a sleep status.
285
- pub inline fn duration(num: u8) u3 {
285
+ pub fn duration(num: u8) u3 {
286
286
  return @intCast(num & SLP);
287
287
  }
288
288
 
289
289
  /// Returns whether `num` reflects any status.
290
- pub inline fn any(num: u8) bool {
290
+ pub fn any(num: u8) bool {
291
291
  return num > 0;
292
292
  }
293
293
 
@@ -316,12 +316,12 @@ test Status {
316
316
  try expect(Status.is(Status.slp(5), .SLP));
317
317
  try expect(!Status.is(Status.slp(5), .EXT));
318
318
  try expect(!Status.is(Status.slp(7), .PSN));
319
- try expectEqual(@as(u3, 5), Status.duration(Status.slp(5)));
319
+ try expectEqual(5, Status.duration(Status.slp(5)));
320
320
  try expect(Status.is(Status.slf(2), .SLP));
321
321
  try expect(Status.is(Status.slf(2), .EXT));
322
322
  try expect(Status.is(Status.TOX, .PSN));
323
323
  try expect(Status.is(Status.TOX, .EXT));
324
- try expectEqual(@as(u3, 1), Status.duration(Status.slp(1)));
324
+ try expectEqual(1, Status.duration(Status.slp(1)));
325
325
  }
326
326
 
327
327
  /// Bitfield representation of volatile statuses and associated data in Generation I.
@@ -378,9 +378,9 @@ pub const Volatiles = packed struct(u64) {
378
378
  /// The identity of whom the active Pokémon is transformed into.
379
379
  transform: u4 = 0,
380
380
  /// The remaining turns the move is disabled.
381
- disabled_duration: u4 = 0,
381
+ disable_duration: u4 = 0,
382
382
  /// The move slot (1-4) that is disabled.
383
- disabled_move: u3 = 0,
383
+ disable_move: u3 = 0,
384
384
  /// The number of turns toxic damage has been accumulating.
385
385
  toxic: u5 = 0,
386
386
  };
@@ -395,8 +395,8 @@ test Volatiles {
395
395
  volatiles.Substitute = true;
396
396
  volatiles.substitute = 42;
397
397
  volatiles.toxic = 4;
398
- volatiles.disabled_move = 2;
399
- volatiles.disabled_duration = 4;
398
+ volatiles.disable_move = 2;
399
+ volatiles.disable_duration = 4;
400
400
 
401
401
  try expect(volatiles.Confusion);
402
402
  try expect(volatiles.Thrashing);
@@ -405,13 +405,13 @@ test Volatiles {
405
405
  try expect(!volatiles.Transform);
406
406
  try expect(!volatiles.MultiHit);
407
407
 
408
- try expectEqual(@as(u16, 235), volatiles.state);
409
- try expectEqual(@as(u8, 42), volatiles.substitute);
410
- try expectEqual(@as(u4, 2), volatiles.disabled_move);
411
- try expectEqual(@as(u4, 4), volatiles.disabled_duration);
412
- try expectEqual(@as(u4, 2), volatiles.confusion);
413
- try expectEqual(@as(u5, 4), volatiles.toxic);
414
- try expectEqual(@as(u4, 3), volatiles.attacks);
408
+ try expectEqual(235, volatiles.state);
409
+ try expectEqual(42, volatiles.substitute);
410
+ try expectEqual(2, volatiles.disable_move);
411
+ try expectEqual(4, volatiles.disable_duration);
412
+ try expectEqual(2, volatiles.confusion);
413
+ try expectEqual(4, volatiles.toxic);
414
+ try expectEqual(3, volatiles.attacks);
415
415
  }
416
416
 
417
417
  /// Representaiton of a Pokémon's stats in Generation I.
@@ -442,9 +442,9 @@ test Stats {
442
442
  try expectEqual(0, stats.def);
443
443
 
444
444
  var base = Species.get(.Gyarados).stats;
445
- try expectEqual(@as(u16, 127), Stats(u16).calc("hp", base.hp, 0, 5120, 38));
445
+ try expectEqual(127, Stats(u16).calc("hp", base.hp, 0, 5120, 38));
446
446
  base = Species.get(.Pidgeot).stats;
447
- try expectEqual(@as(u16, 279), Stats(u16).calc("spe", base.spe, 15, 63001, 100));
447
+ try expectEqual(279, Stats(u16).calc("spe", base.spe, 15, 63001, 100));
448
448
  }
449
449
 
450
450
  /// Representation of a Pokémon's boosts in Generation I.
@@ -537,7 +537,7 @@ pub const Species = species.Species;
537
537
 
538
538
  test Species {
539
539
  try expectEqual(2, @intFromEnum(Species.Ivysaur));
540
- try expectEqual(@as(u8, 100), Species.get(.Mew).stats.def);
540
+ try expectEqual(100, Species.get(.Mew).stats.def);
541
541
  }
542
542
 
543
543
  /// Representation of a Generation I type in Pokémon.
@@ -576,8 +576,8 @@ test Types {
576
576
  try expectEqual(Effectiveness.Resisted, Type.effectiveness(.Fire, .Water));
577
577
  try expectEqual(Effectiveness.Neutral, Type.effectiveness(.Normal, .Grass));
578
578
 
579
- try expectEqual(@as(u8, 3), Type.precedence(.Water, .Water));
580
- try expectEqual(@as(u8, 26), Type.precedence(.Bug, .Ghost));
579
+ try expectEqual(3, Type.precedence(.Water, .Water));
580
+ try expectEqual(26, Type.precedence(.Bug, .Ghost));
581
581
  try expect(Type.precedence(.Poison, .Bug) > Type.precedence(.Poison, .Poison));
582
582
 
583
583
  const t: Types = .{ .type1 = .Rock, .type2 = .Ground };
@@ -617,18 +617,18 @@ pub const DVs = struct {
617
617
 
618
618
  test DVs {
619
619
  var dvs: DVs = .{ .spc = 15, .spe = 15 };
620
- try expectEqual(@as(u4, 15), dvs.hp());
620
+ try expectEqual(15, dvs.hp());
621
621
  dvs = .{
622
622
  .atk = 5,
623
623
  .def = 15,
624
624
  .spe = 13,
625
625
  .spc = 13,
626
626
  };
627
- try expectEqual(@as(u4, 15), dvs.hp());
627
+ try expectEqual(15, dvs.hp());
628
628
  dvs = .{
629
629
  .def = 3,
630
630
  .spe = 10,
631
631
  .spc = 11,
632
632
  };
633
- try expectEqual(@as(u4, 13), dvs.hp());
633
+ try expectEqual(13, dvs.hp());
634
634
  }