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