Raiders of the Lost Aisle
It's Christmas Eve. The shop closes at midnight. Somewhere in this department store is the one toy your kid actually asked for, and between you and it stands a security guard who does not care about your family traditions. Raiders of the Lost Aisle is an original isometric adventure for the 48K Spectrum — three connected rooms, a real isometric floor engine in the spirit of Knight Lore and The Great Escape, and a hero who is, very deliberately, just a dad in a fedora.
An isometric floor from sixteen bytes of maths
The genre-defining trick of Knight Lore's "Filmation" engine and its many descendants is projecting a grid of map coordinates onto a diagonal screen grid. Strip it down to its essentials and it's two lines of arithmetic:
; col = ORIGCOL + (u-v)*2 ; row = ORIGROW + (u+v)
project:
ld a,c
sub d
add a,a
add a,ORIGCOL
ld e,a
ld a,c
add a,d
add a,ORIGROW
ld b,a
ld c,e
ret
Every room is a 5×5 grid of tiles; every tile is a solid 2-cell by 1-cell rectangle, coloured in a chequerboard by (u+v) parity — the same visual language Head Over Heels used for its floors. Because everything sits on one flat layer, there's no need for real depth-sorting: floor tiles never overlap each other, and the hero is always drawn last, on top. The only actual sorting problem in the whole game is hero-versus-guard, solved by whichever has the smaller (u+v) drawing first.
The guard, the corridor, and the clock
Room two is a Great Escape homage in miniature: a corridor walled in on every side but one, with a guard oscillating back and forth across the only open lane. Cross while the guard occupies your tile and you're caught — sent back to the room's entry point, ten seconds poorer on a clock that was already running out. The whole game is timed: a store-closing countdown that only stops for victory or for the small mercy of the entry tile itself being safe ground.
Four bugs a screenshot caught that a logic test couldn't
The headless test suite for this game plays a full round trip — boots the title screen, starts a game, navigates to the toy, crosses the guarded corridor, reaches the till, and separately verifies getting caught and running out of time. Every one of those checks passed on the very first build. The game was still broken in four different ways, and none of them were things an assertion could have caught:
- Movement was uncontrollable. The move-gate tested
tick AND 2instead oftick AND 3— a one-character typo that let a held key fire on two frames in every four instead of one, overshooting several tiles per press. A logic test that only checks "did the hero eventually reach the target tile" never notices it got there three times faster than intended; only watching it move gives that away. - Getting caught could spiral. A catch sends the hero back to the room's entry point — but nothing moved the guard away, so if the guard happened to be sitting on that exact tile, the hero was caught again the very next frame, and the next, draining the clock in an uncontrolled loop until the guard's own patrol timer happened to move it off. The fix: the entry tile is now unconditionally safe ground, exempted from the catch check entirely.
- Text fell off the edge of the screen. Three separate strings were printed at a column plus a length that added up to more than 32 — the print routine has no bounds checking, so the overflowing characters wrapped their address calculation into whatever memory came next, corrupting a stray character into a completely wrong position. It rendered as a single misplaced full stop floating at the edge of the title screen, which is a strange enough symptom that it's worth saying plainly: always render the actual screen and look, because a bug like this produces no error, no crash, no failed assertion — just a wrong picture.
- The game-over text was invisible. The attribute byte for "THE STORE HAS CLOSED" set both ink and paper to red. Every pixel of every letter was there, correctly drawn — there was simply no colour contrast left to see any of them by, so the whole message rendered as a single solid red bar.
Once the first two were found by looking, the last two prompted writing a
small static check that scans the source for every print call
and flags any (column + string length > 32) or (ink == paper) before the
game ever gets assembled — catching this exact class of bug at
build time instead of by accident on a screenshot.
Play it, then build your own department store
- raiders.tap — ready to run in Fuse or any .tap-capable emulator. Q A O P move along the two isometric axes, S starts and restarts.
- raiders.asm
— the full commented source, including the projection maths
and the three room tables. Build it yourself:
pasmo --tapbas raiders.asm raiders.tap - test_raiders.py — the headless test suite that played this game to a win, a catch, and a timeout before any of it shipped.
Each room is 25 bytes of tile data and a couple of coordinates. Add a fourth room, redesign the corridor's patrol path, or swap the whole premise — the projection maths doesn't care whether you're escaping a POW camp or a Boxing Day sale.