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