@pkmn/engine 0.1.0-dev.f918c3bd → 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 (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 +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 +25 -3
  13. package/build/pkg/addon.js +39 -71
  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 +17 -4
  17. package/build/pkg/data/protocol.json +23 -9
  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 +13 -17
  21. package/build/pkg/gen1.js +8 -12
  22. package/build/pkg/gen1.js.map +1 -1
  23. package/build/pkg/index.d.ts +40 -91
  24. package/build/pkg/index.js +6 -63
  25. package/build/pkg/index.js.map +1 -1
  26. package/build/pkg/protocol.d.ts +20 -1
  27. package/build/pkg/protocol.js +109 -107
  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 +303 -101
  40. package/package.json +61 -132
  41. package/src/bin/install-pkmn-engine +30 -20
  42. package/src/bin/pkmn-debug +1 -1
  43. package/src/lib/{binding → bindings}/node.zig +8 -21
  44. package/src/lib/bindings/wasm.zig +58 -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 +21 -10
  50. package/src/lib/common/options.zig +6 -0
  51. package/src/lib/common/protocol.zig +421 -393
  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 +434 -307
  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 +7 -8
  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 +641 -557
  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 +13 -21
  66. package/src/lib/gen2/data/moves.zig +67 -47
  67. package/src/lib/gen2/data/species.zig +2 -4
  68. package/src/lib/gen2/data/types.zig +134 -32
  69. package/src/lib/gen2/data.zig +56 -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 +2778 -362
  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 +96 -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 -328
  83. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -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 gen1 = @import("../../gen1/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 = gen1.Type;
12
10
 
@@ -1599,43 +1597,43 @@ pub const Move = enum(u8) {
1599
1597
  }
1600
1598
 
1601
1599
  /// Whether this effect activates during the "begin" step of move execution.
1602
- pub inline fn onBegin(effect: Effect) bool {
1600
+ pub fn onBegin(effect: Effect) bool {
1603
1601
  return @intFromEnum(effect) > 0 and @intFromEnum(effect) <= 16;
1604
1602
  }
1605
1603
 
1606
1604
  /// Whether this effect lowers stats.
1607
- pub inline fn isStatDown(effect: Effect) bool {
1605
+ pub fn isStatDown(effect: Effect) bool {
1608
1606
  return @intFromEnum(effect) > 16 and @intFromEnum(effect) <= 21;
1609
1607
  }
1610
1608
 
1611
1609
  /// Whether this effect activates during the "end" step of move execution.
1612
- pub inline fn onEnd(effect: Effect) bool {
1610
+ pub fn onEnd(effect: Effect) bool {
1613
1611
  return @intFromEnum(effect) > 16 and @intFromEnum(effect) <= 31;
1614
1612
  }
1615
1613
 
1616
1614
  /// Whether this effect is considered to "always happen".
1617
- pub inline fn alwaysHappens(effect: Effect) bool {
1615
+ pub fn alwaysHappens(effect: Effect) bool {
1618
1616
  return @intFromEnum(effect) > 31 and @intFromEnum(effect) <= 38;
1619
1617
  }
1620
1618
 
1621
1619
  /// Whether this effect is handled specially by the engine.
1622
- pub inline fn isSpecial(effect: Effect) bool {
1620
+ pub fn isSpecial(effect: Effect) bool {
1623
1621
  // NB: isSpecial includes isMulti up to Twineedle
1624
1622
  return @intFromEnum(effect) > 31 and @intFromEnum(effect) <= 46;
1625
1623
  }
1626
1624
 
1627
1625
  /// Whether this effect is a multi-hit effect.
1628
- pub inline fn isMulti(effect: Effect) bool {
1626
+ pub fn isMulti(effect: Effect) bool {
1629
1627
  return @intFromEnum(effect) > 44 and @intFromEnum(effect) <= 47;
1630
1628
  }
1631
1629
 
1632
1630
  /// Whether this effect is has chance of lowering stats.
1633
- pub inline fn isStatDownChance(effect: Effect) bool {
1631
+ pub fn isStatDownChance(effect: Effect) bool {
1634
1632
  return @intFromEnum(effect) > 47 and @intFromEnum(effect) <= 51;
1635
1633
  }
1636
1634
 
1637
1635
  /// Whether this effect has a secondary chance.
1638
- pub inline fn isSecondaryChance(effect: Effect) bool {
1636
+ pub fn isSecondaryChance(effect: Effect) bool {
1639
1637
  // NB: isSecondaryChance includes isStatDownChance as well as Twineedle
1640
1638
  return (@intFromEnum(effect) > 46 and @intFromEnum(effect) <= 61);
1641
1639
  }
@@ -1838,8 +1836,22 @@ pub const Move = enum(u8) {
1838
1836
  /// The number of Pokémon moves in this generation.
1839
1837
  pub const size = 165;
1840
1838
 
1839
+ /// Pokémon moves that can be called by Metronome in this generation.
1840
+ pub const METRONOME = init: {
1841
+ var num = 0;
1842
+ var moves: [163]Move = undefined;
1843
+ for (1..Move.size) |i| {
1844
+ if (i != @intFromEnum(Move.Metronome)) {
1845
+ moves[num] = @enumFromInt(i);
1846
+ num += 1;
1847
+ }
1848
+ }
1849
+ assert(num == moves.len);
1850
+ break :init moves;
1851
+ };
1852
+
1841
1853
  /// Returns the `Data` corresponding to the move.
1842
- pub inline fn get(id: Move) Data {
1854
+ pub fn get(id: Move) Data {
1843
1855
  assert(id != .None and id != .SKIP_TURN);
1844
1856
  return DATA[@intFromEnum(id) - 1];
1845
1857
  }
@@ -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 gen1 = @import("../../gen1/data.zig");
4
+ const std = @import("std");
6
5
 
7
6
  const assert = std.debug.assert;
8
-
9
7
  const Stats = gen1.Stats;
10
8
  const Types = gen1.Types;
11
9
 
@@ -1091,8 +1089,8 @@ pub const Species = enum(u8) {
1091
1089
  /// The number of Pokémon species in this generation.
1092
1090
  pub const size = 151;
1093
1091
 
1094
- /// The Pokémon's critical hit rate=io out of 256.
1095
- pub inline fn chance(id: Species) u8 {
1092
+ /// The Pokémon's critical hit ratio out of 256.
1093
+ pub fn chance(id: Species) u8 {
1096
1094
  assert(id != .None);
1097
1095
  return CHANCES[@intFromEnum(id) - 1];
1098
1096
  }
@@ -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;
@@ -90,16 +89,16 @@ pub const Type = enum(u4) {
90
89
  pub const size = 15;
91
90
 
92
91
  /// Whether or not this type is considered to be special as opposed to physical.
93
- pub inline fn special(self: Type) bool {
92
+ pub fn special(self: Type) bool {
94
93
  return @intFromEnum(self) >= @intFromEnum(Type.Fire);
95
94
  }
96
95
 
97
96
  /// The `Effectiveness` of type `t2` vs. type `t1`.
98
- pub inline fn effectiveness(t1: Type, t2: Type) Effectiveness {
97
+ pub fn effectiveness(t1: Type, t2: Type) Effectiveness {
99
98
  return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
100
99
  }
101
100
 
102
- /// The precedence order of type `t2` vs. type `t1`.
101
+ /// The precedence order of Type `t2` vs. Type `t1`.
103
102
  pub fn precedence(t1: Type, t2: Type) u8 {
104
103
  for (PRECEDENCE, 0..) |matchup, i| {
105
104
  if (matchup.type1 == t1 and matchup.type2 == t2) return @intCast(i);
@@ -120,12 +119,12 @@ pub const Types = packed struct {
120
119
  }
121
120
 
122
121
  /// Whether this typing is immune to type `t`.
123
- pub inline fn immune(self: Types, t: Type) bool {
122
+ pub fn immune(self: Types, t: Type) bool {
124
123
  return t.effectiveness(self.type1) == I or t.effectiveness(self.type2) == I;
125
124
  }
126
125
 
127
126
  /// Whether this typing includes type `t`.
128
- pub inline fn includes(self: Types, t: Type) bool {
127
+ pub fn includes(self: Types, t: Type) bool {
129
128
  return self.type1 == t or self.type2 == t;
130
129
  }
131
130
  };
@@ -1,20 +1,16 @@
1
- const std = @import("std");
2
1
  const builtin = @import("builtin");
3
-
4
- const pkmn = @import("../pkmn.zig");
5
-
2
+ const calc = @import("calc.zig");
3
+ const chance = @import("chance.zig");
6
4
  const data = @import("../common/data.zig");
5
+ const mechanics = @import("mechanics.zig");
6
+ const moves = @import("data/moves.zig");
7
+ const pkmn = @import("../pkmn.zig");
7
8
  const protocol = @import("../common/protocol.zig");
8
9
  const rng = @import("../common/rng.zig");
9
- const util = @import("../common/util.zig");
10
-
11
- const moves = @import("data/moves.zig");
12
10
  const species = @import("data/species.zig");
11
+ const std = @import("std");
13
12
  const types = @import("data/types.zig");
14
-
15
- const calc = @import("calc.zig");
16
- const chance = @import("chance.zig");
17
- const mechanics = @import("mechanics.zig");
13
+ const util = @import("../common/util.zig");
18
14
 
19
15
  const assert = std.debug.assert;
20
16
  const expectEqual = std.testing.expectEqual;
@@ -22,11 +18,11 @@ const expect = std.testing.expect;
22
18
 
23
19
  /// The minimum size in bytes required to hold all Generation I choice options.
24
20
  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.
21
+ /// The maximum number of bytes possibly logged by a single Generation I update.
27
22
  pub const MAX_LOGS: usize = 180;
28
23
 
29
- /// The maximum number of bytes possibly logged by a single Generation I update.
24
+ /// The optimal size in bytes required to hold all Generation I choice options.
25
+ /// At least as large as MAX_CHOICES.
30
26
  pub const CHOICES_SIZE = if (builtin.mode == .ReleaseSmall)
31
27
  MAX_CHOICES
32
28
  else
@@ -47,6 +43,7 @@ const Player = data.Player;
47
43
  const Result = data.Result;
48
44
 
49
45
  const PointerType = util.PointerType;
46
+ const isPointerTo = util.isPointerTo;
50
47
 
51
48
  const showdown = pkmn.options.showdown;
52
49
 
@@ -70,28 +67,28 @@ pub fn Battle(comptime RNG: anytype) type {
70
67
  rng: RNG,
71
68
 
72
69
  /// Returns the `Side` for the given `player`.
73
- pub inline fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
74
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
70
+ pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
71
+ assert(isPointerTo(self, Self));
75
72
  return &self.sides[@intFromEnum(player)];
76
73
  }
77
74
 
78
75
  /// Returns the `Side` of the opponent for the given `player`
79
- pub inline fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
80
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
76
+ pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
77
+ assert(isPointerTo(self, Self));
81
78
  return &self.sides[@intFromEnum(player.foe())];
82
79
  }
83
80
 
84
81
  /// Returns an identifier for the active Pokémon of `player`.
85
- pub inline fn active(self: *const Self, player: Player) ID {
82
+ pub fn active(self: *const Self, player: Player) ID {
86
83
  return player.ident(@intCast(self.side(player).order[0]));
87
84
  }
88
85
 
89
86
  /// Returns the `MoveDetails` for the given `player`.
90
- pub inline fn lastMove(
87
+ pub fn lastMove(
91
88
  self: anytype,
92
89
  player: Player,
93
90
  ) PointerType(@TypeOf(self), MoveDetails) {
94
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
91
+ assert(isPointerTo(self, Self));
95
92
  return &self.last_moves[@intFromEnum(player)];
96
93
  }
97
94
 
@@ -112,7 +109,7 @@ pub fn Battle(comptime RNG: anytype) type {
112
109
  /// make (i.e. on the cartridge a soft-lock occurs).
113
110
  ///
114
111
  /// 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 {
112
+ pub fn choices(self: *const Self, player: Player, request: Choice.Type, out: []Choice) u8 {
116
113
  return mechanics.choices(self, player, request, out);
117
114
  }
118
115
  };
@@ -141,8 +138,8 @@ pub const Side = extern struct {
141
138
  }
142
139
 
143
140
  /// Returns the stored `Pokemon` corresponding to the one-indexed party `slot`.
144
- pub inline fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
145
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
141
+ pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
142
+ assert(isPointerTo(self, Side));
146
143
  assert(slot > 0 and slot <= 6);
147
144
  const id = self.order[slot - 1];
148
145
  assert(id > 0 and id <= 6);
@@ -150,8 +147,8 @@ pub const Side = extern struct {
150
147
  }
151
148
 
152
149
  /// Returns the stored `Pokemon` corresponding to the `active` Pokémon (slot 1).
153
- pub inline fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
154
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
150
+ pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
151
+ assert(isPointerTo(self, Side));
155
152
  return self.get(1);
156
153
  }
157
154
  };
@@ -176,8 +173,8 @@ pub const ActivePokemon = extern struct {
176
173
  }
177
174
 
178
175
  /// 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) {
180
- assert(@typeInfo(@TypeOf(self)).Pointer.child == ActivePokemon);
176
+ pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
177
+ assert(isPointerTo(self, ActivePokemon));
181
178
  assert(mslot > 0 and mslot <= 4);
182
179
  assert(self.moves[mslot - 1].id != .None);
183
180
  return &self.moves[mslot - 1];
@@ -206,8 +203,8 @@ pub const Pokemon = extern struct {
206
203
  }
207
204
 
208
205
  /// 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) {
210
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
206
+ pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
207
+ assert(isPointerTo(self, Pokemon));
211
208
  assert(mslot > 0 and mslot <= 4);
212
209
  assert(self.moves[mslot - 1].id != .None);
213
210
  return &self.moves[mslot - 1];
@@ -255,39 +252,39 @@ pub const Status = enum(u8) {
255
252
 
256
253
  pub const TOX = 0b10001000;
257
254
 
258
- const SLP = 0b111;
255
+ const SLEEP = 0b111;
259
256
 
260
257
  /// Whether or not the status `num` is the same as `status`.
261
- pub inline fn is(num: u8, status: Status) bool {
258
+ pub fn is(num: u8, status: Status) bool {
262
259
  if (status == .SLP) return Status.duration(num) > 0;
263
260
  return ((num >> @intCast(@intFromEnum(status))) & 1) != 0;
264
261
  }
265
262
 
266
263
  /// Initializes a non-sleep `status`. Use `slp` or `slf` to initialize a sleep status.
267
- pub inline fn init(status: Status) u8 {
264
+ pub fn init(status: Status) u8 {
268
265
  assert(status != .SLP and status != .EXT);
269
266
  return @as(u8, 1) << @intCast(@intFromEnum(status));
270
267
  }
271
268
 
272
269
  /// Initializes a non self-inflicted sleep status with duration `dur`.
273
- pub inline fn slp(dur: u3) u8 {
270
+ pub fn slp(dur: u3) u8 {
274
271
  assert(dur > 0);
275
272
  return @as(u8, dur);
276
273
  }
277
274
 
278
275
  /// Initializes a self-inflicted sleep status with duration `dur`.
279
- pub inline fn slf(dur: u3) u8 {
276
+ pub fn slf(dur: u3) u8 {
280
277
  assert(dur > 0);
281
278
  return 0x80 | slp(dur);
282
279
  }
283
280
 
284
281
  /// Returns the duration of a sleep status.
285
- pub inline fn duration(num: u8) u3 {
286
- return @intCast(num & SLP);
282
+ pub fn duration(num: u8) u3 {
283
+ return @intCast(num & SLEEP);
287
284
  }
288
285
 
289
286
  /// Returns whether `num` reflects any status.
290
- pub inline fn any(num: u8) bool {
287
+ pub fn any(num: u8) bool {
291
288
  return num > 0;
292
289
  }
293
290
 
@@ -378,9 +375,9 @@ pub const Volatiles = packed struct(u64) {
378
375
  /// The identity of whom the active Pokémon is transformed into.
379
376
  transform: u4 = 0,
380
377
  /// The remaining turns the move is disabled.
381
- disabled_duration: u4 = 0,
378
+ disable_duration: u4 = 0,
382
379
  /// The move slot (1-4) that is disabled.
383
- disabled_move: u3 = 0,
380
+ disable_move: u3 = 0,
384
381
  /// The number of turns toxic damage has been accumulating.
385
382
  toxic: u5 = 0,
386
383
  };
@@ -395,8 +392,8 @@ test Volatiles {
395
392
  volatiles.Substitute = true;
396
393
  volatiles.substitute = 42;
397
394
  volatiles.toxic = 4;
398
- volatiles.disabled_move = 2;
399
- volatiles.disabled_duration = 4;
395
+ volatiles.disable_move = 2;
396
+ volatiles.disable_duration = 4;
400
397
 
401
398
  try expect(volatiles.Confusion);
402
399
  try expect(volatiles.Thrashing);
@@ -407,14 +404,14 @@ test Volatiles {
407
404
 
408
405
  try expectEqual(@as(u16, 235), volatiles.state);
409
406
  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);
407
+ try expectEqual(@as(u4, 2), volatiles.disable_move);
408
+ try expectEqual(@as(u4, 4), volatiles.disable_duration);
409
+ try expectEqual(@as(u3, 2), volatiles.confusion);
413
410
  try expectEqual(@as(u5, 4), volatiles.toxic);
414
- try expectEqual(@as(u4, 3), volatiles.attacks);
411
+ try expectEqual(@as(u3, 3), volatiles.attacks);
415
412
  }
416
413
 
417
- /// Representaiton of a Pokémon's stats in Generation I.
414
+ /// Representation of a Pokémon's stats in Generation I.
418
415
  pub fn Stats(comptime T: type) type {
419
416
  return extern struct {
420
417
  hp: T = 0,