@pkmn/engine 0.1.0-dev.d4119c62 → 0.1.0-dev.d4bd80b1

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 (83) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +46 -18
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +47 -0
  5. package/build/pkg/addon/browser.js.map +1 -0
  6. package/build/pkg/addon/node.d.ts +3 -0
  7. package/build/pkg/addon/node.js +110 -0
  8. package/build/pkg/addon/node.js.map +1 -0
  9. package/build/pkg/addon/wasm.d.ts +2 -0
  10. package/build/pkg/addon/wasm.js +53 -0
  11. package/build/pkg/addon/wasm.js.map +1 -0
  12. package/build/pkg/addon.d.ts +25 -3
  13. package/build/pkg/addon.js +39 -71
  14. package/build/pkg/addon.js.map +1 -1
  15. package/build/pkg/data/layout.json +15 -2
  16. package/build/pkg/data/protocol.json +23 -9
  17. package/build/pkg/data.d.ts +27 -5
  18. package/build/pkg/data.js.map +1 -1
  19. package/build/pkg/gen1.d.ts +15 -18
  20. package/build/pkg/gen1.js +28 -19
  21. package/build/pkg/gen1.js.map +1 -1
  22. package/build/pkg/index.d.ts +40 -90
  23. package/build/pkg/index.js +23 -70
  24. package/build/pkg/index.js.map +1 -1
  25. package/build/pkg/protocol.d.ts +20 -1
  26. package/build/pkg/protocol.js +109 -107
  27. package/build/pkg/protocol.js.map +1 -1
  28. package/build/tools/debug.js +53 -78
  29. package/build/tools/debug.js.map +1 -1
  30. package/build/tools/display/debug.jsx +152 -0
  31. package/build/tools/display/debug.jsx.map +1 -0
  32. package/build/tools/display/index.js +152 -0
  33. package/build/tools/display/index.js.map +1 -0
  34. package/build/tools/display/ui.jsx +359 -0
  35. package/build/tools/display/ui.jsx.map +1 -0
  36. package/build/tools/display/util.js +33 -0
  37. package/build/tools/display/util.js.map +1 -0
  38. package/build.zig +330 -104
  39. package/package.json +60 -134
  40. package/src/bin/install-pkmn-engine +32 -21
  41. package/src/bin/pkmn-debug +1 -1
  42. package/src/lib/bindings/c.zig +255 -0
  43. package/src/lib/{binding → bindings}/node.zig +8 -21
  44. package/src/lib/bindings/wasm.zig +59 -0
  45. package/src/lib/common/array.zig +77 -0
  46. package/src/lib/common/data.zig +4 -4
  47. package/src/lib/common/debug.zig +39 -8
  48. package/src/lib/common/js.zig +4 -2
  49. package/src/lib/common/optional.zig +14 -10
  50. package/src/lib/common/options.zig +6 -0
  51. package/src/lib/common/protocol.zig +63 -67
  52. package/src/lib/common/rational.zig +128 -32
  53. package/src/lib/common/rng.zig +7 -9
  54. package/src/lib/common/util.zig +50 -1
  55. package/src/lib/gen1/calc.zig +686 -159
  56. package/src/lib/gen1/chance.zig +405 -280
  57. package/src/lib/gen1/data/moves.zig +2 -4
  58. package/src/lib/gen1/data/species.zig +2 -4
  59. package/src/lib/gen1/data/types.zig +1 -2
  60. package/src/lib/gen1/data.zig +24 -27
  61. package/src/lib/gen1/helpers.zig +92 -548
  62. package/src/lib/gen1/mechanics.zig +379 -258
  63. package/src/lib/gen2/calc.zig +37 -27
  64. package/src/lib/gen2/chance.zig +84 -496
  65. package/src/lib/gen2/data/items.zig +1 -3
  66. package/src/lib/gen2/data/moves.zig +2 -4
  67. package/src/lib/gen2/data/species.zig +1 -3
  68. package/src/lib/gen2/data/types.zig +1 -2
  69. package/src/lib/gen2/data.zig +19 -22
  70. package/src/lib/gen2/generated.zig +19 -26
  71. package/src/lib/gen2/helpers.zig +46 -25
  72. package/src/lib/gen2/mechanics.zig +217 -163
  73. package/src/lib/node.zig +18 -0
  74. package/src/lib/pkmn.zig +37 -15
  75. package/src/lib/wasm.zig +17 -0
  76. package/src/tools/display/dom.ts +95 -0
  77. package/src/tools/display/ui.css +354 -0
  78. package/build/test/display.js +0 -400
  79. package/build/test/display.js.map +0 -1
  80. package/src/lib/binding/wasm.zig +0 -12
  81. package/src/lib/gen1/README.md +0 -894
  82. package/src/lib/gen2/README.md +0 -329
  83. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -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;
@@ -45,6 +41,7 @@ const Player = data.Player;
45
41
  const Result = data.Result;
46
42
 
47
43
  const PointerType = util.PointerType;
44
+ const isPointerTo = util.isPointerTo;
48
45
 
49
46
  const showdown = pkmn.options.showdown;
50
47
 
@@ -63,12 +60,12 @@ pub fn Battle(comptime RNG: anytype) type {
63
60
  _: [padding]u8 = .{0} ** padding,
64
61
 
65
62
  pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
66
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
63
+ assert(isPointerTo(self, Self));
67
64
  return &self.sides[@intFromEnum(player)];
68
65
  }
69
66
 
70
67
  pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
71
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
68
+ assert(isPointerTo(self, Self));
72
69
  return &self.sides[@intFromEnum(player.foe())];
73
70
  }
74
71
 
@@ -134,7 +131,7 @@ pub const Side = extern struct {
134
131
  }
135
132
 
136
133
  pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
137
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
134
+ assert(isPointerTo(self, Side));
138
135
  assert(slot > 0 and slot <= 6);
139
136
  const id = self.pokemon[slot - 1].position;
140
137
  assert(id > 0 and id <= 6);
@@ -142,7 +139,7 @@ pub const Side = extern struct {
142
139
  }
143
140
 
144
141
  pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
145
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
142
+ assert(isPointerTo(self, Side));
146
143
  return self.get(1);
147
144
  }
148
145
 
@@ -176,7 +173,7 @@ pub const ActivePokemon = extern struct {
176
173
  }
177
174
 
178
175
  pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
179
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
176
+ assert(isPointerTo(self, Pokemon));
180
177
  assert(mslot > 0 and mslot <= 4);
181
178
  assert(self.moves[mslot - 1].id != .None);
182
179
  return &self.moves[mslot - 1];
@@ -201,7 +198,7 @@ pub const Pokemon = extern struct {
201
198
  }
202
199
 
203
200
  pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
204
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
201
+ assert(isPointerTo(self, Pokemon));
205
202
  assert(mslot > 0 and mslot <= 4);
206
203
  assert(self.moves[mslot - 1].id != .None);
207
204
  return &self.moves[mslot - 1];
@@ -239,7 +236,7 @@ pub const DVs = packed struct(u16) {
239
236
  };
240
237
  const p: u6 = @intCast(1 + ((5 * @as(u8, (dvs.atk & 0b1000) | ((dvs.def & 0b1000)) >> 1 |
241
238
  ((dvs.spe & 0b1000)) >> 2 | ((dvs.spc & 0b1000)) >> 3) + (dvs.spc & 0b0011)) >> 1));
242
- var t = @as(u8, dvs.def & 0b0011) + (@as(u8, dvs.atk & 0b0011) << 2);
239
+ const t = @as(u8, dvs.def & 0b0011) + (@as(u8, dvs.atk & 0b0011) << 2);
243
240
  return .{ .gender = g, .pow = p, .type = Type.hiddenPower(t) };
244
241
  }
245
242
  };
@@ -1,39 +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 assert = std.debug.assert;
11
-
12
- const Player = common.Player;
13
- const Result = common.Result;
14
-
15
- const Effectiveness = data.Effectiveness;
16
- const Move = data.Move;
17
-
18
- const Effects = mechanics.Effects;
19
- const State = mechanics.State;
20
-
21
- 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;
22
13
  const canCharge = mechanics.canCharge;
14
+ const canMove = mechanics.canMove;
15
+ const checkCriticalHit = mechanics.checkCriticalHit;
16
+ const checkHit = mechanics.checkHit;
23
17
  const decrementPP = mechanics.decrementPP;
18
+ const destinyBond = mechanics.destinyBond;
24
19
  const doMove = mechanics.doMove;
25
- const checkHit = mechanics.checkHit;
26
- const checkCriticalHit = mechanics.checkCriticalHit;
27
- const calcDamage = mechanics.calcDamage;
28
- const adjustDamage = mechanics.adjustDamage;
29
- const randomizeDamage = mechanics.randomizeDamage;
30
- const applyDamage = mechanics.applyDamage;
31
- const reportOutcome = mechanics.reportOutcome;
32
20
  const effectChance = mechanics.effectChance;
33
- const afterMove = mechanics.afterMove;
34
- const buildRage = mechanics.buildRage;
21
+ const Effectiveness = data.Effectiveness;
22
+ const Effects = mechanics.Effects;
35
23
  const kingsRock = mechanics.kingsRock;
36
- 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;
37
30
 
38
31
  const SECONDARY = true;
39
32
  const KINGS = true;
@@ -42,7 +35,7 @@ pub fn runMove(battle: anytype, player: Player, state: *State, options: anytype)
42
35
  var log = options.log;
43
36
 
44
37
  var side = battle.side(player);
45
- var volatiles = &side.active.volatiles;
38
+ const volatiles = &side.active.volatiles;
46
39
 
47
40
  const ident = battle.active(player);
48
41
  const foe_ident = battle.active(player.foe());
@@ -1,31 +1,22 @@
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
- const protocol = @import("../common/protocol.zig");
6
5
  const rng = @import("../common/rng.zig");
7
-
8
- const gen1 = @import("../gen1/data.zig");
9
-
10
- const data = @import("data.zig");
6
+ const std = @import("std");
11
7
 
12
8
  const assert = std.debug.assert;
13
-
14
- const expectEqual = std.testing.expectEqual;
15
-
16
9
  const Choice = common.Choice;
17
-
18
- const showdown = options.showdown;
19
-
20
- const PSRNG = rng.PSRNG;
21
-
22
10
  const DVs = data.DVs;
23
11
  const Item = data.Item;
24
12
  const Move = data.Move;
25
13
  const MoveSlot = data.MoveSlot;
14
+ const PSRNG = rng.PSRNG;
15
+ const showdown = options.showdown;
26
16
  const Species = data.Species;
27
17
  const Stats = data.Stats;
28
- const Status = data.Status;
18
+
19
+ const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
29
20
 
30
21
  pub const Options = struct {
31
22
  cleric: bool = showdown,
@@ -65,17 +56,47 @@ pub const Battle = struct {
65
56
  };
66
57
 
67
58
  pub fn prng(rand: *PSRNG) data.PRNG {
68
- // FIXME: what is max range in gen2?
69
59
  return .{
70
60
  .src = .{
71
61
  .seed = if (showdown)
72
62
  rand.newSeed()
73
- else
74
- .{
75
- rand.range(u8, 0, 256), rand.range(u8, 0, 256), rand.range(u8, 0, 256),
76
- rand.range(u8, 0, 256), rand.range(u8, 0, 256), rand.range(u8, 0, 256),
77
- rand.range(u8, 0, 256), rand.range(u8, 0, 256), rand.range(u8, 0, 256),
78
- },
63
+ else seed: {
64
+ // GLITCH: The initial RNG seed in Gen II link battles is heavily constrained
65
+ // https://www.smogon.com/forums/threads/rng-in-rby-link-battles.3746779
66
+ var seed = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0 };
67
+
68
+ // Bytes in seed can only range from 0-252, not 0-255
69
+ const max: u8 = 253;
70
+ // Instructions take multiples of 4 cycles to execute
71
+ var timer: u16 = 4 * rand.range(u16, 0, 16384);
72
+ var add: u8 = rand.range(u8, 0, 256);
73
+ var sub: u8 = rand.range(u8, 0, 256);
74
+ var carry: u8 = 0;
75
+ var div: u8 = 0;
76
+
77
+ var i: u8 = 0;
78
+ while (i < seed.len) {
79
+ div = @intCast(timer >> 8);
80
+ // This is effectively @addWithOverflow but with three operands
81
+ const result = @as(u16, add) + @as(u16, div) + @as(u16, carry);
82
+ add = @intCast(result & 255);
83
+ carry = @intFromBool(result > 255);
84
+ timer +%= 44;
85
+ div = @intCast(timer >> 8);
86
+ sub -%= div +% carry;
87
+
88
+ if (sub < max) {
89
+ seed[i] = sub;
90
+ i += 1;
91
+ timer +%= 152;
92
+ carry = 1;
93
+ } else {
94
+ timer +%= 132;
95
+ carry = 0;
96
+ }
97
+ }
98
+ break :seed seed;
99
+ },
79
100
  },
80
101
  };
81
102
  }
@@ -121,7 +142,7 @@ pub const Pokemon = struct {
121
142
  var pokemon = data.Pokemon{};
122
143
  pokemon.species = p.species;
123
144
  const species = Species.get(p.species);
124
- inline for (@typeInfo(@TypeOf(pokemon.stats)).Struct.fields) |field| {
145
+ inline for (@field(@typeInfo(@TypeOf(pokemon.stats)), @tagName(Struct)).fields) |field| {
125
146
  const hp = comptime std.mem.eql(u8, field.name, "hp");
126
147
  const spc =
127
148
  comptime std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
@@ -162,7 +183,7 @@ pub const Pokemon = struct {
162
183
 
163
184
  var stats: Stats(u16) = .{};
164
185
  const dvs = gen1.DVs.random(rand);
165
- inline for (@typeInfo(@TypeOf(stats)).Struct.fields) |field| {
186
+ inline for (@field(@typeInfo(@TypeOf(stats)), @tagName(Struct)).fields) |field| {
166
187
  const hp = std.mem.eql(u8, field.name, "hp");
167
188
  const spc = std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
168
189
  @field(stats, field.name) = Stats(u16).calc(