@pkmn/engine 0.1.0-dev.6158d5ad → 0.1.0-dev.62399ed5
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 +44 -19
- package/build/pkg/addon.js +6 -7
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/ids.json +12 -12
- package/build/pkg/data/layout.json +2 -2
- 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.js +2 -2
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +2 -1
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.js +61 -42
- package/build/pkg/protocol.js.map +1 -1
- package/build/test/display.js +2 -2
- 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 +102 -104
- package/package.json +43 -23
- package/src/bin/install-pkmn-engine +26 -18
- package/src/lib/common/data.zig +12 -24
- package/src/lib/common/debug.zig +2 -2
- package/src/lib/common/optional.zig +9 -2
- package/src/lib/common/options.zig +2 -0
- package/src/lib/common/protocol.zig +802 -327
- package/src/lib/common/rational.zig +113 -19
- package/src/lib/common/rng.zig +26 -17
- package/src/lib/gen1/calc.zig +219 -50
- package/src/lib/gen1/chance.zig +140 -125
- package/src/lib/gen1/data/moves.zig +192 -180
- package/src/lib/gen1/data/species.zig +3 -3
- package/src/lib/gen1/data/types.zig +7 -7
- package/src/lib/gen1/data.zig +50 -62
- package/src/lib/gen1/helpers.zig +148 -82
- package/src/lib/gen1/mechanics.zig +403 -417
- package/src/lib/gen2/calc.zig +143 -0
- package/src/lib/gen2/chance.zig +1315 -0
- package/src/lib/gen2/data/items.zig +12 -18
- package/src/lib/gen2/data/moves.zig +663 -569
- package/src/lib/gen2/data/species.zig +1 -1
- package/src/lib/gen2/data/types.zig +134 -31
- package/src/lib/gen2/data.zig +106 -79
- package/src/lib/gen2/generated.zig +806 -0
- package/src/lib/gen2/helpers.zig +45 -19
- package/src/lib/gen2/mechanics.zig +3587 -9
- package/src/lib/{binding/node.zig → node.zig} +10 -13
- package/src/lib/pkmn.zig +27 -12
- package/src/lib/{binding/wasm.zig → wasm.zig} +2 -1
- package/src/test/display/pkmn.html.tmpl +5 -5
- package/src/lib/gen1/README.md +0 -892
- package/src/lib/gen2/README.md +0 -308
|
@@ -43,8 +43,7 @@ pub fn Rational(comptime T: type) type {
|
|
|
43
43
|
/// Update the rational by multiplying its numerator by p and its denominator by q.
|
|
44
44
|
/// Both p and q must be >= 1, and if computable at comptime must have no common factors.
|
|
45
45
|
pub fn update(r: *Self, p: anytype, q: anytype) Error!void {
|
|
46
|
-
//
|
|
47
|
-
// std.debug.print("({d}/{d}) * ", .{p, q});
|
|
46
|
+
// std.debug.print("({d}/{d}) * ", .{ p, q }); // DEBUG
|
|
48
47
|
assert(p >= 1);
|
|
49
48
|
assert(q >= 1);
|
|
50
49
|
|
|
@@ -185,16 +184,16 @@ pub fn Rational(comptime T: type) type {
|
|
|
185
184
|
try writer.print("{d}/{d}", .{ self.p, self.q });
|
|
186
185
|
}
|
|
187
186
|
|
|
188
|
-
|
|
187
|
+
fn multiplication(r: *Self, p: anytype, q: anytype) !void {
|
|
189
188
|
r.p = try std.math.mul(T, r.p, p);
|
|
190
189
|
r.q = try std.math.mul(T, r.q, q);
|
|
191
190
|
}
|
|
192
191
|
|
|
193
|
-
|
|
192
|
+
fn addition(r: *Self, p: anytype, q: anytype) !void {
|
|
194
193
|
// (a/b) + (c/d) = (ad+bc)/(bd)
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
194
|
+
const d = try std.math.mul(T, r.q, q);
|
|
195
|
+
const n1 = try std.math.mul(T, r.p, q);
|
|
196
|
+
const n2 = try std.math.mul(T, r.q, p);
|
|
198
197
|
|
|
199
198
|
r.p = try std.math.add(T, n1, n2);
|
|
200
199
|
r.q = d;
|
|
@@ -202,23 +201,81 @@ pub fn Rational(comptime T: type) type {
|
|
|
202
201
|
};
|
|
203
202
|
}
|
|
204
203
|
|
|
205
|
-
// https://
|
|
206
|
-
|
|
204
|
+
// https://lemire.me/blog/greatest-common-divisor-the-extended-euclidean-algorithm-and-speed/
|
|
205
|
+
fn gcd(p: anytype, q: anytype) @TypeOf(p, q) {
|
|
207
206
|
assert(p >= 1);
|
|
208
207
|
assert(q >= 1);
|
|
209
208
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
const T = @TypeOf(p, q);
|
|
210
|
+
switch (@typeInfo(T)) {
|
|
211
|
+
.Int => {
|
|
212
|
+
var u: T = undefined;
|
|
213
|
+
var v: T = undefined;
|
|
214
|
+
if (p < q) {
|
|
215
|
+
u = q;
|
|
216
|
+
v = p;
|
|
217
|
+
} else {
|
|
218
|
+
u = p;
|
|
219
|
+
v = q;
|
|
220
|
+
}
|
|
221
|
+
assert(v <= u);
|
|
222
|
+
u %= v;
|
|
223
|
+
if (u == 0) return v;
|
|
224
|
+
|
|
225
|
+
const zu = @ctz(u);
|
|
226
|
+
const zv = @ctz(v);
|
|
227
|
+
const shift = @min(zu, zv);
|
|
228
|
+
u >>= @intCast(zu);
|
|
229
|
+
v >>= @intCast(zv);
|
|
230
|
+
|
|
231
|
+
while (true) {
|
|
232
|
+
const diff = u -% v;
|
|
233
|
+
if (u > v) {
|
|
234
|
+
u = v;
|
|
235
|
+
v = diff;
|
|
236
|
+
} else {
|
|
237
|
+
v -= u;
|
|
238
|
+
}
|
|
239
|
+
if (diff != 0) v >>= @intCast(@ctz(diff));
|
|
240
|
+
if (v == 0) break;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const result = u << @intCast(shift);
|
|
244
|
+
assert(result > 0);
|
|
245
|
+
return result;
|
|
246
|
+
},
|
|
247
|
+
else => {
|
|
248
|
+
var a = p;
|
|
249
|
+
var b = q;
|
|
250
|
+
var c: T = undefined;
|
|
251
|
+
|
|
252
|
+
while (b != 0) {
|
|
253
|
+
c = b;
|
|
254
|
+
b = @mod(a, b);
|
|
255
|
+
a = c;
|
|
256
|
+
}
|
|
213
257
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
a = c;
|
|
258
|
+
assert(a > 0);
|
|
259
|
+
return a;
|
|
260
|
+
},
|
|
218
261
|
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
test gcd {
|
|
265
|
+
const seed = if (@hasDecl(std.testing, "random_seed")) std.testing.random_seed else 0x12345678;
|
|
266
|
+
var prng = std.Random.DefaultPrng.init(seed);
|
|
267
|
+
var random = prng.random();
|
|
219
268
|
|
|
220
|
-
|
|
221
|
-
|
|
269
|
+
for (0..1000) |_| {
|
|
270
|
+
const a = random.int(u32);
|
|
271
|
+
const b = random.int(u32);
|
|
272
|
+
if (a == 0 or b == 0) continue;
|
|
273
|
+
|
|
274
|
+
try expectEqual(
|
|
275
|
+
gcd(a, b),
|
|
276
|
+
@as(u32, @intFromFloat(gcd(@as(f64, @floatFromInt(a)), @as(f64, @floatFromInt(b))))),
|
|
277
|
+
);
|
|
278
|
+
}
|
|
222
279
|
}
|
|
223
280
|
|
|
224
281
|
fn doTurn(r: anytype) !void {
|
|
@@ -234,6 +291,8 @@ test Rational {
|
|
|
234
291
|
var r: Rational(t) = .{};
|
|
235
292
|
|
|
236
293
|
var c: t = 128;
|
|
294
|
+
_ = &c;
|
|
295
|
+
|
|
237
296
|
try r.update(c, 256);
|
|
238
297
|
try doTurn(&r);
|
|
239
298
|
|
|
@@ -275,7 +334,7 @@ pub const BigRational = struct {
|
|
|
275
334
|
/// Create a new BigRational wrapper. A small amount of memory will be allocated on
|
|
276
335
|
/// initialization. Not default initialized to 1 - you must explicitly `reset` first.
|
|
277
336
|
pub fn init(alloc: std.mem.Allocator) !BigRational {
|
|
278
|
-
return
|
|
337
|
+
return .{ .val = try std.math.big.Rational.init(alloc) };
|
|
279
338
|
}
|
|
280
339
|
|
|
281
340
|
/// Frees all memory associated with a rational.
|
|
@@ -320,6 +379,8 @@ test BigRational {
|
|
|
320
379
|
try r.reset();
|
|
321
380
|
|
|
322
381
|
var c: u8 = 128;
|
|
382
|
+
_ = &c;
|
|
383
|
+
|
|
323
384
|
try r.update(c, 256);
|
|
324
385
|
try doTurn(&r);
|
|
325
386
|
|
|
@@ -351,3 +412,36 @@ test BigRational {
|
|
|
351
412
|
try s.setRatio(71, 78);
|
|
352
413
|
try expect((try s.order(r.val)) == .eq);
|
|
353
414
|
}
|
|
415
|
+
|
|
416
|
+
test "minimum" {
|
|
417
|
+
// TODO: ziglang/zig#21069
|
|
418
|
+
if (builtin.mode == .ReleaseFast or builtin.mode == .ReleaseSmall) {
|
|
419
|
+
return error.SkipZigTest;
|
|
420
|
+
}
|
|
421
|
+
var r = try BigRational.init(std.testing.allocator);
|
|
422
|
+
defer r.deinit();
|
|
423
|
+
var s = try std.math.big.Rational.init(std.testing.allocator);
|
|
424
|
+
defer s.deinit();
|
|
425
|
+
|
|
426
|
+
try r.reset();
|
|
427
|
+
|
|
428
|
+
try r.update(1, 2); // Speed Tie
|
|
429
|
+
for (0..2) |_| {
|
|
430
|
+
try r.update(1, 2); // Confusion
|
|
431
|
+
try r.update(1, 2); // Infatuation
|
|
432
|
+
try r.update(3, 4); // Paralysis
|
|
433
|
+
// Population Bomb
|
|
434
|
+
for (0..10) |_| {
|
|
435
|
+
try r.update(9, 10); // Accuracy
|
|
436
|
+
try r.update(1, 15); // Damage roll
|
|
437
|
+
try r.update(1, 24); // Critical Hit
|
|
438
|
+
try r.update(9, 10); // King's Rock non-proc
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const ZEROS = std.math.pow(u310, 10, 31);
|
|
443
|
+
const n = 36472996377170786403;
|
|
444
|
+
const d: u310 = 146267071761884981524886149560653378220687632500762654519853056 * ZEROS;
|
|
445
|
+
try s.setRatio(n, d);
|
|
446
|
+
try expect((try s.order(r.val)) == .eq);
|
|
447
|
+
}
|
package/src/lib/common/rng.zig
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
2
|
|
|
3
|
-
const options = @import("
|
|
3
|
+
const options = @import("options.zig");
|
|
4
4
|
|
|
5
5
|
const assert = std.debug.assert;
|
|
6
6
|
const expectEqual = std.testing.expectEqual;
|
|
@@ -25,6 +25,11 @@ pub fn PRNG(comptime gen: comptime_int) type {
|
|
|
25
25
|
pub fn next(self: *Self) Output(gen) {
|
|
26
26
|
return self.src.next();
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
pub fn advance(self: *Self, n: usize) void {
|
|
30
|
+
if (!options.advance) return;
|
|
31
|
+
for (0..n) |_| self.src.advance();
|
|
32
|
+
}
|
|
28
33
|
};
|
|
29
34
|
}
|
|
30
35
|
|
|
@@ -61,11 +66,15 @@ pub const PSRNG = extern struct {
|
|
|
61
66
|
(@as(u64, self.range(u16, 0, 0x10000)) << 16) |
|
|
62
67
|
(@as(u64, self.range(u16, 0, 0x10000)));
|
|
63
68
|
}
|
|
69
|
+
|
|
70
|
+
pub fn Bound(comptime T: type) type {
|
|
71
|
+
return std.math.IntFittingRange(0, std.math.maxInt(T) + 1);
|
|
72
|
+
}
|
|
64
73
|
};
|
|
65
74
|
|
|
66
75
|
test PSRNG {
|
|
67
|
-
var psrng =
|
|
68
|
-
try expectEqual(
|
|
76
|
+
var psrng: PSRNG = .{ .src = .{ .seed = 0x0001000200030004 } };
|
|
77
|
+
try expectEqual(121, psrng.range(u8, 0, 256));
|
|
69
78
|
try expectEqual(false, psrng.chance(u8, 128, 256)); // 226 < 128
|
|
70
79
|
}
|
|
71
80
|
|
|
@@ -79,7 +88,7 @@ pub const Gen12 = extern struct {
|
|
|
79
88
|
assert(@sizeOf(Gen12) == 10);
|
|
80
89
|
}
|
|
81
90
|
|
|
82
|
-
pub fn percent(p:
|
|
91
|
+
pub fn percent(comptime p: comptime_int) u8 {
|
|
83
92
|
return @intCast((@as(u16, p) * 0xFF) / 100);
|
|
84
93
|
}
|
|
85
94
|
|
|
@@ -89,18 +98,22 @@ pub const Gen12 = extern struct {
|
|
|
89
98
|
self.index = (self.index + 1) % 9;
|
|
90
99
|
return val;
|
|
91
100
|
}
|
|
101
|
+
|
|
102
|
+
pub fn advance(self: *Gen12) void {
|
|
103
|
+
_ = self.next();
|
|
104
|
+
}
|
|
92
105
|
};
|
|
93
106
|
|
|
94
107
|
test Gen12 {
|
|
95
108
|
const expected = [_]u8{ 6, 11, 16, 21, 26, 31, 36, 41, 46, 31, 56, 81 };
|
|
96
|
-
var rng =
|
|
109
|
+
var rng: Gen12 = .{ .seed = .{ 1, 2, 3, 4, 5, 6, 7, 8, 9 } };
|
|
97
110
|
for (expected) |e| {
|
|
98
111
|
try expectEqual(e, rng.next());
|
|
99
112
|
}
|
|
100
113
|
|
|
101
|
-
try expectEqual(
|
|
102
|
-
try expectEqual(
|
|
103
|
-
try expectEqual(
|
|
114
|
+
try expectEqual(16, Gen12.percent(6) + 1);
|
|
115
|
+
try expectEqual(16, Gen12.percent(7) - 1);
|
|
116
|
+
try expectEqual(128, Gen12.percent(50) + 1);
|
|
104
117
|
}
|
|
105
118
|
|
|
106
119
|
// https://pkmn.cc/pokeemerald/src/random.c
|
|
@@ -129,7 +142,7 @@ test Gen34 {
|
|
|
129
142
|
.{ 0x80000000, 5, 0x0E425287 }, .{ 0x80000000, 10, 0x6F2CF4B2 },
|
|
130
143
|
};
|
|
131
144
|
for (data) |d| {
|
|
132
|
-
var rng =
|
|
145
|
+
var rng: Gen34 = .{ .seed = d[0] };
|
|
133
146
|
for (0..d[1]) |_| _ = rng.next();
|
|
134
147
|
try expectEqual(d[2], rng.seed);
|
|
135
148
|
}
|
|
@@ -161,7 +174,7 @@ test Gen56 {
|
|
|
161
174
|
.{ 0x8000000000000000, 10, 0xE7795501267F125A },
|
|
162
175
|
};
|
|
163
176
|
for (data) |d| {
|
|
164
|
-
var rng =
|
|
177
|
+
var rng: Gen56 = .{ .seed = d[0] };
|
|
165
178
|
for (0..d[1]) |_| _ = rng.next();
|
|
166
179
|
try expectEqual(d[2], rng.seed);
|
|
167
180
|
}
|
|
@@ -188,7 +201,7 @@ pub fn FixedRNG(comptime gen: comptime_int, comptime len: usize) type {
|
|
|
188
201
|
for (0..n) |_| _ = self.next();
|
|
189
202
|
}
|
|
190
203
|
|
|
191
|
-
pub fn range(self: *Self, comptime T: type, from: T, to: Bound(T)) T {
|
|
204
|
+
pub fn range(self: *Self, comptime T: type, from: T, to: PSRNG.Bound(T)) T {
|
|
192
205
|
assert(showdown);
|
|
193
206
|
return @intCast(@as(u64, self.next()) * (to - from) / divisor + from);
|
|
194
207
|
}
|
|
@@ -197,7 +210,7 @@ pub fn FixedRNG(comptime gen: comptime_int, comptime len: usize) type {
|
|
|
197
210
|
self: *Self,
|
|
198
211
|
comptime T: type,
|
|
199
212
|
numerator: T,
|
|
200
|
-
denominator: Bound(T),
|
|
213
|
+
denominator: PSRNG.Bound(T),
|
|
201
214
|
) bool {
|
|
202
215
|
assert(showdown);
|
|
203
216
|
assert(denominator > 0);
|
|
@@ -213,7 +226,7 @@ pub fn FixedRNG(comptime gen: comptime_int, comptime len: usize) type {
|
|
|
213
226
|
test FixedRNG {
|
|
214
227
|
const Type = if (showdown) u32 else u8;
|
|
215
228
|
const expected = [_]Type{ 42, 255, 0 };
|
|
216
|
-
var rng
|
|
229
|
+
var rng: FixedRNG(1, expected.len) = .{ .rolls = expected };
|
|
217
230
|
for (expected) |e| {
|
|
218
231
|
try expectEqual(e, rng.next());
|
|
219
232
|
}
|
|
@@ -228,7 +241,3 @@ fn Output(comptime gen: comptime_int) type {
|
|
|
228
241
|
else => unreachable,
|
|
229
242
|
};
|
|
230
243
|
}
|
|
231
|
-
|
|
232
|
-
fn Bound(comptime T: type) type {
|
|
233
|
-
return std.math.IntFittingRange(0, std.math.maxInt(T) + 1);
|
|
234
|
-
}
|