@pkmn/engine 0.1.0-dev.0cabf16e → 0.1.0-dev.0f9e9648

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 (66) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +47 -4
  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 +196 -84
  33. package/package.json +29 -127
  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 +121 -0
  37. package/src/lib/bindings/wasm.zig +59 -0
  38. package/src/lib/common/array.zig +1 -1
  39. package/src/lib/common/optional.zig +1 -1
  40. package/src/lib/common/options.zig +2 -0
  41. package/src/lib/common/protocol.zig +4 -8
  42. package/src/lib/common/rational.zig +222 -147
  43. package/src/lib/common/rng.zig +1 -3
  44. package/src/lib/common/util.zig +17 -2
  45. package/src/lib/gen1/calc.zig +87 -97
  46. package/src/lib/gen1/chance.zig +34 -18
  47. package/src/lib/gen1/data/moves.zig +2 -4
  48. package/src/lib/gen1/data/species.zig +1 -3
  49. package/src/lib/gen1/data/types.zig +1 -2
  50. package/src/lib/gen1/data.zig +7 -11
  51. package/src/lib/gen1/helpers.zig +4 -11
  52. package/src/lib/gen1/mechanics.zig +66 -50
  53. package/src/lib/gen2/calc.zig +10 -18
  54. package/src/lib/gen2/data/items.zig +1 -3
  55. package/src/lib/gen2/data/moves.zig +2 -4
  56. package/src/lib/gen2/data/species.zig +1 -3
  57. package/src/lib/gen2/data/types.zig +1 -2
  58. package/src/lib/gen2/data.zig +11 -15
  59. package/src/lib/gen2/generated.zig +18 -23
  60. package/src/lib/gen2/helpers.zig +5 -12
  61. package/src/lib/gen2/mechanics.zig +41 -38
  62. package/src/lib/node.zig +3 -116
  63. package/src/lib/pkmn.zig +7 -2
  64. package/src/lib/wasm.zig +13 -9
  65. package/src/tools/display/dom.ts +5 -8
  66. 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 = 49;
185
+ pub const MAX_FRONTIER = 81;
195
186
 
196
187
  pub fn transitions(
197
188
  battle: anytype,
@@ -210,11 +201,11 @@ pub fn transitions(
210
201
  var frontier = std.ArrayList(Actions).init(allocator);
211
202
  defer frontier.deinit();
212
203
 
213
- const durations = options.durations;
204
+ const d = options.durations;
214
205
 
215
206
  var opts = pkmn.battle.options(
216
207
  protocol.NULL,
217
- Chance(Rational(u128)){ .probability = .{}, .durations = durations },
208
+ Chance(Rational(u128)){ .probability = .{}, .durations = d },
218
209
  Calc{},
219
210
  );
220
211
 
@@ -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,
@@ -254,20 +247,20 @@ pub fn transitions(
254
247
  };
255
248
 
256
249
  for (Rolls.speedTie(f.p1)) |tie| { a.p1.speed_tie = tie; a.p2.speed_tie = tie;
257
- for (Rolls.sleep(f.p1, durations.p1)) |p1_slp| { a.p1.sleep = p1_slp;
258
- for (Rolls.sleep(f.p2, durations.p2)) |p2_slp| { a.p2.sleep = p2_slp;
259
- for (Rolls.disable(f.p1, durations.p1, p1_slp)) |p1_dis| { a.p1.disable = p1_dis;
260
- for (Rolls.disable(f.p2, durations.p2, p2_slp)) |p2_dis| { a.p2.disable = p2_dis;
261
- for (Rolls.attacking(f.p1, durations.p1)) |p1_atk| { a.p1.attacking = p1_atk;
262
- for (Rolls.attacking(f.p2, durations.p2)) |p2_atk| { a.p2.attacking = p2_atk;
263
- for (Rolls.confusion(f.p1, durations.p1, p1_atk, p1_slp)) |p1_cfz| { a.p1.confusion = p1_cfz;
264
- for (Rolls.confusion(f.p2, durations.p2, p2_atk, p2_slp)) |p2_cfz| { a.p2.confusion = p2_cfz;
250
+ for (Rolls.sleep(f.p1, d.p1)) |p1_slp| { a.p1.sleep = p1_slp;
251
+ for (Rolls.sleep(f.p2, d.p2)) |p2_slp| { a.p2.sleep = p2_slp;
252
+ for (Rolls.disable(f.p1, d.p1, p1_slp)) |p1_dis| { a.p1.disable = p1_dis;
253
+ for (Rolls.disable(f.p2, d.p2, p2_slp)) |p2_dis| { a.p2.disable = p2_dis;
254
+ for (Rolls.attacking(f.p1, d.p1, p1_slp)) |p1_atk| { a.p1.attacking = p1_atk;
255
+ for (Rolls.attacking(f.p2, d.p2, p2_slp)) |p2_atk| { a.p2.attacking = p2_atk;
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;
268
261
  for (Rolls.paralyzed(f.p2, p2_cfzd)) |p2_par| { a.p2.paralyzed = p2_par;
269
- for (Rolls.binding(f.p1, durations.p1, p1_par)) |p1_bind| { a.p1.binding = p1_bind;
270
- for (Rolls.binding(f.p2, durations.p2, p2_par)) |p2_bind| { a.p2.binding = p2_bind;
262
+ for (Rolls.binding(f.p1, d.p1, p1_par)) |p1_bind| { a.p1.binding = p1_bind;
263
+ for (Rolls.binding(f.p2, d.p2, p2_par)) |p2_bind| { a.p2.binding = p2_bind;
271
264
  for (Rolls.hit(f.p1, p1_par)) |p1_hit| { a.p1.hit = p1_hit;
272
265
  for (Rolls.hit(f.p2, p2_par)) |p2_hit| { a.p2.hit = p2_hit;
273
266
  for (Rolls.psywave(f.p1, p1, p1_hit)) |p1_psywave| { a.p1.psywave = p1_psywave;
@@ -295,7 +288,7 @@ pub fn transitions(
295
288
 
296
289
  opts.calc.overrides = a;
297
290
  opts.calc.summaries = .{};
298
- opts.chance = .{ .probability = .{}, .durations = durations };
291
+ opts.chance = .{ .probability = .{}, .durations = d };
299
292
  const q = &opts.chance.probability;
300
293
 
301
294
  b = battle;
@@ -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,
@@ -346,10 +339,15 @@ pub fn transitions(
346
339
  }
347
340
  }
348
341
  }
349
-
350
342
  if (p1_max != p1_min) try q.update(p1_max - p1_min + 1, 1);
351
343
  if (p2_max != p2_dmg.min) try q.update(p2_max - p2_dmg.min + 1, 1);
344
+
345
+ q.reduce();
352
346
  try p.add(q);
347
+ p.reduce();
348
+ try r.add(q);
349
+ r.reduce();
350
+
353
351
  stats.saved += 1;
354
352
 
355
353
  if (p.q < p.p) {
@@ -357,7 +355,7 @@ pub fn transitions(
357
355
  return error.TestUnexpectedResult;
358
356
  }
359
357
  } else {
360
- if (!matches(opts.chance.actions, i, frontier.items)) {
358
+ if (!opts.chance.actions.matchesAny(frontier.items, i)) {
361
359
  try frontier.append(opts.chance.actions);
362
360
 
363
361
  try debug(writer, opts.chance.actions, .{
@@ -390,14 +388,15 @@ pub fn transitions(
390
388
  }}}}}}}}}}}}}}}}}}}}}}}}}}}}
391
389
 
392
390
  assert(stats.saved > saved);
393
- const old = @hasDecl(std.fmt, "formatFloatDecimal");
394
- if (!old and @TypeOf(writer) != @TypeOf(std.io.null_writer)) {
395
- p.reduce();
396
- try writer.print(
397
- " = {s} ({d:.2}%)\n\n",
398
- .{p, 100 * @as(f128, @floatFromInt(p.p)) / @as(f128, @floatFromInt(p.q))},
399
- );
400
- }
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
+ // }
401
400
 
402
401
  }
403
402
 
@@ -527,23 +526,6 @@ fn unfix(actual: anytype) data.Battle(data.PRNG) {
527
526
  };
528
527
  }
529
528
 
530
- fn map(actions: Actions) Actions {
531
- if (!pkmn.options.overwrite) return actions;
532
- var a = actions;
533
- if (a.p1.confusion == .overwritten) a.p1.confusion = .continuing;
534
- if (a.p2.confusion == .overwritten) a.p2.confusion = .continuing;
535
- return a;
536
- }
537
-
538
- fn matches(actions: Actions, i: usize, frontier: []Actions) bool {
539
- for (frontier, 0..) |f, j| {
540
- // TODO: is skipping this redundant check worth it?
541
- if (i == j) continue;
542
- if (f.matches(actions)) return true;
543
- }
544
- return false;
545
- }
546
-
547
529
  fn err(comptime fmt: []const u8, v: anytype, seed: ?u64) void {
548
530
  const w = std.io.getStdErr().writer();
549
531
  w.print(fmt, v) catch return;
@@ -667,49 +649,57 @@ pub const Rolls = struct {
667
649
  };
668
650
  }
669
651
 
652
+ /// FIXME
653
+ pub fn attacking(
654
+ action: Action,
655
+ duration: Duration,
656
+ parent: Optional(Observation),
657
+ ) []const Optional(Observation) {
658
+ return switch (action.attacking) {
659
+ .None => &OBS_NONE,
660
+ .started => &OBS_STARTED,
661
+ else => if (duration.attacking >= 3)
662
+ &OBS_ENDED
663
+ else if ((parent == .continuing and parent == .ended) or duration.attacking < 2)
664
+ &OBS_CONTINUING
665
+ else
666
+ &OBS,
667
+ };
668
+ }
669
+
670
670
  const CFZ_NONE = [_]Optional(Confusion){.None};
671
671
  const CFZ_STARTED = [_]Optional(Confusion){.started};
672
672
  const CFZ_OVERWRITTEN = [_]Optional(Confusion){ .started, .overwritten };
673
673
  const CFZ_CONTINUING = [_]Optional(Confusion){.continuing};
674
674
  const CFZ_ENDED = [_]Optional(Confusion){.ended};
675
675
  const CFZ = [_]Optional(Confusion){ .continuing, .ended };
676
+ const CFZ_TIE = [_]Optional(Confusion){ .started, .continuing, .ended };
676
677
 
677
678
  /// FIXME
678
679
  pub fn confusion(
679
680
  action: Action,
680
681
  duration: Duration,
682
+ tie: Optional(Player),
681
683
  sibling: Optional(Observation),
682
684
  parent: Optional(Observation),
683
685
  ) []const Optional(Confusion) {
684
686
  return switch (action.confusion) {
685
687
  .None => &CFZ_NONE,
686
- .started => if (sibling == .ended)
688
+ .started => if (pkmn.options.overwrite and sibling == .ended and duration.confusion < 5)
687
689
  &CFZ_OVERWRITTEN
688
690
  else
689
691
  &CFZ_STARTED,
690
692
  else => if (duration.confusion >= 5)
691
693
  &CFZ_ENDED
692
- else if ((parent != .None and parent != .started) or duration.confusion < 2)
694
+ else if ((parent == .continuing and parent == .ended) or duration.confusion < 2)
693
695
  &CFZ_CONTINUING
696
+ else if (tie != .None)
697
+ &CFZ_TIE
694
698
  else
695
699
  &CFZ,
696
700
  };
697
701
  }
698
702
 
699
- /// FIXME
700
- pub fn attacking(action: Action, duration: Duration) []const Optional(Observation) {
701
- return switch (action.attacking) {
702
- .None => &OBS_NONE,
703
- .started => &OBS_STARTED,
704
- else => if (duration.attacking >= 3)
705
- &OBS_ENDED
706
- else if (duration.attacking < 2)
707
- &OBS_CONTINUING
708
- else
709
- &OBS,
710
- };
711
- }
712
-
713
703
  /// Returns a slice with a range of values for binding given the `action`, observed `durations`,
714
704
  /// and the state of the `parent` (whether the player's Pokémon was fully paralyzed).
715
705
  pub fn binding(
@@ -763,7 +753,7 @@ pub const Rolls = struct {
763
753
 
764
754
  /// Returns the max damage roll which will produce the same damage as `roll`
765
755
  /// given the base damage in `summaries`.
766
- 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 {
767
757
  if (roll == 0) return roll;
768
758
 
769
759
  const dmg = summaries.get(player.foe()).damage;
@@ -873,12 +863,12 @@ test "Rolls.damage" {
873
863
 
874
864
  test "Rolls.coalesce" {
875
865
  var summaries = Summaries{ .p1 = .{ .damage = .{ .base = 74, .final = 69, .capped = true } } };
876
- try expectEqual(@as(u8, 0), try Rolls.coalesce(.P2, 0, &summaries, false));
877
- try expectEqual(@as(u8, 241), try Rolls.coalesce(.P2, 238, &summaries, false));
878
- 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));
879
869
  summaries.p1.damage.final = 74;
880
- try expectEqual(@as(u8, 217), try Rolls.coalesce(.P2, 217, &summaries, false));
881
- 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));
882
872
  }
883
873
 
884
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;
@@ -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
 
@@ -267,7 +261,6 @@ fn durations(m: Move) bool {
267
261
  // Any moves that have effects that result in duration tracking with -Dchance
268
262
  return switch (Move.get(m).effect) {
269
263
  .Haze,
270
- .Thrashing,
271
264
  .Metronome,
272
265
  => true,
273
266
  else => false,