use alloc::format;
use core::{
fmt,
fmt::Display,
};
use anyhow::Result;
use zone_alloc::{
BorrowError,
ElementRef,
ElementRefMut,
Handle,
KeyedRegistry,
StrongRegistry,
};
use zone_alloc_strong_handle_derive::StrongHandle;
use crate::{
battle::Mon,
error::{
ConvertError,
general_error,
},
moves::Move,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, StrongHandle)]
pub struct MonHandle(Handle);
impl Display for MonHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, StrongHandle)]
pub struct MoveHandle(Handle);
impl Display for MoveHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
pub type MonRegistry = StrongRegistry<MonHandle, Mon>;
pub type MoveRegistry = KeyedRegistry<MoveHandle, Move>;
pub struct BattleRegistry {
mons: MonRegistry,
last_turn_moves: MoveRegistry,
this_turn_moves: MoveRegistry,
next_active_move_handle: usize,
}
impl BattleRegistry {
pub fn new() -> Self {
Self {
mons: MonRegistry::with_capacity(12),
last_turn_moves: MoveRegistry::new(),
this_turn_moves: MoveRegistry::new(),
next_active_move_handle: 0,
}
}
pub fn register_mon(&self, mon: Mon) -> MonHandle {
self.mons.register(mon)
}
pub fn mon(&self, mon: MonHandle) -> Result<ElementRef<'_, Mon>> {
self.mons
.get(mon)
.map_err(|err| err.convert_error_with_message(format!("mon {mon}")))
}
pub fn mon_mut(&self, mon: MonHandle) -> Result<ElementRefMut<'_, Mon>> {
self.mons
.get_mut(mon)
.map_err(|err| err.convert_error_with_message(format!("mon {mon}")))
}
fn next_active_move_handle(&mut self) -> MoveHandle {
let handle = MoveHandle::from(self.next_active_move_handle);
self.next_active_move_handle += 1;
handle
}
pub fn register_move(&mut self, mov: Move) -> MoveHandle {
let handle = self.next_active_move_handle();
self.this_turn_moves.register(handle, mov);
handle
}
pub fn active_move(&self, mov: MoveHandle) -> Result<ElementRef<'_, Move>> {
match self.this_turn_moves.get(&mov) {
Ok(active_move) => Ok(active_move),
_ => match self.last_turn_moves.get(&mov) {
Ok(active_move) => Ok(active_move),
_ => Err(general_error(format!(
"active move {mov} does not exist in this turn or last turn",
))),
},
}
}
pub fn active_move_mut(&self, mov: MoveHandle) -> Result<ElementRefMut<'_, Move>> {
match self.this_turn_moves.get_mut(&mov) {
Ok(active_move) => Ok(active_move),
_ => match self.last_turn_moves.get_mut(&mov) {
Ok(active_move) => Ok(active_move),
_ => Err(general_error(format!(
"active move {mov} does not exist in this turn or last turn",
))),
},
}
}
pub fn save_active_move_from_next_turn(&self, mov: MoveHandle) -> Result<()> {
match self.last_turn_moves.get_mut(&mov) {
Ok(active_move) => {
self.this_turn_moves.register(mov, active_move.clone());
}
Err(BorrowError::OutOfBounds) => (),
result @ _ => {
return result
.map(|_| ())
.map_err(|err| err.convert_error_with_message(format!("active move {mov}")));
}
}
Ok(())
}
pub fn next_turn(&mut self) -> Result<()> {
if !self.last_turn_moves.safe_to_drop() {
return Err(general_error(
"cannot advance battle registry to the next turn: last_turn_moves is not safe to drop",
));
}
core::mem::swap(&mut self.last_turn_moves, &mut self.this_turn_moves);
self.this_turn_moves = MoveRegistry::new();
Ok(())
}
}