use crate::Hex;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "ser_de", derive(serde::Serialize, serde::Deserialize))]
pub struct HexMap {
radius: u32,
center: Hex,
mirrors: [Hex; 6],
}
impl HexMap {
#[inline]
#[must_use]
pub const fn new(radius: u32) -> Self {
Self {
radius,
center: Hex::ZERO,
mirrors: Hex::wraparound_mirrors(radius),
}
}
#[inline]
#[must_use]
pub fn with_center(self, center: Hex) -> Self {
Self {
radius: self.radius,
center,
mirrors: self.mirrors.map(|h| h + center),
}
}
#[inline]
#[must_use]
pub const fn center(&self) -> Hex {
self.center
}
#[inline]
#[must_use]
pub const fn radius(&self) -> u32 {
self.radius
}
#[must_use]
pub fn wrapped_hex(&self, hex: Hex) -> Hex {
let pos = hex - self.center;
let pos = pos.wrap_with(self.radius, &self.mirrors);
pos + self.center
}
#[must_use]
#[inline]
pub fn wrapped_neighbors(&self, hex: Hex) -> [Hex; 6] {
hex.all_neighbors().map(|h| self.wrapped_hex(h))
}
#[must_use]
#[inline]
pub const fn hex_count(&self) -> usize {
Hex::range_count(self.radius)
}
pub fn all_coords(&self) -> impl Iterator<Item = Hex> {
self.center.range(self.radius)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn wrapping_works() {
let map = HexMap::new(3);
assert_eq!(map.wrapped_hex(Hex::new(0, 4)), Hex::new(-3, 0));
assert_eq!(map.wrapped_hex(Hex::new(4, 0)), Hex::new(-3, 3));
assert_eq!(map.wrapped_hex(Hex::new(4, -4)), Hex::new(0, 3));
}
#[test]
fn wrapping_outside_works() {
let map = HexMap::new(2);
assert_eq!(map.wrapped_hex(Hex::new(3, 0)), Hex::new(-2, 2));
assert_eq!(map.wrapped_hex(Hex::new(5, 0)), Hex::new(0, 2));
assert_eq!(map.wrapped_hex(Hex::new(6, 0)), Hex::new(-1, -1));
assert_eq!(map.wrapped_hex(Hex::new(2, 3)), Hex::new(0, 0)); assert_eq!(map.wrapped_hex(Hex::new(4, 6)), Hex::new(0, 0));
}
}