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