@pkmn/engine 0.1.0-dev.7963b917 → 0.1.0-dev.79957401
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 +70 -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/ids.json +12 -12
- package/build/pkg/data/layout.json +17 -4
- package/build/pkg/data/protocol.json +84 -13
- package/build/pkg/data.d.ts +27 -5
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.d.ts +15 -18
- package/build/pkg/gen1.js +30 -21
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +42 -91
- 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 +123 -102
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +84 -73
- 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 +397 -149
- package/package.json +62 -123
- package/src/bin/install-pkmn-engine +43 -22
- package/src/bin/pkmn-debug +1 -1
- package/src/lib/bindings/c.zig +201 -0
- package/src/lib/{binding → bindings}/node.zig +15 -32
- package/src/lib/bindings/wasm.zig +51 -0
- package/src/lib/common/array.zig +70 -0
- package/src/lib/common/data.zig +12 -24
- package/src/lib/common/debug.zig +46 -30
- package/src/lib/common/js.zig +3 -7
- package/src/lib/common/optional.zig +30 -24
- package/src/lib/common/options.zig +6 -0
- package/src/lib/common/protocol.zig +961 -450
- package/src/lib/common/rational.zig +341 -254
- package/src/lib/common/rng.zig +26 -19
- package/src/lib/common/util.zig +53 -1
- package/src/lib/gen1/calc.zig +726 -178
- package/src/lib/gen1/chance.zig +526 -324
- package/src/lib/gen1/data/moves.zig +193 -183
- package/src/lib/gen1/data/species.zig +4 -6
- package/src/lib/gen1/data/types.zig +9 -10
- package/src/lib/gen1/data.zig +78 -90
- package/src/lib/gen1/helpers.zig +114 -422
- package/src/lib/gen1/mechanics.zig +699 -615
- package/src/lib/gen2/calc.zig +150 -0
- package/src/lib/gen2/chance.zig +914 -0
- package/src/lib/gen2/data/items.zig +13 -21
- package/src/lib/gen2/data/moves.zig +664 -572
- package/src/lib/gen2/data/species.zig +2 -4
- package/src/lib/gen2/data/types.zig +139 -34
- package/src/lib/gen2/data.zig +131 -103
- package/src/lib/gen2/generated.zig +801 -0
- package/src/lib/gen2/helpers.zig +76 -51
- package/src/lib/gen2/mechanics.zig +3569 -29
- 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 -812
- package/src/lib/gen2/README.md +0 -308
- package/src/test/display/pkmn.html.tmpl +0 -368
package/src/lib/gen2/helpers.zig
CHANGED
|
@@ -1,31 +1,20 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
|
-
|
|
3
1
|
const common = @import("../common/data.zig");
|
|
2
|
+
const data = @import("data.zig");
|
|
3
|
+
const gen1 = @import("../gen1/data.zig");
|
|
4
4
|
const options = @import("../common/options.zig");
|
|
5
|
-
const protocol = @import("../common/protocol.zig");
|
|
6
5
|
const rng = @import("../common/rng.zig");
|
|
7
|
-
|
|
8
|
-
const gen1 = @import("../gen1/data.zig");
|
|
9
|
-
|
|
10
|
-
const data = @import("data.zig");
|
|
6
|
+
const std = @import("std");
|
|
11
7
|
|
|
12
8
|
const assert = std.debug.assert;
|
|
13
|
-
|
|
14
|
-
const expectEqual = std.testing.expectEqual;
|
|
15
|
-
|
|
16
9
|
const Choice = common.Choice;
|
|
17
|
-
|
|
18
|
-
const showdown = options.showdown;
|
|
19
|
-
|
|
20
|
-
const PSRNG = rng.PSRNG;
|
|
21
|
-
|
|
22
10
|
const DVs = data.DVs;
|
|
23
11
|
const Item = data.Item;
|
|
24
12
|
const Move = data.Move;
|
|
25
13
|
const MoveSlot = data.MoveSlot;
|
|
14
|
+
const PSRNG = rng.PSRNG;
|
|
15
|
+
const showdown = options.showdown;
|
|
26
16
|
const Species = data.Species;
|
|
27
17
|
const Stats = data.Stats;
|
|
28
|
-
const Status = data.Status;
|
|
29
18
|
|
|
30
19
|
pub const Options = struct {
|
|
31
20
|
cleric: bool = showdown,
|
|
@@ -48,7 +37,7 @@ pub const Battle = struct {
|
|
|
48
37
|
comptime rolls: anytype,
|
|
49
38
|
p1: []const Pokemon,
|
|
50
39
|
p2: []const Pokemon,
|
|
51
|
-
) data.Battle(rng.FixedRNG(
|
|
40
|
+
) data.Battle(rng.FixedRNG(2, rolls.len)) {
|
|
52
41
|
return .{
|
|
53
42
|
.rng = .{ .rolls = rolls },
|
|
54
43
|
.sides = .{ Side.init(p1), Side.init(p2) },
|
|
@@ -65,17 +54,47 @@ pub const Battle = struct {
|
|
|
65
54
|
};
|
|
66
55
|
|
|
67
56
|
pub fn prng(rand: *PSRNG) data.PRNG {
|
|
68
|
-
// FIXME: what is max range in gen2?
|
|
69
57
|
return .{
|
|
70
58
|
.src = .{
|
|
71
59
|
.seed = if (showdown)
|
|
72
60
|
rand.newSeed()
|
|
73
|
-
else
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
61
|
+
else seed: {
|
|
62
|
+
// GLITCH: The initial RNG seed in Gen II link battles is heavily constrained
|
|
63
|
+
// https://www.smogon.com/forums/threads/rng-in-rby-link-battles.3746779
|
|
64
|
+
var seed = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
65
|
+
|
|
66
|
+
// Bytes in seed can only range from 0-252, not 0-255
|
|
67
|
+
const max: u8 = 253;
|
|
68
|
+
// Instructions take multiples of 4 cycles to execute
|
|
69
|
+
var timer: u16 = 4 * rand.range(u16, 0, 16384);
|
|
70
|
+
var add: u8 = rand.range(u8, 0, 256);
|
|
71
|
+
var sub: u8 = rand.range(u8, 0, 256);
|
|
72
|
+
var carry: u8 = 0;
|
|
73
|
+
var div: u8 = 0;
|
|
74
|
+
|
|
75
|
+
var i: usize = 0;
|
|
76
|
+
while (i < seed.len) {
|
|
77
|
+
div = @intCast(timer >> 8);
|
|
78
|
+
// This is effectively @addWithOverflow but with three operands
|
|
79
|
+
const result = @as(u16, add) + @as(u16, div) + @as(u16, carry);
|
|
80
|
+
add = @intCast(result & 255);
|
|
81
|
+
carry = @intFromBool(result > 255);
|
|
82
|
+
timer +%= 44;
|
|
83
|
+
div = @intCast(timer >> 8);
|
|
84
|
+
sub -%= div +% carry;
|
|
85
|
+
|
|
86
|
+
if (sub < max) {
|
|
87
|
+
seed[i] = sub;
|
|
88
|
+
i += 1;
|
|
89
|
+
timer +%= 152;
|
|
90
|
+
carry = 1;
|
|
91
|
+
} else {
|
|
92
|
+
timer +%= 132;
|
|
93
|
+
carry = 0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
break :seed seed;
|
|
97
|
+
},
|
|
79
98
|
},
|
|
80
99
|
};
|
|
81
100
|
}
|
|
@@ -87,7 +106,7 @@ pub const Side = struct {
|
|
|
87
106
|
|
|
88
107
|
for (0..ps.len) |i| {
|
|
89
108
|
side.pokemon[i] = Pokemon.init(ps[i]);
|
|
90
|
-
|
|
109
|
+
side.pokemon[i].position = @as(u4, @intCast(i)) + 1;
|
|
91
110
|
}
|
|
92
111
|
return side;
|
|
93
112
|
}
|
|
@@ -98,7 +117,7 @@ pub const Side = struct {
|
|
|
98
117
|
|
|
99
118
|
for (0..n) |i| {
|
|
100
119
|
side.pokemon[i] = Pokemon.random(rand, opt);
|
|
101
|
-
side.pokemon[i].position = i + 1;
|
|
120
|
+
side.pokemon[i].position = @as(u4, @intCast(i)) + 1;
|
|
102
121
|
}
|
|
103
122
|
|
|
104
123
|
return side;
|
|
@@ -121,26 +140,28 @@ pub const Pokemon = struct {
|
|
|
121
140
|
var pokemon = data.Pokemon{};
|
|
122
141
|
pokemon.species = p.species;
|
|
123
142
|
const species = Species.get(p.species);
|
|
124
|
-
inline for (@typeInfo(@TypeOf(pokemon.stats))
|
|
125
|
-
|
|
143
|
+
inline for (if (@hasField(@TypeOf(@typeInfo(@TypeOf(pokemon.stats)).@"struct"), "fields"))
|
|
144
|
+
@typeInfo(@TypeOf(pokemon.stats)).@"struct".fields
|
|
145
|
+
else
|
|
146
|
+
@typeInfo(@TypeOf(pokemon.stats)).@"struct".field_names) |field|
|
|
147
|
+
{
|
|
148
|
+
const field_name = if (@hasField(@TypeOf(field), "name")) field.name else field;
|
|
149
|
+
const hp = comptime std.mem.eql(u8, field_name, "hp");
|
|
126
150
|
const spc =
|
|
127
|
-
comptime std.mem.eql(u8,
|
|
128
|
-
@field(pokemon.stats,
|
|
129
|
-
|
|
130
|
-
@field(species.stats,
|
|
131
|
-
if (hp) p.dvs.hp() else if (spc) p.dvs.spc else @field(p.dvs,
|
|
132
|
-
@field(p.stats,
|
|
151
|
+
comptime std.mem.eql(u8, field_name, "spa") or std.mem.eql(u8, field_name, "spd");
|
|
152
|
+
@field(pokemon.stats, field_name) = Stats(u16).calc(
|
|
153
|
+
field_name,
|
|
154
|
+
@field(species.stats, field_name),
|
|
155
|
+
if (hp) p.dvs.hp() else if (spc) p.dvs.spc else @field(p.dvs, field_name),
|
|
156
|
+
@field(p.stats, field_name),
|
|
133
157
|
p.level,
|
|
134
158
|
);
|
|
135
159
|
}
|
|
136
160
|
assert(p.moves.len > 0 and p.moves.len <= 4);
|
|
137
161
|
for (p.moves, 0..) |m, j| {
|
|
138
|
-
pokemon.moves[j] =
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
// NB: PP can be at most 61 legally (though can overflow to 63)
|
|
142
|
-
.pp = @intCast(@min(Move.pp(m) / 5 * 8, 61)),
|
|
143
|
-
};
|
|
162
|
+
pokemon.moves[j].id = m;
|
|
163
|
+
// NB: PP can be at most 61 legally (though can overflow to 63)
|
|
164
|
+
pokemon.moves[j].pp = @intCast(@min(Move.pp(m) / 5 * 8, 61));
|
|
144
165
|
}
|
|
145
166
|
pokemon.item = p.item;
|
|
146
167
|
if (p.hp) |hp| {
|
|
@@ -151,7 +172,7 @@ pub const Pokemon = struct {
|
|
|
151
172
|
pokemon.status = p.status;
|
|
152
173
|
pokemon.types = species.types;
|
|
153
174
|
pokemon.level = p.level;
|
|
154
|
-
pokemon.dvs = DVs.from(p.dvs);
|
|
175
|
+
pokemon.dvs = DVs.from(p.species, p.dvs);
|
|
155
176
|
return pokemon;
|
|
156
177
|
}
|
|
157
178
|
|
|
@@ -165,19 +186,24 @@ pub const Pokemon = struct {
|
|
|
165
186
|
|
|
166
187
|
var stats: Stats(u16) = .{};
|
|
167
188
|
const dvs = gen1.DVs.random(rand);
|
|
168
|
-
inline for (@typeInfo(@TypeOf(stats))
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
@
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
189
|
+
inline for (if (@hasField(@TypeOf(@typeInfo(@TypeOf(stats)).@"struct"), "fields"))
|
|
190
|
+
@typeInfo(@TypeOf(stats)).@"struct".fields
|
|
191
|
+
else
|
|
192
|
+
@typeInfo(@TypeOf(stats)).@"struct".field_names) |field|
|
|
193
|
+
{
|
|
194
|
+
const field_name = if (@hasField(@TypeOf(field), "name")) field.name else field;
|
|
195
|
+
const hp = std.mem.eql(u8, field_name, "hp");
|
|
196
|
+
const spc = std.mem.eql(u8, field_name, "spa") or std.mem.eql(u8, field_name, "spd");
|
|
197
|
+
@field(stats, field_name) = Stats(u16).calc(
|
|
198
|
+
field_name,
|
|
199
|
+
@field(species.stats, field_name),
|
|
200
|
+
if (hp) dvs.hp() else if (spc) dvs.spc else @field(dvs, field_name),
|
|
175
201
|
if (rand.chance(u8, 1, 20)) rand.range(u8, 0, 255 + 1) else 255,
|
|
176
202
|
lvl,
|
|
177
203
|
);
|
|
178
204
|
}
|
|
179
205
|
|
|
180
|
-
var ms
|
|
206
|
+
var ms: [4]MoveSlot = @splat(.{});
|
|
181
207
|
const n = if (rand.chance(u8, 1, 100)) rand.range(u4, 1, 3 + 1) else 4;
|
|
182
208
|
for (0..n) |i| {
|
|
183
209
|
var m: Move = .None;
|
|
@@ -192,14 +218,13 @@ pub const Pokemon = struct {
|
|
|
192
218
|
const max_pp: u8 = @intCast(Move.pp(m) + pp_ups * @min(Move.pp(m) / 5, 7));
|
|
193
219
|
ms[i] = .{
|
|
194
220
|
.id = m,
|
|
195
|
-
.pp_ups = pp_ups,
|
|
196
221
|
.pp = if (opt.cleric) max_pp else rand.range(u8, 0, max_pp + 1),
|
|
197
222
|
};
|
|
198
223
|
}
|
|
199
224
|
return .{
|
|
200
225
|
.species = s,
|
|
201
226
|
.types = species.types,
|
|
202
|
-
.dvs = DVs.from(dvs),
|
|
227
|
+
.dvs = DVs.from(s, dvs),
|
|
203
228
|
.level = lvl,
|
|
204
229
|
.stats = stats,
|
|
205
230
|
.hp = if (opt.cleric) stats.hp else rand.range(u16, 0, stats.hp + 1),
|