@pkmn/engine 0.1.0-dev.cf6f5d2c → 0.1.0-dev.d1b39ff0

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 (60) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +95 -59
  3. package/build/pkg/addon.js +9 -9
  4. package/build/pkg/addon.js.map +1 -1
  5. package/build/pkg/data/ids.json +12 -12
  6. package/build/pkg/data/layout.json +27 -5
  7. package/build/pkg/data/protocol.json +69 -12
  8. package/build/pkg/data.d.ts +4 -4
  9. package/build/pkg/data.js.map +1 -1
  10. package/build/pkg/gen1.d.ts +2 -1
  11. package/build/pkg/gen1.js +38 -20
  12. package/build/pkg/gen1.js.map +1 -1
  13. package/build/pkg/index.d.ts +7 -4
  14. package/build/pkg/index.js.map +1 -1
  15. package/build/pkg/protocol.d.ts +4 -2
  16. package/build/pkg/protocol.js +65 -44
  17. package/build/pkg/protocol.js.map +1 -1
  18. package/build/test/display.js +15 -6
  19. package/build/test/display.js.map +1 -1
  20. package/build/tools/debug.js +5 -4
  21. package/build/tools/debug.js.map +1 -1
  22. package/build.zig +148 -126
  23. package/package.json +53 -24
  24. package/src/bin/install-pkmn-engine +35 -22
  25. package/src/lib/common/battle.zig +17 -0
  26. package/src/lib/common/data.zig +19 -31
  27. package/src/lib/common/debug.zig +22 -13
  28. package/src/lib/common/js.zig +118 -0
  29. package/src/lib/common/optional.zig +67 -0
  30. package/src/lib/common/options.zig +11 -0
  31. package/src/lib/common/protocol.zig +906 -367
  32. package/src/lib/common/rational.zig +454 -0
  33. package/src/lib/common/rng.zig +35 -26
  34. package/src/lib/common/util.zig +12 -0
  35. package/src/lib/gen1/calc.zig +802 -0
  36. package/src/lib/gen1/chance.zig +1159 -0
  37. package/src/lib/gen1/data/moves.zig +202 -190
  38. package/src/lib/gen1/data/species.zig +5 -5
  39. package/src/lib/gen1/data/types.zig +10 -10
  40. package/src/lib/gen1/data.zig +104 -90
  41. package/src/lib/gen1/helpers.zig +140 -42
  42. package/src/lib/gen1/mechanics.zig +1135 -773
  43. package/src/lib/gen2/calc.zig +135 -0
  44. package/src/lib/gen2/chance.zig +895 -0
  45. package/src/lib/gen2/data/items.zig +14 -20
  46. package/src/lib/gen2/data/moves.zig +664 -570
  47. package/src/lib/gen2/data/species.zig +2 -2
  48. package/src/lib/gen2/data/types.zig +137 -34
  49. package/src/lib/gen2/data.zig +130 -92
  50. package/src/lib/gen2/generated.zig +806 -0
  51. package/src/lib/gen2/helpers.zig +50 -26
  52. package/src/lib/gen2/mechanics.zig +3568 -12
  53. package/src/lib/node.zig +131 -0
  54. package/src/lib/pkmn.zig +81 -5
  55. package/src/lib/wasm.zig +13 -0
  56. package/src/test/display/pkmn.html.tmpl +5 -5
  57. package/src/lib/binding/node.zig +0 -229
  58. package/src/lib/binding/wasm.zig +0 -10
  59. package/src/lib/gen1/README.md +0 -804
  60. package/src/lib/gen2/README.md +0 -309
@@ -48,7 +48,7 @@ pub const Battle = struct {
48
48
  comptime rolls: anytype,
49
49
  p1: []const Pokemon,
50
50
  p2: []const Pokemon,
51
- ) data.Battle(rng.FixedRNG(1, rolls.len)) {
51
+ ) data.Battle(rng.FixedRNG(2, rolls.len)) {
52
52
  return .{
53
53
  .rng = .{ .rolls = rolls },
54
54
  .sides = .{ Side.init(p1), Side.init(p2) },
@@ -65,19 +65,47 @@ pub const Battle = struct {
65
65
  };
66
66
 
67
67
  pub fn prng(rand: *PSRNG) data.PRNG {
68
- // FIXME: what is max range in gen2?
69
68
  return .{
70
69
  .src = .{
71
70
  .seed = if (showdown)
72
71
  rand.newSeed()
73
- else
74
- .{
75
- rand.range(u8, 0, 256), rand.range(u8, 0, 256),
76
- rand.range(u8, 0, 256), rand.range(u8, 0, 256),
77
- rand.range(u8, 0, 256), rand.range(u8, 0, 256),
78
- rand.range(u8, 0, 256), rand.range(u8, 0, 256),
79
- rand.range(u8, 0, 256), rand.range(u8, 0, 256),
80
- },
72
+ else seed: {
73
+ // GLITCH: The initial RNG seed in Gen II link battles is heavily constrained
74
+ // https://www.smogon.com/forums/threads/rng-in-rby-link-battles.3746779
75
+ var seed = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0 };
76
+
77
+ // Bytes in seed can only range from 0-252, not 0-255
78
+ const max: u8 = 253;
79
+ // Instructions take multiples of 4 cycles to execute
80
+ var timer: u16 = 4 * rand.range(u16, 0, 16384);
81
+ var add: u8 = rand.range(u8, 0, 256);
82
+ var sub: u8 = rand.range(u8, 0, 256);
83
+ var carry: u8 = 0;
84
+ var div: u8 = 0;
85
+
86
+ var i: u8 = 0;
87
+ while (i < seed.len) {
88
+ div = @intCast(timer >> 8);
89
+ // This is effectively @addWithOverflow but with three operands
90
+ const result = @as(u16, add) + @as(u16, div) + @as(u16, carry);
91
+ add = @intCast(result & 255);
92
+ carry = @intFromBool(result > 255);
93
+ timer +%= 44;
94
+ div = @intCast(timer >> 8);
95
+ sub -%= div +% carry;
96
+
97
+ if (sub < max) {
98
+ seed[i] = sub;
99
+ i += 1;
100
+ timer +%= 152;
101
+ carry = 1;
102
+ } else {
103
+ timer +%= 132;
104
+ carry = 0;
105
+ }
106
+ }
107
+ break :seed seed;
108
+ },
81
109
  },
82
110
  };
83
111
  }
@@ -89,7 +117,7 @@ pub const Side = struct {
89
117
 
90
118
  for (0..ps.len) |i| {
91
119
  side.pokemon[i] = Pokemon.init(ps[i]);
92
- // FIXME side.order[i] = i + 1;
120
+ side.pokemon[i].position = @as(u4, @intCast(i)) + 1;
93
121
  }
94
122
  return side;
95
123
  }
@@ -100,7 +128,7 @@ pub const Side = struct {
100
128
 
101
129
  for (0..n) |i| {
102
130
  side.pokemon[i] = Pokemon.random(rand, opt);
103
- side.pokemon[i].position = i + 1;
131
+ side.pokemon[i].position = @as(u4, @intCast(i)) + 1;
104
132
  }
105
133
 
106
134
  return side;
@@ -137,12 +165,9 @@ pub const Pokemon = struct {
137
165
  }
138
166
  assert(p.moves.len > 0 and p.moves.len <= 4);
139
167
  for (p.moves, 0..) |m, j| {
140
- pokemon.moves[j] = .{
141
- .id = m,
142
- .pp_ups = 3,
143
- // NB: PP can be at most 61 legally (though can overflow to 63)
144
- .pp = @intCast(u8, @min(Move.pp(m) / 5 * 8, 61)),
145
- };
168
+ pokemon.moves[j].id = m;
169
+ // NB: PP can be at most 61 legally (though can overflow to 63)
170
+ pokemon.moves[j].pp = @intCast(@min(Move.pp(m) / 5 * 8, 61));
146
171
  }
147
172
  pokemon.item = p.item;
148
173
  if (p.hp) |hp| {
@@ -153,16 +178,16 @@ pub const Pokemon = struct {
153
178
  pokemon.status = p.status;
154
179
  pokemon.types = species.types;
155
180
  pokemon.level = p.level;
156
- pokemon.dvs = DVs.from(p.dvs);
181
+ pokemon.dvs = DVs.from(p.species, p.dvs);
157
182
  return pokemon;
158
183
  }
159
184
 
160
185
  pub fn random(rand: *PSRNG, opt: Options) data.Pokemon {
161
- const s = @intToEnum(Species, rand.range(u8, 1, Species.size + 1));
186
+ const s: Species = @enumFromInt(rand.range(u8, 1, Species.size + 1));
162
187
  const species = Species.get(s);
163
188
  const lvl = if (rand.chance(u8, 1, 20)) rand.range(u8, 1, 99 + 1) else 100;
164
189
  // Pokémon Showdown does not support most items without in-battle held item effects
165
- const max_item = @enumToInt(if (showdown) Item.FlowerMail else Item.TM50);
190
+ const max_item = @intFromEnum(if (showdown) Item.FlowerMail else Item.TM50);
166
191
  const item = if (rand.chance(u8, 1, 10)) 0 else rand.range(u8, 1, max_item + 1);
167
192
 
168
193
  var stats: Stats(u16) = .{};
@@ -184,24 +209,23 @@ pub const Pokemon = struct {
184
209
  for (0..n) |i| {
185
210
  var m: Move = .None;
186
211
  sample: while (true) {
187
- m = @intToEnum(Move, rand.range(u8, 1, 164 + 1));
212
+ m = @enumFromInt(rand.range(u8, 1, 164 + 1));
188
213
  for (0..i) |j| if (ms[j].id == m) continue :sample;
189
214
  break;
190
215
  }
191
- const pp_ups =
216
+ const pp_ups: u8 =
192
217
  if (!opt.cleric and rand.chance(u8, 1, 10)) rand.range(u2, 0, 2 + 1) else 3;
193
218
  // NB: PP can be at most 61 legally (though can overflow to 63)
194
- const max_pp = @intCast(u8, Move.pp(m) + @as(u8, pp_ups) * @min(Move.pp(m) / 5, 7));
219
+ const max_pp: u8 = @intCast(Move.pp(m) + pp_ups * @min(Move.pp(m) / 5, 7));
195
220
  ms[i] = .{
196
221
  .id = m,
197
- .pp_ups = pp_ups,
198
222
  .pp = if (opt.cleric) max_pp else rand.range(u8, 0, max_pp + 1),
199
223
  };
200
224
  }
201
225
  return .{
202
226
  .species = s,
203
227
  .types = species.types,
204
- .dvs = DVs.from(dvs),
228
+ .dvs = DVs.from(s, dvs),
205
229
  .level = lvl,
206
230
  .stats = stats,
207
231
  .hp = if (opt.cleric) stats.hp else rand.range(u16, 0, stats.hp + 1),