1use crate::{
2 Direction, Face, NUM_PENT_VERTS, NUM_PENTAGONS,
3 coord::{CoordIJK, FaceIJK},
4 error,
5};
6use core::fmt;
7
8pub const MAX: u8 = 121;
10
11const BASE_PENTAGONS: u128 = 0x0020_0802_0008_0100_8402_0040_0100_4010;
13
14#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
18#[repr(transparent)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20pub struct BaseCell(u8);
21
22impl BaseCell {
23 pub(crate) const fn new_unchecked(value: u8) -> Self {
29 debug_assert!(value <= MAX, "base cell out of range");
30 Self(value)
31 }
32
33 #[must_use]
45 pub const fn is_pentagon(self) -> bool {
46 BASE_PENTAGONS & (1 << self.0) != 0
47 }
48
49 #[must_use]
59 pub const fn count() -> u8 {
60 MAX + 1
61 }
62
63 pub fn iter() -> impl Iterator<Item = Self> {
73 (0..Self::count()).map(Self::new_unchecked)
74 }
75
76 pub(crate) fn is_cw_offset(self, face: Face) -> bool {
78 self.metadata()
79 .cw_offset_pent
80 .is_some_and(|(offset1, offset2)| {
81 offset1 == face || offset2 == face
82 })
83 }
84
85 pub(crate) fn rotation_count(self, face: Face) -> u8 {
88 let shift = usize::from(face) * 3;
89 let rotation =
90 (BASE_CELL_ROTATIONS[usize::from(self.0)] >> shift) & 0b111;
91
92 debug_assert_ne!(rotation, 0b111, "no cell {self} on face {face:?}");
93
94 rotation as u8
95 }
96
97 pub(crate) const fn is_polar_pentagon(self) -> bool {
100 self.0 == 4 || self.0 == 117
101 }
102
103 pub(crate) const fn pentagon_direction_faces(
107 self,
108 ) -> [Face; NUM_PENT_VERTS as usize] {
109 debug_assert!(self.is_pentagon(), "not a pentagon");
110
111 let mask = (1_u128 << self.0) - 1;
112 let index = (BASE_PENTAGONS & mask).count_ones();
113 PENTAGON_DIRECTION_FACES[index as usize]
114 }
115
116 pub(crate) fn neighbor(self, direction: Direction) -> Option<Self> {
120 let value = NEIGHBORS[usize::from(self)][usize::from(direction)];
121
122 Self::try_from(value).ok()
123 }
124
125 pub(crate) fn neighbor_rotation(self, direction: Direction) -> u8 {
129 let base = usize::from(self);
130 let to = usize::from(direction);
131
132 debug_assert_ne!(NEIGHBOR_60CCW_ROTS[base][to], 0xff);
133 NEIGHBOR_60CCW_ROTS[base][to]
134 }
135
136 pub(crate) fn direction(self, neighbor: Self) -> Option<Direction> {
140 NEIGHBORS[usize::from(self)]
141 .iter()
142 .position(|&cell| u8::from(neighbor) == cell)
143 .map(|dir| {
144 #[expect(
145 clippy::cast_possible_truncation,
146 reason = "Cast safe thx to bounds"
147 )]
148 Direction::new_unchecked(dir as u8)
150 })
151 }
152
153 fn metadata(self) -> &'static Metadata {
155 &METADATA[usize::from(self.0)]
156 }
157}
158
159impl TryFrom<u8> for BaseCell {
160 type Error = error::InvalidBaseCell;
161
162 fn try_from(value: u8) -> Result<Self, Self::Error> {
163 if value > MAX {
164 return Err(Self::Error::new(value, "out of range"));
165 }
166 Ok(Self(value))
167 }
168}
169
170impl From<BaseCell> for u8 {
171 fn from(value: BaseCell) -> Self {
172 value.0
173 }
174}
175
176impl From<BaseCell> for usize {
177 fn from(value: BaseCell) -> Self {
178 Self::from(value.0)
179 }
180}
181
182impl From<BaseCell> for FaceIJK {
183 fn from(value: BaseCell) -> Self {
184 let metadata = value.metadata();
185 Self {
186 face: metadata.home,
187 coord: metadata.coord,
188 }
189 }
190}
191
192impl fmt::Display for BaseCell {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 write!(f, "{}", self.0)
195 }
196}
197
198#[expect(
205 clippy::unusual_byte_groupings,
206 reason = "Grouping by 3 is more explicit here"
207)]
208const BASE_CELL_ROTATIONS: [u64; BaseCell::count() as usize] = [
209 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_001_000_101,
211 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_000_101_111,
212 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_001_000_101,
213 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_001_000_101_111,
214 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_100_011_010_001_000,
215 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_000_101,
216 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_001_000_111,
217 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_001_000_101_111,
218 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_101_111_111_001_000,
219 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_101_111,
220 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_101,
221 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_111,
222 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_001_000_101_111_111,
223 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_000_101_111_111,
224 0b1111_111_111_111_111_111_111_111_111_000_111_111_111_011_011_111_111_111_001_000_111,
225 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_000_101_111_111_001,
226 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_011_101_111_111_001_000,
227 0b1111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_111_111_111_111_011_111,
228 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_001_000,
229 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_111_111,
230 0b1111_111_111_111_111_111_111_111_111_011_111_111_111_000_111_111_111_111_011_111_111,
231 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_001_000_111_111,
232 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_101_111_111_111_000,
233 0b1111_111_111_111_111_111_111_111_111_111_011_111_111_111_000_111_111_111_111_011_111,
234 0b1111_111_111_111_111_111_111_111_111_111_000_111_111_111_011_011_111_111_111_001_000,
235 0b1111_111_111_111_111_111_111_111_111_011_011_111_111_111_000_111_111_111_111_011_111,
236 0b1111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_001_000_101_111_111,
237 0b1111_111_111_111_111_111_111_111_111_000_111_111_111_011_011_111_111_111_111_111_111,
238 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_000_101_111_111_111,
239 0b1111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_101_111_111,
240 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000,
241 0b1111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_101_111_111_001,
242 0b1111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_111_111_111_111_011,
243 0b1111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_011_101_111_111_111_000,
244 0b1111_111_111_111_111_111_111_111_011_111_111_111_111_000_111_111_111_111_011_111_111,
245 0b1111_111_111_111_111_111_111_111_111_000_111_111_111_111_011_111_111_111_111_111_111,
246 0b1111_111_111_111_111_111_111_111_011_011_111_111_111_000_111_111_111_111_011_111_111,
247 0b1111_111_111_111_111_111_111_111_111_111_000_111_111_111_011_011_111_111_111_111_111,
248 0b1111_111_111_111_111_111_111_111_000_111_111_111_011_011_111_111_111_001_000_111_111,
249 0b1111_111_111_111_111_111_111_111_111_111_011_111_111_111_000_111_111_111_111_111_111,
251 0b1111_111_111_111_111_111_111_111_111_011_111_111_111_000_111_111_111_111_111_111_111,
252 0b1111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_111_111_111_001,
253 0b1111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_001_000_111_111_111,
254 0b1111_111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_111_111_111,
255 0b1111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_101_111_111_111,
256 0b1111_111_111_111_111_111_111_111_111_011_011_111_111_111_000_111_111_111_111_111_111,
257 0b1111_111_111_111_011_111_111_111_111_000_111_111_111_011_011_111_111_111_111_111_111,
258 0b1111_111_111_111_111_111_111_111_011_111_111_111_000_111_111_111_111_011_111_111_111,
259 0b1111_111_111_111_111_111_011_111_111_111_111_111_111_111_111_000_111_111_111_111_011,
260 0b1111_111_111_111_111_111_000_111_111_111_111_011_111_111_111_011_000_111_111_111_001,
261 0b1111_111_111_111_111_111_011_111_111_111_011_111_111_111_111_000_111_111_111_111_011,
262 0b1111_111_111_111_111_111_111_111_000_111_111_111_011_011_111_111_111_111_111_111_111,
263 0b1111_111_111_111_111_111_111_111_111_111_000_111_111_111_111_011_111_111_111_111_111,
264 0b1111_111_111_111_111_111_111_111_111_111_111_011_111_111_111_111_000_111_111_111_111,
265 0b1111_111_111_111_111_111_111_111_000_111_111_111_111_011_111_111_111_111_111_111_111,
266 0b1111_111_111_111_111_111_111_111_011_011_111_111_111_000_111_111_111_111_111_111_111,
267 0b1111_111_111_111_011_111_111_111_111_000_111_111_111_111_011_111_111_111_111_111_111,
268 0b1111_111_111_111_111_011_111_111_111_111_000_111_111_111_011_001_111_111_111_111_111,
269 0b1111_111_111_111_111_111_111_000_111_111_111_011_011_111_111_111_001_000_111_111_111,
270 0b1111_111_111_111_111_011_111_111_111_111_000_111_111_111_011_111_111_111_111_111_111,
271 0b1111_111_111_111_011_111_111_111_111_000_111_111_111_011_111_111_111_111_111_111_111,
272 0b1111_111_111_111_111_111_011_111_111_111_111_000_111_111_111_111_011_111_111_111_111,
273 0b1111_111_111_111_111_111_111_011_111_111_111_111_000_111_111_111_111_011_111_111_111,
274 0b1111_111_111_111_000_001_111_111_111_011_011_111_111_111_000_111_111_111_111_111_111,
275 0b1111_111_111_111_111_111_111_011_011_111_111_111_000_111_111_111_111_011_111_111_111,
276 0b1111_111_111_111_111_111_111_011_111_111_111_000_111_111_111_111_011_111_111_111_111,
277 0b1111_111_111_111_111_111_000_111_111_111_111_011_111_111_111_011_111_111_111_111_111,
278 0b1111_111_111_111_111_111_011_111_111_111_111_111_111_111_111_000_111_111_111_111_111,
279 0b1111_111_111_111_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111,
280 0b1111_111_111_111_111_111_111_111_011_111_111_111_000_111_111_111_111_111_111_111_111,
281 0b1111_111_111_111_111_111_011_111_111_111_011_111_111_111_111_000_111_111_111_111_111,
282 0b1111_111_111_011_111_111_111_111_000_111_111_111_011_011_111_111_111_111_111_111_111,
283 0b1111_111_111_000_001_111_111_111_011_011_111_111_111_000_111_111_111_111_111_111_111,
284 0b1111_111_111_011_111_111_111_111_000_111_111_111_111_011_111_111_111_111_111_111_111,
285 0b1111_111_111_111_111_011_111_111_111_111_000_111_111_111_111_011_111_111_111_111_111,
286 0b1111_111_111_111_111_111_011_011_111_111_111_000_111_111_111_111_011_111_111_111_111,
287 0b1111_111_111_111_111_111_111_000_111_111_111_011_011_111_111_111_111_111_111_111_111,
288 0b1111_111_111_111_000_001_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111,
289 0b1111_111_111_111_111_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111_111,
291 0b1111_111_111_111_101_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111_111,
292 0b1111_111_111_101_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111,
293 0b1111_111_111_111_111_111_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111,
294 0b1111_111_111_111_111_111_111_000_111_111_111_111_011_111_111_111_111_111_111_111_111,
295 0b1111_001_111_111_111_000_011_111_111_111_011_111_111_111_111_000_111_111_111_111_111,
296 0b1111_111_111_111_111_111_111_011_011_111_111_111_000_111_111_111_111_111_111_111_111,
297 0b1111_011_111_111_111_111_000_111_111_111_111_011_111_111_111_011_111_111_111_111_111,
298 0b1111_111_111_111_111_111_111_011_111_111_111_000_111_111_111_111_111_111_111_111_111,
299 0b1111_011_111_111_111_111_000_111_111_111_111_111_111_111_111_011_111_111_111_111_111,
300 0b1111_111_111_000_001_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111_111,
301 0b1111_111_111_011_111_111_111_111_000_111_111_111_011_111_111_111_111_111_111_111_111,
302 0b1111_111_111_101_000_001_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111,
303 0b1111_111_111_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111_111,
304 0b1111_001_111_111_111_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111_111,
305 0b1111_111_111_111_000_001_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
306 0b1111_111_111_111_111_111_011_011_111_111_111_000_111_111_111_111_111_111_111_111_111,
307 0b1111_001_111_111_101_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111_111,
308 0b1111_111_011_111_111_111_111_000_111_111_111_011_011_111_111_111_111_111_111_111_111,
309 0b1111_111_000_001_111_111_111_011_011_111_111_111_000_111_111_111_111_111_111_111_111,
310 0b1111_111_011_111_111_111_111_000_111_111_111_111_011_111_111_111_111_111_111_111_111,
311 0b1111_111_111_000_001_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
312 0b1111_000_111_111_111_101_011_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
313 0b1111_011_111_111_111_111_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111,
314 0b1111_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
315 0b1111_111_101_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111_111,
316 0b1111_111_011_111_111_111_111_000_111_111_111_011_111_111_111_111_111_111_111_111_111,
317 0b1111_111_101_000_001_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111_111,
318 0b1111_111_111_101_000_001_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
319 0b1111_000_001_111_111_111_011_011_111_111_111_000_111_111_111_111_111_111_111_111_111,
320 0b1111_001_111_111_111_000_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
321 0b1111_001_111_111_101_000_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
322 0b1111_111_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111_111_111,
323 0b1111_111_000_001_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111_111_111,
324 0b1111_000_001_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
325 0b1111_111_101_000_001_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
326 0b1111_000_001_111_111_101_011_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
327 0b1111_101_000_111_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111_111_111,
328 0b1111_111_000_001_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
329 0b1111_000_001_010_011_100_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
330 0b1111_000_001_111_111_101_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
331 0b1111_101_000_001_111_111_111_011_111_111_111_111_111_111_111_111_111_111_111_111_111,
332 0b1111_000_001_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
333 0b1111_101_000_001_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111_111,
334 ];
336
337struct Metadata {
341 home: Face,
343 coord: CoordIJK,
345 cw_offset_pent: Option<(Face, Face)>,
347}
348
349macro_rules! metadata {
350 ($home:literal, [$i:literal, $j:literal, $k: literal]) => {
351 Metadata {
352 home: Face::new_unchecked($home),
353 coord: CoordIJK::new($i, $j, $k),
354 cw_offset_pent: None,
355 }
356 };
357 ($home:literal, [$i:literal, $j:literal, $k: literal], ($offset1:literal, $offset2:literal)) => {
358 Metadata {
359 home: Face::new_unchecked($home),
360 coord: CoordIJK::new($i, $j, $k),
361 cw_offset_pent: Some((
362 Face::new_unchecked($offset1),
363 Face::new_unchecked($offset2),
364 )),
365 }
366 };
367}
368
369#[rustfmt::skip]
371const METADATA: [Metadata; 122] = [
372 metadata!(1, [1, 0, 0]),
373 metadata!(2, [1, 1, 0]),
374 metadata!(1, [0, 0, 0]),
375 metadata!(2, [1, 0, 0]),
376 metadata!(0, [2, 0, 0]),
377 metadata!(1, [1, 1, 0]),
378 metadata!(1, [0, 0, 1]),
379 metadata!(2, [0, 0, 0]),
380 metadata!(0, [1, 0, 0]),
381 metadata!(2, [0, 1, 0]),
382 metadata!(1, [0, 1, 0]),
383 metadata!(1, [0, 1, 1]),
384 metadata!(3, [1, 0, 0]),
385 metadata!(3, [1, 1, 0]),
386 metadata!(11, [2, 0, 0], (2, 6)),
387 metadata!(4, [1, 0, 0]),
388 metadata!(0, [0, 0, 0]),
389 metadata!(6, [0, 1, 0]),
390 metadata!(0, [0, 0, 1]),
391 metadata!(2, [0, 1, 1]),
392 metadata!(7, [0, 0, 1]),
393 metadata!(2, [0, 0, 1]),
394 metadata!(0, [1, 1, 0]),
395 metadata!(6, [0, 0, 1]),
396 metadata!(10, [2, 0, 0], (1, 5)),
397 metadata!(6, [0, 0, 0]),
398 metadata!(3, [0, 0, 0]),
399 metadata!(11, [1, 0, 0]),
400 metadata!(4, [1, 1, 0]),
401 metadata!(3, [0, 1, 0]),
402 metadata!(0, [0, 1, 1]),
403 metadata!(4, [0, 0, 0]),
404 metadata!(5, [0, 1, 0]),
405 metadata!(0, [0, 1, 0]),
406 metadata!(7, [0, 1, 0]),
407 metadata!(11, [1, 1, 0]),
408 metadata!(7, [0, 0, 0]),
409 metadata!(10, [1, 0, 0]),
410 metadata!(12, [2, 0, 0], (3, 7)),
411 metadata!(6, [1, 0, 1]),
412 metadata!(7, [1, 0, 1]),
413 metadata!(4, [0, 0, 1]),
414 metadata!(3, [0, 0, 1]),
415 metadata!(3, [0, 1, 1]),
416 metadata!(4, [0, 1, 0]),
417 metadata!(6, [1, 0, 0]),
418 metadata!(11, [0, 0, 0]),
419 metadata!(8, [0, 0, 1]),
420 metadata!(5, [0, 0, 1]),
421 metadata!(14, [2, 0, 0], (0, 9)),
422 metadata!(5, [0, 0, 0]),
423 metadata!(12, [1, 0, 0]),
424 metadata!(10, [1, 1, 0]),
425 metadata!(4, [0, 1, 1]),
426 metadata!(12, [1, 1, 0]),
427 metadata!(7, [1, 0, 0]),
428 metadata!(11, [0, 1, 0]),
429 metadata!(10, [0, 0, 0]),
430 metadata!(13, [2, 0, 0], (4, 8)),
431 metadata!(10, [0, 0, 1]),
432 metadata!(11, [0, 0, 1]),
433 metadata!(9, [0, 1, 0]),
434 metadata!(8, [0, 1, 0]),
435 metadata!(6, [2, 0, 0], (11, 15)),
436 metadata!(8, [0, 0, 0]),
437 metadata!(9, [0, 0, 1]),
438 metadata!(14, [1, 0, 0]),
439 metadata!(5, [1, 0, 1]),
440 metadata!(16, [0, 1, 1]),
441 metadata!(8, [1, 0, 1]),
442 metadata!(5, [1, 0, 0]),
443 metadata!(12, [0, 0, 0]),
444 metadata!(7, [2, 0, 0], (12, 16)),
445 metadata!(12, [0, 1, 0]),
446 metadata!(10, [0, 1, 0]),
447 metadata!(9, [0, 0, 0]),
448 metadata!(13, [1, 0, 0]),
449 metadata!(16, [0, 0, 1]),
450 metadata!(15, [0, 1, 1]),
451 metadata!(15, [0, 1, 0]),
452 metadata!(16, [0, 1, 0]),
453 metadata!(14, [1, 1, 0]),
454 metadata!(13, [1, 1, 0]),
455 metadata!(5, [2, 0, 0], (10, 19)),
456 metadata!(8, [1, 0, 0]),
457 metadata!(14, [0, 0, 0]),
458 metadata!(9, [1, 0, 1]),
459 metadata!(14, [0, 0, 1]),
460 metadata!(17, [0, 0, 1]),
461 metadata!(12, [0, 0, 1]),
462 metadata!(16, [0, 0, 0]),
463 metadata!(17, [0, 1, 1]),
464 metadata!(15, [0, 0, 1]),
465 metadata!(16, [1, 0, 1]),
466 metadata!(9, [1, 0, 0]),
467 metadata!(15, [0, 0, 0]),
468 metadata!(13, [0, 0, 0]),
469 metadata!(8, [2, 0, 0], (13, 17)),
470 metadata!(13, [0, 1, 0]),
471 metadata!(17, [1, 0, 1]),
472 metadata!(19, [0, 1, 0]),
473 metadata!(14, [0, 1, 0]),
474 metadata!(19, [0, 1, 1]),
475 metadata!(17, [0, 1, 0]),
476 metadata!(13, [0, 0, 1]),
477 metadata!(17, [0, 0, 0]),
478 metadata!(16, [1, 0, 0]),
479 metadata!(9, [2, 0, 0], (14, 18)),
480 metadata!(15, [1, 0, 1]),
481 metadata!(15, [1, 0, 0]),
482 metadata!(18, [0, 1, 1]),
483 metadata!(18, [0, 0, 1]),
484 metadata!(19, [0, 0, 1]),
485 metadata!(17, [1, 0, 0]),
486 metadata!(19, [0, 0, 0]),
487 metadata!(18, [0, 1, 0]),
488 metadata!(18, [1, 0, 1]),
489 metadata!(19, [2, 0, 0]),
490 metadata!(19, [1, 0, 0]),
491 metadata!(18, [0, 0, 0]),
492 metadata!(19, [1, 0, 1]),
493 metadata!(18, [1, 0, 0]),
494];
495
496macro_rules! faces {
499 [$($face:literal),+] => {
500 [$(Face::new_unchecked($face),)*]
501 }
502}
503
504#[rustfmt::skip]
508const PENTAGON_DIRECTION_FACES: [[Face; NUM_PENT_VERTS as usize]; NUM_PENTAGONS as usize] = [
509 faces!( 4, 0, 2, 1, 3),
510 faces!( 6, 11, 2, 7, 1),
511 faces!( 5, 10, 1, 6, 0),
512 faces!( 7, 12, 3, 8, 2),
513 faces!( 9, 14, 0, 5, 4),
514 faces!( 8, 13, 4, 9, 3),
515 faces!(11, 6, 15, 10, 16),
516 faces!(12, 7, 16, 11, 17),
517 faces!(10, 5, 19, 14, 15),
518 faces!(13, 8, 17, 12, 18),
519 faces!(14, 9, 18, 13, 19),
520 faces!(15, 19, 17, 18, 16),
521];
522
523#[rustfmt::skip]
531const NEIGHBORS: [[u8; 7]; BaseCell::count() as usize] = [
532 [ 0, 1, 5, 2, 4, 3, 8],
533 [ 1, 7, 6, 9, 0, 3, 2],
534 [ 2, 6, 10, 11, 0, 1, 5],
535 [ 3, 13, 1, 7, 4, 12, 0],
536 [ 4, 0xff, 15, 8, 3, 0, 12],
537 [ 5, 2, 18, 10, 8, 0, 16],
538 [ 6, 14, 11, 17, 1, 9, 2],
539 [ 7, 21, 9, 19, 3, 13, 1],
540 [ 8, 5, 22, 16, 4, 0, 15],
541 [ 9, 19, 14, 20, 1, 7, 6],
542 [ 10, 11, 24, 23, 5, 2, 18],
543 [ 11, 17, 23, 25, 2, 6, 10],
544 [ 12, 28, 13, 26, 4, 15, 3],
545 [ 13, 26, 21, 29, 3, 12, 7],
546 [ 14, 0xff, 17, 27, 9, 20, 6],
547 [ 15, 22, 28, 31, 4, 8, 12],
548 [ 16, 18, 33, 30, 8, 5, 22],
549 [ 17, 11, 14, 6, 35, 25, 27],
550 [ 18, 24, 30, 32, 5, 10, 16],
551 [ 19, 34, 20, 36, 7, 21, 9],
552 [ 20, 14, 19, 9, 40, 27, 36],
553 [ 21, 38, 19, 34, 13, 29, 7],
554 [ 22, 16, 41, 33, 15, 8, 31],
555 [ 23, 24, 11, 10, 39, 37, 25],
556 [ 24, 0xff, 32, 37, 10, 23, 18],
557 [ 25, 23, 17, 11, 45, 39, 35],
558 [ 26, 42, 29, 43, 12, 28, 13],
559 [ 27, 40, 35, 46, 14, 20, 17],
560 [ 28, 31, 42, 44, 12, 15, 26],
561 [ 29, 43, 38, 47, 13, 26, 21],
562 [ 30, 32, 48, 50, 16, 18, 33],
563 [ 31, 41, 44, 53, 15, 22, 28],
564 [ 32, 30, 24, 18, 52, 50, 37],
565 [ 33, 30, 49, 48, 22, 16, 41],
566 [ 34, 19, 38, 21, 54, 36, 51],
567 [ 35, 46, 45, 56, 17, 27, 25],
568 [ 36, 20, 34, 19, 55, 40, 54],
569 [ 37, 39, 52, 57, 24, 23, 32],
570 [ 38, 0xff, 34, 51, 29, 47, 21],
571 [ 39, 37, 25, 23, 59, 57, 45],
572 [ 40, 27, 36, 20, 60, 46, 55],
573 [ 41, 49, 53, 61, 22, 33, 31],
574 [ 42, 58, 43, 62, 28, 44, 26],
575 [ 43, 62, 47, 64, 26, 42, 29],
576 [ 44, 53, 58, 65, 28, 31, 42],
577 [ 45, 39, 35, 25, 63, 59, 56],
578 [ 46, 60, 56, 68, 27, 40, 35],
579 [ 47, 38, 43, 29, 69, 51, 64],
580 [ 48, 49, 30, 33, 67, 66, 50],
581 [ 49, 0xff, 61, 66, 33, 48, 41],
582 [ 50, 48, 32, 30, 70, 67, 52],
583 [ 51, 69, 54, 71, 38, 47, 34],
584 [ 52, 57, 70, 74, 32, 37, 50],
585 [ 53, 61, 65, 75, 31, 41, 44],
586 [ 54, 71, 55, 73, 34, 51, 36],
587 [ 55, 40, 54, 36, 72, 60, 73],
588 [ 56, 68, 63, 77, 35, 46, 45],
589 [ 57, 59, 74, 78, 37, 39, 52],
590 [ 58, 0xff, 62, 76, 44, 65, 42],
591 [ 59, 63, 78, 79, 39, 45, 57],
592 [ 60, 72, 68, 80, 40, 55, 46],
593 [ 61, 53, 49, 41, 81, 75, 66],
594 [ 62, 43, 58, 42, 82, 64, 76],
595 [ 63, 0xff, 56, 45, 79, 59, 77],
596 [ 64, 47, 62, 43, 84, 69, 82],
597 [ 65, 58, 53, 44, 86, 76, 75],
598 [ 66, 67, 81, 85, 49, 48, 61],
599 [ 67, 66, 50, 48, 87, 85, 70],
600 [ 68, 56, 60, 46, 90, 77, 80],
601 [ 69, 51, 64, 47, 89, 71, 84],
602 [ 70, 67, 52, 50, 83, 87, 74],
603 [ 71, 89, 73, 91, 51, 69, 54],
604 [ 72, 0xff, 73, 55, 80, 60, 88],
605 [ 73, 91, 72, 88, 54, 71, 55],
606 [ 74, 78, 83, 92, 52, 57, 70],
607 [ 75, 65, 61, 53, 94, 86, 81],
608 [ 76, 86, 82, 96, 58, 65, 62],
609 [ 77, 63, 68, 56, 93, 79, 90],
610 [ 78, 74, 59, 57, 95, 92, 79],
611 [ 79, 78, 63, 59, 93, 95, 77],
612 [ 80, 68, 72, 60, 99, 90, 88],
613 [ 81, 85, 94, 101, 61, 66, 75],
614 [ 82, 96, 84, 98, 62, 76, 64],
615 [ 83, 0xff, 74, 70, 100, 87, 92],
616 [ 84, 69, 82, 64, 97, 89, 98],
617 [ 85, 87, 101, 102, 66, 67, 81],
618 [ 86, 76, 75, 65, 104, 96, 94],
619 [ 87, 83, 102, 100, 67, 70, 85],
620 [ 88, 72, 91, 73, 99, 80, 105],
621 [ 89, 97, 91, 103, 69, 84, 71],
622 [ 90, 77, 80, 68, 106, 93, 99],
623 [ 91, 73, 89, 71, 105, 88, 103],
624 [ 92, 83, 78, 74, 108, 100, 95],
625 [ 93, 79, 90, 77, 109, 95, 106],
626 [ 94, 86, 81, 75, 107, 104, 101],
627 [ 95, 92, 79, 78, 109, 108, 93],
628 [ 96, 104, 98, 110, 76, 86, 82],
629 [ 97, 0xff, 98, 84, 103, 89, 111],
630 [ 98, 110, 97, 111, 82, 96, 84],
631 [ 99, 80, 105, 88, 106, 90, 113],
632 [100, 102, 83, 87, 108, 114, 92],
633 [101, 102, 107, 112, 81, 85, 94],
634 [102, 101, 87, 85, 114, 112, 100],
635 [103, 91, 97, 89, 116, 105, 111],
636 [104, 107, 110, 115, 86, 94, 96],
637 [105, 88, 103, 91, 113, 99, 116],
638 [106, 93, 99, 90, 117, 109, 113],
639 [107, 0xff, 101, 94, 115, 104, 112],
640 [108, 100, 95, 92, 118, 114, 109],
641 [109, 108, 93, 95, 117, 118, 106],
642 [110, 98, 104, 96, 119, 111, 115],
643 [111, 97, 110, 98, 116, 103, 119],
644 [112, 107, 102, 101, 120, 115, 114],
645 [113, 99, 116, 105, 117, 106, 121],
646 [114, 112, 100, 102, 118, 120, 108],
647 [115, 110, 107, 104, 120, 119, 112],
648 [116, 103, 119, 111, 113, 105, 121],
649 [117, 0xff, 109, 118, 113, 121, 106],
650 [118, 120, 108, 114, 117, 121, 109],
651 [119, 111, 115, 110, 121, 116, 120],
652 [120, 115, 114, 112, 121, 119, 118],
653 [121, 116, 120, 119, 117, 113, 118],
654];
655
656#[rustfmt::skip]
665const NEIGHBOR_60CCW_ROTS: [[u8; 7]; BaseCell::count() as usize] = [
666 [0, 5, 0, 0, 1, 5, 1],
667 [0, 0, 1, 0, 1, 0, 1],
668 [0, 0, 0, 0, 0, 5, 0],
669 [0, 5, 0, 0, 2, 5, 1],
670 [0, 0xff, 1, 0, 3, 4, 2],
671 [0, 0, 1, 0, 1, 0, 1],
672 [0, 0, 0, 3, 5, 5, 0],
673 [0, 0, 0, 0, 0, 5, 0],
674 [0, 5, 0, 0, 0, 5, 1],
675 [0, 0, 1, 3, 0, 0, 1],
676 [0, 0, 1, 3, 0, 0, 1],
677 [0, 3, 3, 3, 0, 0, 0],
678 [0, 5, 0, 0, 3, 5, 1],
679 [0, 0, 1, 0, 1, 0, 1],
680 [0, 0xff, 3, 0, 5, 2, 0],
681 [0, 5, 0, 0, 4, 5, 1],
682 [0, 0, 0, 0, 0, 5, 0],
683 [0, 3, 3, 3, 3, 0, 3],
684 [0, 0, 0, 3, 5, 5, 0],
685 [0, 3, 3, 3, 0, 0, 0],
686 [0, 3, 3, 3, 0, 3, 0],
687 [0, 0, 0, 3, 5, 5, 0],
688 [0, 0, 1, 0, 1, 0, 1],
689 [0, 3, 3, 3, 0, 3, 0],
690 [0, 0xff, 3, 0, 5, 2, 0],
691 [0, 0, 0, 3, 0, 0, 3],
692 [0, 0, 0, 0, 0, 5, 0],
693 [0, 3, 0, 0, 0, 3, 3],
694 [0, 0, 1, 0, 1, 0, 1],
695 [0, 0, 1, 3, 0, 0, 1],
696 [0, 3, 3, 3, 0, 0, 0],
697 [0, 0, 0, 0, 0, 5, 0],
698 [0, 3, 3, 3, 3, 0, 3],
699 [0, 0, 1, 3, 0, 0, 1],
700 [0, 3, 3, 3, 3, 0, 3],
701 [0, 0, 3, 0, 3, 0, 3],
702 [0, 0, 0, 3, 0, 0, 3],
703 [0, 3, 0, 0, 0, 3, 3],
704 [0, 0xff, 3, 0, 5, 2, 0],
705 [0, 3, 0, 0, 3, 3, 0],
706 [0, 3, 0, 0, 3, 3, 0],
707 [0, 0, 0, 3, 5, 5, 0],
708 [0, 0, 0, 3, 5, 5, 0],
709 [0, 3, 3, 3, 0, 0, 0],
710 [0, 0, 1, 3, 0, 0, 1],
711 [0, 0, 3, 0, 0, 3, 3],
712 [0, 0, 0, 3, 0, 3, 0],
713 [0, 3, 3, 3, 0, 3, 0],
714 [0, 3, 3, 3, 0, 3, 0],
715 [0, 0xff, 3, 0, 5, 2, 0],
716 [0, 0, 0, 3, 0, 0, 3],
717 [0, 3, 0, 0, 0, 3, 3],
718 [0, 0, 3, 0, 3, 0, 3],
719 [0, 3, 3, 3, 0, 0, 0],
720 [0, 0, 3, 0, 3, 0, 3],
721 [0, 0, 3, 0, 0, 3, 3],
722 [0, 3, 3, 3, 0, 0, 3],
723 [0, 0, 0, 3, 0, 3, 0],
724 [0, 0xff, 3, 0, 5, 2, 0],
725 [0, 3, 3, 3, 3, 3, 0],
726 [0, 3, 3, 3, 3, 3, 0],
727 [0, 3, 3, 3, 3, 0, 3],
728 [0, 3, 3, 3, 3, 0, 3],
729 [0, 0xff, 3, 0, 5, 2, 0],
730 [0, 0, 0, 3, 0, 0, 3],
731 [0, 3, 3, 3, 0, 3, 0],
732 [0, 3, 0, 0, 0, 3, 3],
733 [0, 3, 0, 0, 3, 3, 0],
734 [0, 3, 3, 3, 0, 0, 0],
735 [0, 3, 0, 0, 3, 3, 0],
736 [0, 0, 3, 0, 0, 3, 3],
737 [0, 0, 0, 3, 0, 3, 0],
738 [0, 0xff, 3, 0, 5, 2, 0],
739 [0, 3, 3, 3, 0, 0, 3],
740 [0, 3, 3, 3, 0, 0, 3],
741 [0, 0, 0, 3, 0, 0, 3],
742 [0, 3, 0, 0, 0, 3, 3],
743 [0, 0, 0, 3, 0, 5, 0],
744 [0, 3, 3, 3, 0, 0, 0],
745 [0, 0, 1, 3, 1, 0, 1],
746 [0, 0, 1, 3, 1, 0, 1],
747 [0, 0, 3, 0, 3, 0, 3],
748 [0, 0, 3, 0, 3, 0, 3],
749 [0, 0xff, 3, 0, 5, 2, 0],
750 [0, 0, 3, 0, 0, 3, 3],
751 [0, 0, 0, 3, 0, 3, 0],
752 [0, 3, 0, 0, 3, 3, 0],
753 [0, 3, 3, 3, 3, 3, 0],
754 [0, 0, 0, 3, 0, 5, 0],
755 [0, 3, 3, 3, 3, 3, 0],
756 [0, 0, 0, 0, 0, 0, 1],
757 [0, 3, 3, 3, 0, 0, 0],
758 [0, 0, 0, 3, 0, 5, 0],
759 [0, 5, 0, 0, 5, 5, 0],
760 [0, 0, 3, 0, 0, 3, 3],
761 [0, 0, 0, 0, 0, 0, 1],
762 [0, 0, 0, 3, 0, 3, 0],
763 [0, 0xff, 3, 0, 5, 2, 0],
764 [0, 3, 3, 3, 0, 0, 3],
765 [0, 5, 0, 0, 5, 5, 0],
766 [0, 0, 1, 3, 1, 0, 1],
767 [0, 3, 3, 3, 0, 0, 3],
768 [0, 3, 3, 3, 0, 0, 0],
769 [0, 0, 1, 3, 1, 0, 1],
770 [0, 3, 3, 3, 3, 3, 0],
771 [0, 0, 0, 0, 0, 0, 1],
772 [0, 0, 1, 0, 3, 5, 1],
773 [0, 0xff, 3, 0, 5, 2, 0],
774 [0, 5, 0, 0, 5, 5, 0],
775 [0, 0, 1, 0, 4, 5, 1],
776 [0, 3, 3, 3, 0, 0, 0],
777 [0, 0, 0, 3, 0, 5, 0],
778 [0, 0, 0, 3, 0, 5, 0],
779 [0, 0, 1, 0, 2, 5, 1],
780 [0, 0, 0, 0, 0, 0, 1],
781 [0, 0, 1, 3, 1, 0, 1],
782 [0, 5, 0, 0, 5, 5, 0],
783 [0, 0xff, 1, 0, 3, 4, 2],
784 [0, 0, 1, 0, 0, 5, 1],
785 [0, 0, 0, 0, 0, 0, 1],
786 [0, 5, 0, 0, 5, 5, 0],
787 [0, 0, 1, 0, 1, 5, 1],
788];