transporters
This commit is contained in:
@@ -6,6 +6,7 @@ mod portal_placement;
|
||||
mod pushers;
|
||||
mod round_trip;
|
||||
mod spinners;
|
||||
mod transporters;
|
||||
|
||||
use crate::board::Board;
|
||||
use crate::map_file::MapFile;
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
//! Transporters are scripted objects (the `transporter_*` archetypes expand into
|
||||
//! objects carrying the embedded `transporter.rhai` plus a
|
||||
//! `BUILTIN_transporter_<dir>` tag). Bumping one from its facing side teleports
|
||||
//! the bumper past it, or out of a paired opposite-facing transporter.
|
||||
|
||||
use super::{layer, load_board, map};
|
||||
use crate::game::GameState;
|
||||
use crate::map_file::MapFile;
|
||||
use crate::utils::Direction;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
fn transporter_loads_as_a_tagged_scripted_solid_object() {
|
||||
let board = load_board(&map(
|
||||
3,
|
||||
1,
|
||||
&[layer(
|
||||
"@T ",
|
||||
&[("@", "kind = \"player\""), ("T", "kind = \"transporter_east\"")],
|
||||
)],
|
||||
));
|
||||
let (_, obj) = board
|
||||
.objects
|
||||
.iter()
|
||||
.find(|(_, o)| o.tags.contains("BUILTIN_transporter_east"))
|
||||
.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]
|
||||
fn bumping_a_transporter_drops_you_on_its_far_side() {
|
||||
// Player at (0,0), an east transporter at (1,0), and a free cell at (2,0).
|
||||
let board = load_board(&map(
|
||||
3,
|
||||
1,
|
||||
&[layer(
|
||||
"@T ",
|
||||
&[("@", "kind = \"player\""), ("T", "kind = \"transporter_east\"")],
|
||||
)],
|
||||
));
|
||||
let mut game = GameState::new(board);
|
||||
game.run_init();
|
||||
|
||||
// Walk east into the transporter: it's solid so the player doesn't step onto
|
||||
// it, but the bump queues a teleport that the next tick applies.
|
||||
game.try_move(Direction::East);
|
||||
game.tick(Duration::from_secs_f64(0.1));
|
||||
|
||||
let b = game.board();
|
||||
assert_eq!((b.player.x, b.player.y), (2, 0), "transported past the transporter");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_blocked_far_side_transports_out_of_the_paired_transporter() {
|
||||
// Player, east transporter, a wall blocking its far side, the free entrance
|
||||
// cell, then the paired west transporter. The player should pop out at the
|
||||
// west transporter's entrance (the cell just before it), across the wall.
|
||||
let board = load_board(&map(
|
||||
6,
|
||||
1,
|
||||
&[layer(
|
||||
"@T# W ",
|
||||
&[
|
||||
("@", "kind = \"player\""),
|
||||
("T", "kind = \"transporter_east\""),
|
||||
("#", "kind = \"wall\", tile = 35, fg = \"#808080\", bg = \"#606060\""),
|
||||
("W", "kind = \"transporter_west\""),
|
||||
],
|
||||
)],
|
||||
));
|
||||
let mut game = GameState::new(board);
|
||||
game.run_init();
|
||||
|
||||
game.try_move(Direction::East);
|
||||
game.tick(Duration::from_secs_f64(0.1));
|
||||
|
||||
let b = game.board();
|
||||
assert_eq!(
|
||||
(b.player.x, b.player.y),
|
||||
(3, 0),
|
||||
"transported to the paired transporter's entrance",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transporter_round_trips_to_its_keyword() {
|
||||
let board = load_board(&map(
|
||||
3,
|
||||
1,
|
||||
&[layer(
|
||||
"@T ",
|
||||
&[("@", "kind = \"player\""), ("T", "kind = \"transporter_east\"")],
|
||||
)],
|
||||
));
|
||||
// Save collapses the expanded object back into the `transporter_east` keyword.
|
||||
let toml_out = toml::to_string_pretty(&MapFile::from(&board)).unwrap();
|
||||
assert!(
|
||||
toml_out.contains("transporter_east"),
|
||||
"transporter should save as its archetype keyword, got:\n{toml_out}"
|
||||
);
|
||||
|
||||
// Reload: it is a working transporter object again.
|
||||
let board2 = load_board(&toml_out);
|
||||
assert!(
|
||||
board2
|
||||
.objects
|
||||
.values()
|
||||
.any(|o| o.tags.contains("BUILTIN_transporter_east") && o.builtin_script.is_some()),
|
||||
"reloads as a tagged transporter object",
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user