@pkmn/engine 0.1.0-dev.44a51703 → 0.1.0-dev.46307385
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 +53 -42
- package/build/pkg/addon.js +3 -2
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/layout.json +24 -2
- package/build/pkg/gen1.js +13 -16
- package/build/pkg/gen1.js.map +1 -1
- package/build.zig +75 -54
- package/package.json +23 -14
- package/src/bin/install-pkmn-engine +10 -5
- package/src/lib/binding/node.zig +39 -131
- package/src/lib/binding/wasm.zig +2 -0
- package/src/lib/common/battle.zig +17 -0
- package/src/lib/common/debug.zig +20 -11
- package/src/lib/common/js.zig +118 -0
- package/src/lib/common/optional.zig +60 -0
- package/src/lib/common/options.zig +9 -0
- package/src/lib/common/protocol.zig +48 -0
- package/src/lib/common/rational.zig +353 -0
- package/src/lib/common/rng.zig +5 -5
- package/src/lib/common/util.zig +12 -0
- package/src/lib/gen1/README.md +254 -176
- package/src/lib/gen1/calc.zig +427 -0
- package/src/lib/gen1/chance.zig +1044 -0
- package/src/lib/gen1/data.zig +45 -24
- package/src/lib/gen1/helpers.zig +581 -10
- package/src/lib/gen1/mechanics.zig +726 -448
- package/src/lib/gen2/README.md +12 -13
- package/src/lib/gen2/data.zig +22 -12
- package/src/lib/gen2/helpers.zig +3 -5
- package/src/lib/gen2/mechanics.zig +5 -4
- package/src/lib/pkmn.zig +61 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// Stores state required by optional features to the engine that can be passed to a generation's
|
|
2
|
+
/// `Battle.update` function. All generations generically support protocol logging (enabled via
|
|
3
|
+
/// `-Dlog`), chance actions and probability tracking (enabled via `-Dchance`), and damage
|
|
4
|
+
/// computation and chance overrides (`-Dcalc`), though the concrete types for these features are
|
|
5
|
+
/// generation dependent.
|
|
6
|
+
pub fn Options(comptime Log: type, comptime Chance: type, comptime Calc: type) type {
|
|
7
|
+
return struct { log: Log, chance: Chance, calc: Calc };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/// Helper to create a battle `Options` object with the provided `log`, `chance`, and `calc`.
|
|
11
|
+
pub fn options(
|
|
12
|
+
log: anytype,
|
|
13
|
+
chance: anytype,
|
|
14
|
+
calc: anytype,
|
|
15
|
+
) Options(@TypeOf(log), @TypeOf(chance), @TypeOf(calc)) {
|
|
16
|
+
return .{ .log = log, .chance = chance, .calc = calc };
|
|
17
|
+
}
|
package/src/lib/common/debug.zig
CHANGED
|
@@ -10,18 +10,27 @@ pub fn print(value: anytype) void {
|
|
|
10
10
|
|
|
11
11
|
nosuspend {
|
|
12
12
|
stderr.writeAll("\x1b[41m") catch return;
|
|
13
|
-
|
|
14
|
-
.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
if (@TypeOf(@src()) == @TypeOf(value)) {
|
|
14
|
+
stderr.print("{s} ({s}:{d}:{d})", .{
|
|
15
|
+
value.fn_name,
|
|
16
|
+
value.file,
|
|
17
|
+
value.line,
|
|
18
|
+
value.column,
|
|
19
|
+
}) catch return;
|
|
20
|
+
} else {
|
|
21
|
+
switch (@typeInfo(@TypeOf(value))) {
|
|
22
|
+
.Struct => |info| {
|
|
23
|
+
if (info.is_tuple) {
|
|
24
|
+
inline for (info.fields, 0..) |f, i| {
|
|
25
|
+
inspect(@field(value, f.name));
|
|
26
|
+
if (i < info.fields.len - 1) stderr.writeAll(" ") catch return;
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
inspect(value);
|
|
19
30
|
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
},
|
|
24
|
-
else => inspect(value),
|
|
31
|
+
},
|
|
32
|
+
else => inspect(value),
|
|
33
|
+
}
|
|
25
34
|
}
|
|
26
35
|
stderr.writeAll("\x1b[K\x1b[0m\n") catch return;
|
|
27
36
|
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
|
|
3
|
+
const assert = std.debug.assert;
|
|
4
|
+
|
|
5
|
+
const c = @cImport({
|
|
6
|
+
@cDefine("NAPI_VERSION", "8");
|
|
7
|
+
@cInclude("node_api.h");
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
pub const Array = struct {
|
|
11
|
+
pub fn init(env: c.napi_env, o: struct { length: ?usize }) c.napi_value {
|
|
12
|
+
var result: c.napi_value = undefined;
|
|
13
|
+
assert(c.napi_ok == if (o.length) |n|
|
|
14
|
+
c.napi_create_array_with_length(env, n, &result)
|
|
15
|
+
else
|
|
16
|
+
c.napi_create_array(env, &result));
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pub fn set(env: c.napi_env, array: c.napi_value, index: u32, value: c.napi_value) void {
|
|
21
|
+
assert(c.napi_set_element(env, array, index, value) == c.napi_ok);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
pub const Boolean = struct {
|
|
26
|
+
pub fn init(env: c.napi_env, value: bool) c.napi_value {
|
|
27
|
+
var result: c.napi_value = undefined;
|
|
28
|
+
assert(c.napi_get_boolean(env, value, &result) == c.napi_ok);
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
pub const Number = struct {
|
|
34
|
+
pub fn init(env: c.napi_env, value: anytype) c.napi_value {
|
|
35
|
+
const T = @TypeOf(value);
|
|
36
|
+
var result: c.napi_value = undefined;
|
|
37
|
+
assert(c.napi_ok == switch (@typeInfo(T)) {
|
|
38
|
+
.Int => |info| switch (info.bits) {
|
|
39
|
+
0...32 => switch (info.signedness) {
|
|
40
|
+
.signed => c.napi_create_int32(env, @as(i32, value), &result),
|
|
41
|
+
.unsigned => c.napi_create_uint32(env, @as(u32, value), &result),
|
|
42
|
+
},
|
|
43
|
+
33...52 => c.napi_create_int64(env, @as(i64, value), &result),
|
|
44
|
+
else => @compileError("int can't be represented as JS number"),
|
|
45
|
+
},
|
|
46
|
+
else => @compileError("expected number, got: " ++ @typeName(T)),
|
|
47
|
+
});
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
pub fn get(env: c.napi_env, value: c.napi_value, comptime T: type) T {
|
|
52
|
+
switch (@typeInfo(T)) {
|
|
53
|
+
.Int => |info| switch (info.bits) {
|
|
54
|
+
0...32 => switch (info.signedness) {
|
|
55
|
+
.signed => {
|
|
56
|
+
var result: i32 = undefined;
|
|
57
|
+
assert(c.napi_get_value_int32(env, value, &result) == c.napi_ok);
|
|
58
|
+
return if (info.bits == 32) result else @intCast(result);
|
|
59
|
+
},
|
|
60
|
+
.unsigned => {
|
|
61
|
+
var result: u32 = undefined;
|
|
62
|
+
assert(c.napi_get_value_uint32(env, value, &result) == c.napi_ok);
|
|
63
|
+
return if (info.bits == 32) result else @intCast(result);
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
33...63 => {
|
|
67
|
+
var result: i64 = undefined;
|
|
68
|
+
assert(c.napi_get_value_int64(env, value, &result) == c.napi_ok);
|
|
69
|
+
return @intCast(result);
|
|
70
|
+
},
|
|
71
|
+
else => {
|
|
72
|
+
var result: i64 = undefined;
|
|
73
|
+
assert(c.napi_get_value_int64(env, value, &result) == c.napi_ok);
|
|
74
|
+
return switch (info.signedness) {
|
|
75
|
+
.signed => value,
|
|
76
|
+
.unsigned => if (0 <= value) @intCast(value) else unreachable,
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
else => @compileError("expected number, got: " ++ @typeName(T)),
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
pub const Object = struct {
|
|
86
|
+
pub fn init(env: c.napi_env) c.napi_value {
|
|
87
|
+
var result: c.napi_value = undefined;
|
|
88
|
+
assert(c.napi_create_object(env, &result) == c.napi_ok);
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
pub const Property = union(enum) {
|
|
94
|
+
method: c.napi_callback,
|
|
95
|
+
value: c.napi_value,
|
|
96
|
+
|
|
97
|
+
pub fn init(comptime name: [:0]const u8, property: Property) c.napi_property_descriptor {
|
|
98
|
+
return .{
|
|
99
|
+
.utf8name = name,
|
|
100
|
+
.name = null,
|
|
101
|
+
.method = switch (property) {
|
|
102
|
+
.method => |m| m,
|
|
103
|
+
.value => null,
|
|
104
|
+
},
|
|
105
|
+
.getter = null,
|
|
106
|
+
.setter = null,
|
|
107
|
+
.value = switch (property) {
|
|
108
|
+
.method => null,
|
|
109
|
+
.value => |v| v,
|
|
110
|
+
},
|
|
111
|
+
.attributes = switch (property) {
|
|
112
|
+
.method => c.napi_default,
|
|
113
|
+
.value => c.napi_enumerable,
|
|
114
|
+
},
|
|
115
|
+
.data = null,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
|
|
3
|
+
const expect = std.testing.expect;
|
|
4
|
+
const assert = std.debug.assert;
|
|
5
|
+
|
|
6
|
+
// TODO: ziglang/zig#104
|
|
7
|
+
pub fn Optional(comptime T: type) type {
|
|
8
|
+
const fields = std.meta.fields(switch (@typeInfo(T)) {
|
|
9
|
+
.Bool => enum { false, true },
|
|
10
|
+
else => T,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
var enumFields: [fields.len + 1]std.builtin.Type.EnumField = undefined;
|
|
14
|
+
var decls = [_]std.builtin.Type.Declaration{};
|
|
15
|
+
|
|
16
|
+
enumFields[0] = .{ .name = "None", .value = 0 };
|
|
17
|
+
inline for (fields, 1..) |field, i| {
|
|
18
|
+
assert(!std.mem.eql(u8, field.name, "None"));
|
|
19
|
+
enumFields[i] = .{
|
|
20
|
+
.name = field.name,
|
|
21
|
+
.value = i,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return @Type(.{
|
|
26
|
+
.Enum = .{
|
|
27
|
+
.tag_type = std.math.IntFittingRange(0, fields.len + 1),
|
|
28
|
+
.fields = &enumFields,
|
|
29
|
+
.decls = &decls,
|
|
30
|
+
.is_exhaustive = true,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
test Optional {
|
|
36
|
+
try expect(@bitSizeOf(Optional(bool)) == 2);
|
|
37
|
+
|
|
38
|
+
const a: Optional(bool) = .true;
|
|
39
|
+
try expect(a != .None);
|
|
40
|
+
try expect(a == .true);
|
|
41
|
+
try expect(a != .false);
|
|
42
|
+
|
|
43
|
+
const b: Optional(bool) = .None;
|
|
44
|
+
try expect(b == .None);
|
|
45
|
+
try expect(b != .true);
|
|
46
|
+
try expect(b != .false);
|
|
47
|
+
|
|
48
|
+
const Player = @import("./data.zig").Player;
|
|
49
|
+
try expect(@bitSizeOf(Optional(Player)) == 2);
|
|
50
|
+
|
|
51
|
+
const p: Optional(Player) = .P2;
|
|
52
|
+
try expect(p != .None);
|
|
53
|
+
try expect(p != .P1);
|
|
54
|
+
try expect(p == .P2);
|
|
55
|
+
|
|
56
|
+
const q: Optional(Player) = .None;
|
|
57
|
+
try expect(q == .None);
|
|
58
|
+
try expect(q != .P1);
|
|
59
|
+
try expect(q != .P2);
|
|
60
|
+
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
const build_options = @import("build_options");
|
|
2
2
|
const root = @import("root");
|
|
3
3
|
|
|
4
|
+
/// Configures the behavior of the pkmn package.
|
|
4
5
|
pub const Options = struct {
|
|
5
6
|
showdown: ?bool = null,
|
|
6
7
|
log: ?bool = null,
|
|
8
|
+
chance: ?bool = null,
|
|
9
|
+
calc: ?bool = null,
|
|
7
10
|
advance: ?bool = null,
|
|
8
11
|
ebc: ?bool = null,
|
|
12
|
+
key: ?bool = null,
|
|
9
13
|
internal: ?bool = null,
|
|
10
14
|
};
|
|
11
15
|
|
|
@@ -13,9 +17,14 @@ pub const Options = struct {
|
|
|
13
17
|
pub const showdown = get("showdown", false);
|
|
14
18
|
/// Whether or not protocol message logging is enabled.
|
|
15
19
|
pub const log = get("log", false);
|
|
20
|
+
/// Whether or not update probability tracking is enabled.
|
|
21
|
+
pub const chance = get("chance", false);
|
|
22
|
+
/// Whether or not damage calculator support is enabled.
|
|
23
|
+
pub const calc = get("calc", false);
|
|
16
24
|
|
|
17
25
|
pub const advance = get("advance", true);
|
|
18
26
|
pub const ebc = get("ebc", true);
|
|
27
|
+
pub const key = get("key", false);
|
|
19
28
|
pub const internal = get("internal", false);
|
|
20
29
|
|
|
21
30
|
fn get(comptime name: []const u8, default: bool) bool {
|
|
@@ -102,6 +102,9 @@ pub const ArgType = enum(u8) {
|
|
|
102
102
|
// Gen 8
|
|
103
103
|
CanDynamax,
|
|
104
104
|
SwapSideConditions,
|
|
105
|
+
|
|
106
|
+
// Gen 9
|
|
107
|
+
Terastallize,
|
|
105
108
|
};
|
|
106
109
|
|
|
107
110
|
pub const Move = enum(u8) {
|
|
@@ -219,8 +222,12 @@ pub const Immune = enum(u8) {
|
|
|
219
222
|
OHKO,
|
|
220
223
|
};
|
|
221
224
|
|
|
225
|
+
/// Null object pattern implementation of `Log` backed by a `std.io.null_writer`.
|
|
226
|
+
/// Ignores anything sent to it, though protocol logging should additionally be turned off
|
|
227
|
+
/// entirely with `options.log`.
|
|
222
228
|
pub const NULL = Log(@TypeOf(std.io.null_writer)){ .writer = std.io.null_writer };
|
|
223
229
|
|
|
230
|
+
/// Logs protocol information to its `Writer` during a battle update when `options.log` is enabled.
|
|
224
231
|
pub fn Log(comptime Writer: type) type {
|
|
225
232
|
return struct {
|
|
226
233
|
const Self = @This();
|
|
@@ -231,6 +238,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
231
238
|
|
|
232
239
|
pub fn move(self: Self, source: ID, m: anytype, target: ID, from: anytype) Error!void {
|
|
233
240
|
if (!enabled) return;
|
|
241
|
+
|
|
234
242
|
assert(m != .None);
|
|
235
243
|
try self.writer.writeAll(&.{
|
|
236
244
|
@intFromEnum(ArgType.Move),
|
|
@@ -254,6 +262,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
254
262
|
|
|
255
263
|
pub fn switched(self: Self, ident: ID, pokemon: anytype) Error!void {
|
|
256
264
|
if (!enabled) return;
|
|
265
|
+
|
|
257
266
|
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Switch), @as(u8, @bitCast(ident)) });
|
|
258
267
|
try self.writer.writeAll(&.{ @intFromEnum(pokemon.species), pokemon.level });
|
|
259
268
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
@@ -263,6 +272,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
263
272
|
|
|
264
273
|
pub fn cant(self: Self, ident: ID, reason: Cant) Error!void {
|
|
265
274
|
if (!enabled) return;
|
|
275
|
+
|
|
266
276
|
assert(reason != .Disable);
|
|
267
277
|
try self.writer.writeAll(&.{
|
|
268
278
|
@intFromEnum(ArgType.Cant),
|
|
@@ -273,6 +283,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
273
283
|
|
|
274
284
|
pub fn disabled(self: Self, ident: ID, m: anytype) Error!void {
|
|
275
285
|
if (!enabled) return;
|
|
286
|
+
|
|
276
287
|
try self.writer.writeAll(&.{
|
|
277
288
|
@intFromEnum(ArgType.Cant),
|
|
278
289
|
@as(u8, @bitCast(ident)),
|
|
@@ -283,12 +294,14 @@ pub fn Log(comptime Writer: type) type {
|
|
|
283
294
|
|
|
284
295
|
pub fn faint(self: Self, ident: ID, done: bool) Error!void {
|
|
285
296
|
if (!enabled) return;
|
|
297
|
+
|
|
286
298
|
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Faint), @as(u8, @bitCast(ident)) });
|
|
287
299
|
if (done) try self.writer.writeByte(@intFromEnum(ArgType.None));
|
|
288
300
|
}
|
|
289
301
|
|
|
290
302
|
pub fn turn(self: Self, num: u16) Error!void {
|
|
291
303
|
if (!enabled) return;
|
|
304
|
+
|
|
292
305
|
try self.writer.writeByte(@intFromEnum(ArgType.Turn));
|
|
293
306
|
try self.writer.writeIntNative(u16, num);
|
|
294
307
|
try self.writer.writeByte(@intFromEnum(ArgType.None));
|
|
@@ -296,6 +309,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
296
309
|
|
|
297
310
|
pub fn win(self: Self, player: Player) Error!void {
|
|
298
311
|
if (!enabled) return;
|
|
312
|
+
|
|
299
313
|
try self.writer.writeAll(&.{
|
|
300
314
|
@intFromEnum(ArgType.Win),
|
|
301
315
|
@intFromEnum(player),
|
|
@@ -305,11 +319,13 @@ pub fn Log(comptime Writer: type) type {
|
|
|
305
319
|
|
|
306
320
|
pub fn tie(self: Self) Error!void {
|
|
307
321
|
if (!enabled) return;
|
|
322
|
+
|
|
308
323
|
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Tie), @intFromEnum(ArgType.None) });
|
|
309
324
|
}
|
|
310
325
|
|
|
311
326
|
pub fn damage(self: Self, ident: ID, pokemon: anytype, reason: Damage) Error!void {
|
|
312
327
|
if (!enabled) return;
|
|
328
|
+
|
|
313
329
|
assert(@intFromEnum(reason) <= @intFromEnum(Damage.LeechSeed));
|
|
314
330
|
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @as(u8, @bitCast(ident)) });
|
|
315
331
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
@@ -325,6 +341,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
325
341
|
source: ID,
|
|
326
342
|
) Error!void {
|
|
327
343
|
if (!enabled) return;
|
|
344
|
+
|
|
328
345
|
assert(@intFromEnum(reason) == @intFromEnum(Damage.RecoilOf));
|
|
329
346
|
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @as(u8, @bitCast(ident)) });
|
|
330
347
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
@@ -338,6 +355,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
338
355
|
|
|
339
356
|
pub fn heal(self: Self, ident: ID, pokemon: anytype, reason: Heal) Error!void {
|
|
340
357
|
if (!enabled) return;
|
|
358
|
+
|
|
341
359
|
assert(reason != .Drain);
|
|
342
360
|
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(ident)) });
|
|
343
361
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
@@ -347,6 +365,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
347
365
|
|
|
348
366
|
pub fn drain(self: Self, source: ID, pokemon: anytype, target: ID) Error!void {
|
|
349
367
|
if (!enabled) return;
|
|
368
|
+
|
|
350
369
|
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(source)) });
|
|
351
370
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
352
371
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
@@ -359,6 +378,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
359
378
|
|
|
360
379
|
pub fn status(self: Self, ident: ID, value: u8, reason: Status) Error!void {
|
|
361
380
|
if (!enabled) return;
|
|
381
|
+
|
|
362
382
|
assert(reason != .From);
|
|
363
383
|
try self.writer.writeAll(&.{
|
|
364
384
|
@intFromEnum(ArgType.Status),
|
|
@@ -370,6 +390,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
370
390
|
|
|
371
391
|
pub fn statusFrom(self: Self, ident: ID, value: u8, m: anytype) Error!void {
|
|
372
392
|
if (!enabled) return;
|
|
393
|
+
|
|
373
394
|
try self.writer.writeAll(&.{
|
|
374
395
|
@intFromEnum(ArgType.Status),
|
|
375
396
|
@as(u8, @bitCast(ident)),
|
|
@@ -381,6 +402,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
381
402
|
|
|
382
403
|
pub fn curestatus(self: Self, ident: ID, value: u8, reason: CureStatus) Error!void {
|
|
383
404
|
if (!enabled) return;
|
|
405
|
+
|
|
384
406
|
try self.writer.writeAll(&.{
|
|
385
407
|
@intFromEnum(ArgType.CureStatus),
|
|
386
408
|
@as(u8, @bitCast(ident)),
|
|
@@ -391,6 +413,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
391
413
|
|
|
392
414
|
pub fn boost(self: Self, ident: ID, reason: Boost, num: i8) Error!void {
|
|
393
415
|
if (!enabled) return;
|
|
416
|
+
|
|
394
417
|
assert(num != 0 and (reason != .Rage or num > 0));
|
|
395
418
|
try self.writer.writeAll(&.{
|
|
396
419
|
@intFromEnum(ArgType.Boost),
|
|
@@ -402,11 +425,13 @@ pub fn Log(comptime Writer: type) type {
|
|
|
402
425
|
|
|
403
426
|
pub fn clearallboost(self: Self) Error!void {
|
|
404
427
|
if (!enabled) return;
|
|
428
|
+
|
|
405
429
|
try self.writer.writeAll(&.{@intFromEnum(ArgType.ClearAllBoost)});
|
|
406
430
|
}
|
|
407
431
|
|
|
408
432
|
pub fn fail(self: Self, ident: ID, reason: Fail) Error!void {
|
|
409
433
|
if (!enabled) return;
|
|
434
|
+
|
|
410
435
|
try self.writer.writeAll(&.{
|
|
411
436
|
@intFromEnum(ArgType.Fail),
|
|
412
437
|
@as(u8, @bitCast(ident)),
|
|
@@ -416,11 +441,13 @@ pub fn Log(comptime Writer: type) type {
|
|
|
416
441
|
|
|
417
442
|
pub fn miss(self: Self, source: ID) Error!void {
|
|
418
443
|
if (!enabled) return;
|
|
444
|
+
|
|
419
445
|
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Miss), @as(u8, @bitCast(source)) });
|
|
420
446
|
}
|
|
421
447
|
|
|
422
448
|
pub fn hitcount(self: Self, ident: ID, num: u8) Error!void {
|
|
423
449
|
if (!enabled) return;
|
|
450
|
+
|
|
424
451
|
try self.writer.writeAll(&.{
|
|
425
452
|
@intFromEnum(ArgType.HitCount),
|
|
426
453
|
@as(u8, @bitCast(ident)),
|
|
@@ -430,6 +457,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
430
457
|
|
|
431
458
|
pub fn prepare(self: Self, source: ID, m: anytype) Error!void {
|
|
432
459
|
if (!enabled) return;
|
|
460
|
+
|
|
433
461
|
try self.writer.writeAll(&.{
|
|
434
462
|
@intFromEnum(ArgType.Prepare),
|
|
435
463
|
@as(u8, @bitCast(source)),
|
|
@@ -439,6 +467,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
439
467
|
|
|
440
468
|
pub fn mustrecharge(self: Self, ident: ID) Error!void {
|
|
441
469
|
if (!enabled) return;
|
|
470
|
+
|
|
442
471
|
try self.writer.writeAll(&.{
|
|
443
472
|
@intFromEnum(ArgType.MustRecharge),
|
|
444
473
|
@as(u8, @bitCast(ident)),
|
|
@@ -447,6 +476,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
447
476
|
|
|
448
477
|
pub fn activate(self: Self, ident: ID, reason: Activate) Error!void {
|
|
449
478
|
if (!enabled) return;
|
|
479
|
+
|
|
450
480
|
try self.writer.writeAll(&.{
|
|
451
481
|
@intFromEnum(ArgType.Activate),
|
|
452
482
|
@as(u8, @bitCast(ident)),
|
|
@@ -456,11 +486,13 @@ pub fn Log(comptime Writer: type) type {
|
|
|
456
486
|
|
|
457
487
|
pub fn fieldactivate(self: Self) Error!void {
|
|
458
488
|
if (!enabled) return;
|
|
489
|
+
|
|
459
490
|
try self.writer.writeAll(&.{@intFromEnum(ArgType.FieldActivate)});
|
|
460
491
|
}
|
|
461
492
|
|
|
462
493
|
pub fn start(self: Self, ident: ID, reason: Start) Error!void {
|
|
463
494
|
if (!enabled) return;
|
|
495
|
+
|
|
464
496
|
assert(@intFromEnum(reason) < @intFromEnum(Start.TypeChange));
|
|
465
497
|
try self.writer.writeAll(&.{
|
|
466
498
|
@intFromEnum(ArgType.Start),
|
|
@@ -471,6 +503,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
471
503
|
|
|
472
504
|
pub fn typechange(self: Self, source: ID, types: anytype, target: ID) Error!void {
|
|
473
505
|
if (!enabled) return;
|
|
506
|
+
|
|
474
507
|
try self.writer.writeAll(&.{
|
|
475
508
|
@intFromEnum(ArgType.Start),
|
|
476
509
|
@as(u8, @bitCast(source)),
|
|
@@ -482,6 +515,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
482
515
|
|
|
483
516
|
pub fn startEffect(self: Self, ident: ID, reason: Start, m: anytype) Error!void {
|
|
484
517
|
if (!enabled) return;
|
|
518
|
+
|
|
485
519
|
assert(@intFromEnum(reason) > @intFromEnum(Start.TypeChange));
|
|
486
520
|
try self.writer.writeAll(&.{
|
|
487
521
|
@intFromEnum(ArgType.Start),
|
|
@@ -493,6 +527,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
493
527
|
|
|
494
528
|
pub fn end(self: Self, ident: ID, reason: End) Error!void {
|
|
495
529
|
if (!enabled) return;
|
|
530
|
+
|
|
496
531
|
try self.writer.writeAll(&.{
|
|
497
532
|
@intFromEnum(ArgType.End),
|
|
498
533
|
@as(u8, @bitCast(ident)),
|
|
@@ -502,16 +537,19 @@ pub fn Log(comptime Writer: type) type {
|
|
|
502
537
|
|
|
503
538
|
pub fn ohko(self: Self) Error!void {
|
|
504
539
|
if (!enabled) return;
|
|
540
|
+
|
|
505
541
|
try self.writer.writeAll(&.{@intFromEnum(ArgType.OHKO)});
|
|
506
542
|
}
|
|
507
543
|
|
|
508
544
|
pub fn crit(self: Self, ident: ID) Error!void {
|
|
509
545
|
if (!enabled) return;
|
|
546
|
+
|
|
510
547
|
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Crit), @as(u8, @bitCast(ident)) });
|
|
511
548
|
}
|
|
512
549
|
|
|
513
550
|
pub fn supereffective(self: Self, ident: ID) Error!void {
|
|
514
551
|
if (!enabled) return;
|
|
552
|
+
|
|
515
553
|
try self.writer.writeAll(&.{
|
|
516
554
|
@intFromEnum(ArgType.SuperEffective),
|
|
517
555
|
@as(u8, @bitCast(ident)),
|
|
@@ -520,6 +558,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
520
558
|
|
|
521
559
|
pub fn resisted(self: Self, ident: ID) Error!void {
|
|
522
560
|
if (!enabled) return;
|
|
561
|
+
|
|
523
562
|
try self.writer.writeAll(&.{
|
|
524
563
|
@intFromEnum(ArgType.Resisted),
|
|
525
564
|
@as(u8, @bitCast(ident)),
|
|
@@ -528,6 +567,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
528
567
|
|
|
529
568
|
pub fn immune(self: Self, ident: ID, reason: Immune) Error!void {
|
|
530
569
|
if (!enabled) return;
|
|
570
|
+
|
|
531
571
|
try self.writer.writeAll(&.{
|
|
532
572
|
@intFromEnum(ArgType.Immune),
|
|
533
573
|
@as(u8, @bitCast(ident)),
|
|
@@ -537,6 +577,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
537
577
|
|
|
538
578
|
pub fn transform(self: Self, source: ID, target: ID) Error!void {
|
|
539
579
|
if (!enabled) return;
|
|
580
|
+
|
|
540
581
|
try self.writer.writeAll(&.{
|
|
541
582
|
@intFromEnum(ArgType.Transform),
|
|
542
583
|
@as(u8, @bitCast(source)),
|
|
@@ -546,18 +587,24 @@ pub fn Log(comptime Writer: type) type {
|
|
|
546
587
|
|
|
547
588
|
pub fn laststill(self: Self) Error!void {
|
|
548
589
|
if (!enabled) return;
|
|
590
|
+
|
|
549
591
|
try self.writer.writeAll(&.{@intFromEnum(ArgType.LastStill)});
|
|
550
592
|
}
|
|
551
593
|
|
|
552
594
|
pub fn lastmiss(self: Self) Error!void {
|
|
553
595
|
if (!enabled) return;
|
|
596
|
+
|
|
554
597
|
try self.writer.writeAll(&.{@intFromEnum(ArgType.LastMiss)});
|
|
555
598
|
}
|
|
556
599
|
};
|
|
557
600
|
}
|
|
558
601
|
|
|
602
|
+
/// `Log` type backed by the optimized `ByteStream.Writer`.
|
|
559
603
|
pub const FixedLog = Log(ByteStream.Writer);
|
|
560
604
|
|
|
605
|
+
/// Stripped down version of `std.io.FixedBufferStream` optimized for efficiently writing the
|
|
606
|
+
/// individual protocol bytes. Note that the `ByteStream.Writer` is **not** a `std.io.Writer` and
|
|
607
|
+
/// should not be used for general purpose writing.
|
|
561
608
|
pub const ByteStream = struct {
|
|
562
609
|
buffer: []u8,
|
|
563
610
|
pos: usize = 0,
|
|
@@ -855,6 +902,7 @@ pub fn expectLog(
|
|
|
855
902
|
offset: usize,
|
|
856
903
|
) !void {
|
|
857
904
|
if (!enabled) return;
|
|
905
|
+
|
|
858
906
|
const color = color: {
|
|
859
907
|
if (std.process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) {
|
|
860
908
|
break :color true;
|