diff --git a/core/src/coordinates.rs b/core/src/coordinates.rs index 54aeb1a..f165a9a 100644 --- a/core/src/coordinates.rs +++ b/core/src/coordinates.rs @@ -1,28 +1,7 @@ // Eryn Wells use crate::Color; -use std::fmt; -use std::str::FromStr; - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[repr(u8)] -pub enum Direction { - North, - NorthWest, - West, - SouthWest, - South, - SouthEast, - East, - NorthEast, -} - -impl Direction { - pub fn to_offset(&self) -> i8 { - const OFFSETS: [i8; 8] = [8, 7, -1, -9, -8, -7, 1, 9]; - OFFSETS[*self as usize] - } -} +use std::{fmt, str::FromStr}; macro_rules! try_from_integer { ($type:ident, $int_type:ident) => { @@ -30,14 +9,14 @@ macro_rules! try_from_integer { type Error = (); fn try_from(value: $int_type) -> Result { - Square::try_from(value as u8) + Self::try_from(value as u8) } } }; } macro_rules! coordinate_enum { - ($name: ident, $($variant:ident),*) => { + ($name: ident, [ $($variant:ident),* ]) => { #[repr(u8)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum $name { @@ -69,7 +48,7 @@ macro_rules! coordinate_enum { } macro_rules! range_bound_struct { - ($vis:vis, $type:ident, $repr:ty, $max:expr) => { + ($vis:vis $type:ident, $repr:ty, $max:expr) => { #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] $vis struct $type($repr); @@ -113,7 +92,34 @@ macro_rules! range_bound_struct { } } -range_bound_struct!(pub, File, u8, 8); +coordinate_enum!( + Direction, + [North, NorthEast, East, SouthEast, South, SouthWest, West, NorthWest] +); + +impl Direction { + pub fn to_offset(&self) -> i8 { + const OFFSETS: [i8; 8] = [8, 9, 1, -7, -8, -9, -1, 7]; + OFFSETS[*self as usize] + } + + pub fn opposite(&self) -> Direction { + const OPPOSITES: [Direction; 8] = [ + Direction::South, + Direction::SouthEast, + Direction::East, + Direction::NorthEast, + Direction::North, + Direction::NorthWest, + Direction::West, + Direction::SouthWest, + ]; + + OPPOSITES[*self as usize] + } +} + +range_bound_struct!(pub File, u8, 8); impl File { pub const A: File = File(0); @@ -137,7 +143,7 @@ impl File { ]; } -range_bound_struct!(pub, Rank, u8, 8); +range_bound_struct!(pub Rank, u8, 8); #[allow(dead_code)] impl Rank { @@ -182,7 +188,7 @@ impl Rank { } #[rustfmt::skip] -coordinate_enum!(Square, +coordinate_enum!(Square, [ A1, B1, C1, D1, E1, F1, G1, H1, A2, B2, C2, D2, E2, F2, G2, H2, A3, B3, C3, D3, E3, F3, G3, H3, @@ -191,7 +197,7 @@ coordinate_enum!(Square, A6, B6, C6, D6, E6, F6, G6, H6, A7, B7, C7, D7, E7, F7, G7, H7, A8, B8, C8, D8, E8, F8, G8, H8 -); +]); impl Square { pub unsafe fn from_index(x: u8) -> Square { @@ -357,6 +363,18 @@ impl TryFrom for Rank { mod tests { use super::*; + #[test] + fn direction_offsets() { + assert_eq!(Direction::North.to_offset(), 8); + assert_eq!(Direction::NorthEast.to_offset(), 9); + assert_eq!(Direction::East.to_offset(), 1); + assert_eq!(Direction::SouthEast.to_offset(), -7); + assert_eq!(Direction::South.to_offset(), -8); + assert_eq!(Direction::SouthWest.to_offset(), -9); + assert_eq!(Direction::West.to_offset(), -1); + assert_eq!(Direction::NorthWest.to_offset(), 7); + } + #[test] fn good_algebraic_input() { let sq = Square::from_algebraic_str("a4").expect("Failed to parse 'a4' square");