1use crate::sim::direction::Direction;
2
3#[derive(Clone, Copy, PartialEq, Eq, Debug)]
7pub enum Handedness {
8 Left,
9 Right,
10}
11
12#[derive(Clone, Copy, PartialEq, Eq, Debug)]
13pub enum CrabKind {
14 Common,
15 Juvenile,
16 Giant,
17 Molting,
20 Golden,
23 Sparkling,
26}
27
28impl CrabKind {
29 pub const ALL: [CrabKind; 6] = [
30 CrabKind::Common,
31 CrabKind::Juvenile,
32 CrabKind::Giant,
33 CrabKind::Molting,
34 CrabKind::Golden,
35 CrabKind::Sparkling,
36 ];
37
38 pub fn token(self) -> &'static str {
40 match self {
41 CrabKind::Common => "common",
42 CrabKind::Juvenile => "juvenile",
43 CrabKind::Giant => "giant",
44 CrabKind::Molting => "molting",
45 CrabKind::Golden => "golden",
46 CrabKind::Sparkling => "sparkling",
47 }
48 }
49
50 pub fn from_token(token: &str) -> Option<CrabKind> {
51 Self::ALL.iter().copied().find(|k| k.token() == token)
52 }
53
54 pub fn speed(self) -> u16 {
56 match self {
57 CrabKind::Common | CrabKind::Molting | CrabKind::Sparkling => 12,
58 CrabKind::Juvenile => 18, CrabKind::Giant => 7, CrabKind::Golden => 15, }
62 }
63
64 pub fn value(self) -> u32 {
69 match self {
70 CrabKind::Common => 1,
71 CrabKind::Juvenile => 2,
72 CrabKind::Molting => 5,
73 CrabKind::Giant => 10,
74 CrabKind::Golden => 50,
75 CrabKind::Sparkling => 1, }
77 }
78
79 pub(crate) fn id(self) -> u8 {
80 match self {
81 CrabKind::Common => 0,
82 CrabKind::Juvenile => 1,
83 CrabKind::Giant => 2,
84 CrabKind::Molting => 3,
85 CrabKind::Golden => 4,
86 CrabKind::Sparkling => 5,
87 }
88 }
89}
90
91#[derive(Clone, Copy, Debug)]
96pub struct Crab {
97 pub id: u32,
100 pub tile: u16,
101 pub dir: Direction,
102 pub progress: u16,
103 pub prev_tile: u16,
104 pub prev_progress: u16,
105 pub prev_dir: Direction,
106 pub handed: Handedness,
107 pub kind: CrabKind,
108}
109
110impl Handedness {
111 pub(crate) fn id(self) -> u8 {
112 match self {
113 Handedness::Left => 0,
114 Handedness::Right => 1,
115 }
116 }
117
118 pub fn token(self) -> &'static str {
120 match self {
121 Handedness::Left => "L",
122 Handedness::Right => "R",
123 }
124 }
125
126 pub fn from_token(token: &str) -> Option<Handedness> {
127 match token {
128 "L" => Some(Handedness::Left),
129 "R" => Some(Handedness::Right),
130 _ => None,
131 }
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::{CrabKind, Handedness};
138
139 #[test]
140 fn tokens_round_trip_for_every_kind() {
141 for kind in CrabKind::ALL {
142 assert_eq!(CrabKind::from_token(kind.token()), Some(kind));
143 }
144 assert_eq!(CrabKind::from_token("hermit"), None);
145 for handed in [Handedness::Left, Handedness::Right] {
146 assert_eq!(Handedness::from_token(handed.token()), Some(handed));
147 }
148 }
149
150 #[test]
151 fn golden_crab_is_the_jackpot() {
152 assert_eq!(CrabKind::Golden.value(), 50);
153 assert!(CrabKind::Golden.speed() > CrabKind::Common.speed());
154 assert!(CrabKind::Golden.speed() < CrabKind::Juvenile.speed());
155 }
156}