@pkmn/engine 0.1.0-dev.09d1baec → 0.1.0-dev.0cabf16e
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 +0 -2
- package/README.md +15 -11
- package/build/pkg/addon/browser.d.ts +3 -0
- package/build/pkg/addon/browser.js +43 -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 +96 -0
- package/build/pkg/addon/node.js.map +1 -0
- package/build/pkg/addon.d.ts +2 -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 +132 -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 +187 -72
- package/package.json +48 -32
- 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 +4 -0
- package/src/lib/common/protocol.zig +51 -44
- package/src/lib/common/rational.zig +114 -24
- package/src/lib/common/rng.zig +10 -10
- package/src/lib/common/util.zig +50 -1
- package/src/lib/gen1/calc.zig +671 -125
- package/src/lib/gen1/chance.zig +384 -275
- package/src/lib/gen1/data/species.zig +1 -1
- package/src/lib/gen1/data.zig +31 -30
- package/src/lib/gen1/helpers.zig +89 -538
- package/src/lib/gen1/mechanics.zig +297 -189
- package/src/lib/gen2/calc.zig +34 -16
- package/src/lib/gen2/chance.zig +90 -502
- package/src/lib/gen2/data.zig +15 -14
- package/src/lib/gen2/helpers.zig +41 -13
- package/src/lib/gen2/mechanics.zig +158 -103
- package/src/lib/pkmn.zig +10 -16
- package/src/tools/display/dom.ts +96 -0
- package/src/tools/display/ui.css +359 -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 {
|
|
@@ -10,6 +10,8 @@ pub const Options = struct {
|
|
|
10
10
|
advance: ?bool = null,
|
|
11
11
|
ebc: ?bool = null,
|
|
12
12
|
key: ?bool = null,
|
|
13
|
+
miss: ?bool = null,
|
|
14
|
+
overwrite: ?bool = null,
|
|
13
15
|
internal: ?bool = null,
|
|
14
16
|
};
|
|
15
17
|
|
|
@@ -25,6 +27,8 @@ pub const calc = get("calc", false);
|
|
|
25
27
|
pub const advance = get("advance", true);
|
|
26
28
|
pub const ebc = get("ebc", true);
|
|
27
29
|
pub const key = get("key", false);
|
|
30
|
+
pub const miss = get("miss", true);
|
|
31
|
+
pub const overwrite = get("overwrite", true);
|
|
28
32
|
pub const internal = get("internal", false);
|
|
29
33
|
|
|
30
34
|
fn get(comptime name: []const u8, default: bool) bool {
|
|
@@ -15,6 +15,11 @@ const Player = data.Player;
|
|
|
15
15
|
const ID = data.ID;
|
|
16
16
|
|
|
17
17
|
const endian = builtin.cpu.arch.endian();
|
|
18
|
+
const Endian = std.builtin.Endian;
|
|
19
|
+
const big = if (@hasField(Endian, "big")) Endian.big else Endian.Big;
|
|
20
|
+
const little = if (@hasField(Endian, "little")) Endian.little else Endian.Little;
|
|
21
|
+
|
|
22
|
+
const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int;
|
|
18
23
|
|
|
19
24
|
pub const ArgType = enum(u8) {
|
|
20
25
|
None,
|
|
@@ -220,6 +225,7 @@ pub const Activate = enum(u8) {
|
|
|
220
225
|
BeatUp, // FIXME of
|
|
221
226
|
|
|
222
227
|
Magnitude,
|
|
228
|
+
Spite,
|
|
223
229
|
};
|
|
224
230
|
|
|
225
231
|
pub const Start = enum(u8) {
|
|
@@ -544,6 +550,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
544
550
|
// ident: ID, reason: Activate
|
|
545
551
|
// ident: ID, reason: .SubstituteBlock, m: <Move>
|
|
546
552
|
// ident: ID, reason: .Magnitude, num: u8
|
|
553
|
+
// ident: ID, reason: .Spite, m: <Move>, num: u8
|
|
547
554
|
pub fn activate(self: Self, args: anytype) Error!void {
|
|
548
555
|
if (!enabled) return;
|
|
549
556
|
|
|
@@ -561,6 +568,9 @@ pub fn Log(comptime Writer: type) type {
|
|
|
561
568
|
assert(reason == .Magnitude);
|
|
562
569
|
try self.writer.writeByte(args[2]);
|
|
563
570
|
}
|
|
571
|
+
} else if (args.len == 4) {
|
|
572
|
+
assert(reason == .Spite);
|
|
573
|
+
try self.writer.writeAll(&.{ @intFromEnum(args[2]), args[3] });
|
|
564
574
|
}
|
|
565
575
|
}
|
|
566
576
|
|
|
@@ -835,7 +845,7 @@ pub const ByteStream = struct {
|
|
|
835
845
|
|
|
836
846
|
pub fn writeInt(self: Writer, comptime T: type, v: T, end: std.builtin.Endian) Error!void {
|
|
837
847
|
// TODO: rework this to write directly to the buffer?
|
|
838
|
-
var bytes: [@divExact(@typeInfo(T)
|
|
848
|
+
var bytes: [@divExact(@field(@typeInfo(T), @tagName(Int)).bits, 8)]u8 = undefined;
|
|
839
849
|
std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(v)), &bytes, v, end);
|
|
840
850
|
return self.writeAll(&bytes);
|
|
841
851
|
}
|
|
@@ -859,7 +869,7 @@ pub const ByteStream = struct {
|
|
|
859
869
|
pub const Kind = enum { Move, Species, Type, Status, Item, Weather };
|
|
860
870
|
|
|
861
871
|
pub fn format(
|
|
862
|
-
|
|
872
|
+
gen: anytype,
|
|
863
873
|
a: []const u8,
|
|
864
874
|
b: ?[]const u8,
|
|
865
875
|
color: bool,
|
|
@@ -951,13 +961,13 @@ pub fn format(
|
|
|
951
961
|
}
|
|
952
962
|
printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
|
|
953
963
|
switch (endian) {
|
|
954
|
-
|
|
964
|
+
big => {
|
|
955
965
|
var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
956
966
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
957
967
|
hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
958
968
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
959
969
|
},
|
|
960
|
-
|
|
970
|
+
little => {
|
|
961
971
|
var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
962
972
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
963
973
|
hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
@@ -988,8 +998,8 @@ pub fn format(
|
|
|
988
998
|
},
|
|
989
999
|
.Turn => {
|
|
990
1000
|
const turn = switch (endian) {
|
|
991
|
-
|
|
992
|
-
|
|
1001
|
+
big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
|
|
1002
|
+
little => @as(u16, a[i + 1]) << 8 | @as(u16, a[i]),
|
|
993
1003
|
};
|
|
994
1004
|
printc(" {d}", .{turn}, a, b, &i, 2, color);
|
|
995
1005
|
},
|
|
@@ -1000,13 +1010,13 @@ pub fn format(
|
|
|
1000
1010
|
var id = ID.from(@intCast(a[i]));
|
|
1001
1011
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1002
1012
|
switch (endian) {
|
|
1003
|
-
|
|
1013
|
+
big => {
|
|
1004
1014
|
var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1005
1015
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1006
1016
|
hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1007
1017
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
1008
1018
|
},
|
|
1009
|
-
|
|
1019
|
+
little => {
|
|
1010
1020
|
var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
1011
1021
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1012
1022
|
hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
@@ -1128,13 +1138,13 @@ pub fn format(
|
|
|
1128
1138
|
const id = ID.from(@intCast(a[i]));
|
|
1129
1139
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1130
1140
|
switch (endian) {
|
|
1131
|
-
|
|
1141
|
+
big => {
|
|
1132
1142
|
var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1133
1143
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1134
1144
|
hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1135
1145
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
1136
1146
|
},
|
|
1137
|
-
|
|
1147
|
+
little => {
|
|
1138
1148
|
var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
1139
1149
|
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1140
1150
|
hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
@@ -1202,14 +1212,11 @@ pub fn expectLog(
|
|
|
1202
1212
|
) !void {
|
|
1203
1213
|
if (!enabled) return;
|
|
1204
1214
|
|
|
1205
|
-
const color =
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
} else {
|
|
1211
|
-
break :color std.io.getStdErr().supportsAnsiEscapeCodes();
|
|
1212
|
-
}
|
|
1215
|
+
const color = if (std.process.hasEnvVarConstant("ZIG_DEBUG_COLOR"))
|
|
1216
|
+
true
|
|
1217
|
+
else switch (std.io.tty.detectConfig(std.io.getStdErr())) {
|
|
1218
|
+
.escape_codes => true,
|
|
1219
|
+
else => false,
|
|
1213
1220
|
};
|
|
1214
1221
|
|
|
1215
1222
|
expectEqualBytes(expected, actual, offset) catch |err| switch (err) {
|
|
@@ -1343,8 +1350,8 @@ test "|switch|" {
|
|
|
1343
1350
|
try log.switched(.{ p2.ident(3), &snorlax });
|
|
1344
1351
|
const par = 0b1000000;
|
|
1345
1352
|
var expected: []const u8 = switch (endian) {
|
|
1346
|
-
|
|
1347
|
-
|
|
1353
|
+
big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
|
|
1354
|
+
little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 200, 0, 144, 1, par },
|
|
1348
1355
|
};
|
|
1349
1356
|
try expectLog1(expected, buf[0..9]);
|
|
1350
1357
|
stream.reset();
|
|
@@ -1354,8 +1361,8 @@ test "|switch|" {
|
|
|
1354
1361
|
snorlax.status = 0;
|
|
1355
1362
|
try log.switched(.{ p2.ident(3), &snorlax });
|
|
1356
1363
|
expected = switch (endian) {
|
|
1357
|
-
|
|
1358
|
-
|
|
1364
|
+
big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
|
|
1365
|
+
little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 144, 1, 0 },
|
|
1359
1366
|
};
|
|
1360
1367
|
try expectLog1(expected, buf[0..9]);
|
|
1361
1368
|
stream.reset();
|
|
@@ -1363,8 +1370,8 @@ test "|switch|" {
|
|
|
1363
1370
|
snorlax.hp = 400;
|
|
1364
1371
|
try log.switched(.{ p2.ident(3), &snorlax });
|
|
1365
1372
|
expected = switch (endian) {
|
|
1366
|
-
|
|
1367
|
-
|
|
1373
|
+
big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
|
|
1374
|
+
little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 144, 1, 144, 1, 0 },
|
|
1368
1375
|
};
|
|
1369
1376
|
try expectLog1(expected, buf[0..9]);
|
|
1370
1377
|
stream.reset();
|
|
@@ -1382,8 +1389,8 @@ test "|switch|" {
|
|
|
1382
1389
|
N(gen2.Gender.Female),
|
|
1383
1390
|
91,
|
|
1384
1391
|
} ++ switch (endian) {
|
|
1385
|
-
|
|
1386
|
-
|
|
1392
|
+
big => .{ 0, 200, 1, 144, par },
|
|
1393
|
+
little => .{ 200, 0, 144, 1, par },
|
|
1387
1394
|
});
|
|
1388
1395
|
try expectLog2(expected, buf[0..10]);
|
|
1389
1396
|
stream.reset();
|
|
@@ -1412,8 +1419,8 @@ test "|faint|" {
|
|
|
1412
1419
|
test "|turn|" {
|
|
1413
1420
|
try log.turn(.{42});
|
|
1414
1421
|
const expected = switch (endian) {
|
|
1415
|
-
|
|
1416
|
-
|
|
1422
|
+
big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
|
|
1423
|
+
little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
|
|
1417
1424
|
};
|
|
1418
1425
|
try expectLog1(expected, buf[0..4]);
|
|
1419
1426
|
stream.reset();
|
|
@@ -1437,8 +1444,8 @@ test "|-damage|" {
|
|
|
1437
1444
|
chansey.status = gen1.Status.slp(1);
|
|
1438
1445
|
try log.damage(.{ p2.ident(2), &chansey, .None });
|
|
1439
1446
|
var expected: []const u8 = switch (endian) {
|
|
1440
|
-
|
|
1441
|
-
|
|
1447
|
+
big => &.{ N(ArgType.Damage), 0b1010, 2, 100, 2, 191, 1, N(Damage.None) },
|
|
1448
|
+
little => &.{ N(ArgType.Damage), 0b1010, 100, 2, 191, 2, 1, N(Damage.None) },
|
|
1442
1449
|
};
|
|
1443
1450
|
try expectLog1(expected, buf[0..8]);
|
|
1444
1451
|
stream.reset();
|
|
@@ -1448,8 +1455,8 @@ test "|-damage|" {
|
|
|
1448
1455
|
chansey.status = 0;
|
|
1449
1456
|
try log.damage(.{ p2.ident(2), &chansey, .Confusion });
|
|
1450
1457
|
expected = switch (endian) {
|
|
1451
|
-
|
|
1452
|
-
|
|
1458
|
+
big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0, N(Damage.Confusion) },
|
|
1459
|
+
little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0, N(Damage.Confusion) },
|
|
1453
1460
|
};
|
|
1454
1461
|
try expectLog1(expected, buf[0..8]);
|
|
1455
1462
|
stream.reset();
|
|
@@ -1457,8 +1464,8 @@ test "|-damage|" {
|
|
|
1457
1464
|
chansey.status = gen1.Status.init(.PSN);
|
|
1458
1465
|
try log.damage(.{ p2.ident(2), &chansey, .RecoilOf, p1.ident(1) });
|
|
1459
1466
|
expected = switch (endian) {
|
|
1460
|
-
|
|
1461
|
-
|
|
1467
|
+
big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0b1000, N(Damage.RecoilOf), 1 },
|
|
1468
|
+
little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0b1000, N(Damage.RecoilOf), 1 },
|
|
1462
1469
|
};
|
|
1463
1470
|
try expectLog1(expected, buf[0..9]);
|
|
1464
1471
|
stream.reset();
|
|
@@ -1470,8 +1477,8 @@ test "|-heal|" {
|
|
|
1470
1477
|
chansey.status = gen1.Status.slp(1);
|
|
1471
1478
|
try log.heal(.{ p2.ident(2), &chansey, .None });
|
|
1472
1479
|
var expected: []const u8 = switch (endian) {
|
|
1473
|
-
|
|
1474
|
-
|
|
1480
|
+
big => &.{ N(ArgType.Heal), 0b1010, 2, 100, 2, 191, 1, N(Heal.None) },
|
|
1481
|
+
little => &.{ N(ArgType.Heal), 0b1010, 100, 2, 191, 2, 1, N(Heal.None) },
|
|
1475
1482
|
};
|
|
1476
1483
|
try expectLog1(expected, buf[0..8]);
|
|
1477
1484
|
stream.reset();
|
|
@@ -1481,16 +1488,16 @@ test "|-heal|" {
|
|
|
1481
1488
|
chansey.status = 0;
|
|
1482
1489
|
try log.heal(.{ p2.ident(2), &chansey, .Silent });
|
|
1483
1490
|
expected = switch (endian) {
|
|
1484
|
-
|
|
1485
|
-
|
|
1491
|
+
big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Silent) },
|
|
1492
|
+
little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Silent) },
|
|
1486
1493
|
};
|
|
1487
1494
|
try expectLog1(expected, buf[0..8]);
|
|
1488
1495
|
stream.reset();
|
|
1489
1496
|
|
|
1490
1497
|
try log.heal(.{ p2.ident(2), &chansey, .Drain, p1.ident(1) });
|
|
1491
1498
|
expected = switch (endian) {
|
|
1492
|
-
|
|
1493
|
-
|
|
1499
|
+
big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Drain), 1 },
|
|
1500
|
+
little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Drain), 1 },
|
|
1494
1501
|
};
|
|
1495
1502
|
try expectLog1(expected, buf[0..9]);
|
|
1496
1503
|
stream.reset();
|
|
@@ -1733,8 +1740,8 @@ test "|drag|" {
|
|
|
1733
1740
|
N(gen2.Gender.Female),
|
|
1734
1741
|
91,
|
|
1735
1742
|
} ++ switch (endian) {
|
|
1736
|
-
|
|
1737
|
-
|
|
1743
|
+
big => .{ 0, 200, 1, 144, par },
|
|
1744
|
+
little => .{ 200, 0, 144, 1, par },
|
|
1738
1745
|
});
|
|
1739
1746
|
try expectLog2(expected, buf[0..10]);
|
|
1740
1747
|
stream.reset();
|
|
@@ -1767,8 +1774,8 @@ test "|-sethp|" {
|
|
|
1767
1774
|
blissey.hp = 612;
|
|
1768
1775
|
try log.sethp(.{ p2.ident(2), &blissey, .Silent });
|
|
1769
1776
|
const expected: []const u8 = switch (endian) {
|
|
1770
|
-
|
|
1771
|
-
|
|
1777
|
+
big => &.{ N(ArgType.SetHP), 0b1010, 2, 100, 2, 201, 0, N(SetHP.Silent) },
|
|
1778
|
+
little => &.{ N(ArgType.SetHP), 0b1010, 100, 2, 201, 2, 0, N(SetHP.Silent) },
|
|
1772
1779
|
};
|
|
1773
1780
|
try expectLog2(expected, buf[0..8]);
|
|
1774
1781
|
stream.reset();
|