@pkmn/engine 0.1.0-dev.d97c6e03 → 0.1.0-dev.f3aaee39
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 +67 -56
- package/build/pkg/addon.d.ts +1 -1
- package/build/pkg/addon.js +7 -6
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/layout.json +25 -3
- package/build/pkg/gen1.d.ts +5 -4
- package/build/pkg/gen1.js +46 -30
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +15 -12
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +4 -2
- package/build/pkg/protocol.js +4 -2
- package/build/pkg/protocol.js.map +1 -1
- package/build/test/display.js +29 -12
- package/build/test/display.js.map +1 -1
- package/build.zig +89 -65
- package/package.json +26 -16
- package/src/bin/install-pkmn-engine +11 -6
- package/src/lib/binding/node.zig +45 -140
- package/src/lib/binding/wasm.zig +5 -3
- package/src/lib/common/battle.zig +17 -0
- package/src/lib/common/data.zig +11 -11
- package/src/lib/common/debug.zig +21 -11
- package/src/lib/common/js.zig +118 -0
- package/src/lib/common/optional.zig +60 -0
- package/src/lib/common/options.zig +12 -3
- package/src/lib/common/protocol.zig +242 -178
- package/src/lib/common/rational.zig +353 -0
- package/src/lib/common/rng.zig +10 -10
- package/src/lib/common/util.zig +12 -0
- package/src/lib/gen1/README.md +255 -154
- package/src/lib/gen1/calc.zig +427 -0
- package/src/lib/gen1/chance.zig +1044 -0
- package/src/lib/gen1/data/moves.zig +10 -10
- package/src/lib/gen1/data/species.zig +2 -2
- package/src/lib/gen1/data/types.zig +3 -3
- package/src/lib/gen1/data.zig +64 -38
- package/src/lib/gen1/helpers.zig +592 -32
- package/src/lib/gen1/mechanics.zig +892 -531
- package/src/lib/gen2/README.md +12 -13
- package/src/lib/gen2/data/items.zig +3 -3
- package/src/lib/gen2/data/moves.zig +1 -1
- package/src/lib/gen2/data/species.zig +1 -1
- package/src/lib/gen2/data/types.zig +3 -3
- package/src/lib/gen2/data.zig +33 -22
- package/src/lib/gen2/helpers.zig +9 -11
- package/src/lib/gen2/mechanics.zig +5 -4
- package/src/lib/pkmn.zig +65 -6
package/src/lib/gen2/README.md
CHANGED
|
@@ -54,13 +54,12 @@ The following information is required to simulate a Generation II Pokémon battl
|
|
|
54
54
|
| | | |
|
|
55
55
|
| `active.last_used_move` | `PlayerUsedMove` | `side.lastMove` |
|
|
56
56
|
|
|
57
|
-
- Pokémon Showdown
|
|
57
|
+
- Pokémon Showdown doesn't implement the correct Generation II RNG and as such its `seed` is
|
|
58
58
|
different
|
|
59
|
-
- `battle.turn` only needs to be tracked
|
|
60
|
-
protocol
|
|
59
|
+
- `battle.turn` only needs to be tracked to be compatible with the Pokémon Showdown protocol
|
|
61
60
|
- Battle results (win, lose, draw) or request states are communicated via the return code of
|
|
62
61
|
`Battle.update`
|
|
63
|
-
- Nicknames (`BattleMonNick`/`pokemon.name`)
|
|
62
|
+
- Nicknames (`BattleMonNick`/`pokemon.name`) aren't handled by the pkmn engine as they're expected
|
|
64
63
|
to be handled by driver code if required
|
|
65
64
|
|
|
66
65
|
==**TODO**==
|
|
@@ -77,9 +76,9 @@ between the data structure for the "active" Pokémon and its party members (see
|
|
|
77
76
|
|
|
78
77
|
### `Pokemon` / `ActivePokemon`
|
|
79
78
|
|
|
80
|
-
Similar to the cartridge,
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
Similar to the cartridge, to save space different information is stored depending on whether a
|
|
80
|
+
[Pokémon](https://pkmn.cc/bulba/Pok%c3%a9mon_data_structure_%28Generation_II%29) is actively
|
|
81
|
+
participating in battle vs. is switched out (pret's [`battle_struct` vs.
|
|
83
82
|
`party_struct`](https://pkmn.cc/pokecrystal/macros/ram.asm)). In Pokémon Showdown, all the Pokemon
|
|
84
83
|
are represented by the same
|
|
85
84
|
[`Pokemon`](https://github.com/smogon/pokemon-showdown/blob/master/sim/pokemon.ts) class, and static
|
|
@@ -93,14 +92,14 @@ A `MoveSlot` is a data-type for a `(move, current pp)` pair. A pared down versio
|
|
|
93
92
|
Showdown's `Pokemon#moveSlot`, it also stores data from the cartridge's `battle_struct::Move` macro
|
|
94
93
|
and can be used to replace the `PlayerMove*` data. Move PP is stored as a full byte instead of how
|
|
95
94
|
the cartridge (`battle_struct::PP`) stores it (6 bits for current PP and the remaining 2 bits used
|
|
96
|
-
to store the number of applied PP Ups). PP Up bits
|
|
95
|
+
to store the number of applied PP Ups). PP Up bits don't actually need to be stored on move slot
|
|
97
96
|
as max PP is never relevant in Generation II (the Mystery Berry always increases PP from 0 -> 5).
|
|
98
97
|
|
|
99
98
|
#### `Status`
|
|
100
99
|
|
|
101
100
|
Bitfield representation of a Pokémon's major [status
|
|
102
|
-
condition](https://pkmn.cc/bulba/Status_condition), mirroring how it
|
|
103
|
-
value of `0x00` means that the Pokémon
|
|
101
|
+
condition](https://pkmn.cc/bulba/Status_condition), mirroring how it's stored on the cartridge. A
|
|
102
|
+
value of `0x00` means that the Pokémon isn't affected by any major status, otherwise the lower 3
|
|
104
103
|
bits represent the remaining duration for Sleep. Other status are denoted by the presence of
|
|
105
104
|
individual bits - at most one status should be set at any given time.
|
|
106
105
|
|
|
@@ -161,7 +160,7 @@ boosts should always range from `-6`...`6` instead of `1`...`13` as on the cartr
|
|
|
161
160
|
|
|
162
161
|
`Moves` serves as an identifier for a unique [Pokémon move](https://pkmn.cc/bulba/Move) that can be
|
|
163
162
|
used to retrieve a `Move` with information regarding base power, accuracy and type. As covered
|
|
164
|
-
|
|
163
|
+
earlier, PP information isn't strictly necessary in Generation I, but fits neatly into the 4 bits of
|
|
165
164
|
padding after noticing that all PP values are multiples of 5. `Moves.None` exists as a special
|
|
166
165
|
sentinel value to indicate `null`.
|
|
167
166
|
|
|
@@ -215,8 +214,8 @@ entropy](https://en.wikipedia.org/wiki/Entropy_(information_theory))) is as foll
|
|
|
215
214
|
| **wrap** | 0...5 | 3 | | **perish song** | 0...4 | 3 |
|
|
216
215
|
| **item** | TODO | 5? | | **gender** | 0..1 | 1 |
|
|
217
216
|
|
|
218
|
-
From this
|
|
219
|
-
much overhead the representations
|
|
217
|
+
From this one can determine the minimum bits required to store each data structure to determine how
|
|
218
|
+
much overhead the preceding representations have after taking into consideration [alignment &
|
|
220
219
|
padding](https://en.wikipedia.org/wiki/Data_structure_alignment) and
|
|
221
220
|
[denormalization](https://en.wikipedia.org/wiki/Denormalization):
|
|
222
221
|
|
|
@@ -219,18 +219,18 @@ pub const Item = enum(u8) {
|
|
|
219
219
|
pub inline fn boost(item: Item) ?Type {
|
|
220
220
|
assert(item != .None);
|
|
221
221
|
if (item == .PolkadotBow) return .Normal;
|
|
222
|
-
return if (@
|
|
222
|
+
return if (@intFromEnum(item) <= 18) @enumFromInt(@intFromEnum(item) - 1) else null;
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
/// Whether or not this item is a Berry.
|
|
226
226
|
pub inline fn berry(item: Item) bool {
|
|
227
227
|
assert(item != .None);
|
|
228
|
-
return @
|
|
228
|
+
return @intFromEnum(item) > 30 and @intFromEnum(item) <= 40;
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
/// Whether or not this item is Mail.
|
|
232
232
|
pub inline fn mail(item: Item) bool {
|
|
233
233
|
assert(item != .None);
|
|
234
|
-
return @
|
|
234
|
+
return @intFromEnum(item) > 60 and @intFromEnum(item) <= 70;
|
|
235
235
|
}
|
|
236
236
|
};
|
|
@@ -86,17 +86,17 @@ pub const Type = enum(u8) {
|
|
|
86
86
|
|
|
87
87
|
/// Whether or not this type is considered to be special as opposed to physical.
|
|
88
88
|
pub inline fn special(self: Type) bool {
|
|
89
|
-
return @
|
|
89
|
+
return @intFromEnum(self) >= @intFromEnum(Type.Fire);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
/// The `Effectiveness` of type `t2` vs. type `t1`.
|
|
93
93
|
pub inline fn effectiveness(t1: Type, t2: Type) Effectiveness {
|
|
94
|
-
return CHART[@
|
|
94
|
+
return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
/// The precedence order of type type.
|
|
98
98
|
pub inline fn precedence(self: Type) u8 {
|
|
99
|
-
return PRECEDENCE[@
|
|
99
|
+
return PRECEDENCE[@intFromEnum(self)];
|
|
100
100
|
}
|
|
101
101
|
};
|
|
102
102
|
|
package/src/lib/gen2/data.zig
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
2
|
const builtin = @import("builtin");
|
|
3
3
|
|
|
4
|
+
const pkmn = @import("../pkmn.zig");
|
|
5
|
+
|
|
4
6
|
const data = @import("../common/data.zig");
|
|
5
7
|
const DEBUG = @import("../common/debug.zig").print;
|
|
6
|
-
const options = @import("../common/options.zig");
|
|
7
8
|
const rng = @import("../common/rng.zig");
|
|
9
|
+
const util = @import("../common/util.zig");
|
|
8
10
|
|
|
9
11
|
const items = @import("data/items.zig");
|
|
10
12
|
const moves = @import("data/moves.zig");
|
|
@@ -36,7 +38,9 @@ const ID = data.ID;
|
|
|
36
38
|
const Player = data.Player;
|
|
37
39
|
const Result = data.Result;
|
|
38
40
|
|
|
39
|
-
const
|
|
41
|
+
const PointerType = util.PointerType;
|
|
42
|
+
|
|
43
|
+
const showdown = pkmn.options.showdown;
|
|
40
44
|
|
|
41
45
|
pub const PRNG = rng.PRNG(2);
|
|
42
46
|
|
|
@@ -49,20 +53,22 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
49
53
|
turn: u16 = 0,
|
|
50
54
|
field: Field = .{},
|
|
51
55
|
|
|
52
|
-
pub inline fn side(self:
|
|
53
|
-
|
|
56
|
+
pub inline fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
57
|
+
assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
|
|
58
|
+
return &self.sides[@intFromEnum(player)];
|
|
54
59
|
}
|
|
55
60
|
|
|
56
|
-
pub inline fn foe(self:
|
|
57
|
-
|
|
61
|
+
pub inline fn foe(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
62
|
+
assert(@typeInfo(@TypeOf(self)).Pointer.child == Self);
|
|
63
|
+
return &self.sides[@intFromEnum(player.foe())];
|
|
58
64
|
}
|
|
59
65
|
|
|
60
|
-
pub inline fn active(self: *Self, player: Player) ID {
|
|
61
|
-
return player.ident(@intCast(
|
|
66
|
+
pub inline fn active(self: *const Self, player: Player) ID {
|
|
67
|
+
return player.ident(@intCast(self.side(player).pokemon[0].position));
|
|
62
68
|
}
|
|
63
69
|
|
|
64
|
-
pub fn update(self: *Self, c1: Choice, c2: Choice,
|
|
65
|
-
return mechanics.update(self, c1, c2,
|
|
70
|
+
pub fn update(self: *Self, c1: Choice, c2: Choice, options: anytype) !Result {
|
|
71
|
+
return mechanics.update(self, c1, c2, options);
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
pub fn choices(self: *Self, player: Player, request: Choice.Type, out: []Choice) u8 {
|
|
@@ -118,14 +124,16 @@ const Side = extern struct {
|
|
|
118
124
|
assert(@sizeOf(Side) == 240);
|
|
119
125
|
}
|
|
120
126
|
|
|
121
|
-
pub inline fn get(self:
|
|
127
|
+
pub inline fn get(self: anytype, slot: u8) PointerType(@TypeOf(self), Pokemon) {
|
|
128
|
+
assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
|
|
122
129
|
assert(slot > 0 and slot <= 6);
|
|
123
130
|
const id = self.pokemon[slot - 1].position;
|
|
124
131
|
assert(id > 0 and id <= 6);
|
|
125
132
|
return &self.pokemon[id - 1];
|
|
126
133
|
}
|
|
127
134
|
|
|
128
|
-
pub inline fn stored(self:
|
|
135
|
+
pub inline fn stored(self: anytype) PointerType(@TypeOf(self), Pokemon) {
|
|
136
|
+
assert(@typeInfo(@TypeOf(self)).Pointer.child == Side);
|
|
129
137
|
return self.get(1);
|
|
130
138
|
}
|
|
131
139
|
};
|
|
@@ -145,7 +153,8 @@ const ActivePokemon = extern struct {
|
|
|
145
153
|
assert(@sizeOf(ActivePokemon) == 44);
|
|
146
154
|
}
|
|
147
155
|
|
|
148
|
-
pub inline fn move(self:
|
|
156
|
+
pub inline fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
157
|
+
assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
|
|
149
158
|
assert(mslot > 0 and mslot <= 4);
|
|
150
159
|
assert(self.moves[mslot - 1].id != .None);
|
|
151
160
|
return &self.moves[mslot - 1];
|
|
@@ -169,7 +178,8 @@ const Pokemon = extern struct {
|
|
|
169
178
|
assert(@sizeOf(Pokemon) == 32);
|
|
170
179
|
}
|
|
171
180
|
|
|
172
|
-
pub inline fn move(self:
|
|
181
|
+
pub inline fn move(self: anytype, mslot: u8) PointerType(@TypeOf(self), MoveSlot) {
|
|
182
|
+
assert(@typeInfo(@TypeOf(self)).Pointer.child == Pokemon);
|
|
173
183
|
assert(mslot > 0 and mslot <= 4);
|
|
174
184
|
assert(self.moves[mslot - 1].id != .None);
|
|
175
185
|
return &self.moves[mslot - 1];
|
|
@@ -205,11 +215,11 @@ const DVs = packed struct {
|
|
|
205
215
|
0xFF => .Unknown,
|
|
206
216
|
else => if ((@as(u8, dvs.atk) << 4 | dvs.spe) < ratio) Gender.Female else Gender.Male,
|
|
207
217
|
};
|
|
208
|
-
const p = @intCast(
|
|
218
|
+
const p: u6 = @intCast(1 + ((5 * @as(u8, (dvs.atk & 0b1000) | ((dvs.def & 0b1000)) >> 1 |
|
|
209
219
|
((dvs.spe & 0b1000)) >> 2 | ((dvs.spc & 0b1000)) >> 3) + (dvs.spc & 0b0011)) >> 1));
|
|
210
220
|
var t = @as(u8, dvs.def & 0b0011) + (@as(u8, dvs.atk & 0b0011) << 2) + 1;
|
|
211
|
-
if (t >= @
|
|
212
|
-
return DVs{ .gender = g, .pow = p, .type = @
|
|
221
|
+
if (t >= @intFromEnum(Type.@"???")) t = t + 1;
|
|
222
|
+
return DVs{ .gender = g, .pow = p, .type = @enumFromInt(t) };
|
|
213
223
|
}
|
|
214
224
|
|
|
215
225
|
comptime {
|
|
@@ -327,10 +337,11 @@ pub fn Stats(comptime T: type) type {
|
|
|
327
337
|
|
|
328
338
|
pub fn calc(comptime stat: []const u8, base: T, dv: u4, exp: u16, level: u8) T {
|
|
329
339
|
assert(level > 0 and level <= 100);
|
|
330
|
-
const
|
|
340
|
+
const float: f32 = @floatFromInt(exp);
|
|
341
|
+
const evs: u16 = @min(255, @as(u16, @intFromFloat(@ceil(@sqrt(float)))));
|
|
331
342
|
const core: u32 = (2 *% (@as(u32, base) +% dv)) +% (evs / 4);
|
|
332
343
|
const factor: u32 = if (std.mem.eql(u8, stat, "hp")) level + 10 else 5;
|
|
333
|
-
return @intCast(
|
|
344
|
+
return @intCast(core *% @as(u32, level) / 100 +% factor);
|
|
334
345
|
}
|
|
335
346
|
};
|
|
336
347
|
}
|
|
@@ -390,7 +401,7 @@ test Item {
|
|
|
390
401
|
pub const Move = moves.Move;
|
|
391
402
|
|
|
392
403
|
test Move {
|
|
393
|
-
try expectEqual(251, @
|
|
404
|
+
try expectEqual(251, @intFromEnum(Move.BeatUp));
|
|
394
405
|
const move = Move.get(.DynamicPunch);
|
|
395
406
|
try expectEqual(Move.Effect.ConfusionChance, move.effect);
|
|
396
407
|
try expectEqual(@as(u8, 50), move.accuracy);
|
|
@@ -400,7 +411,7 @@ test Move {
|
|
|
400
411
|
pub const Species = species.Species;
|
|
401
412
|
|
|
402
413
|
test Species {
|
|
403
|
-
try expectEqual(152, @
|
|
414
|
+
try expectEqual(152, @intFromEnum(Species.Chikorita));
|
|
404
415
|
try expectEqual(@as(u8, 100), Species.get(.Celebi).stats.spd);
|
|
405
416
|
}
|
|
406
417
|
|
|
@@ -409,7 +420,7 @@ pub const Types = types.Types;
|
|
|
409
420
|
pub const Effectiveness = gen1.Effectiveness;
|
|
410
421
|
|
|
411
422
|
test Types {
|
|
412
|
-
try expectEqual(13, @
|
|
423
|
+
try expectEqual(13, @intFromEnum(Type.Electric));
|
|
413
424
|
|
|
414
425
|
try expect(!Type.Steel.special());
|
|
415
426
|
try expect(Type.Dark.special());
|
package/src/lib/gen2/helpers.zig
CHANGED
|
@@ -72,11 +72,9 @@ pub fn prng(rand: *PSRNG) data.PRNG {
|
|
|
72
72
|
rand.newSeed()
|
|
73
73
|
else
|
|
74
74
|
.{
|
|
75
|
-
rand.range(u8, 0, 256), rand.range(u8, 0, 256),
|
|
76
|
-
rand.range(u8, 0, 256), rand.range(u8, 0, 256),
|
|
77
|
-
rand.range(u8, 0, 256), rand.range(u8, 0, 256),
|
|
78
|
-
rand.range(u8, 0, 256), rand.range(u8, 0, 256),
|
|
79
|
-
rand.range(u8, 0, 256), rand.range(u8, 0, 256),
|
|
75
|
+
rand.range(u8, 0, 256), rand.range(u8, 0, 256), rand.range(u8, 0, 256),
|
|
76
|
+
rand.range(u8, 0, 256), rand.range(u8, 0, 256), rand.range(u8, 0, 256),
|
|
77
|
+
rand.range(u8, 0, 256), rand.range(u8, 0, 256), rand.range(u8, 0, 256),
|
|
80
78
|
},
|
|
81
79
|
},
|
|
82
80
|
};
|
|
@@ -141,7 +139,7 @@ pub const Pokemon = struct {
|
|
|
141
139
|
.id = m,
|
|
142
140
|
.pp_ups = 3,
|
|
143
141
|
// NB: PP can be at most 61 legally (though can overflow to 63)
|
|
144
|
-
.pp = @intCast(
|
|
142
|
+
.pp = @intCast(@min(Move.pp(m) / 5 * 8, 61)),
|
|
145
143
|
};
|
|
146
144
|
}
|
|
147
145
|
pokemon.item = p.item;
|
|
@@ -158,11 +156,11 @@ pub const Pokemon = struct {
|
|
|
158
156
|
}
|
|
159
157
|
|
|
160
158
|
pub fn random(rand: *PSRNG, opt: Options) data.Pokemon {
|
|
161
|
-
const s = @
|
|
159
|
+
const s: Species = @enumFromInt(rand.range(u8, 1, Species.size + 1));
|
|
162
160
|
const species = Species.get(s);
|
|
163
161
|
const lvl = if (rand.chance(u8, 1, 20)) rand.range(u8, 1, 99 + 1) else 100;
|
|
164
162
|
// Pokémon Showdown does not support most items without in-battle held item effects
|
|
165
|
-
const max_item = @
|
|
163
|
+
const max_item = @intFromEnum(if (showdown) Item.FlowerMail else Item.TM50);
|
|
166
164
|
const item = if (rand.chance(u8, 1, 10)) 0 else rand.range(u8, 1, max_item + 1);
|
|
167
165
|
|
|
168
166
|
var stats: Stats(u16) = .{};
|
|
@@ -184,14 +182,14 @@ pub const Pokemon = struct {
|
|
|
184
182
|
for (0..n) |i| {
|
|
185
183
|
var m: Move = .None;
|
|
186
184
|
sample: while (true) {
|
|
187
|
-
m = @
|
|
185
|
+
m = @enumFromInt(rand.range(u8, 1, 164 + 1));
|
|
188
186
|
for (0..i) |j| if (ms[j].id == m) continue :sample;
|
|
189
187
|
break;
|
|
190
188
|
}
|
|
191
|
-
const pp_ups =
|
|
189
|
+
const pp_ups: u8 =
|
|
192
190
|
if (!opt.cleric and rand.chance(u8, 1, 10)) rand.range(u2, 0, 2 + 1) else 3;
|
|
193
191
|
// NB: PP can be at most 61 legally (though can overflow to 63)
|
|
194
|
-
const max_pp = @intCast(
|
|
192
|
+
const max_pp: u8 = @intCast(Move.pp(m) + pp_ups * @min(Move.pp(m) / 5, 7));
|
|
195
193
|
ms[i] = .{
|
|
196
194
|
.id = m,
|
|
197
195
|
.pp_ups = pp_ups,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
2
|
|
|
3
|
+
const pkmn = @import("../pkmn.zig");
|
|
4
|
+
|
|
3
5
|
const common = @import("../common/data.zig");
|
|
4
6
|
const DEBUG = @import("../common/debug.zig").print;
|
|
5
|
-
const options = @import("../common/options.zig");
|
|
6
7
|
const protocol = @import("../common/protocol.zig");
|
|
7
8
|
const rng = @import("../common/rng.zig");
|
|
8
9
|
|
|
@@ -17,7 +18,7 @@ const ID = common.ID;
|
|
|
17
18
|
const Player = common.Player;
|
|
18
19
|
const Result = common.Result;
|
|
19
20
|
|
|
20
|
-
const showdown = options.showdown;
|
|
21
|
+
const showdown = pkmn.options.showdown;
|
|
21
22
|
|
|
22
23
|
const Damage = protocol.Damage;
|
|
23
24
|
const Heal = protocol.Heal;
|
|
@@ -34,11 +35,11 @@ const Species = data.Species;
|
|
|
34
35
|
const Stats = data.Stats;
|
|
35
36
|
const Status = data.Status;
|
|
36
37
|
|
|
37
|
-
pub fn update(battle: anytype, c1: Choice, c2: Choice,
|
|
38
|
+
pub fn update(battle: anytype, c1: Choice, c2: Choice, options: anytype) !Result {
|
|
38
39
|
_ = battle;
|
|
39
40
|
_ = c1;
|
|
40
41
|
_ = c2;
|
|
41
|
-
_ =
|
|
42
|
+
_ = options;
|
|
42
43
|
|
|
43
44
|
return Result.Default;
|
|
44
45
|
}
|
package/src/lib/pkmn.zig
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
///
|
|
1
|
+
/// Configured Options for the pkmn package.
|
|
2
2
|
pub const options = @import("common/options.zig");
|
|
3
3
|
/// Configures the behavior of the pkmn package.
|
|
4
4
|
pub const Options = options.Options;
|
|
@@ -25,12 +25,12 @@ pub const Result = @import("common/data.zig").Result;
|
|
|
25
25
|
/// Pokémon Showdown's RNG (backed by a Generation V & VI RNG).
|
|
26
26
|
pub const PSRNG = @import("common/rng.zig").PSRNG;
|
|
27
27
|
|
|
28
|
-
/// Namespace for helpers related to protocol
|
|
28
|
+
/// Namespace for helpers related to protocol message logging.
|
|
29
29
|
pub const protocol = if (options.internal) struct {
|
|
30
30
|
pub usingnamespace @import("common/protocol.zig");
|
|
31
31
|
} else struct {
|
|
32
32
|
/// Logs protocol information to its `Writer` during a battle update when
|
|
33
|
-
/// `options.
|
|
33
|
+
/// `options.log` is enabled.
|
|
34
34
|
pub const Log = @import("common/protocol.zig").Log;
|
|
35
35
|
/// Stripped down version of `std.io.FixedBufferStream` optimized for
|
|
36
36
|
/// efficiently writing the individual protocol bytes. Note that the
|
|
@@ -41,14 +41,73 @@ pub const protocol = if (options.internal) struct {
|
|
|
41
41
|
/// intialized with a `LOGS_SIZE`-sized buffer.
|
|
42
42
|
pub const FixedLog = @import("common/protocol.zig").FixedLog;
|
|
43
43
|
/// Null object pattern implementation of `Log` backed by a
|
|
44
|
-
/// `std.io.null_writer`. Ignores anything sent to it, though
|
|
45
|
-
/// should
|
|
44
|
+
/// `std.io.null_writer`. Ignores anything sent to it, though protocol
|
|
45
|
+
/// logging should additionally be turned off entirely with `options.log`.
|
|
46
46
|
pub const NULL = @import("common/protocol.zig").NULL;
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
pub usingnamespace @import("common/rational.zig");
|
|
50
|
+
|
|
51
|
+
/// Namespace for cross-generation battle-related types.
|
|
52
|
+
pub const battle = @import("common/battle.zig");
|
|
53
|
+
|
|
54
|
+
/// Namespace for Generation I Pokémon.
|
|
50
55
|
pub const gen1 = struct {
|
|
51
56
|
pub usingnamespace @import("gen1/data.zig");
|
|
57
|
+
/// Tracks chance actions and their associated probability during a
|
|
58
|
+
/// Generation I battle update when `options.chance` is enabled.
|
|
59
|
+
pub const Chance = @import("gen1/chance.zig").Chance;
|
|
60
|
+
/// Namespace for types associated with tracking Generation I Pokémon chance outcomes.
|
|
61
|
+
pub const chance = struct {
|
|
62
|
+
/// Actions taken by a hypothetical "chance player" that convey
|
|
63
|
+
/// information about which RNG events were observed during a Generation
|
|
64
|
+
/// I battle `update`. This can additionally be provided as input to the
|
|
65
|
+
/// `update` call via the `Calc` when `options.calc` is enabled to
|
|
66
|
+
/// override the normal behavior of the RNG in order to force specific
|
|
67
|
+
/// outcomes.
|
|
68
|
+
pub const Actions = @import("gen1/chance.zig").Actions;
|
|
69
|
+
/// Information about the RNG that was observed during a Generation I
|
|
70
|
+
/// battle `update` for a single player.
|
|
71
|
+
pub const Action = @import("gen1/chance.zig").Action;
|
|
72
|
+
/// TODO
|
|
73
|
+
pub const Durations = @import("gen1/chance.zig").Durations;
|
|
74
|
+
/// TODO
|
|
75
|
+
pub const Duration = @import("gen1/chance.zig").Duration;
|
|
76
|
+
/// Null object pattern implementation of Generation I `Chance` which
|
|
77
|
+
/// does nothing, though chance tracking should additionally be turned
|
|
78
|
+
/// off entirely via `options.chance`.
|
|
79
|
+
pub const NULL = @import("gen1/chance.zig").NULL;
|
|
80
|
+
};
|
|
81
|
+
/// Allows for forcing the value of specific RNG events during a Generation I battle `update`
|
|
82
|
+
/// via `overrides` and tracks `summaries` of information relevant to damage calculation.
|
|
83
|
+
pub const Calc = @import("gen1/calc.zig").Calc;
|
|
84
|
+
/// Namespace for types associated with supported Generation I Pokémon damage calc features.
|
|
85
|
+
pub const calc = if (options.internal) struct {
|
|
86
|
+
pub usingnamespace @import("gen1/calc.zig");
|
|
87
|
+
} else struct {
|
|
88
|
+
/// TODO
|
|
89
|
+
pub const Overrides = @import("gen1/calc.zig").Overrides;
|
|
90
|
+
/// Information relevant to damage calculation that occured during a Generation I
|
|
91
|
+
/// battle `update`.
|
|
92
|
+
pub const Summaries = @import("gen1/calc.zig").Summaries;
|
|
93
|
+
/// Information relevant to damage calculation that occured during a Generation I
|
|
94
|
+
/// battle `update` for a single player.
|
|
95
|
+
pub const Summary = @import("gen1/calc.zig").Summary;
|
|
96
|
+
/// Null object pattern implementation of Generation I `Calc` which does nothing,
|
|
97
|
+
/// though damage calculator support should additionally be turned off
|
|
98
|
+
/// entirely via `options.calc`.
|
|
99
|
+
pub const NULL = @import("gen1/calc.zig").NULL;
|
|
100
|
+
};
|
|
52
101
|
/// Provides helpers for initializing Generation I Pokémon battles.
|
|
53
102
|
pub const helpers = @import("gen1/helpers.zig");
|
|
54
103
|
};
|
|
104
|
+
|
|
105
|
+
// Internal APIs used by other pkmn libraries, not actually part of the public API.
|
|
106
|
+
// NOTE: `pub usingnamespace struct { ... }` here results in a (false?) dependency loop
|
|
107
|
+
pub const js = if (options.internal) struct {
|
|
108
|
+
pub usingnamespace @import("common/js.zig");
|
|
109
|
+
} else struct {};
|
|
110
|
+
pub const bindings = if (options.internal) struct {
|
|
111
|
+
pub const node = @import("binding/node.zig");
|
|
112
|
+
pub const wasm = @import("binding/wasm.zig");
|
|
113
|
+
} else struct {};
|