builtin macro

This commit is contained in:
2026-06-23 01:08:01 -05:00
parent a67f3fa8cf
commit 2e160d6c61
12 changed files with 237 additions and 237 deletions
+17 -18
View File
@@ -6,7 +6,6 @@ use crate::object_def::ObjectDef;
use crate::utils::Direction;
use crate::utils::{Behavior, ObjectId, Player, PortalDef, Pushable, RegistryValue, Solid};
use std::collections::{BTreeMap, HashMap, HashSet};
use crate::builtin_scripts::archetype_script_key;
/// The complete state of one game board (a single room or screen).
///
@@ -499,14 +498,14 @@ impl Board {
/// the normal load path, so this is only needed for the in-memory path. Cells
/// already loaded as objects are untouched, so it is safe to call more than once.
pub fn expand_builtin_archetypes(&mut self) {
use crate::builtin_scripts::{archetype_script, builtin_tag};
use crate::builtin_scripts::builtin_tag;
// Collect first: the loop below mutates both layers and the object map.
let mut found: Vec<(usize, usize, usize, Glyph, Archetype)> = Vec::new();
for z in 0..self.layers.len() {
for y in 0..self.height {
for x in 0..self.width {
let (glyph, arch) = *self.get(z, x, y);
if archetype_script(arch).is_some() {
if matches!(arch, Archetype::Builtin(_, _)) {
found.push((z, x, y, glyph, arch));
}
}
@@ -516,20 +515,25 @@ impl Board {
// Vacate the terrain cell (revealing any floor beneath), then spawn the
// object — mirroring `resolve_entry`'s object template.
*self.get_mut(z, x, y) = (Glyph::transparent(), Archetype::Empty);
let b = arch.behavior();
let Archetype::Builtin(b, _alias) = arch else { continue };
let beh = b.behavior();
let mut obj = ObjectDef::new(x, y);
obj.z = z;
obj.glyph = glyph;
obj.solid = b.solid;
obj.opaque = b.opaque;
obj.solid = beh.solid;
obj.opaque = beh.opaque;
// Carry the archetype's pushability/grab onto the object (pushers and
// spinners are Pushable::No, so they stay unpushable; gems are pushable
// and grabbable).
obj.pushable = b.pushable != crate::utils::Pushable::No;
obj.grab = b.grab;
obj.builtin_script = archetype_script(arch);
obj.script_name = archetype_script_key(arch).map(|s| s.to_owned());
obj.tags.insert(builtin_tag(arch));
obj.pushable = beh.pushable != crate::utils::Pushable::No;
obj.grab = beh.grab;
obj.builtin_script = Some(b.script());
// The compile-cache key and the BUILTIN_* tag are both derived from the
// alias (e.g. "BUILTIN_pusher_east"), so each alias gets its own cached
// AST — a tiny bit less sharing than before, but the source is identical.
let tag = builtin_tag(arch);
obj.script_name = Some(tag.clone());
obj.tags.insert(tag);
self.add_object(obj);
}
}
@@ -614,7 +618,7 @@ impl Board {
#[cfg(test)]
pub(crate) mod tests {
use super::Board;
use crate::archetype::{Archetype, SpinDirection};
use crate::archetype::{Archetype, Builtin};
use crate::glyph::Glyph;
use crate::layer::Layer;
use crate::object_def::ObjectDef;
@@ -963,12 +967,7 @@ pub(crate) mod tests {
#[test]
fn expand_builtin_archetypes_replaces_a_spinner_cell_with_an_object() {
let mut board = open_board(3, 1, (2, 0), vec![]);
stamp(
&mut board,
0,
0,
Archetype::Spinner(SpinDirection::Clockwise),
);
stamp(&mut board, 0, 0, Archetype::Builtin(Builtin::Spinner, "spinner_cw"));
board.expand_builtin_archetypes();
// The terrain cell is vacated and a scripted object takes its place.