#[cfg(feature = "bevy")]
use bevy_ecs::prelude::Component;
#[cfg(feature = "bevy")]
use bevy_reflect::Reflect;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::hash::Hash;
use crate::{Node, NodeAx, distance::*};
pub trait Hex:
Eq + Hash + Distance<isize> + Into<HexCb> + Into<HexAx> + From<HexAx> + Copy
{
fn n_south_west(&self) -> impl Node {
let ax: HexAx = (*self).into();
NodeAx::new(ax.q * 3 - 1, ax.r * 3 - 1)
}
fn n_south_east(&self) -> impl Node {
let ax: HexAx = (*self).into();
NodeAx::new(ax.q * 3 + 1, ax.r * 3 - 2)
}
fn n_east(&self) -> impl Node {
let ax: HexAx = (*self).into();
NodeAx::new(ax.q * 3 + 2, ax.r * 3 - 1)
}
fn n_north_east(&self) -> impl Node {
let ax: HexAx = (*self).into();
NodeAx::new(ax.q * 3 + 1, ax.r * 3 + 1)
}
fn n_north_west(&self) -> impl Node {
let ax: HexAx = (*self).into();
NodeAx::new(ax.q * 3 - 1, ax.r * 3 + 2)
}
fn n_west(&self) -> impl Node {
let ax: HexAx = (*self).into();
NodeAx::new(ax.q * 3 - 2, ax.r * 3 + 1)
}
}
#[derive(Eq, PartialEq, Debug, Copy, Clone, Hash, Default)]
#[cfg_attr(feature = "bevy", derive(Reflect, Component))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
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 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 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 crate::neighbours::Hexes;
use super::*;
#[test]
fn coords_of_cube_sum_to_0() {
let x = HexAx::new(0, 0);
let x_cb = HexCb::from(x);
let neighbours: Vec<HexAx> = x.hexes().collect();
assert_eq!(neighbours.len(), 6);
for (i, y) in neighbours.iter().map(|ax| HexCb::from(*ax)).enumerate() {
assert_eq!(y.q + y.r + y.s, 0);
assert_ne!(y, x_cb);
assert_eq!(y.dist(&x_cb), 1);
for z in neighbours[i + 1..].iter().map(|ax| HexCb::from(*ax)) {
assert_ne!(y, z);
}
}
}
}