@pkmn/engine 0.1.0-dev.c5fe6d07 → 0.1.0-dev.cbdbb719
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 +46 -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 +3 -2
- 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 +8 -3
- 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 +232 -99
- package/package.json +46 -23
- package/src/bin/install-pkmn-engine +25 -17
- package/src/lib/common/array.zig +77 -0
- package/src/lib/common/data.zig +12 -24
- package/src/lib/common/debug.zig +2 -2
- package/src/lib/common/js.zig +4 -2
- package/src/lib/common/optional.zig +21 -10
- package/src/lib/common/options.zig +2 -0
- package/src/lib/common/protocol.zig +807 -327
- package/src/lib/common/rational.zig +125 -31
- package/src/lib/common/rng.zig +22 -13
- package/src/lib/common/util.zig +50 -1
- package/src/lib/gen1/calc.zig +514 -135
- package/src/lib/gen1/chance.zig +407 -284
- 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 +46 -57
- package/src/lib/gen1/helpers.zig +95 -550
- package/src/lib/gen1/mechanics.zig +571 -516
- package/src/lib/gen2/calc.zig +161 -0
- package/src/lib/gen2/chance.zig +907 -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 +107 -79
- package/src/lib/gen2/generated.zig +806 -0
- package/src/lib/gen2/helpers.zig +49 -21
- package/src/lib/gen2/mechanics.zig +3563 -9
- package/src/lib/{binding/node.zig → node.zig} +10 -13
- package/src/lib/pkmn.zig +32 -15
- 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
package/src/lib/gen2/helpers.zig
CHANGED
|
@@ -27,6 +27,8 @@ const Species = data.Species;
|
|
|
27
27
|
const Stats = data.Stats;
|
|
28
28
|
const Status = data.Status;
|
|
29
29
|
|
|
30
|
+
const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
|
|
31
|
+
|
|
30
32
|
pub const Options = struct {
|
|
31
33
|
cleric: bool = showdown,
|
|
32
34
|
};
|
|
@@ -48,7 +50,7 @@ pub const Battle = struct {
|
|
|
48
50
|
comptime rolls: anytype,
|
|
49
51
|
p1: []const Pokemon,
|
|
50
52
|
p2: []const Pokemon,
|
|
51
|
-
) data.Battle(rng.FixedRNG(
|
|
53
|
+
) data.Battle(rng.FixedRNG(2, rolls.len)) {
|
|
52
54
|
return .{
|
|
53
55
|
.rng = .{ .rolls = rolls },
|
|
54
56
|
.sides = .{ Side.init(p1), Side.init(p2) },
|
|
@@ -65,17 +67,47 @@ pub const Battle = struct {
|
|
|
65
67
|
};
|
|
66
68
|
|
|
67
69
|
pub fn prng(rand: *PSRNG) data.PRNG {
|
|
68
|
-
// FIXME: what is max range in gen2?
|
|
69
70
|
return .{
|
|
70
71
|
.src = .{
|
|
71
72
|
.seed = if (showdown)
|
|
72
73
|
rand.newSeed()
|
|
73
|
-
else
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
else seed: {
|
|
75
|
+
// GLITCH: The initial RNG seed in Gen II link battles is heavily constrained
|
|
76
|
+
// https://www.smogon.com/forums/threads/rng-in-rby-link-battles.3746779
|
|
77
|
+
var seed = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
78
|
+
|
|
79
|
+
// Bytes in seed can only range from 0-252, not 0-255
|
|
80
|
+
const max: u8 = 253;
|
|
81
|
+
// Instructions take multiples of 4 cycles to execute
|
|
82
|
+
var timer: u16 = 4 * rand.range(u16, 0, 16384);
|
|
83
|
+
var add: u8 = rand.range(u8, 0, 256);
|
|
84
|
+
var sub: u8 = rand.range(u8, 0, 256);
|
|
85
|
+
var carry: u8 = 0;
|
|
86
|
+
var div: u8 = 0;
|
|
87
|
+
|
|
88
|
+
var i: u8 = 0;
|
|
89
|
+
while (i < seed.len) {
|
|
90
|
+
div = @intCast(timer >> 8);
|
|
91
|
+
// This is effectively @addWithOverflow but with three operands
|
|
92
|
+
const result = @as(u16, add) + @as(u16, div) + @as(u16, carry);
|
|
93
|
+
add = @intCast(result & 255);
|
|
94
|
+
carry = @intFromBool(result > 255);
|
|
95
|
+
timer +%= 44;
|
|
96
|
+
div = @intCast(timer >> 8);
|
|
97
|
+
sub -%= div +% carry;
|
|
98
|
+
|
|
99
|
+
if (sub < max) {
|
|
100
|
+
seed[i] = sub;
|
|
101
|
+
i += 1;
|
|
102
|
+
timer +%= 152;
|
|
103
|
+
carry = 1;
|
|
104
|
+
} else {
|
|
105
|
+
timer +%= 132;
|
|
106
|
+
carry = 0;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
break :seed seed;
|
|
110
|
+
},
|
|
79
111
|
},
|
|
80
112
|
};
|
|
81
113
|
}
|
|
@@ -87,7 +119,7 @@ pub const Side = struct {
|
|
|
87
119
|
|
|
88
120
|
for (0..ps.len) |i| {
|
|
89
121
|
side.pokemon[i] = Pokemon.init(ps[i]);
|
|
90
|
-
|
|
122
|
+
side.pokemon[i].position = @as(u4, @intCast(i)) + 1;
|
|
91
123
|
}
|
|
92
124
|
return side;
|
|
93
125
|
}
|
|
@@ -98,7 +130,7 @@ pub const Side = struct {
|
|
|
98
130
|
|
|
99
131
|
for (0..n) |i| {
|
|
100
132
|
side.pokemon[i] = Pokemon.random(rand, opt);
|
|
101
|
-
side.pokemon[i].position = i + 1;
|
|
133
|
+
side.pokemon[i].position = @as(u4, @intCast(i)) + 1;
|
|
102
134
|
}
|
|
103
135
|
|
|
104
136
|
return side;
|
|
@@ -121,7 +153,7 @@ pub const Pokemon = struct {
|
|
|
121
153
|
var pokemon = data.Pokemon{};
|
|
122
154
|
pokemon.species = p.species;
|
|
123
155
|
const species = Species.get(p.species);
|
|
124
|
-
inline for (@typeInfo(@TypeOf(pokemon.stats))
|
|
156
|
+
inline for (@field(@typeInfo(@TypeOf(pokemon.stats)), @tagName(Struct)).fields) |field| {
|
|
125
157
|
const hp = comptime std.mem.eql(u8, field.name, "hp");
|
|
126
158
|
const spc =
|
|
127
159
|
comptime std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
|
|
@@ -135,12 +167,9 @@ pub const Pokemon = struct {
|
|
|
135
167
|
}
|
|
136
168
|
assert(p.moves.len > 0 and p.moves.len <= 4);
|
|
137
169
|
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
|
-
};
|
|
170
|
+
pokemon.moves[j].id = m;
|
|
171
|
+
// NB: PP can be at most 61 legally (though can overflow to 63)
|
|
172
|
+
pokemon.moves[j].pp = @intCast(@min(Move.pp(m) / 5 * 8, 61));
|
|
144
173
|
}
|
|
145
174
|
pokemon.item = p.item;
|
|
146
175
|
if (p.hp) |hp| {
|
|
@@ -151,7 +180,7 @@ pub const Pokemon = struct {
|
|
|
151
180
|
pokemon.status = p.status;
|
|
152
181
|
pokemon.types = species.types;
|
|
153
182
|
pokemon.level = p.level;
|
|
154
|
-
pokemon.dvs = DVs.from(p.dvs);
|
|
183
|
+
pokemon.dvs = DVs.from(p.species, p.dvs);
|
|
155
184
|
return pokemon;
|
|
156
185
|
}
|
|
157
186
|
|
|
@@ -165,7 +194,7 @@ pub const Pokemon = struct {
|
|
|
165
194
|
|
|
166
195
|
var stats: Stats(u16) = .{};
|
|
167
196
|
const dvs = gen1.DVs.random(rand);
|
|
168
|
-
inline for (@typeInfo(@TypeOf(stats))
|
|
197
|
+
inline for (@field(@typeInfo(@TypeOf(stats)), @tagName(Struct)).fields) |field| {
|
|
169
198
|
const hp = std.mem.eql(u8, field.name, "hp");
|
|
170
199
|
const spc = std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
|
|
171
200
|
@field(stats, field.name) = Stats(u16).calc(
|
|
@@ -192,14 +221,13 @@ pub const Pokemon = struct {
|
|
|
192
221
|
const max_pp: u8 = @intCast(Move.pp(m) + pp_ups * @min(Move.pp(m) / 5, 7));
|
|
193
222
|
ms[i] = .{
|
|
194
223
|
.id = m,
|
|
195
|
-
.pp_ups = pp_ups,
|
|
196
224
|
.pp = if (opt.cleric) max_pp else rand.range(u8, 0, max_pp + 1),
|
|
197
225
|
};
|
|
198
226
|
}
|
|
199
227
|
return .{
|
|
200
228
|
.species = s,
|
|
201
229
|
.types = species.types,
|
|
202
|
-
.dvs = DVs.from(dvs),
|
|
230
|
+
.dvs = DVs.from(s, dvs),
|
|
203
231
|
.level = lvl,
|
|
204
232
|
.stats = stats,
|
|
205
233
|
.hp = if (opt.cleric) stats.hp else rand.range(u16, 0, stats.hp + 1),
|