#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum FighterStatus {
#[default]
Moving,
Stalled,
Attacking,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Fighter {
pub x: f32,
pub y: f32,
pub z: f32,
pub gradient_index: usize,
pub health: f32,
pub team_id: u64,
pub action_points: f32,
pub status: FighterStatus,
}
impl Fighter {
pub fn new(
team_id: u64,
x: f32,
y: f32,
z: f32,
gradient_index: usize,
health: f32,
) -> Self {
Self {
x,
y,
z,
gradient_index,
health: health.clamp(0.0, 1.0),
team_id,
action_points: 0.0,
status: FighterStatus::Moving,
}
}
pub fn position(&self) -> (f32, f32, f32) {
(self.x, self.y, self.z)
}
#[inline]
pub fn cell(&self, width: usize, height: usize, depth: usize) -> (usize, usize, usize) {
let max_x = width.saturating_sub(1);
let max_y = height.saturating_sub(1);
let max_z = depth.saturating_sub(1);
(
(self.x.max(0.0) as usize).min(max_x),
(self.y.max(0.0) as usize).min(max_y),
(self.z.max(0.0) as usize).min(max_z),
)
}
pub fn is_alive(&self) -> bool {
self.health > 0.0
}
}
impl Eq for Fighter {}
impl std::fmt::Display for Fighter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Fighter(pos=({:.1}, {:.1}, {:.1}), health={:.0}%)",
self.x, self.y, self.z, self.health * 100.0
)
}
}