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