use crate::coordinates::{ Distance, Neighbors };
use serde::{ Deserialize, Serialize };
use std::fmt::Debug;
use std::hash::Hash;
use std::marker::PhantomData;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct TwelveConnected;
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Coordinate<Connectivity> {
pub x: i32,
pub y: i32,
#[serde(skip)]
pub _marker: PhantomData<Connectivity>,
}
impl<Connectivity> Coordinate<Connectivity> {
pub const fn new(x: i32, y: i32) -> Self {
Self {
x,
y,
_marker: PhantomData,
}
}
pub fn is_up_pointing(&self) -> bool {
self.x.wrapping_add(self.y) % 2 == 0
}
pub fn is_down_pointing(&self) -> bool {
!self.is_up_pointing()
}
}
impl From<(i32, i32)> for Coordinate<TwelveConnected> {
fn from((x, y): (i32, i32)) -> Self {
Self::new(x, y)
}
}
impl From<[i32; 2]> for Coordinate<TwelveConnected> {
fn from([x, y]: [i32; 2]) -> Self {
Self::new(x, y)
}
}
impl Into<(i32, i32)> for Coordinate<TwelveConnected> {
fn into(self) -> (i32, i32) {
(self.x, self.y)
}
}
impl Into<[i32; 2]> for Coordinate<TwelveConnected> {
fn into(self) -> [i32; 2] {
[self.x, self.y]
}
}
impl Distance for Coordinate<TwelveConnected> {
fn distance(&self, other: &Self) -> u32 {
let dx = (self.x - other.x).abs();
let dy = (self.y - other.y).abs();
dx.max(dy) as u32
}
}
impl Neighbors for Coordinate<TwelveConnected> {
fn neighbors(&self) -> Vec<Self> {
if self.is_up_pointing() {
vec![
Self::new(self.x - 1, self.y), Self::new(self.x + 1, self.y), Self::new(self.x, self.y - 1),
Self::new(self.x - 2, self.y), Self::new(self.x + 2, self.y), Self::new(self.x, self.y - 2), Self::new(self.x - 1, self.y - 1), Self::new(self.x + 1, self.y - 1), Self::new(self.x - 1, self.y + 1), Self::new(self.x + 1, self.y + 1), Self::new(self.x, self.y + 1), Self::new(self.x, self.y + 2), ]
} else {
vec![
Self::new(self.x - 1, self.y), Self::new(self.x + 1, self.y), Self::new(self.x, self.y + 1),
Self::new(self.x - 2, self.y), Self::new(self.x + 2, self.y), Self::new(self.x, self.y + 2), Self::new(self.x - 1, self.y - 1), Self::new(self.x + 1, self.y - 1), Self::new(self.x - 1, self.y + 1), Self::new(self.x + 1, self.y + 1), Self::new(self.x, self.y - 1), Self::new(self.x, self.y - 2), ]
}
}
}
pub type TriangularCoord = Coordinate<TwelveConnected>;