1use crate::abilities::Abilities;
2use crate::choices::{Choices, MoveCategory};
3use crate::items::Items;
4use crate::pokemon::PokemonName;
5use crate::state::SideReference;
6use crate::state::Terrain;
7use crate::state::Weather;
8use crate::state::{LastUsedMove, PokemonVolatileStatus};
9use crate::state::{PokemonBoostableStat, PokemonType};
10use crate::state::{PokemonIndex, PokemonSideCondition};
11use crate::state::{PokemonMoveIndex, PokemonStatus};
12use std::fmt;
13use std::fmt::Formatter;
14
15#[derive(PartialEq, Clone)]
16pub struct StateInstructions {
17 pub percentage: f32,
18 pub instruction_list: Vec<Instruction>,
19}
20
21impl Default for StateInstructions {
22 fn default() -> StateInstructions {
23 StateInstructions {
24 percentage: 100.0,
25 instruction_list: Vec::with_capacity(16),
26 }
27 }
28}
29
30impl fmt::Debug for StateInstructions {
31 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
32 let mut final_string = format!("\n\tPercentage: {}\n\tInstructions:", self.percentage);
33 for i in self.instruction_list.iter() {
34 final_string.push_str(format!("\n\t\t{:?}", i).as_str());
35 }
36 write!(f, "{}\n", final_string)
37 }
38}
39
40impl StateInstructions {
41 pub fn update_percentage(&mut self, modifier: f32) {
42 self.percentage *= modifier;
43 }
44}
45
46#[derive(PartialEq, Clone)]
48pub enum Instruction {
49 Switch(SwitchInstruction),
50 ApplyVolatileStatus(ApplyVolatileStatusInstruction),
51 RemoveVolatileStatus(RemoveVolatileStatusInstruction),
52 ChangeStatus(ChangeStatusInstruction),
53 Heal(HealInstruction),
54 Damage(DamageInstruction),
55 Boost(BoostInstruction),
56 ChangeSideCondition(ChangeSideConditionInstruction),
57 ChangeVolatileStatusDuration(ChangeVolatileStatusDurationInstruction),
58 ChangeWeather(ChangeWeather),
59 DecrementWeatherTurnsRemaining,
60 ChangeTerrain(ChangeTerrain),
61 DecrementTerrainTurnsRemaining,
62 ChangeType(ChangeType),
63 ChangeAbility(ChangeAbilityInstruction),
64 ChangeItem(ChangeItemInstruction),
65 ChangeAttack(ChangeStatInstruction),
66 ChangeDefense(ChangeStatInstruction),
67 ChangeSpecialAttack(ChangeStatInstruction),
68 ChangeSpecialDefense(ChangeStatInstruction),
69 ChangeSpeed(ChangeStatInstruction),
70 DisableMove(DisableMoveInstruction),
71 EnableMove(EnableMoveInstruction),
72 ChangeWish(ChangeWishInstruction),
73 DecrementWish(DecrementWishInstruction),
74 SetFutureSight(SetFutureSightInstruction),
75 DecrementFutureSight(DecrementFutureSightInstruction),
76 DamageSubstitute(DamageInstruction),
77 DecrementRestTurns(DecrementRestTurnsInstruction),
78 SetRestTurns(SetSleepTurnsInstruction),
79 SetSleepTurns(SetSleepTurnsInstruction),
80 ChangeSubstituteHealth(ChangeSubsituteHealthInstruction),
81 FormeChange(FormeChangeInstruction),
82 SetSideOneMoveSecondSwitchOutMove(SetSecondMoveSwitchOutMoveInstruction),
83 SetSideTwoMoveSecondSwitchOutMove(SetSecondMoveSwitchOutMoveInstruction),
84 ToggleBatonPassing(ToggleBatonPassingInstruction),
85 SetLastUsedMove(SetLastUsedMoveInstruction),
86 SetDamageDealtSideOne(SetDamageDealtSideOneInstruction),
87 SetDamageDealtSideTwo(SetDamageDealtSideTwoInstruction),
88 DecrementPP(DecrementPPInstruction),
89 ToggleTrickRoom(ToggleTrickRoomInstruction),
90 DecrementTrickRoomTurnsRemaining,
91 ToggleSideOneForceSwitch,
92 ToggleSideTwoForceSwitch,
93 ToggleTerastallized(ToggleTerastallizedInstruction),
94}
95
96impl fmt::Debug for Instruction {
97 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
98 match self {
99 Instruction::Switch(s) => {
100 write!(
101 f,
102 "Switch {:?}: {:?} -> {:?}",
103 s.side_ref, s.previous_index, s.next_index
104 )
105 }
106 Instruction::ApplyVolatileStatus(a) => {
107 write!(
108 f,
109 "ApplyVolatileStatus {:?}: {:?}",
110 a.side_ref, a.volatile_status
111 )
112 }
113 Instruction::RemoveVolatileStatus(r) => {
114 write!(
115 f,
116 "RemoveVolatileStatus {:?}: {:?}",
117 r.side_ref, r.volatile_status
118 )
119 }
120 Instruction::ChangeStatus(c) => {
121 write!(
122 f,
123 "ChangeStatus {:?}-{:?}: {:?} -> {:?}",
124 c.side_ref, c.pokemon_index, c.old_status, c.new_status
125 )
126 }
127 Instruction::Heal(h) => {
128 write!(f, "Heal {:?}: {:?}", h.side_ref, h.heal_amount)
129 }
130 Instruction::Damage(d) => {
131 write!(f, "Damage {:?}: {}", d.side_ref, d.damage_amount)
132 }
133 Instruction::Boost(b) => {
134 write!(f, "Boost {:?} {:?}: {:?}", b.side_ref, b.stat, b.amount)
135 }
136 Instruction::ChangeSideCondition(c) => {
137 write!(
138 f,
139 "ChangeSideCondition {:?} {:?}: {:?}",
140 c.side_ref, c.side_condition, c.amount
141 )
142 }
143 Instruction::ChangeVolatileStatusDuration(c) => {
144 write!(
145 f,
146 "ChangeVolatileStatusDuration {:?} {:?}: {:?}",
147 c.side_ref, c.volatile_status, c.amount
148 )
149 }
150 Instruction::ChangeWeather(c) => {
151 write!(
152 f,
153 "ChangeWeather: {:?},{:?} -> {:?},{:?}",
154 c.previous_weather,
155 c.previous_weather_turns_remaining,
156 c.new_weather,
157 c.new_weather_turns_remaining
158 )
159 }
160 Instruction::DecrementWeatherTurnsRemaining => {
161 write!(f, "DecrementWeatherTurnsRemaining",)
162 }
163 Instruction::ChangeTerrain(c) => {
164 write!(
165 f,
166 "ChangeTerrain: {:?},{:?} -> {:?},{:?}",
167 c.previous_terrain,
168 c.previous_terrain_turns_remaining,
169 c.new_terrain,
170 c.new_terrain_turns_remaining
171 )
172 }
173 Instruction::DecrementTerrainTurnsRemaining => {
174 write!(f, "DecrementTerrainTurnsRemaining",)
175 }
176 Instruction::ChangeType(c) => {
177 write!(
178 f,
179 "ChangeType {:?}: {:?} -> {:?}",
180 c.side_ref, c.old_types, c.new_types
181 )
182 }
183 Instruction::ChangeAbility(c) => {
184 write!(
185 f,
186 "ChangeAbility {:?}: {:?} -> {:?}",
187 c.side_ref, c.old_ability, c.new_ability
188 )
189 }
190 Instruction::ChangeItem(c) => {
191 write!(
192 f,
193 "ChangeItem {:?}: {:?} -> {:?}",
194 c.side_ref, c.current_item, c.new_item
195 )
196 }
197 Instruction::ChangeAttack(c) => {
198 write!(f, "ChangeAttack {:?}: {}", c.side_ref, c.amount)
199 }
200 Instruction::ChangeDefense(c) => {
201 write!(f, "ChangeDefense {:?}: {}", c.side_ref, c.amount)
202 }
203 Instruction::ChangeSpecialAttack(c) => {
204 write!(f, "ChangeSpecialAttack {:?}: {}", c.side_ref, c.amount)
205 }
206 Instruction::ChangeSpecialDefense(c) => {
207 write!(f, "ChangeSpecialDefense {:?}: {}", c.side_ref, c.amount)
208 }
209 Instruction::ChangeSpeed(c) => {
210 write!(f, "ChangeSpeed {:?}: {}", c.side_ref, c.amount)
211 }
212 Instruction::DisableMove(d) => {
213 write!(f, "DisableMove {:?}: {:?}", d.side_ref, d.move_index)
214 }
215 Instruction::EnableMove(e) => {
216 write!(f, "EnableMove {:?}: {:?}", e.side_ref, e.move_index)
217 }
218 Instruction::ChangeWish(s) => {
219 write!(f, "SetWish {:?}: {:?}", s.side_ref, s.wish_amount_change)
220 }
221 Instruction::DecrementWish(d) => {
222 write!(f, "DecrementWish {:?}", d.side_ref)
223 }
224 Instruction::SetFutureSight(s) => {
225 write!(
226 f,
227 "SetFutureSight {:?}: {:?} -> {:?}",
228 s.side_ref, s.previous_pokemon_index, s.pokemon_index
229 )
230 }
231 Instruction::DecrementFutureSight(d) => {
232 write!(f, "DecrementFutureSight {:?}", d.side_ref)
233 }
234 Instruction::DamageSubstitute(d) => {
235 write!(
236 f,
237 "DamageSubstitute {:?}: {:?}",
238 d.side_ref, d.damage_amount
239 )
240 }
241 Instruction::DecrementRestTurns(d) => {
242 write!(f, "DecrementRestTurns {:?}", d.side_ref)
243 }
244 Instruction::SetRestTurns(s) => {
245 write!(
246 f,
247 "SetRestTurns {:?}-{:?}: {:?} -> {:?}",
248 s.side_ref, s.pokemon_index, s.previous_turns, s.new_turns
249 )
250 }
251 Instruction::SetSleepTurns(s) => {
252 write!(
253 f,
254 "SetSleepTurns {:?}-{:?}: {:?} -> {:?}",
255 s.side_ref, s.pokemon_index, s.previous_turns, s.new_turns
256 )
257 }
258 Instruction::ChangeSubstituteHealth(s) => {
259 write!(
260 f,
261 "SetSubstituteHealth {:?}: {:?}",
262 s.side_ref, s.health_change,
263 )
264 }
265 Instruction::FormeChange(s) => {
266 write!(
267 f,
268 "FormeChange {:?}: {:?} -> {:?}",
269 s.side_ref, s.previous_forme, s.new_forme
270 )
271 }
272 Instruction::SetSideOneMoveSecondSwitchOutMove(s) => {
273 write!(
274 f,
275 "SideOneMoveSecondSwitchOutMove: {:?} -> {:?}",
276 s.previous_choice, s.new_choice
277 )
278 }
279 Instruction::SetSideTwoMoveSecondSwitchOutMove(s) => {
280 write!(
281 f,
282 "SideTwoMoveSecondSwitchOutMove: {:?} -> {:?}",
283 s.previous_choice, s.new_choice
284 )
285 }
286 Instruction::ToggleBatonPassing(s) => {
287 write!(f, "ToggleBatonPassing {:?}", s.side_ref)
288 }
289 Instruction::ToggleTerastallized(s) => {
290 write!(f, "ToggleTerastallized {:?}", s.side_ref)
291 }
292 Instruction::SetLastUsedMove(s) => {
293 write!(
294 f,
295 "SetLastUsedMove {:?}: {:?} -> {:?}",
296 s.side_ref, s.previous_last_used_move, s.last_used_move
297 )
298 }
299 Instruction::SetDamageDealtSideOne(s) => {
300 write!(
301 f,
302 "SetDamageDealt SideOne: ({:?} -> {:?}) Damage Change: {:?} HitSub Change: {:?}",
303 s.previous_move_category,
304 s.move_category,
305 s.damage_change,
306 s.toggle_hit_substitute
307 )
308 }
309 Instruction::SetDamageDealtSideTwo(s) => {
310 write!(
311 f,
312 "SetDamageDealt SideTwo: ({:?} -> {:?}) Damage Change: {:?} HitSub Change: {:?}",
313 s.previous_move_category,
314 s.move_category,
315 s.damage_change,
316 s.toggle_hit_substitute
317 )
318 }
319 Instruction::DecrementPP(s) => {
320 write!(
321 f,
322 "DecrementPP {:?}: {:?} {}",
323 s.side_ref, s.move_index, s.amount
324 )
325 }
326 Instruction::ToggleTrickRoom(i) => {
327 write!(
328 f,
329 "ToggleTrickRoom: {:?},{:?} -> {:?},{:?}",
330 i.currently_active,
331 i.previous_trickroom_turns_remaining,
332 !i.currently_active,
333 i.new_trickroom_turns_remaining,
334 )
335 }
336 Instruction::DecrementTrickRoomTurnsRemaining => {
337 write!(f, "DecrementTrickRoomTurnsRemaining")
338 }
339 Instruction::ToggleSideOneForceSwitch => {
340 write!(f, "ToggleSideOneForceSwitch")
341 }
342 Instruction::ToggleSideTwoForceSwitch => {
343 write!(f, "ToggleSideTwoForceSwitch")
344 }
345 }
346 }
347}
348
349#[derive(Debug, PartialEq, Clone)]
350pub struct SetDamageDealtSideOneInstruction {
351 pub damage_change: i16,
352 pub move_category: MoveCategory,
353 pub previous_move_category: MoveCategory,
354 pub toggle_hit_substitute: bool,
355}
356
357#[derive(Debug, PartialEq, Clone)]
358pub struct SetDamageDealtSideTwoInstruction {
359 pub damage_change: i16,
360 pub move_category: MoveCategory,
361 pub previous_move_category: MoveCategory,
362 pub toggle_hit_substitute: bool,
363}
364
365#[derive(Debug, PartialEq, Clone)]
366pub struct DecrementPPInstruction {
367 pub side_ref: SideReference,
368 pub move_index: PokemonMoveIndex,
369 pub amount: i8,
370}
371
372#[derive(Debug, PartialEq, Clone)]
373pub struct SetLastUsedMoveInstruction {
374 pub side_ref: SideReference,
375 pub last_used_move: LastUsedMove,
376 pub previous_last_used_move: LastUsedMove,
377}
378
379#[derive(Debug, PartialEq, Clone)]
380pub struct ToggleBatonPassingInstruction {
381 pub side_ref: SideReference,
382}
383
384#[derive(Debug, PartialEq, Clone)]
385pub struct DecrementRestTurnsInstruction {
386 pub side_ref: SideReference,
387}
388
389#[derive(Debug, PartialEq, Clone)]
390pub struct SetSleepTurnsInstruction {
391 pub side_ref: SideReference,
392 pub pokemon_index: PokemonIndex,
393 pub new_turns: i8,
394 pub previous_turns: i8,
395}
396
397#[derive(Debug, PartialEq, Clone)]
398pub struct SetSecondMoveSwitchOutMoveInstruction {
399 pub new_choice: Choices,
400 pub previous_choice: Choices,
401}
402
403#[derive(Debug, PartialEq, Clone)]
404pub struct ChangeWishInstruction {
405 pub side_ref: SideReference,
406 pub wish_amount_change: i16,
407}
408
409#[derive(Debug, PartialEq, Clone)]
410pub struct DecrementWishInstruction {
411 pub side_ref: SideReference,
412}
413
414#[derive(Debug, PartialEq, Clone)]
415pub struct SetFutureSightInstruction {
416 pub side_ref: SideReference,
417 pub pokemon_index: PokemonIndex,
418 pub previous_pokemon_index: PokemonIndex,
419}
420
421#[derive(Debug, PartialEq, Clone)]
422pub struct DecrementFutureSightInstruction {
423 pub side_ref: SideReference,
424}
425
426#[derive(Debug, PartialEq, Clone)]
427pub struct EnableMoveInstruction {
428 pub side_ref: SideReference,
429 pub move_index: PokemonMoveIndex,
430}
431
432#[derive(Debug, PartialEq, Clone)]
433pub struct DisableMoveInstruction {
434 pub side_ref: SideReference,
435 pub move_index: PokemonMoveIndex,
436}
437
438#[derive(Debug, PartialEq, Clone)]
439pub struct ChangeItemInstruction {
440 pub side_ref: SideReference,
441 pub current_item: Items,
442 pub new_item: Items,
443}
444
445#[derive(Debug, PartialEq, Clone)]
446pub struct ChangeStatInstruction {
447 pub side_ref: SideReference,
448 pub amount: i16,
449}
450
451#[derive(Debug, PartialEq, Clone)]
452pub struct HealInstruction {
453 pub side_ref: SideReference,
454 pub heal_amount: i16,
455}
456
457#[derive(Debug, PartialEq, Clone)]
458pub struct DamageInstruction {
459 pub side_ref: SideReference,
460 pub damage_amount: i16,
461}
462
463#[derive(Debug, PartialEq, Clone)]
464pub struct ChangeSubsituteHealthInstruction {
465 pub side_ref: SideReference,
466 pub health_change: i16,
467}
468
469#[derive(Debug, PartialEq, Clone)]
470pub struct FormeChangeInstruction {
471 pub side_ref: SideReference,
472 pub new_forme: PokemonName,
473 pub previous_forme: PokemonName,
474}
475
476#[derive(Debug, PartialEq, Clone)]
477pub struct SwitchInstruction {
478 pub side_ref: SideReference,
479 pub previous_index: PokemonIndex,
480 pub next_index: PokemonIndex,
481}
482
483#[derive(Debug, PartialEq, Clone)]
486pub struct ChangeStatusInstruction {
487 pub side_ref: SideReference,
488 pub pokemon_index: PokemonIndex,
489 pub old_status: PokemonStatus,
490 pub new_status: PokemonStatus,
491}
492
493#[derive(Debug, PartialEq, Clone)]
494pub struct ApplyVolatileStatusInstruction {
495 pub side_ref: SideReference,
496 pub volatile_status: PokemonVolatileStatus,
497}
498
499#[derive(Debug, PartialEq, Clone)]
500pub struct RemoveVolatileStatusInstruction {
501 pub side_ref: SideReference,
502 pub volatile_status: PokemonVolatileStatus,
503}
504
505#[derive(Debug, PartialEq, Clone)]
506pub struct BoostInstruction {
507 pub side_ref: SideReference,
508 pub stat: PokemonBoostableStat,
509 pub amount: i8,
510}
511
512#[derive(Debug, PartialEq, Clone)]
513pub struct ChangeSideConditionInstruction {
514 pub side_ref: SideReference,
515 pub side_condition: PokemonSideCondition,
516 pub amount: i8,
517}
518
519#[derive(Debug, PartialEq, Clone)]
520pub struct ChangeVolatileStatusDurationInstruction {
521 pub side_ref: SideReference,
522 pub volatile_status: PokemonVolatileStatus,
523 pub amount: i8,
524}
525
526#[derive(Debug, PartialEq, Clone)]
527pub struct ChangeWeather {
528 pub new_weather: Weather,
529 pub new_weather_turns_remaining: i8,
530 pub previous_weather: Weather,
531 pub previous_weather_turns_remaining: i8,
532}
533
534#[derive(Debug, PartialEq, Clone)]
535pub struct ChangeTerrain {
536 pub new_terrain: Terrain,
537 pub new_terrain_turns_remaining: i8,
538 pub previous_terrain: Terrain,
539 pub previous_terrain_turns_remaining: i8,
540}
541
542#[derive(Debug, PartialEq, Clone)]
543pub struct ToggleTrickRoomInstruction {
544 pub currently_active: bool,
545 pub new_trickroom_turns_remaining: i8,
546 pub previous_trickroom_turns_remaining: i8,
547}
548
549#[derive(Debug, PartialEq, Clone)]
550pub struct ToggleTerastallizedInstruction {
551 pub side_ref: SideReference,
552}
553
554#[derive(Debug, PartialEq, Clone)]
555pub struct ChangeType {
556 pub side_ref: SideReference,
557 pub new_types: (PokemonType, PokemonType),
558 pub old_types: (PokemonType, PokemonType),
559}
560
561#[derive(Debug, PartialEq, Clone)]
562pub struct ChangeAbilityInstruction {
563 pub side_ref: SideReference,
564 pub new_ability: Abilities,
565 pub old_ability: Abilities,
566}
567
568#[cfg(test)]
569mod test {
570 use super::Instruction;
571
572 #[test]
574 fn test_instruction_size() {
575 assert_eq!(size_of::<Instruction>(), 8);
576 assert_eq!(align_of::<Instruction>(), 2);
577 }
578}