add generique type
Some checks failed
Rust Checks / checks (push) Failing after 5m18s
Rust Checks / checks (pull_request) Failing after 1m26s

This commit is contained in:
CoCo_Sol 2024-02-14 14:36:00 +01:00
parent cfb3de298e
commit 8590c94973
3 changed files with 107 additions and 48 deletions

67
Cargo.lock generated
View file

@ -1316,6 +1316,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"bevy", "bevy",
"bevy_egui", "bevy_egui",
"num",
] ]
[[package]] [[package]]
@ -2993,6 +2994,40 @@ dependencies = [
"winapi", "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]] [[package]]
name = "num-derive" name = "num-derive"
version = "0.3.3" version = "0.3.3"
@ -3004,6 +3039,38 @@ dependencies = [
"syn 1.0.109", "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]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.18" version = "0.2.18"

View file

@ -13,3 +13,4 @@ workspace = true
[dependencies] [dependencies]
bevy = "0.12.1" bevy = "0.12.1"
bevy_egui = "0.24.0" bevy_egui = "0.24.0"
num = "0.4.1"

View file

@ -1,21 +1,44 @@
//! All functions related to calculations in a hexagonal grid. //! All functions related to calculations in a hexagonal grid.
use std::collections::HashSet; use std::collections::HashSet;
use std::hash::Hash;
use std::ops; 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<T: Signed + PartialEq + Copy + PartialOrd> HexNumber for T {}
/// Represents a position in a hexagonal grid. /// Represents a position in a hexagonal grid.
/// We use the axial coordinate system explained in this /// We use the axial coordinate system explained in this
/// [documentation](https://www.redblobgames.com/grids/hexagons/#coordinates). /// [documentation](https://www.redblobgames.com/grids/hexagons/#coordinates).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct HexPosition { pub struct HexPosition<T: HexNumber> {
/// Q coordinate /// Q coordinate
pub q: i32, pub q: T,
/// R coordinate /// R coordinate
pub r: i32, pub r: T,
} }
impl HexPosition { impl<T: HexNumber> HexPosition<T> {
/// Returns the distance between two [HexPosition]s. /// Returns the distance between two [HexPosition]s.
/// ///
/// # How it works /// # How it works
@ -37,7 +60,7 @@ impl HexPosition {
/// ///
/// assert_eq!(a.distance_to(&b), 2.0); /// 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 // dx = |x1 - x2| where x = q
let dq = self.q - other.q; let dq = self.q - other.q;
@ -48,9 +71,11 @@ impl HexPosition {
let dz = self.q + self.r - other.q - other.r; let dz = self.q + self.r - other.q - other.r;
// Manhattan distance = (abs(dq) + abs(dr) + abs(ds)) / 2 // 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<T: HexNumber + Eq + Hash + std::cmp::PartialOrd + num::ToPrimitive> HexPosition<T> {
/// Returns all positions within a given `range` from the current /// Returns all positions within a given `range` from the current
/// `HexPosition`. /// `HexPosition`.
/// ///
@ -62,7 +87,7 @@ impl HexPosition {
/// ///
/// # Example /// # Example
/// ///
/// ```no_run /// ```
/// use border_wars::hex::HexPosition; /// use border_wars::hex::HexPosition;
/// ///
/// let position = HexPosition { q: 0, r: 0 }; /// let position = HexPosition { q: 0, r: 0 };
@ -71,10 +96,10 @@ impl HexPosition {
/// ///
/// assert_eq!(positions.len(), 7); /// assert_eq!(positions.len(), 7);
/// ``` /// ```
pub fn range(&self, range: i32) -> HashSet<Self> { pub fn range(&self, range: T) -> HashSet<Self> {
let mut result_positions = HashSet::new(); let mut result_positions = HashSet::new();
for q in (-range)..=range { for q in num::range_inclusive(-range, range) {
for r in (-range).max(-q - range)..=range.min(-q + range) { for r in num::range_inclusive((-range).max(-q - range), range.min(-q + range)) {
result_positions.insert(Self { q, r }); result_positions.insert(Self { q, r });
} }
} }
@ -82,7 +107,7 @@ impl HexPosition {
} }
} }
impl ops::Add<Self> for HexPosition { impl<T: HexNumber> ops::Add<Self> for HexPosition<T> {
type Output = Self; type Output = Self;
fn add(self, other: Self) -> Self::Output { fn add(self, other: Self) -> Self::Output {
@ -93,13 +118,13 @@ impl ops::Add<Self> for HexPosition {
} }
} }
impl ops::AddAssign<Self> for HexPosition { impl<T: HexNumber> ops::AddAssign<Self> for HexPosition<T> {
fn add_assign(&mut self, other: Self) { fn add_assign(&mut self, other: Self) {
*self = *self + other; *self = *self + other;
} }
} }
impl ops::Sub<Self> for HexPosition { impl<T: HexNumber> ops::Sub<Self> for HexPosition<T> {
type Output = Self; type Output = Self;
fn sub(self, other: Self) -> Self { fn sub(self, other: Self) -> Self {
@ -110,42 +135,8 @@ impl ops::Sub<Self> for HexPosition {
} }
} }
impl ops::SubAssign<Self> for HexPosition { impl<T: HexNumber> ops::SubAssign<Self> for HexPosition<T> {
fn sub_assign(&mut self, other: Self) { fn sub_assign(&mut self, other: Self) {
*self = *self - other; *self = *self - other;
} }
} }
impl ops::Mul<i32> for HexPosition {
type Output = Self;
fn mul(self, other: i32) -> Self {
Self {
q: self.q * other,
r: self.r * other,
}
}
}
impl ops::MulAssign<i32> for HexPosition {
fn mul_assign(&mut self, other: i32) {
*self = *self * other;
}
}
impl ops::Div<i32> for HexPosition {
type Output = Self;
fn div(self, other: i32) -> Self {
Self {
q: self.q / other,
r: self.r / other,
}
}
}
impl ops::DivAssign<i32> for HexPosition {
fn div_assign(&mut self, other: i32) {
*self = *self / other;
}
}