@pkmn/engine 0.1.0-dev.c544e10e → 0.1.0-dev.cbdbb719

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 (46) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +41 -14
  3. package/build/pkg/addon.js +6 -7
  4. package/build/pkg/addon.js.map +1 -1
  5. package/build/pkg/data.d.ts +4 -4
  6. package/build/pkg/data.js.map +1 -1
  7. package/build/pkg/gen1.js.map +1 -1
  8. package/build/pkg/index.d.ts +3 -2
  9. package/build/pkg/index.js.map +1 -1
  10. package/build/pkg/protocol.js +4 -4
  11. package/build/pkg/protocol.js.map +1 -1
  12. package/build/test/display.js +8 -3
  13. package/build/test/display.js.map +1 -1
  14. package/build/tools/debug.js +2 -3
  15. package/build/tools/debug.js.map +1 -1
  16. package/build.zig +208 -81
  17. package/package.json +32 -21
  18. package/src/bin/install-pkmn-engine +25 -17
  19. package/src/lib/common/array.zig +77 -0
  20. package/src/lib/common/data.zig +4 -4
  21. package/src/lib/common/debug.zig +2 -2
  22. package/src/lib/common/js.zig +4 -2
  23. package/src/lib/common/optional.zig +14 -10
  24. package/src/lib/common/options.zig +2 -0
  25. package/src/lib/common/protocol.zig +73 -73
  26. package/src/lib/common/rational.zig +121 -27
  27. package/src/lib/common/rng.zig +7 -7
  28. package/src/lib/common/util.zig +50 -1
  29. package/src/lib/gen1/calc.zig +511 -131
  30. package/src/lib/gen1/chance.zig +374 -267
  31. package/src/lib/gen1/data/species.zig +1 -1
  32. package/src/lib/gen1/data.zig +15 -14
  33. package/src/lib/gen1/helpers.zig +96 -536
  34. package/src/lib/gen1/mechanics.zig +285 -189
  35. package/src/lib/gen2/calc.zig +34 -16
  36. package/src/lib/gen2/chance.zig +85 -492
  37. package/src/lib/gen2/data.zig +8 -7
  38. package/src/lib/gen2/generated.zig +1 -3
  39. package/src/lib/gen2/helpers.zig +41 -9
  40. package/src/lib/gen2/mechanics.zig +178 -121
  41. package/src/lib/{binding/node.zig → node.zig} +9 -12
  42. package/src/lib/pkmn.zig +32 -15
  43. package/src/lib/{binding/wasm.zig → wasm.zig} +2 -1
  44. package/src/test/display/pkmn.html.tmpl +5 -5
  45. package/src/lib/gen1/README.md +0 -894
  46. package/src/lib/gen2/README.md +0 -329
@@ -45,6 +45,7 @@ const Player = data.Player;
45
45
  const Result = data.Result;
46
46
 
47
47
  const PointerType = util.PointerType;
48
+ const isPointerTo = util.isPointerTo;
48
49
 
49
50
  const showdown = pkmn.options.showdown;
50
51
 
@@ -63,12 +64,12 @@ pub fn Battle(comptime RNG: anytype) type {
63
64
  _: [padding]u8 = .{0} ** padding,
64
65
 
65
66
  pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
66
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
67
+ assert(isPointerTo(self, Self));
67
68
  return &self.sides[@intFromEnum(player)];
68
69
  }
69
70
 
70
71
  pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
71
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
72
+ assert(isPointerTo(self, Self));
72
73
  return &self.sides[@intFromEnum(player.foe())];
73
74
  }
74
75
 
@@ -134,7 +135,7 @@ pub const Side = extern struct {
134
135
  }
135
136
 
136
137
  pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
137
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
138
+ assert(isPointerTo(self, Side));
138
139
  assert(slot > 0 and slot <= 6);
139
140
  const id = self.pokemon[slot - 1].position;
140
141
  assert(id > 0 and id <= 6);
@@ -142,7 +143,7 @@ pub const Side = extern struct {
142
143
  }
143
144
 
144
145
  pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
145
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
146
+ assert(isPointerTo(self, Side));
146
147
  return self.get(1);
147
148
  }
148
149
 
@@ -176,7 +177,7 @@ pub const ActivePokemon = extern struct {
176
177
  }
177
178
 
178
179
  pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
179
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
180
+ assert(isPointerTo(self, Pokemon));
180
181
  assert(mslot > 0 and mslot <= 4);
181
182
  assert(self.moves[mslot - 1].id != .None);
182
183
  return &self.moves[mslot - 1];
@@ -201,7 +202,7 @@ pub const Pokemon = extern struct {
201
202
  }
202
203
 
203
204
  pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
204
- assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
205
+ assert(isPointerTo(self, Pokemon));
205
206
  assert(mslot > 0 and mslot <= 4);
206
207
  assert(self.moves[mslot - 1].id != .None);
207
208
  return &self.moves[mslot - 1];
@@ -239,7 +240,7 @@ pub const DVs = packed struct(u16) {
239
240
  };
240
241
  const p: u6 = @intCast(1 + ((5 * @as(u8, (dvs.atk & 0b1000) | ((dvs.def & 0b1000)) >> 1 |
241
242
  ((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);
243
+ const t = @as(u8, dvs.def & 0b0011) + (@as(u8, dvs.atk & 0b0011) << 2);
243
244
  return .{ .gender = g, .pow = p, .type = Type.hiddenPower(t) };
244
245
  }
245
246
  };
@@ -7,8 +7,6 @@ const common = @import("../common/data.zig");
7
7
  const data = @import("data.zig");
8
8
  const mechanics = @import("mechanics.zig");
9
9
 
10
- const assert = std.debug.assert;
11
-
12
10
  const Player = common.Player;
13
11
  const Result = common.Result;
14
12
 
@@ -42,7 +40,7 @@ pub fn runMove(battle: anytype, player: Player, state: *State, options: anytype)
42
40
  var log = options.log;
43
41
 
44
42
  var side = battle.side(player);
45
- var volatiles = &side.active.volatiles;
43
+ const volatiles = &side.active.volatiles;
46
44
 
47
45
  const ident = battle.active(player);
48
46
  const foe_ident = battle.active(player.foe());
@@ -27,6 +27,8 @@ const Species = data.Species;
27
27
  const Stats = data.Stats;
28
28
  const Status = data.Status;
29
29
 
30
+ const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
31
+
30
32
  pub const Options = struct {
31
33
  cleric: bool = showdown,
32
34
  };
@@ -65,17 +67,47 @@ pub const Battle = struct {
65
67
  };
66
68
 
67
69
  pub fn prng(rand: *PSRNG) data.PRNG {
68
- // FIXME: what is max range in gen2?
69
70
  return .{
70
71
  .src = .{
71
72
  .seed = if (showdown)
72
73
  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
- },
74
+ else seed: {
75
+ // GLITCH: The initial RNG seed in Gen II link battles is heavily constrained
76
+ // https://www.smogon.com/forums/threads/rng-in-rby-link-battles.3746779
77
+ var seed = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0 };
78
+
79
+ // Bytes in seed can only range from 0-252, not 0-255
80
+ const max: u8 = 253;
81
+ // Instructions take multiples of 4 cycles to execute
82
+ var timer: u16 = 4 * rand.range(u16, 0, 16384);
83
+ var add: u8 = rand.range(u8, 0, 256);
84
+ var sub: u8 = rand.range(u8, 0, 256);
85
+ var carry: u8 = 0;
86
+ var div: u8 = 0;
87
+
88
+ var i: u8 = 0;
89
+ while (i < seed.len) {
90
+ div = @intCast(timer >> 8);
91
+ // This is effectively @addWithOverflow but with three operands
92
+ const result = @as(u16, add) + @as(u16, div) + @as(u16, carry);
93
+ add = @intCast(result & 255);
94
+ carry = @intFromBool(result > 255);
95
+ timer +%= 44;
96
+ div = @intCast(timer >> 8);
97
+ sub -%= div +% carry;
98
+
99
+ if (sub < max) {
100
+ seed[i] = sub;
101
+ i += 1;
102
+ timer +%= 152;
103
+ carry = 1;
104
+ } else {
105
+ timer +%= 132;
106
+ carry = 0;
107
+ }
108
+ }
109
+ break :seed seed;
110
+ },
79
111
  },
80
112
  };
81
113
  }
@@ -121,7 +153,7 @@ pub const Pokemon = struct {
121
153
  var pokemon = data.Pokemon{};
122
154
  pokemon.species = p.species;
123
155
  const species = Species.get(p.species);
124
- inline for (@typeInfo(@TypeOf(pokemon.stats)).Struct.fields) |field| {
156
+ inline for (@field(@typeInfo(@TypeOf(pokemon.stats)), @tagName(Struct)).fields) |field| {
125
157
  const hp = comptime std.mem.eql(u8, field.name, "hp");
126
158
  const spc =
127
159
  comptime std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
@@ -162,7 +194,7 @@ pub const Pokemon = struct {
162
194
 
163
195
  var stats: Stats(u16) = .{};
164
196
  const dvs = gen1.DVs.random(rand);
165
- inline for (@typeInfo(@TypeOf(stats)).Struct.fields) |field| {
197
+ inline for (@field(@typeInfo(@TypeOf(stats)), @tagName(Struct)).fields) |field| {
166
198
  const hp = std.mem.eql(u8, field.name, "hp");
167
199
  const spc = std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
168
200
  @field(stats, field.name) = Stats(u16).calc(