@pkmn/engine 0.1.0-dev.3de821b9 → 0.1.0-dev.3f3af84c
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/README.md +9 -6
- package/build/pkg/addon/browser.d.ts +3 -0
- package/build/pkg/addon/browser.js +47 -0
- package/build/pkg/addon/browser.js.map +1 -0
- package/build/pkg/addon/node.d.ts +3 -0
- package/build/pkg/addon/node.js +100 -0
- package/build/pkg/addon/node.js.map +1 -0
- package/build/pkg/addon/wasm.d.ts +2 -0
- package/build/pkg/addon/wasm.js +53 -0
- package/build/pkg/addon/wasm.js.map +1 -0
- package/build/pkg/addon.d.ts +25 -3
- package/build/pkg/addon.js +34 -65
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/layout.json +15 -2
- package/build/pkg/data/protocol.json +23 -9
- package/build/pkg/data.d.ts +23 -1
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.d.ts +15 -18
- package/build/pkg/gen1.js +11 -12
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +40 -90
- package/build/pkg/index.js +6 -63
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +20 -1
- package/build/pkg/protocol.js +105 -103
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +35 -69
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/debug.jsx +141 -0
- package/build/tools/display/debug.jsx.map +1 -0
- package/build/tools/display/index.js +142 -0
- package/build/tools/display/index.js.map +1 -0
- package/build/tools/display/ui.jsx +349 -0
- package/build/tools/display/ui.jsx.map +1 -0
- package/build/tools/display/util.js +33 -0
- package/build/tools/display/util.js.map +1 -0
- package/build.zig +330 -85
- package/package.json +53 -134
- package/src/bin/install-pkmn-engine +10 -7
- package/src/bin/pkmn-debug +1 -1
- package/src/lib/bindings/c.zig +255 -0
- package/src/lib/bindings/node.zig +121 -0
- package/src/lib/bindings/wasm.zig +59 -0
- package/src/lib/common/array.zig +77 -0
- package/src/lib/common/data.zig +8 -8
- package/src/lib/common/debug.zig +39 -8
- package/src/lib/common/js.zig +4 -2
- package/src/lib/common/optional.zig +13 -9
- package/src/lib/common/options.zig +4 -0
- package/src/lib/common/protocol.zig +44 -43
- package/src/lib/common/rational.zig +53 -51
- package/src/lib/common/rng.zig +5 -7
- package/src/lib/common/util.zig +50 -1
- package/src/lib/gen1/calc.zig +250 -111
- package/src/lib/gen1/chance.zig +130 -121
- package/src/lib/gen1/data/moves.zig +2 -4
- package/src/lib/gen1/data/species.zig +1 -3
- package/src/lib/gen1/data/types.zig +1 -2
- package/src/lib/gen1/data.zig +35 -38
- package/src/lib/gen1/helpers.zig +15 -27
- package/src/lib/gen1/mechanics.zig +118 -95
- package/src/lib/gen2/calc.zig +37 -27
- package/src/lib/gen2/chance.zig +86 -66
- package/src/lib/gen2/data/items.zig +1 -3
- package/src/lib/gen2/data/moves.zig +2 -4
- package/src/lib/gen2/data/species.zig +1 -3
- package/src/lib/gen2/data/types.zig +1 -2
- package/src/lib/gen2/data.zig +26 -29
- package/src/lib/gen2/generated.zig +18 -23
- package/src/lib/gen2/helpers.zig +9 -18
- package/src/lib/gen2/mechanics.zig +81 -81
- package/src/lib/node.zig +3 -116
- package/src/lib/pkmn.zig +14 -7
- package/src/lib/wasm.zig +13 -9
- package/src/tools/display/dom.ts +96 -0
- package/src/tools/display/ui.css +354 -0
- package/build/test/display.js +0 -405
- package/build/test/display.js.map +0 -1
- package/src/test/display/pkmn.html.tmpl +0 -368
package/src/lib/gen1/data.zig
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
1
|
const builtin = @import("builtin");
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
2
|
+
const calc = @import("calc.zig");
|
|
3
|
+
const chance = @import("chance.zig");
|
|
6
4
|
const data = @import("../common/data.zig");
|
|
5
|
+
const mechanics = @import("mechanics.zig");
|
|
6
|
+
const moves = @import("data/moves.zig");
|
|
7
|
+
const pkmn = @import("../pkmn.zig");
|
|
7
8
|
const protocol = @import("../common/protocol.zig");
|
|
8
9
|
const rng = @import("../common/rng.zig");
|
|
9
|
-
const util = @import("../common/util.zig");
|
|
10
|
-
|
|
11
|
-
const moves = @import("data/moves.zig");
|
|
12
10
|
const species = @import("data/species.zig");
|
|
11
|
+
const std = @import("std");
|
|
13
12
|
const types = @import("data/types.zig");
|
|
14
|
-
|
|
15
|
-
const calc = @import("calc.zig");
|
|
16
|
-
const chance = @import("chance.zig");
|
|
17
|
-
const mechanics = @import("mechanics.zig");
|
|
13
|
+
const util = @import("../common/util.zig");
|
|
18
14
|
|
|
19
15
|
const assert = std.debug.assert;
|
|
20
16
|
const expectEqual = std.testing.expectEqual;
|
|
@@ -47,6 +43,7 @@ const Player = data.Player;
|
|
|
47
43
|
const Result = data.Result;
|
|
48
44
|
|
|
49
45
|
const PointerType = util.PointerType;
|
|
46
|
+
const isPointerTo = util.isPointerTo;
|
|
50
47
|
|
|
51
48
|
const showdown = pkmn.options.showdown;
|
|
52
49
|
|
|
@@ -71,13 +68,13 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
71
68
|
|
|
72
69
|
/// Returns the `Side` for the given `player`.
|
|
73
70
|
pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
74
|
-
assert(
|
|
71
|
+
assert(isPointerTo(self, Self));
|
|
75
72
|
return &self.sides[@intFromEnum(player)];
|
|
76
73
|
}
|
|
77
74
|
|
|
78
75
|
/// Returns the `Side` of the opponent for the given `player`
|
|
79
76
|
pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
80
|
-
assert(
|
|
77
|
+
assert(isPointerTo(self, Self));
|
|
81
78
|
return &self.sides[@intFromEnum(player.foe())];
|
|
82
79
|
}
|
|
83
80
|
|
|
@@ -91,7 +88,7 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
91
88
|
self: anytype,
|
|
92
89
|
player: Player,
|
|
93
90
|
) PointerType(@TypeOf(self), MoveDetails) {
|
|
94
|
-
assert(
|
|
91
|
+
assert(isPointerTo(self, Self));
|
|
95
92
|
return &self.last_moves[@intFromEnum(player)];
|
|
96
93
|
}
|
|
97
94
|
|
|
@@ -142,7 +139,7 @@ pub const Side = extern struct {
|
|
|
142
139
|
|
|
143
140
|
/// Returns the stored `Pokemon` corresponding to the one-indexed party `slot`.
|
|
144
141
|
pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
|
|
145
|
-
assert(
|
|
142
|
+
assert(isPointerTo(self, Side));
|
|
146
143
|
assert(slot > 0 and slot <= 6);
|
|
147
144
|
const id = self.order[slot - 1];
|
|
148
145
|
assert(id > 0 and id <= 6);
|
|
@@ -151,7 +148,7 @@ pub const Side = extern struct {
|
|
|
151
148
|
|
|
152
149
|
/// Returns the stored `Pokemon` corresponding to the `active` Pokémon (slot 1).
|
|
153
150
|
pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
|
|
154
|
-
assert(
|
|
151
|
+
assert(isPointerTo(self, Side));
|
|
155
152
|
return self.get(1);
|
|
156
153
|
}
|
|
157
154
|
};
|
|
@@ -177,7 +174,7 @@ pub const ActivePokemon = extern struct {
|
|
|
177
174
|
|
|
178
175
|
/// Returns the active Pokémon's current move slot located at the one-indexed `mslot`.
|
|
179
176
|
pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
180
|
-
assert(
|
|
177
|
+
assert(isPointerTo(self, ActivePokemon));
|
|
181
178
|
assert(mslot > 0 and mslot <= 4);
|
|
182
179
|
assert(self.moves[mslot - 1].id != .None);
|
|
183
180
|
return &self.moves[mslot - 1];
|
|
@@ -207,7 +204,7 @@ pub const Pokemon = extern struct {
|
|
|
207
204
|
|
|
208
205
|
/// Returns the Pokémon's original move slot located at the one-indexed `mslot`.
|
|
209
206
|
pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
210
|
-
assert(
|
|
207
|
+
assert(isPointerTo(self, Pokemon));
|
|
211
208
|
assert(mslot > 0 and mslot <= 4);
|
|
212
209
|
assert(self.moves[mslot - 1].id != .None);
|
|
213
210
|
return &self.moves[mslot - 1];
|
|
@@ -255,7 +252,7 @@ pub const Status = enum(u8) {
|
|
|
255
252
|
|
|
256
253
|
pub const TOX = 0b10001000;
|
|
257
254
|
|
|
258
|
-
const
|
|
255
|
+
const SLEEP = 0b111;
|
|
259
256
|
|
|
260
257
|
/// Whether or not the status `num` is the same as `status`.
|
|
261
258
|
pub fn is(num: u8, status: Status) bool {
|
|
@@ -283,7 +280,7 @@ pub const Status = enum(u8) {
|
|
|
283
280
|
|
|
284
281
|
/// Returns the duration of a sleep status.
|
|
285
282
|
pub fn duration(num: u8) u3 {
|
|
286
|
-
return @intCast(num &
|
|
283
|
+
return @intCast(num & SLEEP);
|
|
287
284
|
}
|
|
288
285
|
|
|
289
286
|
/// Returns whether `num` reflects any status.
|
|
@@ -316,12 +313,12 @@ test Status {
|
|
|
316
313
|
try expect(Status.is(Status.slp(5), .SLP));
|
|
317
314
|
try expect(!Status.is(Status.slp(5), .EXT));
|
|
318
315
|
try expect(!Status.is(Status.slp(7), .PSN));
|
|
319
|
-
try expectEqual(5, Status.duration(Status.slp(5)));
|
|
316
|
+
try expectEqual(@as(u3, 5), Status.duration(Status.slp(5)));
|
|
320
317
|
try expect(Status.is(Status.slf(2), .SLP));
|
|
321
318
|
try expect(Status.is(Status.slf(2), .EXT));
|
|
322
319
|
try expect(Status.is(Status.TOX, .PSN));
|
|
323
320
|
try expect(Status.is(Status.TOX, .EXT));
|
|
324
|
-
try expectEqual(1, Status.duration(Status.slp(1)));
|
|
321
|
+
try expectEqual(@as(u3, 1), Status.duration(Status.slp(1)));
|
|
325
322
|
}
|
|
326
323
|
|
|
327
324
|
/// Bitfield representation of volatile statuses and associated data in Generation I.
|
|
@@ -405,16 +402,16 @@ test Volatiles {
|
|
|
405
402
|
try expect(!volatiles.Transform);
|
|
406
403
|
try expect(!volatiles.MultiHit);
|
|
407
404
|
|
|
408
|
-
try expectEqual(235, volatiles.state);
|
|
409
|
-
try expectEqual(42, volatiles.substitute);
|
|
410
|
-
try expectEqual(2, volatiles.disable_move);
|
|
411
|
-
try expectEqual(4, volatiles.disable_duration);
|
|
412
|
-
try expectEqual(2, volatiles.confusion);
|
|
413
|
-
try expectEqual(4, volatiles.toxic);
|
|
414
|
-
try expectEqual(3, volatiles.attacks);
|
|
405
|
+
try expectEqual(@as(u16, 235), volatiles.state);
|
|
406
|
+
try expectEqual(@as(u8, 42), volatiles.substitute);
|
|
407
|
+
try expectEqual(@as(u4, 2), volatiles.disable_move);
|
|
408
|
+
try expectEqual(@as(u4, 4), volatiles.disable_duration);
|
|
409
|
+
try expectEqual(@as(u3, 2), volatiles.confusion);
|
|
410
|
+
try expectEqual(@as(u5, 4), volatiles.toxic);
|
|
411
|
+
try expectEqual(@as(u3, 3), volatiles.attacks);
|
|
415
412
|
}
|
|
416
413
|
|
|
417
|
-
///
|
|
414
|
+
/// Representation of a Pokémon's stats in Generation I.
|
|
418
415
|
pub fn Stats(comptime T: type) type {
|
|
419
416
|
return extern struct {
|
|
420
417
|
hp: T = 0,
|
|
@@ -442,9 +439,9 @@ test Stats {
|
|
|
442
439
|
try expectEqual(0, stats.def);
|
|
443
440
|
|
|
444
441
|
var base = Species.get(.Gyarados).stats;
|
|
445
|
-
try expectEqual(127, Stats(u16).calc("hp", base.hp, 0, 5120, 38));
|
|
442
|
+
try expectEqual(@as(u16, 127), Stats(u16).calc("hp", base.hp, 0, 5120, 38));
|
|
446
443
|
base = Species.get(.Pidgeot).stats;
|
|
447
|
-
try expectEqual(279, Stats(u16).calc("spe", base.spe, 15, 63001, 100));
|
|
444
|
+
try expectEqual(@as(u16, 279), Stats(u16).calc("spe", base.spe, 15, 63001, 100));
|
|
448
445
|
}
|
|
449
446
|
|
|
450
447
|
/// Representation of a Pokémon's boosts in Generation I.
|
|
@@ -537,7 +534,7 @@ pub const Species = species.Species;
|
|
|
537
534
|
|
|
538
535
|
test Species {
|
|
539
536
|
try expectEqual(2, @intFromEnum(Species.Ivysaur));
|
|
540
|
-
try expectEqual(100, Species.get(.Mew).stats.def);
|
|
537
|
+
try expectEqual(@as(u8, 100), Species.get(.Mew).stats.def);
|
|
541
538
|
}
|
|
542
539
|
|
|
543
540
|
/// Representation of a Generation I type in Pokémon.
|
|
@@ -576,8 +573,8 @@ test Types {
|
|
|
576
573
|
try expectEqual(Effectiveness.Resisted, Type.effectiveness(.Fire, .Water));
|
|
577
574
|
try expectEqual(Effectiveness.Neutral, Type.effectiveness(.Normal, .Grass));
|
|
578
575
|
|
|
579
|
-
try expectEqual(3, Type.precedence(.Water, .Water));
|
|
580
|
-
try expectEqual(26, Type.precedence(.Bug, .Ghost));
|
|
576
|
+
try expectEqual(@as(u8, 3), Type.precedence(.Water, .Water));
|
|
577
|
+
try expectEqual(@as(u8, 26), Type.precedence(.Bug, .Ghost));
|
|
581
578
|
try expect(Type.precedence(.Poison, .Bug) > Type.precedence(.Poison, .Poison));
|
|
582
579
|
|
|
583
580
|
const t: Types = .{ .type1 = .Rock, .type2 = .Ground };
|
|
@@ -617,18 +614,18 @@ pub const DVs = struct {
|
|
|
617
614
|
|
|
618
615
|
test DVs {
|
|
619
616
|
var dvs: DVs = .{ .spc = 15, .spe = 15 };
|
|
620
|
-
try expectEqual(15, dvs.hp());
|
|
617
|
+
try expectEqual(@as(u4, 15), dvs.hp());
|
|
621
618
|
dvs = .{
|
|
622
619
|
.atk = 5,
|
|
623
620
|
.def = 15,
|
|
624
621
|
.spe = 13,
|
|
625
622
|
.spc = 13,
|
|
626
623
|
};
|
|
627
|
-
try expectEqual(15, dvs.hp());
|
|
624
|
+
try expectEqual(@as(u4, 15), dvs.hp());
|
|
628
625
|
dvs = .{
|
|
629
626
|
.def = 3,
|
|
630
627
|
.spe = 10,
|
|
631
628
|
.spc = 11,
|
|
632
629
|
};
|
|
633
|
-
try expectEqual(13, dvs.hp());
|
|
630
|
+
try expectEqual(@as(u4, 13), dvs.hp());
|
|
634
631
|
}
|
package/src/lib/gen1/helpers.zig
CHANGED
|
@@ -1,32 +1,26 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
1
|
const builtin = @import("builtin");
|
|
3
|
-
|
|
4
2
|
const common = @import("../common/data.zig");
|
|
3
|
+
const data = @import("data.zig");
|
|
5
4
|
const options = @import("../common/options.zig");
|
|
6
5
|
const protocol = @import("../common/protocol.zig");
|
|
7
6
|
const rng = @import("../common/rng.zig");
|
|
8
|
-
|
|
9
|
-
const
|
|
7
|
+
const std = @import("std");
|
|
8
|
+
const util = @import("../common/util.zig");
|
|
10
9
|
|
|
11
10
|
const assert = std.debug.assert;
|
|
12
|
-
|
|
13
11
|
const Choice = common.Choice;
|
|
14
|
-
const Player = common.Player;
|
|
15
|
-
|
|
16
|
-
const showdown = options.showdown;
|
|
17
|
-
const chance = options.chance;
|
|
18
|
-
|
|
19
|
-
const PSRNG = rng.PSRNG;
|
|
20
|
-
|
|
21
12
|
const DVs = data.DVs;
|
|
22
13
|
const Move = data.Move;
|
|
23
14
|
const MoveSlot = data.MoveSlot;
|
|
15
|
+
const PSRNG = rng.PSRNG;
|
|
16
|
+
const showdown = options.showdown;
|
|
24
17
|
const Species = data.Species;
|
|
25
18
|
const Stats = data.Stats;
|
|
26
|
-
const Status = data.Status;
|
|
27
19
|
|
|
28
20
|
const endian = builtin.cpu.arch.endian();
|
|
29
21
|
|
|
22
|
+
const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
|
|
23
|
+
|
|
30
24
|
/// Configuration options controlling the domain of valid Pokémon that can be generated by the
|
|
31
25
|
/// random generator helpers.
|
|
32
26
|
pub const Options = struct {
|
|
@@ -169,7 +163,7 @@ pub const Pokemon = struct {
|
|
|
169
163
|
var pokemon = data.Pokemon{};
|
|
170
164
|
pokemon.species = p.species;
|
|
171
165
|
const species = Species.get(p.species);
|
|
172
|
-
inline for (@typeInfo(@TypeOf(pokemon.stats))
|
|
166
|
+
inline for (@field(@typeInfo(@TypeOf(pokemon.stats)), @tagName(Struct)).fields) |field| {
|
|
173
167
|
const hp = comptime std.mem.eql(u8, field.name, "hp");
|
|
174
168
|
const spc =
|
|
175
169
|
comptime std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
|
|
@@ -205,7 +199,7 @@ pub const Pokemon = struct {
|
|
|
205
199
|
const lvl = if (rand.chance(u8, 1, 20)) rand.range(u8, 1, 99 + 1) else 100;
|
|
206
200
|
var stats: Stats(u16) = .{};
|
|
207
201
|
const dvs = DVs.random(rand);
|
|
208
|
-
inline for (@typeInfo(@TypeOf(stats))
|
|
202
|
+
inline for (@field(@typeInfo(@TypeOf(stats)), @tagName(Struct)).fields) |field| {
|
|
209
203
|
@field(stats, field.name) = Stats(u16).calc(
|
|
210
204
|
field.name,
|
|
211
205
|
@field(species.stats, field.name),
|
|
@@ -266,14 +260,7 @@ fn blocked(m: Move) bool {
|
|
|
266
260
|
fn durations(m: Move) bool {
|
|
267
261
|
// Any moves that have effects that result in duration tracking with -Dchance
|
|
268
262
|
return switch (Move.get(m).effect) {
|
|
269
|
-
.
|
|
270
|
-
.Bide,
|
|
271
|
-
.Sleep,
|
|
272
|
-
.Rage,
|
|
273
|
-
.Binding,
|
|
274
|
-
.Thrashing,
|
|
275
|
-
.ConfusionChance,
|
|
276
|
-
.Disable,
|
|
263
|
+
.Haze,
|
|
277
264
|
.Metronome,
|
|
278
265
|
=> true,
|
|
279
266
|
else => false,
|
|
@@ -314,8 +301,8 @@ pub fn diff(
|
|
|
314
301
|
|
|
315
302
|
var i: usize = 0;
|
|
316
303
|
while (i < size) : (i += 2) {
|
|
317
|
-
const val =
|
|
318
|
-
if (val !=
|
|
304
|
+
const val = util.bytesAsValue(u16, std.mem.asBytes(a)[i .. i + 2]).*;
|
|
305
|
+
if (val != util.bytesAsValue(u16, std.mem.asBytes(b)[i .. i + 2]).*) {
|
|
319
306
|
try w.writeByte(@intCast(i / 2));
|
|
320
307
|
try w.writeInt(u16, val, endian);
|
|
321
308
|
}
|
|
@@ -329,7 +316,8 @@ pub fn patch(battle: *data.Battle(data.PRNG), buf: []u8) void {
|
|
|
329
316
|
var i: usize = 0;
|
|
330
317
|
while (i < buf.len) : (i += 3) {
|
|
331
318
|
const off = @as(u16, @intCast(buf[i])) * 2;
|
|
332
|
-
const val = std.mem.readInt(u16, @ptrCast(buf[i + 1 .. i + 3]), endian);
|
|
333
|
-
|
|
319
|
+
const val = std.mem.readInt(u16, @as(*const [2]u8, @ptrCast(buf[i + 1 .. i + 3])), endian);
|
|
320
|
+
const bytes: *[2]u8 = @ptrCast(std.mem.asBytes(battle)[off .. off + 2]);
|
|
321
|
+
std.mem.writeInt(u16, bytes, val, endian);
|
|
334
322
|
}
|
|
335
323
|
}
|