use std::{collections::HashSet, hash::Hash};
use crate::{distance::*, edge::*, neighbours::*, node::Node};
pub trait Hex:
Eq + Hash + Neighbour + Distance<isize> + Into<HexCb> + Into<HexAx> + From<HexAx> + Copy
{
fn edges<T>(&self) -> HashSet<T>
where
T: Edge,
{
self
.neighbours()
.map(|n| EdgeAx::between(self, &n).into())
.collect()
}
fn nodes<T>(&self) -> HashSet<T>
where
T: Node,
{
self
.edges()
.into_iter()
.flat_map(|e: EdgeAx| e.nodes())
.collect()
}
}
#[derive(Eq, PartialEq, Debug, Copy, Clone, Hash)]
pub struct HexAx {
pub q: isize,
pub r: isize,
}
impl HexAx {
pub fn new(q: isize, r: isize) -> Self {
HexAx { q, r }
}
}
impl From<HexCb> for HexAx {
fn from(cb: HexCb) -> Self {
HexAx::new(cb.q, cb.r)
}
}
impl Neighbour for HexAx {
fn get_neighbour(&self, n: u8) -> Option<HexAx> {
match n {
0 => Some(HexAx::new(self.q, self.r + 1)),
1 => Some(HexAx::new(self.q + 1, self.r)),
2 => Some(HexAx::new(self.q + 1, self.r - 1)),
3 => Some(HexAx::new(self.q, self.r - 1)),
4 => Some(HexAx::new(self.q - 1, self.r)),
5 => Some(HexAx::new(self.q - 1, self.r + 1)),
_ => None,
}
}
}
impl Hex for HexAx {}
pub struct FHexAx {
pub q: f32,
pub r: f32,
}
impl FHexAx {
pub fn new(q: f32, r: f32) -> Self {
FHexAx { q, r }
}
}
impl From<&HexAx> for FHexAx {
fn from(value: &HexAx) -> Self {
FHexAx::new(value.q as f32, value.r as f32)
}
}
#[derive(Eq, PartialEq, Debug, Copy, Clone, Hash)]
pub struct HexCb {
pub q: isize,
pub r: isize,
pub s: isize,
}
impl HexCb {
pub fn new(q: isize, r: isize, s: isize) -> HexCb {
HexCb { q, r, s }
}
}
impl From<HexAx> for HexCb {
fn from(ax: HexAx) -> Self {
HexCb::new(ax.q, ax.r, -ax.q - ax.r)
}
}
impl Neighbour for HexCb {
fn get_neighbour(&self, n: u8) -> Option<HexCb> {
match n {
0 => Some(HexCb::new(self.q, self.r + 1, self.s - 1)),
1 => Some(HexCb::new(self.q + 1, self.r, self.s - 1)),
2 => Some(HexCb::new(self.q + 1, self.r - 1, self.s)),
3 => Some(HexCb::new(self.q, self.r - 1, self.s + 1)),
4 => Some(HexCb::new(self.q - 1, self.r, self.s + 1)),
5 => Some(HexCb::new(self.q - 1, self.r + 1, self.s)),
_ => None,
}
}
}
impl Hex for HexCb {}
#[derive(PartialEq, Debug, Copy, Clone)]
pub struct FHexCb {
pub q: f32,
pub r: f32,
pub s: f32,
}
impl FHexCb {
pub fn new(q: f32, r: f32, s: f32) -> FHexCb {
FHexCb { q, r, s }
}
}
impl From<&FHexAx> for FHexCb {
fn from(value: &FHexAx) -> Self {
FHexCb::new(value.q, value.r, -value.q - value.r)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn coords_of_cube_sum_to_0() {
let x = HexCb::new(0, 0, 0);
let neighbours: Vec<HexCb> = x.neighbours().collect();
assert_eq!(neighbours.len(), 6);
for (i, y) in neighbours.iter().enumerate() {
assert_eq!(y.q + y.r + y.s, 0);
assert_ne!(*y, x);
assert_eq!(y.dist(&x), 1);
for z in neighbours[i + 1..].iter() {
assert_ne!(*y, *z);
}
}
}
}