transporters

This commit is contained in:
2026-07-08 10:06:25 -05:00
parent e43dae54a8
commit f407b5d9a6
14 changed files with 323 additions and 34 deletions
+45 -13
View File
@@ -282,24 +282,56 @@ impl GameState {
choice: None,
});
}
Action::Teleport { x, y } => {
Action::Teleport { target, x, y } => {
if !board.in_bounds((x, y)) {
logs.push(LogLine::error(format!("teleport({x},{y}): out of bounds")));
} else {
logs.push(LogLine::error(format!(
"teleport({target},{x},{y}): out of bounds"
)));
} else if target == -1 {
// Move the player. A solid *other than the player itself*
// blocks the destination.
let (ux, uy) = (x as usize, y as usize);
let source_solid = board
.objects
.get(&ba.source)
.map(|o| o.solid)
.unwrap_or(false);
if source_solid && board.solid_at(ux, uy).is_some() {
let blocked = matches!(
board.solid_at(ux, uy),
Some(s) if !s.player()
);
if blocked {
logs.push(LogLine::error(format!(
"teleport({x},{y}): destination is solid"
"teleport(player,{x},{y}): destination is solid"
)));
} else if let Some(obj) = board.objects.get_mut(&ba.source) {
obj.x = ux;
obj.y = uy;
} else {
board.player.x = ux as i64;
board.player.y = uy as i64;
}
} else if let Ok(tid) = ObjectId::try_from(target) {
// Move object `tid` to (x, y). A solid destination blocks
// a solid mover, unless the occupant is that same object.
let (ux, uy) = (x as usize, y as usize);
match board.objects.get(&tid) {
None => logs.push(LogLine::error(format!(
"teleport({target},{x},{y}): no such object"
))),
Some(obj) => {
let source_solid = obj.solid;
let blocked = source_solid
&& matches!(
board.solid_at(ux, uy),
Some(s) if s.object_id() != Some(tid)
);
if blocked {
logs.push(LogLine::error(format!(
"teleport({target},{x},{y}): destination is solid"
)));
} else if let Some(obj) = board.objects.get_mut(&tid) {
obj.x = ux;
obj.y = uy;
}
}
}
} else {
logs.push(LogLine::error(format!(
"teleport({target},{x},{y}): invalid target id"
)));
}
}
// push() self-checks can_push, so an in-bounds guard is all we add.