@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.
Files changed (64) hide show
  1. package/LICENSE +0 -2
  2. package/README.md +15 -11
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +43 -0
  5. package/build/pkg/addon/browser.js.map +1 -0
  6. package/build/pkg/addon/node.d.ts +3 -0
  7. package/build/pkg/addon/node.js +96 -0
  8. package/build/pkg/addon/node.js.map +1 -0
  9. package/build/pkg/addon.d.ts +2 -0
  10. package/build/pkg/addon.js +35 -58
  11. package/build/pkg/addon.js.map +1 -1
  12. package/build/pkg/data.d.ts +25 -4
  13. package/build/pkg/data.js.map +1 -1
  14. package/build/pkg/gen1.js +1 -1
  15. package/build/pkg/gen1.js.map +1 -1
  16. package/build/pkg/index.d.ts +22 -9
  17. package/build/pkg/index.js +15 -10
  18. package/build/pkg/index.js.map +1 -1
  19. package/build/pkg/protocol.d.ts +20 -1
  20. package/build/pkg/protocol.js +109 -107
  21. package/build/pkg/protocol.js.map +1 -1
  22. package/build/tools/debug.js +36 -70
  23. package/build/tools/debug.js.map +1 -1
  24. package/build/tools/display/debug.jsx +141 -0
  25. package/build/tools/display/debug.jsx.map +1 -0
  26. package/build/tools/display/index.js +132 -0
  27. package/build/tools/display/index.js.map +1 -0
  28. package/build/tools/display/ui.jsx +349 -0
  29. package/build/tools/display/ui.jsx.map +1 -0
  30. package/build/tools/display/util.js +18 -0
  31. package/build/tools/display/util.js.map +1 -0
  32. package/build.zig +187 -72
  33. package/package.json +48 -32
  34. package/src/bin/install-pkmn-engine +17 -7
  35. package/src/bin/pkmn-debug +1 -1
  36. package/src/lib/common/array.zig +77 -0
  37. package/src/lib/common/data.zig +8 -8
  38. package/src/lib/common/debug.zig +39 -8
  39. package/src/lib/common/js.zig +4 -2
  40. package/src/lib/common/optional.zig +13 -9
  41. package/src/lib/common/options.zig +4 -0
  42. package/src/lib/common/protocol.zig +51 -44
  43. package/src/lib/common/rational.zig +114 -24
  44. package/src/lib/common/rng.zig +10 -10
  45. package/src/lib/common/util.zig +50 -1
  46. package/src/lib/gen1/calc.zig +671 -125
  47. package/src/lib/gen1/chance.zig +384 -275
  48. package/src/lib/gen1/data/species.zig +1 -1
  49. package/src/lib/gen1/data.zig +31 -30
  50. package/src/lib/gen1/helpers.zig +89 -538
  51. package/src/lib/gen1/mechanics.zig +297 -189
  52. package/src/lib/gen2/calc.zig +34 -16
  53. package/src/lib/gen2/chance.zig +90 -502
  54. package/src/lib/gen2/data.zig +15 -14
  55. package/src/lib/gen2/helpers.zig +41 -13
  56. package/src/lib/gen2/mechanics.zig +158 -103
  57. package/src/lib/pkmn.zig +10 -16
  58. package/src/tools/display/dom.ts +96 -0
  59. package/src/tools/display/ui.css +359 -0
  60. package/build/test/display.js +0 -400
  61. package/build/test/display.js.map +0 -1
  62. package/src/lib/gen1/README.md +0 -894
  63. package/src/lib/gen2/README.md +0 -329
  64. 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: 12, patch: 0, dev: 2036};
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
- const version = Object.keys(index)[+!ZIG_VERSION.dev];
167
- const release = index[version][`${arch}-${platform}`];
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') args.push(`-Dnode-import-library=${lib}`);
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
- const actual = path.join('build', 'lib', `${prefix}pkmn${suffix}.node.${ext}`);
390
- fs.renameSync(path.join(ROOT, actual), path.join(ROOT, artifact));
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 => {
@@ -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', 'mustache']) {
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
+ }
@@ -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
  }
@@ -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 debug.getStderrMutex().unlock();
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
- .Struct => |info| {
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
- .Array => |info| {
55
+ Array => |info| {
46
56
  if (info.child == u8) return stderr.print("{s}", .{value}) catch return;
47
57
  @compileError(err);
48
58
  },
49
- .Pointer => |ptr_info| switch (ptr_info.size) {
59
+ Pointer => |ptr_info| switch (ptr_info.size) {
50
60
  .One => switch (@typeInfo(ptr_info.child)) {
51
- .Array => |info| {
61
+ Array => |info| {
52
62
  if (info.child == u8) return stderr.print("{s}", .{value}) catch return;
53
63
  @compileError(err);
54
64
  },
55
- .Enum, .Union, .Struct => return inspect(value.*),
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
- .Optional => stderr.print("{?}", .{value}) catch return,
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
+ }
@@ -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
- .Int => |info| switch (info.bits) {
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
- .Int => |info| switch (info.bits) {
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
- .Bool => enum { false, true },
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
- return @Type(.{
27
- .Enum = .{
28
- .tag_type = std.math.IntFittingRange(0, fields.len),
29
- .fields = &enumFields,
30
- .decls = &decls,
31
- .is_exhaustive = true,
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).Int.bits, 8)]u8 = undefined;
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
- comptime gen: anytype,
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
- .big => {
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
- .little => {
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
- .big => @as(u16, a[i]) << 8 | @as(u16, a[i + 1]),
992
- .little => @as(u16, a[i + 1]) << 8 | @as(u16, a[i]),
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
- .big => {
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
- .little => {
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
- .big => {
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
- .little => {
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 = color: {
1206
- if (std.process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) {
1207
- break :color true;
1208
- } else if (std.process.hasEnvVarConstant("NO_COLOR")) {
1209
- break :color false;
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
- .big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
1347
- .little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 200, 0, 144, 1, par },
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
- .big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
1358
- .little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 144, 1, 0 },
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
- .big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
1367
- .little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 144, 1, 144, 1, 0 },
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
- .big => .{ 0, 200, 1, 144, par },
1386
- .little => .{ 200, 0, 144, 1, par },
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
- .big => &.{ N(ArgType.Turn), 0, 42, N(ArgType.None) },
1416
- .little => &.{ N(ArgType.Turn), 42, 0, N(ArgType.None) },
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
- .big => &.{ N(ArgType.Damage), 0b1010, 2, 100, 2, 191, 1, N(Damage.None) },
1441
- .little => &.{ N(ArgType.Damage), 0b1010, 100, 2, 191, 2, 1, N(Damage.None) },
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
- .big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0, N(Damage.Confusion) },
1452
- .little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0, N(Damage.Confusion) },
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
- .big => &.{ N(ArgType.Damage), 0b1010, 0, 100, 1, 0, 0b1000, N(Damage.RecoilOf), 1 },
1461
- .little => &.{ N(ArgType.Damage), 0b1010, 100, 0, 0, 1, 0b1000, N(Damage.RecoilOf), 1 },
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
- .big => &.{ N(ArgType.Heal), 0b1010, 2, 100, 2, 191, 1, N(Heal.None) },
1474
- .little => &.{ N(ArgType.Heal), 0b1010, 100, 2, 191, 2, 1, N(Heal.None) },
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
- .big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Silent) },
1485
- .little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Silent) },
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
- .big => &.{ N(ArgType.Heal), 0b1010, 0, 100, 1, 0, 0, N(Heal.Drain), 1 },
1493
- .little => &.{ N(ArgType.Heal), 0b1010, 100, 0, 0, 1, 0, N(Heal.Drain), 1 },
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
- .big => .{ 0, 200, 1, 144, par },
1737
- .little => .{ 200, 0, 144, 1, par },
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
- .big => &.{ N(ArgType.SetHP), 0b1010, 2, 100, 2, 201, 0, N(SetHP.Silent) },
1771
- .little => &.{ N(ArgType.SetHP), 0b1010, 100, 2, 201, 2, 0, N(SetHP.Silent) },
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();