Some more functionality for battling, check if choice is valid, implement target resolvers.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -1 +1,2 @@
|
||||
pub mod choice_queue;
|
||||
pub mod target_resolver;
|
||||
|
||||
169
src/dynamic_data/flow/target_resolver.rs
Normal file
169
src/dynamic_data/flow/target_resolver.rs
Normal file
@@ -0,0 +1,169 @@
|
||||
use crate::dynamic_data::models::battle::Battle;
|
||||
use crate::dynamic_data::models::pokemon::Pokemon;
|
||||
use crate::static_data::MoveTarget;
|
||||
use num_traits::abs;
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub type TargetList<'a> = Vec<Option<Arc<RwLock<Pokemon<'a>>>>>;
|
||||
|
||||
fn get_all_targets<'b>(battle: &Battle<'b>) -> TargetList<'b> {
|
||||
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() {
|
||||
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>(side: u8, index: u8, battle: &Battle<'b>) -> TargetList<'b> {
|
||||
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>(side: u8, index: u8, battle: &Battle<'b>) -> TargetList<'b> {
|
||||
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>(
|
||||
side: u8,
|
||||
index: u8,
|
||||
target: MoveTarget,
|
||||
battle: &Battle<'b>,
|
||||
) -> TargetList<'b> {
|
||||
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() {
|
||||
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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user