the huge refactor
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use super::{log_texts, scripted_object, scripts_from};
|
||||
use crate::archetype::Archetype;
|
||||
use crate::builtin::Archetype;
|
||||
use crate::board::tests::{crate_at, open_board, wall_at};
|
||||
use crate::game::GameState;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
use crate::archetype::Archetype;
|
||||
use crate::builtin::Archetype;
|
||||
use crate::board::Board;
|
||||
use crate::floor::Floor;
|
||||
use crate::game::GameState;
|
||||
use crate::glyph::Glyph;
|
||||
use crate::utils::{Direction, PlayerPos, PortalDef};
|
||||
use crate::utils::{Direction, PlayerPos};
|
||||
use crate::world::World;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::rc::Rc;
|
||||
use crate::portal::Portal;
|
||||
|
||||
/// Builds a 3×3 board with the player at `(px, py)` and the given portals.
|
||||
fn make_board(px: i64, py: i64, portals: Vec<PortalDef>) -> Board {
|
||||
fn make_board(px: i64, py: i64, portals: Vec<Portal>) -> Board {
|
||||
Board {
|
||||
name: "test".into(),
|
||||
width: 3,
|
||||
@@ -38,23 +39,23 @@ fn two_board_world() -> World {
|
||||
let b1 = make_board(
|
||||
0,
|
||||
0,
|
||||
vec![PortalDef {
|
||||
vec![Portal {
|
||||
name: "to_b2".into(),
|
||||
x: 2,
|
||||
y: 0,
|
||||
target_map: "b2".into(),
|
||||
target_entry: "from_b1".into(),
|
||||
target_board: "b2".into(),
|
||||
target_name: "from_b1".into(),
|
||||
}],
|
||||
);
|
||||
let b2 = make_board(
|
||||
0,
|
||||
0,
|
||||
vec![PortalDef {
|
||||
vec![Portal {
|
||||
name: "from_b1".into(),
|
||||
x: 1,
|
||||
y: 1,
|
||||
target_map: "b1".into(),
|
||||
target_entry: "to_b2".into(),
|
||||
target_board: "b1".into(),
|
||||
target_name: "to_b2".into(),
|
||||
}],
|
||||
);
|
||||
World {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::load_board;
|
||||
use crate::archetype::Archetype;
|
||||
use crate::builtin::Archetype;
|
||||
|
||||
#[test]
|
||||
fn fill_builds_a_full_grid_of_one_char() {
|
||||
@@ -23,7 +23,7 @@ palette = { "#" = { kind = "wall", tile = 35, fg = "#808080", bg = "#606060" } }
|
||||
assert!(board.solid_at(x, y).unwrap().player());
|
||||
} else {
|
||||
let obj = &board.objects[&board.object_ids_at(x, y)[0]];
|
||||
let tag = obj.tags.iter().next().unwrap();
|
||||
let tag = obj.scripting.tags.iter().next().unwrap();
|
||||
assert_eq!(tag, "BUILTIN_wall")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::{grid, load_board, map};
|
||||
use crate::archetype::Archetype;
|
||||
use crate::builtin::Archetype;
|
||||
use crate::board::Board;
|
||||
use crate::map_file::MapFile;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::{grid, load_board, map, map_3x1_object};
|
||||
use crate::archetype::Archetype;
|
||||
use crate::builtin::Archetype;
|
||||
|
||||
/// Palette shorthand.
|
||||
const PLAYER: (&str, &str) = ("@", "kind = \"player\"");
|
||||
@@ -30,8 +30,8 @@ fn duplicate_name_clears_second_but_keeps_both_objects() {
|
||||
),
|
||||
));
|
||||
assert_eq!(board.objects.len(), 2, "both objects survive");
|
||||
assert_eq!(board.objects[&1].name.as_deref(), Some("gate"));
|
||||
assert_eq!(board.objects[&2].name, None);
|
||||
assert_eq!(board.objects[&1].scripting.name.as_deref(), Some("gate"));
|
||||
assert_eq!(board.objects[&2].scripting.name, None);
|
||||
assert!(!board.is_valid(), "duplicate name is a nonfatal load error");
|
||||
}
|
||||
|
||||
@@ -66,9 +66,9 @@ fn palette_char_multi_occurrence_only_first_keeps_name() {
|
||||
),
|
||||
));
|
||||
assert_eq!(board.objects.len(), 3);
|
||||
assert_eq!(board.objects[&1].name.as_deref(), Some("guard"));
|
||||
assert_eq!(board.objects[&2].name, None);
|
||||
assert_eq!(board.objects[&3].name, None);
|
||||
assert_eq!(board.objects[&1].scripting.name.as_deref(), Some("guard"));
|
||||
assert_eq!(board.objects[&2].scripting.name, None);
|
||||
assert_eq!(board.objects[&3].scripting.name, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::{grid, load_board, map};
|
||||
use crate::archetype::Archetype;
|
||||
use crate::builtin::Archetype;
|
||||
|
||||
/// Palette shorthands shared by these tests.
|
||||
const EMPTY: (&str, &str) = (".", "kind = \"empty\"");
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
//! carrying the embedded `pusher.rhai` plus a `BUILTIN_pusher_<dir>` tag).
|
||||
|
||||
use super::{grid, load_board, map};
|
||||
use crate::archetype::Archetype;
|
||||
use crate::builtin::Archetype;
|
||||
use crate::game::GameState;
|
||||
use crate::map_file::MapFile;
|
||||
use crate::object_def::ObjectDef;
|
||||
use std::time::Duration;
|
||||
use crate::{Board, Builtin};
|
||||
use crate::Board;
|
||||
|
||||
/// 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 {
|
||||
let (&oid, obj) = board
|
||||
.objects
|
||||
.iter()
|
||||
.find(|(_, o)| o.tags.contains("BUILTIN_pusher_east"))
|
||||
.find(|(_, o)| o.scripting.tags.contains("BUILTIN_pusher_east"))
|
||||
.expect("pusher object");
|
||||
*id = oid;
|
||||
obj
|
||||
@@ -34,17 +34,17 @@ fn pusher_loads_as_a_tagged_scripted_solid_object() {
|
||||
let p = pusher(&board, &mut id);
|
||||
assert_eq!((p.x, p.y), (0, 0));
|
||||
assert!(
|
||||
p.builtin_script.is_some(),
|
||||
p.scripting.builtin_script.is_some(),
|
||||
"carries the embedded pusher script"
|
||||
);
|
||||
// Each alias gets its own compile-cache key (e.g. "BUILTIN_pusher_east") so the
|
||||
// script can read direction from Me.has_tag("BUILTIN_pusher_east").
|
||||
assert_eq!(p.script_name.as_deref(), Some("BUILTIN_pusher_east"));
|
||||
assert_eq!(p.scripting.script_name.as_deref(), Some("BUILTIN_pusher_east"));
|
||||
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))
|
||||
board.object_ids_at(x, y).iter().any(|id| board.objects[id].scripting.tags.contains(tag))
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -135,5 +135,5 @@ fn pusher_round_trips_to_its_keyword() {
|
||||
let mut id = 0;
|
||||
let p = pusher(&board2, &mut id);
|
||||
assert_eq!((p.x, p.y), (0, 0));
|
||||
assert!(p.builtin_script.is_some());
|
||||
assert!(p.scripting.builtin_script.is_some());
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ fn object_tags_round_trip_through_toml() {
|
||||
);
|
||||
let board = load_board(&toml);
|
||||
let obj0 = &board.objects[&1];
|
||||
assert!(obj0.tags.contains("enemy") && obj0.tags.contains("boss"));
|
||||
assert_eq!(obj0.tags.len(), 2);
|
||||
assert!(obj0.scripting.tags.contains("enemy") && obj0.scripting.tags.contains("boss"));
|
||||
assert_eq!(obj0.scripting.tags.len(), 2);
|
||||
|
||||
// Saved tags must be sorted alphabetically (boss before enemy).
|
||||
let toml_out = toml::to_string_pretty(&MapFile::from(&board)).unwrap();
|
||||
@@ -70,7 +70,7 @@ fn object_tags_round_trip_through_toml() {
|
||||
assert!(boss < enemy, "tags must be sorted: boss before enemy");
|
||||
|
||||
let board2 = load_board(&toml_out);
|
||||
assert_eq!(board2.objects[&1].tags, obj0.tags);
|
||||
assert_eq!(board2.objects[&1].scripting.tags, obj0.scripting.tags);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -95,7 +95,7 @@ fn object_name_round_trips_through_toml() {
|
||||
),
|
||||
);
|
||||
let board = load_board(&toml);
|
||||
assert_eq!(board.objects[&1].name.as_deref(), Some("beacon"));
|
||||
assert_eq!(board.objects[&1].scripting.name.as_deref(), Some("beacon"));
|
||||
|
||||
let toml_out = toml::to_string_pretty(&MapFile::from(&board)).unwrap();
|
||||
assert!(
|
||||
@@ -103,7 +103,7 @@ fn object_name_round_trips_through_toml() {
|
||||
"name must appear in saved TOML"
|
||||
);
|
||||
let board2 = load_board(&toml_out);
|
||||
assert_eq!(board2.objects[&1].name.as_deref(), Some("beacon"));
|
||||
assert_eq!(board2.objects[&1].scripting.name.as_deref(), Some("beacon"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -111,7 +111,7 @@ fn unnamed_object_name_stays_none_through_toml() {
|
||||
let toml = map(3, 1, &grid("@O.", &[PLAYER, ("O", &obj("")), EMPTY]));
|
||||
let board2 = round_trip(&toml);
|
||||
assert_eq!(
|
||||
board2.objects[&1].name, None,
|
||||
board2.objects[&1].scripting.name, None,
|
||||
"unnamed object must round-trip as None"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,16 +18,16 @@ fn spinner_loads_as_a_tagged_scripted_solid_object() {
|
||||
let (_, obj) = board
|
||||
.objects
|
||||
.iter()
|
||||
.find(|(_, o)| o.tags.contains("BUILTIN_spinner_cw"))
|
||||
.find(|(_, o)| o.scripting.tags.contains("BUILTIN_spinner_cw"))
|
||||
.expect("spinner object");
|
||||
assert_eq!((obj.x, obj.y), (0, 0));
|
||||
assert!(
|
||||
obj.builtin_script.is_some(),
|
||||
obj.scripting.builtin_script.is_some(),
|
||||
"carries the embedded spinner script"
|
||||
);
|
||||
// Each alias gets its own compile-cache key (e.g. "BUILTIN_spinner_cw") so the
|
||||
// script can read direction from Me.has_tag("BUILTIN_spinner_cw").
|
||||
assert_eq!(obj.script_name.as_deref(), Some("BUILTIN_spinner_cw"));
|
||||
assert_eq!(obj.scripting.script_name.as_deref(), Some("BUILTIN_spinner_cw"));
|
||||
assert!(!board.is_passable(0, 0), "spinner is solid");
|
||||
}
|
||||
|
||||
@@ -53,8 +53,8 @@ fn spinner_round_trips_to_its_keyword() {
|
||||
let (_, obj) = board2
|
||||
.objects
|
||||
.iter()
|
||||
.find(|(_, o)| o.tags.contains("BUILTIN_spinner_ccw"))
|
||||
.find(|(_, o)| o.scripting.tags.contains("BUILTIN_spinner_ccw"))
|
||||
.expect("spinner object after round-trip");
|
||||
assert_eq!((obj.x, obj.y), (0, 0));
|
||||
assert!(obj.builtin_script.is_some());
|
||||
assert!(obj.scripting.builtin_script.is_some());
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ fn transporter_loads_as_a_tagged_scripted_object() {
|
||||
let (_, obj) = board
|
||||
.objects
|
||||
.iter()
|
||||
.find(|(_, o)| o.tags.contains("BUILTIN_transporter_east"))
|
||||
.find(|(_, o)| o.scripting.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.scripting.builtin_script.is_some(), "carries the embedded script");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -145,7 +145,7 @@ fn transporter_round_trips_to_its_keyword() {
|
||||
board2
|
||||
.objects
|
||||
.values()
|
||||
.any(|o| o.tags.contains("BUILTIN_transporter_east") && o.builtin_script.is_some()),
|
||||
.any(|o| o.scripting.tags.contains("BUILTIN_transporter_east") && o.scripting.builtin_script.is_some()),
|
||||
"reloads as a tagged transporter object",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ mod map_file;
|
||||
mod movement;
|
||||
mod scripting;
|
||||
|
||||
use crate::archetype::Archetype;
|
||||
use crate::builtin::Archetype;
|
||||
use crate::board::Board;
|
||||
use crate::floor::Floor;
|
||||
use crate::game::GameState;
|
||||
@@ -24,7 +24,7 @@ fn board_with_object(
|
||||
) -> (Board, HashMap<String, String>) {
|
||||
let mut object = ObjectDef::new(0, 0);
|
||||
object.id = 1;
|
||||
object.script_name = object_script.map(str::to_string);
|
||||
object.scripting.script_name = object_script.map(str::to_string);
|
||||
let board = Board {
|
||||
name: "test".into(),
|
||||
width: 1,
|
||||
@@ -57,7 +57,7 @@ fn scripts_from(pairs: &[(&str, &str)]) -> HashMap<String, String> {
|
||||
/// Returns an `ObjectDef` at `(x, y)` bound to the named script.
|
||||
fn scripted_object(x: usize, y: usize, script: &str) -> ObjectDef {
|
||||
let mut o = ObjectDef::new(x, y);
|
||||
o.script_name = Some(script.to_string());
|
||||
o.scripting.script_name = Some(script.to_string());
|
||||
o
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::archetype::Archetype;
|
||||
use crate::builtin::Archetype;
|
||||
use crate::board::tests::{add_floor, crate_at, open_board, stamp, wall_at};
|
||||
use crate::game::GameState;
|
||||
use crate::glyph::Glyph;
|
||||
|
||||
@@ -131,7 +131,7 @@ fn set_tag_adds_and_removes_via_my_id() {
|
||||
);
|
||||
let mut game = GameState::with_scripts(board, scripts);
|
||||
game.run_init();
|
||||
assert!(game.board().objects[&1].tags.contains("active"));
|
||||
assert!(game.board().objects[&1].scripting.tags.contains("active"));
|
||||
|
||||
// A script removes a pre-existing tag.
|
||||
let (mut board2, scripts2) = board_with_object(
|
||||
@@ -143,11 +143,12 @@ fn set_tag_adds_and_removes_via_my_id() {
|
||||
.objects
|
||||
.get_mut(&1)
|
||||
.unwrap()
|
||||
.scripting
|
||||
.tags
|
||||
.insert("active".to_string());
|
||||
let mut game2 = GameState::with_scripts(board2, scripts2);
|
||||
game2.run_init();
|
||||
assert!(!game2.board().objects[&1].tags.contains("active"));
|
||||
assert!(!game2.board().objects[&1].scripting.tags.contains("active"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -175,7 +176,7 @@ fn objects_with_tag_returns_matching_ids() {
|
||||
let obj1 = scripted_object(0, 0, "q");
|
||||
let mut obj2 = scripted_object(1, 0, "none");
|
||||
// obj2 (id=2) has the "enemy" tag; obj1 (id=1) does not.
|
||||
obj2.tags.insert("enemy".to_string());
|
||||
obj2.scripting.tags.insert("enemy".to_string());
|
||||
let board = open_board(5, 1, (4, 0), vec![obj1, obj2]);
|
||||
let mut game = GameState::with_scripts(
|
||||
board,
|
||||
@@ -202,7 +203,7 @@ fn my_name_returns_name_or_empty_string() {
|
||||
// An object with a name set on its ObjectDef should see it via my_name().
|
||||
let (mut board, scripts) =
|
||||
board_with_object(Some("n"), &[("n", r#"fn init(m) { log(m.name); }"#)]);
|
||||
board.objects.get_mut(&1).unwrap().name = Some("beacon".to_string());
|
||||
board.objects.get_mut(&1).unwrap().scripting.name = Some("beacon".to_string());
|
||||
let mut game = GameState::with_scripts(board, scripts);
|
||||
game.run_init();
|
||||
assert_eq!(log_texts(&game), vec!["beacon"]);
|
||||
@@ -221,7 +222,7 @@ fn object_id_for_name_finds_by_name() {
|
||||
// object_id_for_name to find the named one and logs its id.
|
||||
let obj1 = scripted_object(0, 0, "q");
|
||||
let mut obj2 = scripted_object(1, 0, "none");
|
||||
obj2.name = Some("target".to_string());
|
||||
obj2.scripting.name = Some("target".to_string());
|
||||
let board = open_board(5, 1, (4, 0), vec![obj1, obj2]);
|
||||
let mut game = GameState::with_scripts(
|
||||
board,
|
||||
|
||||
Reference in New Issue
Block a user