@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.
- package/LICENSE +1 -3
- package/README.md +95 -59
- package/build/pkg/addon.js +9 -9
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/ids.json +12 -12
- package/build/pkg/data/layout.json +27 -5
- package/build/pkg/data/protocol.json +69 -12
- package/build/pkg/data.d.ts +4 -4
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.d.ts +2 -1
- package/build/pkg/gen1.js +38 -20
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +7 -4
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +4 -2
- package/build/pkg/protocol.js +65 -44
- package/build/pkg/protocol.js.map +1 -1
- package/build/test/display.js +15 -6
- package/build/test/display.js.map +1 -1
- package/build/tools/debug.js +5 -4
- package/build/tools/debug.js.map +1 -1
- package/build.zig +148 -126
- package/package.json +53 -24
- package/src/bin/install-pkmn-engine +35 -22
- package/src/lib/common/battle.zig +17 -0
- package/src/lib/common/data.zig +19 -31
- package/src/lib/common/debug.zig +22 -13
- package/src/lib/common/js.zig +118 -0
- package/src/lib/common/optional.zig +67 -0
- package/src/lib/common/options.zig +11 -0
- package/src/lib/common/protocol.zig +906 -367
- package/src/lib/common/rational.zig +454 -0
- package/src/lib/common/rng.zig +35 -26
- package/src/lib/common/util.zig +12 -0
- package/src/lib/gen1/calc.zig +802 -0
- package/src/lib/gen1/chance.zig +1159 -0
- package/src/lib/gen1/data/moves.zig +202 -190
- package/src/lib/gen1/data/species.zig +5 -5
- package/src/lib/gen1/data/types.zig +10 -10
- package/src/lib/gen1/data.zig +104 -90
- package/src/lib/gen1/helpers.zig +140 -42
- package/src/lib/gen1/mechanics.zig +1135 -773
- package/src/lib/gen2/calc.zig +135 -0
- package/src/lib/gen2/chance.zig +895 -0
- package/src/lib/gen2/data/items.zig +14 -20
- package/src/lib/gen2/data/moves.zig +664 -570
- package/src/lib/gen2/data/species.zig +2 -2
- package/src/lib/gen2/data/types.zig +137 -34
- package/src/lib/gen2/data.zig +130 -92
- package/src/lib/gen2/generated.zig +806 -0
- package/src/lib/gen2/helpers.zig +50 -26
- package/src/lib/gen2/mechanics.zig +3568 -12
- package/src/lib/node.zig +131 -0
- package/src/lib/pkmn.zig +81 -5
- package/src/lib/wasm.zig +13 -0
- package/src/test/display/pkmn.html.tmpl +5 -5
- package/src/lib/binding/node.zig +0 -229
- package/src/lib/binding/wasm.zig +0 -10
- package/src/lib/gen1/README.md +0 -804
- package/src/lib/gen2/README.md +0 -309
package/src/lib/gen2/helpers.zig
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
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
|
-
|
|
142
|
-
|
|
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 = @
|
|
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 = @
|
|
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 = @
|
|
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(
|
|
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),
|