@pkmn/engine 0.1.0-dev.b01cb48c → 0.1.0-dev.b3197aa3

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 (81) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +54 -6
  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 +34 -65
  14. package/build/pkg/addon.js.map +1 -1
  15. package/build/pkg/data/layout.json +15 -2
  16. package/build/pkg/data/protocol.json +23 -9
  17. package/build/pkg/data.d.ts +23 -1
  18. package/build/pkg/data.js.map +1 -1
  19. package/build/pkg/gen1.d.ts +15 -18
  20. package/build/pkg/gen1.js +28 -19
  21. package/build/pkg/gen1.js.map +1 -1
  22. package/build/pkg/index.d.ts +40 -90
  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 +105 -103
  27. package/build/pkg/protocol.js.map +1 -1
  28. package/build/tools/debug.js +52 -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 +331 -85
  39. package/package.json +56 -136
  40. package/src/bin/install-pkmn-engine +10 -7
  41. package/src/bin/pkmn-debug +1 -1
  42. package/src/lib/bindings/c.zig +255 -0
  43. package/src/lib/bindings/node.zig +117 -0
  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 -6
  49. package/src/lib/common/napi.zig +4 -0
  50. package/src/lib/common/optional.zig +13 -9
  51. package/src/lib/common/options.zig +4 -0
  52. package/src/lib/common/protocol.zig +44 -43
  53. package/src/lib/common/rational.zig +317 -304
  54. package/src/lib/common/rng.zig +5 -7
  55. package/src/lib/common/util.zig +65 -1
  56. package/src/lib/gen1/calc.zig +266 -135
  57. package/src/lib/gen1/chance.zig +469 -110
  58. package/src/lib/gen1/data/moves.zig +2 -4
  59. package/src/lib/gen1/data/species.zig +1 -3
  60. package/src/lib/gen1/data/types.zig +2 -3
  61. package/src/lib/gen1/data.zig +35 -38
  62. package/src/lib/gen1/helpers.zig +17 -27
  63. package/src/lib/gen1/mechanics.zig +213 -160
  64. package/src/lib/gen2/calc.zig +37 -27
  65. package/src/lib/gen2/chance.zig +87 -67
  66. package/src/lib/gen2/data/items.zig +1 -3
  67. package/src/lib/gen2/data/moves.zig +2 -4
  68. package/src/lib/gen2/data/species.zig +1 -3
  69. package/src/lib/gen2/data/types.zig +7 -5
  70. package/src/lib/gen2/data.zig +28 -30
  71. package/src/lib/gen2/generated.zig +18 -23
  72. package/src/lib/gen2/helpers.zig +9 -18
  73. package/src/lib/gen2/mechanics.zig +82 -82
  74. package/src/lib/node.zig +4 -121
  75. package/src/lib/pkmn.zig +14 -7
  76. package/src/lib/wasm.zig +13 -9
  77. package/src/tools/display/dom.ts +93 -0
  78. package/src/tools/display/ui.css +354 -0
  79. package/build/test/display.js +0 -405
  80. package/build/test/display.js.map +0 -1
  81. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -1,12 +1,10 @@
1
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
 
@@ -1,11 +1,9 @@
1
1
  //! Code generated by `tools/generate` - manual edits will be overwritten.
2
2
 
3
- const std = @import("std");
4
-
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
 
@@ -1,8 +1,7 @@
1
1
  //! Code generated by `tools/generate` - manual edits will be overwritten.
2
2
 
3
- const std = @import("std");
4
-
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;
@@ -99,7 +98,7 @@ pub const Type = enum(u4) {
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 `t1` vs. Type `t2`.
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);
@@ -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;
@@ -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
 
@@ -71,13 +68,13 @@ pub fn Battle(comptime RNG: anytype) type {
71
68
 
72
69
  /// Returns the `Side` for the given `player`.
73
70
  pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
74
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
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
76
  pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
80
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
77
+ assert(isPointerTo(self, Self));
81
78
  return &self.sides[@intFromEnum(player.foe())];
82
79
  }
83
80
 
@@ -91,7 +88,7 @@ pub fn Battle(comptime RNG: anytype) type {
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
 
@@ -142,7 +139,7 @@ pub const Side = extern struct {
142
139
 
143
140
  /// Returns the stored `Pokemon` corresponding to the one-indexed party `slot`.
144
141
  pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
145
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
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);
@@ -151,7 +148,7 @@ pub const Side = extern struct {
151
148
 
152
149
  /// Returns the stored `Pokemon` corresponding to the `active` Pokémon (slot 1).
153
150
  pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
154
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
151
+ assert(isPointerTo(self, Side));
155
152
  return self.get(1);
156
153
  }
157
154
  };
@@ -177,7 +174,7 @@ pub const ActivePokemon = extern struct {
177
174
 
178
175
  /// Returns the active Pokémon's current move slot located at the one-indexed `mslot`.
179
176
  pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
180
- assert(@typeInfo(@TypeOf(self)).Pointer.child == ActivePokemon);
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];
@@ -207,7 +204,7 @@ pub const Pokemon = extern struct {
207
204
 
208
205
  /// Returns the Pokémon's original move slot located at the one-indexed `mslot`.
209
206
  pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
210
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
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,7 +252,7 @@ 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
258
  pub fn is(num: u8, status: Status) bool {
@@ -283,7 +280,7 @@ pub const Status = enum(u8) {
283
280
 
284
281
  /// Returns the duration of a sleep status.
285
282
  pub fn duration(num: u8) u3 {
286
- return @intCast(num & SLP);
283
+ return @intCast(num & SLEEP);
287
284
  }
288
285
 
289
286
  /// Returns whether `num` reflects any status.
@@ -316,12 +313,12 @@ test Status {
316
313
  try expect(Status.is(Status.slp(5), .SLP));
317
314
  try expect(!Status.is(Status.slp(5), .EXT));
318
315
  try expect(!Status.is(Status.slp(7), .PSN));
319
- try expectEqual(5, Status.duration(Status.slp(5)));
316
+ try expectEqual(@as(u3, 5), Status.duration(Status.slp(5)));
320
317
  try expect(Status.is(Status.slf(2), .SLP));
321
318
  try expect(Status.is(Status.slf(2), .EXT));
322
319
  try expect(Status.is(Status.TOX, .PSN));
323
320
  try expect(Status.is(Status.TOX, .EXT));
324
- try expectEqual(1, Status.duration(Status.slp(1)));
321
+ try expectEqual(@as(u3, 1), Status.duration(Status.slp(1)));
325
322
  }
326
323
 
327
324
  /// Bitfield representation of volatile statuses and associated data in Generation I.
@@ -405,16 +402,16 @@ test Volatiles {
405
402
  try expect(!volatiles.Transform);
406
403
  try expect(!volatiles.MultiHit);
407
404
 
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);
405
+ try expectEqual(@as(u16, 235), volatiles.state);
406
+ try expectEqual(@as(u8, 42), volatiles.substitute);
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);
410
+ try expectEqual(@as(u5, 4), volatiles.toxic);
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,
@@ -442,9 +439,9 @@ test Stats {
442
439
  try expectEqual(0, stats.def);
443
440
 
444
441
  var base = Species.get(.Gyarados).stats;
445
- try expectEqual(127, Stats(u16).calc("hp", base.hp, 0, 5120, 38));
442
+ try expectEqual(@as(u16, 127), Stats(u16).calc("hp", base.hp, 0, 5120, 38));
446
443
  base = Species.get(.Pidgeot).stats;
447
- try expectEqual(279, Stats(u16).calc("spe", base.spe, 15, 63001, 100));
444
+ try expectEqual(@as(u16, 279), Stats(u16).calc("spe", base.spe, 15, 63001, 100));
448
445
  }
449
446
 
450
447
  /// Representation of a Pokémon's boosts in Generation I.
@@ -537,7 +534,7 @@ pub const Species = species.Species;
537
534
 
538
535
  test Species {
539
536
  try expectEqual(2, @intFromEnum(Species.Ivysaur));
540
- try expectEqual(100, Species.get(.Mew).stats.def);
537
+ try expectEqual(@as(u8, 100), Species.get(.Mew).stats.def);
541
538
  }
542
539
 
543
540
  /// Representation of a Generation I type in Pokémon.
@@ -576,8 +573,8 @@ test Types {
576
573
  try expectEqual(Effectiveness.Resisted, Type.effectiveness(.Fire, .Water));
577
574
  try expectEqual(Effectiveness.Neutral, Type.effectiveness(.Normal, .Grass));
578
575
 
579
- try expectEqual(3, Type.precedence(.Water, .Water));
580
- try expectEqual(26, Type.precedence(.Bug, .Ghost));
576
+ try expectEqual(@as(u8, 3), Type.precedence(.Water, .Water));
577
+ try expectEqual(@as(u8, 26), Type.precedence(.Bug, .Ghost));
581
578
  try expect(Type.precedence(.Poison, .Bug) > Type.precedence(.Poison, .Poison));
582
579
 
583
580
  const t: Types = .{ .type1 = .Rock, .type2 = .Ground };
@@ -617,18 +614,18 @@ pub const DVs = struct {
617
614
 
618
615
  test DVs {
619
616
  var dvs: DVs = .{ .spc = 15, .spe = 15 };
620
- try expectEqual(15, dvs.hp());
617
+ try expectEqual(@as(u4, 15), dvs.hp());
621
618
  dvs = .{
622
619
  .atk = 5,
623
620
  .def = 15,
624
621
  .spe = 13,
625
622
  .spc = 13,
626
623
  };
627
- try expectEqual(15, dvs.hp());
624
+ try expectEqual(@as(u4, 15), dvs.hp());
628
625
  dvs = .{
629
626
  .def = 3,
630
627
  .spe = 10,
631
628
  .spc = 11,
632
629
  };
633
- try expectEqual(13, dvs.hp());
630
+ try expectEqual(@as(u4, 13), dvs.hp());
634
631
  }
@@ -1,31 +1,26 @@
1
- const std = @import("std");
2
1
  const builtin = @import("builtin");
3
-
4
2
  const common = @import("../common/data.zig");
3
+ const data = @import("data.zig");
5
4
  const options = @import("../common/options.zig");
6
5
  const protocol = @import("../common/protocol.zig");
7
6
  const rng = @import("../common/rng.zig");
8
-
9
- const data = @import("data.zig");
7
+ const std = @import("std");
8
+ const util = @import("../common/util.zig");
10
9
 
11
10
  const assert = std.debug.assert;
12
-
13
11
  const Choice = common.Choice;
14
- const Player = common.Player;
15
-
16
- const showdown = options.showdown;
17
-
18
- const PSRNG = rng.PSRNG;
19
-
20
12
  const DVs = data.DVs;
21
13
  const Move = data.Move;
22
14
  const MoveSlot = data.MoveSlot;
15
+ const PSRNG = rng.PSRNG;
16
+ const showdown = options.showdown;
23
17
  const Species = data.Species;
24
18
  const Stats = data.Stats;
25
- const Status = data.Status;
26
19
 
27
20
  const endian = builtin.cpu.arch.endian();
28
21
 
22
+ const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
23
+
29
24
  /// Configuration options controlling the domain of valid Pokémon that can be generated by the
30
25
  /// random generator helpers.
31
26
  pub const Options = struct {
@@ -168,7 +163,7 @@ pub const Pokemon = struct {
168
163
  var pokemon = data.Pokemon{};
169
164
  pokemon.species = p.species;
170
165
  const species = Species.get(p.species);
171
- inline for (@typeInfo(@TypeOf(pokemon.stats)).Struct.fields) |field| {
166
+ inline for (@field(@typeInfo(@TypeOf(pokemon.stats)), @tagName(Struct)).fields) |field| {
172
167
  const hp = comptime std.mem.eql(u8, field.name, "hp");
173
168
  const spc =
174
169
  comptime std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
@@ -204,7 +199,7 @@ pub const Pokemon = struct {
204
199
  const lvl = if (rand.chance(u8, 1, 20)) rand.range(u8, 1, 99 + 1) else 100;
205
200
  var stats: Stats(u16) = .{};
206
201
  const dvs = DVs.random(rand);
207
- inline for (@typeInfo(@TypeOf(stats)).Struct.fields) |field| {
202
+ inline for (@field(@typeInfo(@TypeOf(stats)), @tagName(Struct)).fields) |field| {
208
203
  @field(stats, field.name) = Stats(u16).calc(
209
204
  field.name,
210
205
  @field(species.stats, field.name),
@@ -245,6 +240,7 @@ pub const Pokemon = struct {
245
240
  .stats = stats,
246
241
  .hp = if (opt.cleric) stats.hp else rand.range(u16, 0, stats.hp + 1),
247
242
  .status = if (!opt.cleric and rand.chance(u8, 1, 6 + 1))
243
+ // NB: This will only assign sleep as 2 or 4 when rolled
248
244
  0 | (@as(u8, 1) << rand.range(u3, 1, 6 + 1))
249
245
  else
250
246
  0,
@@ -264,14 +260,7 @@ fn blocked(m: Move) bool {
264
260
  fn durations(m: Move) bool {
265
261
  // Any moves that have effects that result in duration tracking with -Dchance
266
262
  return switch (Move.get(m).effect) {
267
- .Confusion,
268
- .Bide,
269
- .Sleep,
270
- .Rage,
271
- .Binding,
272
- .Thrashing,
273
- .ConfusionChance,
274
- .Disable,
263
+ .Haze,
275
264
  .Metronome,
276
265
  => true,
277
266
  else => false,
@@ -290,7 +279,7 @@ pub fn swtch(slot: u4) Choice {
290
279
 
291
280
  /// Empirically determined maximum number of bytes possibly required to store the diff between two
292
281
  /// Generation I battles.
293
- pub const MAX_DIFFS: usize = 117;
282
+ pub const MAX_DIFFS: usize = 120;
294
283
 
295
284
  /// The optimal size in bytes required to hold the diff between two Generation I battles.
296
285
  /// At least as large as MAX_DIFFS.
@@ -312,8 +301,8 @@ pub fn diff(
312
301
 
313
302
  var i: usize = 0;
314
303
  while (i < size) : (i += 2) {
315
- const val = std.mem.bytesAsValue(u16, std.mem.asBytes(a)[i .. i + 2]).*;
316
- if (val != std.mem.bytesAsValue(u16, std.mem.asBytes(b)[i .. i + 2]).*) {
304
+ const val = util.bytesAsValue(u16, std.mem.asBytes(a)[i .. i + 2]).*;
305
+ if (val != util.bytesAsValue(u16, std.mem.asBytes(b)[i .. i + 2]).*) {
317
306
  try w.writeByte(@intCast(i / 2));
318
307
  try w.writeInt(u16, val, endian);
319
308
  }
@@ -327,7 +316,8 @@ pub fn patch(battle: *data.Battle(data.PRNG), buf: []u8) void {
327
316
  var i: usize = 0;
328
317
  while (i < buf.len) : (i += 3) {
329
318
  const off = @as(u16, @intCast(buf[i])) * 2;
330
- const val = std.mem.readInt(u16, @ptrCast(buf[i + 1 .. i + 3]), endian);
331
- std.mem.writeInt(u16, @ptrCast(std.mem.asBytes(battle)[off .. off + 2]), val, endian);
319
+ const val = std.mem.readInt(u16, @as(*const [2]u8, @ptrCast(buf[i + 1 .. i + 3])), endian);
320
+ const bytes: *[2]u8 = @ptrCast(std.mem.asBytes(battle)[off .. off + 2]);
321
+ std.mem.writeInt(u16, bytes, val, endian);
332
322
  }
333
323
  }