@pkmn/engine 0.1.0-dev.f3aaee39 → 0.1.0-dev.f6545544
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 +51 -23
- 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 +25 -3
- 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 +20 -1
- package/build/pkg/protocol.js +123 -102
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +53 -76
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/debug.jsx +152 -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 +359 -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 +347 -104
- package/package.json +62 -123
- package/src/bin/install-pkmn-engine +31 -20
- package/src/bin/pkmn-debug +1 -1
- package/src/lib/bindings/c.zig +255 -0
- package/src/lib/{binding → bindings}/node.zig +9 -22
- package/src/lib/bindings/wasm.zig +59 -0
- package/src/lib/common/array.zig +77 -0
- package/src/lib/common/data.zig +12 -24
- package/src/lib/common/debug.zig +39 -8
- package/src/lib/common/js.zig +4 -2
- package/src/lib/common/optional.zig +21 -10
- package/src/lib/common/options.zig +6 -0
- package/src/lib/common/protocol.zig +808 -332
- package/src/lib/common/rational.zig +132 -36
- package/src/lib/common/rng.zig +22 -15
- package/src/lib/common/util.zig +50 -1
- package/src/lib/gen1/calc.zig +688 -162
- package/src/lib/gen1/chance.zig +436 -295
- 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 +8 -9
- package/src/lib/gen1/data.zig +55 -70
- package/src/lib/gen1/helpers.zig +91 -562
- package/src/lib/gen1/mechanics.zig +659 -579
- package/src/lib/gen2/calc.zig +153 -0
- package/src/lib/gen2/chance.zig +902 -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 +135 -33
- package/src/lib/gen2/data.zig +115 -91
- package/src/lib/gen2/generated.zig +801 -0
- package/src/lib/gen2/helpers.zig +54 -37
- package/src/lib/gen2/mechanics.zig +3580 -29
- package/src/lib/node.zig +18 -0
- package/src/lib/pkmn.zig +37 -15
- package/src/lib/wasm.zig +17 -0
- package/src/tools/display/dom.ts +95 -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 -892
- package/src/lib/gen2/README.md +0 -308
- package/src/test/display/pkmn.html.tmpl +0 -368
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
//! Code generated by `tools/generate` - manual edits will be overwritten
|
|
2
|
-
|
|
3
|
-
const std = @import("std");
|
|
1
|
+
//! Code generated by `tools/generate` - manual edits will be overwritten.
|
|
4
2
|
|
|
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,8 +1089,8 @@ 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
|
|
1095
|
-
pub
|
|
1092
|
+
/// The Pokémon's critical hit ratio out of 256.
|
|
1093
|
+
pub fn chance(id: Species) u8 {
|
|
1096
1094
|
assert(id != .None);
|
|
1097
1095
|
return CHANCES[@intFromEnum(id) - 1];
|
|
1098
1096
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
//! Code generated by `tools/generate` - manual edits will be overwritten
|
|
2
|
-
|
|
3
|
-
const std = @import("std");
|
|
1
|
+
//! Code generated by `tools/generate` - manual edits will be overwritten.
|
|
4
2
|
|
|
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;
|
|
@@ -30,7 +29,7 @@ pub const Type = enum(u4) {
|
|
|
30
29
|
Ice,
|
|
31
30
|
Dragon,
|
|
32
31
|
|
|
33
|
-
const CHART
|
|
32
|
+
const CHART: [15][15]Effectiveness = .{
|
|
34
33
|
[_]Effectiveness{ N, N, N, N, N, R, N, I, N, N, N, N, N, N, N }, // Normal
|
|
35
34
|
[_]Effectiveness{ S, N, R, R, N, S, R, I, N, N, N, N, R, S, N }, // Fighting
|
|
36
35
|
[_]Effectiveness{ N, S, N, N, N, R, S, N, N, N, S, R, N, N, N }, // Flying
|
|
@@ -90,16 +89,16 @@ pub const Type = enum(u4) {
|
|
|
90
89
|
pub const size = 15;
|
|
91
90
|
|
|
92
91
|
/// Whether or not this type is considered to be special as opposed to physical.
|
|
93
|
-
pub
|
|
92
|
+
pub fn special(self: Type) bool {
|
|
94
93
|
return @intFromEnum(self) >= @intFromEnum(Type.Fire);
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
/// The `Effectiveness` of type `t2` vs. type `t1`.
|
|
98
|
-
pub
|
|
97
|
+
pub fn effectiveness(t1: Type, t2: Type) Effectiveness {
|
|
99
98
|
return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
/// The precedence order of
|
|
101
|
+
/// The precedence order of Type `t2` vs. Type `t1`.
|
|
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);
|
|
@@ -120,12 +119,12 @@ pub const Types = packed struct {
|
|
|
120
119
|
}
|
|
121
120
|
|
|
122
121
|
/// Whether this typing is immune to type `t`.
|
|
123
|
-
pub
|
|
122
|
+
pub fn immune(self: Types, t: Type) bool {
|
|
124
123
|
return t.effectiveness(self.type1) == I or t.effectiveness(self.type2) == I;
|
|
125
124
|
}
|
|
126
125
|
|
|
127
126
|
/// Whether this typing includes type `t`.
|
|
128
|
-
pub
|
|
127
|
+
pub fn includes(self: Types, t: Type) bool {
|
|
129
128
|
return self.type1 == t or self.type2 == t;
|
|
130
129
|
}
|
|
131
130
|
};
|
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,11 +18,11 @@ 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
|
-
/// The
|
|
24
|
+
/// The optimal size in bytes required to hold all Generation I choice options.
|
|
25
|
+
/// At least as large as MAX_CHOICES.
|
|
30
26
|
pub const CHOICES_SIZE = if (builtin.mode == .ReleaseSmall)
|
|
31
27
|
MAX_CHOICES
|
|
32
28
|
else
|
|
@@ -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
|
|
|
@@ -70,28 +67,28 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
70
67
|
rng: RNG,
|
|
71
68
|
|
|
72
69
|
/// Returns the `Side` for the given `player`.
|
|
73
|
-
pub
|
|
74
|
-
assert(
|
|
70
|
+
pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
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
|
-
pub
|
|
80
|
-
assert(
|
|
76
|
+
pub fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
77
|
+
assert(isPointerTo(self, Self));
|
|
81
78
|
return &self.sides[@intFromEnum(player.foe())];
|
|
82
79
|
}
|
|
83
80
|
|
|
84
81
|
/// Returns an identifier for the active Pokémon of `player`.
|
|
85
|
-
pub
|
|
82
|
+
pub fn active(self: *const Self, player: Player) ID {
|
|
86
83
|
return player.ident(@intCast(self.side(player).order[0]));
|
|
87
84
|
}
|
|
88
85
|
|
|
89
86
|
/// Returns the `MoveDetails` for the given `player`.
|
|
90
|
-
pub
|
|
87
|
+
pub fn lastMove(
|
|
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
|
|
|
@@ -112,7 +109,7 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
112
109
|
/// make (i.e. on the cartridge a soft-lock occurs).
|
|
113
110
|
///
|
|
114
111
|
/// 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 {
|
|
112
|
+
pub fn choices(self: *const Self, player: Player, request: Choice.Type, out: []Choice) u8 {
|
|
116
113
|
return mechanics.choices(self, player, request, out);
|
|
117
114
|
}
|
|
118
115
|
};
|
|
@@ -141,8 +138,8 @@ pub const Side = extern struct {
|
|
|
141
138
|
}
|
|
142
139
|
|
|
143
140
|
/// Returns the stored `Pokemon` corresponding to the one-indexed party `slot`.
|
|
144
|
-
pub
|
|
145
|
-
assert(
|
|
141
|
+
pub fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
|
|
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);
|
|
@@ -150,8 +147,8 @@ pub const Side = extern struct {
|
|
|
150
147
|
}
|
|
151
148
|
|
|
152
149
|
/// Returns the stored `Pokemon` corresponding to the `active` Pokémon (slot 1).
|
|
153
|
-
pub
|
|
154
|
-
assert(
|
|
150
|
+
pub fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
|
|
151
|
+
assert(isPointerTo(self, Side));
|
|
155
152
|
return self.get(1);
|
|
156
153
|
}
|
|
157
154
|
};
|
|
@@ -176,8 +173,8 @@ pub const ActivePokemon = extern struct {
|
|
|
176
173
|
}
|
|
177
174
|
|
|
178
175
|
/// Returns the active Pokémon's current move slot located at the one-indexed `mslot`.
|
|
179
|
-
pub
|
|
180
|
-
assert(
|
|
176
|
+
pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
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];
|
|
@@ -206,15 +203,15 @@ pub const Pokemon = extern struct {
|
|
|
206
203
|
}
|
|
207
204
|
|
|
208
205
|
/// Returns the Pokémon's original move slot located at the one-indexed `mslot`.
|
|
209
|
-
pub
|
|
210
|
-
assert(
|
|
206
|
+
pub fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
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];
|
|
214
211
|
}
|
|
215
212
|
};
|
|
216
213
|
|
|
217
|
-
/// Representation of a Generation I
|
|
214
|
+
/// Representation of a Generation I Pokémon's move slot in a battle.
|
|
218
215
|
pub const MoveSlot = extern struct {
|
|
219
216
|
/// The identifier for the move.
|
|
220
217
|
id: Move = .None,
|
|
@@ -222,20 +219,16 @@ pub const MoveSlot = extern struct {
|
|
|
222
219
|
pp: u8 = 0,
|
|
223
220
|
|
|
224
221
|
comptime {
|
|
225
|
-
assert(@sizeOf(MoveSlot) ==
|
|
222
|
+
assert(@sizeOf(MoveSlot) == 2);
|
|
226
223
|
}
|
|
227
224
|
};
|
|
228
225
|
|
|
229
226
|
/// Details required to detect desyncs based on the move last selected/executed by players.
|
|
230
|
-
pub const MoveDetails = packed struct {
|
|
227
|
+
pub const MoveDetails = packed struct(if (showdown) u16 else u8) {
|
|
231
228
|
/// The move slot index of the last move selected in the battle menu.
|
|
232
229
|
index: if (showdown) u8 else u4 = 0,
|
|
233
230
|
/// Whether the last move executed was counterable.
|
|
234
231
|
counterable: if (showdown) u8 else u4 = 0,
|
|
235
|
-
|
|
236
|
-
comptime {
|
|
237
|
-
assert(@sizeOf(MoveDetails) == if (showdown) 2 else 1);
|
|
238
|
-
}
|
|
239
232
|
};
|
|
240
233
|
|
|
241
234
|
/// Bitfield representation of a Generation I & II Pokémon's major status condition.
|
|
@@ -259,39 +252,39 @@ pub const Status = enum(u8) {
|
|
|
259
252
|
|
|
260
253
|
pub const TOX = 0b10001000;
|
|
261
254
|
|
|
262
|
-
const
|
|
255
|
+
const SLEEP = 0b111;
|
|
263
256
|
|
|
264
257
|
/// Whether or not the status `num` is the same as `status`.
|
|
265
|
-
pub
|
|
258
|
+
pub fn is(num: u8, status: Status) bool {
|
|
266
259
|
if (status == .SLP) return Status.duration(num) > 0;
|
|
267
260
|
return ((num >> @intCast(@intFromEnum(status))) & 1) != 0;
|
|
268
261
|
}
|
|
269
262
|
|
|
270
263
|
/// Initializes a non-sleep `status`. Use `slp` or `slf` to initialize a sleep status.
|
|
271
|
-
pub
|
|
264
|
+
pub fn init(status: Status) u8 {
|
|
272
265
|
assert(status != .SLP and status != .EXT);
|
|
273
266
|
return @as(u8, 1) << @intCast(@intFromEnum(status));
|
|
274
267
|
}
|
|
275
268
|
|
|
276
269
|
/// Initializes a non self-inflicted sleep status with duration `dur`.
|
|
277
|
-
pub
|
|
270
|
+
pub fn slp(dur: u3) u8 {
|
|
278
271
|
assert(dur > 0);
|
|
279
272
|
return @as(u8, dur);
|
|
280
273
|
}
|
|
281
274
|
|
|
282
275
|
/// Initializes a self-inflicted sleep status with duration `dur`.
|
|
283
|
-
pub
|
|
276
|
+
pub fn slf(dur: u3) u8 {
|
|
284
277
|
assert(dur > 0);
|
|
285
278
|
return 0x80 | slp(dur);
|
|
286
279
|
}
|
|
287
280
|
|
|
288
281
|
/// Returns the duration of a sleep status.
|
|
289
|
-
pub
|
|
290
|
-
return @intCast(num &
|
|
282
|
+
pub fn duration(num: u8) u3 {
|
|
283
|
+
return @intCast(num & SLEEP);
|
|
291
284
|
}
|
|
292
285
|
|
|
293
286
|
/// Returns whether `num` reflects any status.
|
|
294
|
-
pub
|
|
287
|
+
pub fn any(num: u8) bool {
|
|
295
288
|
return num > 0;
|
|
296
289
|
}
|
|
297
290
|
|
|
@@ -329,7 +322,7 @@ test Status {
|
|
|
329
322
|
}
|
|
330
323
|
|
|
331
324
|
/// Bitfield representation of volatile statuses and associated data in Generation I.
|
|
332
|
-
pub const Volatiles = packed struct {
|
|
325
|
+
pub const Volatiles = packed struct(u64) {
|
|
333
326
|
/// Whether the "Bide" volatile status is present.
|
|
334
327
|
Bide: bool = false,
|
|
335
328
|
/// Whether the "Thrashing" volatile status is present.
|
|
@@ -382,19 +375,15 @@ pub const Volatiles = packed struct {
|
|
|
382
375
|
/// The identity of whom the active Pokémon is transformed into.
|
|
383
376
|
transform: u4 = 0,
|
|
384
377
|
/// The remaining turns the move is disabled.
|
|
385
|
-
|
|
378
|
+
disable_duration: u4 = 0,
|
|
386
379
|
/// The move slot (1-4) that is disabled.
|
|
387
|
-
|
|
380
|
+
disable_move: u3 = 0,
|
|
388
381
|
/// The number of turns toxic damage has been accumulating.
|
|
389
382
|
toxic: u5 = 0,
|
|
390
|
-
|
|
391
|
-
comptime {
|
|
392
|
-
assert(@sizeOf(Volatiles) == 8);
|
|
393
|
-
}
|
|
394
383
|
};
|
|
395
384
|
|
|
396
385
|
test Volatiles {
|
|
397
|
-
var volatiles =
|
|
386
|
+
var volatiles: Volatiles = .{};
|
|
398
387
|
volatiles.Confusion = true;
|
|
399
388
|
volatiles.confusion = 2;
|
|
400
389
|
volatiles.Thrashing = true;
|
|
@@ -403,8 +392,8 @@ test Volatiles {
|
|
|
403
392
|
volatiles.Substitute = true;
|
|
404
393
|
volatiles.substitute = 42;
|
|
405
394
|
volatiles.toxic = 4;
|
|
406
|
-
volatiles.
|
|
407
|
-
volatiles.
|
|
395
|
+
volatiles.disable_move = 2;
|
|
396
|
+
volatiles.disable_duration = 4;
|
|
408
397
|
|
|
409
398
|
try expect(volatiles.Confusion);
|
|
410
399
|
try expect(volatiles.Thrashing);
|
|
@@ -415,14 +404,14 @@ test Volatiles {
|
|
|
415
404
|
|
|
416
405
|
try expectEqual(@as(u16, 235), volatiles.state);
|
|
417
406
|
try expectEqual(@as(u8, 42), volatiles.substitute);
|
|
418
|
-
try expectEqual(@as(u4, 2), volatiles.
|
|
419
|
-
try expectEqual(@as(u4, 4), volatiles.
|
|
420
|
-
try expectEqual(@as(
|
|
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);
|
|
421
410
|
try expectEqual(@as(u5, 4), volatiles.toxic);
|
|
422
|
-
try expectEqual(@as(
|
|
411
|
+
try expectEqual(@as(u3, 3), volatiles.attacks);
|
|
423
412
|
}
|
|
424
413
|
|
|
425
|
-
///
|
|
414
|
+
/// Representation of a Pokémon's stats in Generation I.
|
|
426
415
|
pub fn Stats(comptime T: type) type {
|
|
427
416
|
return extern struct {
|
|
428
417
|
hp: T = 0,
|
|
@@ -456,7 +445,7 @@ test Stats {
|
|
|
456
445
|
}
|
|
457
446
|
|
|
458
447
|
/// Representation of a Pokémon's boosts in Generation I.
|
|
459
|
-
pub const Boosts = packed struct {
|
|
448
|
+
pub const Boosts = packed struct(u32) {
|
|
460
449
|
/// A Pokémon's Attack boosts.
|
|
461
450
|
atk: i4 = 0,
|
|
462
451
|
/// A Pokémon's Defense boosts.
|
|
@@ -471,14 +460,10 @@ pub const Boosts = packed struct {
|
|
|
471
460
|
evasion: i4 = 0,
|
|
472
461
|
|
|
473
462
|
_: u8 = 0,
|
|
474
|
-
|
|
475
|
-
comptime {
|
|
476
|
-
assert(@sizeOf(Boosts) == 4);
|
|
477
|
-
}
|
|
478
463
|
};
|
|
479
464
|
|
|
480
465
|
test Boosts {
|
|
481
|
-
const boosts =
|
|
466
|
+
const boosts: Boosts = .{ .spc = -6 };
|
|
482
467
|
try expectEqual(0, boosts.atk);
|
|
483
468
|
try expectEqual(-6, boosts.spc);
|
|
484
469
|
}
|
|
@@ -490,7 +475,7 @@ test Move {
|
|
|
490
475
|
try expectEqual(2, @intFromEnum(Move.KarateChop));
|
|
491
476
|
const move = Move.get(.Fissure);
|
|
492
477
|
try expectEqual(Move.Effect.OHKO, move.effect);
|
|
493
|
-
try expectEqual(
|
|
478
|
+
try expectEqual(rng.Gen12.percent(30), move.accuracy);
|
|
494
479
|
try expectEqual(Type.Ground, move.type);
|
|
495
480
|
|
|
496
481
|
try expect(!Move.Effect.onBegin(.None));
|
|
@@ -628,16 +613,16 @@ pub const DVs = struct {
|
|
|
628
613
|
};
|
|
629
614
|
|
|
630
615
|
test DVs {
|
|
631
|
-
var dvs =
|
|
616
|
+
var dvs: DVs = .{ .spc = 15, .spe = 15 };
|
|
632
617
|
try expectEqual(@as(u4, 15), dvs.hp());
|
|
633
|
-
dvs =
|
|
618
|
+
dvs = .{
|
|
634
619
|
.atk = 5,
|
|
635
620
|
.def = 15,
|
|
636
621
|
.spe = 13,
|
|
637
622
|
.spc = 13,
|
|
638
623
|
};
|
|
639
624
|
try expectEqual(@as(u4, 15), dvs.hp());
|
|
640
|
-
dvs =
|
|
625
|
+
dvs = .{
|
|
641
626
|
.def = 3,
|
|
642
627
|
.spe = 10,
|
|
643
628
|
.spc = 11,
|