Live: https://monsterrobot.games/games/policesquadquest/ web/index.html is our arcade page shell, matching the house style set by morpquest (boot splash, gold README tab, controls and the shelf explained). tools/webbuild.sh copies it over the engine's default after baking, so the cases/ shelf directory stays nothing but games. Hosting, established by reading the boxes rather than the docs: the deploy-map note pointing at /opt/dealgod/images/engine/ on the dealgod VPS is stale for this domain — that path now falls through to the arcade index. monsterrobot.games is actually served by forum-nginx on the GAMES VPS (humanjing@100.71.119.27) from a bind mount of /home/humanjing/monsterrobot.games, and games are plain directories under games/ picked up by try_files with no nginx change at all. Deployed exactly like /games/morpquest/, which is the same engine. Verified live: all four assets 200 with correct application/wasm content-type, our title (not the arcade fallback), the shelf renders, a case loads and plays, and the parser round-trips over the wire. Nothing existing was touched — fresh directory, no config edited, no cache purge needed for a new path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|---|---|---|
| cases | ||
| tests/scripts | ||
| tools | ||
| web | ||
| .gitignore | ||
| DESIGN.md | ||
| play.sh | ||
| README.md | ||
| RESEARCH.md | ||
Police Squad Quest
A Sierra-style adventure game set in the Police Squad! / Naked Gun universe,
built on the MRPGI engine (~/Documents/MRPGI) — which is
itself a reimplementation of AGI, the engine Sierra shipped Police Quest on.
The game grades you on correct police procedure with a completely straight face. The reward for perfect procedure is catastrophe anyway.
- RESEARCH.md — the source material: all six Police Squad! episodes, all four films, the recurring cast, and the ZAZ comedy grammar.
- DESIGN.md — the game bible: the joke engine, the two Drebins, the eleven-case campaign, and how it all maps onto MRPGI data.
Sixteen cases, all playable, all verified end-to-end at 100/100 (Case One is
95 + 5 optional). python3 tools/lint.py checks all thirteen clean.
Play
./play.sh
That opens the engine's title screen — the whole campaign on one shelf,
arrow keys to choose, Enter to play, Esc backs out of a case to the shelf.
./play.sh 07 still jumps straight to one case. The shelf's big title comes
from cases/collection.json.
Or directly:
cargo run -p mrpgi --manifest-path ~/Documents/MRPGI/Cargo.toml -- --game cases/case-01-substantial-gift
Tab switches between play and the room editor. Type help in play.
What's here
cases/case-00-1958/ |
Act Zero — playable, 100 points. Frank Drebin Sr, 1958, hard noir mono. Five rooms. Played completely straight; the score is the cover-up. |
cases/case-00b-the-quartet/ |
Act Zero crossover — playable, 100 points. Drebin Sr vs. five Ealing-comedy incompetents. Five rooms. |
cases/case-00c-the-liaison/ |
Act Zero crossover — playable, 100 points. 1965: the spy-spoof era arrives hunting a pattern that is Drebin Sr. Five rooms. |
cases/case-01-substantial-gift/ |
Case One — playable, 100 points. Drebin (Nielsen), 1982, monochrome. Five rooms. |
cases/case-03-big-gulch/ |
Case Three — playable, 100 points. Four rooms, the locksmith front. |
cases/case-04-revenge-remorse/ |
Case Four — playable, 100 points. Four rooms, the wrong manual. |
cases/case-05-butler-did-it/ |
Case Five — playable, 100 points. Four rooms, chain of custody on a cake. |
cases/case-06-testimony-of-evil/ |
Case Six — playable, 100 points. Drebin (Nielsen), 1982, monochrome. Five rooms, the whiskey exploit, four deaths. |
cases/case-07-from-the-files/ |
Case Seven — playable, 100 points. Drebin (Nielsen), 1988, full colour. Six rooms, the Anaheim Stadium finale. |
cases/case-02-ring-of-fear/ |
Case Two — playable, 100 points. Drebin (Nielsen), 1982, monochrome. Five rooms, undercover, three deaths. |
cases/case-08b-the-heron/ |
Case 8½ — playable, 100 points. Interpol team-up: Drebin and a Sûreté legend chase a gentleman jewel thief to London. Five rooms. |
cases/case-09-final-insult/ |
Case Nine — playable, 100 points. Four rooms, prison undercover and the envelope. |
cases/case-10-plot-device/ |
Case Ten — playable, 100 points. Drebin Jr (Neeson), 2025, cold palette. Six rooms, the arena finale and the owl. |
cases/case-08-smell-of-fear/ |
Case Eight — playable, 100 points. Drebin (Nielsen), 1991, full colour. Five rooms, the memory test. |
cases/case-11-what-he-wrote/ |
Case Eleven — playable, 100 points. Drebin Jr reads his grandfather's files. Five rooms; the palette drifts from 2025 back to 1958. |
cases/case-12-the-late-movie/ |
Case Twelve — playable, 100 points. The finale: all three Drebins pulled into a demonic cable multiverse. Seven channels. |
tools/sprites.py |
Generates every sprite on the MODELBEAST farm (free, local). |
tools/lint.py |
Checks every case for the authoring traps that have bitten us. Run it before playtesting. |
tools/verify.sh |
Replays every case's win path headlessly and checks it reaches max_score. Scripts in tests/scripts/. |
RESEARCH.md / DESIGN.md |
Source research and the campaign bible. |
Case One — A Substantial Gift
Police Squad! episode 1. A credit union manager is dead, the wrong man is in a cell, and the teller has new braces.
Sign out your badge and sidearm (the door will not let you leave without them), get briefed, tip Johnny, dust the counter, match the print, find the bill, and Mirandize the suspect in the correct order. Get the order wrong and the statement is suppressed, which is a Sierra death card, which is the joke.
Case Seven — From the Files
The Naked Gun (1988). Nordberg is shot on Ludwig's freighter, you tackle a head of state at a state reception, and you get fired — which is the only way forward, because a private citizen can't walk onto a baseball field but an umpire can walk anywhere.
The climax: you are the home plate umpire at Anaheim Stadium with no power to search anyone, so every frisk needs an umpire-legitimate pretext — brush the plate, inspect the mitt, check the bat for pine tar — until you reach Number 44. Announce yourself as police instead and sixty thousand people come over the railings.
Case Ten — The P.L.O.T. Device
The Naked Gun (2025). Liam Neeson's Frank Drebin Jr. — played sincere where his father was oblivious. He means everything he says, all the time, and that is both the joke and, eventually, the thing that saves the city.
Bank cold open (you are the distraction and don't know it) → a suicide that isn't → Richard Cane → a New Year's ball drop, a pair of lost trousers, and a barn owl in a 1950s hat who is lit by a different decade than everything around him.
Play it online
monsterrobot.games/games/policesquadquest/
Web build
The whole campaign bakes into a single self-contained wasm — title screen, all sixteen cases, ~2.1 MB:
./tools/webbuild.sh
Output lands in MRPGI/web/dist/ (wasm + our page shell from
web/index.html + the macroquad JS shim). The shelf's title
comes from cases/collection.json.
Deploy — monsterrobot.games is served by forum-nginx on the games VPS
(humanjing@100.71.119.27) from a bind mount of
/home/humanjing/monsterrobot.games. Games are plain directories under
games/; the server block's try_files $uri $uri/ /index.html picks them up
with no nginx change. Same pattern as /games/morpquest/:
./tools/webbuild.sh
rsync -az --delete ~/Documents/MRPGI/web/dist/ \
humanjing@100.71.119.27:/home/humanjing/monsterrobot.games/games/policesquadquest/
Then curl the live URL cache-busted to confirm. Note the deploy-map's older
note about /opt/dealgod/images/engine/ on the dealgod VPS is stale for this
domain — that path no longer serves monsterrobot.games.
Regenerating art
Sprites are generated locally on MODELBEAST (flux_local → bg_remove_local →
downscale). Prompts live in each case's sprites.json.
python3 tools/sprites.py cases/case-01-substantial-gift # fill gaps
python3 tools/sprites.py cases/case-01-substantial-gift --force # redo all
MB_POOL=1 python3 tools/sprites.py cases/... # if the farm 401s
Seeds derive from the sprite name, so reruns reproduce the same art.
Engine changes
Two small, general-purpose additions were made upstream in MRPGI for this project — both benefit any game:
sprites/ego.pngin a game folder replaces the default party robot as the player avatar (ego1.pngoptional second walk cel).death_textingame.jsonoverrides the death banner, which was previously hardcoded to another game's flavour text.