move tests
This commit is contained in:
@@ -150,3 +150,14 @@ impl TryFrom<&str> for Archetype {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Archetype;
|
||||
|
||||
#[test]
|
||||
fn directional_crate_default_glyph_tiles() {
|
||||
assert_eq!(Archetype::HCrate.default_glyph().tile, 29);
|
||||
assert_eq!(Archetype::VCrate.default_glyph().tile, 18);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,3 +309,178 @@ impl Board {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use color::Rgba8;
|
||||
use crate::archetype::Archetype;
|
||||
use crate::glyph::Glyph;
|
||||
use crate::object_def::ObjectDef;
|
||||
use crate::script::Direction;
|
||||
use crate::utils::{ObjectId, Player, Solid};
|
||||
use super::Board;
|
||||
|
||||
/// Builds an all-empty `w×h` board with the given player position, objects,
|
||||
/// and `(name, source)` scripts. Assigns sequential ids (1..=n) to objects.
|
||||
pub(crate) fn open_board(
|
||||
w: usize,
|
||||
h: usize,
|
||||
player: (i32, i32),
|
||||
objects: Vec<ObjectDef>,
|
||||
scripts: &[(&str, &str)],
|
||||
) -> Board {
|
||||
let mut object_map: BTreeMap<ObjectId, ObjectDef> = BTreeMap::new();
|
||||
let mut next_object_id: ObjectId = 1;
|
||||
for o in objects {
|
||||
object_map.insert(next_object_id, o);
|
||||
next_object_id += 1;
|
||||
}
|
||||
Board {
|
||||
name: "test".into(),
|
||||
width: w,
|
||||
height: h,
|
||||
cells: vec![(Archetype::Empty.default_glyph(), Archetype::Empty); w * h],
|
||||
floor: vec![Archetype::Empty.default_glyph(); w * h],
|
||||
floor_spec: None,
|
||||
player: Player { x: player.0, y: player.1 },
|
||||
objects: object_map,
|
||||
next_object_id,
|
||||
portals: Vec::new(),
|
||||
font: None,
|
||||
zoom: 1,
|
||||
scripts: scripts.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect::<HashMap<_,_>>(),
|
||||
board_script_name: None,
|
||||
load_errors: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Stamps a crate cell onto a board.
|
||||
pub(crate) fn crate_at(board: &mut Board, x: usize, y: usize) {
|
||||
*board.get_mut(x, y) = (Archetype::Crate.default_glyph(), Archetype::Crate);
|
||||
}
|
||||
|
||||
/// Stamps a wall cell onto a board.
|
||||
pub(crate) fn wall_at(board: &mut Board, x: usize, y: usize) {
|
||||
*board.get_mut(x, y) = (Archetype::Wall.default_glyph(), Archetype::Wall);
|
||||
}
|
||||
|
||||
/// Stamps an arbitrary archetype cell onto a board.
|
||||
pub(crate) fn stamp(board: &mut Board, x: usize, y: usize, arch: Archetype) {
|
||||
*board.get_mut(x, y) = (arch.default_glyph(), arch);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn solid_at_reports_wall_object_and_empty() {
|
||||
let mut board = open_board(4, 1, (3, 0), vec![], &[]);
|
||||
board.cells[1] = (Archetype::Wall.default_glyph(), Archetype::Wall);
|
||||
board.add_object(ObjectDef::new(2, 0));
|
||||
|
||||
assert!(board.solid_at(0, 0).is_none());
|
||||
assert!(board.is_passable(0, 0));
|
||||
|
||||
match board.solid_at(1, 0) {
|
||||
Some(Solid::Cell(Archetype::Wall)) => {}
|
||||
other => panic!("expected Solid::Cell(Wall), got {:?}", other.is_some()),
|
||||
}
|
||||
assert!(!board.is_passable(1, 0));
|
||||
|
||||
match board.solid_at(2, 0) {
|
||||
Some(Solid::Object(id)) => assert_eq!((board.objects[&id].x, board.objects[&id].y), (2, 0)),
|
||||
_ => panic!("expected Solid::Object"),
|
||||
}
|
||||
assert!(!board.is_passable(2, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_solid_object_does_not_block() {
|
||||
let mut obj = ObjectDef::new(1, 0);
|
||||
obj.solid = false;
|
||||
let board = open_board(3, 1, (0, 0), vec![obj], &[]);
|
||||
assert!(board.solid_at(1, 0).is_none());
|
||||
assert!(board.is_passable(1, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn solid_at_reports_player() {
|
||||
let board = open_board(3, 1, (1, 0), vec![], &[]);
|
||||
match board.solid_at(1, 0) {
|
||||
Some(Solid::Player) => {}
|
||||
_ => panic!("expected Solid::Player at the player's cell"),
|
||||
}
|
||||
assert!(!board.is_passable(1, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn in_bounds_checks_grid_boundaries() {
|
||||
let board = open_board(3, 2, (0, 0), vec![], &[]);
|
||||
assert!(board.in_bounds((0, 0)));
|
||||
assert!(board.in_bounds((2, 1)));
|
||||
assert!(!board.in_bounds((-1, 0)));
|
||||
assert!(!board.in_bounds((0, -1)));
|
||||
assert!(!board.in_bounds((3, 0)));
|
||||
assert!(!board.in_bounds((0, 2)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_push_is_read_only_and_correct() {
|
||||
let mut board = open_board(3, 1, (0, 0), vec![], &[]);
|
||||
crate_at(&mut board, 1, 0);
|
||||
assert!(board.can_push(1, 0, Direction::East));
|
||||
assert_eq!(board.get(1, 0).1, Archetype::Crate); // no mutation
|
||||
assert_eq!(board.get(2, 0).1, Archetype::Empty);
|
||||
|
||||
let mut board = open_board(3, 1, (0, 0), vec![], &[]);
|
||||
crate_at(&mut board, 1, 0);
|
||||
wall_at(&mut board, 2, 0);
|
||||
assert!(!board.can_push(1, 0, Direction::East));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn push_into_player_pushes_player() {
|
||||
// Crate shoved east into the player slides the player along into open space.
|
||||
let mut board = open_board(4, 1, (2, 0), vec![], &[]);
|
||||
crate_at(&mut board, 1, 0);
|
||||
assert!(board.can_push(1, 0, Direction::East));
|
||||
board.push(1, 0, Direction::East);
|
||||
assert_eq!(board.get(1, 0).1, Archetype::Empty);
|
||||
assert_eq!(board.get(2, 0).1, Archetype::Crate);
|
||||
assert_eq!((board.player.x, board.player.y), (3, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn push_into_player_blocked_by_wall() {
|
||||
// Player backed against a wall: push has nowhere to go, nothing moves.
|
||||
let mut board = open_board(4, 1, (2, 0), vec![], &[]);
|
||||
crate_at(&mut board, 1, 0);
|
||||
wall_at(&mut board, 3, 0);
|
||||
assert!(!board.can_push(1, 0, Direction::East));
|
||||
board.push(1, 0, Direction::East); // no-op
|
||||
assert_eq!(board.get(1, 0).1, Archetype::Crate);
|
||||
assert_eq!((board.player.x, board.player.y), (2, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glyph_at_uses_floor_for_empty_and_grid_for_solid() {
|
||||
// Player parked at (2,0) so it doesn't overlap either asserted cell.
|
||||
let mut board = open_board(3, 1, (2, 0), vec![], &[]);
|
||||
let floor_glyph = Glyph {
|
||||
tile: '.' as u32,
|
||||
fg: Rgba8 { r: 10, g: 20, b: 30, a: 255 },
|
||||
bg: Rgba8 { r: 1, g: 2, b: 3, a: 255 },
|
||||
};
|
||||
board.floor = vec![floor_glyph; 3];
|
||||
wall_at(&mut board, 0, 0);
|
||||
assert_eq!(board.glyph_at(0, 0), Archetype::Wall.default_glyph());
|
||||
assert_eq!(board.glyph_at(1, 0), floor_glyph);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fresh_board_is_valid_and_reports_errors() {
|
||||
let mut board = open_board(1, 1, (0, 0), vec![], &[]);
|
||||
assert!(board.is_valid());
|
||||
board.report_error("something went wrong");
|
||||
assert!(!board.is_valid());
|
||||
assert_eq!(board.load_errors.len(), 1);
|
||||
}
|
||||
}
|
||||
+21
-248
@@ -189,14 +189,13 @@ fn step_object(board: &mut Board, id: ObjectId, dir: Direction) -> Option<Object
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use color::Rgba8;
|
||||
use std::collections::BTreeMap;
|
||||
use std::time::Duration;
|
||||
use crate::archetype::Archetype;
|
||||
use crate::board::Board;
|
||||
use crate::glyph::Glyph;
|
||||
use crate::board::tests::{crate_at, open_board, stamp, wall_at};
|
||||
use crate::object_def::ObjectDef;
|
||||
use crate::utils::{ObjectId, Player, Pushable, Solid};
|
||||
use crate::utils::Player;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -234,49 +233,6 @@ mod tests {
|
||||
o
|
||||
}
|
||||
|
||||
/// Builds an all-empty (passable) `w×h` board with the given player position,
|
||||
/// objects, and `(name, source)` scripts — room for movement, unlike the 1×1
|
||||
/// `board_with_object`.
|
||||
fn open_board(
|
||||
w: usize,
|
||||
h: usize,
|
||||
player: (i32, i32),
|
||||
objects: Vec<ObjectDef>,
|
||||
scripts: &[(&str, &str)],
|
||||
) -> Board {
|
||||
// Assign sequential ids (1..=n) just like the map loader, so tests that
|
||||
// index by id can rely on first-object == id 1.
|
||||
let mut object_map: BTreeMap<ObjectId, ObjectDef> = BTreeMap::new();
|
||||
let mut next_object_id: ObjectId = 1;
|
||||
for o in objects {
|
||||
object_map.insert(next_object_id, o);
|
||||
next_object_id += 1;
|
||||
}
|
||||
Board {
|
||||
name: "test".into(),
|
||||
width: w,
|
||||
height: h,
|
||||
cells: vec![(Archetype::Empty.default_glyph(), Archetype::Empty); w * h],
|
||||
floor: vec![Archetype::Empty.default_glyph(); w * h],
|
||||
floor_spec: None,
|
||||
player: Player {
|
||||
x: player.0,
|
||||
y: player.1,
|
||||
},
|
||||
objects: object_map,
|
||||
next_object_id,
|
||||
portals: Vec::new(),
|
||||
font: None,
|
||||
zoom: 1,
|
||||
scripts: scripts
|
||||
.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect(),
|
||||
board_script_name: None,
|
||||
load_errors: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Flattens each log line into a single string for easy assertions.
|
||||
fn log_texts(game: &GameState) -> Vec<String> {
|
||||
game.log
|
||||
@@ -286,81 +242,26 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn solid_at_reports_wall_object_and_empty() {
|
||||
// A 4×1 board: empty floor, a wall, an object, and the player parked at (3,0)
|
||||
// (kept off the asserted cells, since the player is itself solid).
|
||||
let mut board = open_board(4, 1, (3, 0), vec![], &[]);
|
||||
board.cells[1] = (Archetype::Wall.default_glyph(), Archetype::Wall);
|
||||
// A solid object on the otherwise-empty cell (2, 0).
|
||||
board.add_object(ObjectDef::new(2, 0)); // solid by default
|
||||
|
||||
// Empty floor: nothing solid.
|
||||
assert!(board.solid_at(0, 0).is_none());
|
||||
assert!(board.is_passable(0, 0));
|
||||
|
||||
// Wall cell: the grid archetype is the solid.
|
||||
match board.solid_at(1, 0) {
|
||||
Some(Solid::Cell(Archetype::Wall)) => {}
|
||||
other => panic!("expected Solid::Cell(Wall), got {:?}", other.is_some()),
|
||||
}
|
||||
assert!(!board.is_passable(1, 0));
|
||||
|
||||
// Object cell: the solid object shadows the empty floor under it.
|
||||
match board.solid_at(2, 0) {
|
||||
Some(Solid::Object(id)) => {
|
||||
let o = &board.objects[&id];
|
||||
assert_eq!((o.x, o.y), (2, 0))
|
||||
},
|
||||
_ => panic!("expected Solid::Object"),
|
||||
}
|
||||
assert!(!board.is_passable(2, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_solid_object_does_not_block() {
|
||||
// A non-solid object sits on empty floor: the cell stays passable.
|
||||
let mut obj = ObjectDef::new(1, 0);
|
||||
obj.solid = false;
|
||||
let board = open_board(3, 1, (0, 0), vec![obj], &[]);
|
||||
assert!(board.solid_at(1, 0).is_none());
|
||||
assert!(board.is_passable(1, 0));
|
||||
}
|
||||
|
||||
/// Stamps a crate cell onto an otherwise-open board.
|
||||
fn crate_at(board: &mut Board, x: usize, y: usize) {
|
||||
*board.get_mut(x, y) = (Archetype::Crate.default_glyph(), Archetype::Crate);
|
||||
}
|
||||
|
||||
/// Stamps a wall cell onto an otherwise-open board.
|
||||
fn wall_at(board: &mut Board, x: usize, y: usize) {
|
||||
*board.get_mut(x, y) = (Archetype::Wall.default_glyph(), Archetype::Wall);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn in_bounds_checks_grid_boundaries() {
|
||||
let board = open_board(3, 2, (0, 0), vec![], &[]);
|
||||
assert!(board.in_bounds((0, 0)));
|
||||
assert!(board.in_bounds((2, 1)));
|
||||
assert!(!board.in_bounds((-1, 0)));
|
||||
assert!(!board.in_bounds((0, -1)));
|
||||
assert!(!board.in_bounds((3, 0))); // x == width
|
||||
assert!(!board.in_bounds((0, 2))); // y == height
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_push_is_read_only_and_correct() {
|
||||
// Crate with empty space beyond: pushable, and the board is left untouched.
|
||||
let mut board = open_board(3, 1, (0, 0), vec![], &[]);
|
||||
fn pushing_a_crate_reveals_the_floor_underneath() {
|
||||
// The cell a crate is pushed off of becomes Empty and glyph_at shows floor.
|
||||
// After the push the player is at (1,0); check the cell the player vacated
|
||||
// (0,0) — it is Empty and must reveal the floor glyph, not black-on-black.
|
||||
use color::Rgba8;
|
||||
use crate::glyph::Glyph;
|
||||
let mut board = open_board(4, 1, (0, 0), vec![], &[]);
|
||||
let floor_glyph = Glyph {
|
||||
tile: ',' as u32,
|
||||
fg: Rgba8 { r: 40, g: 60, b: 40, a: 255 },
|
||||
bg: Rgba8 { r: 5, g: 10, b: 5, a: 255 },
|
||||
};
|
||||
board.floor = vec![floor_glyph; 4];
|
||||
crate_at(&mut board, 1, 0);
|
||||
assert!(board.can_push(1, 0, Direction::East));
|
||||
assert_eq!(board.get(1, 0).1, Archetype::Crate); // no mutation
|
||||
assert_eq!(board.get(2, 0).1, Archetype::Empty);
|
||||
|
||||
// Crate against a wall: not pushable.
|
||||
let mut board = open_board(3, 1, (0, 0), vec![], &[]);
|
||||
crate_at(&mut board, 1, 0);
|
||||
wall_at(&mut board, 2, 0);
|
||||
assert!(!board.can_push(1, 0, Direction::East));
|
||||
let mut game = GameState::new(board);
|
||||
game.try_move(Direction::East);
|
||||
let b = game.board();
|
||||
assert_eq!(b.get(2, 0).1, Archetype::Crate);
|
||||
assert_eq!(b.get(1, 0).1, Archetype::Empty);
|
||||
assert_eq!(b.glyph_at(0, 0), floor_glyph);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -460,24 +361,6 @@ mod tests {
|
||||
assert_eq!(b.get(3, 0).1, Archetype::Crate); // crate pushed to (3,0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pushable_allows_only_its_axis() {
|
||||
use Direction::*;
|
||||
for d in [North, South, East, West] {
|
||||
assert!(!Pushable::No.allows(d));
|
||||
assert!(Pushable::Any.allows(d));
|
||||
}
|
||||
assert!(Pushable::Horizontal.allows(East) && Pushable::Horizontal.allows(West));
|
||||
assert!(!Pushable::Horizontal.allows(North) && !Pushable::Horizontal.allows(South));
|
||||
assert!(Pushable::Vertical.allows(North) && Pushable::Vertical.allows(South));
|
||||
assert!(!Pushable::Vertical.allows(East) && !Pushable::Vertical.allows(West));
|
||||
}
|
||||
|
||||
/// Stamps an archetype cell onto an otherwise-open board.
|
||||
fn stamp(board: &mut Board, x: usize, y: usize, arch: Archetype) {
|
||||
*board.get_mut(x, y) = (arch.default_glyph(), arch);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hcrate_pushes_east_but_not_north() {
|
||||
// Pushing east: the HCrate slides.
|
||||
@@ -524,21 +407,6 @@ mod tests {
|
||||
assert_eq!(b.get(1, 0).1, Archetype::VCrate); // didn't move
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fresh_board_is_valid_and_reports_errors() {
|
||||
let mut board = open_board(1, 1, (0, 0), vec![], &[]);
|
||||
assert!(board.is_valid());
|
||||
board.report_error("something went wrong");
|
||||
assert!(!board.is_valid());
|
||||
assert_eq!(board.load_errors.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn directional_crate_default_glyph_tiles() {
|
||||
assert_eq!(Archetype::HCrate.default_glyph().tile, 29);
|
||||
assert_eq!(Archetype::VCrate.default_glyph().tile, 18);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn init_runs_only_on_run_init_not_at_construction() {
|
||||
let board = board_with_object(
|
||||
@@ -916,101 +784,6 @@ mod tests {
|
||||
assert!(log_texts(&game).iter().any(|t| t == "bumped by -1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn glyph_at_uses_floor_for_empty_and_grid_for_solid() {
|
||||
// A board with a distinctive floor glyph; empty cells show the floor, while
|
||||
// a wall keeps drawing its own grid glyph (floor ignored under solids).
|
||||
// Player parked at (2,0) so it doesn't overlap either asserted cell.
|
||||
let mut board = open_board(3, 1, (2, 0), vec![], &[]);
|
||||
let floor_glyph = Glyph {
|
||||
tile: '.' as u32,
|
||||
fg: Rgba8 {
|
||||
r: 10,
|
||||
g: 20,
|
||||
b: 30,
|
||||
a: 255,
|
||||
},
|
||||
bg: Rgba8 {
|
||||
r: 1,
|
||||
g: 2,
|
||||
b: 3,
|
||||
a: 255,
|
||||
},
|
||||
};
|
||||
board.floor = vec![floor_glyph; 3];
|
||||
wall_at(&mut board, 0, 0);
|
||||
assert_eq!(board.glyph_at(0, 0), Archetype::Wall.default_glyph()); // solid: grid glyph
|
||||
assert_eq!(board.glyph_at(1, 0), floor_glyph); // empty: floor glyph
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pushing_a_crate_reveals_the_floor_underneath() {
|
||||
// The cell a crate is pushed off of becomes Empty, so its `glyph_at`
|
||||
// should show the floor glyph rather than black-on-black.
|
||||
let mut board = open_board(4, 1, (0, 0), vec![], &[]);
|
||||
let floor_glyph = Glyph {
|
||||
tile: ',' as u32,
|
||||
fg: Rgba8 {
|
||||
r: 40,
|
||||
g: 60,
|
||||
b: 40,
|
||||
a: 255,
|
||||
},
|
||||
bg: Rgba8 {
|
||||
r: 5,
|
||||
g: 10,
|
||||
b: 5,
|
||||
a: 255,
|
||||
},
|
||||
};
|
||||
board.floor = vec![floor_glyph; 4];
|
||||
crate_at(&mut board, 1, 0);
|
||||
let mut game = GameState::new(board);
|
||||
game.try_move(Direction::East); // player at (0,0) pushes the crate east
|
||||
let b = game.board();
|
||||
assert_eq!(b.get(2, 0).1, Archetype::Crate); // crate moved one east
|
||||
// After the push the player is at (1,0); check the cell the player vacated
|
||||
// (0,0) — it is Empty and must reveal the floor glyph, not black-on-black.
|
||||
assert_eq!(b.get(1, 0).1, Archetype::Empty); // crate's old cell is empty
|
||||
assert_eq!(b.glyph_at(0, 0), floor_glyph); // player's old cell shows floor
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn solid_at_reports_player() {
|
||||
// The player's own cell is solid (and thus impassable to movers).
|
||||
let board = open_board(3, 1, (1, 0), vec![], &[]);
|
||||
match board.solid_at(1, 0) {
|
||||
Some(Solid::Player) => {}
|
||||
_ => panic!("expected Solid::Player at the player's cell"),
|
||||
}
|
||||
assert!(!board.is_passable(1, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn push_into_player_pushes_player() {
|
||||
// Crate shoved east into the player slides the player along into open space.
|
||||
let mut board = open_board(4, 1, (2, 0), vec![], &[]);
|
||||
crate_at(&mut board, 1, 0);
|
||||
assert!(board.can_push(1, 0, Direction::East));
|
||||
board.push(1, 0, Direction::East);
|
||||
assert_eq!(board.get(1, 0).1, Archetype::Empty); // crate left its cell
|
||||
assert_eq!(board.get(2, 0).1, Archetype::Crate); // crate took the player's old cell
|
||||
assert_eq!((board.player.x, board.player.y), (3, 0)); // player shoved east
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn push_into_player_blocked_by_wall() {
|
||||
// Player backed against a wall: the push has nowhere to go, so nothing moves
|
||||
// and the player is never overlapped.
|
||||
let mut board = open_board(4, 1, (2, 0), vec![], &[]);
|
||||
crate_at(&mut board, 1, 0);
|
||||
wall_at(&mut board, 3, 0);
|
||||
assert!(!board.can_push(1, 0, Direction::East));
|
||||
board.push(1, 0, Direction::East); // no-op
|
||||
assert_eq!(board.get(1, 0).1, Archetype::Crate);
|
||||
assert_eq!((board.player.x, board.player.y), (2, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn object_push_into_player() {
|
||||
// A scripted object moving into the player pushes the player when there's room.
|
||||
|
||||
@@ -111,3 +111,25 @@ pub struct Player {
|
||||
/// Row position (0-indexed, increasing downward).
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::script::Direction;
|
||||
use super::Pushable;
|
||||
|
||||
#[test]
|
||||
fn pushable_allows_only_its_axis() {
|
||||
for d in [Direction::North, Direction::South, Direction::East, Direction::West] {
|
||||
assert!(!Pushable::No.allows(d));
|
||||
assert!(Pushable::Any.allows(d));
|
||||
}
|
||||
assert!(Pushable::Horizontal.allows(Direction::East));
|
||||
assert!(Pushable::Horizontal.allows(Direction::West));
|
||||
assert!(!Pushable::Horizontal.allows(Direction::North));
|
||||
assert!(!Pushable::Horizontal.allows(Direction::South));
|
||||
assert!(Pushable::Vertical.allows(Direction::North));
|
||||
assert!(Pushable::Vertical.allows(Direction::South));
|
||||
assert!(!Pushable::Vertical.allows(Direction::East));
|
||||
assert!(!Pushable::Vertical.allows(Direction::West));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user