@pkmn/engine 0.1.0-dev.9a0c07c3 → 0.1.0-dev.a02611a4
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 +71 -60
- 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 +95 -76
- package/package.json +29 -16
- 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/battle.zig +17 -0
- package/src/lib/common/data.zig +11 -11
- package/src/lib/common/debug.zig +21 -11
- package/src/lib/common/js.zig +118 -0
- package/src/lib/common/optional.zig +60 -0
- package/src/lib/common/options.zig +12 -3
- package/src/lib/common/protocol.zig +308 -182
- package/src/lib/common/rational.zig +353 -0
- package/src/lib/common/rng.zig +10 -10
- package/src/lib/common/util.zig +12 -0
- package/src/lib/gen1/README.md +262 -154
- package/src/lib/gen1/calc.zig +426 -0
- package/src/lib/gen1/chance.zig +1044 -0
- 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 +69 -43
- package/src/lib/gen1/helpers.zig +592 -32
- package/src/lib/gen1/mechanics.zig +983 -626
- package/src/lib/gen2/README.md +12 -13
- package/src/lib/gen2/data/items.zig +3 -3
- package/src/lib/gen2/data/moves.zig +16 -3
- package/src/lib/gen2/data/species.zig +1 -1
- package/src/lib/gen2/data/types.zig +3 -3
- package/src/lib/gen2/data.zig +59 -41
- package/src/lib/gen2/helpers.zig +15 -16
- package/src/lib/gen2/mechanics.zig +354 -11
- 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;
|
|
@@ -102,6 +102,9 @@ pub const ArgType = enum(u8) {
|
|
|
102
102
|
// Gen 8
|
|
103
103
|
CanDynamax,
|
|
104
104
|
SwapSideConditions,
|
|
105
|
+
|
|
106
|
+
// Gen 9
|
|
107
|
+
Terastallize,
|
|
105
108
|
};
|
|
106
109
|
|
|
107
110
|
pub const Move = enum(u8) {
|
|
@@ -133,6 +136,8 @@ pub const Damage = enum(u8) {
|
|
|
133
136
|
Confusion,
|
|
134
137
|
LeechSeed,
|
|
135
138
|
RecoilOf,
|
|
139
|
+
|
|
140
|
+
Spikes,
|
|
136
141
|
};
|
|
137
142
|
|
|
138
143
|
pub const Status = enum(u8) {
|
|
@@ -219,8 +224,12 @@ pub const Immune = enum(u8) {
|
|
|
219
224
|
OHKO,
|
|
220
225
|
};
|
|
221
226
|
|
|
227
|
+
/// Null object pattern implementation of `Log` backed by a `std.io.null_writer`.
|
|
228
|
+
/// Ignores anything sent to it, though protocol logging should additionally be turned off
|
|
229
|
+
/// entirely with `options.log`.
|
|
222
230
|
pub const NULL = Log(@TypeOf(std.io.null_writer)){ .writer = std.io.null_writer };
|
|
223
231
|
|
|
232
|
+
/// Logs protocol information to its `Writer` during a battle update when `options.log` is enabled.
|
|
224
233
|
pub fn Log(comptime Writer: type) type {
|
|
225
234
|
return struct {
|
|
226
235
|
const Self = @This();
|
|
@@ -230,91 +239,108 @@ pub fn Log(comptime Writer: type) type {
|
|
|
230
239
|
pub const Error = Writer.Error;
|
|
231
240
|
|
|
232
241
|
pub fn move(self: Self, source: ID, m: anytype, target: ID, from: anytype) Error!void {
|
|
233
|
-
if (!
|
|
242
|
+
if (!enabled) return;
|
|
243
|
+
|
|
234
244
|
assert(m != .None);
|
|
235
245
|
try self.writer.writeAll(&.{
|
|
236
|
-
@
|
|
237
|
-
@
|
|
238
|
-
@
|
|
239
|
-
@
|
|
246
|
+
@intFromEnum(ArgType.Move),
|
|
247
|
+
@as(u8, @bitCast(source)),
|
|
248
|
+
@intFromEnum(m),
|
|
249
|
+
@as(u8, @bitCast(target)),
|
|
240
250
|
});
|
|
241
|
-
const none = &[_]u8{@
|
|
251
|
+
const none = &[_]u8{@intFromEnum(Move.None)};
|
|
242
252
|
try self.writer.writeAll(switch (@typeInfo(@TypeOf(from))) {
|
|
243
253
|
.Null => none,
|
|
244
254
|
.Optional => if (from) |f| blk: {
|
|
245
|
-
assert(@
|
|
246
|
-
break :blk &[_]u8{ @
|
|
255
|
+
assert(@intFromEnum(f) != 0);
|
|
256
|
+
break :blk &[_]u8{ @intFromEnum(Move.From), @intFromEnum(f) };
|
|
247
257
|
} else none,
|
|
248
258
|
else => blk: {
|
|
249
|
-
assert(@
|
|
250
|
-
break :blk &[_]u8{ @
|
|
259
|
+
assert(@intFromEnum(from) != 0);
|
|
260
|
+
break :blk &[_]u8{ @intFromEnum(Move.From), @intFromEnum(from) };
|
|
251
261
|
},
|
|
252
262
|
});
|
|
253
263
|
}
|
|
254
264
|
|
|
255
265
|
pub fn switched(self: Self, ident: ID, pokemon: anytype) Error!void {
|
|
256
|
-
if (!
|
|
257
|
-
|
|
258
|
-
try self.writer.writeAll(&.{ @
|
|
266
|
+
if (!enabled) return;
|
|
267
|
+
|
|
268
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Switch), @as(u8, @bitCast(ident)) });
|
|
269
|
+
if (@hasField(@TypeOf(pokemon.*), "dvs")) {
|
|
270
|
+
try self.writer.writeAll(&.{
|
|
271
|
+
@intFromEnum(pokemon.species),
|
|
272
|
+
@intFromEnum(pokemon.dvs.gender),
|
|
273
|
+
pokemon.level,
|
|
274
|
+
});
|
|
275
|
+
} else {
|
|
276
|
+
try self.writer.writeAll(&.{ @intFromEnum(pokemon.species), pokemon.level });
|
|
277
|
+
}
|
|
259
278
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
260
279
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
261
280
|
try self.writer.writeAll(&.{pokemon.status});
|
|
262
281
|
}
|
|
263
282
|
|
|
264
283
|
pub fn cant(self: Self, ident: ID, reason: Cant) Error!void {
|
|
265
|
-
if (!
|
|
284
|
+
if (!enabled) return;
|
|
285
|
+
|
|
266
286
|
assert(reason != .Disable);
|
|
267
287
|
try self.writer.writeAll(&.{
|
|
268
|
-
@
|
|
269
|
-
@
|
|
270
|
-
@
|
|
288
|
+
@intFromEnum(ArgType.Cant),
|
|
289
|
+
@as(u8, @bitCast(ident)),
|
|
290
|
+
@intFromEnum(reason),
|
|
271
291
|
});
|
|
272
292
|
}
|
|
273
293
|
|
|
274
294
|
pub fn disabled(self: Self, ident: ID, m: anytype) Error!void {
|
|
275
|
-
if (!
|
|
295
|
+
if (!enabled) return;
|
|
296
|
+
|
|
276
297
|
try self.writer.writeAll(&.{
|
|
277
|
-
@
|
|
278
|
-
@
|
|
279
|
-
@
|
|
280
|
-
@
|
|
298
|
+
@intFromEnum(ArgType.Cant),
|
|
299
|
+
@as(u8, @bitCast(ident)),
|
|
300
|
+
@intFromEnum(Cant.Disable),
|
|
301
|
+
@intFromEnum(m),
|
|
281
302
|
});
|
|
282
303
|
}
|
|
283
304
|
|
|
284
305
|
pub fn faint(self: Self, ident: ID, done: bool) Error!void {
|
|
285
|
-
if (!
|
|
286
|
-
|
|
287
|
-
|
|
306
|
+
if (!enabled) return;
|
|
307
|
+
|
|
308
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Faint), @as(u8, @bitCast(ident)) });
|
|
309
|
+
if (done) try self.writer.writeByte(@intFromEnum(ArgType.None));
|
|
288
310
|
}
|
|
289
311
|
|
|
290
312
|
pub fn turn(self: Self, num: u16) Error!void {
|
|
291
|
-
if (!
|
|
292
|
-
|
|
313
|
+
if (!enabled) return;
|
|
314
|
+
|
|
315
|
+
try self.writer.writeByte(@intFromEnum(ArgType.Turn));
|
|
293
316
|
try self.writer.writeIntNative(u16, num);
|
|
294
|
-
try self.writer.writeByte(@
|
|
317
|
+
try self.writer.writeByte(@intFromEnum(ArgType.None));
|
|
295
318
|
}
|
|
296
319
|
|
|
297
320
|
pub fn win(self: Self, player: Player) Error!void {
|
|
298
|
-
if (!
|
|
321
|
+
if (!enabled) return;
|
|
322
|
+
|
|
299
323
|
try self.writer.writeAll(&.{
|
|
300
|
-
@
|
|
301
|
-
@
|
|
302
|
-
@
|
|
324
|
+
@intFromEnum(ArgType.Win),
|
|
325
|
+
@intFromEnum(player),
|
|
326
|
+
@intFromEnum(ArgType.None),
|
|
303
327
|
});
|
|
304
328
|
}
|
|
305
329
|
|
|
306
330
|
pub fn tie(self: Self) Error!void {
|
|
307
|
-
if (!
|
|
308
|
-
|
|
331
|
+
if (!enabled) return;
|
|
332
|
+
|
|
333
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Tie), @intFromEnum(ArgType.None) });
|
|
309
334
|
}
|
|
310
335
|
|
|
311
336
|
pub fn damage(self: Self, ident: ID, pokemon: anytype, reason: Damage) Error!void {
|
|
312
|
-
if (!
|
|
313
|
-
|
|
314
|
-
|
|
337
|
+
if (!enabled) return;
|
|
338
|
+
|
|
339
|
+
assert(@intFromEnum(reason) <= @intFromEnum(Damage.LeechSeed));
|
|
340
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @as(u8, @bitCast(ident)) });
|
|
315
341
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
316
342
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
317
|
-
try self.writer.writeAll(&.{ pokemon.status, @
|
|
343
|
+
try self.writer.writeAll(&.{ pokemon.status, @intFromEnum(reason) });
|
|
318
344
|
}
|
|
319
345
|
|
|
320
346
|
pub fn damageOf(
|
|
@@ -324,227 +350,271 @@ pub fn Log(comptime Writer: type) type {
|
|
|
324
350
|
reason: Damage,
|
|
325
351
|
source: ID,
|
|
326
352
|
) Error!void {
|
|
327
|
-
if (!
|
|
328
|
-
|
|
329
|
-
|
|
353
|
+
if (!enabled) return;
|
|
354
|
+
|
|
355
|
+
assert(@intFromEnum(reason) == @intFromEnum(Damage.RecoilOf));
|
|
356
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @as(u8, @bitCast(ident)) });
|
|
330
357
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
331
358
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
332
359
|
try self.writer.writeAll(&.{
|
|
333
360
|
pokemon.status,
|
|
334
|
-
@
|
|
335
|
-
@
|
|
361
|
+
@intFromEnum(reason),
|
|
362
|
+
@as(u8, @bitCast(source)),
|
|
336
363
|
});
|
|
337
364
|
}
|
|
338
365
|
|
|
339
366
|
pub fn heal(self: Self, ident: ID, pokemon: anytype, reason: Heal) Error!void {
|
|
340
|
-
if (!
|
|
367
|
+
if (!enabled) return;
|
|
368
|
+
|
|
341
369
|
assert(reason != .Drain);
|
|
342
|
-
try self.writer.writeAll(&.{ @
|
|
370
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(ident)) });
|
|
343
371
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
344
372
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
345
|
-
try self.writer.writeAll(&.{ pokemon.status, @
|
|
373
|
+
try self.writer.writeAll(&.{ pokemon.status, @intFromEnum(reason) });
|
|
346
374
|
}
|
|
347
375
|
|
|
348
376
|
pub fn drain(self: Self, source: ID, pokemon: anytype, target: ID) Error!void {
|
|
349
|
-
if (!
|
|
350
|
-
|
|
377
|
+
if (!enabled) return;
|
|
378
|
+
|
|
379
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(source)) });
|
|
351
380
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
352
381
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
353
382
|
try self.writer.writeAll(&.{
|
|
354
383
|
pokemon.status,
|
|
355
|
-
@
|
|
356
|
-
@
|
|
384
|
+
@intFromEnum(Heal.Drain),
|
|
385
|
+
@as(u8, @bitCast(target)),
|
|
357
386
|
});
|
|
358
387
|
}
|
|
359
388
|
|
|
360
389
|
pub fn status(self: Self, ident: ID, value: u8, reason: Status) Error!void {
|
|
361
|
-
if (!
|
|
390
|
+
if (!enabled) return;
|
|
391
|
+
|
|
362
392
|
assert(reason != .From);
|
|
363
393
|
try self.writer.writeAll(&.{
|
|
364
|
-
@
|
|
365
|
-
@
|
|
394
|
+
@intFromEnum(ArgType.Status),
|
|
395
|
+
@as(u8, @bitCast(ident)),
|
|
366
396
|
value,
|
|
367
|
-
@
|
|
397
|
+
@intFromEnum(reason),
|
|
368
398
|
});
|
|
369
399
|
}
|
|
370
400
|
|
|
371
401
|
pub fn statusFrom(self: Self, ident: ID, value: u8, m: anytype) Error!void {
|
|
372
|
-
if (!
|
|
402
|
+
if (!enabled) return;
|
|
403
|
+
|
|
373
404
|
try self.writer.writeAll(&.{
|
|
374
|
-
@
|
|
375
|
-
@
|
|
405
|
+
@intFromEnum(ArgType.Status),
|
|
406
|
+
@as(u8, @bitCast(ident)),
|
|
376
407
|
value,
|
|
377
|
-
@
|
|
378
|
-
@
|
|
408
|
+
@intFromEnum(Status.From),
|
|
409
|
+
@intFromEnum(m),
|
|
379
410
|
});
|
|
380
411
|
}
|
|
381
412
|
|
|
382
413
|
pub fn curestatus(self: Self, ident: ID, value: u8, reason: CureStatus) Error!void {
|
|
383
|
-
if (!
|
|
414
|
+
if (!enabled) return;
|
|
415
|
+
|
|
384
416
|
try self.writer.writeAll(&.{
|
|
385
|
-
@
|
|
386
|
-
@
|
|
417
|
+
@intFromEnum(ArgType.CureStatus),
|
|
418
|
+
@as(u8, @bitCast(ident)),
|
|
387
419
|
value,
|
|
388
|
-
@
|
|
420
|
+
@intFromEnum(reason),
|
|
389
421
|
});
|
|
390
422
|
}
|
|
391
423
|
|
|
392
424
|
pub fn boost(self: Self, ident: ID, reason: Boost, num: i8) Error!void {
|
|
393
|
-
if (!
|
|
425
|
+
if (!enabled) return;
|
|
426
|
+
|
|
394
427
|
assert(num != 0 and (reason != .Rage or num > 0));
|
|
395
428
|
try self.writer.writeAll(&.{
|
|
396
|
-
@
|
|
397
|
-
@
|
|
398
|
-
@
|
|
399
|
-
@
|
|
429
|
+
@intFromEnum(ArgType.Boost),
|
|
430
|
+
@as(u8, @bitCast(ident)),
|
|
431
|
+
@intFromEnum(reason),
|
|
432
|
+
@as(u8, @intCast(num + 6)),
|
|
400
433
|
});
|
|
401
434
|
}
|
|
402
435
|
|
|
403
436
|
pub fn clearallboost(self: Self) Error!void {
|
|
404
|
-
if (!
|
|
405
|
-
|
|
437
|
+
if (!enabled) return;
|
|
438
|
+
|
|
439
|
+
try self.writer.writeAll(&.{@intFromEnum(ArgType.ClearAllBoost)});
|
|
406
440
|
}
|
|
407
441
|
|
|
408
442
|
pub fn fail(self: Self, ident: ID, reason: Fail) Error!void {
|
|
409
|
-
if (!
|
|
443
|
+
if (!enabled) return;
|
|
444
|
+
|
|
410
445
|
try self.writer.writeAll(&.{
|
|
411
|
-
@
|
|
412
|
-
@
|
|
413
|
-
@
|
|
446
|
+
@intFromEnum(ArgType.Fail),
|
|
447
|
+
@as(u8, @bitCast(ident)),
|
|
448
|
+
@intFromEnum(reason),
|
|
414
449
|
});
|
|
415
450
|
}
|
|
416
451
|
|
|
417
452
|
pub fn miss(self: Self, source: ID) Error!void {
|
|
418
|
-
if (!
|
|
419
|
-
|
|
453
|
+
if (!enabled) return;
|
|
454
|
+
|
|
455
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Miss), @as(u8, @bitCast(source)) });
|
|
420
456
|
}
|
|
421
457
|
|
|
422
458
|
pub fn hitcount(self: Self, ident: ID, num: u8) Error!void {
|
|
423
|
-
if (!
|
|
424
|
-
|
|
459
|
+
if (!enabled) return;
|
|
460
|
+
|
|
461
|
+
try self.writer.writeAll(&.{
|
|
462
|
+
@intFromEnum(ArgType.HitCount),
|
|
463
|
+
@as(u8, @bitCast(ident)),
|
|
464
|
+
num,
|
|
465
|
+
});
|
|
425
466
|
}
|
|
426
467
|
|
|
427
468
|
pub fn prepare(self: Self, source: ID, m: anytype) Error!void {
|
|
428
|
-
if (!
|
|
469
|
+
if (!enabled) return;
|
|
470
|
+
|
|
429
471
|
try self.writer.writeAll(&.{
|
|
430
|
-
@
|
|
431
|
-
@
|
|
432
|
-
@
|
|
472
|
+
@intFromEnum(ArgType.Prepare),
|
|
473
|
+
@as(u8, @bitCast(source)),
|
|
474
|
+
@intFromEnum(m),
|
|
433
475
|
});
|
|
434
476
|
}
|
|
435
477
|
|
|
436
478
|
pub fn mustrecharge(self: Self, ident: ID) Error!void {
|
|
437
|
-
if (!
|
|
438
|
-
|
|
479
|
+
if (!enabled) return;
|
|
480
|
+
|
|
481
|
+
try self.writer.writeAll(&.{
|
|
482
|
+
@intFromEnum(ArgType.MustRecharge),
|
|
483
|
+
@as(u8, @bitCast(ident)),
|
|
484
|
+
});
|
|
439
485
|
}
|
|
440
486
|
|
|
441
487
|
pub fn activate(self: Self, ident: ID, reason: Activate) Error!void {
|
|
442
|
-
if (!
|
|
488
|
+
if (!enabled) return;
|
|
489
|
+
|
|
443
490
|
try self.writer.writeAll(&.{
|
|
444
|
-
@
|
|
445
|
-
@
|
|
446
|
-
@
|
|
491
|
+
@intFromEnum(ArgType.Activate),
|
|
492
|
+
@as(u8, @bitCast(ident)),
|
|
493
|
+
@intFromEnum(reason),
|
|
447
494
|
});
|
|
448
495
|
}
|
|
449
496
|
|
|
450
497
|
pub fn fieldactivate(self: Self) Error!void {
|
|
451
|
-
if (!
|
|
452
|
-
|
|
498
|
+
if (!enabled) return;
|
|
499
|
+
|
|
500
|
+
try self.writer.writeAll(&.{@intFromEnum(ArgType.FieldActivate)});
|
|
453
501
|
}
|
|
454
502
|
|
|
455
503
|
pub fn start(self: Self, ident: ID, reason: Start) Error!void {
|
|
456
|
-
if (!
|
|
457
|
-
|
|
504
|
+
if (!enabled) return;
|
|
505
|
+
|
|
506
|
+
assert(@intFromEnum(reason) < @intFromEnum(Start.TypeChange));
|
|
458
507
|
try self.writer.writeAll(&.{
|
|
459
|
-
@
|
|
460
|
-
@
|
|
461
|
-
@
|
|
508
|
+
@intFromEnum(ArgType.Start),
|
|
509
|
+
@as(u8, @bitCast(ident)),
|
|
510
|
+
@intFromEnum(reason),
|
|
462
511
|
});
|
|
463
512
|
}
|
|
464
513
|
|
|
465
514
|
pub fn typechange(self: Self, source: ID, types: anytype, target: ID) Error!void {
|
|
466
|
-
if (!
|
|
515
|
+
if (!enabled) return;
|
|
516
|
+
|
|
467
517
|
try self.writer.writeAll(&.{
|
|
468
|
-
@
|
|
469
|
-
@
|
|
470
|
-
@
|
|
471
|
-
@
|
|
472
|
-
@
|
|
518
|
+
@intFromEnum(ArgType.Start),
|
|
519
|
+
@as(u8, @bitCast(source)),
|
|
520
|
+
@intFromEnum(Start.TypeChange),
|
|
521
|
+
@as(u8, @bitCast(types)),
|
|
522
|
+
@as(u8, @bitCast(target)),
|
|
473
523
|
});
|
|
474
524
|
}
|
|
475
525
|
|
|
476
526
|
pub fn startEffect(self: Self, ident: ID, reason: Start, m: anytype) Error!void {
|
|
477
|
-
if (!
|
|
478
|
-
|
|
527
|
+
if (!enabled) return;
|
|
528
|
+
|
|
529
|
+
assert(@intFromEnum(reason) > @intFromEnum(Start.TypeChange));
|
|
479
530
|
try self.writer.writeAll(&.{
|
|
480
|
-
@
|
|
481
|
-
@
|
|
482
|
-
@
|
|
483
|
-
@
|
|
531
|
+
@intFromEnum(ArgType.Start),
|
|
532
|
+
@as(u8, @bitCast(ident)),
|
|
533
|
+
@intFromEnum(reason),
|
|
534
|
+
@intFromEnum(m),
|
|
484
535
|
});
|
|
485
536
|
}
|
|
486
537
|
|
|
487
538
|
pub fn end(self: Self, ident: ID, reason: End) Error!void {
|
|
488
|
-
if (!
|
|
539
|
+
if (!enabled) return;
|
|
540
|
+
|
|
489
541
|
try self.writer.writeAll(&.{
|
|
490
|
-
@
|
|
491
|
-
@
|
|
492
|
-
@
|
|
542
|
+
@intFromEnum(ArgType.End),
|
|
543
|
+
@as(u8, @bitCast(ident)),
|
|
544
|
+
@intFromEnum(reason),
|
|
493
545
|
});
|
|
494
546
|
}
|
|
495
547
|
|
|
496
548
|
pub fn ohko(self: Self) Error!void {
|
|
497
|
-
if (!
|
|
498
|
-
|
|
549
|
+
if (!enabled) return;
|
|
550
|
+
|
|
551
|
+
try self.writer.writeAll(&.{@intFromEnum(ArgType.OHKO)});
|
|
499
552
|
}
|
|
500
553
|
|
|
501
554
|
pub fn crit(self: Self, ident: ID) Error!void {
|
|
502
|
-
if (!
|
|
503
|
-
|
|
555
|
+
if (!enabled) return;
|
|
556
|
+
|
|
557
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Crit), @as(u8, @bitCast(ident)) });
|
|
504
558
|
}
|
|
505
559
|
|
|
506
560
|
pub fn supereffective(self: Self, ident: ID) Error!void {
|
|
507
|
-
if (!
|
|
508
|
-
|
|
561
|
+
if (!enabled) return;
|
|
562
|
+
|
|
563
|
+
try self.writer.writeAll(&.{
|
|
564
|
+
@intFromEnum(ArgType.SuperEffective),
|
|
565
|
+
@as(u8, @bitCast(ident)),
|
|
566
|
+
});
|
|
509
567
|
}
|
|
510
568
|
|
|
511
569
|
pub fn resisted(self: Self, ident: ID) Error!void {
|
|
512
|
-
if (!
|
|
513
|
-
|
|
570
|
+
if (!enabled) return;
|
|
571
|
+
|
|
572
|
+
try self.writer.writeAll(&.{
|
|
573
|
+
@intFromEnum(ArgType.Resisted),
|
|
574
|
+
@as(u8, @bitCast(ident)),
|
|
575
|
+
});
|
|
514
576
|
}
|
|
515
577
|
|
|
516
578
|
pub fn immune(self: Self, ident: ID, reason: Immune) Error!void {
|
|
517
|
-
if (!
|
|
579
|
+
if (!enabled) return;
|
|
580
|
+
|
|
518
581
|
try self.writer.writeAll(&.{
|
|
519
|
-
@
|
|
520
|
-
@
|
|
521
|
-
@
|
|
582
|
+
@intFromEnum(ArgType.Immune),
|
|
583
|
+
@as(u8, @bitCast(ident)),
|
|
584
|
+
@intFromEnum(reason),
|
|
522
585
|
});
|
|
523
586
|
}
|
|
524
587
|
|
|
525
588
|
pub fn transform(self: Self, source: ID, target: ID) Error!void {
|
|
526
|
-
if (!
|
|
589
|
+
if (!enabled) return;
|
|
590
|
+
|
|
527
591
|
try self.writer.writeAll(&.{
|
|
528
|
-
@
|
|
529
|
-
@
|
|
530
|
-
@
|
|
592
|
+
@intFromEnum(ArgType.Transform),
|
|
593
|
+
@as(u8, @bitCast(source)),
|
|
594
|
+
@as(u8, @bitCast(target)),
|
|
531
595
|
});
|
|
532
596
|
}
|
|
533
597
|
|
|
534
598
|
pub fn laststill(self: Self) Error!void {
|
|
535
|
-
if (!
|
|
536
|
-
|
|
599
|
+
if (!enabled) return;
|
|
600
|
+
|
|
601
|
+
try self.writer.writeAll(&.{@intFromEnum(ArgType.LastStill)});
|
|
537
602
|
}
|
|
538
603
|
|
|
539
604
|
pub fn lastmiss(self: Self) Error!void {
|
|
540
|
-
if (!
|
|
541
|
-
|
|
605
|
+
if (!enabled) return;
|
|
606
|
+
|
|
607
|
+
try self.writer.writeAll(&.{@intFromEnum(ArgType.LastMiss)});
|
|
542
608
|
}
|
|
543
609
|
};
|
|
544
610
|
}
|
|
545
611
|
|
|
612
|
+
/// `Log` type backed by the optimized `ByteStream.Writer`.
|
|
546
613
|
pub const FixedLog = Log(ByteStream.Writer);
|
|
547
614
|
|
|
615
|
+
/// Stripped down version of `std.io.FixedBufferStream` optimized for efficiently writing the
|
|
616
|
+
/// individual protocol bytes. Note that the `ByteStream.Writer` is **not** a `std.io.Writer` and
|
|
617
|
+
/// should not be used for general purpose writing.
|
|
548
618
|
pub const ByteStream = struct {
|
|
549
619
|
buffer: []u8,
|
|
550
620
|
pos: usize = 0,
|
|
@@ -588,12 +658,18 @@ pub const ByteStream = struct {
|
|
|
588
658
|
pub const Kind = enum { Move, Species, Type, Status };
|
|
589
659
|
pub const Formatter = fn (Kind, u8) []const u8;
|
|
590
660
|
|
|
591
|
-
pub fn format(
|
|
661
|
+
pub fn format(
|
|
662
|
+
comptime gen: comptime_int,
|
|
663
|
+
comptime formatter: Formatter,
|
|
664
|
+
a: []const u8,
|
|
665
|
+
b: ?[]const u8,
|
|
666
|
+
color: bool,
|
|
667
|
+
) void {
|
|
592
668
|
print("\n", .{});
|
|
593
669
|
|
|
594
670
|
var i: usize = 0;
|
|
595
671
|
while (i < a.len) {
|
|
596
|
-
const arg = @
|
|
672
|
+
const arg: ArgType = @enumFromInt(a[i]);
|
|
597
673
|
const name = switch (arg) {
|
|
598
674
|
.None => if (color) "\x1b[2m-\x1b[0m" else "-",
|
|
599
675
|
.LastStill => "|[still]",
|
|
@@ -639,19 +715,27 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
639
715
|
.OHKO,
|
|
640
716
|
=> {},
|
|
641
717
|
.Move => {
|
|
642
|
-
const source = ID.from(@intCast(
|
|
718
|
+
const source = ID.from(@intCast(a[i]));
|
|
643
719
|
printc(" {s}({d})", .{ @tagName(source.player), source.id }, a, b, &i, 1, color);
|
|
644
720
|
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
645
|
-
const target = ID.from(@intCast(
|
|
721
|
+
const target = ID.from(@intCast(a[i]));
|
|
646
722
|
printc(" {s}({d})", .{ @tagName(target.player), target.id }, a, b, &i, 1, color);
|
|
647
|
-
const reason = @
|
|
723
|
+
const reason: Move = @enumFromInt(a[i]);
|
|
648
724
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
649
725
|
if (reason == .From) printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
650
726
|
},
|
|
651
727
|
.Switch => {
|
|
652
|
-
const id = ID.from(@intCast(
|
|
728
|
+
const id = ID.from(@intCast(a[i]));
|
|
653
729
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
654
730
|
printc(" {s}", .{formatter(.Species, a[i])}, a, b, &i, 1, color);
|
|
731
|
+
if (gen > 1) {
|
|
732
|
+
if (a[i] == N(gen2.Gender.Unknown)) {
|
|
733
|
+
i += 1;
|
|
734
|
+
} else {
|
|
735
|
+
var gender = if (a[i] == N(gen2.Gender.Male)) "M" else "F";
|
|
736
|
+
printc(", {s}", .{gender}, a, b, &i, 1, color);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
655
739
|
printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
|
|
656
740
|
switch (endian) {
|
|
657
741
|
.Big => {
|
|
@@ -670,9 +754,9 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
670
754
|
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
671
755
|
},
|
|
672
756
|
.Cant => {
|
|
673
|
-
const id = ID.from(@intCast(
|
|
757
|
+
const id = ID.from(@intCast(a[i]));
|
|
674
758
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
675
|
-
const reason = @
|
|
759
|
+
const reason: Cant = @enumFromInt(a[i]);
|
|
676
760
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
677
761
|
if (reason == .Disable) {
|
|
678
762
|
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
@@ -685,7 +769,7 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
685
769
|
.SuperEffective,
|
|
686
770
|
.Resisted,
|
|
687
771
|
=> {
|
|
688
|
-
const id = ID.from(@intCast(
|
|
772
|
+
const id = ID.from(@intCast(a[i]));
|
|
689
773
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
690
774
|
},
|
|
691
775
|
.Turn => {
|
|
@@ -695,9 +779,11 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
695
779
|
};
|
|
696
780
|
printc(" {d}", .{turn}, a, b, &i, 2, color);
|
|
697
781
|
},
|
|
698
|
-
.Win =>
|
|
782
|
+
.Win => {
|
|
783
|
+
printc(" {s}", .{@tagName(@as(Player, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
784
|
+
},
|
|
699
785
|
.Damage, .Heal => {
|
|
700
|
-
var id = ID.from(@intCast(
|
|
786
|
+
var id = ID.from(@intCast(a[i]));
|
|
701
787
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
702
788
|
switch (endian) {
|
|
703
789
|
.Big => {
|
|
@@ -715,91 +801,92 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
715
801
|
}
|
|
716
802
|
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
717
803
|
if (arg == .Damage) {
|
|
718
|
-
const reason = a[i];
|
|
719
|
-
printc(" {s}", .{@tagName(
|
|
720
|
-
if (reason ==
|
|
721
|
-
id = ID.from(@intCast(
|
|
804
|
+
const reason: Damage = @enumFromInt(a[i]);
|
|
805
|
+
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
806
|
+
if (reason == .RecoilOf) {
|
|
807
|
+
id = ID.from(@intCast(a[i]));
|
|
722
808
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
723
809
|
}
|
|
724
810
|
} else {
|
|
725
|
-
const reason = @
|
|
811
|
+
const reason: Heal = @enumFromInt(a[i]);
|
|
726
812
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
727
813
|
if (reason == .Drain) {
|
|
728
|
-
id = ID.from(@intCast(
|
|
814
|
+
id = ID.from(@intCast(a[i]));
|
|
729
815
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
730
816
|
}
|
|
731
817
|
}
|
|
732
818
|
},
|
|
733
819
|
.Status => {
|
|
734
|
-
const id = ID.from(@intCast(
|
|
820
|
+
const id = ID.from(@intCast(a[i]));
|
|
735
821
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
736
822
|
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
737
|
-
const reason = @
|
|
823
|
+
const reason: Status = @enumFromInt(a[i]);
|
|
738
824
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
739
825
|
if (reason == .From) printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
740
826
|
},
|
|
741
827
|
.CureStatus => {
|
|
742
|
-
const id = ID.from(@intCast(
|
|
828
|
+
const id = ID.from(@intCast(a[i]));
|
|
743
829
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
744
830
|
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
745
|
-
|
|
831
|
+
const reason: CureStatus = @enumFromInt(a[i]);
|
|
832
|
+
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
746
833
|
},
|
|
747
834
|
.Boost => {
|
|
748
|
-
const id = ID.from(@intCast(
|
|
835
|
+
const id = ID.from(@intCast(a[i]));
|
|
749
836
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
750
|
-
printc(" {s}", .{@tagName(@
|
|
837
|
+
printc(" {s}", .{@tagName(@as(Boost, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
751
838
|
printc(" {d}", .{a[i]}, a, b, &i, 1, color);
|
|
752
839
|
},
|
|
753
840
|
.Fail => {
|
|
754
|
-
const id = ID.from(@intCast(
|
|
841
|
+
const id = ID.from(@intCast(a[i]));
|
|
755
842
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
756
|
-
printc(" {s}", .{@tagName(@
|
|
843
|
+
printc(" {s}", .{@tagName(@as(Fail, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
757
844
|
},
|
|
758
845
|
.HitCount => {
|
|
759
|
-
const id = ID.from(@intCast(
|
|
846
|
+
const id = ID.from(@intCast(a[i]));
|
|
760
847
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
761
848
|
printc(" {d}", .{a[i]}, a, b, &i, 1, color);
|
|
762
849
|
},
|
|
763
850
|
.Prepare => {
|
|
764
|
-
const id = ID.from(@intCast(
|
|
851
|
+
const id = ID.from(@intCast(a[i]));
|
|
765
852
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
766
853
|
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
767
854
|
},
|
|
768
855
|
.Activate => {
|
|
769
|
-
const id = ID.from(@intCast(
|
|
856
|
+
const id = ID.from(@intCast(a[i]));
|
|
770
857
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
771
|
-
printc(" {s}", .{@tagName(@
|
|
858
|
+
printc(" {s}", .{@tagName(@as(Activate, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
772
859
|
},
|
|
773
860
|
.Start => {
|
|
774
|
-
const id = ID.from(@intCast(
|
|
861
|
+
const id = ID.from(@intCast(a[i]));
|
|
775
862
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
776
863
|
const reason = a[i];
|
|
777
|
-
printc(" {s}", .{@tagName(@
|
|
778
|
-
if (@
|
|
779
|
-
const types = @
|
|
864
|
+
printc(" {s}", .{@tagName(@as(Start, @enumFromInt(reason)))}, a, b, &i, 1, color);
|
|
865
|
+
if (@as(Start, @enumFromInt(reason)) == .TypeChange) {
|
|
866
|
+
const types = @as(gen1.Types, @bitCast(a[i]));
|
|
780
867
|
const args = .{
|
|
781
|
-
formatter(.Type, @
|
|
782
|
-
formatter(.Type, @
|
|
868
|
+
formatter(.Type, @intFromEnum(types.type1)),
|
|
869
|
+
formatter(.Type, @intFromEnum(types.type2)),
|
|
783
870
|
};
|
|
784
871
|
printc(" {s}/{s}", args, a, b, &i, 1, color);
|
|
785
|
-
} else if (reason >= @
|
|
872
|
+
} else if (reason >= @intFromEnum(Start.Disable)) {
|
|
786
873
|
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
787
874
|
}
|
|
788
875
|
},
|
|
789
876
|
.End => {
|
|
790
|
-
const id = ID.from(@intCast(
|
|
877
|
+
const id = ID.from(@intCast(a[i]));
|
|
791
878
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
792
|
-
printc(" {s}", .{@tagName(@
|
|
879
|
+
printc(" {s}", .{@tagName(@as(End, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
793
880
|
},
|
|
794
881
|
.Immune => {
|
|
795
|
-
const id = ID.from(@intCast(
|
|
882
|
+
const id = ID.from(@intCast(a[i]));
|
|
796
883
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
797
|
-
printc(" {s}", .{@tagName(@
|
|
884
|
+
printc(" {s}", .{@tagName(@as(Immune, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
798
885
|
},
|
|
799
886
|
.Transform => {
|
|
800
|
-
const source = ID.from(@intCast(
|
|
887
|
+
const source = ID.from(@intCast(a[i]));
|
|
801
888
|
printc(" {s}({d})", .{ @tagName(source.player), source.id }, a, b, &i, 1, color);
|
|
802
|
-
const target = ID.from(@intCast(
|
|
889
|
+
const target = ID.from(@intCast(a[i]));
|
|
803
890
|
printc(" {s}({d})", .{ @tagName(target.player), target.id }, a, b, &i, 1, color);
|
|
804
891
|
},
|
|
805
892
|
else => unreachable,
|
|
@@ -833,12 +920,14 @@ fn printc(
|
|
|
833
920
|
}
|
|
834
921
|
|
|
835
922
|
pub fn expectLog(
|
|
923
|
+
comptime gen: comptime_int,
|
|
836
924
|
comptime formatter: Formatter,
|
|
837
925
|
expected: []const u8,
|
|
838
926
|
actual: []const u8,
|
|
839
927
|
offset: usize,
|
|
840
928
|
) !void {
|
|
841
|
-
if (!
|
|
929
|
+
if (!enabled) return;
|
|
930
|
+
|
|
842
931
|
const color = color: {
|
|
843
932
|
if (std.process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) {
|
|
844
933
|
break :color true;
|
|
@@ -851,8 +940,8 @@ pub fn expectLog(
|
|
|
851
940
|
|
|
852
941
|
expectEqualBytes(expected, actual, offset) catch |err| switch (err) {
|
|
853
942
|
error.TestExpectedEqual => {
|
|
854
|
-
format(formatter, expected, null, color);
|
|
855
|
-
format(formatter, actual, expected, color);
|
|
943
|
+
format(gen, formatter, expected, null, color);
|
|
944
|
+
format(gen, formatter, actual, expected, color);
|
|
856
945
|
return err;
|
|
857
946
|
},
|
|
858
947
|
else => return err,
|
|
@@ -881,7 +970,7 @@ fn expectEqualBytes(expected: []const u8, actual: []const u8, offset: usize) !vo
|
|
|
881
970
|
const endian = builtin.target.cpu.arch.endian();
|
|
882
971
|
|
|
883
972
|
fn N(e: anytype) u8 {
|
|
884
|
-
return @
|
|
973
|
+
return @intFromEnum(e);
|
|
885
974
|
}
|
|
886
975
|
|
|
887
976
|
const p1 = Player.P1;
|
|
@@ -892,6 +981,11 @@ const gen1 = struct {
|
|
|
892
981
|
pub const helpers = @import("../gen1/helpers.zig");
|
|
893
982
|
};
|
|
894
983
|
|
|
984
|
+
const gen2 = struct {
|
|
985
|
+
pub usingnamespace @import("../gen2/data.zig");
|
|
986
|
+
pub const helpers = @import("../gen2/helpers.zig");
|
|
987
|
+
};
|
|
988
|
+
|
|
895
989
|
var buf: [gen1.LOGS_SIZE]u8 = undefined;
|
|
896
990
|
var stream = ByteStream{ .buffer = &buf };
|
|
897
991
|
var log: FixedLog = .{ .writer = stream.writer() };
|
|
@@ -900,18 +994,31 @@ const M = gen1.Move;
|
|
|
900
994
|
const S = gen1.Species;
|
|
901
995
|
|
|
902
996
|
fn expectLog1(expected: []const u8, actual: []const u8) !void {
|
|
903
|
-
return expectLog(gen1Formatter, expected, actual, 0);
|
|
997
|
+
return expectLog(1, gen1Formatter, expected, actual, 0);
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
fn expectLog2(expected: []const u8, actual: []const u8) !void {
|
|
1001
|
+
return expectLog(2, gen2Formatter, expected, actual, 0);
|
|
904
1002
|
}
|
|
905
1003
|
|
|
906
1004
|
fn gen1Formatter(kind: Kind, byte: u8) []const u8 {
|
|
907
1005
|
return switch (kind) {
|
|
908
|
-
.Move => @tagName(@
|
|
909
|
-
.Species => @tagName(@
|
|
910
|
-
.Type => @tagName(@
|
|
1006
|
+
.Move => @tagName(@as(gen1.Move, @enumFromInt(byte))),
|
|
1007
|
+
.Species => @tagName(@as(gen1.Species, @enumFromInt(byte))),
|
|
1008
|
+
.Type => @tagName(@as(gen1.Type, @enumFromInt(byte))),
|
|
911
1009
|
.Status => gen1.Status.name(byte),
|
|
912
1010
|
};
|
|
913
1011
|
}
|
|
914
1012
|
|
|
1013
|
+
fn gen2Formatter(kind: Kind, byte: u8) []const u8 {
|
|
1014
|
+
return switch (kind) {
|
|
1015
|
+
.Move => @tagName(@as(gen2.Move, @enumFromInt(byte))),
|
|
1016
|
+
.Species => @tagName(@as(gen2.Species, @enumFromInt(byte))),
|
|
1017
|
+
.Type => @tagName(@as(gen2.Type, @enumFromInt(byte))),
|
|
1018
|
+
.Status => gen2.Status.name(byte),
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
|
|
915
1022
|
test "|move|" {
|
|
916
1023
|
try log.move(p2.ident(4), M.Thunderbolt, p1.ident(5), null);
|
|
917
1024
|
try expectLog1(
|
|
@@ -993,6 +1100,25 @@ test "|switch|" {
|
|
|
993
1100
|
};
|
|
994
1101
|
try expectLog1(expected, buf[0..9]);
|
|
995
1102
|
stream.reset();
|
|
1103
|
+
|
|
1104
|
+
var blissey = gen2.helpers.Pokemon.init(.{ .species = .Blissey, .moves = &.{.Splash} });
|
|
1105
|
+
blissey.level = 91;
|
|
1106
|
+
blissey.hp = 200;
|
|
1107
|
+
blissey.stats.hp = 400;
|
|
1108
|
+
blissey.status = gen2.Status.init(.PAR);
|
|
1109
|
+
try log.switched(p2.ident(3), &blissey);
|
|
1110
|
+
expected = &(.{
|
|
1111
|
+
N(ArgType.Switch),
|
|
1112
|
+
0b1011,
|
|
1113
|
+
N(gen2.Species.Blissey),
|
|
1114
|
+
N(gen2.Gender.Female),
|
|
1115
|
+
91,
|
|
1116
|
+
} ++ switch (endian) {
|
|
1117
|
+
.Big => .{ 0, 200, 1, 144, par },
|
|
1118
|
+
.Little => .{ 200, 0, 144, 1, par },
|
|
1119
|
+
});
|
|
1120
|
+
try expectLog2(expected, buf[0..10]);
|
|
1121
|
+
stream.reset();
|
|
996
1122
|
}
|
|
997
1123
|
|
|
998
1124
|
test "|cant|" {
|