@pkmn/engine 0.1.0-dev.d3e796d5 → 0.1.0-dev.d56bdadd

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.
@@ -0,0 +1,808 @@
1
+ //! Code generated by `tools/generate` - manual edits will be overwritten.
2
+
3
+ const std = @import("std");
4
+
5
+ const common = @import("../common/data.zig");
6
+
7
+ const data = @import("data.zig");
8
+ const mechanics = @import("mechanics.zig");
9
+
10
+ const assert = std.debug.assert;
11
+
12
+ const Player = common.Player;
13
+ const Result = common.Result;
14
+
15
+ const Effectiveness = data.Effectiveness;
16
+ const Move = data.Move;
17
+
18
+ const Effects = mechanics.Effects;
19
+ const State = mechanics.State;
20
+
21
+ const canMove = mechanics.canMove;
22
+ const canCharge = mechanics.canCharge;
23
+ const decrementPP = mechanics.decrementPP;
24
+ const doMove = mechanics.doMove;
25
+ const checkHit = mechanics.checkHit;
26
+ const checkCriticalHit = mechanics.checkCriticalHit;
27
+ const calcDamage = mechanics.calcDamage;
28
+ const adjustDamage = mechanics.adjustDamage;
29
+ const randomizeDamage = mechanics.randomizeDamage;
30
+ const applyDamage = mechanics.applyDamage;
31
+ const reportOutcome = mechanics.reportOutcome;
32
+ const effectChance = mechanics.effectChance;
33
+ const afterMove = mechanics.afterMove;
34
+ const buildRage = mechanics.buildRage;
35
+ const kingsRock = mechanics.kingsRock;
36
+ const destinyBond = mechanics.destinyBond;
37
+
38
+ const SECONDARY = true;
39
+ const KINGS = true;
40
+
41
+ pub fn runMove(battle: anytype, player: Player, state: *State, options: anytype) !void {
42
+ var log = options.log;
43
+
44
+ var side = battle.side(player);
45
+ var volatiles = &side.active.volatiles;
46
+
47
+ const ident = battle.active(player);
48
+ const foe_ident = battle.active(player.foe());
49
+
50
+ const move = Move.get(state.move);
51
+ switch (move.effect) {
52
+ .AlwaysHit, .HighCritical, .Priority, .JumpKick, .None => {
53
+ if (!try canMove(battle, player, state, options)) return;
54
+ if (!try doMove(!SECONDARY, battle, player, state, options)) return;
55
+ _ = try afterMove(KINGS, battle, player, state, options);
56
+ },
57
+ .DoubleHit, .MultiHit => {
58
+ if (!try canMove(battle, player, state, options)) return;
59
+ // TODO startloop
60
+ try checkHit(battle, player, state, options);
61
+ try checkCriticalHit(battle, player, state, options);
62
+ try calcDamage(battle, player, state, options);
63
+ try adjustDamage(battle, player, state, options);
64
+ try randomizeDamage(battle, player, state, options);
65
+
66
+ if (state.miss) state.damage = 0;
67
+
68
+ try applyDamage(battle, player, state, options);
69
+ // TODO critsupereffectivelooptext
70
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
71
+ // TODO endloop
72
+ try kingsRock(battle, player, state, options);
73
+ },
74
+ .PayDay => {
75
+ if (!try canMove(battle, player, state, options)) return;
76
+ if (!try doMove(!SECONDARY, battle, player, state, options)) return;
77
+ try Effects.payDay(battle, player, state, options);
78
+ _ = try afterMove(KINGS, battle, player, state, options);
79
+ },
80
+ .BurnChance => {
81
+ if (!try canMove(battle, player, state, options)) return;
82
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
83
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
84
+ try Effects.burnChance(battle, player, state, options);
85
+ },
86
+ .FreezeChance => {
87
+ if (!try canMove(battle, player, state, options)) return;
88
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
89
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
90
+ try Effects.freezeChance(battle, player, state, options);
91
+ },
92
+ .ParalyzeChance => {
93
+ if (!try canMove(battle, player, state, options)) return;
94
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
95
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
96
+ try Effects.paralyzeChance(battle, player, state, options);
97
+ },
98
+ .OHKO => {
99
+ if (!try canMove(battle, player, state, options)) return;
100
+ try Effects.ohko.immune(battle, player, state, options);
101
+ try Effects.ohko.damage(battle, player, state, options);
102
+ try applyDamage(battle, player, state, options);
103
+ try reportOutcome(battle, player, state, options);
104
+ _ = try afterMove(!KINGS, battle, player, state, options);
105
+ },
106
+ .Gust => {
107
+ if (!try canMove(battle, player, state, options)) return;
108
+ try checkCriticalHit(battle, player, state, options);
109
+ try calcDamage(battle, player, state, options);
110
+ try adjustDamage(battle, player, state, options);
111
+ try randomizeDamage(battle, player, state, options);
112
+ try Effects.double.flying(battle, player, state, options);
113
+ try checkHit(battle, player, state, options);
114
+ try applyDamage(battle, player, state, options);
115
+ try reportOutcome(battle, player, state, options);
116
+ _ = try afterMove(!KINGS, battle, player, state, options);
117
+ },
118
+ .ForceSwitch => {
119
+ if (!try canMove(battle, player, state, options)) return;
120
+ try checkHit(battle, player, state, options);
121
+ try Effects.forceSwitch(battle, player, state, options);
122
+ },
123
+ .RazorWind, .SolarBeam, .FlyDig => {
124
+ if (!try canCharge(battle, player, state, options)) return;
125
+ if (!try doMove(!SECONDARY, battle, player, state, options)) return;
126
+ _ = try afterMove(KINGS, battle, player, state, options);
127
+ },
128
+ .Binding => {
129
+ if (!try canMove(battle, player, state, options)) return;
130
+ try checkHit(battle, player, state, options);
131
+ try checkCriticalHit(battle, player, state, options);
132
+ try calcDamage(battle, player, state, options);
133
+ try adjustDamage(battle, player, state, options);
134
+ try randomizeDamage(battle, player, state, options);
135
+
136
+ if (state.miss) state.damage = 0;
137
+
138
+ try applyDamage(battle, player, state, options);
139
+ try reportOutcome(battle, player, state, options);
140
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
141
+ try Effects.binding(battle, player, state, options);
142
+ },
143
+ .Stomp => {
144
+ if (!try canMove(battle, player, state, options)) return;
145
+ try checkCriticalHit(battle, player, state, options);
146
+ try calcDamage(battle, player, state, options);
147
+ try adjustDamage(battle, player, state, options);
148
+ try randomizeDamage(battle, player, state, options);
149
+ try Effects.double.minimize(battle, player, state, options);
150
+ try checkHit(battle, player, state, options);
151
+ try effectChance(battle, player, state, options);
152
+ try applyDamage(battle, player, state, options);
153
+ try reportOutcome(battle, player, state, options);
154
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
155
+ try Effects.flinchChance(battle, player, state, options);
156
+ },
157
+ .FlinchChance => {
158
+ if (!try canMove(battle, player, state, options)) return;
159
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
160
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
161
+ try Effects.flinchChance(battle, player, state, options);
162
+ },
163
+ .Recoil => {
164
+ if (!try canMove(battle, player, state, options)) return;
165
+ if (!try doMove(!SECONDARY, battle, player, state, options)) return;
166
+ try Effects.recoil(battle, player, state, options);
167
+ _ = try afterMove(KINGS, battle, player, state, options);
168
+ },
169
+ .Thrashing => {
170
+ // TODO checkrampage
171
+ // doturn
172
+ const charging = false; // TODO
173
+ const skip_pp = charging or state.move == .Struggle or
174
+ (volatiles.BeatUp or volatiles.Thrashing or volatiles.Bide);
175
+ if (!skip_pp) _ = decrementPP(side, state.move, state.mslot); // TODO if no pp return
176
+ // TODO rampage
177
+ // usedmovetext
178
+ try log.move(ident, state.move, foe_ident); // FIXME self? from?
179
+ try checkHit(battle, player, state, options);
180
+ try checkCriticalHit(battle, player, state, options);
181
+ try calcDamage(battle, player, state, options);
182
+ try adjustDamage(battle, player, state, options);
183
+ try randomizeDamage(battle, player, state, options);
184
+
185
+ if (state.miss) state.damage = 0;
186
+
187
+ try applyDamage(battle, player, state, options);
188
+ try reportOutcome(battle, player, state, options);
189
+ _ = try afterMove(KINGS, battle, player, state, options);
190
+ },
191
+ .PoisonChance => {
192
+ if (!try canMove(battle, player, state, options)) return;
193
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
194
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
195
+ try Effects.poisonChance(battle, player, state, options);
196
+ },
197
+ .Twineedle => {
198
+ if (!try canMove(battle, player, state, options)) return;
199
+ // TODO startloop
200
+ try checkHit(battle, player, state, options);
201
+ try effectChance(battle, player, state, options);
202
+ try checkCriticalHit(battle, player, state, options);
203
+ try calcDamage(battle, player, state, options);
204
+ try adjustDamage(battle, player, state, options);
205
+ try randomizeDamage(battle, player, state, options);
206
+
207
+ if (state.miss) state.damage = 0;
208
+
209
+ try applyDamage(battle, player, state, options);
210
+ // TODO critsupereffectivelooptext
211
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
212
+ // TODO endloop
213
+ try kingsRock(battle, player, state, options);
214
+ try Effects.poisonChance(battle, player, state, options);
215
+ },
216
+ .Sleep => {
217
+ if (!try canMove(battle, player, state, options)) return;
218
+ try checkHit(battle, player, state, options);
219
+ // TODO checksafeguard
220
+ try Effects.sleep(battle, player, state, options);
221
+ },
222
+ .Confusion => {
223
+ if (!try canMove(battle, player, state, options)) return;
224
+ try checkHit(battle, player, state, options);
225
+ // TODO checksafeguard
226
+ try Effects.confusion(battle, player, state, options);
227
+ },
228
+ .SuperFang, .LevelDamage, .Psywave, .FixedDamage => {
229
+ if (!try canMove(battle, player, state, options)) return;
230
+ try Effects.fixedDamage(battle, player, state, options);
231
+ try checkHit(battle, player, state, options);
232
+
233
+ if (state.immune()) {
234
+ state.damage = 0;
235
+ state.miss = true;
236
+ }
237
+ state.effectiveness = Effectiveness.neutral;
238
+
239
+ try applyDamage(battle, player, state, options);
240
+ _ = try afterMove(KINGS, battle, player, state, options);
241
+ },
242
+ .Disable => {
243
+ if (!try canMove(battle, player, state, options)) return;
244
+ try checkHit(battle, player, state, options);
245
+ try Effects.disable(battle, player, state, options);
246
+ },
247
+ .Mist => {
248
+ if (!try canMove(battle, player, state, options)) return;
249
+ try Effects.mist(battle, player, state, options);
250
+ },
251
+ .ConfusionChance => {
252
+ if (!try canMove(battle, player, state, options)) return;
253
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
254
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
255
+ try Effects.confusionChance(battle, player, state, options);
256
+ },
257
+ .HyperBeam => {
258
+ if (!try canMove(battle, player, state, options)) return;
259
+ if (!try doMove(!SECONDARY, battle, player, state, options)) return;
260
+ try Effects.hyperBeam(battle, player, state, options);
261
+ _ = try afterMove(!KINGS, battle, player, state, options);
262
+ },
263
+ .MirrorCoat, .Counter => {
264
+ if (!try canMove(battle, player, state, options)) return;
265
+ try Effects.counter(battle, player, state, options);
266
+ try applyDamage(battle, player, state, options);
267
+ _ = try afterMove(KINGS, battle, player, state, options);
268
+ },
269
+ .DreamEater, .DrainHP => {
270
+ if (!try canMove(battle, player, state, options)) return;
271
+ if (!try doMove(!SECONDARY, battle, player, state, options)) return;
272
+ try Effects.drainHP(battle, player, state, options);
273
+ _ = try afterMove(KINGS, battle, player, state, options);
274
+ },
275
+ .LeechSeed => {
276
+ if (!try canMove(battle, player, state, options)) return;
277
+ try checkHit(battle, player, state, options);
278
+ try Effects.leechSeed(battle, player, state, options);
279
+ },
280
+ .Toxic, .Poison => {
281
+ if (!try canMove(battle, player, state, options)) return;
282
+ try checkHit(battle, player, state, options);
283
+ try adjustDamage(battle, player, state, options);
284
+ // TODO checksafeguard
285
+ try Effects.poison(battle, player, state, options);
286
+ },
287
+ .Paralyze => {
288
+ if (!try canMove(battle, player, state, options)) return;
289
+ try adjustDamage(battle, player, state, options);
290
+ try checkHit(battle, player, state, options);
291
+ // TODO checksafeguard
292
+ try Effects.paralyze(battle, player, state, options);
293
+ },
294
+ .Thunder => {
295
+ if (!try canMove(battle, player, state, options)) return;
296
+ try checkCriticalHit(battle, player, state, options);
297
+ try calcDamage(battle, player, state, options);
298
+ try checkHit(battle, player, state, options);
299
+ try effectChance(battle, player, state, options);
300
+ try adjustDamage(battle, player, state, options);
301
+ try randomizeDamage(battle, player, state, options);
302
+ try applyDamage(battle, player, state, options);
303
+ try reportOutcome(battle, player, state, options);
304
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
305
+ try Effects.paralyzeChance(battle, player, state, options);
306
+ },
307
+ .Earthquake => {
308
+ if (!try canMove(battle, player, state, options)) return;
309
+ try checkCriticalHit(battle, player, state, options);
310
+ try calcDamage(battle, player, state, options);
311
+ try adjustDamage(battle, player, state, options);
312
+ try randomizeDamage(battle, player, state, options);
313
+ try Effects.double.underground(battle, player, state, options);
314
+ try checkHit(battle, player, state, options);
315
+ try effectChance(battle, player, state, options);
316
+ try applyDamage(battle, player, state, options);
317
+ try reportOutcome(battle, player, state, options);
318
+ _ = try afterMove(!KINGS, battle, player, state, options);
319
+ },
320
+ .Rage => {
321
+ if (!try canMove(battle, player, state, options)) return;
322
+ try checkCriticalHit(battle, player, state, options);
323
+ try calcDamage(battle, player, state, options);
324
+ try adjustDamage(battle, player, state, options);
325
+ try checkHit(battle, player, state, options);
326
+ try Effects.rage.damage(battle, player, state, options);
327
+ try randomizeDamage(battle, player, state, options);
328
+ // TODO failuretext
329
+ try Effects.rage.start(battle, player, state, options);
330
+ try applyDamage(battle, player, state, options);
331
+ try reportOutcome(battle, player, state, options);
332
+ _ = try afterMove(KINGS, battle, player, state, options);
333
+ },
334
+ .Teleport => {
335
+ if (!try canMove(battle, player, state, options)) return;
336
+ try Effects.teleport(battle, player, state, options);
337
+ },
338
+ .Mimic => {
339
+ if (!try canMove(battle, player, state, options)) return;
340
+ try checkHit(battle, player, state, options);
341
+ try Effects.mimic(battle, player, state, options);
342
+ },
343
+ .Heal => {
344
+ if (!try canMove(battle, player, state, options)) return;
345
+ try Effects.heal(battle, player, state, options);
346
+ },
347
+ .LightScreen => {
348
+ if (!try canMove(battle, player, state, options)) return;
349
+ try Effects.lightScreen(battle, player, state, options);
350
+ },
351
+ .Haze => {
352
+ if (!try canMove(battle, player, state, options)) return;
353
+ try Effects.haze(battle, player, state, options);
354
+ },
355
+ .Reflect => {
356
+ if (!try canMove(battle, player, state, options)) return;
357
+ try Effects.reflect(battle, player, state, options);
358
+ },
359
+ .FocusEnergy => {
360
+ if (!try canMove(battle, player, state, options)) return;
361
+ try Effects.focusEnergy(battle, player, state, options);
362
+ },
363
+ .Bide => {
364
+ try Effects.bide.store(battle, player, state, options);
365
+ // doturn
366
+ const charging = false; // TODO
367
+ const skip_pp = charging or state.move == .Struggle or
368
+ (volatiles.BeatUp or volatiles.Thrashing or volatiles.Bide);
369
+ if (!skip_pp) _ = decrementPP(side, state.move, state.mslot); // TODO if no pp return
370
+ // usedmovetext
371
+ try log.move(ident, state.move, foe_ident); // FIXME self? from?
372
+ try Effects.bide.unleash(battle, player, state, options);
373
+
374
+ if (state.immune()) {
375
+ state.damage = 0;
376
+ state.miss = true;
377
+ }
378
+ state.effectiveness = Effectiveness.neutral;
379
+
380
+ try checkHit(battle, player, state, options);
381
+ // TODO bidefailtext
382
+ try applyDamage(battle, player, state, options);
383
+ _ = try afterMove(KINGS, battle, player, state, options);
384
+ },
385
+ .Metronome => {
386
+ if (!try canMove(battle, player, state, options)) return;
387
+ try Effects.metronome(battle, player, state, options);
388
+ },
389
+ .MirrorMove => {
390
+ if (!try canMove(battle, player, state, options)) return;
391
+ try Effects.mirrorMove(battle, player, state, options);
392
+ },
393
+ .Explode => {
394
+ if (!try canMove(battle, player, state, options)) return;
395
+ try checkCriticalHit(battle, player, state, options);
396
+ try calcDamage(battle, player, state, options);
397
+ try adjustDamage(battle, player, state, options);
398
+ try randomizeDamage(battle, player, state, options);
399
+ try checkHit(battle, player, state, options);
400
+ try Effects.explode(battle, player, state, options);
401
+ try applyDamage(battle, player, state, options);
402
+ try reportOutcome(battle, player, state, options);
403
+ _ = try afterMove(KINGS, battle, player, state, options);
404
+ },
405
+ .SkullBash => {
406
+ if (!try canCharge(battle, player, state, options)) return;
407
+ if (!try doMove(!SECONDARY, battle, player, state, options)) return;
408
+ if (!try afterMove(KINGS, battle, player, state, options)) return;
409
+ // TODO endturn
410
+ try Effects.boost(battle, player, state, options);
411
+ },
412
+ .SkyAttack => {
413
+ if (!try canCharge(battle, player, state, options)) return;
414
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
415
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
416
+ try Effects.flinchChance(battle, player, state, options);
417
+ try kingsRock(battle, player, state, options);
418
+ },
419
+ .Transform => {
420
+ if (!try canMove(battle, player, state, options)) return;
421
+ try Effects.transform(battle, player, state, options);
422
+ },
423
+ .Splash => {
424
+ if (!try canMove(battle, player, state, options)) return;
425
+ try Effects.splash(battle, player, state, options);
426
+ },
427
+ .Conversion => {
428
+ if (!try canMove(battle, player, state, options)) return;
429
+ try Effects.conversion(battle, player, state, options);
430
+ },
431
+ .TriAttack => {
432
+ if (!try canMove(battle, player, state, options)) return;
433
+ if (!try doMove(!SECONDARY, battle, player, state, options)) return;
434
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
435
+ try Effects.triAttack(battle, player, state, options);
436
+ },
437
+ .Substitute => {
438
+ if (!try canMove(battle, player, state, options)) return;
439
+ try Effects.substitute(battle, player, state, options);
440
+ },
441
+ .Sketch => {
442
+ if (!try canMove(battle, player, state, options)) return;
443
+ try Effects.sketch(battle, player, state, options);
444
+ },
445
+ .TripleKick => {
446
+ if (!try canMove(battle, player, state, options)) return;
447
+ // TODO startloop
448
+ try checkHit(battle, player, state, options);
449
+ try checkCriticalHit(battle, player, state, options);
450
+ try calcDamage(battle, player, state, options);
451
+ try Effects.tripleKick(battle, player, state, options);
452
+ try adjustDamage(battle, player, state, options);
453
+ try randomizeDamage(battle, player, state, options);
454
+
455
+ if (state.miss) state.damage = 0;
456
+
457
+ try applyDamage(battle, player, state, options);
458
+ // TODO critsupereffectivelooptext
459
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
460
+ // TODO kickcounter
461
+ // TODO endloop
462
+ try kingsRock(battle, player, state, options);
463
+ },
464
+ .Thief => {
465
+ if (!try canMove(battle, player, state, options)) return;
466
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
467
+ try Effects.thief(battle, player, state, options);
468
+ _ = try afterMove(KINGS, battle, player, state, options);
469
+ },
470
+ .MeanLook => {
471
+ if (!try canMove(battle, player, state, options)) return;
472
+ try Effects.meanLook(battle, player, state, options);
473
+ },
474
+ .LockOn => {
475
+ if (!try canMove(battle, player, state, options)) return;
476
+ try checkHit(battle, player, state, options);
477
+ try Effects.lockOn(battle, player, state, options);
478
+ },
479
+ .Nightmare => {
480
+ if (!try canMove(battle, player, state, options)) return;
481
+ try Effects.nightmare(battle, player, state, options);
482
+ },
483
+ .Snore => {
484
+ if (!try canMove(battle, player, state, options)) return;
485
+ try checkCriticalHit(battle, player, state, options);
486
+ try calcDamage(battle, player, state, options);
487
+ try adjustDamage(battle, player, state, options);
488
+ try randomizeDamage(battle, player, state, options);
489
+ try checkHit(battle, player, state, options);
490
+ try effectChance(battle, player, state, options);
491
+ if (!try Effects.snore(battle, player, state, options)) return;
492
+ try applyDamage(battle, player, state, options);
493
+ try reportOutcome(battle, player, state, options);
494
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
495
+ try Effects.flinchChance(battle, player, state, options);
496
+ try kingsRock(battle, player, state, options);
497
+ },
498
+ .Curse => {
499
+ if (!try canMove(battle, player, state, options)) return;
500
+ try Effects.curse(battle, player, state, options);
501
+ },
502
+ .Reversal => {
503
+ if (!try canMove(battle, player, state, options)) return;
504
+ try Effects.reversal(battle, player, state, options);
505
+ try adjustDamage(battle, player, state, options);
506
+ try checkHit(battle, player, state, options);
507
+ try applyDamage(battle, player, state, options);
508
+ // TODO reversalsupereffectivetext
509
+ _ = try afterMove(KINGS, battle, player, state, options);
510
+ },
511
+ .Conversion2 => {
512
+ if (!try canMove(battle, player, state, options)) return;
513
+ try checkHit(battle, player, state, options);
514
+ try Effects.conversion2(battle, player, state, options);
515
+ },
516
+ .Spite => {
517
+ if (!try canMove(battle, player, state, options)) return;
518
+ try checkHit(battle, player, state, options);
519
+ try Effects.spite(battle, player, state, options);
520
+ },
521
+ .Endure, .Protect => {
522
+ if (!try canMove(battle, player, state, options)) return;
523
+ try Effects.protect(battle, player, state, options);
524
+ },
525
+ .BellyDrum => {
526
+ if (!try canMove(battle, player, state, options)) return;
527
+ try Effects.bellyDrum(battle, player, state, options);
528
+ },
529
+ .Spikes => {
530
+ if (!try canMove(battle, player, state, options)) return;
531
+ try Effects.spikes(battle, player, state, options);
532
+ },
533
+ .Foresight => {
534
+ if (!try canMove(battle, player, state, options)) return;
535
+ try checkHit(battle, player, state, options);
536
+ try Effects.foresight(battle, player, state, options);
537
+ },
538
+ .DestinyBond => {
539
+ if (!try canMove(battle, player, state, options)) return;
540
+ try Effects.destinyBond(battle, player, state, options);
541
+ },
542
+ .PerishSong => {
543
+ if (!try canMove(battle, player, state, options)) return;
544
+ try Effects.perishSong(battle, player, state, options);
545
+ },
546
+ .Sandstorm => {
547
+ if (!try canMove(battle, player, state, options)) return;
548
+ try Effects.sandstorm(battle, player, state, options);
549
+ },
550
+ .Rollout => {
551
+ try Effects.rollout.check(battle, player, state, options);
552
+ // doturn
553
+ const charging = false; // TODO
554
+ const skip_pp = charging or state.move == .Struggle or
555
+ (volatiles.BeatUp or volatiles.Thrashing or volatiles.Bide);
556
+ if (!skip_pp) _ = decrementPP(side, state.move, state.mslot); // TODO if no pp return
557
+ // usedmovetext
558
+ try log.move(ident, state.move, foe_ident); // FIXME self? from?
559
+ try checkCriticalHit(battle, player, state, options);
560
+ try calcDamage(battle, player, state, options);
561
+ try adjustDamage(battle, player, state, options);
562
+ try checkHit(battle, player, state, options);
563
+ try Effects.rollout.power(battle, player, state, options);
564
+ try randomizeDamage(battle, player, state, options);
565
+ try applyDamage(battle, player, state, options);
566
+ try reportOutcome(battle, player, state, options);
567
+ _ = try afterMove(KINGS, battle, player, state, options);
568
+ },
569
+ .FalseSwipe => {
570
+ if (!try canMove(battle, player, state, options)) return;
571
+ try checkCriticalHit(battle, player, state, options);
572
+ try calcDamage(battle, player, state, options);
573
+ try adjustDamage(battle, player, state, options);
574
+ try randomizeDamage(battle, player, state, options);
575
+ try Effects.falseSwipe(battle, player, state, options);
576
+ try checkHit(battle, player, state, options);
577
+ try applyDamage(battle, player, state, options);
578
+ try reportOutcome(battle, player, state, options);
579
+ _ = try afterMove(KINGS, battle, player, state, options);
580
+ },
581
+ .Swagger => {
582
+ if (!try canMove(battle, player, state, options)) return;
583
+ try checkHit(battle, player, state, options);
584
+ try Effects.boost(battle, player.foe(), state, options);
585
+ try Effects.confusionChance(battle, player, state, options);
586
+ },
587
+ .FuryCutter => {
588
+ if (!try canMove(battle, player, state, options)) return;
589
+ try checkCriticalHit(battle, player, state, options);
590
+ try calcDamage(battle, player, state, options);
591
+ try adjustDamage(battle, player, state, options);
592
+ try checkHit(battle, player, state, options);
593
+ try Effects.furyCutter(battle, player, state, options);
594
+ try randomizeDamage(battle, player, state, options);
595
+ try applyDamage(battle, player, state, options);
596
+ try reportOutcome(battle, player, state, options);
597
+ _ = try afterMove(KINGS, battle, player, state, options);
598
+ },
599
+ .Attract => {
600
+ if (!try canMove(battle, player, state, options)) return;
601
+ try checkHit(battle, player, state, options);
602
+ try Effects.attract(battle, player, state, options);
603
+ },
604
+ .SleepTalk => {
605
+ if (!try canMove(battle, player, state, options)) return;
606
+ try Effects.sleepTalk(battle, player, state, options);
607
+ },
608
+ .HealBell => {
609
+ if (!try canMove(battle, player, state, options)) return;
610
+ try Effects.healBell(battle, player, state, options);
611
+ },
612
+ .Frustration, .Return => {
613
+ if (!try canMove(battle, player, state, options)) return;
614
+ try checkCriticalHit(battle, player, state, options);
615
+ try Effects.happiness(battle, player, state, options);
616
+ try calcDamage(battle, player, state, options);
617
+ try adjustDamage(battle, player, state, options);
618
+ try randomizeDamage(battle, player, state, options);
619
+ try checkHit(battle, player, state, options);
620
+ try applyDamage(battle, player, state, options);
621
+ try reportOutcome(battle, player, state, options);
622
+ _ = try afterMove(KINGS, battle, player, state, options);
623
+ },
624
+ .Present => {
625
+ if (!try canMove(battle, player, state, options)) return;
626
+ try checkHit(battle, player, state, options);
627
+ try checkCriticalHit(battle, player, state, options);
628
+ try Effects.present(battle, player, state, options);
629
+ try calcDamage(battle, player, state, options);
630
+ try adjustDamage(battle, player, state, options);
631
+ try randomizeDamage(battle, player, state, options);
632
+
633
+ if (state.miss) state.damage = 0;
634
+
635
+ try applyDamage(battle, player, state, options);
636
+ try reportOutcome(battle, player, state, options);
637
+ _ = try afterMove(KINGS, battle, player, state, options);
638
+ },
639
+ .Safeguard => {
640
+ if (!try canMove(battle, player, state, options)) return;
641
+ try Effects.safeguard(battle, player, state, options);
642
+ },
643
+ .PainSplit => {
644
+ if (!try canMove(battle, player, state, options)) return;
645
+ try checkHit(battle, player, state, options);
646
+ try Effects.painSplit(battle, player, state, options);
647
+ },
648
+ .FlameWheel, .SacredFire => {
649
+ if (!try canMove(battle, player, state, options)) return;
650
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
651
+ try Effects.defrost(battle, player, state, options);
652
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
653
+ try Effects.burnChance(battle, player, state, options);
654
+ },
655
+ .Magnitude => {
656
+ if (!try canMove(battle, player, state, options)) return;
657
+ try checkCriticalHit(battle, player, state, options);
658
+ try Effects.magnitude(battle, player, state, options);
659
+ try calcDamage(battle, player, state, options);
660
+ try adjustDamage(battle, player, state, options);
661
+ try randomizeDamage(battle, player, state, options);
662
+ try checkHit(battle, player, state, options);
663
+ try Effects.double.underground(battle, player, state, options);
664
+ try applyDamage(battle, player, state, options);
665
+ try reportOutcome(battle, player, state, options);
666
+ _ = try afterMove(KINGS, battle, player, state, options);
667
+ },
668
+ .BatonPass => {
669
+ if (!try canMove(battle, player, state, options)) return;
670
+ try Effects.batonPass(battle, player, state, options);
671
+ },
672
+ .Encore => {
673
+ if (!try canMove(battle, player, state, options)) return;
674
+ try checkHit(battle, player, state, options);
675
+ try Effects.encore(battle, player, state, options);
676
+ },
677
+ .Pursuit => {
678
+ if (!try canMove(battle, player, state, options)) return;
679
+ try checkCriticalHit(battle, player, state, options);
680
+ try calcDamage(battle, player, state, options);
681
+ try adjustDamage(battle, player, state, options);
682
+ try randomizeDamage(battle, player, state, options);
683
+ try Effects.pursuit(battle, player, state, options);
684
+ try checkHit(battle, player, state, options);
685
+ try applyDamage(battle, player, state, options);
686
+ try reportOutcome(battle, player, state, options);
687
+ _ = try afterMove(KINGS, battle, player, state, options);
688
+ },
689
+ .RapidSpin => {
690
+ if (!try canMove(battle, player, state, options)) return;
691
+ if (!try doMove(!SECONDARY, battle, player, state, options)) return;
692
+ try Effects.rapidSpin(battle, player, state, options);
693
+ _ = try afterMove(KINGS, battle, player, state, options);
694
+ },
695
+ .MorningSun, .Synthesis, .Moonlight => {
696
+ if (!try canMove(battle, player, state, options)) return;
697
+ try Effects.weatherHeal(battle, player, state, options);
698
+ },
699
+ .HiddenPower => {
700
+ if (!try canMove(battle, player, state, options)) return;
701
+ try checkCriticalHit(battle, player, state, options);
702
+ try Effects.hiddenPower(battle, player, state, options);
703
+ try calcDamage(battle, player, state, options);
704
+ try adjustDamage(battle, player, state, options);
705
+ try randomizeDamage(battle, player, state, options);
706
+ try checkHit(battle, player, state, options);
707
+ try applyDamage(battle, player, state, options);
708
+ try reportOutcome(battle, player, state, options);
709
+ _ = try afterMove(KINGS, battle, player, state, options);
710
+ },
711
+ .Twister => {
712
+ if (!try canMove(battle, player, state, options)) return;
713
+ try checkCriticalHit(battle, player, state, options);
714
+ try calcDamage(battle, player, state, options);
715
+ try adjustDamage(battle, player, state, options);
716
+ try randomizeDamage(battle, player, state, options);
717
+ try Effects.double.flying(battle, player, state, options);
718
+ try checkHit(battle, player, state, options);
719
+ try effectChance(battle, player, state, options);
720
+ try applyDamage(battle, player, state, options);
721
+ try reportOutcome(battle, player, state, options);
722
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
723
+ try Effects.flinchChance(battle, player, state, options);
724
+ },
725
+ .RainDance => {
726
+ if (!try canMove(battle, player, state, options)) return;
727
+ try Effects.rainDance(battle, player, state, options);
728
+ },
729
+ .SunnyDay => {
730
+ if (!try canMove(battle, player, state, options)) return;
731
+ try Effects.sunnyDay(battle, player, state, options);
732
+ },
733
+ .PsychUp => {
734
+ if (!try canMove(battle, player, state, options)) return;
735
+ try Effects.psychUp(battle, player, state, options);
736
+ },
737
+ .AllStatUpChance => {
738
+ if (!try canMove(battle, player, state, options)) return;
739
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
740
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
741
+ try Effects.allStatUpChance(battle, player, state, options);
742
+ },
743
+ .FutureSight => {
744
+ // TODO checkfuturesight
745
+ if (!try canMove(battle, player, state, options)) return;
746
+ try calcDamage(battle, player, state, options);
747
+ try Effects.futureSight(battle, player, state, options);
748
+ try randomizeDamage(battle, player, state, options);
749
+ try checkHit(battle, player, state, options);
750
+ try applyDamage(battle, player, state, options);
751
+ _ = try afterMove(!KINGS, battle, player, state, options);
752
+ },
753
+ .BeatUp => {
754
+ if (!try canMove(battle, player, state, options)) return;
755
+ // TODO startloop
756
+ try checkHit(battle, player, state, options);
757
+ try checkCriticalHit(battle, player, state, options);
758
+ try Effects.beatUp(battle, player, state, options);
759
+ try randomizeDamage(battle, player, state, options);
760
+
761
+ if (state.miss) state.damage = 0;
762
+
763
+ try applyDamage(battle, player, state, options);
764
+ try reportOutcome(battle, player, state, options);
765
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
766
+ // TODO endloop
767
+ // TODO beatupfailtext
768
+ try kingsRock(battle, player, state, options);
769
+ },
770
+ // zig fmt: off
771
+ .AttackUp1, .AttackUp2, .DefenseCurl, .DefenseUp1, .DefenseUp2,
772
+ .EvasionUp1, .SpAtkUp1, .SpDefUp2, .SpeedUp2 => {
773
+ // zig fmt: on
774
+ _ = try canMove(battle, player, state, options);
775
+ try Effects.boost(battle, player, state, options);
776
+ if (move.effect == .DefenseCurl) {
777
+ try Effects.defenseCurl(battle, player, state, options);
778
+ }
779
+ },
780
+ .AttackUpChance, .DefenseUpChance => {
781
+ _ = try canMove(battle, player, state, options);
782
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
783
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
784
+ try Effects.boost(battle, player, state, options);
785
+ },
786
+ // zig fmt: off
787
+ .AccuracyDown1, .AttackDown1, .AttackDown2, .DefenseDown1,
788
+ .DefenseDown2, .EvasionDown1, .SpeedDown1, .SpeedDown2 => {
789
+ // zig fmt: on
790
+ _ = try canMove(battle, player, state, options);
791
+ try checkHit(battle, player, state, options);
792
+ try Effects.unboost(battle, player, state, options);
793
+ },
794
+ // zig fmt: off
795
+ .AccuracyDownChance, .AttackDownChance, .DefenseDownChance,
796
+ .SpDefDownChance, .SpeedDownChance => {
797
+ // zig fmt: on
798
+ _ = try canMove(battle, player, state, options);
799
+ if (!try doMove(SECONDARY, battle, player, state, options)) return;
800
+ if (!try afterMove(!KINGS, battle, player, state, options)) return;
801
+ // GLITCH: moves that lower Defense can do so after breaking a Substitute
802
+ if (move.effect == .DefenseDownChance) {
803
+ try effectChance(battle, player, state, options);
804
+ }
805
+ try Effects.unboost(battle, player, state, options);
806
+ },
807
+ }
808
+ }