PkmnLib_rs/src/dynamic_data/models/pokemon_party.rs

117 lines
3.2 KiB
Rust
Executable File

use anyhow::Result;
use parking_lot::lock_api::RwLockReadGuard;
use parking_lot::{RawRwLock, RwLock};
use crate::dynamic_data::models::pokemon::Pokemon;
use crate::VecExt;
/// A list of Pokemon belonging to a trainer.
#[derive(Debug)]
pub struct PokemonParty {
/// The underlying list of Pokemon.
pokemon: RwLock<Vec<Option<Pokemon>>>,
}
impl PokemonParty {
/// Instantiates a party with a set size.
pub fn new(size: usize) -> Self {
let mut pokemon = Vec::with_capacity(size);
for _i in 0..size {
pokemon.push(None);
}
Self {
pokemon: RwLock::new(pokemon),
}
}
/// Instantiates a party with a list.
pub fn new_from_vec(pokemon: Vec<Option<Pokemon>>) -> Self {
Self {
pokemon: RwLock::new(pokemon),
}
}
/// Gets a Pokemon at an index in the party.
pub fn at(&self, index: usize) -> Option<Pokemon> {
let read_lock = self.pokemon.read();
let opt = read_lock.get(index);
if let Some(v) = opt {
v.clone()
} else {
None
}
}
/// Swaps two Pokemon in the party around.
pub fn switch(&self, a: usize, b: usize) {
self.pokemon.write().swap(a, b);
}
/// Sets the Pokemon at an index to a Pokemon, returning the old Pokemon.
pub fn swap_into(&self, index: usize, pokemon: Option<Pokemon>) -> Result<Option<Pokemon>> {
let mut party = self.pokemon.write();
if index >= party.len() {
return Ok(pokemon);
}
let value = party.get_mut_res(index)?;
let old = match pokemon {
Some(p) => value.replace(p),
None => value.take(),
};
Ok(old)
}
/// Whether or not the party still has Pokemon that can be used in battle.
pub fn has_usable_pokemon(&self) -> bool {
for pokemon in self.pokemon.read().iter().flatten() {
if pokemon.is_usable() {
return true;
}
}
false
}
/// Get the length of the underlying list of Pokemon.
pub fn length(&self) -> usize {
self.pokemon.read().len()
}
/// Gets the underlying list of Pokemon.
pub fn pokemon(&self) -> RwLockReadGuard<'_, RawRwLock, Vec<Option<Pokemon>>> {
self.pokemon.read()
}
/// Makes sure there are no empty spots in the party anymore, leaving the length the same.
pub fn pack_party(&self) -> Result<()> {
let mut first_empty = None;
let mut i = 0;
let mut party = self.pokemon.write();
loop {
if party.get_res(i)?.is_none() {
if first_empty.is_none() {
first_empty = Some(i)
}
} else if let Some(f) = first_empty {
party.swap(f, i);
i = f;
first_empty = None;
}
i += 1;
if i >= party.len() {
break;
}
}
Ok(())
}
/// Checks if the party contains a given pokemon.
pub fn has_pokemon(&self, pokemon: &Pokemon) -> bool {
for p in self.pokemon.read().iter().flatten() {
if Pokemon::eq(p, pokemon) {
return true;
}
}
false
}
}