@pkmn/engine 0.1.0-dev.a1fcc5d9 → 0.1.0-dev.a27b3ff3

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 (68) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +51 -5
  3. package/build/pkg/addon/browser.d.ts +1 -1
  4. package/build/pkg/addon/browser.js +6 -2
  5. package/build/pkg/addon/browser.js.map +1 -1
  6. package/build/pkg/addon/node.js +22 -8
  7. package/build/pkg/addon/node.js.map +1 -1
  8. package/build/pkg/addon/wasm.d.ts +2 -0
  9. package/build/pkg/addon/wasm.js +53 -0
  10. package/build/pkg/addon/wasm.js.map +1 -0
  11. package/build/pkg/addon.d.ts +24 -4
  12. package/build/pkg/addon.js +8 -17
  13. package/build/pkg/addon.js.map +1 -1
  14. package/build/pkg/data/layout.json +15 -2
  15. package/build/pkg/data/protocol.json +23 -9
  16. package/build/pkg/gen1.d.ts +15 -18
  17. package/build/pkg/gen1.js +28 -19
  18. package/build/pkg/gen1.js.map +1 -1
  19. package/build/pkg/index.d.ts +37 -100
  20. package/build/pkg/index.js +23 -75
  21. package/build/pkg/index.js.map +1 -1
  22. package/build/tools/debug.js +18 -9
  23. package/build/tools/debug.js.map +1 -1
  24. package/build/tools/display/debug.jsx +18 -7
  25. package/build/tools/display/debug.jsx.map +1 -1
  26. package/build/tools/display/index.js +35 -15
  27. package/build/tools/display/index.js.map +1 -1
  28. package/build/tools/display/ui.jsx +17 -7
  29. package/build/tools/display/ui.jsx.map +1 -1
  30. package/build/tools/display/util.js +16 -1
  31. package/build/tools/display/util.js.map +1 -1
  32. package/build.zig +198 -85
  33. package/package.json +29 -125
  34. package/src/bin/install-pkmn-engine +3 -2
  35. package/src/lib/bindings/c.zig +255 -0
  36. package/src/lib/bindings/node.zig +117 -0
  37. package/src/lib/bindings/wasm.zig +59 -0
  38. package/src/lib/common/array.zig +1 -1
  39. package/src/lib/common/js.zig +1 -5
  40. package/src/lib/common/napi.zig +4 -0
  41. package/src/lib/common/optional.zig +1 -1
  42. package/src/lib/common/options.zig +2 -0
  43. package/src/lib/common/protocol.zig +4 -8
  44. package/src/lib/common/rational.zig +281 -270
  45. package/src/lib/common/rng.zig +1 -3
  46. package/src/lib/common/util.zig +17 -2
  47. package/src/lib/gen1/calc.zig +52 -69
  48. package/src/lib/gen1/chance.zig +34 -18
  49. package/src/lib/gen1/data/moves.zig +2 -4
  50. package/src/lib/gen1/data/species.zig +1 -3
  51. package/src/lib/gen1/data/types.zig +2 -3
  52. package/src/lib/gen1/data.zig +7 -11
  53. package/src/lib/gen1/helpers.zig +4 -10
  54. package/src/lib/gen1/mechanics.zig +76 -51
  55. package/src/lib/gen2/calc.zig +10 -18
  56. package/src/lib/gen2/data/items.zig +1 -3
  57. package/src/lib/gen2/data/moves.zig +2 -4
  58. package/src/lib/gen2/data/species.zig +1 -3
  59. package/src/lib/gen2/data/types.zig +7 -5
  60. package/src/lib/gen2/data.zig +14 -17
  61. package/src/lib/gen2/generated.zig +18 -23
  62. package/src/lib/gen2/helpers.zig +5 -12
  63. package/src/lib/gen2/mechanics.zig +42 -39
  64. package/src/lib/node.zig +4 -121
  65. package/src/lib/pkmn.zig +7 -2
  66. package/src/lib/wasm.zig +13 -9
  67. package/src/tools/display/dom.ts +5 -8
  68. package/src/tools/display/ui.css +0 -5
@@ -1,44 +1,35 @@
1
- const std = @import("std");
2
-
3
- const pkmn = @import("../pkmn.zig");
1
+ const DEBUG = @import("../common/debug.zig").print;
4
2
 
3
+ const chance = @import("chance.zig");
5
4
  const common = @import("../common/data.zig");
6
- const DEBUG = @import("../common/debug.zig").print;
5
+ const data = @import("data.zig");
6
+ const helpers = @import("helpers.zig");
7
7
  const optional = @import("../common/optional.zig");
8
+ const pkmn = @import("../pkmn.zig");
8
9
  const protocol = @import("../common/protocol.zig");
9
10
  const rational = @import("../common/rational.zig");
11
+ const std = @import("std");
10
12
  const util = @import("../common/util.zig");
11
13
 
12
- const chance = @import("chance.zig");
13
- const data = @import("data.zig");
14
- const helpers = @import("helpers.zig");
15
-
16
- const assert = std.debug.assert;
17
-
18
- const expect = std.testing.expect;
19
- const expectEqual = std.testing.expectEqual;
20
- const expectEqualSlices = std.testing.expectEqualSlices;
21
-
22
- const enabled = pkmn.options.calc;
23
-
24
- const Player = common.Player;
25
- const Result = common.Result;
26
- const Choice = common.Choice;
27
-
28
- const Optional = optional.Optional;
29
-
30
- const Rational = rational.Rational;
31
-
32
- const PointerType = util.PointerType;
33
- const isPointerTo = util.isPointerTo;
34
-
35
- const Actions = chance.Actions;
36
14
  const Action = chance.Action;
15
+ const Actions = chance.Actions;
16
+ const assert = std.debug.assert;
37
17
  const Chance = chance.Chance;
18
+ const Choice = common.Choice;
38
19
  const Confusion = chance.Confusion;
39
20
  const Duration = chance.Duration;
40
21
  const Durations = chance.Durations;
22
+ const enabled = pkmn.options.calc;
23
+ const expect = std.testing.expect;
24
+ const expectEqual = std.testing.expectEqual;
25
+ const expectEqualSlices = std.testing.expectEqualSlices;
26
+ const isPointerTo = util.isPointerTo;
41
27
  const Observation = chance.Observation;
28
+ const Optional = optional.Optional;
29
+ const Player = common.Player;
30
+ const PointerType = util.PointerType;
31
+ const Rational = rational.Rational;
32
+ const Result = common.Result;
42
33
  const Sleeps = chance.Sleeps;
43
34
 
44
35
  const tty = true; // DEBUG
@@ -108,7 +99,7 @@ pub const Calc = struct {
108
99
  self: Calc,
109
100
  player: Player,
110
101
  comptime field: Action.Field,
111
- ) ?std.meta.FieldType(Action, field) {
102
+ ) ?util.FieldType(Action, field) {
112
103
  if (!enabled) return null;
113
104
 
114
105
  const val = @field(self.overrides.get(player), @tagName(field));
@@ -155,7 +146,7 @@ const Null = struct {
155
146
  self: Null,
156
147
  player: Player,
157
148
  comptime field: Action.Field,
158
- ) ?std.meta.FieldType(Action, field) {
149
+ ) ?util.FieldType(Action, field) {
159
150
  _ = .{ self, player };
160
151
  return null;
161
152
  }
@@ -191,7 +182,7 @@ pub const Options = struct {
191
182
  metronome: bool = false,
192
183
  };
193
184
 
194
- pub const MAX_FRONTIER = 67;
185
+ pub const MAX_FRONTIER = 83;
195
186
 
196
187
  pub fn transitions(
197
188
  battle: anytype,
@@ -225,7 +216,7 @@ pub fn transitions(
225
216
  const p1 = b.side(.P1);
226
217
  const p2 = b.side(.P2);
227
218
 
228
- var p: Rational(u128) = .{ .p = 0, .q = 1 };
219
+ var p: Rational(u256) = .{ .p = 0, .q = 1 };
229
220
  try frontier.append(opts.chance.actions);
230
221
 
231
222
  // zig fmt: off
@@ -240,6 +231,8 @@ pub fn transitions(
240
231
  const f = frontier.items[i];
241
232
  const saved = stats.saved;
242
233
 
234
+ var r: Rational(u256) = .{ .p = 0, .q = 1 };
235
+
243
236
  try debug(writer, f, .{
244
237
  .shape = true,
245
238
  .color = i,
@@ -260,8 +253,8 @@ pub fn transitions(
260
253
  for (Rolls.disable(f.p2, d.p2, p2_slp)) |p2_dis| { a.p2.disable = p2_dis;
261
254
  for (Rolls.attacking(f.p1, d.p1, p1_slp)) |p1_atk| { a.p1.attacking = p1_atk;
262
255
  for (Rolls.attacking(f.p2, d.p2, p2_slp)) |p2_atk| { a.p2.attacking = p2_atk;
263
- for (Rolls.confusion(f.p1, d.p1, p1_atk, p1_slp)) |p1_cfz| { a.p1.confusion = p1_cfz;
264
- for (Rolls.confusion(f.p2, d.p2, p2_atk, p2_slp)) |p2_cfz| { a.p2.confusion = p2_cfz;
256
+ for (Rolls.confusion(f.p1, d.p1, tie, p1_atk, p1_slp)) |p1_cfz| { a.p1.confusion = p1_cfz;
257
+ for (Rolls.confusion(f.p2, d.p2, tie, p2_atk, p2_slp)) |p2_cfz| { a.p2.confusion = p2_cfz;
265
258
  for (Rolls.confused(f.p1, p1_cfz)) |p1_cfzd| { a.p1.confused = p1_cfzd;
266
259
  for (Rolls.confused(f.p2, p2_cfz)) |p2_cfzd| { a.p2.confused = p2_cfzd;
267
260
  for (Rolls.paralyzed(f.p1, p1_cfzd)) |p1_par| { a.p1.paralyzed = p1_par;
@@ -307,12 +300,12 @@ pub fn transitions(
307
300
  const p1_max: u9 = if (p2_dmg.min != p2_min)
308
301
  p1_dmg.min
309
302
  else
310
- try Rolls.coalesce(.P1, @as(u8, @intCast(p1_dmg.min)), summaries, cap);
303
+ Rolls.coalesce(.P1, @as(u8, @intCast(p1_dmg.min)), summaries, cap);
311
304
  const p2_max: u9 =
312
- try Rolls.coalesce(.P2, @as(u8, @intCast(p2_dmg.min)), summaries, cap);
305
+ Rolls.coalesce(.P2, @as(u8, @intCast(p2_dmg.min)), summaries, cap);
313
306
 
314
307
  if (opts.chance.actions.matches(f)) {
315
- if (!map(opts.chance.actions).eql(a)) {
308
+ if (!opts.chance.actions.relax().eql(a)) {
316
309
  if (!summary) {
317
310
  try debug(writer, opts.chance.actions, .{
318
311
  .p1_max = p1_max,
@@ -352,6 +345,8 @@ pub fn transitions(
352
345
  q.reduce();
353
346
  try p.add(q);
354
347
  p.reduce();
348
+ try r.add(q);
349
+ r.reduce();
355
350
 
356
351
  stats.saved += 1;
357
352
 
@@ -360,7 +355,7 @@ pub fn transitions(
360
355
  return error.TestUnexpectedResult;
361
356
  }
362
357
  } else {
363
- if (!matches(opts.chance.actions, i, frontier.items)) {
358
+ if (!opts.chance.actions.matchesAny(frontier.items, i)) {
364
359
  try frontier.append(opts.chance.actions);
365
360
 
366
361
  try debug(writer, opts.chance.actions, .{
@@ -393,14 +388,15 @@ pub fn transitions(
393
388
  }}}}}}}}}}}}}}}}}}}}}}}}}}}}
394
389
 
395
390
  assert(stats.saved > saved);
396
- const old = @hasDecl(std.fmt, "formatFloatDecimal");
397
- if (!old and @TypeOf(writer) != @TypeOf(std.io.null_writer)) {
398
- p.reduce();
399
- try writer.print(
400
- " = {s} ({d:.2}%)\n\n",
401
- .{p, 100 * @as(f128, @floatFromInt(p.p)) / @as(f128, @floatFromInt(p.q))},
402
- );
403
- }
391
+ // TODO: ziglang/zig#22667
392
+ // const old = @hasDecl(std.fmt, "formatFloatDecimal");
393
+ // if (!old and @TypeOf(writer) != @TypeOf(std.io.null_writer)) {
394
+ // try writer.print(
395
+ // " {} ({d:.2}%)\n = ──────────\n {} ({d:.2}%)\n\n",
396
+ // .{r, 100 * @as(f128, @floatFromInt(r.p)) / @as(f128, @floatFromInt(r.q)),
397
+ // p, 100 * @as(f128, @floatFromInt(p.p)) / @as(f128, @floatFromInt(p.q))},
398
+ // );
399
+ // }
404
400
 
405
401
  }
406
402
 
@@ -530,23 +526,6 @@ fn unfix(actual: anytype) data.Battle(data.PRNG) {
530
526
  };
531
527
  }
532
528
 
533
- fn map(actions: Actions) Actions {
534
- if (!pkmn.options.overwrite) return actions;
535
- var a = actions;
536
- if (a.p1.confusion == .overwritten) a.p1.confusion = .continuing;
537
- if (a.p2.confusion == .overwritten) a.p2.confusion = .continuing;
538
- return a;
539
- }
540
-
541
- fn matches(actions: Actions, i: usize, frontier: []Actions) bool {
542
- for (frontier, 0..) |f, j| {
543
- // TODO: is skipping this redundant check worth it?
544
- if (i == j) continue;
545
- if (f.matches(actions)) return true;
546
- }
547
- return false;
548
- }
549
-
550
529
  fn err(comptime fmt: []const u8, v: anytype, seed: ?u64) void {
551
530
  const w = std.io.getStdErr().writer();
552
531
  w.print(fmt, v) catch return;
@@ -694,11 +673,13 @@ pub const Rolls = struct {
694
673
  const CFZ_CONTINUING = [_]Optional(Confusion){.continuing};
695
674
  const CFZ_ENDED = [_]Optional(Confusion){.ended};
696
675
  const CFZ = [_]Optional(Confusion){ .continuing, .ended };
676
+ const CFZ_TIE = [_]Optional(Confusion){ .started, .continuing, .ended };
697
677
 
698
678
  /// FIXME
699
679
  pub fn confusion(
700
680
  action: Action,
701
681
  duration: Duration,
682
+ tie: Optional(Player),
702
683
  sibling: Optional(Observation),
703
684
  parent: Optional(Observation),
704
685
  ) []const Optional(Confusion) {
@@ -712,6 +693,8 @@ pub const Rolls = struct {
712
693
  &CFZ_ENDED
713
694
  else if ((parent == .continuing and parent == .ended) or duration.confusion < 2)
714
695
  &CFZ_CONTINUING
696
+ else if (tie != .None)
697
+ &CFZ_TIE
715
698
  else
716
699
  &CFZ,
717
700
  };
@@ -770,7 +753,7 @@ pub const Rolls = struct {
770
753
 
771
754
  /// Returns the max damage roll which will produce the same damage as `roll`
772
755
  /// given the base damage in `summaries`.
773
- pub fn coalesce(player: Player, roll: u8, summaries: *Summaries, cap: bool) !u8 {
756
+ pub fn coalesce(player: Player, roll: u8, summaries: *Summaries, cap: bool) u8 {
774
757
  if (roll == 0) return roll;
775
758
 
776
759
  const dmg = summaries.get(player.foe()).damage;
@@ -880,12 +863,12 @@ test "Rolls.damage" {
880
863
 
881
864
  test "Rolls.coalesce" {
882
865
  var summaries = Summaries{ .p1 = .{ .damage = .{ .base = 74, .final = 69, .capped = true } } };
883
- try expectEqual(@as(u8, 0), try Rolls.coalesce(.P2, 0, &summaries, false));
884
- try expectEqual(@as(u8, 241), try Rolls.coalesce(.P2, 238, &summaries, false));
885
- try expectEqual(@as(u8, 255), try Rolls.coalesce(.P2, 238, &summaries, true));
866
+ try expectEqual(@as(u8, 0), Rolls.coalesce(.P2, 0, &summaries, false));
867
+ try expectEqual(@as(u8, 241), Rolls.coalesce(.P2, 238, &summaries, false));
868
+ try expectEqual(@as(u8, 255), Rolls.coalesce(.P2, 238, &summaries, true));
886
869
  summaries.p1.damage.final = 74;
887
- try expectEqual(@as(u8, 217), try Rolls.coalesce(.P2, 217, &summaries, false));
888
- try expectEqual(@as(u8, 255), try Rolls.coalesce(.P2, 217, &summaries, true));
870
+ try expectEqual(@as(u8, 217), Rolls.coalesce(.P2, 217, &summaries, false));
871
+ try expectEqual(@as(u8, 255), Rolls.coalesce(.P2, 217, &summaries, true));
889
872
  }
890
873
 
891
874
  test "Rolls.hit" {
@@ -1,30 +1,27 @@
1
- const std = @import("std");
2
-
3
- const assert = std.debug.assert;
4
- const print = std.debug.print;
5
-
6
- const expect = std.testing.expect;
7
- const expectEqual = std.testing.expectEqual;
8
-
9
1
  const DEBUG = @import("../common/debug.zig").print;
2
+
3
+ const array = @import("../common/array.zig");
4
+ const common = @import("../common/data.zig");
5
+ const data = @import("data.zig");
6
+ const optional = @import("../common/optional.zig");
10
7
  const options = @import("../common/options.zig");
11
8
  const rational = @import("../common/rational.zig");
9
+ const std = @import("std");
12
10
  const util = @import("../common/util.zig");
13
11
 
14
- const Array = @import("../common/array.zig").Array;
15
- const Player = @import("../common/data.zig").Player;
16
- const Optional = @import("../common/optional.zig").Optional;
17
-
18
- const data = @import("data.zig");
19
-
12
+ const Array = array.Array;
13
+ const assert = std.debug.assert;
20
14
  const enabled = options.chance;
21
- const showdown = options.showdown;
22
-
23
- const PointerType = util.PointerType;
15
+ const expect = std.testing.expect;
16
+ const expectEqual = std.testing.expectEqual;
24
17
  const isPointerTo = util.isPointerTo;
25
-
26
18
  const Move = data.Move;
27
19
  const MoveSlot = data.MoveSlot;
20
+ const Optional = optional.Optional;
21
+ const Player = common.Player;
22
+ const PointerType = util.PointerType;
23
+ const print = std.debug.print;
24
+ const showdown = options.showdown;
28
25
 
29
26
  const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
30
27
  const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
@@ -75,6 +72,25 @@ pub const Actions = extern struct {
75
72
  return true;
76
73
  }
77
74
 
75
+ /// TODO
76
+ pub fn matchesAny(a: Actions, bs: []Actions, i: usize) bool {
77
+ for (bs, 0..) |b, j| {
78
+ // TODO: is skipping this redundant check worth it?
79
+ if (i == j) continue;
80
+ if (b.matches(a)) return true;
81
+ }
82
+ return false;
83
+ }
84
+
85
+ /// TODO
86
+ pub fn relax(actions: Actions) Actions {
87
+ if (!options.overwrite) return actions;
88
+ var a = actions;
89
+ if (a.p1.confusion == .overwritten) a.p1.confusion = .continuing;
90
+ if (a.p2.confusion == .overwritten) a.p2.confusion = .continuing;
91
+ return a;
92
+ }
93
+
78
94
  pub fn fmt(self: Actions, writer: anytype, shape: bool) !void {
79
95
  try writer.writeAll("<P1 = ");
80
96
  try self.p1.fmt(writer, shape);
@@ -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;
@@ -1,25 +1,19 @@
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");
7
+ const std = @import("std");
8
8
  const util = @import("../common/util.zig");
9
9
 
10
- const data = @import("data.zig");
11
-
12
10
  const assert = std.debug.assert;
13
-
14
11
  const Choice = common.Choice;
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
19