@pkmn/engine 0.1.0-dev.3393edb3 → 0.1.0-dev.36b5d56b

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 (42) hide show
  1. package/build/pkg/addon/browser.d.ts +1 -1
  2. package/build/pkg/addon/browser.js +2 -1
  3. package/build/pkg/addon/browser.js.map +1 -1
  4. package/build/pkg/addon/node.js +2 -1
  5. package/build/pkg/addon/node.js.map +1 -1
  6. package/build/pkg/addon/wasm.d.ts +2 -0
  7. package/build/pkg/addon/wasm.js +21 -0
  8. package/build/pkg/addon/wasm.js.map +1 -0
  9. package/build/pkg/addon.d.ts +20 -0
  10. package/build/pkg/addon.js.map +1 -1
  11. package/build/tools/debug.js +1 -1
  12. package/build/tools/debug.js.map +1 -1
  13. package/build/tools/display/index.js +17 -8
  14. package/build/tools/display/index.js.map +1 -1
  15. package/build.zig +89 -68
  16. package/package.json +19 -16
  17. package/src/lib/common/debug.zig +9 -4
  18. package/src/lib/common/options.zig +2 -0
  19. package/src/lib/common/protocol.zig +4 -8
  20. package/src/lib/common/rational.zig +7 -5
  21. package/src/lib/common/rng.zig +1 -3
  22. package/src/lib/gen1/calc.zig +82 -88
  23. package/src/lib/gen1/chance.zig +34 -18
  24. package/src/lib/gen1/data/moves.zig +2 -4
  25. package/src/lib/gen1/data/species.zig +1 -3
  26. package/src/lib/gen1/data/types.zig +1 -2
  27. package/src/lib/gen1/data.zig +7 -11
  28. package/src/lib/gen1/helpers.zig +4 -11
  29. package/src/lib/gen1/mechanics.zig +68 -56
  30. package/src/lib/gen2/calc.zig +9 -17
  31. package/src/lib/gen2/data/items.zig +1 -3
  32. package/src/lib/gen2/data/moves.zig +2 -4
  33. package/src/lib/gen2/data/species.zig +1 -3
  34. package/src/lib/gen2/data/types.zig +1 -2
  35. package/src/lib/gen2/data.zig +11 -15
  36. package/src/lib/gen2/generated.zig +18 -23
  37. package/src/lib/gen2/helpers.zig +5 -12
  38. package/src/lib/gen2/mechanics.zig +22 -30
  39. package/src/lib/node.zig +2 -4
  40. package/src/lib/pkmn.zig +4 -0
  41. package/src/lib/wasm.zig +1 -2
  42. package/src/tools/display/ui.css +8 -5
@@ -1,36 +1,28 @@
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 pkmn = @import("../pkmn.zig");
7
7
  const protocol = @import("../common/protocol.zig");
8
8
  const rng = @import("../common/rng.zig");
9
-
10
- const data = @import("data.zig");
11
- const chance = @import("chance.zig");
9
+ const std = @import("std");
12
10
 
13
11
  const assert = std.debug.assert;
14
-
15
- const expectEqual = std.testing.expectEqual;
16
-
17
- const showdown = pkmn.options.showdown;
18
-
19
- const Choice = common.Choice;
20
- const ID = common.ID;
21
- const Player = common.Player;
22
- const Result = common.Result;
23
-
24
12
  const Boost = protocol.Boost;
13
+ const Choice = common.Choice;
25
14
  const Damage = protocol.Damage;
15
+ const Effectiveness = data.Effectiveness;
16
+ const expectEqual = std.testing.expectEqual;
26
17
  const Fail = protocol.Fail;
27
- const Heal = protocol.Heal;
28
-
29
18
  const Gen12 = rng.Gen12;
30
-
31
- const Effectiveness = data.Effectiveness;
19
+ const Heal = protocol.Heal;
20
+ const ID = common.ID;
32
21
  const Move = data.Move;
33
22
  const MoveSlot = data.MoveSlot;
23
+ const Player = common.Player;
24
+ const Result = common.Result;
25
+ const showdown = pkmn.options.showdown;
34
26
  const Side = data.Side;
35
27
  const Species = data.Species;
36
28
  const Stats = data.Stats;
@@ -173,7 +165,10 @@ fn selectMove(
173
165
  if (foe_choice.type == .Switch) {
174
166
  const last = side.active.move(battle.lastMove(player).index);
175
167
  if (last.id == .Metronome) side.last_selected_move = last.id;
176
- if (last.id == .MirrorMove) return Result.Error;
168
+ if (last.id == .MirrorMove) {
169
+ if (!pkmn.options.mod) return Result.Error;
170
+ side.last_selected_move = last.id;
171
+ }
177
172
  }
178
173
  }
179
174
  return null;
@@ -341,7 +336,6 @@ fn doTurn(
341
336
  player_choice,
342
337
  player_rewrap,
343
338
  player_skip,
344
- true,
345
339
  &residual,
346
340
  options,
347
341
  )) |r| return r;
@@ -364,7 +358,6 @@ fn doTurn(
364
358
  foe_choice,
365
359
  foe_rewrap,
366
360
  foe_skip,
367
- false,
368
361
  &residual,
369
362
  options,
370
363
  )) |r| return r;
@@ -392,7 +385,6 @@ fn executeMove(
392
385
  choice: Choice,
393
386
  rewrap: bool,
394
387
  skip: bool,
395
- first: bool,
396
388
  residual: *bool,
397
389
  options: anytype,
398
390
  ) !?Result {
@@ -427,7 +419,7 @@ fn executeMove(
427
419
  mslot = @intCast(battle.lastMove(player).index);
428
420
  const stored = side.stored();
429
421
  // GLITCH: Struggle bypass PP underflow via Hyper Beam / Trapping-switch auto selection
430
- auto = isForced(&side.active) or
422
+ auto = pkmn.options.mod or isForced(&side.active) or
431
423
  side.active.volatiles.Binding or side.active.volatiles.Bide or
432
424
  side.last_selected_move == .HyperBeam or
433
425
  Status.is(stored.status, .FRZ) or Status.is(stored.status, .SLP);
@@ -452,7 +444,7 @@ fn executeMove(
452
444
 
453
445
  var skip_can = false;
454
446
  var skip_pp = false;
455
- switch (try beforeMove(battle, player, skip, first, residual, options)) {
447
+ switch (try beforeMove(battle, player, skip, residual, options)) {
456
448
  .done => return null,
457
449
  .skip_can => skip_can = true,
458
450
  .skip_pp => skip_pp = true,
@@ -460,6 +452,25 @@ fn executeMove(
460
452
  .err => return @as(?Result, Result.Error),
461
453
  }
462
454
 
455
+ // Pokémon Showdown incorrectly implements PP deduction when handling the Hyper Beam automatic
456
+ // selection glitch - if the move was proced due to Metronome / Mirror Move it either subtracts
457
+ // from the Hyper Beam slot if present or skips PP deduction entirely...
458
+ if (showdown and !skip_pp and side.last_selected_move == .HyperBeam and
459
+ side.last_selected_move != side.active.move(battle.lastMove(player).index).id)
460
+ {
461
+ assert(mslot == 1);
462
+ const has_beam = has_beam: {
463
+ for (side.active.moves, 0..) |m, i| {
464
+ if (m.id == .HyperBeam) {
465
+ mslot = @intCast(i + 1);
466
+ break :has_beam true;
467
+ }
468
+ }
469
+ break :has_beam false;
470
+ };
471
+ if (!has_beam) skip_pp = true;
472
+ }
473
+
463
474
  const can = skip_can or
464
475
  try canMove(battle, player, mslot, auto, skip_pp, .None, residual, options);
465
476
  if (!can) return null;
@@ -473,7 +484,6 @@ fn beforeMove(
473
484
  battle: anytype,
474
485
  player: Player,
475
486
  skip: bool,
476
- first: bool,
477
487
  residual: *bool,
478
488
  options: anytype,
479
489
  ) !BeforeMove {
@@ -558,24 +568,17 @@ fn beforeMove(
558
568
  // This can only happen if a Pokémon started the battle frozen/sleeping and was thawed/woken
559
569
  // before the side had a selected a move - we simply need to assume this leads to a desync
560
570
  if (side.last_selected_move == .None) {
561
- assert(!showdown);
571
+ assert(!pkmn.options.mod);
562
572
  return .err;
563
573
  }
564
574
 
565
575
  if (volatiles.Confusion) {
566
576
  assert(volatiles.confusion > 0);
567
577
  if (options.calc.overridden(player, .confusion)) |obs| switch (obs) {
568
- .started => {
569
- if (!first or (options.calc.overridden(player, .confused) orelse .None) != .None) {
570
- volatiles.confusion -= 1;
571
- } else {
572
- volatiles.confusion = 0;
573
- }
574
- },
578
+ .started, .ended => volatiles.confusion = 0,
575
579
  .continuing => if (volatiles.confusion > 1) {
576
580
  volatiles.confusion -= 1;
577
581
  },
578
- .ended => volatiles.confusion = 0,
579
582
  .overwritten => {},
580
583
  else => unreachable,
581
584
  } else {
@@ -703,7 +706,7 @@ fn beforeMove(
703
706
  try options.chance.attacking(player, if (volatiles.attacks == 0) .ended else .continuing);
704
707
 
705
708
  if (volatiles.attacks == 0) {
706
- const overwritten = pkmn.options.overwrite and volatiles.Confusion;
709
+ const overwritten = volatiles.Confusion;
707
710
 
708
711
  volatiles.Thrashing = false;
709
712
  volatiles.Confusion = true;
@@ -714,7 +717,11 @@ fn beforeMove(
714
717
  // can be expected to recognize this pattern and pass the information only to the
715
718
  // correct player)
716
719
  try log.start(.{ battle.active(player), .ConfusionSilent });
717
- options.chance.observe(.confusion, player, if (overwritten) .overwritten else .started);
720
+ options.chance.observe(.confusion, player, if (overwritten)
721
+ if (pkmn.options.overwrite) .overwritten else .continuing
722
+ else
723
+ .started);
724
+ if (!overwritten) options.calc.confusion(player);
718
725
  }
719
726
 
720
727
  // This shouldn't actually set last_used_move, but Pokémon Showdown sets last
@@ -780,9 +787,14 @@ fn canMove(
780
787
 
781
788
  if (move.effect == .Thrashing) {
782
789
  Effects.thrashing(battle, player, options);
783
- } else if (!showdown and move.effect == .Binding) {
784
- // Pokémon Showdown handles this after hit/miss checks and damage calculation
785
- try Effects.binding(battle, player, false, options);
790
+ } else if (move.effect == .Binding) {
791
+ // Pokémon Showdown handles this after hit/miss checks and damage calculation, though clears
792
+ // Recharging in onTryMove (required for the Hyper Beam automatic selection glitch)
793
+ if (showdown) {
794
+ battle.foe(player).active.volatiles.Recharging = false;
795
+ } else {
796
+ try Effects.binding(battle, player, false, options);
797
+ }
786
798
  }
787
799
 
788
800
  return true;
@@ -1136,7 +1148,7 @@ fn calcDamage(
1136
1148
  if ((!showdown or !cfz) and (atk > 255 or def > 255)) {
1137
1149
  atk = @max((atk / 4) & 255, 1);
1138
1150
  // GLITCH: not adjusted to be a min of 1 on cartridge (can lead to division-by-zero freeze)
1139
- def = @max((def / 4) & 255, if (showdown) 1 else 0);
1151
+ def = @max((def / 4) & 255, if (pkmn.options.mod) 1 else 0);
1140
1152
  }
1141
1153
 
1142
1154
  const lvl: u32 = side.stored().level * @as(u2, if (crit) 2 else 1);
@@ -1157,7 +1169,7 @@ fn calcDamage(
1157
1169
  // encountered so we need to make sure that in the event of a miss we commit the status of the
1158
1170
  // crit roll. The alternative to doing this extra work is to *always* commit the crit roll but
1159
1171
  // that results in counter intuitive probabilities in the common case
1160
- if (pkmn.options.chance and !showdown) {
1172
+ if (pkmn.options.chance and !pkmn.options.mod) {
1161
1173
  atk = attack(side, !crit, special);
1162
1174
  def = defense(target, !crit, special, false);
1163
1175
  if ((atk > 255 or def > 255) and (def / 4) & 255 == 0) options.chance.glitch();
@@ -1242,13 +1254,13 @@ fn specialDamage(battle: anytype, player: Player, move: Move.Data, options: anyt
1242
1254
  .Psywave => power: {
1243
1255
  const max: u8 = @intCast(@as(u16, side.stored().level) * 3 / 2);
1244
1256
  // GLITCH: Psywave infinite glitch loop
1245
- if (!showdown and max <= 1) return Result.Error;
1257
+ if (!pkmn.options.mod and max <= 1) return Result.Error;
1246
1258
  break :power try Rolls.psywave(battle, player, max, options);
1247
1259
  },
1248
1260
  else => unreachable,
1249
1261
  };
1250
1262
 
1251
- if (battle.last_damage == 0) return if (showdown) null else Result.Error;
1263
+ if (battle.last_damage == 0) return if (pkmn.options.mod) null else Result.Error;
1252
1264
 
1253
1265
  const sub = showdown and foe.active.volatiles.Substitute;
1254
1266
  _ = try applyDamage(battle, player.foe(), player.foe(), .None, options);
@@ -1285,7 +1297,7 @@ fn counterDamage(battle: anytype, player: Player, move: Move.Data, options: anyt
1285
1297
 
1286
1298
  if (!used or !selected) {
1287
1299
  // GLITCH: Counter desync (covered by Desync Clause Mod on Pokémon Showdown)
1288
- if (!showdown) return Result.Error;
1300
+ if (!pkmn.options.mod) return Result.Error;
1289
1301
  try options.log.fail(.{ battle.active(player), .None });
1290
1302
  return null;
1291
1303
  }
@@ -1532,7 +1544,7 @@ fn faint(battle: anytype, player: Player, done: bool, cap: bool, options: anytyp
1532
1544
  assert(!foe_volatiles.MultiHit);
1533
1545
  if (foe_volatiles.Bide) {
1534
1546
  assert(!foe_volatiles.Thrashing and !foe_volatiles.Rage);
1535
- foe_volatiles.state = if (showdown) 0 else foe_volatiles.state & 255;
1547
+ foe_volatiles.state = if (pkmn.options.mod) 0 else foe_volatiles.state & 255;
1536
1548
  if (foe_volatiles.state != 0) return Result.Error;
1537
1549
  }
1538
1550
 
@@ -1623,12 +1635,12 @@ fn endTurn(battle: anytype, options: anytype) @TypeOf(options.log).Error!Result
1623
1635
 
1624
1636
  battle.turn += 1;
1625
1637
 
1626
- if (showdown and pkmn.options.ebc and checkEBC(battle)) {
1638
+ if (pkmn.options.mod and pkmn.options.ebc and checkEBC(battle)) {
1627
1639
  try options.log.tie(.{});
1628
1640
  return Result.Tie;
1629
1641
  }
1630
1642
 
1631
- if (showdown and battle.turn >= 1000) {
1643
+ if (pkmn.options.mod and battle.turn >= 1000) {
1632
1644
  try options.log.tie(.{});
1633
1645
  return Result.Tie;
1634
1646
  } else if (battle.turn >= 65535) {
@@ -1877,6 +1889,7 @@ pub const Effects = struct {
1877
1889
 
1878
1890
  foe.active.volatiles.confusion = Rolls.confusionDuration(battle, player, options);
1879
1891
  options.chance.observe(.confusion, player.foe(), .started);
1892
+ options.calc.confusion(player.foe());
1880
1893
 
1881
1894
  try options.log.start(.{ battle.active(player.foe()), .Confusion });
1882
1895
  }
@@ -1922,12 +1935,11 @@ pub const Effects = struct {
1922
1935
 
1923
1936
  // Technically this is still considered simply a "miss" on the cartridge,
1924
1937
  // but diverging from Pokémon Showdown here would mostly just be pedantic
1925
- if (n == 0) {
1938
+ if (n == 0 or (pkmn.options.mod and err)) {
1926
1939
  try options.log.fail(.{ foe_ident, .None });
1927
1940
  return null;
1928
1941
  } else if (err) {
1929
1942
  // GLITCH: Transform + Mirror Move / Metronome PP softlock
1930
- assert(!showdown);
1931
1943
  return Result.Error;
1932
1944
  }
1933
1945
 
@@ -2005,7 +2017,7 @@ pub const Effects = struct {
2005
2017
  if (foe.active.types.includes(move.type)) return;
2006
2018
  if (!try Rolls.secondaryChance(battle, player, true, options)) return;
2007
2019
  // Freeze Clause Mod
2008
- if (showdown) for (foe.pokemon) |p| if (Status.is(p.status, .FRZ)) return;
2020
+ if (pkmn.options.mod) for (foe.pokemon) |p| if (Status.is(p.status, .FRZ)) return;
2009
2021
 
2010
2022
  foe_stored.status = Status.init(.FRZ);
2011
2023
  // GLITCH: Hyper Beam recharging status is not cleared
@@ -2346,7 +2358,7 @@ pub const Effects = struct {
2346
2358
  }
2347
2359
 
2348
2360
  // Sleep Clause Mod
2349
- if (showdown) {
2361
+ if (pkmn.options.mod) {
2350
2362
  for (foe.pokemon) |p| {
2351
2363
  if (Status.is(p.status, .SLP) and !Status.is(p.status, .EXT)) return;
2352
2364
  }
@@ -2452,7 +2464,7 @@ pub const Effects = struct {
2452
2464
  if (side.active.volatiles.Binding) return;
2453
2465
  side.active.volatiles.Binding = true;
2454
2466
  // GLITCH: Hyper Beam automatic selection glitch if Recharging gets cleared on miss
2455
- // (Pokémon Showdown unitentionally patches this glitch, preventing automatic selection)
2467
+ // (Pokémon Showdown clears Recharging in onTryMove instead)
2456
2468
  if (!showdown) {
2457
2469
  foe.active.volatiles.Recharging = false;
2458
2470
  } else if (foe.stored().hp == 0) return if (!rewrap) battle.rng.advance(1);
@@ -3218,7 +3230,7 @@ pub fn choices(battle: anytype, player: Player, request: Choice.Type, out: []Cho
3218
3230
  // Struggle (Pokémon Showdown would use 'move 1' here)
3219
3231
  if (n == before) {
3220
3232
  // GLITCH: Transform + Mirror Move / Metronome PP softlock
3221
- if (!showdown) {
3233
+ if (!pkmn.options.mod) {
3222
3234
  while (slot <= 4) : (slot += 1) {
3223
3235
  if (active.moves[slot - 1].pp != 0) return n;
3224
3236
  }
@@ -1,27 +1,19 @@
1
- const std = @import("std");
2
-
3
- const pkmn = @import("../pkmn.zig");
4
-
1
+ const chance = @import("chance.zig");
5
2
  const common = @import("../common/data.zig");
6
- const util = @import("../common/util.zig");
7
-
8
3
  const Optional = @import("../common/optional.zig").Optional;
4
+ const pkmn = @import("../pkmn.zig");
5
+ const std = @import("std");
6
+ const util = @import("../common/util.zig");
9
7
 
10
- const chance = @import("chance.zig");
11
-
8
+ const Action = chance.Action;
9
+ const Actions = chance.Actions;
12
10
  const assert = std.debug.assert;
13
-
11
+ const Criticals = chance.Criticals;
12
+ const Damages = chance.Damages;
14
13
  const enabled = pkmn.options.calc;
15
-
14
+ const isPointerTo = util.isPointerTo;
16
15
  const Player = common.Player;
17
-
18
16
  const PointerType = util.PointerType;
19
- const isPointerTo = util.isPointerTo;
20
-
21
- const Actions = chance.Actions;
22
- const Action = chance.Action;
23
- const Criticals = chance.Criticals;
24
- const Damages = chance.Damages;
25
17
 
26
18
  const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
27
19
  const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
@@ -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 data = @import("../../gen2/data.zig");
4
+ const std = @import("std");
6
5
 
7
6
  const assert = std.debug.assert;
8
-
9
7
  const Type = data.Type;
10
8
 
11
9
  /// Representation of a held item in Generation II Pokémon.
@@ -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 gen2 = @import("../../gen2/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 = gen2.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 gen2 = @import("../../gen2/data.zig");
4
+ const std = @import("std");
6
5
 
7
6
  const assert = std.debug.assert;
8
-
9
7
  const Stats = gen2.Stats;
10
8
  const Types = gen2.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,24 +1,20 @@
1
- const std = @import("std");
2
- const builtin = @import("builtin");
3
-
4
- const pkmn = @import("../pkmn.zig");
5
-
6
- const data = @import("../common/data.zig");
7
1
  const DEBUG = @import("../common/debug.zig").print;
8
- const protocol = @import("../common/protocol.zig");
9
- const rng = @import("../common/rng.zig");
10
- const util = @import("../common/util.zig");
11
2
 
3
+ const builtin = @import("builtin");
4
+ const calc = @import("calc.zig");
5
+ const chance = @import("chance.zig");
6
+ const data = @import("../common/data.zig");
7
+ const gen1 = @import("../gen1/data.zig");
12
8
  const items = @import("data/items.zig");
9
+ const mechanics = @import("mechanics.zig");
13
10
  const moves = @import("data/moves.zig");
11
+ const pkmn = @import("../pkmn.zig");
12
+ const protocol = @import("../common/protocol.zig");
13
+ const rng = @import("../common/rng.zig");
14
14
  const species = @import("data/species.zig");
15
+ const std = @import("std");
15
16
  const types = @import("data/types.zig");
16
-
17
- const gen1 = @import("../gen1/data.zig");
18
-
19
- const calc = @import("calc.zig");
20
- const chance = @import("chance.zig");
21
- const mechanics = @import("mechanics.zig");
17
+ const util = @import("../common/util.zig");
22
18
 
23
19
  const assert = std.debug.assert;
24
20
  const expectEqual = std.testing.expectEqual;
@@ -1,37 +1,32 @@
1
1
  //! Code generated by `tools/generate` - manual edits will be overwritten.
2
2
 
3
- const std = @import("std");
4
-
5
3
  const common = @import("../common/data.zig");
6
-
7
4
  const data = @import("data.zig");
8
5
  const mechanics = @import("mechanics.zig");
6
+ const std = @import("std");
9
7
 
10
- const Player = common.Player;
11
- const Result = common.Result;
12
-
13
- const Effectiveness = data.Effectiveness;
14
- const Move = data.Move;
15
-
16
- const Effects = mechanics.Effects;
17
- const State = mechanics.State;
18
-
19
- const canMove = mechanics.canMove;
8
+ const adjustDamage = mechanics.adjustDamage;
9
+ const afterMove = mechanics.afterMove;
10
+ const applyDamage = mechanics.applyDamage;
11
+ const buildRage = mechanics.buildRage;
12
+ const calcDamage = mechanics.calcDamage;
20
13
  const canCharge = mechanics.canCharge;
14
+ const canMove = mechanics.canMove;
15
+ const checkCriticalHit = mechanics.checkCriticalHit;
16
+ const checkHit = mechanics.checkHit;
21
17
  const decrementPP = mechanics.decrementPP;
18
+ const destinyBond = mechanics.destinyBond;
22
19
  const doMove = mechanics.doMove;
23
- const checkHit = mechanics.checkHit;
24
- const checkCriticalHit = mechanics.checkCriticalHit;
25
- const calcDamage = mechanics.calcDamage;
26
- const adjustDamage = mechanics.adjustDamage;
27
- const randomizeDamage = mechanics.randomizeDamage;
28
- const applyDamage = mechanics.applyDamage;
29
- const reportOutcome = mechanics.reportOutcome;
30
20
  const effectChance = mechanics.effectChance;
31
- const afterMove = mechanics.afterMove;
32
- const buildRage = mechanics.buildRage;
21
+ const Effectiveness = data.Effectiveness;
22
+ const Effects = mechanics.Effects;
33
23
  const kingsRock = mechanics.kingsRock;
34
- const destinyBond = mechanics.destinyBond;
24
+ const Move = data.Move;
25
+ const Player = common.Player;
26
+ const randomizeDamage = mechanics.randomizeDamage;
27
+ const reportOutcome = mechanics.reportOutcome;
28
+ const Result = common.Result;
29
+ const State = mechanics.State;
35
30
 
36
31
  const SECONDARY = true;
37
32
  const KINGS = true;
@@ -1,25 +1,18 @@
1
- const std = @import("std");
2
-
3
1
  const common = @import("../common/data.zig");
2
+ const data = @import("data.zig");
3
+ const gen1 = @import("../gen1/data.zig");
4
4
  const options = @import("../common/options.zig");
5
5
  const rng = @import("../common/rng.zig");
6
-
7
- const gen1 = @import("../gen1/data.zig");
8
-
9
- const data = @import("data.zig");
6
+ const std = @import("std");
10
7
 
11
8
  const assert = std.debug.assert;
12
-
13
9
  const Choice = common.Choice;
14
-
15
- const showdown = options.showdown;
16
-
17
- const PSRNG = rng.PSRNG;
18
-
19
10
  const DVs = data.DVs;
20
11
  const Item = data.Item;
21
12
  const Move = data.Move;
22
13
  const MoveSlot = data.MoveSlot;
14
+ const PSRNG = rng.PSRNG;
15
+ const showdown = options.showdown;
23
16
  const Species = data.Species;
24
17
  const Stats = data.Stats;
25
18
 
@@ -1,44 +1,36 @@
1
- const std = @import("std");
2
-
3
- const pkmn = @import("../pkmn.zig");
4
-
5
- const common = @import("../common/data.zig");
6
1
  const DEBUG = @import("../common/debug.zig").print;
7
- const protocol = @import("../common/protocol.zig");
8
- const rng = @import("../common/rng.zig");
9
2
 
3
+ const common = @import("../common/data.zig");
10
4
  const data = @import("data.zig");
11
5
  const generated = @import("generated.zig");
12
-
13
- const assert = std.debug.assert;
14
-
15
- const expectEqual = std.testing.expectEqual;
16
- const expectEqualSlices = std.testing.expectEqualSlices;
17
- const expectEqualStrings = std.testing.expectEqualStrings;
18
-
19
- const showdown = pkmn.options.showdown;
20
-
21
- const Choice = common.Choice;
22
- const ID = common.ID;
23
- const Player = common.Player;
24
- const Result = common.Result;
6
+ const pkmn = @import("../pkmn.zig");
7
+ const protocol = @import("../common/protocol.zig");
8
+ const rng = @import("../common/rng.zig");
9
+ const std = @import("std");
25
10
 
26
11
  const Activate = protocol.Activate;
12
+ const ActivePokemon = data.ActivePokemon;
13
+ const assert = std.debug.assert;
27
14
  const Boost = protocol.Boost;
15
+ const Boosts = data.Boosts;
16
+ const Choice = common.Choice;
28
17
  const Damage = protocol.Damage;
18
+ const Effectiveness = data.Effectiveness;
29
19
  const End = protocol.End;
20
+ const expectEqual = std.testing.expectEqual;
21
+ const expectEqualSlices = std.testing.expectEqualSlices;
22
+ const expectEqualStrings = std.testing.expectEqualStrings;
30
23
  const Fail = protocol.Fail;
31
- const Heal = protocol.Heal;
32
- const Start = protocol.Start;
33
-
34
24
  const Gen12 = rng.Gen12;
35
-
36
- const ActivePokemon = data.ActivePokemon;
37
- const Boosts = data.Boosts;
38
- const Effectiveness = data.Effectiveness;
25
+ const Heal = protocol.Heal;
26
+ const ID = common.ID;
39
27
  const Item = data.Item;
40
28
  const Move = data.Move;
29
+ const Player = common.Player;
30
+ const Result = common.Result;
31
+ const showdown = pkmn.options.showdown;
41
32
  const Side = data.Side;
33
+ const Start = protocol.Start;
42
34
  const Stats = data.Stats;
43
35
  const Status = data.Status;
44
36
  const TriAttack = data.TriAttack;
@@ -1200,7 +1192,7 @@ fn updateSideCondition(
1200
1192
  fn endTurn(battle: anytype, options: anytype) @TypeOf(options.log).Error!Result {
1201
1193
  battle.turn += 1;
1202
1194
 
1203
- if (showdown and battle.turn >= 1000) {
1195
+ if (pkmn.options.mod and battle.turn >= 1000) {
1204
1196
  try options.log.tie(.{});
1205
1197
  return Result.Tie;
1206
1198
  } else if (battle.turn >= 65535) {
@@ -1706,7 +1698,7 @@ pub const Effects = struct {
1706
1698
  if (!state.proc) return;
1707
1699
  if (foe.conditions.Safeguard) return;
1708
1700
  // Freeze Clause Mod
1709
- if (showdown) for (foe.pokemon) |p| if (Status.is(p.status, .FRZ)) return;
1701
+ if (pkmn.options.mod) for (foe.pokemon) |p| if (Status.is(p.status, .FRZ)) return;
1710
1702
 
1711
1703
  foe_stored.status = Status.init(.FRZ);
1712
1704
  try options.log.status(.{ foe_ident, foe_stored.status, .None });
@@ -2384,7 +2376,7 @@ pub const Effects = struct {
2384
2376
  }
2385
2377
 
2386
2378
  // Sleep Clause Mod
2387
- if (showdown) {
2379
+ if (pkmn.options.mod) {
2388
2380
  for (foe.pokemon) |p| {
2389
2381
  if (Status.is(p.status, .SLP) and !Status.is(p.status, .EXT)) return;
2390
2382
  }
package/src/lib/node.zig CHANGED
@@ -1,8 +1,6 @@
1
- const std = @import("std");
2
-
3
- const pkmn = @import("pkmn.zig");
4
-
5
1
  const js = @import("common/js.zig");
2
+ const pkmn = @import("pkmn.zig");
3
+ const std = @import("std");
6
4
 
7
5
  const assert = std.debug.assert;
8
6
 
package/src/lib/pkmn.zig CHANGED
@@ -96,6 +96,10 @@ pub const gen1 = struct {
96
96
  /// though damage calculator support should additionally be turned off
97
97
  /// entirely via `options.calc`.
98
98
  pub const NULL = @import("gen1/calc.zig").NULL;
99
+ /// TODO
100
+ pub const MAX_FRONTIER = @import("gen1/calc.zig").MAX_FRONTIER;
101
+ /// TODO
102
+ pub const Rolls = @import("gen1/calc.zig").Rolls;
99
103
  };
100
104
  /// Provides helpers for initializing Generation I Pokémon battles.
101
105
  pub const helpers = @import("gen1/helpers.zig");
package/src/lib/wasm.zig CHANGED
@@ -1,6 +1,5 @@
1
- const std = @import("std");
2
-
3
1
  const pkmn = @import("pkmn.zig");
2
+ const std = @import("std");
4
3
 
5
4
  export const SHOWDOWN = pkmn.options.showdown;
6
5
  export const LOG = pkmn.options.log;