[core] Rewrite Direction as a coordinate_enum!

- Order the values of Direction in a clockwise fashion
- Implement Direction::opposite() to return the opposing direction
- Make some small changes to the macros in this file to improve readability, maybe.
This commit is contained in:
Eryn Wells 2024-03-08 08:17:54 -08:00
parent 3f6ffef9f3
commit 82aa7a2b01

View file

@ -1,28 +1,7 @@
// Eryn Wells <eryn@erynwells.me>
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<Self, Self::Error> {
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<char> 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");