diff --git a/Cargo.lock b/Cargo.lock index 3f17b55..04d3d7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1316,6 +1316,7 @@ version = "0.1.0" dependencies = [ "bevy", "bevy_egui", + "num", ] [[package]] @@ -2993,6 +2994,40 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +dependencies = [ + "num-traits", +] + [[package]] name = "num-derive" version = "0.3.3" @@ -3004,6 +3039,38 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.18" diff --git a/crates/border-wars/Cargo.toml b/crates/border-wars/Cargo.toml index 19f39d9..389e9b0 100644 --- a/crates/border-wars/Cargo.toml +++ b/crates/border-wars/Cargo.toml @@ -13,3 +13,4 @@ workspace = true [dependencies] bevy = "0.12.1" bevy_egui = "0.24.0" +num = "0.4.1" diff --git a/crates/border-wars/src/hex.rs b/crates/border-wars/src/hex.rs index 1761ab5..7462106 100644 --- a/crates/border-wars/src/hex.rs +++ b/crates/border-wars/src/hex.rs @@ -1,21 +1,44 @@ //! All functions related to calculations in a hexagonal grid. use std::collections::HashSet; +use std::hash::Hash; use std::ops; +use num::Signed; + +/// Represents a number that can be used in a hexagonal grid. +pub trait HexNumber: Signed + PartialEq + Copy + PartialOrd { + /// Returns the minimum value between `self` and `other`. + fn min(&self, other: Self) -> Self { + if *self < other { + return *self; + } + other + } + + /// Returns the maximum value between `self` and `other`. + fn max(&self, other: Self) -> Self { + if *self > other { + return *self; + } + other + } +} +impl HexNumber for T {} + /// Represents a position in a hexagonal grid. /// We use the axial coordinate system explained in this /// [documentation](https://www.redblobgames.com/grids/hexagons/#coordinates). #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct HexPosition { +pub struct HexPosition { /// Q coordinate - pub q: i32, + pub q: T, /// R coordinate - pub r: i32, + pub r: T, } -impl HexPosition { +impl HexPosition { /// Returns the distance between two [HexPosition]s. /// /// # How it works @@ -37,7 +60,7 @@ impl HexPosition { /// /// assert_eq!(a.distance_to(&b), 2.0); /// ``` - pub fn distance_to(&self, other: &Self) -> f32 { + pub fn distance_to(&self, other: &Self) -> T { // dx = |x1 - x2| where x = q let dq = self.q - other.q; @@ -48,9 +71,11 @@ impl HexPosition { let dz = self.q + self.r - other.q - other.r; // Manhattan distance = (abs(dq) + abs(dr) + abs(ds)) / 2 - (dq.abs() + dr.abs() + dz.abs()) as f32 / 2.0 + (dq.abs() + dr.abs() + dz.abs()) / (T::one() + T::one()) } +} +impl HexPosition { /// Returns all positions within a given `range` from the current /// `HexPosition`. /// @@ -62,7 +87,7 @@ impl HexPosition { /// /// # Example /// - /// ```no_run + /// ``` /// use border_wars::hex::HexPosition; /// /// let position = HexPosition { q: 0, r: 0 }; @@ -71,10 +96,10 @@ impl HexPosition { /// /// assert_eq!(positions.len(), 7); /// ``` - pub fn range(&self, range: i32) -> HashSet { + pub fn range(&self, range: T) -> HashSet { let mut result_positions = HashSet::new(); - for q in (-range)..=range { - for r in (-range).max(-q - range)..=range.min(-q + range) { + for q in num::range_inclusive(-range, range) { + for r in num::range_inclusive((-range).max(-q - range), range.min(-q + range)) { result_positions.insert(Self { q, r }); } } @@ -82,7 +107,7 @@ impl HexPosition { } } -impl ops::Add for HexPosition { +impl ops::Add for HexPosition { type Output = Self; fn add(self, other: Self) -> Self::Output { @@ -93,13 +118,13 @@ impl ops::Add for HexPosition { } } -impl ops::AddAssign for HexPosition { +impl ops::AddAssign for HexPosition { fn add_assign(&mut self, other: Self) { *self = *self + other; } } -impl ops::Sub for HexPosition { +impl ops::Sub for HexPosition { type Output = Self; fn sub(self, other: Self) -> Self { @@ -110,42 +135,8 @@ impl ops::Sub for HexPosition { } } -impl ops::SubAssign for HexPosition { +impl ops::SubAssign for HexPosition { fn sub_assign(&mut self, other: Self) { *self = *self - other; } } - -impl ops::Mul for HexPosition { - type Output = Self; - - fn mul(self, other: i32) -> Self { - Self { - q: self.q * other, - r: self.r * other, - } - } -} - -impl ops::MulAssign for HexPosition { - fn mul_assign(&mut self, other: i32) { - *self = *self * other; - } -} - -impl ops::Div for HexPosition { - type Output = Self; - - fn div(self, other: i32) -> Self { - Self { - q: self.q / other, - r: self.r / other, - } - } -} - -impl ops::DivAssign for HexPosition { - fn div_assign(&mut self, other: i32) { - *self = *self / other; - } -}