use crate::sim::direction::Direction;
use crate::sim::pose::Pose;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Handedness {
Left,
Right,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum CrabKind {
Common,
Juvenile,
Giant,
Molting,
Golden,
Sparkling,
}
impl CrabKind {
pub const ALL: [CrabKind; 6] = [
CrabKind::Common,
CrabKind::Juvenile,
CrabKind::Giant,
CrabKind::Molting,
CrabKind::Golden,
CrabKind::Sparkling,
];
pub fn token(self) -> &'static str {
match self {
CrabKind::Common => "common",
CrabKind::Juvenile => "juvenile",
CrabKind::Giant => "giant",
CrabKind::Molting => "molting",
CrabKind::Golden => "golden",
CrabKind::Sparkling => "sparkling",
}
}
pub fn from_token(token: &str) -> Option<CrabKind> {
Self::ALL.iter().copied().find(|k| k.token() == token)
}
pub fn speed(self) -> u16 {
match self {
CrabKind::Common | CrabKind::Molting | CrabKind::Sparkling => 12,
CrabKind::Juvenile => 18, CrabKind::Giant => 7, CrabKind::Golden => 15, }
}
pub fn value(self) -> u32 {
match self {
CrabKind::Common => 1,
CrabKind::Juvenile => 2,
CrabKind::Molting => 5,
CrabKind::Giant => 10,
CrabKind::Golden => 50,
CrabKind::Sparkling => 1, }
}
pub(crate) fn id(self) -> u8 {
match self {
CrabKind::Common => 0,
CrabKind::Juvenile => 1,
CrabKind::Giant => 2,
CrabKind::Molting => 3,
CrabKind::Golden => 4,
CrabKind::Sparkling => 5,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct Crab {
pub id: u32,
pub tile: u16,
pub dir: Direction,
pub progress: u16,
pub prev: Pose,
pub handed: Handedness,
pub kind: CrabKind,
}
impl Crab {
pub fn bank_points(&self, value: u32, claw_call: bool) -> i32 {
let value = value as i32;
match (claw_call, self.handed) {
(false, _) => value,
(true, Handedness::Right) => value * 2,
(true, Handedness::Left) => -value,
}
}
pub fn pose(&self) -> Pose {
Pose {
tile: self.tile,
dir: self.dir,
progress: self.progress,
}
}
}
impl Handedness {
pub(crate) fn id(self) -> u8 {
match self {
Handedness::Left => 0,
Handedness::Right => 1,
}
}
pub fn token(self) -> &'static str {
match self {
Handedness::Left => "L",
Handedness::Right => "R",
}
}
pub fn from_token(token: &str) -> Option<Handedness> {
match token {
"L" => Some(Handedness::Left),
"R" => Some(Handedness::Right),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::{CrabKind, Handedness};
#[test]
fn tokens_round_trip_for_every_kind() {
for kind in CrabKind::ALL {
assert_eq!(CrabKind::from_token(kind.token()), Some(kind));
}
assert_eq!(CrabKind::from_token("hermit"), None);
for handed in [Handedness::Left, Handedness::Right] {
assert_eq!(Handedness::from_token(handed.token()), Some(handed));
}
}
#[test]
fn golden_crab_is_the_jackpot() {
assert_eq!(CrabKind::Golden.value(), 50);
assert!(CrabKind::Golden.speed() > CrabKind::Common.speed());
assert!(CrabKind::Golden.speed() < CrabKind::Juvenile.speed());
}
}