@pkmn/engine 0.1.0-dev.e5b5a998 → 0.1.0-dev.f918c3bd
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 +53 -42
- package/build/pkg/addon.js +3 -2
- package/build/pkg/addon.js.map +1 -1
- package/build/pkg/data/layout.json +24 -2
- package/build/pkg/data/protocol.json +69 -12
- package/build/pkg/gen1.js +13 -16
- package/build/pkg/gen1.js.map +1 -1
- package/build/pkg/protocol.js +56 -37
- package/build/pkg/protocol.js.map +1 -1
- package/build.zig +82 -57
- package/package.json +33 -15
- package/src/bin/install-pkmn-engine +10 -5
- package/src/lib/binding/node.zig +46 -141
- package/src/lib/binding/wasm.zig +4 -2
- package/src/lib/common/battle.zig +17 -0
- package/src/lib/common/data.zig +15 -27
- package/src/lib/common/debug.zig +20 -11
- package/src/lib/common/js.zig +118 -0
- package/src/lib/common/optional.zig +60 -0
- package/src/lib/common/options.zig +9 -0
- package/src/lib/common/protocol.zig +643 -138
- package/src/lib/common/rational.zig +353 -0
- package/src/lib/common/rng.zig +15 -15
- package/src/lib/common/util.zig +12 -0
- package/src/lib/gen1/README.md +257 -177
- package/src/lib/gen1/calc.zig +426 -0
- package/src/lib/gen1/chance.zig +1058 -0
- package/src/lib/gen1/data/moves.zig +168 -170
- package/src/lib/gen1/data/types.zig +2 -2
- package/src/lib/gen1/data.zig +61 -51
- package/src/lib/gen1/helpers.zig +588 -17
- package/src/lib/gen1/mechanics.zig +776 -502
- package/src/lib/gen2/README.md +102 -83
- package/src/lib/gen2/data/items.zig +1 -1
- package/src/lib/gen2/data/moves.zig +634 -562
- package/src/lib/gen2/data/types.zig +1 -1
- package/src/lib/gen2/data.zig +100 -67
- package/src/lib/gen2/helpers.zig +15 -21
- package/src/lib/gen2/mechanics.zig +1147 -11
- package/src/lib/pkmn.zig +61 -2
|
@@ -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) {
|
|
@@ -118,12 +121,16 @@ pub const Cant = enum(u8) {
|
|
|
118
121
|
Disable,
|
|
119
122
|
Recharge,
|
|
120
123
|
PP,
|
|
124
|
+
|
|
125
|
+
Attract,
|
|
121
126
|
};
|
|
122
127
|
|
|
123
128
|
pub const Heal = enum(u8) {
|
|
124
129
|
None,
|
|
125
130
|
Silent,
|
|
126
131
|
Drain,
|
|
132
|
+
|
|
133
|
+
Leftovers,
|
|
127
134
|
};
|
|
128
135
|
|
|
129
136
|
pub const Damage = enum(u8) {
|
|
@@ -133,6 +140,13 @@ pub const Damage = enum(u8) {
|
|
|
133
140
|
Confusion,
|
|
134
141
|
LeechSeed,
|
|
135
142
|
RecoilOf,
|
|
143
|
+
|
|
144
|
+
Bind,
|
|
145
|
+
Wrap,
|
|
146
|
+
FireSpin,
|
|
147
|
+
Clamp,
|
|
148
|
+
Whirlpool,
|
|
149
|
+
Spikes,
|
|
136
150
|
};
|
|
137
151
|
|
|
138
152
|
pub const Status = enum(u8) {
|
|
@@ -177,6 +191,16 @@ pub const Activate = enum(u8) {
|
|
|
177
191
|
Struggle,
|
|
178
192
|
Substitute,
|
|
179
193
|
Splash,
|
|
194
|
+
|
|
195
|
+
Attract,
|
|
196
|
+
LockOn,
|
|
197
|
+
Bind,
|
|
198
|
+
Wrap,
|
|
199
|
+
FireSpin,
|
|
200
|
+
Clamp,
|
|
201
|
+
Whirlpool,
|
|
202
|
+
|
|
203
|
+
BeatUp, // FIXME of
|
|
180
204
|
};
|
|
181
205
|
|
|
182
206
|
pub const Start = enum(u8) {
|
|
@@ -194,6 +218,18 @@ pub const Start = enum(u8) {
|
|
|
194
218
|
|
|
195
219
|
Disable,
|
|
196
220
|
Mimic,
|
|
221
|
+
|
|
222
|
+
Nightmare,
|
|
223
|
+
Curse,
|
|
224
|
+
Foresight,
|
|
225
|
+
Encore,
|
|
226
|
+
FutureSight,
|
|
227
|
+
|
|
228
|
+
PerishSong3Silent,
|
|
229
|
+
PerishSong3,
|
|
230
|
+
PerishSong2,
|
|
231
|
+
PerishSong1,
|
|
232
|
+
PerishSong0,
|
|
197
233
|
};
|
|
198
234
|
|
|
199
235
|
pub const End = enum(u8) {
|
|
@@ -202,16 +238,27 @@ pub const End = enum(u8) {
|
|
|
202
238
|
Bide,
|
|
203
239
|
Substitute,
|
|
204
240
|
|
|
205
|
-
|
|
241
|
+
Nightmare,
|
|
242
|
+
Curse,
|
|
243
|
+
Foresight,
|
|
244
|
+
Encore,
|
|
245
|
+
FutureSight,
|
|
246
|
+
LeechSeed,
|
|
247
|
+
Bind,
|
|
248
|
+
Wrap,
|
|
249
|
+
FireSpin,
|
|
250
|
+
Clamp,
|
|
251
|
+
Whirlpool,
|
|
252
|
+
|
|
206
253
|
DisableSilent,
|
|
207
254
|
ConfusionSilent,
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
255
|
+
MistSilent,
|
|
256
|
+
FocusEnergySilent,
|
|
257
|
+
LeechSeedSilent,
|
|
258
|
+
ToxicSilent,
|
|
259
|
+
LightScreenSilent,
|
|
260
|
+
ReflectSilent,
|
|
261
|
+
BideSilent,
|
|
215
262
|
};
|
|
216
263
|
|
|
217
264
|
pub const Immune = enum(u8) {
|
|
@@ -219,8 +266,34 @@ pub const Immune = enum(u8) {
|
|
|
219
266
|
OHKO,
|
|
220
267
|
};
|
|
221
268
|
|
|
269
|
+
pub const EndItem = enum(u8) {
|
|
270
|
+
None,
|
|
271
|
+
Eat,
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
pub const SetHP = enum(u8) {
|
|
275
|
+
None,
|
|
276
|
+
Silent,
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
pub const Side = enum(u8) {
|
|
280
|
+
Safeguard,
|
|
281
|
+
Reflect,
|
|
282
|
+
LightScreen,
|
|
283
|
+
Spikes,
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
pub const Weather = enum(u8) {
|
|
287
|
+
None,
|
|
288
|
+
Upkeep,
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
/// Null object pattern implementation of `Log` backed by a `std.io.null_writer`.
|
|
292
|
+
/// Ignores anything sent to it, though protocol logging should additionally be turned off
|
|
293
|
+
/// entirely with `options.log`.
|
|
222
294
|
pub const NULL = Log(@TypeOf(std.io.null_writer)){ .writer = std.io.null_writer };
|
|
223
295
|
|
|
296
|
+
/// Logs protocol information to its `Writer` during a battle update when `options.log` is enabled.
|
|
224
297
|
pub fn Log(comptime Writer: type) type {
|
|
225
298
|
return struct {
|
|
226
299
|
const Self = @This();
|
|
@@ -231,12 +304,13 @@ pub fn Log(comptime Writer: type) type {
|
|
|
231
304
|
|
|
232
305
|
pub fn move(self: Self, source: ID, m: anytype, target: ID, from: anytype) Error!void {
|
|
233
306
|
if (!enabled) return;
|
|
307
|
+
|
|
234
308
|
assert(m != .None);
|
|
235
309
|
try self.writer.writeAll(&.{
|
|
236
310
|
@intFromEnum(ArgType.Move),
|
|
237
|
-
@
|
|
311
|
+
@as(u8, @bitCast(source)),
|
|
238
312
|
@intFromEnum(m),
|
|
239
|
-
@
|
|
313
|
+
@as(u8, @bitCast(target)),
|
|
240
314
|
});
|
|
241
315
|
const none = &[_]u8{@intFromEnum(Move.None)};
|
|
242
316
|
try self.writer.writeAll(switch (@typeInfo(@TypeOf(from))) {
|
|
@@ -253,9 +327,22 @@ pub fn Log(comptime Writer: type) type {
|
|
|
253
327
|
}
|
|
254
328
|
|
|
255
329
|
pub fn switched(self: Self, ident: ID, pokemon: anytype) Error!void {
|
|
330
|
+
return switchDrag(self, .Switch, ident, pokemon);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
fn switchDrag(self: Self, arg: ArgType, ident: ID, pokemon: anytype) Error!void {
|
|
256
334
|
if (!enabled) return;
|
|
257
|
-
|
|
258
|
-
try self.writer.writeAll(&.{ @intFromEnum(
|
|
335
|
+
|
|
336
|
+
try self.writer.writeAll(&.{ @intFromEnum(arg), @as(u8, @bitCast(ident)) });
|
|
337
|
+
if (@hasField(@TypeOf(pokemon.*), "dvs")) {
|
|
338
|
+
try self.writer.writeAll(&.{
|
|
339
|
+
@intFromEnum(pokemon.species),
|
|
340
|
+
@intFromEnum(pokemon.dvs.gender),
|
|
341
|
+
pokemon.level,
|
|
342
|
+
});
|
|
343
|
+
} else {
|
|
344
|
+
try self.writer.writeAll(&.{ @intFromEnum(pokemon.species), pokemon.level });
|
|
345
|
+
}
|
|
259
346
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
260
347
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
261
348
|
try self.writer.writeAll(&.{pokemon.status});
|
|
@@ -263,19 +350,21 @@ pub fn Log(comptime Writer: type) type {
|
|
|
263
350
|
|
|
264
351
|
pub fn cant(self: Self, ident: ID, reason: Cant) Error!void {
|
|
265
352
|
if (!enabled) return;
|
|
353
|
+
|
|
266
354
|
assert(reason != .Disable);
|
|
267
355
|
try self.writer.writeAll(&.{
|
|
268
356
|
@intFromEnum(ArgType.Cant),
|
|
269
|
-
@
|
|
357
|
+
@as(u8, @bitCast(ident)),
|
|
270
358
|
@intFromEnum(reason),
|
|
271
359
|
});
|
|
272
360
|
}
|
|
273
361
|
|
|
274
362
|
pub fn disabled(self: Self, ident: ID, m: anytype) Error!void {
|
|
275
363
|
if (!enabled) return;
|
|
364
|
+
|
|
276
365
|
try self.writer.writeAll(&.{
|
|
277
366
|
@intFromEnum(ArgType.Cant),
|
|
278
|
-
@
|
|
367
|
+
@as(u8, @bitCast(ident)),
|
|
279
368
|
@intFromEnum(Cant.Disable),
|
|
280
369
|
@intFromEnum(m),
|
|
281
370
|
});
|
|
@@ -283,12 +372,14 @@ pub fn Log(comptime Writer: type) type {
|
|
|
283
372
|
|
|
284
373
|
pub fn faint(self: Self, ident: ID, done: bool) Error!void {
|
|
285
374
|
if (!enabled) return;
|
|
286
|
-
|
|
375
|
+
|
|
376
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Faint), @as(u8, @bitCast(ident)) });
|
|
287
377
|
if (done) try self.writer.writeByte(@intFromEnum(ArgType.None));
|
|
288
378
|
}
|
|
289
379
|
|
|
290
380
|
pub fn turn(self: Self, num: u16) Error!void {
|
|
291
381
|
if (!enabled) return;
|
|
382
|
+
|
|
292
383
|
try self.writer.writeByte(@intFromEnum(ArgType.Turn));
|
|
293
384
|
try self.writer.writeIntNative(u16, num);
|
|
294
385
|
try self.writer.writeByte(@intFromEnum(ArgType.None));
|
|
@@ -296,6 +387,7 @@ pub fn Log(comptime Writer: type) type {
|
|
|
296
387
|
|
|
297
388
|
pub fn win(self: Self, player: Player) Error!void {
|
|
298
389
|
if (!enabled) return;
|
|
390
|
+
|
|
299
391
|
try self.writer.writeAll(&.{
|
|
300
392
|
@intFromEnum(ArgType.Win),
|
|
301
393
|
@intFromEnum(player),
|
|
@@ -305,13 +397,15 @@ pub fn Log(comptime Writer: type) type {
|
|
|
305
397
|
|
|
306
398
|
pub fn tie(self: Self) Error!void {
|
|
307
399
|
if (!enabled) return;
|
|
400
|
+
|
|
308
401
|
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Tie), @intFromEnum(ArgType.None) });
|
|
309
402
|
}
|
|
310
403
|
|
|
311
404
|
pub fn damage(self: Self, ident: ID, pokemon: anytype, reason: Damage) Error!void {
|
|
312
405
|
if (!enabled) return;
|
|
406
|
+
|
|
313
407
|
assert(@intFromEnum(reason) <= @intFromEnum(Damage.LeechSeed));
|
|
314
|
-
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @
|
|
408
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @as(u8, @bitCast(ident)) });
|
|
315
409
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
316
410
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
317
411
|
try self.writer.writeAll(&.{ pokemon.status, @intFromEnum(reason) });
|
|
@@ -325,21 +419,23 @@ pub fn Log(comptime Writer: type) type {
|
|
|
325
419
|
source: ID,
|
|
326
420
|
) Error!void {
|
|
327
421
|
if (!enabled) return;
|
|
422
|
+
|
|
328
423
|
assert(@intFromEnum(reason) == @intFromEnum(Damage.RecoilOf));
|
|
329
|
-
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @
|
|
424
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Damage), @as(u8, @bitCast(ident)) });
|
|
330
425
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
331
426
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
332
427
|
try self.writer.writeAll(&.{
|
|
333
428
|
pokemon.status,
|
|
334
429
|
@intFromEnum(reason),
|
|
335
|
-
@
|
|
430
|
+
@as(u8, @bitCast(source)),
|
|
336
431
|
});
|
|
337
432
|
}
|
|
338
433
|
|
|
339
434
|
pub fn heal(self: Self, ident: ID, pokemon: anytype, reason: Heal) Error!void {
|
|
340
435
|
if (!enabled) return;
|
|
436
|
+
|
|
341
437
|
assert(reason != .Drain);
|
|
342
|
-
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @
|
|
438
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(ident)) });
|
|
343
439
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
344
440
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
345
441
|
try self.writer.writeAll(&.{ pokemon.status, @intFromEnum(reason) });
|
|
@@ -347,22 +443,24 @@ pub fn Log(comptime Writer: type) type {
|
|
|
347
443
|
|
|
348
444
|
pub fn drain(self: Self, source: ID, pokemon: anytype, target: ID) Error!void {
|
|
349
445
|
if (!enabled) return;
|
|
350
|
-
|
|
446
|
+
|
|
447
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Heal), @as(u8, @bitCast(source)) });
|
|
351
448
|
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
352
449
|
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
353
450
|
try self.writer.writeAll(&.{
|
|
354
451
|
pokemon.status,
|
|
355
452
|
@intFromEnum(Heal.Drain),
|
|
356
|
-
@
|
|
453
|
+
@as(u8, @bitCast(target)),
|
|
357
454
|
});
|
|
358
455
|
}
|
|
359
456
|
|
|
360
457
|
pub fn status(self: Self, ident: ID, value: u8, reason: Status) Error!void {
|
|
361
458
|
if (!enabled) return;
|
|
459
|
+
|
|
362
460
|
assert(reason != .From);
|
|
363
461
|
try self.writer.writeAll(&.{
|
|
364
462
|
@intFromEnum(ArgType.Status),
|
|
365
|
-
@
|
|
463
|
+
@as(u8, @bitCast(ident)),
|
|
366
464
|
value,
|
|
367
465
|
@intFromEnum(reason),
|
|
368
466
|
});
|
|
@@ -370,9 +468,10 @@ pub fn Log(comptime Writer: type) type {
|
|
|
370
468
|
|
|
371
469
|
pub fn statusFrom(self: Self, ident: ID, value: u8, m: anytype) Error!void {
|
|
372
470
|
if (!enabled) return;
|
|
471
|
+
|
|
373
472
|
try self.writer.writeAll(&.{
|
|
374
473
|
@intFromEnum(ArgType.Status),
|
|
375
|
-
@
|
|
474
|
+
@as(u8, @bitCast(ident)),
|
|
376
475
|
value,
|
|
377
476
|
@intFromEnum(Status.From),
|
|
378
477
|
@intFromEnum(m),
|
|
@@ -381,9 +480,10 @@ pub fn Log(comptime Writer: type) type {
|
|
|
381
480
|
|
|
382
481
|
pub fn curestatus(self: Self, ident: ID, value: u8, reason: CureStatus) Error!void {
|
|
383
482
|
if (!enabled) return;
|
|
483
|
+
|
|
384
484
|
try self.writer.writeAll(&.{
|
|
385
485
|
@intFromEnum(ArgType.CureStatus),
|
|
386
|
-
@
|
|
486
|
+
@as(u8, @bitCast(ident)),
|
|
387
487
|
value,
|
|
388
488
|
@intFromEnum(reason),
|
|
389
489
|
});
|
|
@@ -391,98 +491,113 @@ pub fn Log(comptime Writer: type) type {
|
|
|
391
491
|
|
|
392
492
|
pub fn boost(self: Self, ident: ID, reason: Boost, num: i8) Error!void {
|
|
393
493
|
if (!enabled) return;
|
|
494
|
+
|
|
394
495
|
assert(num != 0 and (reason != .Rage or num > 0));
|
|
395
496
|
try self.writer.writeAll(&.{
|
|
396
497
|
@intFromEnum(ArgType.Boost),
|
|
397
|
-
@
|
|
498
|
+
@as(u8, @bitCast(ident)),
|
|
398
499
|
@intFromEnum(reason),
|
|
399
|
-
@
|
|
500
|
+
@as(u8, @intCast(num + 6)),
|
|
400
501
|
});
|
|
401
502
|
}
|
|
402
503
|
|
|
403
504
|
pub fn clearallboost(self: Self) Error!void {
|
|
404
505
|
if (!enabled) return;
|
|
506
|
+
|
|
405
507
|
try self.writer.writeAll(&.{@intFromEnum(ArgType.ClearAllBoost)});
|
|
406
508
|
}
|
|
407
509
|
|
|
408
510
|
pub fn fail(self: Self, ident: ID, reason: Fail) Error!void {
|
|
409
511
|
if (!enabled) return;
|
|
512
|
+
|
|
410
513
|
try self.writer.writeAll(&.{
|
|
411
514
|
@intFromEnum(ArgType.Fail),
|
|
412
|
-
@
|
|
515
|
+
@as(u8, @bitCast(ident)),
|
|
413
516
|
@intFromEnum(reason),
|
|
414
517
|
});
|
|
415
518
|
}
|
|
416
519
|
|
|
417
520
|
pub fn miss(self: Self, source: ID) Error!void {
|
|
418
521
|
if (!enabled) return;
|
|
419
|
-
|
|
522
|
+
|
|
523
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Miss), @as(u8, @bitCast(source)) });
|
|
420
524
|
}
|
|
421
525
|
|
|
422
526
|
pub fn hitcount(self: Self, ident: ID, num: u8) Error!void {
|
|
423
527
|
if (!enabled) return;
|
|
528
|
+
|
|
424
529
|
try self.writer.writeAll(&.{
|
|
425
530
|
@intFromEnum(ArgType.HitCount),
|
|
426
|
-
@
|
|
531
|
+
@as(u8, @bitCast(ident)),
|
|
427
532
|
num,
|
|
428
533
|
});
|
|
429
534
|
}
|
|
430
535
|
|
|
431
536
|
pub fn prepare(self: Self, source: ID, m: anytype) Error!void {
|
|
432
537
|
if (!enabled) return;
|
|
538
|
+
|
|
433
539
|
try self.writer.writeAll(&.{
|
|
434
540
|
@intFromEnum(ArgType.Prepare),
|
|
435
|
-
@
|
|
541
|
+
@as(u8, @bitCast(source)),
|
|
436
542
|
@intFromEnum(m),
|
|
437
543
|
});
|
|
438
544
|
}
|
|
439
545
|
|
|
440
546
|
pub fn mustrecharge(self: Self, ident: ID) Error!void {
|
|
441
547
|
if (!enabled) return;
|
|
442
|
-
|
|
548
|
+
|
|
549
|
+
try self.writer.writeAll(&.{
|
|
550
|
+
@intFromEnum(ArgType.MustRecharge),
|
|
551
|
+
@as(u8, @bitCast(ident)),
|
|
552
|
+
});
|
|
443
553
|
}
|
|
444
554
|
|
|
445
555
|
pub fn activate(self: Self, ident: ID, reason: Activate) Error!void {
|
|
446
556
|
if (!enabled) return;
|
|
557
|
+
|
|
447
558
|
try self.writer.writeAll(&.{
|
|
448
559
|
@intFromEnum(ArgType.Activate),
|
|
449
|
-
@
|
|
560
|
+
@as(u8, @bitCast(ident)),
|
|
450
561
|
@intFromEnum(reason),
|
|
451
562
|
});
|
|
452
563
|
}
|
|
453
564
|
|
|
454
565
|
pub fn fieldactivate(self: Self) Error!void {
|
|
455
566
|
if (!enabled) return;
|
|
567
|
+
|
|
456
568
|
try self.writer.writeAll(&.{@intFromEnum(ArgType.FieldActivate)});
|
|
457
569
|
}
|
|
458
570
|
|
|
459
571
|
pub fn start(self: Self, ident: ID, reason: Start) Error!void {
|
|
460
572
|
if (!enabled) return;
|
|
573
|
+
|
|
461
574
|
assert(@intFromEnum(reason) < @intFromEnum(Start.TypeChange));
|
|
462
575
|
try self.writer.writeAll(&.{
|
|
463
576
|
@intFromEnum(ArgType.Start),
|
|
464
|
-
@
|
|
577
|
+
@as(u8, @bitCast(ident)),
|
|
465
578
|
@intFromEnum(reason),
|
|
466
579
|
});
|
|
467
580
|
}
|
|
468
581
|
|
|
469
582
|
pub fn typechange(self: Self, source: ID, types: anytype, target: ID) Error!void {
|
|
470
583
|
if (!enabled) return;
|
|
584
|
+
|
|
471
585
|
try self.writer.writeAll(&.{
|
|
472
586
|
@intFromEnum(ArgType.Start),
|
|
473
|
-
@
|
|
587
|
+
@as(u8, @bitCast(source)),
|
|
474
588
|
@intFromEnum(Start.TypeChange),
|
|
475
|
-
@
|
|
476
|
-
@
|
|
589
|
+
@as(u8, @bitCast(types)),
|
|
590
|
+
@as(u8, @bitCast(target)),
|
|
477
591
|
});
|
|
478
592
|
}
|
|
479
593
|
|
|
480
594
|
pub fn startEffect(self: Self, ident: ID, reason: Start, m: anytype) Error!void {
|
|
481
595
|
if (!enabled) return;
|
|
596
|
+
|
|
482
597
|
assert(@intFromEnum(reason) > @intFromEnum(Start.TypeChange));
|
|
483
598
|
try self.writer.writeAll(&.{
|
|
484
599
|
@intFromEnum(ArgType.Start),
|
|
485
|
-
@
|
|
600
|
+
@as(u8, @bitCast(ident)),
|
|
486
601
|
@intFromEnum(reason),
|
|
487
602
|
@intFromEnum(m),
|
|
488
603
|
});
|
|
@@ -490,68 +605,211 @@ pub fn Log(comptime Writer: type) type {
|
|
|
490
605
|
|
|
491
606
|
pub fn end(self: Self, ident: ID, reason: End) Error!void {
|
|
492
607
|
if (!enabled) return;
|
|
608
|
+
|
|
493
609
|
try self.writer.writeAll(&.{
|
|
494
610
|
@intFromEnum(ArgType.End),
|
|
495
|
-
@
|
|
611
|
+
@as(u8, @bitCast(ident)),
|
|
496
612
|
@intFromEnum(reason),
|
|
497
613
|
});
|
|
498
614
|
}
|
|
499
615
|
|
|
500
616
|
pub fn ohko(self: Self) Error!void {
|
|
501
617
|
if (!enabled) return;
|
|
618
|
+
|
|
502
619
|
try self.writer.writeAll(&.{@intFromEnum(ArgType.OHKO)});
|
|
503
620
|
}
|
|
504
621
|
|
|
505
622
|
pub fn crit(self: Self, ident: ID) Error!void {
|
|
506
623
|
if (!enabled) return;
|
|
507
|
-
|
|
624
|
+
|
|
625
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.Crit), @as(u8, @bitCast(ident)) });
|
|
508
626
|
}
|
|
509
627
|
|
|
510
628
|
pub fn supereffective(self: Self, ident: ID) Error!void {
|
|
511
629
|
if (!enabled) return;
|
|
630
|
+
|
|
512
631
|
try self.writer.writeAll(&.{
|
|
513
632
|
@intFromEnum(ArgType.SuperEffective),
|
|
514
|
-
@
|
|
633
|
+
@as(u8, @bitCast(ident)),
|
|
515
634
|
});
|
|
516
635
|
}
|
|
517
636
|
|
|
518
637
|
pub fn resisted(self: Self, ident: ID) Error!void {
|
|
519
638
|
if (!enabled) return;
|
|
520
|
-
|
|
639
|
+
|
|
640
|
+
try self.writer.writeAll(&.{
|
|
641
|
+
@intFromEnum(ArgType.Resisted),
|
|
642
|
+
@as(u8, @bitCast(ident)),
|
|
643
|
+
});
|
|
521
644
|
}
|
|
522
645
|
|
|
523
646
|
pub fn immune(self: Self, ident: ID, reason: Immune) Error!void {
|
|
524
647
|
if (!enabled) return;
|
|
648
|
+
|
|
525
649
|
try self.writer.writeAll(&.{
|
|
526
650
|
@intFromEnum(ArgType.Immune),
|
|
527
|
-
@
|
|
651
|
+
@as(u8, @bitCast(ident)),
|
|
528
652
|
@intFromEnum(reason),
|
|
529
653
|
});
|
|
530
654
|
}
|
|
531
655
|
|
|
532
656
|
pub fn transform(self: Self, source: ID, target: ID) Error!void {
|
|
533
657
|
if (!enabled) return;
|
|
658
|
+
|
|
534
659
|
try self.writer.writeAll(&.{
|
|
535
660
|
@intFromEnum(ArgType.Transform),
|
|
536
|
-
@
|
|
537
|
-
@
|
|
661
|
+
@as(u8, @bitCast(source)),
|
|
662
|
+
@as(u8, @bitCast(target)),
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
pub fn drag(self: Self, ident: ID, pokemon: anytype) Error!void {
|
|
667
|
+
return switchDrag(self, .Drag, ident, pokemon);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
pub fn item(self: Self, target: ID, i: anytype, source: ID) Error!void {
|
|
671
|
+
if (!enabled) return;
|
|
672
|
+
|
|
673
|
+
try self.writer.writeAll(&.{
|
|
674
|
+
@intFromEnum(ArgType.Item),
|
|
675
|
+
@as(u8, @bitCast(target)),
|
|
676
|
+
@intFromEnum(i),
|
|
677
|
+
@as(u8, @bitCast(source)),
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
pub fn enditem(self: Self, ident: ID, i: anytype, reason: EndItem) Error!void {
|
|
682
|
+
if (!enabled) return;
|
|
683
|
+
|
|
684
|
+
try self.writer.writeAll(&.{
|
|
685
|
+
@intFromEnum(ArgType.EndItem),
|
|
686
|
+
@as(u8, @bitCast(ident)),
|
|
687
|
+
@intFromEnum(i),
|
|
688
|
+
@intFromEnum(reason),
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
pub fn cureteam(self: Self, source: ID) Error!void {
|
|
693
|
+
if (!enabled) return;
|
|
694
|
+
|
|
695
|
+
try self.writer.writeAll(&.{
|
|
696
|
+
@intFromEnum(ArgType.CureTeam),
|
|
697
|
+
@as(u8, @bitCast(source)),
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
pub fn sethp(self: Self, ident: ID, pokemon: anytype, reason: SetHP) Error!void {
|
|
702
|
+
if (!enabled) return;
|
|
703
|
+
|
|
704
|
+
try self.writer.writeAll(&.{ @intFromEnum(ArgType.SetHP), @as(u8, @bitCast(ident)) });
|
|
705
|
+
try self.writer.writeIntNative(u16, pokemon.hp);
|
|
706
|
+
try self.writer.writeIntNative(u16, pokemon.stats.hp);
|
|
707
|
+
try self.writer.writeAll(&.{pokemon.status});
|
|
708
|
+
try self.writer.writeByte(@intFromEnum(reason));
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
pub fn setboost(self: Self, ident: ID, num: i8) Error!void {
|
|
712
|
+
if (!enabled) return;
|
|
713
|
+
|
|
714
|
+
try self.writer.writeAll(&.{
|
|
715
|
+
@intFromEnum(ArgType.SetBoost),
|
|
716
|
+
@as(u8, @bitCast(ident)),
|
|
717
|
+
@as(u8, @intCast(num + 6)),
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
pub fn copyboost(self: Self, source: ID, target: ID) Error!void {
|
|
722
|
+
if (!enabled) return;
|
|
723
|
+
|
|
724
|
+
try self.writer.writeAll(&.{
|
|
725
|
+
@intFromEnum(ArgType.CopyBoost),
|
|
726
|
+
@as(u8, @bitCast(source)),
|
|
727
|
+
@as(u8, @bitCast(target)),
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
pub fn sidestart(self: Self, player: Player, reason: Side) Error!void {
|
|
732
|
+
if (!enabled) return;
|
|
733
|
+
|
|
734
|
+
try self.writer.writeAll(&.{
|
|
735
|
+
@intFromEnum(ArgType.SideStart),
|
|
736
|
+
@intFromEnum(player),
|
|
737
|
+
@intFromEnum(reason),
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
pub fn sideend(self: Self, player: Player, reason: Side) Error!void {
|
|
742
|
+
if (!enabled) return;
|
|
743
|
+
|
|
744
|
+
assert(@intFromEnum(reason) != @intFromEnum(Side.Spikes));
|
|
745
|
+
try self.writer.writeAll(&.{
|
|
746
|
+
@intFromEnum(ArgType.SideEnd),
|
|
747
|
+
@intFromEnum(player),
|
|
748
|
+
@intFromEnum(reason),
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
pub fn spikesend(self: Self, player: Player, m: anytype, source: ID) Error!void {
|
|
753
|
+
if (!enabled) return;
|
|
754
|
+
|
|
755
|
+
try self.writer.writeAll(&.{
|
|
756
|
+
@intFromEnum(ArgType.SideEnd),
|
|
757
|
+
@intFromEnum(player),
|
|
758
|
+
@intFromEnum(Side.Spikes),
|
|
759
|
+
@intFromEnum(m),
|
|
760
|
+
@as(u8, @bitCast(source)),
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
pub fn singlemove(self: Self, ident: ID, m: anytype) Error!void {
|
|
765
|
+
return single(self, .SingleMove, ident, m);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
pub fn singleturn(self: Self, ident: ID, m: anytype) Error!void {
|
|
769
|
+
return single(self, .SingleTurn, ident, m);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
fn single(self: Self, arg: ArgType, ident: ID, m: anytype) Error!void {
|
|
773
|
+
if (!enabled) return;
|
|
774
|
+
|
|
775
|
+
try self.writer.writeAll(&.{
|
|
776
|
+
@intFromEnum(arg),
|
|
777
|
+
@as(u8, @bitCast(ident)),
|
|
778
|
+
@intFromEnum(m),
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
pub fn weather(self: Self, w: anytype, reason: Weather) Error!void {
|
|
783
|
+
if (!enabled) return;
|
|
784
|
+
|
|
785
|
+
assert(!(w == .None and reason == .Upkeep));
|
|
786
|
+
try self.writer.writeAll(&.{
|
|
787
|
+
@intFromEnum(ArgType.Weather),
|
|
788
|
+
@intFromEnum(w),
|
|
789
|
+
@intFromEnum(reason),
|
|
538
790
|
});
|
|
539
791
|
}
|
|
540
792
|
|
|
541
793
|
pub fn laststill(self: Self) Error!void {
|
|
542
794
|
if (!enabled) return;
|
|
795
|
+
|
|
543
796
|
try self.writer.writeAll(&.{@intFromEnum(ArgType.LastStill)});
|
|
544
797
|
}
|
|
545
798
|
|
|
546
799
|
pub fn lastmiss(self: Self) Error!void {
|
|
547
800
|
if (!enabled) return;
|
|
801
|
+
|
|
548
802
|
try self.writer.writeAll(&.{@intFromEnum(ArgType.LastMiss)});
|
|
549
803
|
}
|
|
550
804
|
};
|
|
551
805
|
}
|
|
552
806
|
|
|
807
|
+
/// `Log` type backed by the optimized `ByteStream.Writer`.
|
|
553
808
|
pub const FixedLog = Log(ByteStream.Writer);
|
|
554
809
|
|
|
810
|
+
/// Stripped down version of `std.io.FixedBufferStream` optimized for efficiently writing the
|
|
811
|
+
/// individual protocol bytes. Note that the `ByteStream.Writer` is **not** a `std.io.Writer` and
|
|
812
|
+
/// should not be used for general purpose writing.
|
|
555
813
|
pub const ByteStream = struct {
|
|
556
814
|
buffer: []u8,
|
|
557
815
|
pos: usize = 0,
|
|
@@ -592,15 +850,19 @@ pub const ByteStream = struct {
|
|
|
592
850
|
}
|
|
593
851
|
};
|
|
594
852
|
|
|
595
|
-
pub const Kind = enum { Move, Species, Type, Status };
|
|
596
|
-
pub const Formatter = fn (Kind, u8) []const u8;
|
|
853
|
+
pub const Kind = enum { Move, Species, Type, Status, Item, Weather };
|
|
597
854
|
|
|
598
|
-
pub fn format(
|
|
855
|
+
pub fn format(
|
|
856
|
+
comptime gen: anytype,
|
|
857
|
+
a: []const u8,
|
|
858
|
+
b: ?[]const u8,
|
|
859
|
+
color: bool,
|
|
860
|
+
) void {
|
|
599
861
|
print("\n", .{});
|
|
600
862
|
|
|
601
863
|
var i: usize = 0;
|
|
602
864
|
while (i < a.len) {
|
|
603
|
-
const arg = @enumFromInt(
|
|
865
|
+
const arg: ArgType = @enumFromInt(a[i]);
|
|
604
866
|
const name = switch (arg) {
|
|
605
867
|
.None => if (color) "\x1b[2m-\x1b[0m" else "-",
|
|
606
868
|
.LastStill => "|[still]",
|
|
@@ -633,6 +895,18 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
633
895
|
.Resisted => "|-resisted|",
|
|
634
896
|
.Immune => "|-immune|",
|
|
635
897
|
.Transform => "|-transform|",
|
|
898
|
+
.Drag => "|drag|",
|
|
899
|
+
.Item => "|-item|",
|
|
900
|
+
.EndItem => "|-enditem|",
|
|
901
|
+
.CureTeam => "|-cureteam|",
|
|
902
|
+
.SetHP => "|-sethp|",
|
|
903
|
+
.SetBoost => "|-setboost|",
|
|
904
|
+
.CopyBoost => "|-copyboost|",
|
|
905
|
+
.SideStart => "|-sidestart|",
|
|
906
|
+
.SideEnd => "|-sideend|",
|
|
907
|
+
.SingleMove => "|-singlemove|",
|
|
908
|
+
.SingleTurn => "|-singleturn|",
|
|
909
|
+
.Weather => "|-weather|",
|
|
636
910
|
else => unreachable,
|
|
637
911
|
};
|
|
638
912
|
printc("{s}", .{name}, a, b, &i, 1, color);
|
|
@@ -646,19 +920,29 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
646
920
|
.OHKO,
|
|
647
921
|
=> {},
|
|
648
922
|
.Move => {
|
|
649
|
-
const source = ID.from(@intCast(
|
|
923
|
+
const source = ID.from(@intCast(a[i]));
|
|
650
924
|
printc(" {s}({d})", .{ @tagName(source.player), source.id }, a, b, &i, 1, color);
|
|
651
|
-
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
652
|
-
const target = ID.from(@intCast(
|
|
925
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
926
|
+
const target = ID.from(@intCast(a[i]));
|
|
653
927
|
printc(" {s}({d})", .{ @tagName(target.player), target.id }, a, b, &i, 1, color);
|
|
654
|
-
const reason = @enumFromInt(
|
|
928
|
+
const reason: Move = @enumFromInt(a[i]);
|
|
655
929
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
656
|
-
if (reason == .From)
|
|
930
|
+
if (reason == .From) {
|
|
931
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
932
|
+
}
|
|
657
933
|
},
|
|
658
|
-
.Switch => {
|
|
659
|
-
const id = ID.from(@intCast(
|
|
934
|
+
.Switch, .Drag => {
|
|
935
|
+
const id = ID.from(@intCast(a[i]));
|
|
660
936
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
661
|
-
printc(" {s}", .{formatter(.Species, a[i])}, a, b, &i, 1, color);
|
|
937
|
+
printc(" {s}", .{formatter(gen, .Species, a[i])}, a, b, &i, 1, color);
|
|
938
|
+
if (@hasDecl(gen, "Gender")) {
|
|
939
|
+
if (a[i] == N(gen.Gender.Unknown)) {
|
|
940
|
+
i += 1;
|
|
941
|
+
} else {
|
|
942
|
+
var gender = if (a[i] == N(gen.Gender.Male)) "M" else "F";
|
|
943
|
+
printc(", {s}", .{gender}, a, b, &i, 1, color);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
662
946
|
printc(" L{d}", .{a[i]}, a, b, &i, 1, color);
|
|
663
947
|
switch (endian) {
|
|
664
948
|
.Big => {
|
|
@@ -674,15 +958,15 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
674
958
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
675
959
|
},
|
|
676
960
|
}
|
|
677
|
-
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
961
|
+
printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
|
|
678
962
|
},
|
|
679
963
|
.Cant => {
|
|
680
|
-
const id = ID.from(@intCast(
|
|
964
|
+
const id = ID.from(@intCast(a[i]));
|
|
681
965
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
682
|
-
const reason = @enumFromInt(
|
|
966
|
+
const reason: Cant = @enumFromInt(a[i]);
|
|
683
967
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
684
968
|
if (reason == .Disable) {
|
|
685
|
-
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
969
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
686
970
|
}
|
|
687
971
|
},
|
|
688
972
|
.Faint,
|
|
@@ -691,8 +975,9 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
691
975
|
.Crit,
|
|
692
976
|
.SuperEffective,
|
|
693
977
|
.Resisted,
|
|
978
|
+
.CureTeam,
|
|
694
979
|
=> {
|
|
695
|
-
const id = ID.from(@intCast(
|
|
980
|
+
const id = ID.from(@intCast(a[i]));
|
|
696
981
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
697
982
|
},
|
|
698
983
|
.Turn => {
|
|
@@ -702,9 +987,11 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
702
987
|
};
|
|
703
988
|
printc(" {d}", .{turn}, a, b, &i, 2, color);
|
|
704
989
|
},
|
|
705
|
-
.Win =>
|
|
990
|
+
.Win => {
|
|
991
|
+
printc(" {s}", .{@tagName(@as(Player, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
992
|
+
},
|
|
706
993
|
.Damage, .Heal => {
|
|
707
|
-
var id = ID.from(@intCast(
|
|
994
|
+
var id = ID.from(@intCast(a[i]));
|
|
708
995
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
709
996
|
switch (endian) {
|
|
710
997
|
.Big => {
|
|
@@ -720,95 +1007,150 @@ pub fn format(comptime formatter: Formatter, a: []const u8, b: ?[]const u8, colo
|
|
|
720
1007
|
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
721
1008
|
},
|
|
722
1009
|
}
|
|
723
|
-
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
1010
|
+
printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
|
|
724
1011
|
if (arg == .Damage) {
|
|
725
|
-
const reason = a[i];
|
|
726
|
-
printc(" {s}", .{@tagName(
|
|
727
|
-
if (reason ==
|
|
728
|
-
id = ID.from(@intCast(
|
|
1012
|
+
const reason: Damage = @enumFromInt(a[i]);
|
|
1013
|
+
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
1014
|
+
if (reason == .RecoilOf) {
|
|
1015
|
+
id = ID.from(@intCast(a[i]));
|
|
729
1016
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
730
1017
|
}
|
|
731
1018
|
} else {
|
|
732
|
-
const reason = @enumFromInt(
|
|
1019
|
+
const reason: Heal = @enumFromInt(a[i]);
|
|
733
1020
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
734
1021
|
if (reason == .Drain) {
|
|
735
|
-
id = ID.from(@intCast(
|
|
1022
|
+
id = ID.from(@intCast(a[i]));
|
|
736
1023
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
737
1024
|
}
|
|
738
1025
|
}
|
|
739
1026
|
},
|
|
740
1027
|
.Status => {
|
|
741
|
-
const id = ID.from(@intCast(
|
|
1028
|
+
const id = ID.from(@intCast(a[i]));
|
|
742
1029
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
743
|
-
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
744
|
-
const reason = @enumFromInt(
|
|
1030
|
+
printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
|
|
1031
|
+
const reason: Status = @enumFromInt(a[i]);
|
|
745
1032
|
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
746
|
-
if (reason == .From)
|
|
1033
|
+
if (reason == .From) {
|
|
1034
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
1035
|
+
}
|
|
747
1036
|
},
|
|
748
1037
|
.CureStatus => {
|
|
749
|
-
const id = ID.from(@intCast(
|
|
1038
|
+
const id = ID.from(@intCast(a[i]));
|
|
750
1039
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
751
|
-
printc(" {s}", .{formatter(.Status, a[i])}, a, b, &i, 1, color);
|
|
752
|
-
|
|
1040
|
+
printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
|
|
1041
|
+
const reason: CureStatus = @enumFromInt(a[i]);
|
|
1042
|
+
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
753
1043
|
},
|
|
754
1044
|
.Boost => {
|
|
755
|
-
const id = ID.from(@intCast(
|
|
1045
|
+
const id = ID.from(@intCast(a[i]));
|
|
756
1046
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
757
|
-
printc(" {s}", .{@tagName(@
|
|
1047
|
+
printc(" {s}", .{@tagName(@as(Boost, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
758
1048
|
printc(" {d}", .{a[i]}, a, b, &i, 1, color);
|
|
759
1049
|
},
|
|
760
1050
|
.Fail => {
|
|
761
|
-
const id = ID.from(@intCast(
|
|
1051
|
+
const id = ID.from(@intCast(a[i]));
|
|
762
1052
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
763
|
-
printc(" {s}", .{@tagName(@
|
|
1053
|
+
printc(" {s}", .{@tagName(@as(Fail, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
764
1054
|
},
|
|
765
|
-
.HitCount => {
|
|
766
|
-
const id = ID.from(@intCast(
|
|
1055
|
+
.HitCount, .SetBoost => {
|
|
1056
|
+
const id = ID.from(@intCast(a[i]));
|
|
767
1057
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
768
1058
|
printc(" {d}", .{a[i]}, a, b, &i, 1, color);
|
|
769
1059
|
},
|
|
770
|
-
.Prepare => {
|
|
771
|
-
const id = ID.from(@intCast(
|
|
1060
|
+
.Prepare, .SingleMove, .SingleTurn => {
|
|
1061
|
+
const id = ID.from(@intCast(a[i]));
|
|
772
1062
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
773
|
-
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
1063
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
774
1064
|
},
|
|
775
1065
|
.Activate => {
|
|
776
|
-
const id = ID.from(@intCast(
|
|
1066
|
+
const id = ID.from(@intCast(a[i]));
|
|
777
1067
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
778
|
-
printc(" {s}", .{@tagName(@
|
|
1068
|
+
printc(" {s}", .{@tagName(@as(Activate, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
779
1069
|
},
|
|
780
1070
|
.Start => {
|
|
781
|
-
const id = ID.from(@intCast(
|
|
1071
|
+
const id = ID.from(@intCast(a[i]));
|
|
782
1072
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
783
1073
|
const reason = a[i];
|
|
784
|
-
printc(" {s}", .{@tagName(@
|
|
785
|
-
if (@
|
|
786
|
-
const types = @
|
|
1074
|
+
printc(" {s}", .{@tagName(@as(Start, @enumFromInt(reason)))}, a, b, &i, 1, color);
|
|
1075
|
+
if (@as(Start, @enumFromInt(reason)) == .TypeChange) {
|
|
1076
|
+
const types = @as(gen1.Types, @bitCast(a[i]));
|
|
787
1077
|
const args = .{
|
|
788
|
-
formatter(.Type, @intFromEnum(types.type1)),
|
|
789
|
-
formatter(.Type, @intFromEnum(types.type2)),
|
|
1078
|
+
formatter(gen, .Type, @intFromEnum(types.type1)),
|
|
1079
|
+
formatter(gen, .Type, @intFromEnum(types.type2)),
|
|
790
1080
|
};
|
|
791
1081
|
printc(" {s}/{s}", args, a, b, &i, 1, color);
|
|
792
1082
|
} else if (reason >= @intFromEnum(Start.Disable)) {
|
|
793
|
-
printc(" {s}", .{formatter(.Move, a[i])}, a, b, &i, 1, color);
|
|
1083
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
794
1084
|
}
|
|
795
1085
|
},
|
|
796
1086
|
.End => {
|
|
797
|
-
const id = ID.from(@intCast(
|
|
1087
|
+
const id = ID.from(@intCast(a[i]));
|
|
798
1088
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
799
|
-
printc(" {s}", .{@tagName(@
|
|
1089
|
+
printc(" {s}", .{@tagName(@as(End, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
800
1090
|
},
|
|
801
1091
|
.Immune => {
|
|
802
|
-
const id = ID.from(@intCast(
|
|
1092
|
+
const id = ID.from(@intCast(a[i]));
|
|
803
1093
|
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
804
|
-
printc(" {s}", .{@tagName(@
|
|
1094
|
+
printc(" {s}", .{@tagName(@as(Immune, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
805
1095
|
},
|
|
806
|
-
.Transform => {
|
|
807
|
-
const source = ID.from(@intCast(
|
|
1096
|
+
.Transform, .CopyBoost => {
|
|
1097
|
+
const source = ID.from(@intCast(a[i]));
|
|
808
1098
|
printc(" {s}({d})", .{ @tagName(source.player), source.id }, a, b, &i, 1, color);
|
|
809
|
-
const target = ID.from(@intCast(
|
|
1099
|
+
const target = ID.from(@intCast(a[i]));
|
|
810
1100
|
printc(" {s}({d})", .{ @tagName(target.player), target.id }, a, b, &i, 1, color);
|
|
811
1101
|
},
|
|
1102
|
+
.Item, .EndItem => {
|
|
1103
|
+
var id = ID.from(@intCast(a[i]));
|
|
1104
|
+
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1105
|
+
printc(" {s}", .{formatter(gen, .Item, a[i])}, a, b, &i, 1, color);
|
|
1106
|
+
if (arg == .Item) {
|
|
1107
|
+
id = ID.from(@intCast(a[i]));
|
|
1108
|
+
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1109
|
+
} else {
|
|
1110
|
+
const reason: EndItem = @enumFromInt(a[i]);
|
|
1111
|
+
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
1112
|
+
}
|
|
1113
|
+
},
|
|
1114
|
+
.SetHP => {
|
|
1115
|
+
const id = ID.from(@intCast(a[i]));
|
|
1116
|
+
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1117
|
+
switch (endian) {
|
|
1118
|
+
.Big => {
|
|
1119
|
+
var hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1120
|
+
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1121
|
+
hp = @as(u16, a[i]) << 8 | @as(u16, a[i + 1]);
|
|
1122
|
+
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
1123
|
+
},
|
|
1124
|
+
.Little => {
|
|
1125
|
+
var hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
1126
|
+
printc(" {d}", .{hp}, a, b, &i, 2, color);
|
|
1127
|
+
hp = @as(u16, a[i + 1]) << 8 | @as(u16, a[i]);
|
|
1128
|
+
printc("/{d}", .{hp}, a, b, &i, 2, color);
|
|
1129
|
+
},
|
|
1130
|
+
}
|
|
1131
|
+
printc(" {s}", .{formatter(gen, .Status, a[i])}, a, b, &i, 1, color);
|
|
1132
|
+
printc(" {s}", .{@tagName(@as(SetHP, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
1133
|
+
},
|
|
1134
|
+
.SideStart => {
|
|
1135
|
+
const id = ID.from(@intCast(a[i]));
|
|
1136
|
+
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1137
|
+
printc(" {s}", .{@tagName(@as(Side, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
1138
|
+
},
|
|
1139
|
+
.SideEnd => {
|
|
1140
|
+
var id = ID.from(@intCast(a[i]));
|
|
1141
|
+
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1142
|
+
const reason: Side = @enumFromInt(a[i]);
|
|
1143
|
+
printc(" {s}", .{@tagName(reason)}, a, b, &i, 1, color);
|
|
1144
|
+
if (reason == .Spikes) {
|
|
1145
|
+
printc(" {s}", .{formatter(gen, .Move, a[i])}, a, b, &i, 1, color);
|
|
1146
|
+
id = ID.from(@intCast(a[i]));
|
|
1147
|
+
printc(" {s}({d})", .{ @tagName(id.player), id.id }, a, b, &i, 1, color);
|
|
1148
|
+
}
|
|
1149
|
+
},
|
|
1150
|
+
.Weather => {
|
|
1151
|
+
printc(" {s}", .{formatter(gen, .Weather, a[i])}, a, b, &i, 1, color);
|
|
1152
|
+
printc(" {s}", .{@tagName(@as(Weather, @enumFromInt(a[i])))}, a, b, &i, 1, color);
|
|
1153
|
+
},
|
|
812
1154
|
else => unreachable,
|
|
813
1155
|
}
|
|
814
1156
|
print("\n", .{});
|
|
@@ -840,12 +1182,13 @@ fn printc(
|
|
|
840
1182
|
}
|
|
841
1183
|
|
|
842
1184
|
pub fn expectLog(
|
|
843
|
-
comptime
|
|
1185
|
+
comptime gen: anytype,
|
|
844
1186
|
expected: []const u8,
|
|
845
1187
|
actual: []const u8,
|
|
846
1188
|
offset: usize,
|
|
847
1189
|
) !void {
|
|
848
1190
|
if (!enabled) return;
|
|
1191
|
+
|
|
849
1192
|
const color = color: {
|
|
850
1193
|
if (std.process.hasEnvVarConstant("ZIG_DEBUG_COLOR")) {
|
|
851
1194
|
break :color true;
|
|
@@ -858,8 +1201,8 @@ pub fn expectLog(
|
|
|
858
1201
|
|
|
859
1202
|
expectEqualBytes(expected, actual, offset) catch |err| switch (err) {
|
|
860
1203
|
error.TestExpectedEqual => {
|
|
861
|
-
format(
|
|
862
|
-
format(
|
|
1204
|
+
format(gen, expected, null, color);
|
|
1205
|
+
format(gen, actual, expected, color);
|
|
863
1206
|
return err;
|
|
864
1207
|
},
|
|
865
1208
|
else => return err,
|
|
@@ -899,49 +1242,71 @@ const gen1 = struct {
|
|
|
899
1242
|
pub const helpers = @import("../gen1/helpers.zig");
|
|
900
1243
|
};
|
|
901
1244
|
|
|
1245
|
+
const gen2 = struct {
|
|
1246
|
+
pub usingnamespace @import("../gen2/data.zig");
|
|
1247
|
+
pub const helpers = @import("../gen2/helpers.zig");
|
|
1248
|
+
};
|
|
1249
|
+
|
|
902
1250
|
var buf: [gen1.LOGS_SIZE]u8 = undefined;
|
|
903
|
-
var stream =
|
|
1251
|
+
var stream: ByteStream = .{ .buffer = &buf };
|
|
904
1252
|
var log: FixedLog = .{ .writer = stream.writer() };
|
|
905
1253
|
|
|
906
|
-
const
|
|
907
|
-
const
|
|
1254
|
+
const M1 = gen1.Move;
|
|
1255
|
+
const S1 = gen1.Species;
|
|
1256
|
+
|
|
1257
|
+
const M2 = gen2.Move;
|
|
1258
|
+
const S2 = gen2.Species;
|
|
1259
|
+
const I2 = gen2.Item;
|
|
1260
|
+
const W2 = gen2.Weather;
|
|
908
1261
|
|
|
909
1262
|
fn expectLog1(expected: []const u8, actual: []const u8) !void {
|
|
910
|
-
return expectLog(
|
|
1263
|
+
return expectLog(gen1, expected, actual, 0);
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
fn expectLog2(expected: []const u8, actual: []const u8) !void {
|
|
1267
|
+
return expectLog(gen2, expected, actual, 0);
|
|
911
1268
|
}
|
|
912
1269
|
|
|
913
|
-
fn
|
|
1270
|
+
fn formatter(comptime gen: anytype, kind: Kind, byte: u8) []const u8 {
|
|
914
1271
|
return switch (kind) {
|
|
915
|
-
.Move => @tagName(@
|
|
916
|
-
.Species => @tagName(@
|
|
917
|
-
.Type => @tagName(@
|
|
918
|
-
.Status =>
|
|
1272
|
+
.Move => @tagName(@as(gen.Move, @enumFromInt(byte))),
|
|
1273
|
+
.Species => @tagName(@as(gen.Species, @enumFromInt(byte))),
|
|
1274
|
+
.Type => @tagName(@as(gen.Type, @enumFromInt(byte))),
|
|
1275
|
+
.Status => gen.Status.name(byte),
|
|
1276
|
+
.Item => if (@hasDecl(gen, "Item"))
|
|
1277
|
+
@tagName(@as(gen.Item, @enumFromInt(byte)))
|
|
1278
|
+
else
|
|
1279
|
+
unreachable,
|
|
1280
|
+
.Weather => if (@hasDecl(gen, "Weather"))
|
|
1281
|
+
@tagName(@as(gen.Weather, @enumFromInt(byte)))
|
|
1282
|
+
else
|
|
1283
|
+
unreachable,
|
|
919
1284
|
};
|
|
920
1285
|
}
|
|
921
1286
|
|
|
922
1287
|
test "|move|" {
|
|
923
|
-
try log.move(p2.ident(4),
|
|
1288
|
+
try log.move(p2.ident(4), M1.Thunderbolt, p1.ident(5), null);
|
|
924
1289
|
try expectLog1(
|
|
925
|
-
&.{ N(ArgType.Move), 0b1100, N(
|
|
1290
|
+
&.{ N(ArgType.Move), 0b1100, N(M1.Thunderbolt), 0b0101, N(Move.None) },
|
|
926
1291
|
buf[0..5],
|
|
927
1292
|
);
|
|
928
1293
|
stream.reset();
|
|
929
1294
|
|
|
930
|
-
try log.move(p2.ident(4),
|
|
931
|
-
const wrap = N(
|
|
1295
|
+
try log.move(p2.ident(4), M1.Wrap, p1.ident(5), M1.Wrap);
|
|
1296
|
+
const wrap = N(M1.Wrap);
|
|
932
1297
|
try expectLog1(
|
|
933
1298
|
&.{ N(ArgType.Move), 0b1100, wrap, 0b0101, N(Move.From), wrap },
|
|
934
1299
|
buf[0..6],
|
|
935
1300
|
);
|
|
936
1301
|
stream.reset();
|
|
937
1302
|
|
|
938
|
-
try log.move(p2.ident(4),
|
|
1303
|
+
try log.move(p2.ident(4), M1.SkullBash, .{}, null);
|
|
939
1304
|
try log.laststill();
|
|
940
1305
|
try expectLog1(
|
|
941
1306
|
&.{
|
|
942
1307
|
N(ArgType.Move),
|
|
943
1308
|
0b1100,
|
|
944
|
-
N(
|
|
1309
|
+
N(M1.SkullBash),
|
|
945
1310
|
0,
|
|
946
1311
|
N(Move.None),
|
|
947
1312
|
N(ArgType.LastStill),
|
|
@@ -950,13 +1315,13 @@ test "|move|" {
|
|
|
950
1315
|
);
|
|
951
1316
|
stream.reset();
|
|
952
1317
|
|
|
953
|
-
try log.move(p2.ident(4),
|
|
1318
|
+
try log.move(p2.ident(4), M1.Tackle, p1.ident(5), null);
|
|
954
1319
|
try log.lastmiss();
|
|
955
1320
|
try expectLog1(
|
|
956
1321
|
&.{
|
|
957
1322
|
N(ArgType.Move),
|
|
958
1323
|
0b1100,
|
|
959
|
-
N(
|
|
1324
|
+
N(M1.Tackle),
|
|
960
1325
|
0b0101,
|
|
961
1326
|
N(Move.None),
|
|
962
1327
|
N(ArgType.LastMiss),
|
|
@@ -975,8 +1340,8 @@ test "|switch|" {
|
|
|
975
1340
|
try log.switched(p2.ident(3), &snorlax);
|
|
976
1341
|
const par = 0b1000000;
|
|
977
1342
|
var expected: []const u8 = switch (endian) {
|
|
978
|
-
.Big => &.{ N(ArgType.Switch), 0b1011, N(
|
|
979
|
-
.Little => &.{ N(ArgType.Switch), 0b1011, N(
|
|
1343
|
+
.Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 0, 200, 1, 144, par },
|
|
1344
|
+
.Little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 91, 200, 0, 144, 1, par },
|
|
980
1345
|
};
|
|
981
1346
|
try expectLog1(expected, buf[0..9]);
|
|
982
1347
|
stream.reset();
|
|
@@ -986,8 +1351,8 @@ test "|switch|" {
|
|
|
986
1351
|
snorlax.status = 0;
|
|
987
1352
|
try log.switched(p2.ident(3), &snorlax);
|
|
988
1353
|
expected = switch (endian) {
|
|
989
|
-
.Big => &.{ N(ArgType.Switch), 0b1011, N(
|
|
990
|
-
.Little => &.{ N(ArgType.Switch), 0b1011, N(
|
|
1354
|
+
.Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 1, 144, 0 },
|
|
1355
|
+
.Little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 0, 0, 144, 1, 0 },
|
|
991
1356
|
};
|
|
992
1357
|
try expectLog1(expected, buf[0..9]);
|
|
993
1358
|
stream.reset();
|
|
@@ -995,11 +1360,30 @@ test "|switch|" {
|
|
|
995
1360
|
snorlax.hp = 400;
|
|
996
1361
|
try log.switched(p2.ident(3), &snorlax);
|
|
997
1362
|
expected = switch (endian) {
|
|
998
|
-
.Big => &.{ N(ArgType.Switch), 0b1011, N(
|
|
999
|
-
.Little => &.{ N(ArgType.Switch), 0b1011, N(
|
|
1363
|
+
.Big => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 1, 144, 1, 144, 0 },
|
|
1364
|
+
.Little => &.{ N(ArgType.Switch), 0b1011, N(S1.Snorlax), 100, 144, 1, 144, 1, 0 },
|
|
1000
1365
|
};
|
|
1001
1366
|
try expectLog1(expected, buf[0..9]);
|
|
1002
1367
|
stream.reset();
|
|
1368
|
+
|
|
1369
|
+
var blissey = gen2.helpers.Pokemon.init(.{ .species = .Blissey, .moves = &.{.Splash} });
|
|
1370
|
+
blissey.level = 91;
|
|
1371
|
+
blissey.hp = 200;
|
|
1372
|
+
blissey.stats.hp = 400;
|
|
1373
|
+
blissey.status = gen2.Status.init(.PAR);
|
|
1374
|
+
try log.switched(p2.ident(3), &blissey);
|
|
1375
|
+
expected = &(.{
|
|
1376
|
+
N(ArgType.Switch),
|
|
1377
|
+
0b1011,
|
|
1378
|
+
N(S2.Blissey),
|
|
1379
|
+
N(gen2.Gender.Female),
|
|
1380
|
+
91,
|
|
1381
|
+
} ++ switch (endian) {
|
|
1382
|
+
.Big => .{ 0, 200, 1, 144, par },
|
|
1383
|
+
.Little => .{ 200, 0, 144, 1, par },
|
|
1384
|
+
});
|
|
1385
|
+
try expectLog2(expected, buf[0..10]);
|
|
1386
|
+
stream.reset();
|
|
1003
1387
|
}
|
|
1004
1388
|
|
|
1005
1389
|
test "|cant|" {
|
|
@@ -1007,8 +1391,8 @@ test "|cant|" {
|
|
|
1007
1391
|
try expectLog1(&.{ N(ArgType.Cant), 0b1110, N(Cant.Bound) }, buf[0..3]);
|
|
1008
1392
|
stream.reset();
|
|
1009
1393
|
|
|
1010
|
-
try log.disabled(p1.ident(2),
|
|
1011
|
-
try expectLog1(&.{ N(ArgType.Cant), 2, N(Cant.Disable), N(
|
|
1394
|
+
try log.disabled(p1.ident(2), M1.Earthquake);
|
|
1395
|
+
try expectLog1(&.{ N(ArgType.Cant), 2, N(Cant.Disable), N(M1.Earthquake) }, buf[0..4]);
|
|
1012
1396
|
stream.reset();
|
|
1013
1397
|
}
|
|
1014
1398
|
|
|
@@ -1118,9 +1502,9 @@ test "|-status|" {
|
|
|
1118
1502
|
try expectLog1(&.{ N(ArgType.Status), 0b1010, 0b1000, N(Status.Silent) }, buf[0..4]);
|
|
1119
1503
|
stream.reset();
|
|
1120
1504
|
|
|
1121
|
-
try log.statusFrom(p1.ident(1), gen1.Status.init(.PAR),
|
|
1505
|
+
try log.statusFrom(p1.ident(1), gen1.Status.init(.PAR), M1.BodySlam);
|
|
1122
1506
|
try expectLog1(
|
|
1123
|
-
&.{ N(ArgType.Status), 0b0001, 0b1000000, N(Status.From), N(
|
|
1507
|
+
&.{ N(ArgType.Status), 0b0001, 0b1000000, N(Status.From), N(M1.BodySlam) },
|
|
1124
1508
|
buf[0..5],
|
|
1125
1509
|
);
|
|
1126
1510
|
stream.reset();
|
|
@@ -1191,8 +1575,8 @@ test "|-hitcount|" {
|
|
|
1191
1575
|
}
|
|
1192
1576
|
|
|
1193
1577
|
test "|-prepare|" {
|
|
1194
|
-
try log.prepare(p2.ident(2),
|
|
1195
|
-
try expectLog1(&.{ N(ArgType.Prepare), 0b1010, N(
|
|
1578
|
+
try log.prepare(p2.ident(2), M1.Dig);
|
|
1579
|
+
try expectLog1(&.{ N(ArgType.Prepare), 0b1010, N(M1.Dig) }, buf[0..3]);
|
|
1196
1580
|
stream.reset();
|
|
1197
1581
|
}
|
|
1198
1582
|
|
|
@@ -1249,12 +1633,12 @@ test "|-start|" {
|
|
|
1249
1633
|
);
|
|
1250
1634
|
stream.reset();
|
|
1251
1635
|
|
|
1252
|
-
try log.startEffect(p1.ident(2), .Disable,
|
|
1253
|
-
try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Disable), N(
|
|
1636
|
+
try log.startEffect(p1.ident(2), .Disable, M1.Surf);
|
|
1637
|
+
try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Disable), N(M1.Surf) }, buf[0..4]);
|
|
1254
1638
|
stream.reset();
|
|
1255
1639
|
|
|
1256
|
-
try log.startEffect(p1.ident(2), .Mimic,
|
|
1257
|
-
try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Mimic), N(
|
|
1640
|
+
try log.startEffect(p1.ident(2), .Mimic, M1.Surf);
|
|
1641
|
+
try expectLog1(&.{ N(ArgType.Start), 0b0010, N(Start.Mimic), N(M1.Surf) }, buf[0..4]);
|
|
1258
1642
|
stream.reset();
|
|
1259
1643
|
}
|
|
1260
1644
|
|
|
@@ -1273,21 +1657,25 @@ test "|-ohko|" {
|
|
|
1273
1657
|
try expectLog1(&.{N(ArgType.OHKO)}, buf[0..1]);
|
|
1274
1658
|
stream.reset();
|
|
1275
1659
|
}
|
|
1660
|
+
|
|
1276
1661
|
test "|-crit|" {
|
|
1277
1662
|
try log.crit(p2.ident(5));
|
|
1278
1663
|
try expectLog1(&.{ N(ArgType.Crit), 0b1101 }, buf[0..2]);
|
|
1279
1664
|
stream.reset();
|
|
1280
1665
|
}
|
|
1666
|
+
|
|
1281
1667
|
test "|-supereffective|" {
|
|
1282
1668
|
try log.supereffective(p1.ident(1));
|
|
1283
1669
|
try expectLog1(&.{ N(ArgType.SuperEffective), 0b0001 }, buf[0..2]);
|
|
1284
1670
|
stream.reset();
|
|
1285
1671
|
}
|
|
1672
|
+
|
|
1286
1673
|
test "|-resisted|" {
|
|
1287
1674
|
try log.resisted(p2.ident(2));
|
|
1288
1675
|
try expectLog1(&.{ N(ArgType.Resisted), 0b1010 }, buf[0..2]);
|
|
1289
1676
|
stream.reset();
|
|
1290
1677
|
}
|
|
1678
|
+
|
|
1291
1679
|
test "|-immune|" {
|
|
1292
1680
|
try log.immune(p1.ident(3), .None);
|
|
1293
1681
|
try expectLog1(&.{ N(ArgType.Immune), 0b0011, N(Immune.None) }, buf[0..3]);
|
|
@@ -1297,8 +1685,125 @@ test "|-immune|" {
|
|
|
1297
1685
|
try expectLog1(&.{ N(ArgType.Immune), 0b1010, N(Immune.OHKO) }, buf[0..3]);
|
|
1298
1686
|
stream.reset();
|
|
1299
1687
|
}
|
|
1688
|
+
|
|
1300
1689
|
test "|-transform|" {
|
|
1301
1690
|
try log.transform(p2.ident(4), p1.ident(5));
|
|
1302
1691
|
try expectLog1(&.{ N(ArgType.Transform), 0b1100, 0b0101 }, buf[0..3]);
|
|
1303
1692
|
stream.reset();
|
|
1304
1693
|
}
|
|
1694
|
+
|
|
1695
|
+
test "|drag|" {
|
|
1696
|
+
var blissey = gen2.helpers.Pokemon.init(.{ .species = .Blissey, .moves = &.{.Splash} });
|
|
1697
|
+
blissey.level = 91;
|
|
1698
|
+
blissey.hp = 200;
|
|
1699
|
+
blissey.stats.hp = 400;
|
|
1700
|
+
blissey.status = gen2.Status.init(.PAR);
|
|
1701
|
+
try log.drag(p2.ident(3), &blissey);
|
|
1702
|
+
const par = 0b1000000;
|
|
1703
|
+
const expected = &(.{
|
|
1704
|
+
N(ArgType.Drag),
|
|
1705
|
+
0b1011,
|
|
1706
|
+
N(S2.Blissey),
|
|
1707
|
+
N(gen2.Gender.Female),
|
|
1708
|
+
91,
|
|
1709
|
+
} ++ switch (endian) {
|
|
1710
|
+
.Big => .{ 0, 200, 1, 144, par },
|
|
1711
|
+
.Little => .{ 200, 0, 144, 1, par },
|
|
1712
|
+
});
|
|
1713
|
+
try expectLog2(expected, buf[0..10]);
|
|
1714
|
+
stream.reset();
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
test "|-item|" {
|
|
1718
|
+
try log.item(p2.ident(2), I2.GoldBerry, p1.ident(4));
|
|
1719
|
+
try expectLog2(&.{ N(ArgType.Item), 0b1010, N(I2.GoldBerry), 0b0100 }, buf[0..4]);
|
|
1720
|
+
stream.reset();
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
test "|-enditem|" {
|
|
1724
|
+
try log.enditem(p1.ident(1), I2.BerserkGene, .None);
|
|
1725
|
+
try expectLog2(&.{ N(ArgType.EndItem), 0b0001, N(I2.BerserkGene), N(EndItem.None) }, buf[0..4]);
|
|
1726
|
+
stream.reset();
|
|
1727
|
+
|
|
1728
|
+
try log.enditem(p2.ident(4), I2.PRZCureBerry, .Eat);
|
|
1729
|
+
try expectLog2(&.{ N(ArgType.EndItem), 0b1100, N(I2.PRZCureBerry), N(EndItem.Eat) }, buf[0..4]);
|
|
1730
|
+
stream.reset();
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
test "|-cureteam|" {
|
|
1734
|
+
try log.cureteam(p2.ident(5));
|
|
1735
|
+
try expectLog2(&.{ N(ArgType.CureTeam), 0b1101 }, buf[0..2]);
|
|
1736
|
+
stream.reset();
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
test "|-sethp|" {
|
|
1740
|
+
var blissey = gen2.helpers.Pokemon.init(.{ .species = .Blissey, .moves = &.{.PainSplit} });
|
|
1741
|
+
blissey.hp = 612;
|
|
1742
|
+
try log.sethp(p2.ident(2), &blissey, .Silent);
|
|
1743
|
+
var expected: []const u8 = switch (endian) {
|
|
1744
|
+
.Big => &.{ N(ArgType.SetHP), 0b1010, 2, 100, 2, 201, 0, N(SetHP.Silent) },
|
|
1745
|
+
.Little => &.{ N(ArgType.SetHP), 0b1010, 100, 2, 201, 2, 0, N(SetHP.Silent) },
|
|
1746
|
+
};
|
|
1747
|
+
try expectLog2(expected, buf[0..8]);
|
|
1748
|
+
stream.reset();
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
test "|-setboost|" {
|
|
1752
|
+
try log.setboost(p2.ident(6), 6);
|
|
1753
|
+
try expectLog2(&.{ N(ArgType.SetBoost), 0b1110, 12 }, buf[0..3]);
|
|
1754
|
+
stream.reset();
|
|
1755
|
+
|
|
1756
|
+
try log.setboost(p2.ident(3), 2);
|
|
1757
|
+
try expectLog2(&.{ N(ArgType.SetBoost), 0b1011, 8 }, buf[0..3]);
|
|
1758
|
+
stream.reset();
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
test "|-copyboost|" {
|
|
1762
|
+
try log.copyboost(p2.ident(3), p1.ident(6));
|
|
1763
|
+
try expectLog2(&.{ N(ArgType.CopyBoost), 0b1011, 0b0110 }, buf[0..3]);
|
|
1764
|
+
stream.reset();
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
test "|-sidestart|" {
|
|
1768
|
+
try log.sidestart(.P2, .Reflect);
|
|
1769
|
+
try expectLog2(&.{ N(ArgType.SideStart), 1, N(Side.Reflect) }, buf[0..3]);
|
|
1770
|
+
stream.reset();
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
test "|-sideend|" {
|
|
1774
|
+
try log.sideend(.P2, .LightScreen);
|
|
1775
|
+
try expectLog2(&.{ N(ArgType.SideEnd), 1, N(Side.LightScreen) }, buf[0..3]);
|
|
1776
|
+
stream.reset();
|
|
1777
|
+
|
|
1778
|
+
try log.spikesend(.P1, M2.RapidSpin, p1.ident(3));
|
|
1779
|
+
try expectLog2(&.{
|
|
1780
|
+
N(ArgType.SideEnd),
|
|
1781
|
+
0,
|
|
1782
|
+
N(Side.Spikes),
|
|
1783
|
+
N(M2.RapidSpin),
|
|
1784
|
+
0b0011,
|
|
1785
|
+
}, buf[0..5]);
|
|
1786
|
+
stream.reset();
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
test "|-singlemove|" {
|
|
1790
|
+
try log.singlemove(p2.ident(2), M2.DestinyBond);
|
|
1791
|
+
try expectLog2(&.{ N(ArgType.SingleMove), 0b1010, N(M2.DestinyBond) }, buf[0..3]);
|
|
1792
|
+
stream.reset();
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
test "|-singleturn|" {
|
|
1796
|
+
try log.singleturn(p1.ident(3), M2.Protect);
|
|
1797
|
+
try expectLog2(&.{ N(ArgType.SingleTurn), 0b0011, N(M2.Protect) }, buf[0..3]);
|
|
1798
|
+
stream.reset();
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
test "|-weather|" {
|
|
1802
|
+
try log.weather(W2.Rain, .Upkeep);
|
|
1803
|
+
try expectLog2(&.{ N(ArgType.Weather), N(W2.Rain), N(Weather.Upkeep) }, buf[0..3]);
|
|
1804
|
+
stream.reset();
|
|
1805
|
+
|
|
1806
|
+
try log.weather(W2.None, .None);
|
|
1807
|
+
try expectLog2(&.{ N(ArgType.Weather), N(W2.None), N(Weather.None) }, buf[0..3]);
|
|
1808
|
+
stream.reset();
|
|
1809
|
+
}
|