This commit is contained in:
2026-07-14 23:48:50 -05:00
parent 03185c9c68
commit 5146cc9bcc
25 changed files with 380 additions and 272 deletions
+2 -1
View File
@@ -3,6 +3,7 @@ use crate::archetype::Archetype;
use crate::board::tests::{crate_at, open_board, wall_at};
use crate::game::GameState;
use std::time::Duration;
use crate::Builtin;
#[test]
fn move_command_relocates_the_source_object() {
@@ -45,7 +46,7 @@ fn object_pushes_crate_on_init() {
let b = game.board();
assert_eq!((b.objects[&1].x, b.objects[&1].y), (2, 0));
assert_eq!(b.get(2, 0).1, Archetype::Empty);
assert_eq!(b.get(3, 0).1, Archetype::Crate);
assert_eq!(b.get(3, 0).1, Archetype::Builtin(Builtin::Crate, "crate"));
}
#[test]
+1
View File
@@ -18,6 +18,7 @@ fn make_board(px: i64, py: i64, portals: Vec<PortalDef>) -> Board {
grid: vec![(Glyph::transparent(), Archetype::Empty); 9],
floor: Floor::Blank,
decorations: Vec::new(),
sensors: Vec::new(),
player: PlayerPos { x: px, y: py },
objects: BTreeMap::new(),
next_object_id: 1,
+7 -5
View File
@@ -19,12 +19,14 @@ palette = { "#" = { kind = "wall", tile = 35, fg = "#808080", bg = "#606060" } }
let board = load_board(toml);
for y in 0..2 {
for x in 0..3 {
let expected = if (x, y) == (0, 0) {
Archetype::Empty // player won its fallback cell
if (x, y) == (0, 0) { // player won its fallback cell
assert!(board.solid_at(x, y).unwrap().player());
} else {
Archetype::Wall
};
assert_eq!(board.get(x, y).1, expected, "cell ({x}, {y})");
let obj = &board.objects[&board.object_ids_at(x, y)[0]];
let tag = obj.tags.iter().next().unwrap();
assert_eq!(tag, "BUILTIN_wall")
}
}
}
assert_eq!((board.player.x, board.player.y), (0, 0));
@@ -77,6 +77,6 @@ fn non_solid_object_and_wall_coexist_in_separate_cells() {
// never be authored onto a wall cell. A wall and a (separate-cell) non-solid
// object both load fine.
let board = load_board(&map_3x1_object("#G@", "G", "solid = false"));
assert_eq!(board.objects.len(), 1);
assert_eq!(board.objects.len(), 2); // The wall (for now) shows up as an object because it's a builtin, TODO
assert!(board.is_valid());
}
+6 -1
View File
@@ -7,6 +7,7 @@ use crate::game::GameState;
use crate::map_file::MapFile;
use crate::object_def::ObjectDef;
use std::time::Duration;
use crate::{Board, Builtin};
/// Finds the pusher object on a board (by its built-in tag).
fn pusher<'a>(board: &'a crate::board::Board, id: &mut u32) -> &'a ObjectDef {
@@ -42,6 +43,10 @@ fn pusher_loads_as_a_tagged_scripted_solid_object() {
assert!(!board.is_passable(0, 0), "pusher is solid");
}
fn is_tag(board: &Board, x: usize, y: usize, tag: &str) -> bool {
board.object_ids_at(x, y).iter().any(|id| board.objects[id].tags.contains(tag))
}
#[test]
fn pusher_advances_and_shoves_a_crate() {
// Pusher at (0,0), crate at (1,0), the player parked at the east edge.
@@ -74,7 +79,7 @@ fn pusher_advances_and_shoves_a_crate() {
"crate left its start cell"
);
assert!(
(2..b.width).any(|x| b.get(x, 0).1 == Archetype::Crate),
(2..b.width).any(|x| is_tag(&b, x, 0, "BUILTIN_crate")),
"crate was shoved east"
);
}
+1 -4
View File
@@ -10,7 +10,7 @@ use crate::utils::Direction;
use std::time::Duration;
#[test]
fn transporter_loads_as_a_tagged_scripted_solid_object() {
fn transporter_loads_as_a_tagged_scripted_object() {
let board = load_board(&map(
3,
1,
@@ -26,9 +26,6 @@ fn transporter_loads_as_a_tagged_scripted_solid_object() {
.expect("transporter object");
assert_eq!((obj.x, obj.y), (1, 0));
assert!(obj.builtin_script.is_some(), "carries the embedded script");
assert!(obj.solid, "transporter is solid");
assert!(!obj.opaque, "transporter is see-through");
assert!(!obj.pushable, "transporter cannot be pushed");
}
#[test]
+2 -1
View File
@@ -32,6 +32,7 @@ fn board_with_object(
grid: vec![(Glyph::transparent(), Archetype::Empty)],
floor: Floor::Blank,
decorations: Vec::new(),
sensors: Vec::new(),
player: PlayerPos { x: 0, y: 0 },
objects: BTreeMap::from([(1, object)]),
next_object_id: 2,
@@ -64,7 +65,7 @@ fn scripted_object(x: usize, y: usize, script: &str) -> ObjectDef {
/// kind that receives an `enter` hook when a solid relocates onto its cell.
fn nonsolid_object(x: usize, y: usize, script: &str) -> ObjectDef {
let mut o = scripted_object(x, y, script);
o.solid = false;
o.behavior.solid = false;
o
}
+20 -19
View File
@@ -3,8 +3,9 @@ use crate::board::tests::{add_floor, crate_at, open_board, stamp, wall_at};
use crate::game::GameState;
use crate::glyph::Glyph;
use crate::object_def::ObjectDef;
use crate::utils::Direction;
use crate::utils::{Direction, Pushable};
use color::Rgba8;
use crate::Builtin;
#[test]
fn pushing_a_crate_reveals_the_floor_underneath() {
@@ -32,7 +33,7 @@ fn pushing_a_crate_reveals_the_floor_underneath() {
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(2, 0).1, Archetype::Builtin(Builtin::Crate, "crate"));
assert_eq!(b.get(1, 0).1, Archetype::Empty);
assert_eq!(b.glyph_at(0, 0), floor_glyph);
}
@@ -46,7 +47,7 @@ fn player_pushes_single_crate() {
let b = game.board();
assert_eq!((b.player.x, b.player.y), (1, 0));
assert_eq!(b.get(1, 0).1, Archetype::Empty);
assert_eq!(b.get(2, 0).1, Archetype::Crate);
assert_eq!(b.get(2, 0).1, Archetype::Builtin(Builtin::Crate, "crate"));
}
#[test]
@@ -58,8 +59,8 @@ fn push_blocked_by_wall_moves_nothing() {
game.try_move(Direction::East);
let b = game.board();
assert_eq!((b.player.x, b.player.y), (0, 0));
assert_eq!(b.get(1, 0).1, Archetype::Crate);
assert_eq!(b.get(2, 0).1, Archetype::Wall);
assert_eq!(b.get(1, 0).1, Archetype::Builtin(Builtin::Crate, "crate"));
assert_eq!(b.get(2, 0).1, Archetype::Builtin(Builtin::Wall, "wall"));
}
#[test]
@@ -71,7 +72,7 @@ fn push_blocked_by_edge_moves_nothing() {
game.try_move(Direction::East);
let b = game.board();
assert_eq!((b.player.x, b.player.y), (0, 0));
assert_eq!(b.get(1, 0).1, Archetype::Crate);
assert_eq!(b.get(1, 0).1, Archetype::Builtin(Builtin::Crate, "crate"));
}
#[test]
@@ -84,8 +85,8 @@ fn cascade_pushes_two_crates() {
let b = game.board();
assert_eq!((b.player.x, b.player.y), (1, 0));
assert_eq!(b.get(1, 0).1, Archetype::Empty);
assert_eq!(b.get(2, 0).1, Archetype::Crate);
assert_eq!(b.get(3, 0).1, Archetype::Crate);
assert_eq!(b.get(2, 0).1, Archetype::Builtin(Builtin::Crate, "crate"));
assert_eq!(b.get(3, 0).1, Archetype::Builtin(Builtin::Crate, "crate"));
}
#[test]
@@ -98,15 +99,15 @@ fn cascade_blocked_by_wall_moves_nothing() {
game.try_move(Direction::East);
let b = game.board();
assert_eq!((b.player.x, b.player.y), (0, 0));
assert_eq!(b.get(1, 0).1, Archetype::Crate);
assert_eq!(b.get(2, 0).1, Archetype::Crate);
assert_eq!(b.get(1, 0).1, Archetype::Builtin(Builtin::Crate, "crate"));
assert_eq!(b.get(2, 0).1, Archetype::Builtin(Builtin::Crate, "crate"));
}
#[test]
fn player_pushes_pushable_solid_object() {
// A solid, pushable object is shoved exactly like a crate.
let mut obj = ObjectDef::new(1, 0);
obj.pushable = true;
obj.behavior.pushable = Pushable::Any;
let board = open_board(4, 1, (0, 0), vec![obj]);
let mut game = GameState::new(board);
game.try_move(Direction::East);
@@ -119,44 +120,44 @@ fn player_pushes_pushable_solid_object() {
fn hcrate_pushes_east_but_not_north() {
// Pushing east: the HCrate slides.
let mut board = open_board(4, 1, (0, 0), vec![]);
stamp(&mut board, 1, 0, Archetype::HCrate);
stamp(&mut board, 1, 0, Archetype::Builtin(Builtin::HCrate, "hcrate"));
let mut game = GameState::new(board);
game.try_move(Direction::East);
let b = game.board();
assert_eq!((b.player.x, b.player.y), (1, 0));
assert_eq!(b.get(1, 0).1, Archetype::Empty);
assert_eq!(b.get(2, 0).1, Archetype::HCrate);
assert_eq!(b.get(2, 0).1, Archetype::Builtin(Builtin::HCrate, "hcrate"));
drop(b);
// Pushing north into an HCrate: blocked, nothing moves.
let mut board = open_board(1, 4, (0, 3), vec![]);
stamp(&mut board, 0, 2, Archetype::HCrate);
stamp(&mut board, 0, 2, Archetype::Builtin(Builtin::HCrate, "hcrate"));
let mut game = GameState::new(board);
game.try_move(Direction::North);
let b = game.board();
assert_eq!((b.player.x, b.player.y), (0, 3));
assert_eq!(b.get(0, 2).1, Archetype::HCrate);
assert_eq!(b.get(0, 2).1, Archetype::Builtin(Builtin::HCrate, "hcrate"));
}
#[test]
fn vcrate_pushes_north_but_not_east() {
// Pushing north: the VCrate slides.
let mut board = open_board(1, 4, (0, 3), vec![]);
stamp(&mut board, 0, 2, Archetype::VCrate);
stamp(&mut board, 0, 2, Archetype::Builtin(Builtin::VCrate, "vcrate"));
let mut game = GameState::new(board);
game.try_move(Direction::North);
let b = game.board();
assert_eq!((b.player.x, b.player.y), (0, 2));
assert_eq!(b.get(0, 2).1, Archetype::Empty);
assert_eq!(b.get(0, 1).1, Archetype::VCrate);
assert_eq!(b.get(0, 1).1, Archetype::Builtin(Builtin::VCrate, "vcrate"));
drop(b);
// Pushing east into a VCrate: blocked, nothing moves.
let mut board = open_board(4, 1, (0, 0), vec![]);
stamp(&mut board, 1, 0, Archetype::VCrate);
stamp(&mut board, 1, 0, Archetype::Builtin(Builtin::VCrate, "vcrate"));
let mut game = GameState::new(board);
game.try_move(Direction::East);
let b = game.board();
assert_eq!((b.player.x, b.player.y), (0, 0));
assert_eq!(b.get(1, 0).1, Archetype::VCrate);
assert_eq!(b.get(1, 0).1, Archetype::Builtin(Builtin::VCrate, "vcrate"));
}