#![no_std]
#![forbid(unsafe_code)]
#[cfg(test)]
extern crate alloc;
pub mod int;
pub(crate) mod internal;
mod dir;
pub use dir::Direction;
mod hex;
pub use hex::Hex;
mod iter;
pub use iter::{HexLine, HexRange, HexRing};
mod offset;
pub use offset::{EvenQ, EvenR, OddQ, OddR, OffsetHex, OffsetScheme};
pub type HexI = Hex<i32>;
pub type HexI16 = Hex<i16>;
pub type HexI8 = Hex<i8>;
#[macro_export]
macro_rules! hex {
($q:expr, $r:expr) => {
$crate::Hex::new($q, $r)
};
}
#[cfg(test)]
mod proptests {
use crate::Hex;
use proptest::prelude::*;
fn hex_strategy() -> impl Strategy<Value = Hex<i16>> {
(-45_i16..=45, -45_i16..=45).prop_map(|(q, r)| hex!(q, r))
}
fn radius_strategy() -> impl Strategy<Value = i16> {
0_i16..=10
}
proptest! {
#[test]
fn distance_symmetry(
a in hex_strategy(),
b in hex_strategy(),
) {
prop_assert_eq!(a.distance(b), b.distance(a));
}
#[test]
fn ring_count_formula(
center in hex_strategy(),
r in radius_strategy(),
) {
#[allow(clippy::cast_sign_loss)]
let expected = if r == 0 { 1 } else { 6 * r as usize };
prop_assert_eq!(center.ring(r).count(), expected);
}
#[test]
fn range_count_formula(
center in hex_strategy(),
r in radius_strategy(),
) {
let r = i32::from(r);
#[allow(clippy::cast_sign_loss)]
let expected = (3 * r * r + 3 * r + 1) as usize;
let center: Hex<i32> = Hex::new(i32::from(center.q), i32::from(center.r));
prop_assert_eq!(center.range(r).count(), expected);
}
#[test]
fn line_count_equals_distance_plus_one(
a in hex_strategy(),
b in hex_strategy(),
) {
#[allow(clippy::cast_sign_loss)]
let expected = a.distance(b) as usize + 1;
prop_assert_eq!(a.line_to(b).count(), expected);
}
#[test]
fn rotate_cw_six_times_identity(h in hex_strategy()) {
let mut cur = h;
for _ in 0..6 {
cur = cur.rotate_cw();
}
prop_assert_eq!(cur, h);
}
#[test]
fn reflect_q_involution(h in hex_strategy()) {
prop_assert_eq!(h.reflect_q().reflect_q(), h);
}
}
}