@pkmn/engine 0.1.0-dev.9a0c07c3 → 0.1.0-dev.a324c50f
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 +32 -29
- package/build/pkg/addon.d.ts +7 -0
- package/build/pkg/addon.js +112 -0
- package/build/pkg/addon.js.map +1 -0
- package/build/pkg/data/layout.json +25 -3
- package/build/pkg/gen1.d.ts +5 -4
- package/build/pkg/gen1.js +47 -31
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/index.d.ts +15 -12
- package/build/pkg/index.js.map +1 -1
- package/build/pkg/protocol.d.ts +4 -2
- package/build/pkg/protocol.js +4 -2
- package/build/pkg/protocol.js.map +1 -1
- package/build/test/display.js +31 -13
- package/build/test/display.js.map +1 -1
- package/build.zig +49 -39
- package/package.json +18 -14
- package/src/bin/install-pkmn-engine +11 -6
- package/src/bin/pkmn-debug +34 -7
- package/src/lib/binding/node.zig +46 -141
- package/src/lib/binding/wasm.zig +6 -4
- package/src/lib/common/data.zig +11 -11
- package/src/lib/common/debug.zig +21 -11
- package/src/lib/common/options.zig +12 -3
- package/src/lib/common/protocol.zig +239 -178
- package/src/lib/common/rng.zig +10 -10
- package/src/lib/gen1/README.md +111 -81
- package/src/lib/gen1/data/moves.zig +10 -10
- package/src/lib/gen1/data/species.zig +2 -2
- package/src/lib/gen1/data/types.zig +3 -3
- package/src/lib/gen1/data.zig +64 -43
- package/src/lib/gen1/helpers.zig +439 -32
- package/src/lib/gen1/mechanics.zig +987 -612
- package/src/lib/gen2/data/items.zig +3 -3
- package/src/lib/gen2/data/moves.zig +1 -1
- package/src/lib/gen2/data/species.zig +1 -1
- package/src/lib/gen2/data/types.zig +3 -3
- package/src/lib/gen2/data.zig +37 -26
- package/src/lib/gen2/helpers.zig +9 -11
- package/src/lib/gen2/mechanics.zig +5 -4
- package/src/lib/pkmn.zig +68 -9
|
@@ -7,7 +7,7 @@ const options = @import("./options.zig");
|
|
|
7
7
|
const assert = std.debug.assert;
|
|
8
8
|
const print = std.debug.print;
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const enabled = options.log;
|
|
11
11
|
|
|
12
12
|
const Player = data.Player;
|
|
13
13
|
const ID = data.ID;
|
|
@@ -219,8 +219,12 @@ pub const Immune = enum(u8) {
|
|
|
219
219
|
OHKO,
|
|
220
220
|
};
|
|
221
221
|
|
|
222
|
+
/// Null object pattern implementation of `Log` backed by a `std.io.null_writer`.
|
|
223
|
+
/// Ignores anything sent to it, though protocol logging should additionally be turned off
|
|
224
|
+
/// entirely with `options.log`.
|
|
222
225
|
pub const NULL = Log(@TypeOf(std.io.null_writer)){ .writer = std.io.null_writer };
|
|
223
226
|
|
|
227
|
+
/// Logs protocol information to its `Writer` during a battle update when `options.log` is enabled.
|
|
224
228
|
pub fn Log(comptime Writer: type) type {
|
|
225
229
|
return struct {
|
|
226
230
|
const Self = @This();
|
|
@@ -230,91 +234,100 @@ pub fn Log(comptime Writer: type) type {
|
|
|
230
234
|
pub const Error = Writer.Error;
|
|
231
235
|
|
|
232
236
|
pub fn move(self: Self, source: ID, m: anytype, target: ID, from: anytype) Error!void {
|
|
233
|
-
if (!
|
|
237
|
+
if (!enabled) return;
|
|
238
|
+
|
|
234
239
|
assert(m != .None);
|
|
235
240
|
try self.writer.writeAll(&.{
|
|
236
|
-
@
|
|
237
|
-
@
|
|
238
|
-
@
|
|
239
|
-
@
|
|
241
|
+
@intFromEnum(ArgType.Move),
|
|
242
|
+
@as(u8, @bitCast(source)),
|
|
243
|
+
@intFromEnum(m),
|
|
244
|
+
@as(u8, @bitCast(target)),
|
|
240
245
|
});
|
|
241
|
-
const none = &[_]u8{@
|
|
246
|
+
const none = &[_]u8{@intFromEnum(Move.None)};
|
|
242
247
|
try self.writer.writeAll(switch (@typeInfo(@TypeOf(from))) {
|
|
243
248
|
.Null => none,
|
|
244
249
|
.Optional => if (from) |f| blk: {
|
|
245
|
-
assert(@
|
|
246
|
-
break :blk &[_]u8{ @
|
|
250
|
+
assert(@intFromEnum(f) != 0);
|
|
251
|
+
break :blk &[_]u8{ @intFromEnum(Move.From), @intFromEnum(f) };
|
|
247
252
|
} else none,
|
|
248
253
|
else => blk: {
|
|
249
|
-
assert(@
|
|
250
|
-
break :blk &[_]u8{ @
|
|
254
|
+
assert(@intFromEnum(from) != 0);
|
|
255
|
+
break :blk &[_]u8{ @intFromEnum(Move.From), @intFromEnum(from) };
|
|
251
256
|
},
|
|
252
257
|
});
|
|
253
258
|
}
|
|
254
259
|
|
|
255
260
|
pub fn switched(self: Self, ident: ID, pokemon: anytype) Error!void {
|
|
256
|
-
if (!
|
|
257
|
-
|
|
258
|
-
try self.writer.writeAll(&.{ @
|
|
261
|
+
if (!enabled) return;
|
|
262
|
+
|
|
263
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Switch), @as(u8, @bitCast(ident)) });
|
|
264
|
+
try self.writer.writeAll(&.{ @intFromEnum(pokemon.species), pokemon.level });
|
|
259
265
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
260
266
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
261
267
|
try self.writer.writeAll(&.{pokemon.status});
|
|
262
268
|
}
|
|
263
269
|
|
|
264
270
|
pub fn cant(self: Self, ident: ID, reason: Cant) Error!void {
|
|
265
|
-
if (!
|
|
271
|
+
if (!enabled) return;
|
|
272
|
+
|
|
266
273
|
assert(reason != .Disable);
|
|
267
274
|
try self.writer.writeAll(&.{
|
|
268
|
-
@
|
|
269
|
-
@
|
|
270
|
-
@
|
|
275
|
+
@intFromEnum(ArgType.Cant),
|
|
276
|
+
@as(u8, @bitCast(ident)),
|
|
277
|
+
@intFromEnum(reason),
|
|
271
278
|
});
|
|
272
279
|
}
|
|
273
280
|
|
|
274
281
|
pub fn disabled(self: Self, ident: ID, m: anytype) Error!void {
|
|
275
|
-
if (!
|
|
282
|
+
if (!enabled) return;
|
|
283
|
+
|
|
276
284
|
try self.writer.writeAll(&.{
|
|
277
|
-
@
|
|
278
|
-
@
|
|
279
|
-
@
|
|
280
|
-
@
|
|
285
|
+
@intFromEnum(ArgType.Cant),
|
|
286
|
+
@as(u8, @bitCast(ident)),
|
|
287
|
+
@intFromEnum(Cant.Disable),
|
|
288
|
+
@intFromEnum(m),
|
|
281
289
|
});
|
|
282
290
|
}
|
|
283
291
|
|
|
284
292
|
pub fn faint(self: Self, ident: ID, done: bool) Error!void {
|
|
285
|
-
if (!
|
|
286
|
-
|
|
287
|
-
|
|
293
|
+
if (!enabled) return;
|
|
294
|
+
|
|
295
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Faint), @as(u8, @bitCast(ident)) });
|
|
296
|
+
if (done) try self.writer.writeByte(@intFromEnum(ArgType.None));
|
|
288
297
|
}
|
|
289
298
|
|
|
290
299
|
pub fn turn(self: Self, num: u16) Error!void {
|
|
291
|
-
if (!
|
|
292
|
-
|
|
300
|
+
if (!enabled) return;
|
|
301
|
+
|
|
302
|
+
try self.writer.writeByte(@intFromEnum(ArgType.Turn));
|
|
293
303
|
try self.writer.writeIntNative(u16, num);
|
|
294
|
-
try self.writer.writeByte(@
|
|
304
|
+
try self.writer.writeByte(@intFromEnum(ArgType.None));
|
|
295
305
|
}
|
|
296
306
|
|
|
297
307
|
pub fn win(self: Self, player: Player) Error!void {
|
|
298
|
-
if (!
|
|
308
|
+
if (!enabled) return;
|
|
309
|
+
|
|
299
310
|
try self.writer.writeAll(&.{
|
|
300
|
-
@
|
|
301
|
-
@
|
|
302
|
-
@
|
|
311
|
+
@intFromEnum(ArgType.Win),
|
|
312
|
+
@intFromEnum(player),
|
|
313
|
+
@intFromEnum(ArgType.None),
|
|
303
314
|
});
|
|
304
315
|
}
|
|
305
316
|
|
|
306
317
|
pub fn tie(self: Self) Error!void {
|
|
307
|
-
if (!
|
|
308
|
-
|
|
318
|
+
if (!enabled) return;
|
|
319
|
+
|
|
320
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Tie), @intFromEnum(ArgType.None) });
|
|
309
321
|
}
|
|
310
322
|
|
|
311
323
|
pub fn damage(self: Self, ident: ID, pokemon: anytype, reason: Damage) Error!void {
|
|
312
|
-
if (!
|
|
313
|
-
|
|
314
|
-
|
|
324
|
+
if (!enabled) return;
|
|
325
|
+
|
|
326
|
+
assert(@intFromEnum(reason) <= @intFromEnum(Damage.LeechSeed));
|
|
327
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @as(u8, @bitCast(ident)) });
|
|
315
328
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
316
329
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
317
|
-
try self.writer.writeAll(&.{ pokemon.status, @
|
|
330
|
+
try self.writer.writeAll(&.{ pokemon.status, @intFromEnum(reason) });
|
|
318
331
|
}
|
|
319
332
|
|
|
320
333
|
pub fn damageOf(
|
|
@@ -324,227 +337,271 @@ pub fn Log(comptime Writer: type) type {
|
|
|
324
337
|
reason: Damage,
|
|
325
338
|
source: ID,
|
|
326
339
|
) Error!void {
|
|
327
|
-
if (!
|
|
328
|
-
|
|
329
|
-
|
|
340
|
+
if (!enabled) return;
|
|
341
|
+
|
|
342
|
+
assert(@intFromEnum(reason) == @intFromEnum(Damage.RecoilOf));
|
|
343
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @as(u8, @bitCast(ident)) });
|
|
330
344
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
331
345
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
332
346
|
try self.writer.writeAll(&.{
|
|
333
347
|
pokemon.status,
|
|
334
|
-
@
|
|
335
|
-
@
|
|
348
|
+
@intFromEnum(reason),
|
|
349
|
+
@as(u8, @bitCast(source)),
|
|
336
350
|
});
|
|
337
351
|
}
|
|
338
352
|
|
|
339
353
|
pub fn heal(self: Self, ident: ID, pokemon: anytype, reason: Heal) Error!void {
|
|
340
|
-
if (!
|
|
354
|
+
if (!enabled) return;
|
|
355
|
+
|
|
341
356
|
assert(reason != .Drain);
|
|
342
|
-
try self.writer.writeAll(&.{ @
|
|
357
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(ident)) });
|
|
343
358
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
344
359
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
345
|
-
try self.writer.writeAll(&.{ pokemon.status, @
|
|
360
|
+
try self.writer.writeAll(&.{ pokemon.status, @intFromEnum(reason) });
|
|
346
361
|
}
|
|
347
362
|
|
|
348
363
|
pub fn drain(self: Self, source: ID, pokemon: anytype, target: ID) Error!void {
|
|
349
|
-
if (!
|
|
350
|
-
|
|
364
|
+
if (!enabled) return;
|
|
365
|
+
|
|
366
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(source)) });
|
|
351
367
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
352
368
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
353
369
|
try self.writer.writeAll(&.{
|
|
354
370
|
pokemon.status,
|
|
355
|
-
@
|
|
356
|
-
@
|
|
371
|
+
@intFromEnum(Heal.Drain),
|
|
372
|
+
@as(u8, @bitCast(target)),
|
|
357
373
|
});
|
|
358
374
|
}
|
|
359
375
|
|
|
360
376
|
pub fn status(self: Self, ident: ID, value: u8, reason: Status) Error!void {
|
|
361
|
-
if (!
|
|
377
|
+
if (!enabled) return;
|
|
378
|
+
|
|
362
379
|
assert(reason != .From);
|
|
363
380
|
try self.writer.writeAll(&.{
|
|
364
|
-
@
|
|
365
|
-
@
|
|
381
|
+
@intFromEnum(ArgType.Status),
|
|
382
|
+
@as(u8, @bitCast(ident)),
|
|
366
383
|
value,
|
|
367
|
-
@
|
|
384
|
+
@intFromEnum(reason),
|
|
368
385
|
});
|
|
369
386
|
}
|
|
370
387
|
|
|
371
388
|
pub fn statusFrom(self: Self, ident: ID, value: u8, m: anytype) Error!void {
|
|
372
|
-
if (!
|
|
389
|
+
if (!enabled) return;
|
|
390
|
+
|
|
373
391
|
try self.writer.writeAll(&.{
|
|
374
|
-
@
|
|
375
|
-
@
|
|
392
|
+
@intFromEnum(ArgType.Status),
|
|
393
|
+
@as(u8, @bitCast(ident)),
|
|
376
394
|
value,
|
|
377
|
-
@
|
|
378
|
-
@
|
|
395
|
+
@intFromEnum(Status.From),
|
|
396
|
+
@intFromEnum(m),
|
|
379
397
|
});
|
|
380
398
|
}
|
|
381
399
|
|
|
382
400
|
pub fn curestatus(self: Self, ident: ID, value: u8, reason: CureStatus) Error!void {
|
|
383
|
-
if (!
|
|
401
|
+
if (!enabled) return;
|
|
402
|
+
|
|
384
403
|
try self.writer.writeAll(&.{
|
|
385
|
-
@
|
|
386
|
-
@
|
|
404
|
+
@intFromEnum(ArgType.CureStatus),
|
|
405
|
+
@as(u8, @bitCast(ident)),
|
|
387
406
|
value,
|
|
388
|
-
@
|
|
407
|
+
@intFromEnum(reason),
|
|
389
408
|
});
|
|
390
409
|
}
|
|
391
410
|
|
|
392
411
|
pub fn boost(self: Self, ident: ID, reason: Boost, num: i8) Error!void {
|
|
393
|
-
if (!
|
|
412
|
+
if (!enabled) return;
|
|
413
|
+
|
|
394
414
|
assert(num != 0 and (reason != .Rage or num > 0));
|
|
395
415
|
try self.writer.writeAll(&.{
|
|
396
|
-
@
|
|
397
|
-
@
|
|
398
|
-
@
|
|
399
|
-
@
|
|
416
|
+
@intFromEnum(ArgType.Boost),
|
|
417
|
+
@as(u8, @bitCast(ident)),
|
|
418
|
+
@intFromEnum(reason),
|
|
419
|
+
@as(u8, @intCast(num + 6)),
|
|
400
420
|
});
|
|
401
421
|
}
|
|
402
422
|
|
|
403
423
|
pub fn clearallboost(self: Self) Error!void {
|
|
404
|
-
if (!
|
|
405
|
-
|
|
424
|
+
if (!enabled) return;
|
|
425
|
+
|
|
426
|
+
try self.writer.writeAll(&.{@intFromEnum(ArgType.ClearAllBoost)});
|
|
406
427
|
}
|
|
407
428
|
|
|
408
429
|
pub fn fail(self: Self, ident: ID, reason: Fail) Error!void {
|
|
409
|
-
if (!
|
|
430
|
+
if (!enabled) return;
|
|
431
|
+
|
|
410
432
|
try self.writer.writeAll(&.{
|
|
411
|
-
@
|
|
412
|
-
@
|
|
413
|
-
@
|
|
433
|
+
@intFromEnum(ArgType.Fail),
|
|
434
|
+
@as(u8, @bitCast(ident)),
|
|
435
|
+
@intFromEnum(reason),
|
|
414
436
|
});
|
|
415
437
|
}
|
|
416
438
|
|
|
417
439
|
pub fn miss(self: Self, source: ID) Error!void {
|
|
418
|
-
if (!
|
|
419
|
-
|
|
440
|
+
if (!enabled) return;
|
|
441
|
+
|
|
442
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Miss), @as(u8, @bitCast(source)) });
|
|
420
443
|
}
|
|
421
444
|
|
|
422
445
|
pub fn hitcount(self: Self, ident: ID, num: u8) Error!void {
|
|
423
|
-
if (!
|
|
424
|
-
|
|
446
|
+
if (!enabled) return;
|
|
447
|
+
|
|
448
|
+
try self.writer.writeAll(&.{
|
|
449
|
+
@intFromEnum(ArgType.HitCount),
|
|
450
|
+
@as(u8, @bitCast(ident)),
|
|
451
|
+
num,
|
|
452
|
+
});
|
|
425
453
|
}
|
|
426
454
|
|
|
427
455
|
pub fn prepare(self: Self, source: ID, m: anytype) Error!void {
|
|
428
|
-
if (!
|
|
456
|
+
if (!enabled) return;
|
|
457
|
+
|
|
429
458
|
try self.writer.writeAll(&.{
|
|
430
|
-
@
|
|
431
|
-
@
|
|
432
|
-
@
|
|
459
|
+
@intFromEnum(ArgType.Prepare),
|
|
460
|
+
@as(u8, @bitCast(source)),
|
|
461
|
+
@intFromEnum(m),
|
|
433
462
|
});
|
|
434
463
|
}
|
|
435
464
|
|
|
436
465
|
pub fn mustrecharge(self: Self, ident: ID) Error!void {
|
|
437
|
-
if (!
|
|
438
|
-
|
|
466
|
+
if (!enabled) return;
|
|
467
|
+
|
|
468
|
+
try self.writer.writeAll(&.{
|
|
469
|
+
@intFromEnum(ArgType.MustRecharge),
|
|
470
|
+
@as(u8, @bitCast(ident)),
|
|
471
|
+
});
|
|
439
472
|
}
|
|
440
473
|
|
|
441
474
|
pub fn activate(self: Self, ident: ID, reason: Activate) Error!void {
|
|
442
|
-
if (!
|
|
475
|
+
if (!enabled) return;
|
|
476
|
+
|
|
443
477
|
try self.writer.writeAll(&.{
|
|
444
|
-
@
|
|
445
|
-
@
|
|
446
|
-
@
|
|
478
|
+
@intFromEnum(ArgType.Activate),
|
|
479
|
+
@as(u8, @bitCast(ident)),
|
|
480
|
+
@intFromEnum(reason),
|
|
447
481
|
});
|
|
448
482
|
}
|
|
449
483
|
|
|
450
484
|
pub fn fieldactivate(self: Self) Error!void {
|
|
451
|
-
if (!
|
|
452
|
-
|
|
485
|
+
if (!enabled) return;
|
|
486
|
+
|
|
487
|
+
try self.writer.writeAll(&.{@intFromEnum(ArgType.FieldActivate)});
|
|
453
488
|
}
|
|
454
489
|
|
|
455
490
|
pub fn start(self: Self, ident: ID, reason: Start) Error!void {
|
|
456
|
-
if (!
|
|
457
|
-
|
|
491
|
+
if (!enabled) return;
|
|
492
|
+
|
|
493
|
+
assert(@intFromEnum(reason) < @intFromEnum(Start.TypeChange));
|
|
458
494
|
try self.writer.writeAll(&.{
|
|
459
|
-
@
|
|
460
|
-
@
|
|
461
|
-
@
|
|
495
|
+
@intFromEnum(ArgType.Start),
|
|
496
|
+
@as(u8, @bitCast(ident)),
|
|
497
|
+
@intFromEnum(reason),
|
|
462
498
|
});
|
|
463
499
|
}
|
|
464
500
|
|
|
465
501
|
pub fn typechange(self: Self, source: ID, types: anytype, target: ID) Error!void {
|
|
466
|
-
if (!
|
|
502
|
+
if (!enabled) return;
|
|
503
|
+
|
|
467
504
|
try self.writer.writeAll(&.{
|
|
468
|
-
@
|
|
469
|
-
@
|
|
470
|
-
@
|
|
471
|
-
@
|
|
472
|
-
@
|
|
505
|
+
@intFromEnum(ArgType.Start),
|
|
506
|
+
@as(u8, @bitCast(source)),
|
|
507
|
+
@intFromEnum(Start.TypeChange),
|
|
508
|
+
@as(u8, @bitCast(types)),
|
|
509
|
+
@as(u8, @bitCast(target)),
|
|
473
510
|
});
|
|
474
511
|
}
|
|
475
512
|
|
|
476
513
|
pub fn startEffect(self: Self, ident: ID, reason: Start, m: anytype) Error!void {
|
|
477
|
-
if (!
|
|
478
|
-
|
|
514
|
+
if (!enabled) return;
|
|
515
|
+
|
|
516
|
+
assert(@intFromEnum(reason) > @intFromEnum(Start.TypeChange));
|
|
479
517
|
try self.writer.writeAll(&.{
|
|
480
|
-
@
|
|
481
|
-
@
|
|
482
|
-
@
|
|
483
|
-
@
|
|
518
|
+
@intFromEnum(ArgType.Start),
|
|
519
|
+
@as(u8, @bitCast(ident)),
|
|
520
|
+
@intFromEnum(reason),
|
|
521
|
+
@intFromEnum(m),
|
|
484
522
|
});
|
|
485
523
|
}
|
|
486
524
|
|
|
487
525
|
pub fn end(self: Self, ident: ID, reason: End) Error!void {
|
|
488
|
-
if (!
|
|
526
|
+
if (!enabled) return;
|
|
527
|
+
|
|
489
528
|
try self.writer.writeAll(&.{
|
|
490
|
-
@
|
|
491
|
-
@
|
|
492
|
-
@
|
|
529
|
+
@intFromEnum(ArgType.End),
|
|
530
|
+
@as(u8, @bitCast(ident)),
|
|
531
|
+
@intFromEnum(reason),
|
|
493
532
|
});
|
|
494
533
|
}
|
|
495
534
|
|
|
496
535
|
pub fn ohko(self: Self) Error!void {
|
|
497
|
-
if (!
|
|
498
|
-
|
|
536
|
+
if (!enabled) return;
|
|
537
|
+
|
|
538
|
+
try self.writer.writeAll(&.{@intFromEnum(ArgType.OHKO)});
|
|
499
539
|
}
|
|
500
540
|
|
|
501
541
|
pub fn crit(self: Self, ident: ID) Error!void {
|
|
502
|
-
if (!
|
|
503
|
-
|
|
542
|
+
if (!enabled) return;
|
|
543
|
+
|
|
544
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Crit), @as(u8, @bitCast(ident)) });
|
|
504
545
|
}
|
|
505
546
|
|
|
506
547
|
pub fn supereffective(self: Self, ident: ID) Error!void {
|
|
507
|
-
if (!
|
|
508
|
-
|
|
548
|
+
if (!enabled) return;
|
|
549
|
+
|
|
550
|
+
try self.writer.writeAll(&.{
|
|
551
|
+
@intFromEnum(ArgType.SuperEffective),
|
|
552
|
+
@as(u8, @bitCast(ident)),
|
|
553
|
+
});
|
|
509
554
|
}
|
|
510
555
|
|
|
511
556
|
pub fn resisted(self: Self, ident: ID) Error!void {
|
|
512
|
-
if (!
|
|
513
|
-
|
|
557
|
+
if (!enabled) return;
|
|
558
|
+
|
|
559
|
+
try self.writer.writeAll(&.{
|
|
560
|
+
@intFromEnum(ArgType.Resisted),
|
|
561
|
+
@as(u8, @bitCast(ident)),
|
|
562
|
+
});
|
|
514
563
|
}
|
|
515
564
|
|
|
516
565
|
pub fn immune(self: Self, ident: ID, reason: Immune) Error!void {
|
|
517
|
-
if (!
|
|
566
|
+
if (!enabled) return;
|
|
567
|
+
|
|
518
568
|
try self.writer.writeAll(&.{
|
|
519
|
-
@
|
|
520
|
-
@
|
|
521
|
-
@
|
|
569
|
+
@intFromEnum(ArgType.Immune),
|
|
570
|
+
@as(u8, @bitCast(ident)),
|
|
571
|
+
@intFromEnum(reason),
|
|
522
572
|
});
|
|
523
573
|
}
|
|
524
574
|
|
|
525
575
|
pub fn transform(self: Self, source: ID, target: ID) Error!void {
|
|
526
|
-
if (!
|
|
576
|
+
if (!enabled) return;
|
|
577
|
+
|
|
527
578
|
try self.writer.writeAll(&.{
|
|
528
|
-
@
|
|
529
|
-
@
|
|
530
|
-
@
|
|
579
|
+
@intFromEnum(ArgType.Transform),
|
|
580
|
+
@as(u8, @bitCast(source)),
|
|
581
|
+
@as(u8, @bitCast(target)),
|
|
531
582
|
});
|
|
532
583
|
}
|
|
533
584
|
|
|
534
585
|
pub fn laststill(self: Self) Error!void {
|
|
535
|
-
if (!
|
|
536
|
-
|
|
586
|
+
if (!enabled) return;
|
|
587
|
+
|
|
588
|
+
try self.writer.writeAll(&.{@intFromEnum(ArgType.LastStill)});
|
|
537
589
|
}
|
|
538
590
|
|
|
539
591
|
pub fn lastmiss(self: Self) Error!void {
|
|
540
|
-
if (!
|
|
541
|
-
|
|
592
|
+
if (!enabled) return;
|
|
593
|
+
|
|
594
|
+
try self.writer.writeAll(&.{@intFromEnum(ArgType.LastMiss)});
|
|
542
595
|
}
|
|
543
596
|
};
|
|
544
597
|
}
|
|
545
598
|
|
|
599
|
+
/// `Log` type backed by the optimized `ByteStream.Writer`.
|
|
546
600
|
pub const FixedLog = Log(ByteStream.Writer);
|
|
547
601
|
|
|
602
|
+
/// Stripped down version of `std.io.FixedBufferStream` optimized for efficiently writing the
|
|
603
|
+
/// individual protocol bytes. Note that the `ByteStream.Writer` is **not** a `std.io.Writer` and
|
|
604
|
+
/// should not be used for general purpose writing.
|
|
548
605
|
pub const ByteStream = struct {
|
|
549
606
|
buffer: []u8,
|
|
550
607
|
pos: usize = 0,
|
|
@@ -593,7 +650,7 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
593
650
|
|
|
594
651
|
var i: usize = 0;
|
|
595
652
|
while (i < a.len) {
|
|
596
|
-
const arg = @
|
|
653
|
+
const arg: ArgType = @enumFromInt(a[i]);
|
|
597
654
|
const name = switch (arg) {
|
|
598
655
|
.None => if (color) "\x1b[2m-\x1b[0m" else "-",
|
|
599
656
|
.LastStill => "|[still]",
|
|
@@ -639,17 +696,17 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
639
696
|
.OHKO,
|
|
640
697
|
=> {},
|
|
641
698
|
.Move => {
|
|
642
|
-
const source = ID.from(@intCast(
|
|
699
|
+
const source = ID.from(@intCast(a[i]));
|
|
643
700
|
printc(" {s}({d})", .{ @tagName(source.player), source.id }, a, b, &i, 1, color);
|
|
644
701
|
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
645
|
-
const target = ID.from(@intCast(
|
|
702
|
+
const target = ID.from(@intCast(a[i]));
|
|
646
703
|
printc(" {s}({d})", .{ @tagName(target.player), target.id }, a, b, &i, 1, color);
|
|
647
|
-
const reason = @
|
|
704
|
+
const reason: Move = @enumFromInt(a[i]);
|
|
648
705
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
649
706
|
if (reason == .From) printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
650
707
|
},
|
|
651
708
|
.Switch => {
|
|
652
|
-
const id = ID.from(@intCast(
|
|
709
|
+
const id = ID.from(@intCast(a[i]));
|
|
653
710
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
654
711
|
printc(" {s}", .{formatter(.Species, a[i])}, a, b, &i, 1, color);
|
|
655
712
|
printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
|
|
@@ -670,9 +727,9 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
670
727
|
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
671
728
|
},
|
|
672
729
|
.Cant => {
|
|
673
|
-
const id = ID.from(@intCast(
|
|
730
|
+
const id = ID.from(@intCast(a[i]));
|
|
674
731
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
675
|
-
const reason = @
|
|
732
|
+
const reason: Cant = @enumFromInt(a[i]);
|
|
676
733
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
677
734
|
if (reason == .Disable) {
|
|
678
735
|
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
@@ -685,7 +742,7 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
685
742
|
.SuperEffective,
|
|
686
743
|
.Resisted,
|
|
687
744
|
=> {
|
|
688
|
-
const id = ID.from(@intCast(
|
|
745
|
+
const id = ID.from(@intCast(a[i]));
|
|
689
746
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
690
747
|
},
|
|
691
748
|
.Turn => {
|
|
@@ -695,9 +752,11 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
695
752
|
};
|
|
696
753
|
printc(" {d}", .{turn}, a, b, &i, 2, color);
|
|
697
754
|
},
|
|
698
|
-
.Win =>
|
|
755
|
+
.Win => {
|
|
756
|
+
printc(" {s}", .{@tagName(@as(Player, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
757
|
+
},
|
|
699
758
|
.Damage, .Heal => {
|
|
700
|
-
var id = ID.from(@intCast(
|
|
759
|
+
var id = ID.from(@intCast(a[i]));
|
|
701
760
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
702
761
|
switch (endian) {
|
|
703
762
|
.Big => {
|
|
@@ -715,91 +774,92 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
715
774
|
}
|
|
716
775
|
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
717
776
|
if (arg == .Damage) {
|
|
718
|
-
const reason = a[i];
|
|
719
|
-
printc(" {s}", .{@tagName(
|
|
720
|
-
if (reason ==
|
|
721
|
-
id = ID.from(@intCast(
|
|
777
|
+
const reason: Damage = @enumFromInt(a[i]);
|
|
778
|
+
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
779
|
+
if (reason == .RecoilOf) {
|
|
780
|
+
id = ID.from(@intCast(a[i]));
|
|
722
781
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
723
782
|
}
|
|
724
783
|
} else {
|
|
725
|
-
const reason = @
|
|
784
|
+
const reason: Heal = @enumFromInt(a[i]);
|
|
726
785
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
727
786
|
if (reason == .Drain) {
|
|
728
|
-
id = ID.from(@intCast(
|
|
787
|
+
id = ID.from(@intCast(a[i]));
|
|
729
788
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
730
789
|
}
|
|
731
790
|
}
|
|
732
791
|
},
|
|
733
792
|
.Status => {
|
|
734
|
-
const id = ID.from(@intCast(
|
|
793
|
+
const id = ID.from(@intCast(a[i]));
|
|
735
794
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
736
795
|
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
737
|
-
const reason = @
|
|
796
|
+
const reason: Status = @enumFromInt(a[i]);
|
|
738
797
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
739
798
|
if (reason == .From) printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
740
799
|
},
|
|
741
800
|
.CureStatus => {
|
|
742
|
-
const id = ID.from(@intCast(
|
|
801
|
+
const id = ID.from(@intCast(a[i]));
|
|
743
802
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
744
803
|
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
745
|
-
|
|
804
|
+
const reason: CureStatus = @enumFromInt(a[i]);
|
|
805
|
+
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
746
806
|
},
|
|
747
807
|
.Boost => {
|
|
748
|
-
const id = ID.from(@intCast(
|
|
808
|
+
const id = ID.from(@intCast(a[i]));
|
|
749
809
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
750
|
-
printc(" {s}", .{@tagName(@
|
|
810
|
+
printc(" {s}", .{@tagName(@as(Boost, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
751
811
|
printc(" {d}", .{a[i]}, a, b, &i, 1, color);
|
|
752
812
|
},
|
|
753
813
|
.Fail => {
|
|
754
|
-
const id = ID.from(@intCast(
|
|
814
|
+
const id = ID.from(@intCast(a[i]));
|
|
755
815
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
756
|
-
printc(" {s}", .{@tagName(@
|
|
816
|
+
printc(" {s}", .{@tagName(@as(Fail, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
757
817
|
},
|
|
758
818
|
.HitCount => {
|
|
759
|
-
const id = ID.from(@intCast(
|
|
819
|
+
const id = ID.from(@intCast(a[i]));
|
|
760
820
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
761
821
|
printc(" {d}", .{a[i]}, a, b, &i, 1, color);
|
|
762
822
|
},
|
|
763
823
|
.Prepare => {
|
|
764
|
-
const id = ID.from(@intCast(
|
|
824
|
+
const id = ID.from(@intCast(a[i]));
|
|
765
825
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
766
826
|
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
767
827
|
},
|
|
768
828
|
.Activate => {
|
|
769
|
-
const id = ID.from(@intCast(
|
|
829
|
+
const id = ID.from(@intCast(a[i]));
|
|
770
830
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
771
|
-
printc(" {s}", .{@tagName(@
|
|
831
|
+
printc(" {s}", .{@tagName(@as(Activate, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
772
832
|
},
|
|
773
833
|
.Start => {
|
|
774
|
-
const id = ID.from(@intCast(
|
|
834
|
+
const id = ID.from(@intCast(a[i]));
|
|
775
835
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
776
836
|
const reason = a[i];
|
|
777
|
-
printc(" {s}", .{@tagName(@
|
|
778
|
-
if (@
|
|
779
|
-
const types = @
|
|
837
|
+
printc(" {s}", .{@tagName(@as(Start, @enumFromInt(reason)))}, a, b, &i, 1, color);
|
|
838
|
+
if (@as(Start, @enumFromInt(reason)) == .TypeChange) {
|
|
839
|
+
const types = @as(gen1.Types, @bitCast(a[i]));
|
|
780
840
|
const args = .{
|
|
781
|
-
formatter(.Type, @
|
|
782
|
-
formatter(.Type, @
|
|
841
|
+
formatter(.Type, @intFromEnum(types.type1)),
|
|
842
|
+
formatter(.Type, @intFromEnum(types.type2)),
|
|
783
843
|
};
|
|
784
844
|
printc(" {s}/{s}", args, a, b, &i, 1, color);
|
|
785
|
-
} else if (reason >= @
|
|
845
|
+
} else if (reason >= @intFromEnum(Start.Disable)) {
|
|
786
846
|
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
787
847
|
}
|
|
788
848
|
},
|
|
789
849
|
.End => {
|
|
790
|
-
const id = ID.from(@intCast(
|
|
850
|
+
const id = ID.from(@intCast(a[i]));
|
|
791
851
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
792
|
-
printc(" {s}", .{@tagName(@
|
|
852
|
+
printc(" {s}", .{@tagName(@as(End, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
793
853
|
},
|
|
794
854
|
.Immune => {
|
|
795
|
-
const id = ID.from(@intCast(
|
|
855
|
+
const id = ID.from(@intCast(a[i]));
|
|
796
856
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
797
|
-
printc(" {s}", .{@tagName(@
|
|
857
|
+
printc(" {s}", .{@tagName(@as(Immune, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
798
858
|
},
|
|
799
859
|
.Transform => {
|
|
800
|
-
const source = ID.from(@intCast(
|
|
860
|
+
const source = ID.from(@intCast(a[i]));
|
|
801
861
|
printc(" {s}({d})", .{ @tagName(source.player), source.id }, a, b, &i, 1, color);
|
|
802
|
-
const target = ID.from(@intCast(
|
|
862
|
+
const target = ID.from(@intCast(a[i]));
|
|
803
863
|
printc(" {s}({d})", .{ @tagName(target.player), target.id }, a, b, &i, 1, color);
|
|
804
864
|
},
|
|
805
865
|
else => unreachable,
|
|
@@ -838,7 +898,8 @@ pub fn expectLog(
|
|
|
838
898
|
actual: []const u8,
|
|
839
899
|
offset: usize,
|
|
840
900
|
) !void {
|
|
841
|
-
if (!
|
|
901
|
+
if (!enabled) return;
|
|
902
|
+
|
|
842
903
|
const color = color: {
|
|
843
904
|
if (std.process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) {
|
|
844
905
|
break :color true;
|
|
@@ -881,7 +942,7 @@ fn expectEqualBytes(expected: []const u8, actual: []const u8, offset: usize) !vo
|
|
|
881
942
|
const endian = builtin.target.cpu.arch.endian();
|
|
882
943
|
|
|
883
944
|
fn N(e: anytype) u8 {
|
|
884
|
-
return @
|
|
945
|
+
return @intFromEnum(e);
|
|
885
946
|
}
|
|
886
947
|
|
|
887
948
|
const p1 = Player.P1;
|
|
@@ -905,9 +966,9 @@ fn expectLog1(expected: []const u8, actual: []const u8) !void {
|
|
|
905
966
|
|
|
906
967
|
fn gen1Formatter(kind: Kind, byte: u8) []const u8 {
|
|
907
968
|
return switch (kind) {
|
|
908
|
-
.Move => @tagName(@
|
|
909
|
-
.Species => @tagName(@
|
|
910
|
-
.Type => @tagName(@
|
|
969
|
+
.Move => @tagName(@as(M, @enumFromInt(byte))),
|
|
970
|
+
.Species => @tagName(@as(S, @enumFromInt(byte))),
|
|
971
|
+
.Type => @tagName(@as(gen1.Type, @enumFromInt(byte))),
|
|
911
972
|
.Status => gen1.Status.name(byte),
|
|
912
973
|
};
|
|
913
974
|
}
|