Started this one as a "what would Atari's Adventure look like in 2026?" question and ended up with two playable versions, random worlds, and a leaderboard living on this site.
Two versions
Both are single HTML files, drawn entirely in code on a canvas, no image files and no build step.
- Top-down is the faithful remake: the same castles, keys, dragons, bat and chasm, with modern lighting and sound.
- Isometric is a separate version with proper walls, shadows, torchlight and trees that fade out when you walk behind them.
Bugs worth remembering
The isometric version crashed on start. The cause was a variable name collision: the chasm's rectangle was called CH, the same name as the canvas height, so the canvas never cleared. My first headless test used a stub canvas and missed it. Running the game against a real canvas in Node found it right away. Stub canvases lie.
It also felt awkward to walk around, because "up" on screen is a diagonal in an isometric grid. The fix was a grid-aligned control mode as the default, with a toggle for the screen-relative one.
Random worlds that can always be finished
Every game now shuffles the items, the dragons and the obstacles in each room. The part I cared about was making sure a random world can still be won. Each layout goes through a solver that checks the keys, the bridge, the sword and the magnet can all be reached in some order, plus a walkability check that every item and dragon sits somewhere the player can actually get to. If a layout fails, it tries again.
I ran 3,000 seeds through generation with no failures, and an independent walkability check over 600 of them. What I did not do is have a bot play through to the end, so "checked" is not the same as "proven".
The solver also exposed a soft-lock: get eaten on the far shore while carrying the bridge and the bridge is stranded there. The bridge now goes back to the gorge.
A daily world and a three-letter top 10
The isometric game has a daily world. Everyone gets the same layout that day, seeded from the UTC date, and fast runs reach that day's top 10. The top-down game has a single all-time board, since its world never changes.
You enter three letters, which keeps names short and bad words out, with a blocklist on the server as a backstop. Scores are stored as one small JSON file per board in Vercel Blob. A file inside a deployment is read-only, so writing scores to the repo was never an option.
Two honest limits: the game runs in the browser, so a determined person could still send a fake time, and the server only rejects anything under 45 seconds, which is a guess I'll tune once there are real scores.
Shipping it safely
hackerlabs.dev is a live site, so none of this went straight to main. The flow was a branch, a pull request, a Vercel preview, a test score written through the console to prove the store worked, and then a merge. Two things tripped me up: a newly connected Blob store only reaches builds made after it's connected, so the preview needed a redeploy, and the files I added had to land in public/adventure/ and app/api/scores/ without touching anything already there.
What's next
- Touch controls for phones
- The daily world in the top-down version
- A hard mode with limited lives
