# Police Squad Quest — design bible A Sierra-style adventure game in the *Police Squad!* / *Naked Gun* universe, built on [MRPGI](../MRPGI). Source research: [RESEARCH.md](RESEARCH.md). --- ## 1. The joke engine The premise isn't "a funny adventure game". It's a specific collision: > **Sierra's *Police Quest* (1987) × ZAZ's *Police Squad!* (1982).** *Police Quest* was designed by Jim Walls, a real ex-cop, and was famously **pedantic**: you had to walk around your car and check the tyres, radio in correctly, draw your weapon *before* firing (or you shot yourself in the leg), and read the Miranda rights in the right order. Get the procedure wrong → you die. It is the single most self-serious game Sierra ever shipped. *Police Squad!* is the same subject matter played as total farce. **So the game grades you on procedure with a completely straight face, and the reward for perfect procedure is catastrophe anyway.** That's the machine. It's mechanical, not just written — the player *performs* the joke rather than watching it. Three rules fall out of that: 1. **The game never winks.** All system text is flat police-procedural prose. Score readouts, death cards, refusals — deadpan. The comedy is what the flat text is describing. (See RESEARCH.md §4.) 2. **Correct procedure is mandatory and useless.** You *must* do it. It never helps. 3. **The parser is Frank's brain.** A text parser is a literal-minded machine, and literalism is ZAZ's core joke. `look` answers take things at face value. ### Worked example — the opening of Case One ``` > take badge Taken. (+2) > east You have not signed for a sidearm. Regulations are regulations. > take revolver Taken. (+2) > east ``` Two points for procedure. Then you get to the crime scene and the body is gone because Nordberg filed it. --- ## 2. The two Drebins, and the three eras John's instinct that Frank Drebin Sr should be "a 1950s style cop" is exactly right, and it's supported by the source: *Police Squad!* was a straight parody of ***M Squad*** (1957–60) and *Felony Squad*. The 2025 film then makes Neeson's Frank Drebin **Jr.** canon — and gives Sr. a supernatural cameo as an owl. A two-Drebin game is the franchise's own structure, not a liberty. | Act | Who | Look | Palette | |-----|-----|------|---------| | **I** | Frank Drebin **Sr** — the TV series | 1950s hardboiled cop show, shot on videotape | EGA **0 / 7 / 8 / 15** + brown ego. Monochrome. | | **II** | Frank Drebin **Sr** — the films | 1988–94 blockbuster | Full 16-colour EGA | | **III** | Frank Drebin **Jr** (Neeson) — 2025 | modern LA, tech-money | Full EGA, cold blues/cyans | **The palette restriction is free and does all the work.** MRPGI is EGA anyway; Act I simply doesn't use the other twelve colours, so the era switch is visible the instant a case loads. Act III's owl is the transition device: Sr. shows up to help Jr., which is canon and also lets both Drebins share a screen. **Drebin Jr's homage** (John's specific ask): Neeson's register is *sincerity* where Nielsen's was obliviousness. Jr. isn't stupid — he's earnest, gravel-voiced, and completely committed to a plan that makes no sense. Write Jr's `look` text as genuinely moving. Then have it be about a vending machine. --- ## 3. Structure — one folder per case MRPGI loads any directory with `--game DIR`, so **each mission is a standalone game folder** under `cases/`. No global room numbering, no hub-state plumbing, cases can be built in any order and in parallel. ``` cases/case-01-substantial-gift/ game.json manifest: name, start_room, intro, extra verbs, flags, max_score sprites.json MODELBEAST prompts (input to tools/sprites.py — not read by the engine) sprites/*.png generated art; ego.png is the player rooms/room*.json the case ``` `./play.sh` lists cases and runs one. Skipped: a hub world and cross-case save — add when there are enough cases to want them. --- ## 4. Mechanics — all of it is pure JSON MRPGI already has every field this design needs. **No engine work.** | Want | Field | Use | |------|-------|-----| | Procedure gate on a doorway | `exit_flags` + `exit_blocked` | "You have not signed for a sidearm." | | Sierra death | `kills` on object or dialogue choice | The `use_text` is the death card | | Police Quest scoring | `points` + manifest `max_score` | Points for *procedure*, not progress | | Evidence that appears once found | `visible_flag` | Dusting reveals the print | | Things that vanish | `hidden_by_flag` | The body Nordberg files | | Item locks | `needs`, `consumes` | Warrant, evidence bag | | Interrogation | `dialogue` + `requires_flag` / `sets_flag` | Miranda rights in order | Two small engine changes were made upstream in MRPGI, both general-purpose and useful to any game: a folder can supply **`sprites/ego.png`** to replace the default party robot (plus optional `ego1.png` for the walk bob), and **`death_text`** in `game.json` overrides the death banner, which was previously hardcoded to another game's flavour text. Nothing else was added — every mechanic below already existed. ### Custom verbs `game.json` merges extra synonyms into the verb table, and the AI-parser whitelist is generated from the same table so they can't drift: ```json "verbs": [ { "name": "use", "words": ["dust", "cuff", "book", "frisk", "radio", "mirandize", "arrest"] }, { "name": "look", "words": ["investigate", "detect"] }, { "name": "talk", "words": ["interrogate", "question"] } ] ``` --- ## 5. The campaign ### Act I — Frank Drebin Sr, *Police Squad!* (monochrome) Six cases, one per episode. Each opens with a **special guest star being murdered in the title card** — a real object in the room whose only purpose is to die. | # | Case | From | Hook | Procedure gag | |---|------|------|------|---------------| | 01 | **A Substantial Gift** | Ep 1 | Credit union manager shot; teller Sally Decker did it for orthodontist money and framed a customer | Sign out badge + sidearm; dust for prints; Mirandize in order — **built, see §6** | | 02 | **Ring of Fear** | Ep 2 | Undercover as a boxing manager; a fighter's wife kidnapped to force a dive | You must maintain your cover identity *and* file correct overtime paperwork | | 03 | **Rendezvous at Big Gulch** | Ep 3 | Protection racket; Frank and Norberg run a **locksmith shop** as a front | The front business is graded on customer service. Real locks. Real customers. | | 04 | **Revenge and Remorse** | Ep 4 | Courthouse bombing, Eddie Casales framed | Bomb disposal by the manual, in order. The manual is wrong. | | 05 | **The Butler Did It** | Ep 5 | Kidnapping at a rich man's birthday party | Chain of custody on a birthday cake | | 06 | **Testimony of Evil** | Ep 6 | Comedian dies; nightclub drug ring | Undercover as a stand-up. You must actually pick punchlines. Dying on stage = a Sierra death card. | ### Act II — Frank Drebin Sr, the films (full colour) | # | Case | From | Hook | |---|------|------|------| | 07 | **From the Files** | *Naked Gun* (1988) | **BUILT — see §7.** Nordberg shot on Ludwig's freighter; the Queen's reception; then Anaheim Stadium, where you **umpire a baseball game in order to legally frisk the players**. | | 08 | **The Smell of Fear** | *Naked Gun 2½* (1991) | Spot the fake Dr. Meinheimer by testing a photographic memory the double doesn't have. Includes the zoo, the SWAT tank, and disarming a nuclear device — solution: unplug it. | | 09 | **The Final Insult** | *33⅓* (1994) | Retired Frank goes undercover in prison as "Nick the Slasher McGurk". Bomb in the Best Picture envelope. Marriage counselling is a live stat you must not tank. | ### Act III — Frank Drebin Jr, 2025 (full colour, cold palette) | # | Case | From | Hook | |---|------|------|------| | 10 | **The P.L.O.T. Device** | *Naked Gun* (2025) | Open in the schoolgirl disguise during the bank robbery — you're the distraction and don't know it. Investigate Simon Davenport's "suicide" with Beth. Richard Cane's bunker plan. Police Squad is decommissioned mid-game and your badge stops opening doors. | | 11 | **Ponzi-scheme.com Arena** | *Naked Gun* (2025) finale | New Year's ball drop. You lose your trousers retrieving the device — and the game keeps scoring you on uniform regulations. **Frank Drebin Sr arrives as an owl**: Act I's monochrome palette flies into Act III's colour one. | ### The prologue — "1958" A short unlockable Act 0: **Drebin Sr as a rookie**, played completely straight as *M Squad*. Same monochrome palette, no jokes in the system text at all — until the last screen. It's the origin of the owl. --- ## 6. Case One — as built **`cases/case-01-substantial-gift/`** — the vertical slice, playable now. Five rooms, 100 points. | Room | Place | Contains | |------|-------|----------| | 0 | Police Squad HQ, squad room | Hocken (briefing), Nordberg (injured), **Al** (74px — his head leaves the top of the screen and no one comments), your desk, badge, sidearm, case file | | 1 | The street | Johnny the Snitch's shoeshine stand, the squad car | | 2 | The credit union | The body, the vault, the teller counter, **Sally Decker** | | 3 | The crime lab | Ted Olson and the microscope | | 4 | The orthodontist's | The dental chair, the braces cast, the arrest | **The chain:** sign out badge + revolver (procedure gate on the HQ exit) → read the case file → crime scene → dust the counter for prints → take the evidence bag → lab: Olson matches the print → the orthodontist's bill names Sally → return and Mirandize her **in the correct order** (wrong order = she walks and you get a Sierra death card from Hocken, which is not a real death, which is the joke) → arrest. **Running gags wired in as mechanics:** - **Al** — a 74px sprite in a 168px room. Placed so his head is above the frame. His `look` text describes only his shoes. - **Johnny** — `talk johnny` costs a dollar and will answer *anything*. His dialogue tree has more nodes about orthodontics and macroeconomics than the case. - **Nordberg** — appears in every room in worse condition. Never mentioned. - **The guest star** — dies in the title card. `look guest` in room 0 before he dies, and he's already dead. - **The freeze-frame ending** — the win text describes the cast holding still while things audibly keep going wrong. --- ## 7. Case Seven — the umpire problem **`cases/case-07-from-the-files/`** — Act II, full-colour EGA. Six rooms, 100 points. Hospital → Ludwig Shipping → the Queen's reception → the officials' room → home plate → the upper deck. **The central mechanic: the strike zone is the puzzle.** Drebin has been fired, so he has no power to search anyone. But a home plate umpire can crouch six inches from a professional athlete, take his bat off him, and inspect his equipment — and nobody in a stadium of sixty thousand thinks twice, because that is simply what umpires do. **So every frisk needs an umpire-legitimate pretext, in order:** 1. `use homeplate` — brush the plate. The only reason a masked man on his knees beside an athlete is acceptable. Sets `at_plate`. 2. `use catcher` — inspect the mitt for a foreign substance. Clean. 3. `use batter` — check the bat for pine tar above the legal limit. Clean. 4. `use slugger` — Number 44, who has been staring at the owner's box since the second inning. A pager taped inside the batting glove. Skip the pretext and the object simply refuses (`requires_flag`). Announce yourself as police — a dialogue choice that is right there, and correct, and what a police officer would do — and sixty thousand people come over the railings. Sierra death. **The other inversion:** at the Queen's reception, Ludwig hands a two-hundred- year-old firearm to the person you are there to protect, and you tackle a head of state. That is *correct procedure*, it ends your career, and **being fired is the only way to progress** — a private citizen can't walk onto that field, but an umpire can walk anywhere. Also in: Nordberg conducting an entire briefing through a wired jaw; Ludwig owning two hundred and six ships and one of them being called I LUV LUDWIG; the anthem lyric sheet; the steamroller, established in Room 5 as scenery an hour before it is needed. **Two authoring traps this case caught, worth knowing before writing Case 08:** - **Object names must not be prefixes of each other.** `ludwigdesk` shadowed `ludwig`, so `talk ludwig` addressed the furniture. The parser matches loosely; renaming it to `desk` fixed it. - **Flag-gated edge exits need walkable floor into the trigger zone.** The north exit fires at `y ≤ 21`, which was inside the painted stands (a `Wall` band) — the upper deck was unreachable on foot until a tunnel was carved through it. Verify every exit by *walking* it, not with `goto_room`. --- ## 8. The glitches are canon *Police Quest II* shipped with bugs that are, without alteration, Naked Gun jokes. A player who has never heard of Sierra reads them as Drebin being Drebin; a player who has reads them as a love letter. **So we ship them deliberately.** | Real PQ2 bug | In Police Squad Quest | |---|---| | Keys locked in the car, station doors lock behind you → **softlocked in the parking lot on screen one** | The squad car in Case One: *"The keys are locked inside, on the seat, in plain view, behind your own reflection."* Non-fatal. Nobody mentions it. | | **Keith**, your partner, slacks off and smokes; driving back to the station makes him go do "paperwork" | **Nordberg.** Casts, traction, cigarette, assigned as your partner, has not stood up. His paperwork is a magazine. | | Firing without raising the weapon → **you shoot yourself in the foot** | Hocken dialogue: *"Permission to test-fire my sidearm indoors, Captain."* → *"Granted."* → Sierra death. An optional trap, exactly as Sierra used it. | | Holding a direction while drawing → **hands and gun detach and float above your head** | Act II gag: a `raise` verb that reports the weapon is now above the ceiling, and stays there for the rest of the case. | | **"Headless chicken" pathfinding** — NPCs spiral endlessly around obstacles | Al, in Case One, *"continues walking in a tight, rapid circle around the water cooler, as he has all morning."* | | **Metal detector only checks if you're facing up** — walk diagonally past it | Act III airport screen. The detector is correct and the regulation is correct and you go through diagonally. | | **Waving a drawn gun at airport security** with no reaction until you cross a specific vector | Same screen. The guard reacts to geometry, not to guns. | | **Air-walking** — keep the swimming animation on dry land | Act II, after the zoo. Frank swims across the car park. | | **Levitating into the sky** off a transition | Act III finale — but it's the owl. | | Typing **`halt`** resets the enemy's shot counter → infinite standoff | `halt` is already a verb in Case One's manifest. In the Act II standoff it works, forever, and the game never acknowledges why. | | **Infinite score** by re-dusting the ashtray / re-questioning the amnesiac witness | Case One, dusting the counter: *"The department pays out on a lifted print once. You may dust this counter as many times as you like. It has been looked into."* | The rule: **play the bug straight.** Never nudge the player. The comedy is that the game is behaving exactly as documented. --- ## 9. Art pipeline `tools/sprites.py ` reads that case's `sprites.json` and generates every missing sprite on the **MODELBEAST** farm (free, local, m3ultra): ``` flux_local (text→image, 512²) → bg_remove_local (RMBG-2.0 cutout) → Pillow nearest-neighbour trim+downscale to the sprite's target height ``` Trimming to the alpha bounding box before scaling is what puts the subject's feet on the bottom edge, which is how MRPGI positions and depth-sorts sprites. The engine quantizes to EGA itself on load, so the script only owes it a small transparent PNG. A shared `STYLE` constant in the script enforces the Sierra look; per-sprite prompts stay short. Act I prompts end in *"black and white monochrome grayscale only"* — that one phrase is the whole 1950s era treatment. ```bash python3 tools/sprites.py cases/case-01-substantial-gift # fill gaps python3 tools/sprites.py cases/case-01-substantial-gift --force # redo all python3 tools/sprites.py cases/case-01-substantial-gift --only ego,al ``` Seeds are derived from the sprite name, so a rerun reproduces the same art. ### On LoRAs (tested, negative result) The farm has ~40 LoRAs, but **none of them currently apply to this pipeline**, and it's worth writing down why so nobody burns an afternoon on it twice: - The style LoRAs worth wanting (`style_retro-flux`, `old_timey_v4`) live in `vendor/comfyui/models/loras/`, which is **not** in `MB_LORA_DIRS` — a bare name 404s. A full path loads them. - Loaded that way they are still a **no-op**. They're FLUX.1-dev LoRAs and the only ungated model is `flux2-klein-4b`, a different architecture. An A/B at a fixed seed gives three visually identical images (checksums differ by a hair; nothing you can see). `Iso-Pixel-05` is SD-architecture — same result. - Using them for real needs either the HF-gated `dev` model, or routing SD/SDXL LoRAs through the `comfyui_sd` operator instead. **And it wouldn't help much anyway.** The pixel-art look comes from the nearest-neighbour crush to ~24px, not from the model — a style LoRA at 512px is thrown away by the downscale. Plain `flux2-klein-4b` is the right tool here. Where the farm's bulk capacity *does* pay off is quantity: 48 sprites across two cases, free, in a few minutes. **Farm gotcha:** the guest token caps concurrent jobs, and going over returns `429`/`401` — which reads like an auth failure and isn't. `tools/sprites.py` retries with backoff; if a whole batch fails, something else of yours is using the farm. Don't run two clients at once.