test(walls): 93% coverage

This commit is contained in:
Kristofers Solo 2024-12-25 22:57:13 +02:00
parent 43a669dee8
commit 9740ce1a5a
6 changed files with 325 additions and 159 deletions

71
Cargo.lock generated
View File

@ -1347,18 +1347,18 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytemuck"
version = "1.20.0"
version = "1.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a"
checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"
dependencies = [
"bytemuck_derive",
]
[[package]]
name = "bytemuck_derive"
version = "1.8.0"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec"
checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a"
dependencies = [
"proc-macro2",
"quote",
@ -1399,9 +1399,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.3"
version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d"
checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e"
dependencies = [
"jobserver",
"libc",
@ -1525,9 +1525,9 @@ dependencies = [
[[package]]
name = "const_panic"
version = "0.2.10"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "013b6c2c3a14d678f38cd23994b02da3a1a1b6a5d1eedddfe63a5a5f11b13a81"
checksum = "53857514f72ee4a2b583de67401e3ff63a5472ca4acf289d09a9ea7636dfec17"
[[package]]
name = "const_soft_float"
@ -1677,18 +1677,18 @@ dependencies = [
[[package]]
name = "crossbeam-channel"
version = "0.5.13"
version = "0.5.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
@ -1705,9 +1705,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crunchy"
@ -1951,9 +1951,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
[[package]]
name = "font-types"
@ -2297,13 +2297,13 @@ dependencies = [
[[package]]
name = "gpu-descriptor"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557"
checksum = "dcf29e94d6d243368b7a56caa16bc213e4f9f8ed38c4d9557069527b5d5281ca"
dependencies = [
"bitflags 2.6.0",
"gpu-descriptor-types",
"hashbrown 0.14.5",
"hashbrown 0.15.1",
]
[[package]]
@ -2375,10 +2375,13 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]]
name = "hexlab"
version = "0.3.1"
version = "0.4.0"
dependencies = [
"bevy",
"bevy_reflect",
"bevy_utils",
"claims",
"glam",
"hexx",
"rand",
"rstest",
@ -2698,9 +2701,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.8.0"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
dependencies = [
"adler2",
"simd-adler32",
@ -2708,9 +2711,9 @@ dependencies = [
[[package]]
name = "naga"
version = "23.0.0"
version = "23.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d5941e45a15b53aad4375eedf02033adb7a28931eedc31117faffa52e6a857e"
checksum = "364f94bc34f61332abebe8cad6f6cd82a5b65cff22c828d05d0968911462ca4f"
dependencies = [
"arrayvec",
"bit-set 0.8.0",
@ -3269,9 +3272,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "png"
version = "0.17.15"
version = "0.17.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b67582bd5b65bdff614270e2ea89a1cf15bef71245cc1e5f7ea126977144211d"
checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526"
dependencies = [
"bitflags 1.3.2",
"crc32fast",
@ -3710,9 +3713,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.133"
version = "1.0.134"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d"
dependencies = [
"itoa",
"memchr",
@ -3938,9 +3941,9 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "1.8.0"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8"
dependencies = [
"tinyvec_macros",
]
@ -4085,9 +4088,9 @@ checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e"
[[package]]
name = "unicode-bidi"
version = "0.3.17"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
[[package]]
name = "unicode-bidi-mirroring"
@ -4755,9 +4758,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winit"
version = "0.30.5"
version = "0.30.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0be9e76a1f1077e04a411f0b989cbd3c93339e1771cb41e71ac4aee95bfd2c67"
checksum = "dba50bc8ef4b6f1a75c9274fb95aa9a8f63fbc66c56f391bd85cf68d51e7b1a3"
dependencies = [
"android-activity",
"atomic-waker",

View File

@ -1,7 +1,7 @@
[package]
name = "hexlab"
authors = ["Kristofers Solo <dev@kristofers.xyz>"]
version = "0.3.1"
version = "0.4.0"
edition = "2021"
description = "A hexagonal maze generation and manipulation library"
repository = "https://github.com/kristoferssolo/hexlab"
@ -19,11 +19,20 @@ exclude = ["/.github", "/.gitignore", "/tests", "*.png", "*.md"]
readme = "README.md"
[dependencies]
bevy = { version = "0.15", optional = true }
hexx = { version = "0.19" }
rand = "0.8"
serde = { version = "1.0", features = ["derive"], optional = true }
thiserror = "2.0"
bevy = { version = "0.15", optional = true }
bevy_utils = { version = "0.15", optional = true }
glam = { version = "0.29", optional = true }
[dependencies.bevy_reflect]
version = "0.15"
optional = true
default-features = false
features = ["glam"]
[dev-dependencies]
claims = "0.8"
@ -32,8 +41,13 @@ rstest = "0.23"
[features]
default = []
serde = ["dep:serde", "hexx/serde"]
bevy = ["bevy_reflect"]
bevy_reflect = ["dep:bevy", "hexx/bevy_reflect"]
bevy = ["dep:bevy", "bevy_reflect"]
bevy_reflect = [
"dep:bevy_reflect",
"dep:bevy_utils",
"hexx/bevy_reflect",
"dep:glam",
]
full = ["serde", "bevy"]
[profile.dev]

View File

@ -1,15 +1,13 @@
mod backtrack;
use crate::HexMaze;
use backtrack::generate_backtracking;
#[cfg(feature = "bevy_reflect")]
use bevy::prelude::*;
use hexx::Hex;
#[allow(clippy::module_name_repetitions)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "bevy", derive(Component))]
#[cfg_attr(feature = "bevy", reflect(Component))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "bevy", derive(bevy::Component))]
#[cfg_attr(feature = "bevy", reflect(bevy::Component))]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum GeneratorType {
#[default]

View File

@ -1,8 +1,6 @@
use super::{HexTile, Walls};
#[cfg(feature = "bevy_reflect")]
use bevy::prelude::*;
#[cfg(feature = "bevy_reflect")]
use bevy::utils::HashMap;
use bevy_utils::HashMap;
use hexx::{EdgeDirection, Hex};
#[cfg(not(feature = "bevy_reflect"))]
use std::collections::HashMap;
@ -14,9 +12,9 @@ use std::ops::{Deref, DerefMut};
/// of tiles and their associated walls.
#[allow(clippy::module_name_repetitions)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "bevy", derive(Component))]
#[cfg_attr(feature = "bevy", reflect(Component))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "bevy", derive(bevy::Component))]
#[cfg_attr(feature = "bevy", reflect(bevy::Component))]
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct HexMaze(HashMap<Hex, HexTile>);
@ -56,7 +54,6 @@ impl HexMaze {
///
/// assert_eq!(maze.len(), 1);
/// assert!(!maze.is_empty());
/// assert!(!maze.get_tile(&coord).is_some());
/// ```
pub fn add_tile(&mut self, coords: Hex) {
let tile = HexTile::new(coords);
@ -80,8 +77,9 @@ impl HexMaze {
/// maze.add_tile(coord);
///
/// maze.add_wall(coord, EdgeDirection::FLAT_NORTH);
/// let walls = maze.get_walls(&coord).unwrap();
/// assert!(walls.contains(EdgeDirection::FLAT_NORTH));
/// let walls = maze.get_walls(&coord);
/// assert!(walls.is_some());
/// assert!(walls.unwrap().contains(EdgeDirection::FLAT_NORTH));
/// ```
pub fn add_wall(&mut self, coord: Hex, direction: EdgeDirection) {
if let Some(tile) = self.0.get_mut(&coord) {
@ -104,7 +102,8 @@ impl HexMaze {
/// let coord = Hex::ZERO;
/// maze.add_tile(coord);
///
/// assert!(!maze.get_tile(&coord).is_some());
/// assert!(maze.get_tile(&coord).is_some());
/// assert!(maze.get_tile(&Hex::new(1, 1)).is_none());
/// ```
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]

View File

@ -1,6 +1,4 @@
use super::Walls;
#[cfg(feature = "bevy_reflect")]
use bevy::prelude::*;
use hexx::Hex;
#[cfg(feature = "bevy_reflect")]
use hexx::HexLayout;
@ -11,7 +9,7 @@ use std::fmt::Display;
/// Each tile has a position and a set of walls defining its boundaries.
#[allow(clippy::module_name_repetitions)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "bevy", derive(Component))]
#[cfg_attr(feature = "bevy", reflect(Component))]
#[derive(Debug, Clone, Default, PartialEq, Eq)]
@ -26,6 +24,16 @@ impl HexTile {
/// # Arguments
///
/// - `pos` - The hexagonal coordinates of the tile.
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let tile = HexTile::new(Hex::new(1, -1));
/// assert_eq!(tile.pos(), Hex::new(1, -1));
/// assert_eq!(*tile.walls(), Walls::default());
/// ```
#[must_use]
pub fn new(pos: Hex) -> Self {
Self {
@ -35,6 +43,15 @@ impl HexTile {
}
/// Returns a reference to the tile's walls
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let tile = HexTile::new(Hex::ZERO);
/// assert_eq!(*tile.walls(), Walls::default());
/// ```
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
pub const fn walls(&self) -> &Walls {
@ -42,11 +59,21 @@ impl HexTile {
}
/// Returns position of the tile
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let tile = HexTile::new(Hex::new(2, -2));
/// assert_eq!(tile.pos(), Hex::new(2, -2));
/// ```
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
pub const fn pos(&self) -> Hex {
self.pos
}
/// Converts the tile's position to a 2D vector based on the given layout.
///
/// # Arguments
@ -55,7 +82,7 @@ impl HexTile {
#[cfg(feature = "bevy_reflect")]
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
pub fn to_vec2(&self, layout: &HexLayout) -> Vec2 {
pub fn to_vec2(&self, layout: &HexLayout) -> glam::Vec2 {
layout.hex_to_world_pos(self.pos)
}
@ -67,7 +94,9 @@ impl HexTile {
#[cfg(feature = "bevy_reflect")]
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
pub fn to_vec3(&self, layout: &HexLayout) -> Vec3 {
pub fn to_vec3(&self, layout: &HexLayout) -> glam::Vec3 {
use glam::Vec3;
let pos = self.to_vec2(layout);
Vec3::new(pos.x, 0., pos.y)
}
@ -90,76 +119,26 @@ impl Display for HexTile {
#[cfg(test)]
mod test {
use hexx::EdgeDirection;
use super::*;
use hexx::EdgeDirection;
use rand::{thread_rng, Rng};
#[test]
fn new_tile() {
let pos = Hex::ZERO;
let tile = HexTile::new(pos);
assert_eq!(tile.pos, pos, "Position should match constructor argument");
assert_eq!(
tile.walls,
Walls::default(),
"Walls should be initialized to default"
);
}
#[test]
fn tile_walls_accessor() {
let pos = Hex::new(1, -1);
let tile = HexTile::new(pos);
// Test walls accessor method
let walls_ref = tile.walls();
assert_eq!(
walls_ref, &tile.walls,
"Walls accessor should return reference to walls"
);
fn random_hex() -> Hex {
let mut rng = thread_rng();
Hex::new(rng.gen(), rng.gen())
}
#[test]
fn tile_modification() {
let pos = Hex::new(2, 3);
let mut tile = HexTile::new(pos);
let hex = random_hex();
let mut tile = HexTile::new(hex);
// Modify walls
tile.walls.remove(EdgeDirection::FLAT_TOP);
assert!(
!tile.walls.contains(EdgeDirection::FLAT_TOP),
"Wall should be removed"
);
assert!(!tile.walls.contains(EdgeDirection::FLAT_TOP));
tile.walls.add(EdgeDirection::FLAT_TOP);
assert!(
tile.walls.contains(EdgeDirection::FLAT_TOP),
"Wall should be added back"
);
}
#[test]
fn tile_clone() {
let pos = Hex::new(0, -2);
let tile = HexTile::new(pos);
// Test Clone trait
let cloned_tile = tile.clone();
assert_eq!(tile, cloned_tile, "Cloned tile should equal original");
}
#[test]
fn tile_debug() {
let pos = Hex::ZERO;
let tile = HexTile::new(pos);
// Test Debug trait
let debug_string = format!("{:?}", tile);
assert!(
debug_string.contains("HexTile"),
"Debug output should contain struct name"
);
assert!(tile.walls.contains(EdgeDirection::FLAT_TOP));
}
#[test]
@ -174,38 +153,10 @@ mod test {
// Verify each tile has correct position
for (tile, &pos) in tiles.iter().zip(positions.iter()) {
assert_eq!(
tile.pos, pos,
"Tile position should match constructor argument"
);
assert_eq!(tile.pos, pos);
}
}
#[test]
fn tile_equality() {
let pos1 = Hex::new(1, 1);
let pos2 = Hex::new(1, 1);
let pos3 = Hex::new(2, 1);
let tile1 = HexTile::new(pos1);
let tile2 = HexTile::new(pos2);
let tile3 = HexTile::new(pos3);
assert_eq!(tile1, tile2, "Tiles with same position should be equal");
assert_ne!(
tile1, tile3,
"Tiles with different positions should not be equal"
);
// Test with modified walls
let mut tile4 = HexTile::new(pos1);
tile4.walls.remove(EdgeDirection::FLAT_TOP);
assert_ne!(
tile1, tile4,
"Tiles with different walls should not be equal"
);
}
#[test]
fn hex_boundaries() {
// Test with extreme coordinate values
@ -218,10 +169,77 @@ mod test {
for pos in extreme_positions {
let tile = HexTile::new(pos);
assert_eq!(
tile.pos, pos,
"Tile should handle extreme coordinate values"
);
assert_eq!(tile.pos, pos);
}
}
#[test]
fn hex_tile_creation_and_properties() {
let hex = random_hex();
let tile = HexTile::new(hex);
assert_eq!(tile.pos(), hex);
assert!(tile.walls().is_enclosed());
}
#[test]
fn hex_tile_from_hex() {
let hex = random_hex();
let tile = HexTile::from(hex);
assert_eq!(tile.pos, hex);
assert_eq!(tile.walls, Walls::default());
}
#[test]
fn hex_hex_into_tile() {
let hex = random_hex();
let tile: HexTile = hex.into();
assert_eq!(tile.pos, hex);
assert_eq!(tile.walls, Walls::default());
}
#[test]
fn hex_tile_display() {
let tile = HexTile::new(Hex::new(3, -3));
assert_eq!(format!("{tile}"), "(3,-3)");
}
#[test]
fn hex_tile_wall_modifications() {
let mut tile = HexTile::new(Hex::ZERO);
for direction in EdgeDirection::ALL_DIRECTIONS {
tile.walls.add(direction);
}
assert_eq!(tile.walls.count(), 6);
for direction in EdgeDirection::ALL_DIRECTIONS {
tile.walls.remove(direction);
}
assert_eq!(tile.walls.count(), 0);
}
#[cfg(feature = "bevy_reflect")]
mod bevy_tests {
use super::*;
use glam::{Vec2, Vec3};
#[test]
fn hex_tile_to_vec2() {
let layout = HexLayout::default();
let tile = HexTile::new(Hex::new(1, 0));
let vec2 = tile.to_vec2(&layout);
assert_eq!(vec2, Vec2::new(1.5, -0.8660254));
}
#[test]
fn hex_tile_to_vec3() {
let layout = HexLayout::default();
let tile = HexTile::new(Hex::new(0, 1));
let vec3 = tile.to_vec3(&layout);
assert_eq!(vec3, Vec3::new(0.0, 0.0, -1.7320508));
}
}
}

View File

@ -1,5 +1,3 @@
#[cfg(feature = "bevy_reflect")]
use bevy::prelude::*;
use hexx::EdgeDirection;
/// A bit-flag representation of walls in a hexagonal tile.
@ -28,7 +26,7 @@ use hexx::EdgeDirection;
/// assert_eq!(walls.count(), 2);
/// ```
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "bevy", derive(Component))]
#[cfg_attr(feature = "bevy", reflect(Component))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -38,6 +36,15 @@ impl Walls {
/// Creates a new set of walls with all edges closed.
///
/// This is the default state where all six edges of the hexagon have walls.
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let walls = Walls::new();
/// assert!(walls.is_enclosed());
/// ```
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
pub fn new() -> Self {
@ -45,6 +52,15 @@ impl Walls {
}
/// Creates a new set of walls with no edges (completely open).
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let walls = Walls::empty();
/// assert!(walls.is_empty());
/// ```
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
pub const fn empty() -> Self {
@ -52,6 +68,15 @@ impl Walls {
}
/// Checks if the walls are currently empty (no walls present).
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let walls = Walls::empty();
/// assert!(walls.is_empty());
/// ```
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
pub const fn is_empty(&self) -> bool {
@ -62,7 +87,26 @@ impl Walls {
///
/// # Arguments
///
/// 0 `direction` - The direction in which to add the wall.
/// - `direction` - The direction in which to add the wall.
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let mut walls = Walls::empty();
/// assert_eq!(walls.count(), 0);
///
/// walls.add(1);
/// assert_eq!(walls.count(), 1);
///
/// walls.add(1);
/// assert_eq!(walls.count(), 1);
///
/// walls.add(EdgeDirection::FLAT_NORTH);
/// assert_eq!(walls.count(), 2);
///
/// ```
#[cfg_attr(not(debug_assertions), inline)]
pub fn add<T>(&mut self, direction: T)
where
@ -76,6 +120,23 @@ impl Walls {
/// # Arguments
///
/// - `direction` - The direction from which to remove the wall.
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let mut walls = Walls::new();
///
/// assert!(walls.remove(1));
/// assert_eq!(walls.count(), 5);
///
/// assert!(!walls.remove(1));
/// assert_eq!(walls.count(), 5);
///
/// assert!(walls.remove(EdgeDirection::FLAT_NORTH));
/// assert_eq!(walls.count(), 4);
/// ```
#[cfg_attr(not(debug_assertions), inline)]
pub fn remove<T>(&mut self, direction: T) -> bool
where
@ -93,6 +154,18 @@ impl Walls {
/// # Arguments
///
/// - `other` - The direction to check for a wall.
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let mut walls = Walls::empty();
/// walls.add(EdgeDirection::FLAT_NORTH);
///
/// assert!(walls.contains(EdgeDirection::FLAT_NORTH));
/// assert!(!walls.contains(EdgeDirection::FLAT_SOUTH));
/// ```
#[cfg_attr(not(debug_assertions), inline)]
pub fn contains<T>(&self, other: T) -> bool
where
@ -102,6 +175,18 @@ impl Walls {
}
/// Returns the raw bit representation of the walls
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let walls = Walls::new();
/// assert_eq!(walls.as_bits(), 0b11_1111);
///
/// let walls = Walls::empty();
/// assert_eq!(walls.as_bits(), 0);
/// ```
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
pub const fn as_bits(&self) -> u8 {
@ -109,6 +194,21 @@ impl Walls {
}
/// Returns the total number of walls present
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let mut walls = Walls::empty();
/// assert!(walls.is_empty());
///
/// walls.add(0);
/// assert_eq!(walls.count(), 1);
///
/// walls.add(1);
/// assert_eq!(walls.count(), 2);
/// ```
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
pub fn count(&self) -> u8 {
@ -116,6 +216,14 @@ impl Walls {
}
/// Returns a `Walls` value representing all possible directions.
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// assert_eq!(Walls::all_directions().as_bits(), 0b11_1111);
/// ```
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
pub const fn all_directions() -> Self {
@ -134,6 +242,20 @@ impl Walls {
/// # Returns
///
/// The previous state (`true` if a wall was present before toggling, `false` otherwise).
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let mut walls = Walls::empty();
///
/// assert!(!walls.toggle(0));
/// assert_eq!(walls.count(), 1);
///
/// assert!(walls.toggle(0));
/// assert_eq!(walls.count(), 0);
/// ```
pub fn toggle<T>(&mut self, direction: T) -> bool
where
T: Into<Self> + Copy,
@ -155,10 +277,10 @@ impl Walls {
///
/// # Deprecated
///
/// This method is deprecated since version 0.3.1. Use `is_enclosed()` instead.
/// This method is deprecated since version 0.4.0. Use `is_enclosed()` instead.
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
#[deprecated(since = "0.3.1", note = "use `walls::Walls::is_enclosed()`")]
#[deprecated(since = "0.4.0", note = "use `walls::Walls::is_enclosed()`")]
pub fn is_closed(&self) -> bool {
self.is_enclosed()
}
@ -168,6 +290,18 @@ impl Walls {
/// # Returns
///
/// `true` if the hexagon has all possible walls, making it completely enclosed.
///
/// # Examples
///
/// ```
/// use hexlab::prelude::*;
///
/// let mut walls = Walls::new();
/// assert!(walls.is_enclosed());
///
/// walls.remove(0);
/// assert!(!walls.is_enclosed());
/// ```
#[cfg_attr(not(debug_assertions), inline)]
#[must_use]
pub fn is_enclosed(&self) -> bool {
@ -247,7 +381,7 @@ mod test {
#[test]
fn all_directions_creates_closed_walls() {
let walls = Walls::all_directions();
assert!(walls.is_closed());
assert!(walls.is_enclosed());
assert!(!walls.is_empty());
assert_eq!(walls.as_bits(), 0b111111);
}
@ -284,7 +418,7 @@ mod test {
#[test]
fn new_created_closed_walls() {
let walls = Walls::new();
assert!(walls.is_closed());
assert!(walls.is_enclosed());
assert_eq!(walls.as_bits(), 0b111111);
}
@ -393,7 +527,7 @@ mod test {
#[test]
fn default_creates_closed_walls() {
let walls = Walls::default();
assert!(walls.is_closed());
assert!(walls.is_enclosed());
assert_eq!(walls.as_bits(), 0b111111);
}