@pkmn/engine 0.1.0-dev.32adfe77 → 0.1.0-dev.36b5d56b
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 +15 -11
- package/build/pkg/addon/browser.d.ts +3 -0
- package/build/pkg/addon/browser.js +44 -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 +97 -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 +21 -0
- package/build/pkg/addon/wasm.js.map +1 -0
- package/build/pkg/addon.d.ts +22 -0
- package/build/pkg/addon.js +35 -58
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data.d.ts +25 -4
- package/build/pkg/data.js.map +1 -1
- package/build/pkg/gen1.js +1 -1
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +22 -9
- package/build/pkg/index.js +15 -10
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +20 -1
- package/build/pkg/protocol.js +109 -107
- package/build/pkg/protocol.js.map +1 -1
- package/build/tools/debug.js +36 -70
- package/build/tools/debug.js.map +1 -1
- package/build/tools/display/debug.jsx +141 -0
- package/build/tools/display/debug.jsx.map +1 -0
- package/build/tools/display/index.js +141 -0
- package/build/tools/display/index.js.map +1 -0
- package/build/tools/display/ui.jsx +349 -0
- package/build/tools/display/ui.jsx.map +1 -0
- package/build/tools/display/util.js +18 -0
- package/build/tools/display/util.js.map +1 -0
- package/build.zig +218 -76
- package/package.json +53 -33
- package/src/bin/install-pkmn-engine +17 -7
- package/src/bin/pkmn-debug +1 -1
- 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 +6 -0
- package/src/lib/common/protocol.zig +50 -44
- package/src/lib/common/rational.zig +121 -29
- package/src/lib/common/rng.zig +5 -7
- package/src/lib/common/util.zig +50 -1
- package/src/lib/gen1/calc.zig +683 -156
- package/src/lib/gen1/chance.zig +415 -290
- 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 +38 -41
- package/src/lib/gen1/helpers.zig +92 -548
- package/src/lib/gen1/mechanics.zig +325 -235
- package/src/lib/gen2/calc.zig +37 -27
- package/src/lib/gen2/chance.zig +90 -502
- 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 +46 -25
- package/src/lib/gen2/mechanics.zig +180 -133
- package/src/lib/node.zig +2 -4
- package/src/lib/pkmn.zig +14 -16
- package/src/lib/wasm.zig +1 -2
- package/src/tools/display/dom.ts +96 -0
- package/src/tools/display/ui.css +354 -0
- package/build/test/display.js +0 -400
- package/build/test/display.js.map +0 -1
- package/src/lib/gen1/README.md +0 -894
- package/src/lib/gen2/README.md +0 -329
- package/src/test/display/pkmn.html.tmpl +0 -368
|
@@ -10,7 +10,7 @@ const path = require('path');
|
|
|
10
10
|
const {pipeline} = require('stream/promises');
|
|
11
11
|
const tty = require('tty');
|
|
12
12
|
|
|
13
|
-
const ZIG_VERSION = {major: 0, minor:
|
|
13
|
+
const ZIG_VERSION = {major: 0, minor: 11, patch: 0};
|
|
14
14
|
const DEV = ZIG_VERSION.dev ? `-dev.${ZIG_VERSION.dev}` : '';
|
|
15
15
|
const VERSION = `${ZIG_VERSION.major}.${ZIG_VERSION.minor}.${ZIG_VERSION.patch}${DEV}`;
|
|
16
16
|
const INDEX = 'https://ziglang.org/download/index.json';
|
|
@@ -163,8 +163,10 @@ const install = async () => {
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
const index = JSON.parse(await fetch(INDEX));
|
|
166
|
-
|
|
167
|
-
const
|
|
166
|
+
// TODO: ziglang/zig#17768
|
|
167
|
+
// const version = Object.keys(index)[+!ZIG_VERSION.dev];
|
|
168
|
+
const version = VERSION;
|
|
169
|
+
const release = index[VERSION][`${arch}-${platform}`];
|
|
168
170
|
const url = release.tarball;
|
|
169
171
|
|
|
170
172
|
let base = path.basename(url);
|
|
@@ -370,8 +372,10 @@ const downloadImportLib = async () => {
|
|
|
370
372
|
const args = ['build', '-p', 'build', ...opts];
|
|
371
373
|
if (!process.env.DEBUG_PKMN_ENGINE) args.push('-Doptimize=ReleaseFast', '-Dstrip');
|
|
372
374
|
if (config.type === 'node') {
|
|
373
|
-
args.push(`-Dnode-headers=${headers}`);
|
|
374
|
-
if (process.platform === 'win32')
|
|
375
|
+
args.push(`-Dnode-headers=${path.relative(ROOT, headers)}`);
|
|
376
|
+
if (process.platform === 'win32') {
|
|
377
|
+
args.push(`-Dnode-import-library=${path.relative(ROOT, lib)}`);
|
|
378
|
+
}
|
|
375
379
|
} else {
|
|
376
380
|
args.push('-Dwasm');
|
|
377
381
|
}
|
|
@@ -386,8 +390,14 @@ const downloadImportLib = async () => {
|
|
|
386
390
|
const prefix = process.platform === 'win32' ? '' : 'lib';
|
|
387
391
|
const ext = process.platform === 'darwin'
|
|
388
392
|
? 'dylib' : process.platform === 'win32' ? 'dll' : 'so';
|
|
389
|
-
|
|
390
|
-
|
|
393
|
+
try {
|
|
394
|
+
const actual = path.join(ROOT, 'build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
|
|
395
|
+
fs.renameSync(actual, artifact);
|
|
396
|
+
} catch (err) {
|
|
397
|
+
// ziglang/zig#19743 changed this path
|
|
398
|
+
const actual = path.join(ROOT, 'build', 'bin', `${prefix}pkmn${suffix}.node.${ext}`);
|
|
399
|
+
fs.renameSync(actual, artifact);
|
|
400
|
+
}
|
|
391
401
|
}
|
|
392
402
|
}
|
|
393
403
|
})().catch(e => {
|
package/src/bin/pkmn-debug
CHANGED
|
@@ -15,7 +15,7 @@ const ROOT = resolve(__dirname, '..', '..');
|
|
|
15
15
|
const packageJSON = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8'));
|
|
16
16
|
|
|
17
17
|
const missing = [];
|
|
18
|
-
for (const dep of ['@pkmn/img', 'html-minifier', '
|
|
18
|
+
for (const dep of ['@pkmn/img', 'html-minifier', 'esbuild']) {
|
|
19
19
|
try {
|
|
20
20
|
require.resolve(dep);
|
|
21
21
|
} catch (e) {
|
|
@@ -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 = .{ .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.getStderrMutex().lock();
|
|
8
|
-
defer
|
|
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 = .{
|
|
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,9 +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,
|
|
14
|
+
miss: ?bool = null,
|
|
15
|
+
overwrite: ?bool = null,
|
|
13
16
|
internal: ?bool = null,
|
|
14
17
|
};
|
|
15
18
|
|
|
@@ -22,9 +25,12 @@ pub const chance = get("chance", false);
|
|
|
22
25
|
/// Whether or not damage calculator support is enabled.
|
|
23
26
|
pub const calc = get("calc", false);
|
|
24
27
|
|
|
28
|
+
pub const mod = showdown or get("mod", false);
|
|
25
29
|
pub const advance = get("advance", true);
|
|
26
30
|
pub const ebc = get("ebc", true);
|
|
27
31
|
pub const key = get("key", false);
|
|
32
|
+
pub const miss = get("miss", true);
|
|
33
|
+
pub const overwrite = get("overwrite", true);
|
|
28
34
|
pub const internal = get("internal", false);
|
|
29
35
|
|
|
30
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,
|
|
@@ -220,6 +221,7 @@ pub const Activate = enum(u8) {
|
|
|
220
221
|
BeatUp, // FIXME of
|
|
221
222
|
|
|
222
223
|
Magnitude,
|
|
224
|
+
Spite,
|
|
223
225
|
};
|
|
224
226
|
|
|
225
227
|
pub const Start = enum(u8) {
|
|
@@ -544,6 +546,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
544
546
|
// ident: ID, reason: Activate
|
|
545
547
|
// ident: ID, reason: .SubstituteBlock, m: <Move>
|
|
546
548
|
// ident: ID, reason: .Magnitude, num: u8
|
|
549
|
+
// ident: ID, reason: .Spite, m: <Move>, num: u8
|
|
547
550
|
pub fn activate(self: Self, args: anytype) Error!void {
|
|
548
551
|
if (!enabled) return;
|
|
549
552
|
|
|
@@ -561,6 +564,9 @@ pub fn Log(comptime Writer: type) type {
|
|
|
561
564
|
assert(reason == .Magnitude);
|
|
562
565
|
try self.writer.writeByte(args[2]);
|
|
563
566
|
}
|
|
567
|
+
} else if (args.len == 4) {
|
|
568
|
+
assert(reason == .Spite);
|
|
569
|
+
try self.writer.writeAll(&.{ @intFromEnum(args[2]), args[3] });
|
|
564
570
|
}
|
|
565
571
|
}
|
|
566
572
|
|
|
@@ -835,7 +841,7 @@ pub const ByteStream = struct {
|
|
|
835
841
|
|
|
836
842
|
pub fn writeInt(self: Writer, comptime T: type, v: T, end: std.builtin.Endian) Error!void {
|
|
837
843
|
// TODO: rework this to write directly to the buffer?
|
|
838
|
-
var bytes: [@divExact(@typeInfo(T)
|
|
844
|
+
var bytes: [@divExact(@field(@typeInfo(T), @tagName(Int)).bits, 8)]u8 = undefined;
|
|
839
845
|
std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(v)), &bytes, v, end);
|
|
840
846
|
return self.writeAll(&bytes);
|
|
841
847
|
}
|
|
@@ -859,7 +865,7 @@ pub const ByteStream = struct {
|
|
|
859
865
|
pub const Kind = enum { Move, Species, Type, Status, Item, Weather };
|
|
860
866
|
|
|
861
867
|
pub fn format(
|
|
862
|
-
|
|
868
|
+
gen: anytype,
|
|
863
869
|
a: []const u8,
|
|
864
870
|
b: ?[]const u8,
|
|
865
871
|
color: bool,
|
|
@@ -951,13 +957,13 @@ pub fn format(
|
|
|
951
957
|
}
|
|
952
958
|
printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
|
|
953
959
|
switch (endian) {
|
|
954
|
-
|
|
960
|
+
big => {
|
|
955
961
|
var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
956
962
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
957
963
|
hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
958
964
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
959
965
|
},
|
|
960
|
-
|
|
966
|
+
little => {
|
|
961
967
|
var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
962
968
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
963
969
|
hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
@@ -988,8 +994,8 @@ pub fn format(
|
|
|
988
994
|
},
|
|
989
995
|
.Turn => {
|
|
990
996
|
const turn = switch (endian) {
|
|
991
|
-
|
|
992
|
-
|
|
997
|
+
big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
|
|
998
|
+
little => @as(u16, a[i + 1]) << 8 | @as(u16, a[i]),
|
|
993
999
|
};
|
|
994
1000
|
printc(" {d}", .{turn}, a, b, &i, 2, color);
|
|
995
1001
|
},
|
|
@@ -1000,13 +1006,13 @@ pub fn format(
|
|
|
1000
1006
|
var id = ID.from(@intCast(a[i]));
|
|
1001
1007
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1002
1008
|
switch (endian) {
|
|
1003
|
-
|
|
1009
|
+
big => {
|
|
1004
1010
|
var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1005
1011
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1006
1012
|
hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1007
1013
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
1008
1014
|
},
|
|
1009
|
-
|
|
1015
|
+
little => {
|
|
1010
1016
|
var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
1011
1017
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1012
1018
|
hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
@@ -1128,13 +1134,13 @@ pub fn format(
|
|
|
1128
1134
|
const id = ID.from(@intCast(a[i]));
|
|
1129
1135
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1130
1136
|
switch (endian) {
|
|
1131
|
-
|
|
1137
|
+
big => {
|
|
1132
1138
|
var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1133
1139
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1134
1140
|
hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1135
1141
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
1136
1142
|
},
|
|
1137
|
-
|
|
1143
|
+
little => {
|
|
1138
1144
|
var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
1139
1145
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1140
1146
|
hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
@@ -1340,8 +1346,8 @@ test "|switch|" {
|
|
|
1340
1346
|
try log.switched(.{ p2.ident(3), &snorlax });
|
|
1341
1347
|
const par = 0b1000000;
|
|
1342
1348
|
var expected: []const u8 = switch (endian) {
|
|
1343
|
-
|
|
1344
|
-
|
|
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 },
|
|
1345
1351
|
};
|
|
1346
1352
|
try expectLog1(expected, buf[0..9]);
|
|
1347
1353
|
stream.reset();
|
|
@@ -1351,8 +1357,8 @@ test "|switch|" {
|
|
|
1351
1357
|
snorlax.status = 0;
|
|
1352
1358
|
try log.switched(.{ p2.ident(3), &snorlax });
|
|
1353
1359
|
expected = switch (endian) {
|
|
1354
|
-
|
|
1355
|
-
|
|
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 },
|
|
1356
1362
|
};
|
|
1357
1363
|
try expectLog1(expected, buf[0..9]);
|
|
1358
1364
|
stream.reset();
|
|
@@ -1360,8 +1366,8 @@ test "|switch|" {
|
|
|
1360
1366
|
snorlax.hp = 400;
|
|
1361
1367
|
try log.switched(.{ p2.ident(3), &snorlax });
|
|
1362
1368
|
expected = switch (endian) {
|
|
1363
|
-
|
|
1364
|
-
|
|
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 },
|
|
1365
1371
|
};
|
|
1366
1372
|
try expectLog1(expected, buf[0..9]);
|
|
1367
1373
|
stream.reset();
|
|
@@ -1379,8 +1385,8 @@ test "|switch|" {
|
|
|
1379
1385
|
N(gen2.Gender.Female),
|
|
1380
1386
|
91,
|
|
1381
1387
|
} ++ switch (endian) {
|
|
1382
|
-
|
|
1383
|
-
|
|
1388
|
+
big => .{ 0, 200, 1, 144, par },
|
|
1389
|
+
little => .{ 200, 0, 144, 1, par },
|
|
1384
1390
|
});
|
|
1385
1391
|
try expectLog2(expected, buf[0..10]);
|
|
1386
1392
|
stream.reset();
|
|
@@ -1409,8 +1415,8 @@ test "|faint|" {
|
|
|
1409
1415
|
test "|turn|" {
|
|
1410
1416
|
try log.turn(.{42});
|
|
1411
1417
|
const expected = switch (endian) {
|
|
1412
|
-
|
|
1413
|
-
|
|
1418
|
+
big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
|
|
1419
|
+
little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
|
|
1414
1420
|
};
|
|
1415
1421
|
try expectLog1(expected, buf[0..4]);
|
|
1416
1422
|
stream.reset();
|
|
@@ -1434,8 +1440,8 @@ test "|-damage|" {
|
|
|
1434
1440
|
chansey.status = gen1.Status.slp(1);
|
|
1435
1441
|
try log.damage(.{ p2.ident(2), &chansey, .None });
|
|
1436
1442
|
var expected: []const u8 = switch (endian) {
|
|
1437
|
-
|
|
1438
|
-
|
|
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) },
|
|
1439
1445
|
};
|
|
1440
1446
|
try expectLog1(expected, buf[0..8]);
|
|
1441
1447
|
stream.reset();
|
|
@@ -1445,8 +1451,8 @@ test "|-damage|" {
|
|
|
1445
1451
|
chansey.status = 0;
|
|
1446
1452
|
try log.damage(.{ p2.ident(2), &chansey, .Confusion });
|
|
1447
1453
|
expected = switch (endian) {
|
|
1448
|
-
|
|
1449
|
-
|
|
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) },
|
|
1450
1456
|
};
|
|
1451
1457
|
try expectLog1(expected, buf[0..8]);
|
|
1452
1458
|
stream.reset();
|
|
@@ -1454,8 +1460,8 @@ test "|-damage|" {
|
|
|
1454
1460
|
chansey.status = gen1.Status.init(.PSN);
|
|
1455
1461
|
try log.damage(.{ p2.ident(2), &chansey, .RecoilOf, p1.ident(1) });
|
|
1456
1462
|
expected = switch (endian) {
|
|
1457
|
-
|
|
1458
|
-
|
|
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 },
|
|
1459
1465
|
};
|
|
1460
1466
|
try expectLog1(expected, buf[0..9]);
|
|
1461
1467
|
stream.reset();
|
|
@@ -1467,8 +1473,8 @@ test "|-heal|" {
|
|
|
1467
1473
|
chansey.status = gen1.Status.slp(1);
|
|
1468
1474
|
try log.heal(.{ p2.ident(2), &chansey, .None });
|
|
1469
1475
|
var expected: []const u8 = switch (endian) {
|
|
1470
|
-
|
|
1471
|
-
|
|
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) },
|
|
1472
1478
|
};
|
|
1473
1479
|
try expectLog1(expected, buf[0..8]);
|
|
1474
1480
|
stream.reset();
|
|
@@ -1478,16 +1484,16 @@ test "|-heal|" {
|
|
|
1478
1484
|
chansey.status = 0;
|
|
1479
1485
|
try log.heal(.{ p2.ident(2), &chansey, .Silent });
|
|
1480
1486
|
expected = switch (endian) {
|
|
1481
|
-
|
|
1482
|
-
|
|
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) },
|
|
1483
1489
|
};
|
|
1484
1490
|
try expectLog1(expected, buf[0..8]);
|
|
1485
1491
|
stream.reset();
|
|
1486
1492
|
|
|
1487
1493
|
try log.heal(.{ p2.ident(2), &chansey, .Drain, p1.ident(1) });
|
|
1488
1494
|
expected = switch (endian) {
|
|
1489
|
-
|
|
1490
|
-
|
|
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 },
|
|
1491
1497
|
};
|
|
1492
1498
|
try expectLog1(expected, buf[0..9]);
|
|
1493
1499
|
stream.reset();
|
|
@@ -1730,8 +1736,8 @@ test "|drag|" {
|
|
|
1730
1736
|
N(gen2.Gender.Female),
|
|
1731
1737
|
91,
|
|
1732
1738
|
} ++ switch (endian) {
|
|
1733
|
-
|
|
1734
|
-
|
|
1739
|
+
big => .{ 0, 200, 1, 144, par },
|
|
1740
|
+
little => .{ 200, 0, 144, 1, par },
|
|
1735
1741
|
});
|
|
1736
1742
|
try expectLog2(expected, buf[0..10]);
|
|
1737
1743
|
stream.reset();
|
|
@@ -1764,8 +1770,8 @@ test "|-sethp|" {
|
|
|
1764
1770
|
blissey.hp = 612;
|
|
1765
1771
|
try log.sethp(.{ p2.ident(2), &blissey, .Silent });
|
|
1766
1772
|
const expected: []const u8 = switch (endian) {
|
|
1767
|
-
|
|
1768
|
-
|
|
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) },
|
|
1769
1775
|
};
|
|
1770
1776
|
try expectLog2(expected, buf[0..8]);
|
|
1771
1777
|
stream.reset();
|