@pkmn/engine 0.1.0-dev.645b4750 → 0.1.0-dev.6ba42cd5
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 -1
- package/README.md +12 -31
- package/build/pkg/addon/wasm.js.map +1 -1
- package/build/pkg/addon.d.ts +4 -4
- package/build/pkg/addon.js.map +1 -1
- package/build/tools/debug.js +19 -1
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/ui.jsx +1 -1
- package/build/tools/display/ui.jsx.map +1 -1
- package/build.zig +135 -225
- package/package.json +23 -21
- package/src/bin/install-pkmn-engine +22 -7
- package/src/lib/bindings/c.zig +27 -82
- package/src/lib/bindings/node.zig +7 -11
- package/src/lib/bindings/wasm.zig +6 -15
- package/src/lib/common/array.zig +5 -12
- package/src/lib/common/debug.zig +11 -21
- package/src/lib/common/js.zig +3 -9
- package/src/lib/common/optional.zig +11 -21
- package/src/lib/common/protocol.zig +176 -163
- package/src/lib/common/rational.zig +91 -173
- package/src/lib/common/util.zig +14 -46
- package/src/lib/gen1/calc.zig +46 -52
- package/src/lib/gen1/chance.zig +17 -32
- package/src/lib/gen1/data/types.zig +2 -2
- package/src/lib/gen1/data.zig +5 -5
- package/src/lib/gen1/helpers.zig +8 -10
- package/src/lib/gen1/mechanics.zig +23 -14
- package/src/lib/gen2/calc.zig +3 -6
- package/src/lib/gen2/chance.zig +12 -18
- package/src/lib/gen2/data/types.zig +6 -3
- package/src/lib/gen2/data.zig +8 -7
- package/src/lib/gen2/helpers.zig +4 -6
- package/src/lib/gen2/mechanics.zig +9 -9
- package/src/lib/napi.h +2 -0
- package/src/lib/node.zig +1 -5
- package/src/lib/pkmn.zig +91 -17
- package/src/lib/wasm.zig +2 -6
package/src/lib/gen2/calc.zig
CHANGED
|
@@ -15,9 +15,6 @@ const isPointerTo = util.isPointerTo;
|
|
|
15
15
|
const Player = common.Player;
|
|
16
16
|
const PointerType = util.PointerType;
|
|
17
17
|
|
|
18
|
-
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
19
|
-
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
20
|
-
|
|
21
18
|
/// Information relevant to damage calculation that occured during a Generation II battle `update`.
|
|
22
19
|
pub const Summaries = extern struct {
|
|
23
20
|
/// Relevant information for Player 1.
|
|
@@ -91,8 +88,8 @@ pub const Calc = struct {
|
|
|
91
88
|
};
|
|
92
89
|
|
|
93
90
|
return if (switch (@typeInfo(@TypeOf(val))) {
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
.@"enum" => val != .None,
|
|
92
|
+
.int => val != 0,
|
|
96
93
|
else => unreachable,
|
|
97
94
|
}) val else null;
|
|
98
95
|
}
|
|
@@ -148,6 +145,6 @@ fn ReturnType(comptime field: Action.Field) type {
|
|
|
148
145
|
return ?(switch (field) {
|
|
149
146
|
.damages => u8,
|
|
150
147
|
.critical_hits => Optional(bool),
|
|
151
|
-
else =>
|
|
148
|
+
else => @FieldType(Action, @tagName(field)),
|
|
152
149
|
});
|
|
153
150
|
}
|
package/src/lib/gen2/chance.zig
CHANGED
|
@@ -27,10 +27,6 @@ const Type = data.Type;
|
|
|
27
27
|
const Effectiveness = data.Effectiveness;
|
|
28
28
|
const TriAttack = data.TriAttack;
|
|
29
29
|
|
|
30
|
-
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
31
|
-
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
32
|
-
const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
|
|
33
|
-
|
|
34
30
|
/// Actions taken by a hypothetical "chance player" that convey information about which RNG events
|
|
35
31
|
/// were observed during a Generation II battle `update`. This can additionally be provided as input
|
|
36
32
|
/// to the `update` call to override the normal behavior of the RNG in order to force specific
|
|
@@ -57,15 +53,15 @@ pub const Actions = extern struct {
|
|
|
57
53
|
/// same shape if they have the same fields set (though those fields need not necessarily be
|
|
58
54
|
/// set to the same value).
|
|
59
55
|
pub fn matches(a: Actions, b: Actions) bool {
|
|
60
|
-
inline for (@
|
|
61
|
-
inline for (@
|
|
56
|
+
inline for (@typeInfo(Actions).@"struct".fields) |player| {
|
|
57
|
+
inline for (@typeInfo(Action).@"struct".fields) |field| {
|
|
62
58
|
const a_val = @field(@field(a, player.name), field.name);
|
|
63
59
|
const b_val = @field(@field(b, player.name), field.name);
|
|
64
60
|
|
|
65
61
|
switch (@typeInfo(@TypeOf(a_val))) {
|
|
66
|
-
|
|
62
|
+
.@"enum" => if ((@intFromEnum(a_val) > 0) != (@intFromEnum(b_val) > 0))
|
|
67
63
|
return false,
|
|
68
|
-
|
|
64
|
+
.int => if ((a_val > 0) != (b_val > 0)) return false,
|
|
69
65
|
else => unreachable,
|
|
70
66
|
}
|
|
71
67
|
}
|
|
@@ -73,7 +69,7 @@ pub const Actions = extern struct {
|
|
|
73
69
|
return true;
|
|
74
70
|
}
|
|
75
71
|
|
|
76
|
-
pub fn fmt(self: Actions, writer:
|
|
72
|
+
pub fn fmt(self: Actions, writer: *std.Io.Writer, shape: bool) !void {
|
|
77
73
|
try writer.writeAll("<P1 = ");
|
|
78
74
|
try self.p1.fmt(writer, shape);
|
|
79
75
|
try writer.writeAll(", P2 = ");
|
|
@@ -81,8 +77,7 @@ pub const Actions = extern struct {
|
|
|
81
77
|
try writer.writeAll(">");
|
|
82
78
|
}
|
|
83
79
|
|
|
84
|
-
pub fn format(a: Actions,
|
|
85
|
-
_ = .{ f, o };
|
|
80
|
+
pub fn format(a: Actions, w: *std.Io.Writer) !void {
|
|
86
81
|
try fmt(a, w, false);
|
|
87
82
|
}
|
|
88
83
|
};
|
|
@@ -186,18 +181,17 @@ pub const Action = packed struct(u128) {
|
|
|
186
181
|
|
|
187
182
|
pub const Field = std.meta.FieldEnum(Action);
|
|
188
183
|
|
|
189
|
-
pub fn format(a: Action,
|
|
190
|
-
_ = .{ f, o };
|
|
184
|
+
pub fn format(a: Action, w: *std.Io.Writer) !void {
|
|
191
185
|
try fmt(a, w, false);
|
|
192
186
|
}
|
|
193
187
|
|
|
194
|
-
pub fn fmt(self: Action, writer:
|
|
188
|
+
pub fn fmt(self: Action, writer: *std.Io.Writer, shape: bool) !void {
|
|
195
189
|
try writer.writeByte('(');
|
|
196
190
|
var printed = false;
|
|
197
|
-
inline for (@
|
|
191
|
+
inline for (@typeInfo(Action).@"struct".fields) |field| {
|
|
198
192
|
const val = @field(self, field.name);
|
|
199
193
|
switch (@typeInfo(@TypeOf(val))) {
|
|
200
|
-
|
|
194
|
+
.@"enum" => if (val != .None) {
|
|
201
195
|
if (printed) try writer.writeAll(", ");
|
|
202
196
|
if (shape) {
|
|
203
197
|
try writer.print("{s}:?", .{field.name});
|
|
@@ -211,7 +205,7 @@ pub const Action = packed struct(u128) {
|
|
|
211
205
|
}
|
|
212
206
|
printed = true;
|
|
213
207
|
},
|
|
214
|
-
|
|
208
|
+
.int => if (val != 0) {
|
|
215
209
|
if (printed) try writer.writeAll(", ");
|
|
216
210
|
if (shape) {
|
|
217
211
|
try writer.print("{s}:?", .{field.name});
|
|
@@ -786,7 +780,7 @@ pub fn expectProbability(r: anytype, p: u64, q: u64) !void {
|
|
|
786
780
|
|
|
787
781
|
r.reduce();
|
|
788
782
|
if (r.p != p or r.q != q) {
|
|
789
|
-
print("expected {d}/{d}, found {}\n", .{ p, q, r });
|
|
783
|
+
print("expected {d}/{d}, found {f}\n", .{ p, q, r });
|
|
790
784
|
return error.TestExpectedEqual;
|
|
791
785
|
}
|
|
792
786
|
}
|
|
@@ -172,9 +172,12 @@ pub const Type = enum(u8) {
|
|
|
172
172
|
return CHART[@intFromEnum(t1)][@intFromEnum(t2)];
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
/// The precedence order of Type `
|
|
176
|
-
pub fn precedence(
|
|
177
|
-
return
|
|
175
|
+
/// The precedence order of Type `t1` vs. Type `t2`.
|
|
176
|
+
pub fn precedence(t1: Type, t2: Type) u8 {
|
|
177
|
+
// The Ice vs. Fire matchup is out of order - return a higher
|
|
178
|
+
// number than anything else so that it sorts last correctly
|
|
179
|
+
if (t1 == .Ice and t2 == .Fire) return 18;
|
|
180
|
+
return PRECEDENCE[@intFromEnum(t2)];
|
|
178
181
|
}
|
|
179
182
|
|
|
180
183
|
/// The internal index of this Type used by Present.
|
package/src/lib/gen2/data.zig
CHANGED
|
@@ -57,7 +57,7 @@ pub fn Battle(comptime RNG: anytype) type {
|
|
|
57
57
|
turn: u16 = 0,
|
|
58
58
|
field: Field = .{},
|
|
59
59
|
|
|
60
|
-
_: [padding]u8 =
|
|
60
|
+
_: [padding]u8 = @splat(0),
|
|
61
61
|
|
|
62
62
|
pub fn side(self: anytype, player: Player) PointerType(@TypeOf(self), Side) {
|
|
63
63
|
assert(isPointerTo(self, Self));
|
|
@@ -100,13 +100,13 @@ pub const Weather = enum(u4) {
|
|
|
100
100
|
};
|
|
101
101
|
|
|
102
102
|
pub const Side = extern struct {
|
|
103
|
-
pokemon: [6]Pokemon =
|
|
103
|
+
pokemon: [6]Pokemon = @splat(.{}),
|
|
104
104
|
active: ActivePokemon align(8) = .{},
|
|
105
105
|
conditions: Conditions = .{},
|
|
106
106
|
// NB: wLastPlayerCounterMove / wLastEnemyCounterMove (wLastPlayerMove / wLastEnemyMove)
|
|
107
107
|
last_used_move: Move = .None,
|
|
108
108
|
|
|
109
|
-
_: [7]u8 =
|
|
109
|
+
_: [7]u8 = @splat(0),
|
|
110
110
|
|
|
111
111
|
const Conditions = packed struct(u32) {
|
|
112
112
|
Spikes: bool = false,
|
|
@@ -161,7 +161,7 @@ pub const Side = extern struct {
|
|
|
161
161
|
pub const ActivePokemon = extern struct {
|
|
162
162
|
volatiles: Volatiles align(4) = .{},
|
|
163
163
|
stats: Stats(u16) = .{},
|
|
164
|
-
moves: [4]MoveSlot =
|
|
164
|
+
moves: [4]MoveSlot = @splat(.{}),
|
|
165
165
|
boosts: Boosts = .{},
|
|
166
166
|
types: Types = .{},
|
|
167
167
|
species: Species = .None,
|
|
@@ -182,7 +182,7 @@ pub const ActivePokemon = extern struct {
|
|
|
182
182
|
|
|
183
183
|
pub const Pokemon = extern struct {
|
|
184
184
|
stats: Stats(u16) = .{},
|
|
185
|
-
moves: [4]MoveSlot =
|
|
185
|
+
moves: [4]MoveSlot = @splat(.{}),
|
|
186
186
|
types: Types = .{},
|
|
187
187
|
dvs: DVs = .{},
|
|
188
188
|
hp: u16 = 0,
|
|
@@ -449,8 +449,9 @@ test Types {
|
|
|
449
449
|
try expect(!Type.Steel.special());
|
|
450
450
|
try expect(Type.Dark.special());
|
|
451
451
|
|
|
452
|
-
try expectEqual(@as(u8, 3), Type.Water.
|
|
453
|
-
try expect(Type.
|
|
452
|
+
try expectEqual(@as(u8, 3), Type.precedence(.Water, .Water));
|
|
453
|
+
try expect(Type.precedence(.Poison, .Bug) > Type.precedence(.Poison, .Poison));
|
|
454
|
+
try expect(Type.precedence(.Ice, .Fire) > Type.precedence(.Ice, .Water));
|
|
454
455
|
|
|
455
456
|
try expectEqual(Effectiveness.Super, Type.effectiveness(.Ghost, .Psychic));
|
|
456
457
|
try expectEqual(Effectiveness.Super, Type.effectiveness(.Water, .Fire));
|
package/src/lib/gen2/helpers.zig
CHANGED
|
@@ -16,8 +16,6 @@ const showdown = options.showdown;
|
|
|
16
16
|
const Species = data.Species;
|
|
17
17
|
const Stats = data.Stats;
|
|
18
18
|
|
|
19
|
-
const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
|
|
20
|
-
|
|
21
19
|
pub const Options = struct {
|
|
22
20
|
cleric: bool = showdown,
|
|
23
21
|
};
|
|
@@ -74,7 +72,7 @@ pub fn prng(rand: *PSRNG) data.PRNG {
|
|
|
74
72
|
var carry: u8 = 0;
|
|
75
73
|
var div: u8 = 0;
|
|
76
74
|
|
|
77
|
-
var i:
|
|
75
|
+
var i: usize = 0;
|
|
78
76
|
while (i < seed.len) {
|
|
79
77
|
div = @intCast(timer >> 8);
|
|
80
78
|
// This is effectively @addWithOverflow but with three operands
|
|
@@ -142,7 +140,7 @@ pub const Pokemon = struct {
|
|
|
142
140
|
var pokemon = data.Pokemon{};
|
|
143
141
|
pokemon.species = p.species;
|
|
144
142
|
const species = Species.get(p.species);
|
|
145
|
-
inline for (@
|
|
143
|
+
inline for (@typeInfo(@TypeOf(pokemon.stats)).@"struct".fields) |field| {
|
|
146
144
|
const hp = comptime std.mem.eql(u8, field.name, "hp");
|
|
147
145
|
const spc =
|
|
148
146
|
comptime std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
|
|
@@ -183,7 +181,7 @@ pub const Pokemon = struct {
|
|
|
183
181
|
|
|
184
182
|
var stats: Stats(u16) = .{};
|
|
185
183
|
const dvs = gen1.DVs.random(rand);
|
|
186
|
-
inline for (@
|
|
184
|
+
inline for (@typeInfo(@TypeOf(stats)).@"struct".fields) |field| {
|
|
187
185
|
const hp = std.mem.eql(u8, field.name, "hp");
|
|
188
186
|
const spc = std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
|
|
189
187
|
@field(stats, field.name) = Stats(u16).calc(
|
|
@@ -195,7 +193,7 @@ pub const Pokemon = struct {
|
|
|
195
193
|
);
|
|
196
194
|
}
|
|
197
195
|
|
|
198
|
-
var ms
|
|
196
|
+
var ms: [4]MoveSlot = @splat(.{});
|
|
199
197
|
const n = if (rand.chance(u8, 1, 100)) rand.range(u4, 1, 3 + 1) else 4;
|
|
200
198
|
for (0..n) |i| {
|
|
201
199
|
var m: Move = .None;
|
|
@@ -682,7 +682,7 @@ pub fn adjustDamage(battle: anytype, player: Player, state: *State, _: anytype)
|
|
|
682
682
|
|
|
683
683
|
// Type effectiveness matchup precedence only matters with (NVE, SE)
|
|
684
684
|
if (!showdown and (eff1 + eff2) == Effectiveness.mismatch and
|
|
685
|
-
types.type1.precedence(
|
|
685
|
+
Type.precedence(state.type, types.type1) > Type.precedence(state.type, types.type2))
|
|
686
686
|
{
|
|
687
687
|
assert(eff2 != neutral);
|
|
688
688
|
d = d *% eff2 / 10;
|
|
@@ -1558,7 +1558,7 @@ pub const Effects = struct {
|
|
|
1558
1558
|
const last = battle.foe(player).lastMove(true);
|
|
1559
1559
|
const failed = volatiles.Encore or
|
|
1560
1560
|
(last == .None or last == .Struggle or
|
|
1561
|
-
|
|
1561
|
+
last == .Encore or .last == .MirrorMove);
|
|
1562
1562
|
if (failed) return options.log.fail(.{ foe_ident, .None });
|
|
1563
1563
|
|
|
1564
1564
|
var slot: u3 = 0;
|
|
@@ -3081,7 +3081,7 @@ pub const Rolls = struct {
|
|
|
3081
3081
|
}
|
|
3082
3082
|
|
|
3083
3083
|
// Conversion 2 can at most choose between 7 types (vs. a Grass-type attack)
|
|
3084
|
-
var CONVERSION_2: [7]Type =
|
|
3084
|
+
var CONVERSION_2: [7]Type = @splat(.@"???");
|
|
3085
3085
|
|
|
3086
3086
|
fn conversion2(battle: anytype, player: Player, mtype: Type, options: anytype) !Type {
|
|
3087
3087
|
var i: u8 = 0;
|
|
@@ -3506,11 +3506,11 @@ pub fn choices(battle: anytype, player: Player, request: Choice.Type, out: []Cho
|
|
|
3506
3506
|
},
|
|
3507
3507
|
.Switch => {
|
|
3508
3508
|
const side = battle.side(player);
|
|
3509
|
-
var slot:
|
|
3509
|
+
var slot: usize = 2;
|
|
3510
3510
|
while (slot <= 6) : (slot += 1) {
|
|
3511
3511
|
const id = side.order[slot - 1];
|
|
3512
3512
|
if (id == 0 or side.pokemon[id - 1].hp == 0) continue;
|
|
3513
|
-
out[n] = .{ .type = .Switch, .data = slot };
|
|
3513
|
+
out[n] = .{ .type = .Switch, .data = @intCast(slot) };
|
|
3514
3514
|
n += 1;
|
|
3515
3515
|
}
|
|
3516
3516
|
if (n == 0) {
|
|
@@ -3540,11 +3540,11 @@ pub fn choices(battle: anytype, player: Player, request: Choice.Type, out: []Cho
|
|
|
3540
3540
|
return n;
|
|
3541
3541
|
}
|
|
3542
3542
|
|
|
3543
|
-
var slot:
|
|
3543
|
+
var slot: usize = 2;
|
|
3544
3544
|
while (!active.volatiles.Trapped and slot <= 6) : (slot += 1) {
|
|
3545
3545
|
const id = side.order[slot - 1];
|
|
3546
3546
|
if (id == 0 or side.pokemon[id - 1].hp == 0) continue;
|
|
3547
|
-
out[n] = .{ .type = .Switch, .data = slot };
|
|
3547
|
+
out[n] = .{ .type = .Switch, .data = @intCast(slot) };
|
|
3548
3548
|
n += 1;
|
|
3549
3549
|
}
|
|
3550
3550
|
|
|
@@ -3577,7 +3577,7 @@ pub fn choices(battle: anytype, player: Player, request: Choice.Type, out: []Cho
|
|
|
3577
3577
|
const struggle =
|
|
3578
3578
|
m.id == .Bide and (m.pp == 0 or active.volatiles.disable.move == slot);
|
|
3579
3579
|
const s = if (struggle) 0 else slot;
|
|
3580
|
-
out[n] = .{ .type = .Move, .data = s };
|
|
3580
|
+
out[n] = .{ .type = .Move, .data = @intCast(s) };
|
|
3581
3581
|
n += 1;
|
|
3582
3582
|
return n;
|
|
3583
3583
|
}
|
|
@@ -3591,7 +3591,7 @@ pub fn choices(battle: anytype, player: Player, request: Choice.Type, out: []Cho
|
|
|
3591
3591
|
if (m.id == .None) break;
|
|
3592
3592
|
if (m.pp == 0) continue;
|
|
3593
3593
|
if (active.volatiles.disable.move == slot) continue;
|
|
3594
|
-
out[n] = .{ .type = .Move, .data = slot };
|
|
3594
|
+
out[n] = .{ .type = .Move, .data = @intCast(slot) };
|
|
3595
3595
|
n += 1;
|
|
3596
3596
|
}
|
|
3597
3597
|
// Struggle (Pokémon Showdown would use 'move 1' here)
|
package/src/lib/napi.h
ADDED
package/src/lib/node.zig
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
+
const c = @import("napi");
|
|
1
2
|
const js = @import("common/js.zig");
|
|
2
3
|
const node = @import("bindings/node.zig");
|
|
3
4
|
const std = @import("std");
|
|
4
5
|
|
|
5
6
|
const assert = std.debug.assert;
|
|
6
7
|
|
|
7
|
-
const c = @cImport({
|
|
8
|
-
@cDefine("NAPI_VERSION", "8");
|
|
9
|
-
@cInclude("node_api.h");
|
|
10
|
-
});
|
|
11
|
-
|
|
12
8
|
export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi_value {
|
|
13
9
|
const properties = [_]c.napi_property_descriptor{
|
|
14
10
|
js.Property.init("engine", .{ .value = node.register(env) }),
|
package/src/lib/pkmn.zig
CHANGED
|
@@ -22,9 +22,9 @@ pub const Choice = @import("common/data.zig").Choice;
|
|
|
22
22
|
/// considered terminal.
|
|
23
23
|
pub const Result = @import("common/data.zig").Result;
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
/// Helpers for working with bit-packed arrays of non-powers-of-2 types.
|
|
26
26
|
pub const Array = @import("common/array.zig").Array;
|
|
27
|
-
|
|
27
|
+
/// Optimized optional representation which stores the empty None value as a sentinel.
|
|
28
28
|
pub const Optional = @import("common/optional.zig").Optional;
|
|
29
29
|
|
|
30
30
|
/// Pokémon Showdown's RNG (backed by a Generation V & VI RNG).
|
|
@@ -32,31 +32,78 @@ pub const PSRNG = @import("common/rng.zig").PSRNG;
|
|
|
32
32
|
|
|
33
33
|
/// Namespace for helpers related to protocol message logging.
|
|
34
34
|
pub const protocol = if (options.internal) @import("common/protocol.zig") else struct {
|
|
35
|
-
/// Logs protocol information to its `
|
|
35
|
+
/// Logs protocol information to its `WriterT` during a battle update when
|
|
36
36
|
/// `options.log` is enabled.
|
|
37
37
|
pub const Log = @import("common/protocol.zig").Log;
|
|
38
|
-
///
|
|
39
|
-
///
|
|
40
|
-
/// `ByteStream.Writer` is **not** a `std.io.Writer` and should not be
|
|
41
|
-
/// used for general purpose writing.
|
|
42
|
-
pub const ByteStream = @import("common/protocol.zig").ByteStream;
|
|
43
|
-
/// `Log` type backed by the optimized `ByteStream.Writer`. Intended to be
|
|
44
|
-
/// intialized with a `LOGS_SIZE`-sized buffer.
|
|
38
|
+
/// `Log` type backed by the optimized `Writer`. Intended to be intialized with
|
|
39
|
+
/// a `LOGS_SIZE`-sized buffer.
|
|
45
40
|
pub const FixedLog = @import("common/protocol.zig").FixedLog;
|
|
46
|
-
///
|
|
47
|
-
///
|
|
48
|
-
///
|
|
41
|
+
/// Minimal logging helper optimized for efficiently writing the individual
|
|
42
|
+
/// protocol bytes into a fixed buffer. Note that this is **not** a
|
|
43
|
+
/// `std.Io.Writer` and should not be used for general purpose writing.
|
|
44
|
+
pub const Writer = @import("common/protocol.zig").Writer;
|
|
45
|
+
/// Null object pattern implementation of `Log` backed by a null writer.
|
|
46
|
+
/// Ignores anything sent to it, though protocol logging should additionally
|
|
47
|
+
/// be turned off entirely with `options.log`.
|
|
49
48
|
pub const NULL = @import("common/protocol.zig").NULL;
|
|
50
49
|
};
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
/// Specialization of a rational number used by the engine to compute probabilties.
|
|
52
|
+
pub const Rational = @import("common/rational.zig").Rational;
|
|
53
53
|
|
|
54
54
|
/// Namespace for cross-generation battle-related types.
|
|
55
55
|
pub const battle = @import("common/battle.zig");
|
|
56
56
|
|
|
57
57
|
/// Namespace for Generation I Pokémon.
|
|
58
58
|
pub const gen1 = struct {
|
|
59
|
-
|
|
59
|
+
const data = @import("gen1/data.zig");
|
|
60
|
+
/// The minimum size in bytes required to hold all Generation I choice options.
|
|
61
|
+
pub const MAX_CHOICES = data.MAX_CHOICES;
|
|
62
|
+
/// The maximum number of bytes possibly logged by a single Generation I update.
|
|
63
|
+
pub const MAX_LOGS = data.MAX_LOGS;
|
|
64
|
+
/// The optimal size in bytes required to hold all Generation I choice options.
|
|
65
|
+
/// At least as large as MAX_CHOICES.
|
|
66
|
+
pub const CHOICES_SIZE = data.CHOICES_SIZE;
|
|
67
|
+
/// The optimal size in bytes required to hold the largest amount of log data possible from a
|
|
68
|
+
/// single Generation I update. At least as large as MAX_LOGS.
|
|
69
|
+
pub const LOGS_SIZE = data.LOGS_SIZE;
|
|
70
|
+
/// Null object pattern implementation of pkmn.battle.Options for Generation I.
|
|
71
|
+
pub const NULL = data.NULL;
|
|
72
|
+
/// The pseudo random number generator used by Generation I.
|
|
73
|
+
pub const PRNG = data.PRNG;
|
|
74
|
+
/// Representation of a Generation I battle.
|
|
75
|
+
pub const Battle = data.Battle;
|
|
76
|
+
/// Representation of one side of a Generation I Pokémon battle.
|
|
77
|
+
pub const Side = data.Side;
|
|
78
|
+
/// Representation of the state for single Generation I Pokémon while active in battle.
|
|
79
|
+
pub const ActivePokemon = data.ActivePokemon;
|
|
80
|
+
/// Representation of the state for single Generation I Pokémon while inactive in the party.
|
|
81
|
+
pub const Pokemon = data.Pokemon;
|
|
82
|
+
/// Representation of a Generation I Pokémon's move slot in a battle.
|
|
83
|
+
pub const MoveSlot = data.MoveSlot;
|
|
84
|
+
/// Details required to detect desyncs based on the move last selected/executed by players.
|
|
85
|
+
pub const MoveDetails = data.MoveDetails;
|
|
86
|
+
/// Bitfield representation of a Generation I & II Pokémon's major status condition.
|
|
87
|
+
pub const Status = data.Status;
|
|
88
|
+
/// Bitfield representation of volatile statuses and associated data in Generation I.
|
|
89
|
+
pub const Volatiles = data.Volatiles;
|
|
90
|
+
/// Representation of a Pokémon's stats in Generation I.
|
|
91
|
+
pub const Stats = data.Stats;
|
|
92
|
+
/// Representation of a Pokémon's boosts in Generation I.
|
|
93
|
+
pub const Boosts = data.Boosts;
|
|
94
|
+
/// Representation of a Generation I Pokémon move.
|
|
95
|
+
pub const Move = data.Move;
|
|
96
|
+
/// Representation of a Generation I Pokémon species.
|
|
97
|
+
pub const Species = data.Species;
|
|
98
|
+
/// Representation of a Generation I type in Pokémon.
|
|
99
|
+
pub const Type = data.Type;
|
|
100
|
+
/// Representation of a Generation I Pokémon's typing.
|
|
101
|
+
pub const Types = data.Types;
|
|
102
|
+
/// Modifiers for the effectiveness of a type vs. another type in Pokémon.
|
|
103
|
+
pub const Effectiveness = data.Effectiveness;
|
|
104
|
+
/// Representation of a Generation I Pokémon's determinant values.
|
|
105
|
+
pub const DVs = data.DVs;
|
|
106
|
+
|
|
60
107
|
/// Tracks chance actions and their associated probability during a
|
|
61
108
|
/// Generation I battle update when `options.chance` is enabled.
|
|
62
109
|
pub const Chance = @import("gen1/chance.zig").Chance;
|
|
@@ -107,7 +154,34 @@ pub const gen1 = struct {
|
|
|
107
154
|
|
|
108
155
|
/// TODO
|
|
109
156
|
pub const gen2 = struct {
|
|
110
|
-
|
|
157
|
+
const data = @import("gen2/data.zig");
|
|
158
|
+
pub const MAX_CHOICES = data.MAX_CHOICES;
|
|
159
|
+
pub const MAX_LOGS = data.MAX_LOGS;
|
|
160
|
+
pub const CHOICES_SIZE = data.CHOICES_SIZE;
|
|
161
|
+
pub const LOGS_SIZE = data.LOGS_SIZE;
|
|
162
|
+
pub const NULL = data.NULL;
|
|
163
|
+
pub const PRNG = data.PRNG;
|
|
164
|
+
pub const Battle = data.Battle;
|
|
165
|
+
pub const Field = data.Field;
|
|
166
|
+
pub const Weather = data.Weather;
|
|
167
|
+
pub const Side = data.Side;
|
|
168
|
+
pub const ActivePokemon = data.ActivePokemon;
|
|
169
|
+
pub const Pokemon = data.Pokemon;
|
|
170
|
+
pub const Gender = data.Gender;
|
|
171
|
+
pub const DVs = data.DVs;
|
|
172
|
+
pub const MoveSlot = data.MoveSlot;
|
|
173
|
+
pub const Status = data.Status;
|
|
174
|
+
pub const TriAttack = data.TriAttack;
|
|
175
|
+
pub const Volatiles = data.Volatiles;
|
|
176
|
+
pub const Stats = data.Stats;
|
|
177
|
+
pub const Boosts = data.Boosts;
|
|
178
|
+
pub const Item = data.Item;
|
|
179
|
+
pub const Move = data.Move;
|
|
180
|
+
pub const Species = data.Species;
|
|
181
|
+
pub const Type = data.Type;
|
|
182
|
+
pub const Types = data.Types;
|
|
183
|
+
pub const Effectiveness = data.Effectiveness;
|
|
184
|
+
|
|
111
185
|
pub const Chance = @import("gen2/chance.zig").Chance;
|
|
112
186
|
pub const chance = struct {
|
|
113
187
|
pub const Actions = @import("gen2/chance.zig").Actions;
|
|
@@ -126,8 +200,8 @@ pub const gen2 = struct {
|
|
|
126
200
|
};
|
|
127
201
|
|
|
128
202
|
// Internal APIs used by other pkmn libraries, not actually part of the public API.
|
|
129
|
-
// NOTE: `pub usingnamespace struct { ... }` here results in a (false?) dependency loop
|
|
130
203
|
pub const js = if (options.internal) @import("common/js.zig") else {};
|
|
204
|
+
pub const util = if (options.internal) @import("common/util.zig") else {};
|
|
131
205
|
pub const bindings = if (options.internal) struct {
|
|
132
206
|
pub const c = @import("bindings/c.zig");
|
|
133
207
|
pub const node = @import("bindings/node.zig");
|
package/src/lib/wasm.zig
CHANGED
|
@@ -9,9 +9,5 @@ export const CALC = wasm.options.calc;
|
|
|
9
9
|
export const GEN1_CHOICES_SIZE = wasm.gen(1).CHOICES_SIZE;
|
|
10
10
|
export const GEN1_LOGS_SIZE = wasm.gen(1).LOGS_SIZE;
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
usingnamespace if (exportable) struct {
|
|
15
|
-
export const GEN1_update = wasm.gen(1).update;
|
|
16
|
-
export const GEN1_choices = wasm.gen(1).choices;
|
|
17
|
-
} else wasm.exports();
|
|
12
|
+
export const GEN1_update = wasm.gen(1).update;
|
|
13
|
+
export const GEN1_choices = wasm.gen(1).choices;
|