cleanup
This commit is contained in:
@@ -235,11 +235,13 @@ impl Board {
|
||||
self.solid_at(x, y).is_none()
|
||||
}
|
||||
|
||||
/// Returns `true` if the mover as `(x1, y1)` can enter `(x2, y2)` — i.e. it would not
|
||||
/// break the rules of "one solid per cell, except for player + grab".
|
||||
/// Returns `true` if the solids at `(x1, y1)` and `(x2, y2)` may share a cell —
|
||||
/// i.e. moving one onto the other wouldn't break the "one solid per cell"
|
||||
/// invariant. That holds when at least one cell is empty, or one holds the
|
||||
/// player and the other a **grab** thing (the player collects it).
|
||||
///
|
||||
/// Convenience inverse of [`solid_at`](Board::solid_at).
|
||||
/// Panics if `x` or `y` are out of bounds.
|
||||
/// Off-board coordinates are never combinable (returns `false` rather than
|
||||
/// panicking). Backs the script-facing `combinable(x1, y1, x2, y2)` fn.
|
||||
pub fn is_combinable(&self, x1: usize, y1: usize, x2: usize, y2: usize) -> bool {
|
||||
// Are either out of bounds?
|
||||
if !self.in_bounds((x1 as i32, y1 as i32)) || !self.in_bounds((x2 as i32, y2 as i32)) {
|
||||
|
||||
@@ -55,9 +55,11 @@ pub(crate) fn archetype_script(arch: Archetype) -> Option<&'static str> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the embedded script implementing `arch` as an object, or `None` if the
|
||||
/// archetype is a plain terrain cell. The one place script-backed archetypes are
|
||||
/// declared.
|
||||
/// Returns the synthetic `BUILTIN_*` compile-key for `arch`'s embedded script, or
|
||||
/// `None` if the archetype is a plain terrain cell. [`Board::expand_builtin_archetypes`](crate::board::Board::expand_builtin_archetypes)
|
||||
/// stores this as the expanded object's `script_name` so every instance of a
|
||||
/// script-backed archetype shares one compiled AST (the source comes from
|
||||
/// [`archetype_script`]).
|
||||
pub(crate) fn archetype_script_key(arch: Archetype) -> Option<&'static str> {
|
||||
match arch {
|
||||
Archetype::Pusher(_) => Some("BUILTIN_pusher"),
|
||||
|
||||
@@ -54,13 +54,18 @@ pub struct ObjectDef {
|
||||
/// remove itself via `die()`). Set when a grab archetype (e.g. a gem) is
|
||||
/// expanded into an object. Defaults to `false`.
|
||||
pub grab: bool,
|
||||
/// Name of the Rhai script in [`Board::scripts`] that drives this object.
|
||||
/// `None` means this object has no script yet.
|
||||
/// Compile-key of the Rhai script that drives this object: a name in
|
||||
/// [`World::scripts`](crate::world::World::scripts) for a hand-authored object,
|
||||
/// or a synthetic `BUILTIN_*` name set when a script-backed archetype is
|
||||
/// expanded (see [`builtin_script`](ObjectDef::builtin_script)). `None` means
|
||||
/// this object has no script yet.
|
||||
pub script_name: Option<String>,
|
||||
/// Embedded built-in script source, set when a script-backed archetype (e.g. a
|
||||
/// `pusher_*`) is expanded into an object at load time (see
|
||||
/// [`crate::builtin_scripts`]). Takes precedence over [`script_name`](ObjectDef::script_name)
|
||||
/// and is not part of the map file (it is regenerated from the archetype on load).
|
||||
/// `pusher_*` or `gem`) is expanded into an object at load time (see
|
||||
/// [`crate::builtin_scripts`]). When set, this is the object's script *source*
|
||||
/// (its compile-key is the synthetic `BUILTIN_*` [`script_name`](ObjectDef::script_name)
|
||||
/// the same expansion assigns). Not part of the map file — it is regenerated
|
||||
/// from the archetype on load.
|
||||
pub builtin_script: Option<&'static str>,
|
||||
/// Open-ended string labels for this object. Serialized as a TOML array;
|
||||
/// not subject to any rate limit — mutations take effect immediately after
|
||||
|
||||
+12
-7
@@ -115,15 +115,19 @@ struct CompiledScript {
|
||||
struct ObjectRuntime {
|
||||
object_id: ObjectId,
|
||||
/// Key into [`ScriptHost::scripts`] for this object's compiled script — the
|
||||
/// pool name for a named script, or the source text for an embedded built-in.
|
||||
/// world-pool name for a named script, or the synthetic `BUILTIN_*` name for an
|
||||
/// expanded built-in.
|
||||
script_key: String,
|
||||
scope: Scope<'static>,
|
||||
output_queue: ObjQueue,
|
||||
}
|
||||
|
||||
/// The compile-key for an object's script: the embedded source itself for a
|
||||
/// built-in (so identical built-ins share one compiled AST), or the world-pool
|
||||
/// name for a named script. `None` if the object has no script.
|
||||
/// The compile-key for an object's script: the object's `script_name` — a
|
||||
/// world-pool name for a named script, or a synthetic `BUILTIN_*` name set by
|
||||
/// [`Board::expand_builtin_archetypes`](crate::board::Board::expand_builtin_archetypes)
|
||||
/// for an expanded built-in (so identical built-ins share one compiled AST,
|
||||
/// while the source still comes from `builtin_script`). `None` if the object has
|
||||
/// no script.
|
||||
fn script_key(obj: &ObjectDef) -> Option<String> {
|
||||
obj.script_name.clone()
|
||||
}
|
||||
@@ -226,9 +230,10 @@ impl ScriptHost {
|
||||
|
||||
let board = board_cell.borrow();
|
||||
|
||||
// Compile each referenced script once, keyed by `script_key` (pool name for
|
||||
// named scripts, source text for embedded built-ins so identical ones share
|
||||
// one AST).
|
||||
// Compile each referenced script once, keyed by `script_key` (the object's
|
||||
// `script_name`: a world-pool name for named scripts, or a synthetic
|
||||
// `BUILTIN_*` name for built-ins so identical ones share one AST). The
|
||||
// source for a built-in still comes from its embedded `builtin_script`.
|
||||
let mut scripts: HashMap<String, CompiledScript> = HashMap::new();
|
||||
let mut failed: HashSet<String> = HashSet::new();
|
||||
for obj in board.objects.values() {
|
||||
|
||||
@@ -36,7 +36,9 @@ fn pusher_loads_as_a_tagged_scripted_solid_object() {
|
||||
p.builtin_script.is_some(),
|
||||
"carries the embedded pusher script"
|
||||
);
|
||||
assert!(p.script_name.is_none());
|
||||
// Expansion keys all pushers under one synthetic script name so they share a
|
||||
// compiled AST; the source still comes from `builtin_script`.
|
||||
assert_eq!(p.script_name.as_deref(), Some("BUILTIN_pusher"));
|
||||
assert!(!board.is_passable(0, 0), "pusher is solid");
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,9 @@ fn spinner_loads_as_a_tagged_scripted_solid_object() {
|
||||
obj.builtin_script.is_some(),
|
||||
"carries the embedded spinner script"
|
||||
);
|
||||
assert!(obj.script_name.is_none());
|
||||
// Expansion keys all spinners under one synthetic script name so they share a
|
||||
// compiled AST; the source still comes from `builtin_script`.
|
||||
assert_eq!(obj.script_name.as_deref(), Some("BUILTIN_spinner"));
|
||||
assert!(!board.is_passable(0, 0), "spinner is solid");
|
||||
}
|
||||
|
||||
|
||||
@@ -84,17 +84,19 @@ pub enum Solid {
|
||||
}
|
||||
|
||||
impl Solid {
|
||||
/// Whether this occupant is the player.
|
||||
pub fn player(&self) -> bool {
|
||||
matches!(self, Solid::Player)
|
||||
}
|
||||
|
||||
|
||||
/// Whether this occupant is a **grab** thing (a gem-like solid the player
|
||||
/// collects on contact). The player itself is never grabbable; a terrain cell
|
||||
/// reports its archetype's `grab` flag, and an object reports its own.
|
||||
pub fn grab(&self, board: &Board) -> bool {
|
||||
match self {
|
||||
Solid::Player => false,
|
||||
Solid::Cell(arch) => arch.behavior().grab,
|
||||
Solid::Object(id) => {
|
||||
board.objects.get(id).map_or(false, |obj| obj.grab)
|
||||
}
|
||||
Solid::Object(id) => board.objects.get(id).is_some_and(|obj| obj.grab),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user