redoing bump

This commit is contained in:
2026-07-08 13:21:27 -05:00
parent f407b5d9a6
commit e545395ac6
12 changed files with 243 additions and 90 deletions
+40 -24
View File
@@ -8,8 +8,9 @@
//
// The direction is not baked into this source: every transporter shares one
// compiled copy and reads its `BUILTIN_transporter_<dir>` tag. The world is
// reached through the global `Board`/`Player` constants; `teleport(id, x, y)`
// moves an arbitrary entity (`-1` is the player).
// reached through the global `Board`/`Player` constants. The bumper is moved by
// coordinate via `shift([[from], [to]])`, which relocates whatever solid sits at
// the entrance — player, object, or a pushed crate — onto the empty destination.
// This transporter's facing unit vector, from its direction tag.
fn facing(me) {
@@ -27,6 +28,16 @@ fn opposite_tag(me) {
else { "BUILTIN_transporter_east" }
}
// The direction a front bump arrives from — the side opposite our facing (a
// north-facing transporter is entered from the south, etc.). `bump` reacts only
// when the reported direction matches this.
fn entrance_dir(me) {
if me.has_tag("BUILTIN_transporter_north") { South }
else if me.has_tag("BUILTIN_transporter_south") { North }
else if me.has_tag("BUILTIN_transporter_east") { West }
else { East }
}
// The 4-frame animation loop for this direction (CP437 tile codes).
fn frames(me) {
if me.has_tag("BUILTIN_transporter_north") { [94, 45, 94, 126] } // ^ - ^ ~
@@ -47,38 +58,41 @@ fn tick(me, dt) {
me.delay(0.15);
}
fn bump(me, id) {
// Move whatever solid sits at (sx, sy) onto the empty cell (tx, ty) immediately.
// A two-cell `shift` relocates the source solid — player, object, or crate — and
// leaves its old cell empty (the destination is checked empty by the caller). Kept
// as a helper so the nested-array literal stays at a shallow expression depth.
fn transport(sx, sy, tx, ty) {
shift([[sx, sy], [tx, ty]]); now();
}
fn bump(me, dir) {
// Only transport things that hit us from the front — the entrance side. `dir`
// is the direction the bump came from; a bump from any other side does nothing.
if dir != entrance_dir(me) { return; }
let d = facing(me);
let dx = d[0];
let dy = d[1];
// Only transport things that hit us from the front — the entrance cell at
// (me - d). A bump from any other side does nothing.
let bx;
let by;
if id == -1 {
bx = Player.x;
by = Player.y;
} else {
let o = Board.get(id);
if o == () { return; }
bx = o.x;
by = o.y;
}
if bx != me.x - dx || by != me.y - dy { return; }
// Whatever solid is pressed against our entrance cell (me - d) gets moved:
// the player, another object, or a pushed crate — all handled uniformly by
// shifting the solid at that coordinate onto an empty destination.
let ex = me.x - dx;
let ey = me.y - dy;
// 1. The cell just past us (the opposite side): if nothing solid is there,
// drop the bumper onto it.
let fx = me.x + dx;
let fy = me.y + dy;
if Board.passable(fx, fy) {
teleport(id, fx, fy); now();
transport(ex, ey, fx, fy);
return;
}
// 2. Otherwise scan along our axis for the nearest opposite-facing transporter
// whose entrance (the cell just before it) is free, and drop the bumper
// there. A blocked pair is skipped; give up at the board edge.
// whose far side (the cell just past it) is free, and drop the bumper there.
// A blocked pair is skipped; give up at the board edge.
let opp = Board.tagged(opposite_tag(me));
let cx = fx;
let cy = fy;
@@ -94,10 +108,12 @@ fn bump(me, id) {
if o.x == cx && o.y == cy { here = true; }
}
if here {
let ex = cx + dx;
let ey = cy + dy;
if Board.passable(ex, ey) {
teleport(id, ex, ey); now();
// Emerge on the paired transporter's far side — the cell just past it
// along our scan (cx + d), out its back.
let tx = cx + dx;
let ty = cy + dy;
if Board.passable(tx, ty) {
transport(ex, ey, tx, ty);
return;
}
}