#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TileShape {
Square,
Hexagon,
TriangleUp,
TriangleDown,
Octagon,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TileKind {
Box,
BoxOnGoal,
Pusher,
PusherOnGoal,
#[default]
Floor,
Goal,
Wall,
}
impl TileKind {
pub fn is_wall(&self) -> bool { *self == Self::Wall }
pub fn has_pusher(&self) -> bool { *self == Self::Pusher || *self == Self::PusherOnGoal }
pub fn has_box(&self) -> bool { *self == Self::Box || *self == Self::BoxOnGoal }
pub fn has_goal(&self) -> bool {
*self == Self::Goal || *self == Self::BoxOnGoal || *self == Self::PusherOnGoal
}
pub fn is_empty_floor(&self) -> bool { *self == Self::Floor }
pub fn can_start_a_row(&self) -> bool { self.is_wall() || *self == Self::BoxOnGoal }
}
#[cfg(test)]
mod tests {
use super::*;
const ALL_KINDS: [TileKind; 7] = [
TileKind::Box,
TileKind::BoxOnGoal,
TileKind::Pusher,
TileKind::PusherOnGoal,
TileKind::Floor,
TileKind::Goal,
TileKind::Wall,
];
fn matching(predicate: impl Fn(&TileKind) -> bool) -> Vec<TileKind> {
ALL_KINDS
.into_iter()
.filter(|kind| predicate(kind))
.collect()
}
#[test]
fn only_the_wall_is_a_wall() {
assert_eq!(matching(TileKind::is_wall), vec![TileKind::Wall]);
}
#[test]
fn a_pusher_on_a_goal_still_has_a_pusher() {
assert_eq!(
matching(TileKind::has_pusher),
vec![TileKind::Pusher, TileKind::PusherOnGoal]
);
}
#[test]
fn a_box_on_a_goal_still_has_a_box() {
assert_eq!(matching(TileKind::has_box), vec![TileKind::Box, TileKind::BoxOnGoal]);
}
#[test]
fn an_occupied_goal_still_has_a_goal() {
assert_eq!(
matching(TileKind::has_goal),
vec![TileKind::BoxOnGoal, TileKind::PusherOnGoal, TileKind::Goal]
);
}
#[test]
fn only_the_floor_is_empty_floor() {
assert_eq!(matching(TileKind::is_empty_floor), vec![TileKind::Floor]);
}
#[test]
fn the_default_tile_is_empty_floor() {
assert!(TileKind::default().is_empty_floor());
}
#[test]
fn only_walls_and_boxes_on_goals_can_start_a_row() {
assert_eq!(
matching(TileKind::can_start_a_row),
vec![TileKind::BoxOnGoal, TileKind::Wall]
);
}
#[test]
fn a_plain_box_cannot_start_a_row() {
assert!(!TileKind::Box.can_start_a_row());
assert!(TileKind::BoxOnGoal.can_start_a_row());
}
}