@pkmn/engine 0.1.0-dev.5570b5c5 → 0.1.0-dev.565de616

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 (76) hide show
  1. package/README.md +12 -8
  2. package/build/pkg/addon/browser.d.ts +3 -0
  3. package/build/pkg/addon/browser.js +44 -0
  4. package/build/pkg/addon/browser.js.map +1 -0
  5. package/build/pkg/addon/node.d.ts +3 -0
  6. package/build/pkg/addon/node.js +97 -0
  7. package/build/pkg/addon/node.js.map +1 -0
  8. package/build/pkg/addon/wasm.d.ts +2 -0
  9. package/build/pkg/addon/wasm.js +21 -0
  10. package/build/pkg/addon/wasm.js.map +1 -0
  11. package/build/pkg/addon.d.ts +22 -0
  12. package/build/pkg/addon.js +29 -51
  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/data.d.ts +23 -1
  17. package/build/pkg/data.js.map +1 -1
  18. package/build/pkg/gen1.d.ts +10 -13
  19. package/build/pkg/gen1.js +1 -1
  20. package/build/pkg/gen1.js.map +1 -1
  21. package/build/pkg/index.d.ts +53 -12
  22. package/build/pkg/index.js +15 -10
  23. package/build/pkg/index.js.map +1 -1
  24. package/build/pkg/protocol.d.ts +20 -1
  25. package/build/pkg/protocol.js +105 -103
  26. package/build/pkg/protocol.js.map +1 -1
  27. package/build/tools/debug.js +35 -68
  28. package/build/tools/debug.js.map +1 -1
  29. package/build/tools/display/debug.jsx +141 -0
  30. package/build/tools/display/debug.jsx.map +1 -0
  31. package/build/tools/display/index.js +141 -0
  32. package/build/tools/display/index.js.map +1 -0
  33. package/build/tools/display/ui.jsx +349 -0
  34. package/build/tools/display/ui.jsx.map +1 -0
  35. package/build/tools/display/util.js +18 -0
  36. package/build/tools/display/util.js.map +1 -0
  37. package/build.zig +230 -74
  38. package/package.json +51 -31
  39. package/src/bin/install-pkmn-engine +8 -6
  40. package/src/bin/pkmn-debug +1 -1
  41. package/src/lib/common/array.zig +77 -0
  42. package/src/lib/common/data.zig +8 -8
  43. package/src/lib/common/debug.zig +39 -8
  44. package/src/lib/common/js.zig +4 -2
  45. package/src/lib/common/optional.zig +13 -9
  46. package/src/lib/common/options.zig +6 -0
  47. package/src/lib/common/protocol.zig +45 -44
  48. package/src/lib/common/rational.zig +121 -29
  49. package/src/lib/common/rng.zig +5 -7
  50. package/src/lib/common/util.zig +50 -1
  51. package/src/lib/gen1/calc.zig +683 -156
  52. package/src/lib/gen1/chance.zig +415 -291
  53. package/src/lib/gen1/data/moves.zig +2 -4
  54. package/src/lib/gen1/data/species.zig +1 -3
  55. package/src/lib/gen1/data/types.zig +1 -2
  56. package/src/lib/gen1/data.zig +38 -41
  57. package/src/lib/gen1/helpers.zig +92 -548
  58. package/src/lib/gen1/mechanics.zig +325 -235
  59. package/src/lib/gen2/calc.zig +37 -27
  60. package/src/lib/gen2/chance.zig +90 -503
  61. package/src/lib/gen2/data/items.zig +1 -3
  62. package/src/lib/gen2/data/moves.zig +2 -4
  63. package/src/lib/gen2/data/species.zig +1 -3
  64. package/src/lib/gen2/data/types.zig +1 -2
  65. package/src/lib/gen2/data.zig +26 -29
  66. package/src/lib/gen2/generated.zig +18 -23
  67. package/src/lib/gen2/helpers.zig +46 -25
  68. package/src/lib/gen2/mechanics.zig +69 -107
  69. package/src/lib/node.zig +2 -4
  70. package/src/lib/pkmn.zig +14 -16
  71. package/src/lib/wasm.zig +1 -2
  72. package/src/tools/display/dom.ts +96 -0
  73. package/src/tools/display/ui.css +354 -0
  74. package/build/test/display.js +0 -400
  75. package/build/test/display.js.map +0 -1
  76. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -1,50 +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
- const util = @import("../common/util.zig");
10
2
 
3
+ const common = @import("../common/data.zig");
11
4
  const data = @import("data.zig");
12
5
  const generated = @import("generated.zig");
13
-
14
- const assert = std.debug.assert;
15
-
16
- const expectEqual = std.testing.expectEqual;
17
- const expectEqualSlices = std.testing.expectEqualSlices;
18
- const expectEqualStrings = std.testing.expectEqualStrings;
19
-
20
- const showdown = pkmn.options.showdown;
21
-
22
- const Choice = common.Choice;
23
- const ID = common.ID;
24
- const Player = common.Player;
25
- 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");
26
10
 
27
11
  const Activate = protocol.Activate;
12
+ const ActivePokemon = data.ActivePokemon;
13
+ const assert = std.debug.assert;
28
14
  const Boost = protocol.Boost;
15
+ const Boosts = data.Boosts;
16
+ const Choice = common.Choice;
29
17
  const Damage = protocol.Damage;
18
+ const Effectiveness = data.Effectiveness;
30
19
  const End = protocol.End;
20
+ const expectEqual = std.testing.expectEqual;
21
+ const expectEqualSlices = std.testing.expectEqualSlices;
22
+ const expectEqualStrings = std.testing.expectEqualStrings;
31
23
  const Fail = protocol.Fail;
32
- const Heal = protocol.Heal;
33
- const Start = protocol.Start;
34
-
35
24
  const Gen12 = rng.Gen12;
36
-
37
- const PointerType = util.PointerType;
38
-
39
- const ActivePokemon = data.ActivePokemon;
40
- const Boosts = data.Boosts;
41
- const Effectiveness = data.Effectiveness;
25
+ const Heal = protocol.Heal;
26
+ const ID = common.ID;
42
27
  const Item = data.Item;
43
28
  const Move = data.Move;
44
- const MoveSlot = data.MoveSlot;
45
- const Pokemon = data.Pokemon;
29
+ const Player = common.Player;
30
+ const Result = common.Result;
31
+ const showdown = pkmn.options.showdown;
46
32
  const Side = data.Side;
47
- const Species = data.Species;
33
+ const Start = protocol.Start;
48
34
  const Stats = data.Stats;
49
35
  const Status = data.Status;
50
36
  const TriAttack = data.TriAttack;
@@ -106,6 +92,7 @@ pub const State = struct {
106
92
  type: Type, // BATTLE_VARS_MOVE_TYPE
107
93
  accuracy: u8, // wEnemyMoveStruct + MOVE_ACC
108
94
  move: Move, // wCurPlayerMove
95
+ hit: u3 = 0,
109
96
  from: Move = .None,
110
97
  mslot: u4, // wCurMoveNum
111
98
  first: bool, // wEnemyGoesFirst
@@ -256,7 +243,6 @@ fn switchIn(battle: anytype, player: Player, slot: u8, kind: SwitchIn, options:
256
243
  } else {
257
244
  try options.log.switched(.{ battle.active(player), incoming });
258
245
  }
259
- options.chance.switched(player, side.pokemon[0].position, out);
260
246
 
261
247
  if (side.conditions.Spikes and !active.types.includes(.Flying)) {
262
248
  incoming.hp -|= @max(incoming.stats.hp / 8, 1);
@@ -442,18 +428,9 @@ fn beforeMove(battle: anytype, player: Player, move: Move, options: anytype) !bo
442
428
  if (Status.is(stored.status, .SLP)) slp: {
443
429
  const before = stored.status;
444
430
  // Even if the EXT bit is set this will still correctly modify the sleep duration
445
- // if (options.calc.modify(player, .sleep)) |extend| {
446
- // if (!extend) stored.status = 0;
447
- // } else {
448
431
  stored.status -= 1;
449
- // }
450
-
451
- const duration = Status.duration(stored.status);
452
- if (!Status.is(stored.status, .EXT)) {
453
- try options.chance.sleep(player, duration);
454
- }
455
432
 
456
- if (duration == 0) {
433
+ if (Status.duration(stored.status) == 0) {
457
434
  try log.curestatus(.{ ident, before, .Message });
458
435
  stored.status = 0; // clears EXT if present
459
436
  resetCant(volatiles);
@@ -483,12 +460,7 @@ fn beforeMove(battle: anytype, player: Player, move: Move, options: anytype) !bo
483
460
  }
484
461
 
485
462
  if (volatiles.disable.duration > 0) {
486
- // if (options.calc.modify(player, .disable)) |extend| {
487
- // if (!extend) volatiles.disable.duration = 0;
488
- // } else {
489
463
  volatiles.disable.duration -= 1;
490
- // }
491
- try options.chance.disable(player, volatiles.disable.duration);
492
464
 
493
465
  if (volatiles.disable.duration == 0) {
494
466
  volatiles.disable.move = 0;
@@ -498,13 +470,7 @@ fn beforeMove(battle: anytype, player: Player, move: Move, options: anytype) !bo
498
470
 
499
471
  if (volatiles.Confusion) {
500
472
  assert(volatiles.confusion > 0);
501
-
502
- // if (options.calc.modify(player, .confusion)) |extend| {
503
- // if (!extend) volatiles.confusion = 0;
504
- // } else {
505
473
  volatiles.confusion -= 1;
506
- // }
507
- try options.chance.confusion(player, volatiles.confusion);
508
474
 
509
475
  if (volatiles.confusion == 0) {
510
476
  volatiles.Confusion = false;
@@ -665,7 +631,7 @@ pub fn checkCriticalHit(battle: anytype, player: Player, state: *State, options:
665
631
  }
666
632
  assert(stage <= 4);
667
633
 
668
- state.crit = try Rolls.criticalHit(battle, player, CRITICAL_HITS[stage], options);
634
+ state.crit = try Rolls.criticalHit(battle, player, state.hit, CRITICAL_HITS[stage], options);
669
635
  }
670
636
 
671
637
  pub fn calcDamage(
@@ -733,7 +699,7 @@ pub fn adjustDamage(battle: anytype, player: Player, state: *State, _: anytype)
733
699
 
734
700
  pub fn randomizeDamage(battle: anytype, player: Player, state: *State, options: anytype) !void {
735
701
  if (state.damage <= 1) return;
736
- const random = try Rolls.damage(battle, player, options);
702
+ const random = try Rolls.damage(battle, player, state.hit, options);
737
703
  options.calc.base(player.foe(), state.damage);
738
704
  state.damage = @intCast(@as(u32, state.damage) *% random / 255);
739
705
  options.calc.final(player.foe(), state.damage);
@@ -1226,7 +1192,7 @@ fn updateSideCondition(
1226
1192
  fn endTurn(battle: anytype, options: anytype) @TypeOf(options.log).Error!Result {
1227
1193
  battle.turn += 1;
1228
1194
 
1229
- if (showdown and battle.turn >= 1000) {
1195
+ if (pkmn.options.mod and battle.turn >= 1000) {
1230
1196
  try options.log.tie(.{});
1231
1197
  return Result.Tie;
1232
1198
  } else if (battle.turn >= 65535) {
@@ -1341,13 +1307,7 @@ pub const Effects = struct {
1341
1307
 
1342
1308
  if (!volatiles.Bide) return;
1343
1309
 
1344
- // if (options.calc.modify(player, .attacking)) |extend| {
1345
- // if (!extend) volatiles.attacks = 0;
1346
- // } else {
1347
1310
  volatiles.attacks -= 1;
1348
- // }
1349
- try options.chance.attacking(player, volatiles.attacks);
1350
-
1351
1311
  if (volatiles.attacks != 0) return options.log.activate(.{ ident, .Bide });
1352
1312
 
1353
1313
  volatiles.Bide = false;
@@ -1738,7 +1698,7 @@ pub const Effects = struct {
1738
1698
  if (!state.proc) return;
1739
1699
  if (foe.conditions.Safeguard) return;
1740
1700
  // Freeze Clause Mod
1741
- 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;
1742
1702
 
1743
1703
  foe_stored.status = Status.init(.FRZ);
1744
1704
  try options.log.status(.{ foe_ident, foe_stored.status, .None });
@@ -2416,7 +2376,7 @@ pub const Effects = struct {
2416
2376
  }
2417
2377
 
2418
2378
  // Sleep Clause Mod
2419
- if (showdown) {
2379
+ if (pkmn.options.mod) {
2420
2380
  for (foe.pokemon) |p| {
2421
2381
  if (Status.is(p.status, .SLP) and !Status.is(p.status, .EXT)) return;
2422
2382
  }
@@ -2876,7 +2836,7 @@ fn convertible(active: ActivePokemon, m: Move) bool {
2876
2836
 
2877
2837
  pub const Rolls = struct {
2878
2838
  fn speedTie(battle: anytype, options: anytype) !bool {
2879
- const p1 = if (options.calc.overridden(.P1, .speed_tie)) |player|
2839
+ const p1 = if (options.calc.overridden(.P1, 0, .speed_tie)) |player|
2880
2840
  player == .P1
2881
2841
  else if (showdown)
2882
2842
  battle.rng.range(u8, 0, 2) == 0
@@ -2888,7 +2848,7 @@ pub const Rolls = struct {
2888
2848
  }
2889
2849
 
2890
2850
  fn quickClaw(battle: anytype, player: Player, options: anytype) !bool {
2891
- const qkc = if (options.calc.overridden(player, .quick_claw)) |val|
2851
+ const qkc = if (options.calc.overridden(player, 0, .quick_claw)) |val|
2892
2852
  val == .true
2893
2853
  else if (showdown)
2894
2854
  battle.rng.chance(u8, 60, 256)
@@ -2900,7 +2860,7 @@ pub const Rolls = struct {
2900
2860
  }
2901
2861
 
2902
2862
  fn hit(battle: anytype, player: Player, accuracy: u8, options: anytype) !bool {
2903
- const ok = if (options.calc.overridden(player, .hit)) |val|
2863
+ const ok = if (options.calc.overridden(player, 0, .hit)) |val|
2904
2864
  val == .true
2905
2865
  else if (showdown)
2906
2866
  battle.rng.chance(u8, accuracy, 256)
@@ -2911,20 +2871,22 @@ pub const Rolls = struct {
2911
2871
  return ok;
2912
2872
  }
2913
2873
 
2914
- fn criticalHit(battle: anytype, player: Player, rate: u8, options: anytype) !bool {
2915
- const crit = if (options.calc.overridden(player, .critical_hit)) |val|
2874
+ fn criticalHit(battle: anytype, player: Player, i: u3, rate: u8, options: anytype) !bool {
2875
+ _ = .{ player, options };
2876
+ const crit = if (options.calc.overridden(player, i, .critical_hits)) |val|
2916
2877
  val == .true
2917
2878
  else if (showdown)
2918
2879
  battle.rng.chance(u8, rate, 256)
2919
2880
  else
2920
2881
  battle.rng.next() < rate;
2921
2882
 
2922
- try options.chance.criticalHit(player, crit, rate);
2883
+ try options.chance.criticalHit(player, i, crit, rate);
2923
2884
  return crit;
2924
2885
  }
2925
2886
 
2926
- fn damage(battle: anytype, player: Player, options: anytype) !u8 {
2927
- const roll = if (options.calc.overridden(player, .damage)) |val|
2887
+ fn damage(battle: anytype, player: Player, i: u3, options: anytype) !u8 {
2888
+ _ = .{ player, options };
2889
+ const roll = if (options.calc.overridden(player, i, .damages)) |val|
2928
2890
  val
2929
2891
  else roll: {
2930
2892
  if (showdown) break :roll battle.rng.range(u8, 217, 256);
@@ -2935,12 +2897,12 @@ pub const Rolls = struct {
2935
2897
  };
2936
2898
 
2937
2899
  assert(roll >= 217 and roll <= 255);
2938
- try options.chance.damage(player, roll);
2900
+ try options.chance.damage(player, i, roll);
2939
2901
  return roll;
2940
2902
  }
2941
2903
 
2942
2904
  fn confused(battle: anytype, player: Player, options: anytype) !bool {
2943
- const cfz = if (options.calc.overridden(player, .confused)) |val|
2905
+ const cfz = if (options.calc.overridden(player, 0, .confused)) |val|
2944
2906
  val == .true
2945
2907
  else if (showdown)
2946
2908
  !battle.rng.chance(u8, 128, 256)
@@ -2952,7 +2914,7 @@ pub const Rolls = struct {
2952
2914
  }
2953
2915
 
2954
2916
  fn attract(battle: anytype, player: Player, options: anytype) !bool {
2955
- const cant = if (options.calc.overridden(player, .attract)) |val|
2917
+ const cant = if (options.calc.overridden(player, 0, .attract)) |val|
2956
2918
  val == .true
2957
2919
  else if (showdown)
2958
2920
  battle.rng.chance(u8, 1, 2)
@@ -2964,7 +2926,7 @@ pub const Rolls = struct {
2964
2926
  }
2965
2927
 
2966
2928
  fn paralyzed(battle: anytype, player: Player, options: anytype) !bool {
2967
- const par = if (options.calc.overridden(player, .paralyzed)) |val|
2929
+ const par = if (options.calc.overridden(player, 0, .paralyzed)) |val|
2968
2930
  val == .true
2969
2931
  else if (showdown)
2970
2932
  battle.rng.chance(u8, 63, 256)
@@ -2976,7 +2938,7 @@ pub const Rolls = struct {
2976
2938
  }
2977
2939
 
2978
2940
  fn defrost(battle: anytype, player: Player, options: anytype) !bool {
2979
- const thaw = if (options.calc.overridden(player, .defrost)) |val|
2941
+ const thaw = if (options.calc.overridden(player, 0, .defrost)) |val|
2980
2942
  val == .true
2981
2943
  else if (showdown)
2982
2944
  battle.rng.chance(u8, 25, 256)
@@ -2989,7 +2951,7 @@ pub const Rolls = struct {
2989
2951
 
2990
2952
  fn secondaryChance(battle: anytype, player: Player, rate: u8, options: anytype) !bool {
2991
2953
  // GLITCH: 100% secondary chance will still fail 1/256 of the time
2992
- const proc = if (options.calc.overridden(player, .secondary_chance)) |val|
2954
+ const proc = if (options.calc.overridden(player, 0, .secondary_chance)) |val|
2993
2955
  val == .true
2994
2956
  else if (showdown)
2995
2957
  battle.rng.chance(u8, rate, 256)
@@ -3001,7 +2963,7 @@ pub const Rolls = struct {
3001
2963
  }
3002
2964
 
3003
2965
  fn item(battle: anytype, player: Player, options: anytype) !bool {
3004
- const proc = if (options.calc.overridden(player, .item)) |val|
2966
+ const proc = if (options.calc.overridden(player, 0, .item)) |val|
3005
2967
  val == .true
3006
2968
  else if (showdown)
3007
2969
  battle.rng.chance(u8, 30, 256)
@@ -3013,7 +2975,7 @@ pub const Rolls = struct {
3013
2975
  }
3014
2976
 
3015
2977
  fn triAttack(battle: anytype, player: Player, options: anytype) !TriAttack {
3016
- const status: TriAttack = if (options.calc.overridden(player, .tri_attack)) |val|
2978
+ const status: TriAttack = if (options.calc.overridden(player, 0, .tri_attack)) |val|
3017
2979
  @enumFromInt(@intFromEnum(val) - 1)
3018
2980
  else if (showdown)
3019
2981
  @enumFromInt(battle.rng.range(u2, 0, 2))
@@ -3029,7 +2991,7 @@ pub const Rolls = struct {
3029
2991
  }
3030
2992
 
3031
2993
  fn present(battle: anytype, player: Player, options: anytype) !u8 {
3032
- const power = if (options.calc.overridden(player, .present)) |val|
2994
+ const power = if (options.calc.overridden(player, 0, .present)) |val|
3033
2995
  (val - 1) * 40
3034
2996
  else if (showdown) power: {
3035
2997
  const r = battle.rng.range(u8, 0, 10);
@@ -3051,7 +3013,7 @@ pub const Rolls = struct {
3051
3013
  }
3052
3014
 
3053
3015
  fn magnitude(battle: anytype, player: Player, options: anytype) !u8 {
3054
- const num: u8 = if (options.calc.overridden(player, .magnitude)) |val|
3016
+ const num: u8 = if (options.calc.overridden(player, 0, .magnitude)) |val|
3055
3017
  val + 3
3056
3018
  else if (showdown) num: {
3057
3019
  const r = battle.rng.range(u8, 0, 100);
@@ -3079,7 +3041,7 @@ pub const Rolls = struct {
3079
3041
  }
3080
3042
 
3081
3043
  fn tripleKick(battle: anytype, player: Player, options: anytype) !u2 {
3082
- const hits = if (options.calc.overridden(player, .triple_kick)) |val|
3044
+ const hits = if (options.calc.overridden(player, 0, .triple_kick)) |val|
3083
3045
  val
3084
3046
  else if (showdown)
3085
3047
  battle.rng.range(u2, 1, 4)
@@ -3097,7 +3059,7 @@ pub const Rolls = struct {
3097
3059
 
3098
3060
  fn spite(battle: anytype, player: Player, options: anytype) !u3 {
3099
3061
  assert(!showdown);
3100
- const pp: u3 = if (options.calc.overridden(player, .spite)) |val|
3062
+ const pp: u3 = if (options.calc.overridden(player, 0, .spite)) |val|
3101
3063
  val + 1
3102
3064
  else
3103
3065
  @intCast((battle.rng.next() & 3) + 2);
@@ -3114,7 +3076,7 @@ pub const Rolls = struct {
3114
3076
  var i: u8 = 0;
3115
3077
  const neutral = @intFromEnum(Effectiveness.Neutral);
3116
3078
  assert(mtype != .@"???");
3117
- const ty: Type = if (options.calc.overridden(player, .conversion_2)) |val|
3079
+ const ty: Type = if (options.calc.overridden(player, 0, .conversion_2)) |val|
3118
3080
  @enumFromInt(@intFromEnum(val) - 1)
3119
3081
  else if (showdown) ty: {
3120
3082
  for (Type.SHOWDOWN) |t| {
@@ -3148,7 +3110,7 @@ pub const Rolls = struct {
3148
3110
  assert(count <= 8);
3149
3111
  const num = if (count == 8) 0 else @as(u8, 255) >> @intCast(count);
3150
3112
 
3151
- const ok = if (options.calc.overridden(player, .protect)) |val|
3113
+ const ok = if (options.calc.overridden(player, 0, .protect)) |val|
3152
3114
  val == .true
3153
3115
  else if (showdown)
3154
3116
  battle.rng.chance(u8, num, 255)
@@ -3170,7 +3132,7 @@ pub const Rolls = struct {
3170
3132
  const moves = active.moves;
3171
3133
 
3172
3134
  // TODO: consider throwing error instead of rerolling?
3173
- const overridden = if (options.calc.overridden(player, .move_slot)) |val|
3135
+ const overridden = if (options.calc.overridden(player, 0, .move_slot)) |val|
3174
3136
  if (convertible(active, moves[val - 1].id)) val else null
3175
3137
  else
3176
3138
  null;
@@ -3207,7 +3169,7 @@ pub const Rolls = struct {
3207
3169
  const moves = active.moves;
3208
3170
 
3209
3171
  // TODO: consider throwing error instead of rerolling?
3210
- const overridden = if (options.calc.overridden(player, .move_slot)) |val|
3172
+ const overridden = if (options.calc.overridden(player, 0, .move_slot)) |val|
3211
3173
  if (val != mslot and Move.get(moves[val - 1].id).extra.sleep_talk) val else null
3212
3174
  else
3213
3175
  null;
@@ -3251,7 +3213,7 @@ pub const Rolls = struct {
3251
3213
  assert(n > 0 and n <= 6);
3252
3214
 
3253
3215
  // TODO: consider throwing error instead of rerolling?
3254
- const overridden = if (options.calc.overridden(player, .force_switch)) |val| val: {
3216
+ const overridden = if (options.calc.overridden(player, 0, .force_switch)) |val| val: {
3255
3217
  for (slots) |slot| if (slot == val) break :val if (foe.get(slot).hp > 0) val else null;
3256
3218
  break :val null;
3257
3219
  } else null;
@@ -3277,7 +3239,7 @@ pub const Rolls = struct {
3277
3239
  const DISTRIBUTION = [_]u3{ 2, 2, 2, 3, 3, 3, 4, 5 };
3278
3240
 
3279
3241
  fn multiHit(battle: anytype, player: Player, options: anytype) !u3 {
3280
- const n: u3 = if (options.calc.overridden(player, .multi_hit)) |val|
3242
+ const n: u3 = if (options.calc.overridden(player, 0, .multi_hit)) |val|
3281
3243
  @intCast(val)
3282
3244
  else if (showdown)
3283
3245
  DISTRIBUTION[battle.rng.range(u3, 0, DISTRIBUTION.len)]
@@ -3292,7 +3254,7 @@ pub const Rolls = struct {
3292
3254
  }
3293
3255
 
3294
3256
  fn psywave(battle: anytype, player: Player, max: u8, options: anytype) !u8 {
3295
- const power = if (options.calc.overridden(player, .psywave)) |val|
3257
+ const power = if (options.calc.overridden(player, 0, .psywave)) |val|
3296
3258
  val
3297
3259
  else if (showdown)
3298
3260
  battle.rng.range(u8, 1, max)
@@ -3318,7 +3280,7 @@ pub const Rolls = struct {
3318
3280
  }
3319
3281
 
3320
3282
  // TODO: consider throwing error instead of rerolling?
3321
- const overridden = if (options.calc.overridden(player, .metronome)) |val| val: {
3283
+ const overridden = if (options.calc.overridden(player, 0, .metronome)) |val| val: {
3322
3284
  for (moves) |m| if (m.id == val) break :val null;
3323
3285
  break :val val;
3324
3286
  } else null;
@@ -3350,7 +3312,7 @@ pub const Rolls = struct {
3350
3312
  }
3351
3313
 
3352
3314
  fn sleepDuration(battle: anytype, player: Player, options: anytype) u3 {
3353
- const duration: u3 = if (options.calc.overridden(player, .duration)) |val|
3315
+ const duration: u3 = if (options.calc.overridden(player, 0, .duration)) |val|
3354
3316
  @intCast(val)
3355
3317
  else if (showdown)
3356
3318
  battle.rng.range(u3, 1, 7)
@@ -3362,12 +3324,12 @@ pub const Rolls = struct {
3362
3324
  };
3363
3325
 
3364
3326
  assert(duration >= 1 and duration <= 6);
3365
- options.chance.duration(.sleep, player, player.foe(), duration);
3327
+ options.chance.duration(player, duration);
3366
3328
  return duration + 1;
3367
3329
  }
3368
3330
 
3369
3331
  fn confusionDuration(battle: anytype, player: Player, self: bool, options: anytype) u3 {
3370
- const duration: u3 = if (options.calc.overridden(player, .duration)) |val|
3332
+ const duration: u3 = if (options.calc.overridden(player, 0, .duration)) |val|
3371
3333
  @intCast(val)
3372
3334
  else if (showdown)
3373
3335
  // Pokémon Showdown incorrectly uses the same duration for self-confusion
@@ -3376,16 +3338,16 @@ pub const Rolls = struct {
3376
3338
  @intCast((battle.rng.next() & if (self) 1 else 3) + 2);
3377
3339
 
3378
3340
  assert(duration >= 2 and duration <= if (!showdown and self) 3 else 5);
3379
- options.chance.duration(.confusion, player, if (self) player else player.foe(), duration);
3341
+ options.chance.duration(player, duration);
3380
3342
  return duration;
3381
3343
  }
3382
3344
 
3383
3345
  fn disableDuration(battle: anytype, player: Player, options: anytype) u4 {
3384
- const duration: u4 = if (options.calc.overridden(player, .duration)) |val|
3346
+ const duration: u3 = if (options.calc.overridden(player, 0, .duration)) |val|
3385
3347
  @intCast(val)
3386
3348
  else if (showdown)
3387
3349
  // Pokémon Showdown incorrectly inherits Generation III's Disable duration
3388
- battle.rng.range(u4, 2, 6)
3350
+ battle.rng.range(u3, 2, 6)
3389
3351
  else duration: {
3390
3352
  while (true) {
3391
3353
  const r = battle.rng.next() & 7;
@@ -3394,12 +3356,12 @@ pub const Rolls = struct {
3394
3356
  };
3395
3357
 
3396
3358
  assert(duration >= 2 and duration <= (if (showdown) 5 else 7));
3397
- options.chance.duration(.disable, player, player.foe(), duration);
3359
+ options.chance.duration(player, duration);
3398
3360
  return duration;
3399
3361
  }
3400
3362
 
3401
3363
  fn attackingDuration(battle: anytype, player: Player, options: anytype) u3 {
3402
- const duration: u3 = if (options.calc.overridden(player, .duration)) |val|
3364
+ const duration: u3 = if (options.calc.overridden(player, 0, .duration)) |val|
3403
3365
  @intCast(val)
3404
3366
  else if (showdown)
3405
3367
  battle.rng.range(u3, 2, 4)
@@ -3407,12 +3369,12 @@ pub const Rolls = struct {
3407
3369
  @intCast((battle.rng.next() & 1) + 2); // BUG: thrash is + 1 not +2
3408
3370
 
3409
3371
  assert(duration >= 2 and duration <= 3);
3410
- options.chance.duration(.attacking, player, player, duration);
3372
+ options.chance.duration(player, duration);
3411
3373
  return duration;
3412
3374
  }
3413
3375
 
3414
3376
  fn bindingDuration(battle: anytype, player: Player, options: anytype) u3 {
3415
- const duration: u3 = (if (options.calc.overridden(player, .duration)) |val|
3377
+ const duration: u3 = (if (options.calc.overridden(player, 0, .duration)) |val|
3416
3378
  @intCast(val)
3417
3379
  else if (showdown)
3418
3380
  // TODO: PS does range(3, 6) here which after subtracting 1 is actually 2-4 not 2-5!
@@ -3421,13 +3383,13 @@ pub const Rolls = struct {
3421
3383
  @intCast(battle.rng.next() & 3 + 2));
3422
3384
 
3423
3385
  assert(duration >= 2 and duration <= 5);
3424
- options.chance.duration(.binding, player, player.foe(), duration);
3386
+ options.chance.duration(player, duration);
3425
3387
  return duration + 1;
3426
3388
  }
3427
3389
 
3428
3390
  // TODO: consider sharing implementation with bindingDuration
3429
3391
  fn encoreDuration(battle: anytype, player: Player, options: anytype) u3 {
3430
- const duration: u3 = (if (options.calc.overridden(player, .duration)) |val|
3392
+ const duration: u3 = (if (options.calc.overridden(player, 0, .duration)) |val|
3431
3393
  @intCast(val)
3432
3394
  else if (showdown)
3433
3395
  battle.rng.range(u3, 2, 6)
@@ -3435,7 +3397,7 @@ pub const Rolls = struct {
3435
3397
  @intCast(battle.rng.next() & 3 + 2));
3436
3398
 
3437
3399
  assert(duration >= 2 and duration <= 5);
3438
- options.chance.duration(.encore, player, player.foe(), duration);
3400
+ options.chance.duration(player, duration);
3439
3401
  return duration + 1;
3440
3402
  }
3441
3403
  };
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
@@ -22,13 +22,16 @@ pub const Choice = @import("common/data.zig").Choice;
22
22
  /// considered terminal.
23
23
  pub const Result = @import("common/data.zig").Result;
24
24
 
25
+ // TODO
26
+ pub const Array = @import("common/array.zig").Array;
27
+ // TODO
28
+ pub const Optional = @import("common/optional.zig").Optional;
29
+
25
30
  /// Pokémon Showdown's RNG (backed by a Generation V & VI RNG).
26
31
  pub const PSRNG = @import("common/rng.zig").PSRNG;
27
32
 
28
33
  /// Namespace for helpers related to protocol message logging.
29
- pub const protocol = if (options.internal) struct {
30
- pub usingnamespace @import("common/protocol.zig");
31
- } else struct {
34
+ pub const protocol = if (options.internal) @import("common/protocol.zig") else struct {
32
35
  /// Logs protocol information to its `Writer` during a battle update when
33
36
  /// `options.log` is enabled.
34
37
  pub const Log = @import("common/protocol.zig").Log;
@@ -82,11 +85,7 @@ pub const gen1 = struct {
82
85
  /// via `overrides` and tracks `summaries` of information relevant to damage calculation.
83
86
  pub const Calc = @import("gen1/calc.zig").Calc;
84
87
  /// Namespace for types associated with supported Generation I Pokémon damage calc features.
85
- pub const calc = if (options.internal) struct {
86
- pub usingnamespace @import("gen1/calc.zig");
87
- } else struct {
88
- /// TODO
89
- pub const Overrides = @import("gen1/calc.zig").Overrides;
88
+ pub const calc = if (options.internal) @import("gen1/calc.zig") else struct {
90
89
  /// Information relevant to damage calculation that occured during a Generation I
91
90
  /// battle `update`.
92
91
  pub const Summaries = @import("gen1/calc.zig").Summaries;
@@ -97,6 +96,10 @@ pub const gen1 = struct {
97
96
  /// though damage calculator support should additionally be turned off
98
97
  /// entirely via `options.calc`.
99
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;
100
103
  };
101
104
  /// Provides helpers for initializing Generation I Pokémon battles.
102
105
  pub const helpers = @import("gen1/helpers.zig");
@@ -114,10 +117,7 @@ pub const gen2 = struct {
114
117
  pub const NULL = @import("gen2/chance.zig").NULL;
115
118
  };
116
119
  pub const Calc = @import("gen2/calc.zig").Calc;
117
- pub const calc = if (options.internal) struct {
118
- pub usingnamespace @import("gen2/calc.zig");
119
- } else struct {
120
- pub const Overrides = @import("gen2/calc.zig").Overrides;
120
+ pub const calc = if (options.internal) @import("gen2/calc.zig") else struct {
121
121
  pub const Summaries = @import("gen2/calc.zig").Summaries;
122
122
  pub const Summary = @import("gen2/calc.zig").Summary;
123
123
  pub const NULL = @import("gen2/calc.zig").NULL;
@@ -127,10 +127,8 @@ pub const gen2 = struct {
127
127
 
128
128
  // Internal APIs used by other pkmn libraries, not actually part of the public API.
129
129
  // NOTE: `pub usingnamespace struct { ... }` here results in a (false?) dependency loop
130
- pub const js = if (options.internal) struct {
131
- pub usingnamespace @import("common/js.zig");
132
- } else struct {};
130
+ pub const js = if (options.internal) @import("common/js.zig") else {};
133
131
  pub const bindings = if (options.internal) struct {
134
132
  pub const node = @import("node.zig");
135
133
  pub const wasm = @import("wasm.zig");
136
- } else struct {};
134
+ } else {};
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;