use crate::dynamic_data::models::battle::Battle; use crate::dynamic_data::models::pokemon::Pokemon; use crate::static_data::MoveTarget; use num_traits::abs; use std::ops::Deref; use std::sync::Arc; pub type TargetList<'own, 'library> = Vec>>>; fn get_all_targets<'b, 'library>(battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> { let mut v = Vec::with_capacity(battle.pokemon_per_side() as usize * battle.number_of_sides() as usize); for side in battle.sides() { for pokemon in side.pokemon().deref() { v.push(pokemon.as_ref().cloned()); } } v } fn get_opposite_side(side: u8) -> u8 { if side == 0 { return 1; } 0 } fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> { let left = index as i32 - 1; let right = index + 1; if left < 0 && right >= battle.pokemon_per_side() { return vec![ battle.get_pokemon(side, index).as_ref().cloned(), battle.get_pokemon(get_opposite_side(side), index).as_ref().cloned(), ]; } if left >= 0 { return if right < battle.pokemon_per_side() { vec![ battle.get_pokemon(side, index).as_ref().cloned(), battle.get_pokemon(side, left as u8).as_ref().cloned(), battle.get_pokemon(side, right).as_ref().cloned(), battle.get_pokemon(get_opposite_side(side), index).as_ref().cloned(), ] } else { vec![ battle.get_pokemon(side, index).as_ref().cloned(), battle.get_pokemon(side, left as u8).as_ref().cloned(), battle.get_pokemon(get_opposite_side(side), index).as_ref().cloned(), ] }; } vec![ battle.get_pokemon(side, index).as_ref().cloned(), battle.get_pokemon(side, right).as_ref().cloned(), battle.get_pokemon(get_opposite_side(side), index).as_ref().cloned(), ] } fn get_all_adjacent_opponent<'b, 'library>( side: u8, index: u8, battle: &Battle<'b, 'library>, ) -> TargetList<'b, 'library> { let left = index as i32 - 1; let right = index + 1; if left < 0 && right >= battle.pokemon_per_side() { return vec![battle.get_pokemon(side, index).as_ref().cloned()]; } if left >= 0 { if right < battle.pokemon_per_side() { return vec![ battle.get_pokemon(side, index).as_ref().cloned(), battle.get_pokemon(side, left as u8).as_ref().cloned(), battle.get_pokemon(side, right).as_ref().cloned(), ]; } return vec![ battle.get_pokemon(side, index).as_ref().cloned(), battle.get_pokemon(side, left as u8).as_ref().cloned(), ]; } vec![ battle.get_pokemon(side, index).as_ref().cloned(), battle.get_pokemon(side, right).as_ref().cloned(), ] } pub fn resolve_targets<'b, 'library>( side: u8, index: u8, target: MoveTarget, battle: &Battle<'b, 'library>, ) -> TargetList<'b, 'library> { match target { MoveTarget::Adjacent | MoveTarget::AdjacentAlly | MoveTarget::AdjacentAllySelf | MoveTarget::AdjacentOpponent | MoveTarget::Any | MoveTarget::RandomOpponent | MoveTarget::SelfUse => { vec![battle.get_pokemon(side, index).as_ref().cloned()] } MoveTarget::All => get_all_targets(battle), MoveTarget::AllAdjacent => get_all_adjacent(side, index, battle), MoveTarget::AllAdjacentOpponent => get_all_adjacent_opponent(side, index, battle), MoveTarget::AllAlly | MoveTarget::AllOpponent => { let mut v = Vec::new(); for pokemon in battle.sides()[side as usize].pokemon().deref() { v.push(pokemon.as_ref().cloned()); } v } } } pub fn is_valid_target(side: u8, index: u8, target: MoveTarget, user: &Pokemon) -> bool { let user_side = user.get_battle_side_index(); let user_index = user.get_battle_index(); // If the user is not on the field, nothing is a valid target if user_side.is_none() || user_index.is_none() { return false; } match target { MoveTarget::Adjacent | MoveTarget::AllAdjacent => { let diff = abs(index as i32 - user_index.unwrap() as i32); if diff == 0 { return user_side.unwrap() != side; } diff <= 1 } MoveTarget::AdjacentAlly => { if user_side.unwrap() != side { false } else { abs(index as i32 - user_index.unwrap() as i32) == 1 } } MoveTarget::AdjacentAllySelf => { if user_side.unwrap() != side { false } else { abs(index as i32 - user_index.unwrap() as i32) <= 1 } } MoveTarget::AdjacentOpponent | MoveTarget::AllAdjacentOpponent => { if user_side.unwrap() == side { false } else { abs(index as i32 - user_index.unwrap() as i32) <= 1 } } MoveTarget::All | MoveTarget::Any | MoveTarget::RandomOpponent => true, MoveTarget::AllAlly => user_side.unwrap() == side, MoveTarget::AllOpponent => user_side.unwrap() != side, MoveTarget::SelfUse => user_side.unwrap() == side && user_index.unwrap() == index, } }