PkmnLib_rs/src/dynamic_data/flow/target_resolver.rs

161 lines
5.5 KiB
Rust

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<Option<Arc<Pokemon<'own, 'library>>>>;
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,
}
}