Act V and Let Go
Act V is levels 18 to 22. Each act V level combines three earlier ideas and adds a time budget or the cap of two echoes. Five levels were planned. One was never built, and two more changed shape once the simulation measured them.
Five levels
Clockwork is about sharing one memory. Two ghosts can be cast from the same 3 seconds, and one ghost can press two plates in turn. In the first room you cast standing on plate a, run to plate b, and cast again as you arrive.

Hall of Mirrors is about where a reflection stands. It stands where you stood, even if that spot is over spikes on the other side of the shrine, and two shrines reflect one stand twice. Both of its rooms use plates two cells wide, because that gives the stand a 40 px window instead of 24.

Three Steps Behind is about the quarter-second press. A running ghost presses each plate for about 14 frames, 3 seconds after you did, and if you paused on a plate the ghost holds it for as long as the pause. The first room is the one place in act V where --cheese hits, and every hit is the intended move.
Let Go replaced a planned level called Scaffold. The next sections are about why.
The Last Light is the finale, four rooms across 101 tiles. It brings back the ferry with a toll gate, both of Hall of Mirrors’ rooms, and a last room where one memory makes two ghosts. One holds a door, and the other is the ferry.

Ideas that died in the simulation
The plan for act V had three ideas the simulation disproved.
A reflection of a ride is a ride. The plan for Hall of Mirrors was to reflect a ferry so it carried you somewhere new. A mirrored ghost replays its memory in time order, so the ride part runs from the far mirror point back toward the shrine. Its last pose is always within a tile of the shrine, because you had to touch the shrine to cast. Level 10’s ferry only goes outward because the walk away is recorded before the walk back. Hall of Mirrors kept two rooms instead of three.
Clockwork’s cap trick. The third room was going to force sharing with the echo cap, where a third cast drops the oldest ghost. Measured, the cap never forces anything there. A ghost that presses a and then b holds a only during its first second, so by the time a third cast could drop it, its door is already behind you. The built room forces sharing with a third plate that needs a standing ghost at the end.
Scaffold. This level was going to climb a wall on a staircase of ghosts. You jump, cast low enough to land on the step it leaves, stand on that step, and cast the next one from its back. The plan estimated a window of about 60 frames for each of those casts. It measured 12. Step k+1 arrives 3 seconds after its cast, step k fades 4 seconds after it arrived, and a player needs about half a second to land and 0.3 seconds to be airborne again. A wider window is possible right after a respawn, when the short memory makes the first replay arrive early. That gives two rungs, and two rungs is the two-cast ladder that --cheese already counts as a shortcut. No room could pass both the slack rule and the shortcut rule, so Scaffold wasn’t built.
Let Go
Three ideas were tried for the empty slot before one was built:
- The echo cap as a tool. A third cast removes the oldest ghost, so a cast can shut a door. This one was picked.
- The fresh memory after a respawn as a delay you can tune. Rejected, because the intended move is the single swept cast that
--cheesealready plays. - A rider dropped on a shelf by a replayed jump. Rejected by arithmetic. The rider’s feet top out at 62.8 px against a 64 px shelf, and the window was about 24 frames.
The cap had been in the game since the first build, as a limit. It’s two lines in World:cast, and the removal happens before the new ghost exists:
if #self.echoes >= Echo.MAX then table.remove(self.echoes, 1) end
local mirror = self:touchedMirror()
if mirror then Echo.mirror(snap, mirror.tx * T + T / 2) end
self.echoes[#self.echoes + 1] = Echo.new(snap, mirror ~= nil)
Let Go turns that limit into the puzzle. Sometimes you want a ghost gone. Door A in each room is two things at once. It’s a one-tile gate standing on crumble over spikes, and past one more crumble tile, a floor five tiles long over more spikes. While a ghost holds plate a, the gate is open and so is the floor. To cross, you need the gate open as you step into it and the floor shut after.
The trick that makes it work is a rule every door already had. A door also stays open while you stand in it, so it can’t close on you:
local open = pressedBy[id] or false
if not open and player then
for _, c in ipairs(cells) do
if touchesCell(player, c) then open = true break end
end
end
That check is per letter, so your body in the gate keeps every cell of door A open, the floor too. You stand in the doorway and cast until the third ghost takes the one on a with it. Then you step forward onto the crumble tile past the gate. Your body has left door A, so the gate shuts behind you and the floor ahead turns solid. The stone under the doorway cracks, so you can’t wait there for the ghost to fade instead.

The three rooms follow teach, test and twist. In Let Go you cast once on a and twice in the doorway. In Oldest First a second plate, b, holds the exit door, and the cast in the doorway takes the oldest ghost. So the cast on a has to come before the one on b, or the kill takes the keeper. In Borrowed Time the two casts in the doorway replay a pause on plate c three seconds later. That pause has to last between 0.7 and 2.8 seconds.
Nine naive approaches have to fail in the first room alone, among them no ghost, one cast in the doorway, waiting in the doorway for the fade, mashing, and jumping the open floor. Its narrowest decision is 42 px. One weak spot stays open. A blind route that waits at the gate’s edge for the ghost on a to fade and then walks straight through has a 24-frame window in every room, under the 30-frame bar. Rooms 2 and 3 also keep their gate and exit door 21 and 23 tiles from the waystone, past the first screen, though the plates that carry each room’s idea are on it.
One letter, several doors
Let Go’s door A is a gate and a floor at once because both are marked with the letter A. Every act V level, and levels 11 and 13 before them, uses one letter in separate places like that. The renderer drew each letter as a single slab over the bounding box of all its cells. So a door in two places showed one slab covering the floors and corridors between its pieces, and an upright door showed only in its first piece’s column.
The fix splits each letter into its 4-connected runs of cells, once per world, and draws and lights each run as its own door:
-- A letter can mark several separate doors that share a plate. Each 4-connected run of its cells is one piece,
-- listed in map order so every run draws them in the same order.
local function doorPieces(world)
The “same order” part fixed a second, quieter bug. The old loop walked the doors with pairs(), and LuaJIT seeds its string hashing per process, so overlapping slabs and door glows came out in a different order from one launch to the next.
What building act V taught
Building act V left five rules for whoever builds the next level:
- A crumble bridge two or more tiles long in front of a door stops the quarter-second press. A player who waits at the door for it falls.
- The memory after a respawn is empty. A naive approach that relies on an early ghost has to be proven to fail from a fresh respawn too.
- Plates sit one tile clear of crumble and shrines, because stopping on a plate overshoots it by 5 px.
- Two-cell plates widen a reflected stand’s window from 24 px to 40.
- Landing a jump on a single ghost is a 20 px window, which fails the slack rule. Board ghosts by stepping off ledges, the way the ferry does.
22 levels

Every room in levels 18 to 22 has a solve and a list of naives, and every strategy’s decisions get at least 30 frames or 24 px. Death, R and Restart level all go through the real scenes. --cheese finds no shallow strategy in any room of levels 18, 19, 21 and 22, nor in rooms 2 and 3 of Three Steps Behind. Its only hits are in that level’s first room, where they’re the intended move.