builtin scripts

This commit is contained in:
2026-06-16 14:34:42 -05:00
parent 7608fc959f
commit 6464e47747
13 changed files with 317 additions and 119 deletions
-47
View File
@@ -199,21 +199,6 @@ impl Board {
(0..self.layers.len()).find(|&z| self.get(z, x, y).1.behavior().solid)
}
/// Returns the coordinates of every [`Archetype::Pusher`] terrain cell on the
/// board (scanning all layers). Used by the pusher heartbeat in
/// [`GameState::tick`](crate::game::GameState::tick).
pub fn pusher_cells(&self) -> Vec<(usize, usize)> {
let mut cells = Vec::new();
for y in 0..self.height {
for x in 0..self.width {
if matches!(self.solid_at(x, y), Some(Solid::Cell(Archetype::Pusher(_)))) {
cells.push((x, y));
}
}
}
cells
}
/// Returns `true` if a mover can enter `(x, y)` — i.e. no solid occupies it.
///
/// Convenience inverse of [`solid_at`](Board::solid_at).
@@ -290,38 +275,6 @@ impl Board {
}
}
/// Advances a [`Archetype::Pusher`] cell at `(x, y)` one step in its facing
/// direction. Reads the direction from the cell itself.
///
/// - If the target is passable: slides the pusher in.
/// - If the target has a pushable chain: pushes it first, then slides in.
/// - If blocked or out of bounds: no-op, returns `false`.
pub(crate) fn advance_pusher(&mut self, x: usize, y: usize) -> bool {
let Some(z) = self.solid_cell_layer(x, y) else {
return false;
};
let Archetype::Pusher(dir) = self.get(z, x, y).1 else {
return false;
};
let (dx, dy): (i32, i32) = dir.into();
let tx = x as i32 + dx;
let ty = y as i32 + dy;
if !self.in_bounds((tx, ty)) {
return false;
}
let (tx, ty) = (tx as usize, ty as usize);
if self.is_passable(tx, ty) {
self.shift_solid(x, y, dx, dy);
true
} else if self.can_push(tx, ty, dir) {
self.push(tx, ty, dir); // clear the chain first
self.shift_solid(x, y, dx, dy);
true
} else {
false
}
}
/// Moves the single solid occupant of `(x, y)` one step by `(dx, dy)`.
///
/// A solid object is relocated (keeping its layer); otherwise the solid