@pkmn/engine 0.1.0-dev.deda8593 → 0.1.0-dev.e0a786f8
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 +9 -6
- 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 +34 -65
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/layout.json +15 -2
- package/build/pkg/data/protocol.json +23 -9
- package/build/pkg/data.d.ts +23 -1
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.d.ts +15 -18
- package/build/pkg/gen1.js +28 -19
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +40 -90
- 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 +105 -103
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +52 -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 +330 -85
- package/package.json +54 -135
- package/src/bin/install-pkmn-engine +10 -7
- package/src/bin/pkmn-debug +1 -1
- package/src/lib/bindings/c.zig +255 -0
- package/src/lib/bindings/node.zig +121 -0
- package/src/lib/bindings/wasm.zig +59 -0
- package/src/lib/common/array.zig +77 -0
- package/src/lib/common/data.zig +8 -8
- package/src/lib/common/debug.zig +39 -8
- package/src/lib/common/js.zig +4 -2
- package/src/lib/common/optional.zig +13 -9
- package/src/lib/common/options.zig +4 -0
- package/src/lib/common/protocol.zig +45 -44
- package/src/lib/common/rational.zig +323 -157
- package/src/lib/common/rng.zig +5 -7
- package/src/lib/common/util.zig +60 -1
- package/src/lib/gen1/calc.zig +527 -161
- package/src/lib/gen1/chance.zig +366 -240
- package/src/lib/gen1/data/moves.zig +2 -4
- package/src/lib/gen1/data/species.zig +1 -3
- package/src/lib/gen1/data/types.zig +1 -2
- package/src/lib/gen1/data.zig +35 -38
- package/src/lib/gen1/helpers.zig +17 -554
- package/src/lib/gen1/mechanics.zig +280 -193
- package/src/lib/gen2/calc.zig +37 -27
- package/src/lib/gen2/chance.zig +90 -503
- package/src/lib/gen2/data/items.zig +1 -3
- package/src/lib/gen2/data/moves.zig +2 -4
- package/src/lib/gen2/data/species.zig +1 -3
- package/src/lib/gen2/data/types.zig +1 -2
- package/src/lib/gen2/data.zig +26 -29
- package/src/lib/gen2/generated.zig +18 -23
- package/src/lib/gen2/helpers.zig +9 -18
- package/src/lib/gen2/mechanics.zig +88 -115
- package/src/lib/node.zig +3 -116
- package/src/lib/pkmn.zig +14 -7
- package/src/lib/wasm.zig +13 -9
- package/src/tools/display/dom.ts +93 -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/test/display/pkmn.html.tmpl +0 -368
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const pkmn = @import("../pkmn.zig");
|
|
2
|
+
const std = @import("std");
|
|
3
|
+
|
|
4
|
+
const assert = std.debug.assert;
|
|
5
|
+
|
|
6
|
+
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
7
|
+
const Strong = if (@hasField(std.builtin.GlobalLinkage, "strong")) .strong else .Strong;
|
|
8
|
+
|
|
9
|
+
pub const options = pkmn.options;
|
|
10
|
+
|
|
11
|
+
pub fn gen(comptime num: comptime_int) type {
|
|
12
|
+
const g = @field(pkmn, "gen" ++ std.fmt.comptimePrint("{d}", .{num}));
|
|
13
|
+
return struct {
|
|
14
|
+
pub const CHOICES_SIZE = size(g.CHOICES_SIZE);
|
|
15
|
+
pub const LOGS_SIZE = size(g.LOGS_SIZE);
|
|
16
|
+
|
|
17
|
+
pub fn update(
|
|
18
|
+
battle: *g.Battle(g.PRNG),
|
|
19
|
+
c1: pkmn.Choice,
|
|
20
|
+
c2: pkmn.Choice,
|
|
21
|
+
options_: ?[*]u8,
|
|
22
|
+
) callconv(.C) pkmn.Result {
|
|
23
|
+
return (if (options_) |o| result: {
|
|
24
|
+
const buf = @as([*]u8, @ptrCast(o))[0..g.LOGS_SIZE];
|
|
25
|
+
var stream: pkmn.protocol.ByteStream = .{ .buffer = buf };
|
|
26
|
+
// TODO: extract out
|
|
27
|
+
var opts = pkmn.battle.options(
|
|
28
|
+
pkmn.protocol.FixedLog{ .writer = stream.writer() },
|
|
29
|
+
g.chance.NULL,
|
|
30
|
+
g.calc.NULL,
|
|
31
|
+
);
|
|
32
|
+
break :result battle.update(c1, c2, &opts);
|
|
33
|
+
} else battle.update(c1, c2, &g.NULL)) catch unreachable;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pub fn choices(
|
|
37
|
+
battle: *g.Battle(g.PRNG),
|
|
38
|
+
player: u8,
|
|
39
|
+
request: u8,
|
|
40
|
+
buf: [*]u8,
|
|
41
|
+
) callconv(.C) u8 {
|
|
42
|
+
assert(player <= @field(@typeInfo(pkmn.Player), @tagName(Enum)).fields.len);
|
|
43
|
+
assert(request <= @field(@typeInfo(pkmn.Choice.Type), @tagName(Enum)).fields.len);
|
|
44
|
+
|
|
45
|
+
const n = CHOICES_SIZE;
|
|
46
|
+
return battle.choices(@enumFromInt(player), @enumFromInt(request), @ptrCast(buf[0..n]));
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
pub fn exports() type {
|
|
52
|
+
@export(gen(1).update, .{ .name = "GEN1_update", .linkage = Strong });
|
|
53
|
+
@export(gen(1).choices, .{ .name = "GEN1_choices", .linkage = Strong });
|
|
54
|
+
return struct {};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
fn size(n: usize) u32 {
|
|
58
|
+
return std.math.ceilPowerOfTwo(u32, @as(u32, @intCast(n))) catch unreachable;
|
|
59
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
|
|
3
|
+
const expectEqual = std.testing.expectEqual;
|
|
4
|
+
const assert = std.debug.assert;
|
|
5
|
+
|
|
6
|
+
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
7
|
+
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
8
|
+
|
|
9
|
+
/// Helpers for working with bit-packed arrays of non-powers-of-2 types.
|
|
10
|
+
/// NOTE: ziglang/zig#12547
|
|
11
|
+
pub fn Array(comptime n: comptime_int, comptime U: type) type {
|
|
12
|
+
return struct {
|
|
13
|
+
const size = @bitSizeOf(U);
|
|
14
|
+
const options: std.builtin.Type.Int = .{ .signedness = .unsigned, .bits = size * n };
|
|
15
|
+
pub const T = @Type(if (@hasField(std.builtin.Type, "int"))
|
|
16
|
+
.{ .int = options }
|
|
17
|
+
else
|
|
18
|
+
.{ .Int = options });
|
|
19
|
+
|
|
20
|
+
/// Returns the value stored at index `i` in the array `a`.
|
|
21
|
+
pub fn get(a: T, i: usize) U {
|
|
22
|
+
assert(i < n);
|
|
23
|
+
const shift = i * size;
|
|
24
|
+
const mask: T = (1 << size) - 1;
|
|
25
|
+
const result = (a >> @intCast(shift)) & mask;
|
|
26
|
+
return switch (@typeInfo(U)) {
|
|
27
|
+
Enum => @enumFromInt(result),
|
|
28
|
+
Int => @intCast(result),
|
|
29
|
+
else => unreachable,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// Sets the value at index `i` to `val` in the array `a`.
|
|
34
|
+
pub fn set(a: T, i: usize, val: U) T {
|
|
35
|
+
assert(i < n);
|
|
36
|
+
const v: T = switch (@typeInfo(U)) {
|
|
37
|
+
Enum => @intFromEnum(val),
|
|
38
|
+
Int => @intCast(val),
|
|
39
|
+
else => unreachable,
|
|
40
|
+
};
|
|
41
|
+
const shift = i * size;
|
|
42
|
+
const mask: T = @as(T, @intCast((1 << size) - 1)) << @intCast(shift);
|
|
43
|
+
const result: T = a & ~mask;
|
|
44
|
+
return result | (v << @intCast(shift));
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
test Array {
|
|
50
|
+
const A = Array(5, u8);
|
|
51
|
+
var a: A.T = 0;
|
|
52
|
+
try expectEqual(u40, @TypeOf(a));
|
|
53
|
+
|
|
54
|
+
a = A.set(a, 4, 241);
|
|
55
|
+
try expectEqual(@as(u8, 241), A.get(a, 4));
|
|
56
|
+
a = A.set(a, 4, 1);
|
|
57
|
+
try expectEqual(@as(u8, 1), A.get(a, 4));
|
|
58
|
+
|
|
59
|
+
for (0..5) |i| a = A.set(a, i, @intCast(i));
|
|
60
|
+
for (0..5) |i| try expectEqual(@as(u8, @intCast(i)), A.get(a, i));
|
|
61
|
+
|
|
62
|
+
const Optional = @import("optional.zig").Optional;
|
|
63
|
+
|
|
64
|
+
const B = Array(4, Optional(bool));
|
|
65
|
+
var b: B.T = 0;
|
|
66
|
+
try expectEqual(u8, @TypeOf(b));
|
|
67
|
+
|
|
68
|
+
b = B.set(b, 2, .true);
|
|
69
|
+
try expectEqual(Optional(bool).None, B.get(b, 1));
|
|
70
|
+
try expectEqual(Optional(bool).true, B.get(b, 2));
|
|
71
|
+
try expectEqual(@as(u8, 0b00100000), b);
|
|
72
|
+
b = B.set(b, 2, .None);
|
|
73
|
+
b = B.set(b, 0, .false);
|
|
74
|
+
try expectEqual(Optional(bool).None, B.get(b, 2));
|
|
75
|
+
try expectEqual(Optional(bool).false, B.get(b, 0));
|
|
76
|
+
try expectEqual(@as(u8, 0b0000001), b);
|
|
77
|
+
}
|
package/src/lib/common/data.zig
CHANGED
|
@@ -22,8 +22,8 @@ pub const Player = enum(u1) {
|
|
|
22
22
|
|
|
23
23
|
test Player {
|
|
24
24
|
try expectEqual(Player.P2, Player.P1.foe());
|
|
25
|
-
try expectEqual(0b0001, @as(u8, @bitCast(Player.P1.ident(1))));
|
|
26
|
-
try expectEqual(0b1101, @as(u8, @bitCast(Player.P2.ident(5))));
|
|
25
|
+
try expectEqual(@as(u8, 0b0001), @as(u8, @bitCast(Player.P1.ident(1))));
|
|
26
|
+
try expectEqual(@as(u8, 0b1101), @as(u8, @bitCast(Player.P2.ident(5))));
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/// An identifier for a specific Pokémon in battle.
|
|
@@ -46,8 +46,8 @@ pub const ID = packed struct(u8) {
|
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
test ID {
|
|
49
|
-
try expectEqual(0b0001, @as(u8, @bitCast(ID{ .player = .P1, .id = 1 })));
|
|
50
|
-
try expectEqual(0b1101, @as(u8, @bitCast(ID{ .player = .P2, .id = 5 })));
|
|
49
|
+
try expectEqual(@as(u8, 0b0001), @as(u8, @bitCast(ID{ .player = .P1, .id = 1 })));
|
|
50
|
+
try expectEqual(@as(u8, 0b1101), @as(u8, @bitCast(ID{ .player = .P2, .id = 5 })));
|
|
51
51
|
const id: ID = .{ .player = .P2, .id = 4 };
|
|
52
52
|
try expectEqual(id, ID.from(id.int()));
|
|
53
53
|
}
|
|
@@ -76,8 +76,8 @@ test Choice {
|
|
|
76
76
|
const p2: Choice = .{ .type = .Switch, .data = 5 };
|
|
77
77
|
try expectEqual(5, p2.data);
|
|
78
78
|
try expectEqual(Choice.Type.Move, p1.type);
|
|
79
|
-
try expectEqual(0b0001_0001, @as(u8, @bitCast(p1)));
|
|
80
|
-
try expectEqual(0b0001_0110, @as(u8, @bitCast(p2)));
|
|
79
|
+
try expectEqual(@as(u8, 0b0001_0001), @as(u8, @bitCast(p1)));
|
|
80
|
+
try expectEqual(@as(u8, 0b0001_0110), @as(u8, @bitCast(p2)));
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/// The result of the battle - all results other than 'None' should be considered terminal.
|
|
@@ -112,6 +112,6 @@ pub const Result = packed struct(u8) {
|
|
|
112
112
|
};
|
|
113
113
|
|
|
114
114
|
test Result {
|
|
115
|
-
try expectEqual(0b0101_0000, @as(u8, @bitCast(Result.Default)));
|
|
116
|
-
try expectEqual(0b1000_0000, @as(u8, @bitCast(Result{ .p2 = .Switch })));
|
|
115
|
+
try expectEqual(@as(u8, 0b0101_0000), @as(u8, @bitCast(Result.Default)));
|
|
116
|
+
try expectEqual(@as(u8, 0b1000_0000), @as(u8, @bitCast(Result{ .p2 = .Switch })));
|
|
117
117
|
}
|
package/src/lib/common/debug.zig
CHANGED
|
@@ -3,9 +3,19 @@ const std = @import("std");
|
|
|
3
3
|
const debug = std.debug;
|
|
4
4
|
const io = std.io;
|
|
5
5
|
|
|
6
|
+
const Array = if (@hasField(std.builtin.Type, "array")) .array else .Array;
|
|
7
|
+
const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum;
|
|
8
|
+
const Optional = if (@hasField(std.builtin.Type, "optional")) .optional else .Optional;
|
|
9
|
+
const Pointer = if (@hasField(std.builtin.Type, "pointer")) .pointer else .Pointer;
|
|
10
|
+
const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
|
|
11
|
+
const Union = if (@hasField(std.builtin.Type, "union")) .@"union" else .Union;
|
|
12
|
+
|
|
6
13
|
pub fn print(value: anytype) void {
|
|
7
|
-
debug.lockStdErr();
|
|
8
|
-
defer debug
|
|
14
|
+
if (@hasDecl(debug, "lockStdErr")) debug.lockStdErr() else debug.getStderrMutex().lock();
|
|
15
|
+
defer if (@hasDecl(debug, "unlockStdErr"))
|
|
16
|
+
debug.unlockStdErr()
|
|
17
|
+
else
|
|
18
|
+
debug.getStderrMutex().unlock();
|
|
9
19
|
const stderr = io.getStdErr().writer();
|
|
10
20
|
|
|
11
21
|
nosuspend {
|
|
@@ -19,7 +29,7 @@ pub fn print(value: anytype) void {
|
|
|
19
29
|
}) catch return;
|
|
20
30
|
} else {
|
|
21
31
|
switch (@typeInfo(@TypeOf(value))) {
|
|
22
|
-
|
|
32
|
+
Struct => |info| {
|
|
23
33
|
if (info.is_tuple) {
|
|
24
34
|
inline for (info.fields, 0..) |f, i| {
|
|
25
35
|
inspect(@field(value, f.name));
|
|
@@ -42,17 +52,17 @@ fn inspect(value: anytype) void {
|
|
|
42
52
|
nosuspend {
|
|
43
53
|
const err = "Unable to format type '" ++ @typeName(@TypeOf(value)) ++ "'";
|
|
44
54
|
switch (@typeInfo(@TypeOf(value))) {
|
|
45
|
-
|
|
55
|
+
Array => |info| {
|
|
46
56
|
if (info.child == u8) return stderr.print("{s}", .{value}) catch return;
|
|
47
57
|
@compileError(err);
|
|
48
58
|
},
|
|
49
|
-
|
|
59
|
+
Pointer => |ptr_info| switch (ptr_info.size) {
|
|
50
60
|
.One => switch (@typeInfo(ptr_info.child)) {
|
|
51
|
-
|
|
61
|
+
Array => |info| {
|
|
52
62
|
if (info.child == u8) return stderr.print("{s}", .{value}) catch return;
|
|
53
63
|
@compileError(err);
|
|
54
64
|
},
|
|
55
|
-
|
|
65
|
+
Enum, Union, Struct => return inspect(value.*),
|
|
56
66
|
else => @compileError(err),
|
|
57
67
|
},
|
|
58
68
|
.Many, .C => {
|
|
@@ -67,8 +77,29 @@ fn inspect(value: anytype) void {
|
|
|
67
77
|
@compileError(err);
|
|
68
78
|
},
|
|
69
79
|
},
|
|
70
|
-
|
|
80
|
+
Optional => stderr.print("{?}", .{value}) catch return,
|
|
71
81
|
else => stderr.print("{}", .{value}) catch return,
|
|
72
82
|
}
|
|
73
83
|
}
|
|
74
84
|
}
|
|
85
|
+
|
|
86
|
+
const showdown = @import("./options.zig").showdown;
|
|
87
|
+
const Result = @import("./data.zig").Result;
|
|
88
|
+
const Choice = @import("./data.zig").Choice;
|
|
89
|
+
|
|
90
|
+
pub fn dump(gen: u8, battle: anytype, frame: ?struct { Result, Choice, Choice }) void {
|
|
91
|
+
const file = std.fs.cwd().createFile("logs/dump.bin", .{}) catch return;
|
|
92
|
+
defer file.close();
|
|
93
|
+
var w = file.writer();
|
|
94
|
+
w.writeByte(@intFromBool(showdown)) catch return;
|
|
95
|
+
w.writeByte(gen) catch return;
|
|
96
|
+
w.writeInt(i16, 0, .little) catch return;
|
|
97
|
+
w.writeInt(i32, 0, .little) catch return;
|
|
98
|
+
w.writeStruct(battle) catch return;
|
|
99
|
+
w.writeStruct(battle) catch return;
|
|
100
|
+
if (frame) |f| {
|
|
101
|
+
w.writeStruct(f[0]) catch return;
|
|
102
|
+
w.writeStruct(f[1]) catch return;
|
|
103
|
+
w.writeStruct(f[2]) catch return;
|
|
104
|
+
}
|
|
105
|
+
}
|
package/src/lib/common/js.zig
CHANGED
|
@@ -2,6 +2,8 @@ const std = @import("std");
|
|
|
2
2
|
|
|
3
3
|
const assert = std.debug.assert;
|
|
4
4
|
|
|
5
|
+
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
6
|
+
|
|
5
7
|
const c = @cImport({
|
|
6
8
|
@cDefine("NAPI_VERSION", "8");
|
|
7
9
|
@cInclude("node_api.h");
|
|
@@ -35,7 +37,7 @@ pub const Number = struct {
|
|
|
35
37
|
const T = @TypeOf(value);
|
|
36
38
|
var result: c.napi_value = undefined;
|
|
37
39
|
assert(c.napi_ok == switch (@typeInfo(T)) {
|
|
38
|
-
|
|
40
|
+
Int => |info| switch (info.bits) {
|
|
39
41
|
0...32 => switch (info.signedness) {
|
|
40
42
|
.signed => c.napi_create_int32(env, @as(i32, value), &result),
|
|
41
43
|
.unsigned => c.napi_create_uint32(env, @as(u32, value), &result),
|
|
@@ -50,7 +52,7 @@ pub const Number = struct {
|
|
|
50
52
|
|
|
51
53
|
pub fn get(env: c.napi_env, value: c.napi_value, comptime T: type) T {
|
|
52
54
|
switch (@typeInfo(T)) {
|
|
53
|
-
|
|
55
|
+
Int => |info| switch (info.bits) {
|
|
54
56
|
0...32 => switch (info.signedness) {
|
|
55
57
|
.signed => {
|
|
56
58
|
var result: i32 = undefined;
|
|
@@ -3,10 +3,12 @@ const std = @import("std");
|
|
|
3
3
|
const expect = std.testing.expect;
|
|
4
4
|
const assert = std.debug.assert;
|
|
5
5
|
|
|
6
|
+
const Bool = if (@hasField(std.builtin.Type, "bool")) .bool else .Bool;
|
|
7
|
+
|
|
6
8
|
// TODO: ziglang/zig#104
|
|
7
9
|
pub fn Optional(comptime T: type) type {
|
|
8
10
|
const fields = std.meta.fields(switch (@typeInfo(T)) {
|
|
9
|
-
|
|
11
|
+
Bool => enum { false, true },
|
|
10
12
|
else => T,
|
|
11
13
|
});
|
|
12
14
|
|
|
@@ -23,14 +25,16 @@ pub fn Optional(comptime T: type) type {
|
|
|
23
25
|
};
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
const options: std.builtin.Type.Enum = .{
|
|
29
|
+
.tag_type = std.math.IntFittingRange(0, fields.len),
|
|
30
|
+
.fields = &enumFields,
|
|
31
|
+
.decls = &decls,
|
|
32
|
+
.is_exhaustive = true,
|
|
33
|
+
};
|
|
34
|
+
return @Type(if (@hasField(std.builtin.Type, "enum"))
|
|
35
|
+
.{ .@"enum" = options }
|
|
36
|
+
else
|
|
37
|
+
.{ .Enum = options });
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
test Optional {
|
|
@@ -7,10 +7,12 @@ pub const Options = struct {
|
|
|
7
7
|
log: ?bool = null,
|
|
8
8
|
chance: ?bool = null,
|
|
9
9
|
calc: ?bool = null,
|
|
10
|
+
mod: ?bool = null,
|
|
10
11
|
advance: ?bool = null,
|
|
11
12
|
ebc: ?bool = null,
|
|
12
13
|
key: ?bool = null,
|
|
13
14
|
miss: ?bool = null,
|
|
15
|
+
overwrite: ?bool = null,
|
|
14
16
|
internal: ?bool = null,
|
|
15
17
|
};
|
|
16
18
|
|
|
@@ -23,10 +25,12 @@ pub const chance = get("chance", false);
|
|
|
23
25
|
/// Whether or not damage calculator support is enabled.
|
|
24
26
|
pub const calc = get("calc", false);
|
|
25
27
|
|
|
28
|
+
pub const mod = showdown or get("mod", false);
|
|
26
29
|
pub const advance = get("advance", true);
|
|
27
30
|
pub const ebc = get("ebc", true);
|
|
28
31
|
pub const key = get("key", false);
|
|
29
32
|
pub const miss = get("miss", true);
|
|
33
|
+
pub const overwrite = get("overwrite", true);
|
|
30
34
|
pub const internal = get("internal", false);
|
|
31
35
|
|
|
32
36
|
fn get(comptime name: []const u8, default: bool) bool {
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
1
|
const builtin = @import("builtin");
|
|
3
|
-
|
|
4
|
-
const pkmn = @import("../pkmn.zig");
|
|
5
|
-
|
|
6
2
|
const data = @import("data.zig");
|
|
7
3
|
const options = @import("options.zig");
|
|
4
|
+
const pkmn = @import("../pkmn.zig");
|
|
5
|
+
const std = @import("std");
|
|
8
6
|
|
|
9
7
|
const assert = std.debug.assert;
|
|
10
|
-
const print = std.debug.print;
|
|
11
|
-
|
|
12
8
|
const enabled = options.log;
|
|
13
|
-
|
|
14
|
-
const Player = data.Player;
|
|
15
9
|
const ID = data.ID;
|
|
10
|
+
const Player = data.Player;
|
|
11
|
+
const print = std.debug.print;
|
|
16
12
|
|
|
17
13
|
const endian = builtin.cpu.arch.endian();
|
|
14
|
+
const Endian = std.builtin.Endian;
|
|
15
|
+
const big = if (@hasField(Endian, "big")) Endian.big else Endian.Big;
|
|
16
|
+
const little = if (@hasField(Endian, "little")) Endian.little else Endian.Little;
|
|
17
|
+
|
|
18
|
+
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
18
19
|
|
|
19
20
|
pub const ArgType = enum(u8) {
|
|
20
21
|
None,
|
|
@@ -840,7 +841,7 @@ pub const ByteStream = struct {
|
|
|
840
841
|
|
|
841
842
|
pub fn writeInt(self: Writer, comptime T: type, v: T, end: std.builtin.Endian) Error!void {
|
|
842
843
|
// TODO: rework this to write directly to the buffer?
|
|
843
|
-
var bytes: [@divExact(@typeInfo(T)
|
|
844
|
+
var bytes: [@divExact(@field(@typeInfo(T), @tagName(Int)).bits, 8)]u8 = undefined;
|
|
844
845
|
std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(v)), &bytes, v, end);
|
|
845
846
|
return self.writeAll(&bytes);
|
|
846
847
|
}
|
|
@@ -864,7 +865,7 @@ pub const ByteStream = struct {
|
|
|
864
865
|
pub const Kind = enum { Move, Species, Type, Status, Item, Weather };
|
|
865
866
|
|
|
866
867
|
pub fn format(
|
|
867
|
-
|
|
868
|
+
gen: anytype,
|
|
868
869
|
a: []const u8,
|
|
869
870
|
b: ?[]const u8,
|
|
870
871
|
color: bool,
|
|
@@ -956,13 +957,13 @@ pub fn format(
|
|
|
956
957
|
}
|
|
957
958
|
printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
|
|
958
959
|
switch (endian) {
|
|
959
|
-
|
|
960
|
+
big => {
|
|
960
961
|
var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
961
962
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
962
963
|
hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
963
964
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
964
965
|
},
|
|
965
|
-
|
|
966
|
+
little => {
|
|
966
967
|
var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
967
968
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
968
969
|
hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
@@ -993,8 +994,8 @@ pub fn format(
|
|
|
993
994
|
},
|
|
994
995
|
.Turn => {
|
|
995
996
|
const turn = switch (endian) {
|
|
996
|
-
|
|
997
|
-
|
|
997
|
+
big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
|
|
998
|
+
little => @as(u16, a[i + 1]) << 8 | @as(u16, a[i]),
|
|
998
999
|
};
|
|
999
1000
|
printc(" {d}", .{turn}, a, b, &i, 2, color);
|
|
1000
1001
|
},
|
|
@@ -1005,13 +1006,13 @@ pub fn format(
|
|
|
1005
1006
|
var id = ID.from(@intCast(a[i]));
|
|
1006
1007
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1007
1008
|
switch (endian) {
|
|
1008
|
-
|
|
1009
|
+
big => {
|
|
1009
1010
|
var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1010
1011
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1011
1012
|
hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1012
1013
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
1013
1014
|
},
|
|
1014
|
-
|
|
1015
|
+
little => {
|
|
1015
1016
|
var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
1016
1017
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1017
1018
|
hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
@@ -1133,13 +1134,13 @@ pub fn format(
|
|
|
1133
1134
|
const id = ID.from(@intCast(a[i]));
|
|
1134
1135
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1135
1136
|
switch (endian) {
|
|
1136
|
-
|
|
1137
|
+
big => {
|
|
1137
1138
|
var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1138
1139
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1139
1140
|
hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1140
1141
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
1141
1142
|
},
|
|
1142
|
-
|
|
1143
|
+
little => {
|
|
1143
1144
|
var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
1144
1145
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1145
1146
|
hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
@@ -1345,8 +1346,8 @@ test "|switch|" {
|
|
|
1345
1346
|
try log.switched(.{ p2.ident(3), &snorlax });
|
|
1346
1347
|
const par = 0b1000000;
|
|
1347
1348
|
var expected: []const u8 = switch (endian) {
|
|
1348
|
-
|
|
1349
|
-
|
|
1349
|
+
big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
|
|
1350
|
+
little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 200, 0, 144, 1, par },
|
|
1350
1351
|
};
|
|
1351
1352
|
try expectLog1(expected, buf[0..9]);
|
|
1352
1353
|
stream.reset();
|
|
@@ -1356,8 +1357,8 @@ test "|switch|" {
|
|
|
1356
1357
|
snorlax.status = 0;
|
|
1357
1358
|
try log.switched(.{ p2.ident(3), &snorlax });
|
|
1358
1359
|
expected = switch (endian) {
|
|
1359
|
-
|
|
1360
|
-
|
|
1360
|
+
big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
|
|
1361
|
+
little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 144, 1, 0 },
|
|
1361
1362
|
};
|
|
1362
1363
|
try expectLog1(expected, buf[0..9]);
|
|
1363
1364
|
stream.reset();
|
|
@@ -1365,8 +1366,8 @@ test "|switch|" {
|
|
|
1365
1366
|
snorlax.hp = 400;
|
|
1366
1367
|
try log.switched(.{ p2.ident(3), &snorlax });
|
|
1367
1368
|
expected = switch (endian) {
|
|
1368
|
-
|
|
1369
|
-
|
|
1369
|
+
big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
|
|
1370
|
+
little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 144, 1, 144, 1, 0 },
|
|
1370
1371
|
};
|
|
1371
1372
|
try expectLog1(expected, buf[0..9]);
|
|
1372
1373
|
stream.reset();
|
|
@@ -1384,8 +1385,8 @@ test "|switch|" {
|
|
|
1384
1385
|
N(gen2.Gender.Female),
|
|
1385
1386
|
91,
|
|
1386
1387
|
} ++ switch (endian) {
|
|
1387
|
-
|
|
1388
|
-
|
|
1388
|
+
big => .{ 0, 200, 1, 144, par },
|
|
1389
|
+
little => .{ 200, 0, 144, 1, par },
|
|
1389
1390
|
});
|
|
1390
1391
|
try expectLog2(expected, buf[0..10]);
|
|
1391
1392
|
stream.reset();
|
|
@@ -1414,8 +1415,8 @@ test "|faint|" {
|
|
|
1414
1415
|
test "|turn|" {
|
|
1415
1416
|
try log.turn(.{42});
|
|
1416
1417
|
const expected = switch (endian) {
|
|
1417
|
-
|
|
1418
|
-
|
|
1418
|
+
big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
|
|
1419
|
+
little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
|
|
1419
1420
|
};
|
|
1420
1421
|
try expectLog1(expected, buf[0..4]);
|
|
1421
1422
|
stream.reset();
|
|
@@ -1439,8 +1440,8 @@ test "|-damage|" {
|
|
|
1439
1440
|
chansey.status = gen1.Status.slp(1);
|
|
1440
1441
|
try log.damage(.{ p2.ident(2), &chansey, .None });
|
|
1441
1442
|
var expected: []const u8 = switch (endian) {
|
|
1442
|
-
|
|
1443
|
-
|
|
1443
|
+
big => &.{ N(ArgType.Damage), 0b1010, 2, 100, 2, 191, 1, N(Damage.None) },
|
|
1444
|
+
little => &.{ N(ArgType.Damage), 0b1010, 100, 2, 191, 2, 1, N(Damage.None) },
|
|
1444
1445
|
};
|
|
1445
1446
|
try expectLog1(expected, buf[0..8]);
|
|
1446
1447
|
stream.reset();
|
|
@@ -1450,8 +1451,8 @@ test "|-damage|" {
|
|
|
1450
1451
|
chansey.status = 0;
|
|
1451
1452
|
try log.damage(.{ p2.ident(2), &chansey, .Confusion });
|
|
1452
1453
|
expected = switch (endian) {
|
|
1453
|
-
|
|
1454
|
-
|
|
1454
|
+
big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0, N(Damage.Confusion) },
|
|
1455
|
+
little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0, N(Damage.Confusion) },
|
|
1455
1456
|
};
|
|
1456
1457
|
try expectLog1(expected, buf[0..8]);
|
|
1457
1458
|
stream.reset();
|
|
@@ -1459,8 +1460,8 @@ test "|-damage|" {
|
|
|
1459
1460
|
chansey.status = gen1.Status.init(.PSN);
|
|
1460
1461
|
try log.damage(.{ p2.ident(2), &chansey, .RecoilOf, p1.ident(1) });
|
|
1461
1462
|
expected = switch (endian) {
|
|
1462
|
-
|
|
1463
|
-
|
|
1463
|
+
big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0b1000, N(Damage.RecoilOf), 1 },
|
|
1464
|
+
little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0b1000, N(Damage.RecoilOf), 1 },
|
|
1464
1465
|
};
|
|
1465
1466
|
try expectLog1(expected, buf[0..9]);
|
|
1466
1467
|
stream.reset();
|
|
@@ -1472,8 +1473,8 @@ test "|-heal|" {
|
|
|
1472
1473
|
chansey.status = gen1.Status.slp(1);
|
|
1473
1474
|
try log.heal(.{ p2.ident(2), &chansey, .None });
|
|
1474
1475
|
var expected: []const u8 = switch (endian) {
|
|
1475
|
-
|
|
1476
|
-
|
|
1476
|
+
big => &.{ N(ArgType.Heal), 0b1010, 2, 100, 2, 191, 1, N(Heal.None) },
|
|
1477
|
+
little => &.{ N(ArgType.Heal), 0b1010, 100, 2, 191, 2, 1, N(Heal.None) },
|
|
1477
1478
|
};
|
|
1478
1479
|
try expectLog1(expected, buf[0..8]);
|
|
1479
1480
|
stream.reset();
|
|
@@ -1483,16 +1484,16 @@ test "|-heal|" {
|
|
|
1483
1484
|
chansey.status = 0;
|
|
1484
1485
|
try log.heal(.{ p2.ident(2), &chansey, .Silent });
|
|
1485
1486
|
expected = switch (endian) {
|
|
1486
|
-
|
|
1487
|
-
|
|
1487
|
+
big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Silent) },
|
|
1488
|
+
little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Silent) },
|
|
1488
1489
|
};
|
|
1489
1490
|
try expectLog1(expected, buf[0..8]);
|
|
1490
1491
|
stream.reset();
|
|
1491
1492
|
|
|
1492
1493
|
try log.heal(.{ p2.ident(2), &chansey, .Drain, p1.ident(1) });
|
|
1493
1494
|
expected = switch (endian) {
|
|
1494
|
-
|
|
1495
|
-
|
|
1495
|
+
big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Drain), 1 },
|
|
1496
|
+
little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Drain), 1 },
|
|
1496
1497
|
};
|
|
1497
1498
|
try expectLog1(expected, buf[0..9]);
|
|
1498
1499
|
stream.reset();
|
|
@@ -1735,8 +1736,8 @@ test "|drag|" {
|
|
|
1735
1736
|
N(gen2.Gender.Female),
|
|
1736
1737
|
91,
|
|
1737
1738
|
} ++ switch (endian) {
|
|
1738
|
-
|
|
1739
|
-
|
|
1739
|
+
big => .{ 0, 200, 1, 144, par },
|
|
1740
|
+
little => .{ 200, 0, 144, 1, par },
|
|
1740
1741
|
});
|
|
1741
1742
|
try expectLog2(expected, buf[0..10]);
|
|
1742
1743
|
stream.reset();
|
|
@@ -1769,8 +1770,8 @@ test "|-sethp|" {
|
|
|
1769
1770
|
blissey.hp = 612;
|
|
1770
1771
|
try log.sethp(.{ p2.ident(2), &blissey, .Silent });
|
|
1771
1772
|
const expected: []const u8 = switch (endian) {
|
|
1772
|
-
|
|
1773
|
-
|
|
1773
|
+
big => &.{ N(ArgType.SetHP), 0b1010, 2, 100, 2, 201, 0, N(SetHP.Silent) },
|
|
1774
|
+
little => &.{ N(ArgType.SetHP), 0b1010, 100, 2, 201, 2, 0, N(SetHP.Silent) },
|
|
1774
1775
|
};
|
|
1775
1776
|
try expectLog2(expected, buf[0..8]);
|
|
1776
1777
|
stream.reset();
|