@pkmn/engine 0.1.0-dev.77410aff → 0.1.0-dev.78dc891c
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 +40 -28
- 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 +110 -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 +26 -4
- package/build/pkg/addon.js +39 -71
- 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 +27 -6
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.d.ts +15 -18
- package/build/pkg/gen1.js +28 -19
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +40 -90
- package/build/pkg/index.js +23 -70
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +29 -1
- package/build/pkg/protocol.js +109 -107
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +84 -75
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/debug.jsx +66 -0
- package/build/tools/display/debug.jsx.map +1 -0
- package/build/tools/display/index.js +152 -0
- package/build/tools/display/index.js.map +1 -0
- package/build/tools/display/ui.jsx +360 -0
- package/build/tools/display/ui.jsx.map +1 -0
- package/build/tools/display/util.js +157 -0
- package/build/tools/display/util.js.map +1 -0
- package/build.zig +366 -148
- package/package.json +61 -133
- package/src/bin/install-pkmn-engine +47 -21
- package/src/bin/pkmn-debug +1 -1
- package/src/lib/bindings/c.zig +201 -0
- package/src/lib/{binding → bindings}/node.zig +9 -22
- package/src/lib/bindings/wasm.zig +51 -0
- package/src/lib/common/array.zig +70 -0
- package/src/lib/common/data.zig +4 -4
- package/src/lib/common/debug.zig +45 -29
- package/src/lib/common/js.zig +3 -7
- package/src/lib/common/optional.zig +27 -23
- package/src/lib/common/options.zig +6 -0
- package/src/lib/common/protocol.zig +205 -174
- package/src/lib/common/rational.zig +338 -255
- package/src/lib/common/rng.zig +7 -9
- package/src/lib/common/util.zig +53 -1
- package/src/lib/gen1/calc.zig +721 -172
- package/src/lib/gen1/chance.zig +486 -300
- package/src/lib/gen1/data/moves.zig +2 -4
- package/src/lib/gen1/data/species.zig +2 -4
- package/src/lib/gen1/data/types.zig +3 -4
- package/src/lib/gen1/data.zig +34 -34
- package/src/lib/gen1/helpers.zig +116 -561
- package/src/lib/gen1/mechanics.zig +402 -269
- package/src/lib/gen2/calc.zig +35 -28
- package/src/lib/gen2/chance.zig +111 -511
- 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 +7 -5
- package/src/lib/gen2/data.zig +31 -30
- package/src/lib/gen2/generated.zig +18 -23
- package/src/lib/gen2/helpers.zig +68 -39
- package/src/lib/gen2/mechanics.zig +215 -157
- package/src/lib/napi.h +2 -0
- package/src/lib/node.zig +14 -0
- package/src/lib/pkmn.zig +125 -29
- package/src/lib/wasm.zig +13 -0
- package/src/tools/display/dom.ts +108 -0
- package/src/tools/display/ui.css +354 -0
- package/build/test/display.js +0 -400
- package/build/test/display.js.map +0 -1
- package/src/lib/binding/wasm.zig +0 -12
- package/src/lib/gen1/README.md +0 -894
- package/src/lib/gen2/README.md +0 -329
- package/src/test/display/pkmn.html.tmpl +0 -368
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
//! Code generated by `tools/generate` - manual edits will be overwritten.
|
|
2
2
|
|
|
3
|
-
const std = @import("std");
|
|
4
|
-
|
|
5
|
-
const rng = @import("../../common/rng.zig");
|
|
6
3
|
const gen1 = @import("../../gen1/data.zig");
|
|
4
|
+
const rng = @import("../../common/rng.zig");
|
|
5
|
+
const std = @import("std");
|
|
7
6
|
|
|
8
7
|
const assert = std.debug.assert;
|
|
9
|
-
|
|
10
8
|
const percent = rng.Gen12.percent;
|
|
11
9
|
const Type = gen1.Type;
|
|
12
10
|
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
//! Code generated by `tools/generate` - manual edits will be overwritten.
|
|
2
2
|
|
|
3
|
-
const std = @import("std");
|
|
4
|
-
|
|
5
3
|
const gen1 = @import("../../gen1/data.zig");
|
|
4
|
+
const std = @import("std");
|
|
6
5
|
|
|
7
6
|
const assert = std.debug.assert;
|
|
8
|
-
|
|
9
7
|
const Stats = gen1.Stats;
|
|
10
8
|
const Types = gen1.Types;
|
|
11
9
|
|
|
@@ -1091,7 +1089,7 @@ pub const Species = enum(u8) {
|
|
|
1091
1089
|
/// The number of Pokémon species in this generation.
|
|
1092
1090
|
pub const size = 151;
|
|
1093
1091
|
|
|
1094
|
-
/// The Pokémon's critical hit
|
|
1092
|
+
/// The Pokémon's critical hit ratio out of 256.
|
|
1095
1093
|
pub fn chance(id: Species) u8 {
|
|
1096
1094
|
assert(id != .None);
|
|
1097
1095
|
return CHANCES[@intFromEnum(id) - 1];
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
//! Code generated by `tools/generate` - manual edits will be overwritten.
|
|
2
2
|
|
|
3
|
-
const std = @import("std");
|
|
4
|
-
|
|
5
3
|
const gen1 = @import("../../gen1/data.zig");
|
|
4
|
+
const std = @import("std");
|
|
6
5
|
|
|
7
6
|
const assert = std.debug.assert;
|
|
8
7
|
const Effectiveness = gen1.Effectiveness;
|
|
@@ -99,7 +98,7 @@ pub const Type = enum(u4) {
|
|
|
99
98
|
return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
/// The precedence order of Type `
|
|
101
|
+
/// The precedence order of Type `t1` vs. Type `t2`.
|
|
103
102
|
pub fn precedence(t1: Type, t2: Type) u8 {
|
|
104
103
|
for (PRECEDENCE, 0..) |matchup, i| {
|
|
105
104
|
if (matchup.type1 == t1 and matchup.type2 == t2) return @intCast(i);
|
|
@@ -109,7 +108,7 @@ pub const Type = enum(u4) {
|
|
|
109
108
|
};
|
|
110
109
|
|
|
111
110
|
/// Representation of a Pokémon's typing.
|
|
112
|
-
pub const Types = packed struct {
|
|
111
|
+
pub const Types = packed struct(u8) {
|
|
113
112
|
/// A Pokémon's primary type.
|
|
114
113
|
type1: Type = .Normal,
|
|
115
114
|
/// A Pokémon's secondary type (may be identical to its primary type).
|
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;
|
|
@@ -22,18 +18,21 @@ const expect = std.testing.expect;
|
|
|
22
18
|
|
|
23
19
|
/// The minimum size in bytes required to hold all Generation I choice options.
|
|
24
20
|
pub const MAX_CHOICES: usize = 9; // move 1..4, switch 2..6
|
|
25
|
-
/// The
|
|
26
|
-
/// At least as large as MAX_CHOICES.
|
|
21
|
+
/// The maximum number of bytes possibly logged by a single Generation I update.
|
|
27
22
|
pub const MAX_LOGS: usize = 180;
|
|
28
23
|
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
const ReleaseSmall: std.builtin.OptimizeMode =
|
|
25
|
+
if (@hasDecl(std.builtin.OptimizeMode, "ReleaseSmall")) .small else .ReleaseSmall;
|
|
26
|
+
|
|
27
|
+
/// The optimal size in bytes required to hold all Generation I choice options.
|
|
28
|
+
/// At least as large as MAX_CHOICES.
|
|
29
|
+
pub const CHOICES_SIZE = if (builtin.mode == ReleaseSmall)
|
|
31
30
|
MAX_CHOICES
|
|
32
31
|
else
|
|
33
32
|
std.math.ceilPowerOfTwo(usize, MAX_CHOICES) catch unreachable;
|
|
34
33
|
/// The optimal size in bytes required to hold the largest amount of log data possible from a
|
|
35
34
|
/// single Generation I update. At least as large as MAX_LOGS.
|
|
36
|
-
pub const LOGS_SIZE = if (builtin.mode ==
|
|
35
|
+
pub const LOGS_SIZE = if (builtin.mode == ReleaseSmall)
|
|
37
36
|
MAX_LOGS
|
|
38
37
|
else
|
|
39
38
|
std.math.ceilPowerOfTwo(usize, MAX_LOGS) catch unreachable;
|
|
@@ -47,6 +46,7 @@ const Player = data.Player;
|
|
|
47
46
|
const Result = data.Result;
|
|
48
47
|
|
|
49
48
|
const PointerType = util.PointerType;
|
|
49
|
+
const isPointerTo = util.isPointerTo;
|
|
50
50
|
|
|
51
51
|
const showdown = pkmn.options.showdown;
|
|
52
52
|
|
|
@@ -65,19 +65,19 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
65
65
|
/// The last damage dealt by either side.
|
|
66
66
|
last_damage: u16 = 0,
|
|
67
67
|
/// Details about the last move selected/used by each player required to detect desyncs.
|
|
68
|
-
last_moves: [2]MoveDetails =
|
|
68
|
+
last_moves: [2]MoveDetails = @splat(.{}),
|
|
69
69
|
/// The pseudo random number generator.
|
|
70
70
|
rng: RNG,
|
|
71
71
|
|
|
72
72
|
/// Returns the `Side` for the given `player`.
|
|
73
73
|
pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
74
|
-
assert(
|
|
74
|
+
assert(isPointerTo(self, Self));
|
|
75
75
|
return &self.sides[@intFromEnum(player)];
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/// Returns the `Side` of the opponent for the given `player`
|
|
79
79
|
pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
80
|
-
assert(
|
|
80
|
+
assert(isPointerTo(self, Self));
|
|
81
81
|
return &self.sides[@intFromEnum(player.foe())];
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -91,7 +91,7 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
91
91
|
self: anytype,
|
|
92
92
|
player: Player,
|
|
93
93
|
) PointerType(@TypeOf(self), MoveDetails) {
|
|
94
|
-
assert(
|
|
94
|
+
assert(isPointerTo(self, Self));
|
|
95
95
|
return &self.last_moves[@intFromEnum(player)];
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -112,7 +112,7 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
112
112
|
/// make (i.e. on the cartridge a soft-lock occurs).
|
|
113
113
|
///
|
|
114
114
|
/// This function will always return choices > 0 if `pkmn.options.showdown` is true.
|
|
115
|
-
pub fn choices(self: *Self, player: Player, request: Choice.Type, out: []Choice) u8 {
|
|
115
|
+
pub fn choices(self: *const Self, player: Player, request: Choice.Type, out: []Choice) u8 {
|
|
116
116
|
return mechanics.choices(self, player, request, out);
|
|
117
117
|
}
|
|
118
118
|
};
|
|
@@ -125,12 +125,12 @@ test Battle {
|
|
|
125
125
|
/// Representation of one side of a Generation I Pokémon battle.
|
|
126
126
|
pub const Side = extern struct {
|
|
127
127
|
/// The player's party in its original order
|
|
128
|
-
pokemon: [6]Pokemon =
|
|
128
|
+
pokemon: [6]Pokemon = @splat(.{}),
|
|
129
129
|
/// The active Pokémon for the side, zero initialized if the battle has yet to start.
|
|
130
130
|
/// Note that fainted Pokémon are still consider "active" until their replacement switches in.
|
|
131
131
|
active: ActivePokemon = .{},
|
|
132
132
|
/// One-based slot indexes reflecting the current order of the player's party.
|
|
133
|
-
order: [6]u8 =
|
|
133
|
+
order: [6]u8 = @splat(0),
|
|
134
134
|
/// The last move the player selected.
|
|
135
135
|
last_selected_move: Move = .None,
|
|
136
136
|
/// The last move the player used.
|
|
@@ -142,7 +142,7 @@ pub const Side = extern struct {
|
|
|
142
142
|
|
|
143
143
|
/// Returns the stored `Pokemon` corresponding to the one-indexed party `slot`.
|
|
144
144
|
pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
|
|
145
|
-
assert(
|
|
145
|
+
assert(isPointerTo(self, Side));
|
|
146
146
|
assert(slot > 0 and slot <= 6);
|
|
147
147
|
const id = self.order[slot - 1];
|
|
148
148
|
assert(id > 0 and id <= 6);
|
|
@@ -151,7 +151,7 @@ pub const Side = extern struct {
|
|
|
151
151
|
|
|
152
152
|
/// Returns the stored `Pokemon` corresponding to the `active` Pokémon (slot 1).
|
|
153
153
|
pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
|
|
154
|
-
assert(
|
|
154
|
+
assert(isPointerTo(self, Side));
|
|
155
155
|
return self.get(1);
|
|
156
156
|
}
|
|
157
157
|
};
|
|
@@ -169,7 +169,7 @@ pub const ActivePokemon = extern struct {
|
|
|
169
169
|
/// The active Pokémon's volatile statuses and associated data.
|
|
170
170
|
volatiles: Volatiles = .{},
|
|
171
171
|
/// The active Pokémon's current move slots.
|
|
172
|
-
moves: [4]MoveSlot =
|
|
172
|
+
moves: [4]MoveSlot = @splat(.{}),
|
|
173
173
|
|
|
174
174
|
comptime {
|
|
175
175
|
assert(@sizeOf(ActivePokemon) == 32);
|
|
@@ -177,7 +177,7 @@ pub const ActivePokemon = extern struct {
|
|
|
177
177
|
|
|
178
178
|
/// Returns the active Pokémon's current move slot located at the one-indexed `mslot`.
|
|
179
179
|
pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
180
|
-
assert(
|
|
180
|
+
assert(isPointerTo(self, ActivePokemon));
|
|
181
181
|
assert(mslot > 0 and mslot <= 4);
|
|
182
182
|
assert(self.moves[mslot - 1].id != .None);
|
|
183
183
|
return &self.moves[mslot - 1];
|
|
@@ -189,7 +189,7 @@ pub const Pokemon = extern struct {
|
|
|
189
189
|
/// The Pokémon's unmodified stats.
|
|
190
190
|
stats: Stats(u16) = .{},
|
|
191
191
|
/// The Pokémon's original stored move slots.
|
|
192
|
-
moves: [4]MoveSlot =
|
|
192
|
+
moves: [4]MoveSlot = @splat(.{}),
|
|
193
193
|
/// The Pokémon's current HP.
|
|
194
194
|
hp: u16 = 0,
|
|
195
195
|
/// The Pokémon's current status.
|
|
@@ -207,7 +207,7 @@ pub const Pokemon = extern struct {
|
|
|
207
207
|
|
|
208
208
|
/// Returns the Pokémon's original move slot located at the one-indexed `mslot`.
|
|
209
209
|
pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
210
|
-
assert(
|
|
210
|
+
assert(isPointerTo(self, Pokemon));
|
|
211
211
|
assert(mslot > 0 and mslot <= 4);
|
|
212
212
|
assert(self.moves[mslot - 1].id != .None);
|
|
213
213
|
return &self.moves[mslot - 1];
|
|
@@ -255,7 +255,7 @@ pub const Status = enum(u8) {
|
|
|
255
255
|
|
|
256
256
|
pub const TOX = 0b10001000;
|
|
257
257
|
|
|
258
|
-
const
|
|
258
|
+
const SLEEP = 0b111;
|
|
259
259
|
|
|
260
260
|
/// Whether or not the status `num` is the same as `status`.
|
|
261
261
|
pub fn is(num: u8, status: Status) bool {
|
|
@@ -283,7 +283,7 @@ pub const Status = enum(u8) {
|
|
|
283
283
|
|
|
284
284
|
/// Returns the duration of a sleep status.
|
|
285
285
|
pub fn duration(num: u8) u3 {
|
|
286
|
-
return @intCast(num &
|
|
286
|
+
return @intCast(num & SLEEP);
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
/// Returns whether `num` reflects any status.
|
|
@@ -409,12 +409,12 @@ test Volatiles {
|
|
|
409
409
|
try expectEqual(@as(u8, 42), volatiles.substitute);
|
|
410
410
|
try expectEqual(@as(u4, 2), volatiles.disable_move);
|
|
411
411
|
try expectEqual(@as(u4, 4), volatiles.disable_duration);
|
|
412
|
-
try expectEqual(@as(
|
|
412
|
+
try expectEqual(@as(u3, 2), volatiles.confusion);
|
|
413
413
|
try expectEqual(@as(u5, 4), volatiles.toxic);
|
|
414
|
-
try expectEqual(@as(
|
|
414
|
+
try expectEqual(@as(u3, 3), volatiles.attacks);
|
|
415
415
|
}
|
|
416
416
|
|
|
417
|
-
///
|
|
417
|
+
/// Representation of a Pokémon's stats in Generation I.
|
|
418
418
|
pub fn Stats(comptime T: type) type {
|
|
419
419
|
return extern struct {
|
|
420
420
|
hp: T = 0,
|