Case Two: Ring of Fear — the paperwork is what keeps you alive

Act I, monochrome. Five rooms, 100 points, verified end-to-end at 100/100 on
the first pass, plus three verified Sierra deaths.

Frank goes under as fight manager "Frank Deacon" to break a fight-fixing racket.
The procedure gag from the bible finally has teeth: Form 22-B, the four-page
application for an authorised cover identity, is filed in Act 1 by a clerk in
Sacramento who never learns anything about it — and that form is the only thing
standing between Frank and a very short career. At the promoter's licence check
the "I'm licensed" reply is gated on having filed it; skip the form and the
single visible option is the fatal one. Bureaucracy as the thing that saves you
is the exact inversion the campaign is built on.

Act I cases now share a sprite set: 18 PNGs copied from case-01, 14 new ones
generated. tools/sprites.py skips keys beginning with "_" so sprites.json can
carry a note about which sprites are shared.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-07-25 22:47:23 +10:00
parent e95360a1b2
commit e429351ab3
42 changed files with 827 additions and 3 deletions

View File

@ -135,13 +135,17 @@ whitelist is generated from the same table so they can't drift:
### Act I — Frank Drebin Sr, *Police Squad!* (monochrome)
Six cases, one per episode. Each opens with a **special guest star being murdered
Six cases, one per episode. **Act I cases share a sprite set** — copy the common
PNGs (ego, hocken, nordberg, al, johnny, olson, badge, revolver, casefile, desk,
phone, coffeepot, filecabinet, squadcar, evidence, shoeshine, body, counter) from
an existing case, then run `tools/sprites.py`, which skips anything already
present and generates only the new props. 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 |
| 02 | **Ring of Fear** | Ep 2 | **BUILT.** Undercover as fight manager Frank Deacon; Buddy Kessler's wife taken to force a dive in the fourth | **The paperwork is what keeps you alive.** File Form 22-B in Act 1 and a clerk in Sacramento makes Frank Deacon real. Skip it and the promoter's licence check leaves you exactly one dialogue option, which is fatal. Three ways to blow the cover, all deaths. |
| 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 |

View File

@ -32,6 +32,7 @@ cargo run -p mrpgi --manifest-path ~/Documents/MRPGI/Cargo.toml -- --game cases/
|---|---|
| `cases/case-01-substantial-gift/` | **Case One — playable, 100 points.** Drebin Sr, 1982, monochrome. Five rooms. |
| `cases/case-07-from-the-files/` | **Case Seven — playable, 100 points.** Drebin Sr, 1988, full colour. Six rooms, the Anaheim Stadium finale. |
| `cases/case-02-ring-of-fear/` | **Case Two — playable, 100 points.** Drebin Sr, 1982, monochrome. Five rooms, undercover, three deaths. |
| `cases/case-10-plot-device/` | **Case Ten — playable, 100 points.** Drebin Jr (Neeson), 2025, cold palette. Six rooms, the arena finale and the owl. |
| `tools/sprites.py` | Generates every sprite on the MODELBEAST farm (free, local). |
| `RESEARCH.md` / `DESIGN.md` | Source research and the campaign bible. |

View File

@ -0,0 +1,21 @@
{
"name": "Police Squad Quest — Case Two: Ring of Fear",
"start_room": 0,
"max_score": 100,
"intro_text": "POLICE SQUAD. Somebody is fixing fights at the Olympic, and three men who tried to say so are no longer saying anything. Captain Hocken wants a man on the inside. I'm going in as a fight manager. My name is Drebin. From this morning it's Frank Deacon, and Frank Deacon manages fighters, and Frank Deacon has never met a police officer in his life. Type 'help'.",
"death_text": "† OFFICER DOWN. Your cover is filed under DECEASED. The day restarts. †",
"verbs": [
{ "name": "use", "words": ["frisk", "search", "cuff", "book", "arrest", "file", "sign", "radio", "halt", "spar", "train", "stop"] },
{ "name": "look", "words": ["investigate", "observe", "detect"] },
{ "name": "talk", "words": ["interrogate", "question", "brief"] }
],
"flags": {
"paperwork_filed": false,
"briefed": false,
"knows_fighter": false,
"knows_kidnap": false,
"cover_checked": false,
"has_ledger": false,
"wife_safe": false
}
}

View File

@ -0,0 +1,135 @@
{
"name": "Police Squad HQ — Squad Room",
"enter_text": "The squad room. Somebody has put a boxing poster on the notice board and somebody else has written on it.",
"music": 3,
"strokes": [
{ "Rect": { "x": 0, "y": 0, "w": 160, "h": 168, "color": 7, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 0, "w": 160, "h": 58, "color": 8, "meaning": "Wall" } },
{ "Rect": { "x": 0, "y": 58, "w": 160, "h": 110, "color": 7, "meaning": "Floor" } },
{ "Rect": { "x": 0, "y": 55, "w": 160, "h": 3, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 100, "y": 12, "w": 46, "h": 32, "color": 15, "meaning": "None" } },
{ "Rect": { "x": 122, "y": 12, "w": 2, "h": 32, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 100, "y": 26, "w": 46, "h": 2, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 14, "y": 14, "w": 42, "h": 30, "color": 15, "meaning": "None" } },
{ "Rect": { "x": 18, "y": 18, "w": 16, "h": 3, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 18, "y": 24, "w": 24, "h": 3, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 18, "y": 30, "w": 20, "h": 3, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 18, "y": 36, "w": 28, "h": 3, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 0, "w": 5, "h": 168, "color": 0, "meaning": "Wall" } },
{ "Rect": { "x": 0, "y": 163, "w": 160, "h": 5, "color": 0, "meaning": "Wall" } }
],
"spawn": [86, 148],
"exits": [null, 1, null, null],
"exit_flags": ["", "briefed", "", ""],
"exit_blocked": ["", "You are not undercover yet. You are a police detective standing in a police station, which is the opposite of undercover.", "", ""],
"objects": [
{
"name": "desk",
"sprite": "desk",
"x": 50,
"y": 142,
"look": "Your desk. The drawer still sticks. It has stuck for eleven years and it will outlive everyone in this room.",
"synonyms": "table",
"use_text": "You clear the desk, because a man going under does not leave anything on a desk. It takes four seconds. There was nothing on it."
},
{
"name": "form",
"sprite": "casefile",
"x": 62,
"y": 130,
"look": "FORM 22-B: APPLICATION FOR AUTHORISED COVER IDENTITY AND ASSOCIATED OVERTIME. Four pages. Section 3 requires you to state, in advance, the number of hours you expect to spend not being yourself.",
"synonyms": "paperwork 22b overtime application file papers",
"points": 10,
"sets_flag": "paperwork_filed",
"use_text": "You fill in Form 22-B correctly and in full, including Section 3, in which you estimate that you will spend fourteen days not being yourself. Police Squad files it with the State Athletic Commission the same afternoon, because that is what the form is for and because nobody in this department has ever once failed to file a form. Somewhere in a filing cabinet in Sacramento, a fight manager named Frank Deacon comes into existence, licensed, bonded, and current on his dues."
},
{
"name": "phone",
"sprite": "phone",
"x": 30,
"y": 138,
"look": "The phone. Still ringing. Nobody has ever mentioned it and you have stopped hearing it, which is worse.",
"synonyms": "telephone",
"use_text": "You answer it. The same man asks whether you are satisfied with your current carpeting. You tell him you are going undercover for fourteen days. He asks whether that affects the carpeting."
},
{
"name": "al",
"sprite": "al",
"x": 80,
"y": 66,
"look": "Officer Al. From here you can see his shoes and about nine inches of trouser. He is holding something up for everyone to look at. Everyone is looking at it.",
"synonyms": "tall officer legs",
"use_text": "You shake his hand. You have to jump."
},
{
"name": "guest",
"sprite": "guest",
"x": 118,
"y": 150,
"look": "A television actor in a dinner jacket, one arm raised mid-wave, smiling. He has been dead since the opening titles. This week's is a different one from last week's. Nobody has commented on the pattern.",
"synonyms": "star actor man body",
"use_text": "You check him for a pulse, as procedure requires. There isn't one, as the opening titles established. You note the time and step over him."
},
{
"name": "nordberg",
"sprite": "nordberg",
"x": 138,
"y": 152,
"look": "Officer Nordberg, in a wheelchair now, both legs out in front of him in casts. He is your backup on this assignment.",
"synonyms": "norberg partner officer backup",
"use_text": "You confirm the signal with Nordberg. If you are in trouble, you take off your hat. If you are in serious trouble, you take off your hat twice.",
"dialogue": [
{
"says": "Nordberg: I'll be right outside the whole time, Frank. Whole time. Right outside.",
"choices": [
{ "text": "Outside where, Nordberg?", "goto": 1 },
{ "text": "You can't drive, Nordberg.", "goto": 2 }
]
},
{
"says": "Nordberg: Outside. You know. Around. He gestures at the window with a plaster cast, and hits the window.",
"choices": [{ "text": "Just stay by the radio.", "goto": -1 }]
},
{
"says": "Nordberg: I can drive, Frank. I got the hand controls. He does not have the hands.",
"choices": [{ "text": "Stay by the radio, Nordberg.", "goto": -1 }]
}
]
},
{
"name": "hocken",
"sprite": "hocken",
"x": 106,
"y": 126,
"look": "Captain Ed Hocken, holding a fight programme he has folded down to one name.",
"synonyms": "captain ed boss",
"dialogue": [
{
"says": "Hocken: Three men in eleven months, Frank. All of them ready to talk about the Olympic, none of them talked. Somebody up there is buying fights and burying anybody who says so.",
"choices": [
{ "text": "Who's fighting Friday?", "goto": 1 },
{ "text": "Who's buying?", "goto": 2 },
{ "text": "I'll go in as a police officer.", "goto": 5, "kills": true },
{ "text": "I'm licensed and ready, Captain.", "goto": 3, "requires_flag": "paperwork_filed", "sets_flag": "briefed", "points": 10 }
]
},
{
"says": "Hocken: Kid named Buddy Kessler. Twenty-two and two. He's never gone down in his life and the money says he goes down in the fourth.",
"choices": [{ "text": "The money is usually right.", "goto": 0 }]
},
{
"says": "Hocken: A promoter named Sid Tannenbaum. Owns the gym, owns the room, owns the referee. We've had him three times and we've never had him once.",
"choices": [{ "text": "Then we do it from inside.", "goto": 0 }]
},
{
"says": "Hocken: Good. You're Frank Deacon. Frank Deacon has a licence, a bond, and eleven years of dues paid quarterly, because we filed the form. Hocken: Frank — Tannenbaum will check. He checks everybody. That form is the only thing standing between you and a very short career as a fight manager.",
"choices": []
},
{ "says": "", "choices": [] },
{
"says": "Hocken: As a what? You explain that you intend to enter a criminal organisation openly identified as a member of Police Squad, on the grounds that honesty has served you well. Hocken: Frank. Frank. Sit down. It is eleven days before they find the car."
}
]
}
]
}

View File

@ -0,0 +1,98 @@
{
"name": "Sullivan's Gym — Third Floor",
"enter_text": "Sweat, resin, and a radiator that has been on since 1948. Somewhere behind you a speed bag is going and it does not stop for the entire scene.",
"music": 4,
"strokes": [
{ "Rect": { "x": 0, "y": 0, "w": 160, "h": 168, "color": 7, "meaning": "Floor" } },
{ "Rect": { "x": 0, "y": 0, "w": 160, "h": 60, "color": 8, "meaning": "Wall" } },
{ "Rect": { "x": 0, "y": 58, "w": 160, "h": 3, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 61, "w": 160, "h": 107, "color": 7, "meaning": "Floor" } },
{ "Rect": { "x": 8, "y": 8, "w": 34, "h": 44, "color": 15, "meaning": "None" } },
{ "Rect": { "x": 12, "y": 12, "w": 26, "h": 3, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 12, "y": 20, "w": 26, "h": 12, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 12, "y": 36, "w": 20, "h": 3, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 12, "y": 44, "w": 24, "h": 3, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 116, "y": 10, "w": 36, "h": 40, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 120, "y": 14, "w": 28, "h": 32, "color": 15, "meaning": "None" } },
{ "Rect": { "x": 124, "y": 20, "w": 20, "h": 3, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 124, "y": 28, "w": 20, "h": 3, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 124, "y": 36, "w": 12, "h": 3, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 100, "w": 160, "h": 2, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 164, "w": 160, "h": 4, "color": 0, "meaning": "Wall" } }
],
"spawn": [16, 140],
"exits": [null, 2, null, 0],
"exit_flags": ["", "knows_fighter", "", ""],
"exit_blocked": ["", "You have not been introduced to anybody. A manager who walks into a fighter's locker room uninvited is a manager nobody has heard of.", "", ""],
"objects": [
{
"name": "poster",
"sprite": "poster",
"x": 82,
"y": 96,
"look": "FRIDAY NIGHT AT THE OLYMPIC — KESSLER vs. MARCHETTI, TEN ROUNDS. Kessler is twenty-two and two. Marchetti is nine and fourteen and has not won a fight since the war.",
"synonyms": "bill card fight sign board",
"points": 5,
"use_text": "You read the card properly. Kessler is a four-to-one favourite everywhere in this city except one place, and in that one place — a room above a tailor's on Alvarado — you can get even money on Marchetti, and you can only get it until Thursday. Somebody is not gambling. Gambling has odds. Somebody is shopping."
},
{
"name": "punchbag",
"sprite": "punchbag",
"x": 42,
"y": 122,
"look": "A heavy bag, patched with tape, hanging dead still. Everything else in this gym is moving.",
"synonyms": "bag heavy leather",
"use_text": "You hit the bag twice, in the manner of a man who manages fighters rather than one who is one. Nobody looks up, which means you did it correctly, which is the only compliment this room gives."
},
{
"name": "trainer",
"sprite": "trainer",
"x": 106,
"y": 130,
"look": "An old cornerman with a towel on his shoulder. He has worked this gym for thirty years and he has the face of a man who has watched a great many people make a great many decisions.",
"synonyms": "cornerman old man sullivan coach",
"points": 10,
"sets_flag": "knows_fighter",
"use_text": "You buy the old man a coffee and let him talk, which is all he has wanted for about nine years.",
"dialogue": [
{
"says": "Trainer: Don't know you.",
"choices": [
{ "text": "Frank Deacon. I manage fighters.", "goto": 1 },
{ "text": "Detective Frank Drebin, Police Squad.", "goto": 5, "kills": true },
{ "text": "Nobody does.", "goto": 2 }
]
},
{
"says": "Trainer: Deacon. He looks at you for a while. Trainer: Deacon. Yeah. Heard of you. He has not heard of you. Nobody has heard of you. But there is a licence in Sacramento with your name on it and this is a business where a man is what the paperwork says he is.",
"choices": [
{ "text": "Who's the kid?", "goto": 3 },
{ "text": "Who runs this gym?", "goto": 4 }
]
},
{
"says": "Trainer: That's the truth.",
"choices": [{ "text": "Frank Deacon. I manage fighters.", "goto": 1 }]
},
{
"says": "Trainer: Buddy Kessler. Best hands I've had in this gym in thirty years and he's been throwing up before training all week. Trainer: A kid that good don't get sick before training. A kid that good gets sick before something else.",
"choices": [
{ "text": "Where is he now?", "goto": 6, "sets_flag": "knows_fighter", "points": 10 },
{ "text": "Sick how?", "goto": 6, "sets_flag": "knows_fighter", "points": 10 }
]
},
{
"says": "Trainer: Sid Tannenbaum owns the building. Sullivan's been dead nine years. Trainer: We kept the name. Nobody wants to train at Tannenbaum's.",
"choices": [{ "text": "I can see why.", "goto": 0 }]
},
{
"says": "Trainer: ...Police. He does not shout. He does not run. He simply puts down the towel and walks to the office at the far end of the gym and closes the door, and it is the calmest, most unhurried betrayal you have ever watched, and it takes eleven seconds, and it is enough."
},
{
"says": "Trainer: Locker room. Been in there an hour with the door shut and his gloves still tied. Trainer: Mister. If you really do manage fighters — go talk to him. Somebody ought to.",
"choices": [{ "text": "I'll go talk to him.", "goto": -1 }]
}
]
}
]
}

View File

@ -0,0 +1,320 @@
{
"name": "Sullivan's Gym — Fighters' Locker Room",
"enter_text": "One bulb, six lockers, and a twenty-four-year-old sitting on a stool with his gloves still tied.",
"music": 2,
"strokes": [
{
"Rect": {
"x": 0,
"y": 0,
"w": 160,
"h": 168,
"color": 7,
"meaning": "Floor"
}
},
{
"Rect": {
"x": 0,
"y": 0,
"w": 160,
"h": 64,
"color": 8,
"meaning": "Wall"
}
},
{
"Rect": {
"x": 0,
"y": 62,
"w": 160,
"h": 3,
"color": 0,
"meaning": "None"
}
},
{
"Rect": {
"x": 0,
"y": 65,
"w": 160,
"h": 103,
"color": 7,
"meaning": "Floor"
}
},
{
"Rect": {
"x": 6,
"y": 10,
"w": 22,
"h": 48,
"color": 15,
"meaning": "None"
}
},
{
"Rect": {
"x": 30,
"y": 10,
"w": 22,
"h": 48,
"color": 15,
"meaning": "None"
}
},
{
"Rect": {
"x": 54,
"y": 10,
"w": 22,
"h": 48,
"color": 15,
"meaning": "None"
}
},
{
"Rect": {
"x": 6,
"y": 10,
"w": 70,
"h": 3,
"color": 0,
"meaning": "None"
}
},
{
"Rect": {
"x": 28,
"y": 10,
"w": 2,
"h": 48,
"color": 0,
"meaning": "None"
}
},
{
"Rect": {
"x": 52,
"y": 10,
"w": 2,
"h": 48,
"color": 0,
"meaning": "None"
}
},
{
"Rect": {
"x": 14,
"y": 30,
"w": 5,
"h": 3,
"color": 0,
"meaning": "None"
}
},
{
"Rect": {
"x": 38,
"y": 30,
"w": 5,
"h": 3,
"color": 0,
"meaning": "None"
}
},
{
"Rect": {
"x": 62,
"y": 30,
"w": 5,
"h": 3,
"color": 0,
"meaning": "None"
}
},
{
"Rect": {
"x": 108,
"y": 14,
"w": 40,
"h": 34,
"color": 0,
"meaning": "None"
}
},
{
"Rect": {
"x": 112,
"y": 18,
"w": 32,
"h": 26,
"color": 15,
"meaning": "None"
}
},
{
"Rect": {
"x": 118,
"y": 24,
"w": 20,
"h": 4,
"color": 0,
"meaning": "None"
}
},
{
"Rect": {
"x": 118,
"y": 32,
"w": 14,
"h": 4,
"color": 0,
"meaning": "None"
}
},
{
"Rect": {
"x": 0,
"y": 164,
"w": 160,
"h": 4,
"color": 0,
"meaning": "Wall"
}
}
],
"spawn": [
16,
140
],
"exits": [
null,
3,
null,
1
],
"exit_flags": [
"",
"knows_kidnap",
"",
""
],
"exit_blocked": [
"",
"The kid hasn't told you anything yet, and he is the only person in this building who wants to.",
"",
""
],
"objects": [
{
"name": "gloves",
"sprite": "gloves",
"x": 40,
"y": 120,
"look": "A spare pair, laced and hanging. In thirty years this gym has never had a fighter sit for an hour with his gloves on and not hit anything.",
"synonyms": "mitts leather pair",
"use_text": "You check the laces on the spare pair, the way a manager does, because a manager checks laces and a police detective does not know that a manager checks laces. The trainer, across the room, stops watching you."
},
{
"name": "bucket",
"sprite": "bucket",
"x": 116,
"y": 128,
"look": "A corner bucket with a sponge in it. Beside it, on the bench, is a telephone that does not belong in a locker room and has a very long cord running out under the door.",
"synonyms": "sponge pail towel water",
"use_text": "You follow the cord. It goes out under the door, along the corridor, down the stairwell, and into the office at the far end of the gym. Somebody has run a private line into this room so that this room can be called."
},
{
"name": "cornerstool",
"sprite": "cornerstool",
"x": 70,
"y": 138,
"look": "A three-legged corner stool. He has been sitting on it for an hour and he has not moved it once.",
"synonyms": "stool seat chair",
"use_text": "You turn the stool around and sit on it backwards, facing him, the way a cornerman does between rounds. It is the correct way to sit in this room. He notices."
},
{
"name": "boxer",
"sprite": "boxer",
"x": 82,
"y": 128,
"look": "Buddy Kessler. Twenty-two and two, the best hands in the city, and he has been crying, which he will deny, and which you will not mention.",
"synonyms": "buddy kessler kid fighter",
"dialogue": [
{
"says": "Kessler: Whatever you're selling, mister, I ain't buying and I ain't talking.",
"choices": [
{
"text": "Frank Deacon. I manage fighters.",
"goto": 1
},
{
"text": "Nobody sits an hour in gloves, son.",
"goto": 2
},
{
"text": "I'm a police officer, and I can help you.",
"goto": 6,
"kills": true
}
]
},
{
"says": "Kessler: Then you're the only man in this building who does. He laughs. It is not a good laugh.",
"choices": [
{
"text": "Nobody sits an hour in gloves, son.",
"goto": 2
}
]
},
{
"says": "Kessler: ...I'm going down in the fourth. He says it to the floor. It is the first time he has said it out loud and it costs him everything he has.",
"choices": [
{
"text": "You're four-to-one, Buddy. Why?",
"goto": 3
},
{
"text": "Then you're going down in the fourth.",
"goto": 4
}
]
},
{
"says": "Kessler: Because they got Ellie. Kessler: Tuesday night. Two men, a car, and a phone in this room that rings when they feel like ringing it. I go down in the fourth and she comes home Saturday. I win, and she don't.",
"choices": [
{
"text": "Who called, Buddy?",
"goto": 5,
"sets_flag": "knows_kidnap",
"points": 15
}
]
},
{
"says": "Kessler: ...What? It is not what anybody has said to him all week, and it is exactly enough of a shock to get the rest out of him.",
"choices": [
{
"text": "Unless you tell me why.",
"goto": 3
}
]
},
{
"says": "Kessler: Tannenbaum. Office at the end of the gym. He didn't even use a middleman, mister — he called me himself, from forty feet away, because he don't think anybody's ever going to ask. Kessler: Are you going to ask?",
"choices": [
{
"text": "I'm going to ask.",
"goto": -1
}
]
},
{
"says": "Kessler: ...Police. He is not angry. He is much worse than angry. He looks at the telephone with the long cord, and then at you, and he says: 'They're listening to this room, mister. They've been listening to this room since Tuesday.' It is eleven days before they find the car, and it is the same eleven days, and it is the same car."
}
]
}
]
}

View File

@ -0,0 +1,106 @@
{
"name": "Sullivan's Gym — Tannenbaum's Office",
"enter_text": "Wood panelling, a floor safe, and a man who has been waiting to meet you since the trainer walked in here eleven minutes ago.",
"music": 3,
"strokes": [
{ "Rect": { "x": 0, "y": 0, "w": 160, "h": 168, "color": 7, "meaning": "Floor" } },
{ "Rect": { "x": 0, "y": 0, "w": 160, "h": 62, "color": 8, "meaning": "Wall" } },
{ "Rect": { "x": 0, "y": 28, "w": 160, "h": 2, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 60, "w": 160, "h": 3, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 63, "w": 160, "h": 105, "color": 7, "meaning": "Floor" } },
{ "Rect": { "x": 10, "y": 6, "w": 30, "h": 20, "color": 15, "meaning": "None" } },
{ "Rect": { "x": 46, "y": 6, "w": 30, "h": 20, "color": 15, "meaning": "None" } },
{ "Rect": { "x": 82, "y": 6, "w": 30, "h": 20, "color": 15, "meaning": "None" } },
{ "Rect": { "x": 118, "y": 6, "w": 30, "h": 20, "color": 15, "meaning": "None" } },
{ "Rect": { "x": 16, "y": 12, "w": 18, "h": 8, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 52, "y": 12, "w": 18, "h": 8, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 88, "y": 12, "w": 18, "h": 8, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 124, "y": 12, "w": 18, "h": 8, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 106, "y": 34, "w": 44, "h": 22, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 110, "y": 38, "w": 36, "h": 14, "color": 15, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 164, "w": 160, "h": 4, "color": 0, "meaning": "Wall" } }
],
"spawn": [16, 140],
"exits": [null, 4, null, 2],
"exit_flags": ["", "has_ledger", "", ""],
"exit_blocked": ["", "You have a story and no paper. A story is what the other three men had.", "", ""],
"objects": [
{
"name": "heavy",
"sprite": "heavy",
"x": 38,
"y": 122,
"look": "A man in an overcoat standing against the wall by the door, who has not taken his hands out of his pockets since you came in, and who is standing exactly where you would stand if your job were to make sure nobody left.",
"synonyms": "muscle enforcer man overcoat goon",
"use_text": "You do not touch him. There is a time to take a man like this and it is not in his own office with the door shut behind you, and Frank Deacon — who manages fighters, and who has been doing this for eleven years — would know that."
},
{
"name": "safe",
"sprite": "safe",
"x": 128,
"y": 116,
"look": "A floor safe behind the desk. Not a good one. A man who owns the police does not buy a good safe.",
"synonyms": "strongbox box dial floor",
"requires_flag": "cover_checked",
"points": 15,
"sets_flag": "has_ledger",
"use_text": "He opens it himself, in front of you, because you are a licensed fight manager and he is about to make you an offer, and men like Sid Tannenbaum do not make offers they intend to write down anywhere else. Inside is a ledger. Not a code, not a cipher — a ledger, in columns, in his own hand: eleven fights, four years, every one of them bought, with the fighter's name, the round, and the price. Kessler, B. — 4th — $8,000. Ellie's name is not in it. Ellie is not a line item. Ellie is what the eight thousand is for."
},
{
"name": "ledger",
"sprite": "ledger",
"x": 100,
"y": 128,
"look": "The ledger, open on the desk between you. Eleven fights in four years in a man's own handwriting. Three men died for a thing that has been sitting in a bad safe forty feet from a public gymnasium the entire time.",
"synonyms": "book accounts records columns",
"visible_flag": "has_ledger",
"use_text": "You do not take it. You read it, twice, and you put it back exactly where it was, and you close the safe, because the ledger is worth nothing at all if Sid Tannenbaum knows you have seen it before Friday."
},
{
"name": "promoter",
"sprite": "promoter",
"x": 74,
"y": 132,
"look": "Sid Tannenbaum. Owns the gym, owns the room, owns the referee, and is presently deciding whether he owns you.",
"synonyms": "sid tannenbaum boss man cigar",
"dialogue": [
{
"says": "Tannenbaum: So you're the fella been walking round my gym asking about my fighter. Tannenbaum: Deacon, is it. Frank Deacon. He is already reaching for the telephone.",
"choices": [
{ "text": "That's right.", "goto": 1 },
{ "text": "I manage fighters. Kessler's got nobody.", "goto": 1 },
{ "text": "Police Squad. You're under arrest, Tannenbaum.", "goto": 5, "kills": true }
]
},
{
"says": "Tannenbaum: Uh huh. He calls the State Athletic Commission, from his own desk, in front of you, and he reads out your name and he waits. He waits for eleven seconds. It is the longest eleven seconds of your career and there is nothing whatsoever you can do about it, because the answer was decided on Monday morning by a clerk in Sacramento with a four-page form.",
"choices": [
{ "text": "Take your time, Mr. Tannenbaum.", "goto": 2, "requires_flag": "paperwork_filed", "sets_flag": "cover_checked", "points": 10 },
{ "text": "There's been a mix-up with my licence.", "goto": 6, "kills": true }
]
},
{
"says": "Tannenbaum: Licensed eleven years, bonded, dues paid quarterly. He hangs up. He is delighted. He has been looking for a licensed manager with no fighters and no scruples for about two years, and Sacramento has just told him one walked in the door. Tannenbaum: Deacon, I like you. Sit down. Let me show you how this works.",
"choices": [
{ "text": "Show me how it works.", "goto": 3 },
{ "text": "What's in it for Kessler?", "goto": 4 }
]
},
{
"says": "Tannenbaum: Eight fights a year, ten per cent, and you never have to watch one. He goes to the floor safe, and he crouches down, and he starts turning the dial in front of you, because you are licensed, and because a licensed man is a man with something to lose.",
"choices": [{ "text": "Ten per cent is ten per cent.", "goto": -1 }]
},
{
"says": "Tannenbaum: Kessler gets his girl back Saturday and a long career going down in the fourth. Tannenbaum: You think that's cruel. It ain't cruel, Deacon. Cruel is twenty-two and two and no money and everybody in this city knowing your name for nine more months.",
"choices": [{ "text": "Show me how it works.", "goto": 3 }]
},
{
"says": "Tannenbaum: ...Police. He does not move. He does not even put the cigar down. The man in the overcoat by the door takes his hands out of his pockets, which is the first thing he has done since you came in, and it is the last thing you see him do."
},
{
"says": "Tannenbaum: A mix-up. He hangs up the telephone very gently, which is worse than slamming it. Tannenbaum: There's no Frank Deacon, is there. Eleven years I been asking Sacramento about people and there has never once been a mix-up. The man in the overcoat takes his hands out of his pockets."
}
]
}
]
}

View File

@ -0,0 +1,79 @@
{
"name": "The Olympic Auditorium — Ringside, Friday",
"enter_text": "Round three. Four thousand people, a great deal of smoke, and a kid who has ninety seconds left to decide what kind of man he is.",
"music": 4,
"strokes": [
{ "Rect": { "x": 0, "y": 0, "w": 160, "h": 168, "color": 8, "meaning": "Floor" } },
{ "Rect": { "x": 0, "y": 0, "w": 160, "h": 40, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 12, "w": 160, "h": 2, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 20, "w": 160, "h": 2, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 28, "w": 160, "h": 2, "color": 8, "meaning": "None" } },
{ "Rect": { "x": 60, "y": 2, "w": 40, "h": 10, "color": 15, "meaning": "None" } },
{ "Rect": { "x": 64, "y": 5, "w": 12, "h": 4, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 84, "y": 5, "w": 12, "h": 4, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 40, "w": 160, "h": 128, "color": 8, "meaning": "Floor" } },
{ "Rect": { "x": 0, "y": 40, "w": 160, "h": 3, "color": 7, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 122, "w": 160, "h": 3, "color": 0, "meaning": "None" } },
{ "Rect": { "x": 0, "y": 125, "w": 160, "h": 43, "color": 7, "meaning": "Floor" } },
{ "Rect": { "x": 0, "y": 164, "w": 160, "h": 4, "color": 0, "meaning": "Wall" } }
],
"spawn": [18, 146],
"exits": [null, null, null, 3],
"objects": [
{
"name": "ring",
"sprite": "ring",
"x": 80,
"y": 112,
"look": "The ring. Kessler is carrying him — you can see it from here, everybody who knows anything can see it from here — and the clock says fifty seconds of the third.",
"synonyms": "canvas ropes fight corner posts",
"use_text": "You cannot stop the fight. You have no badge in this building, you are Frank Deacon of Sacramento, and the referee is Sid Tannenbaum's referee. What you have is ninety seconds and a girl in a room somewhere."
},
{
"name": "heavy",
"sprite": "heavy",
"x": 38,
"y": 140,
"look": "The man in the overcoat, working the aisle, with his hands in his pockets and his eyes on the clock rather than the fight. A man watching a clock at a boxing match is a man waiting to make a telephone call.",
"synonyms": "muscle enforcer man overcoat goon",
"points": 10,
"sets_flag": "wife_safe",
"use_text": "You take him in the aisle in eleven seconds, which is your father's record, and which you have never once matched before or since. In his coat: a room key for the Alvarado Hotel, third floor, and a note of the times he is expected to telephone it. The next one is in four minutes. Nordberg is outside. Nordberg cannot walk, cannot drive, and cannot hold a radio. Nordberg gets there in three.",
"dialogue": [
{
"says": "The man in the overcoat looks at you without any expression at all.",
"choices": [
{ "text": "Take your hands out of your pockets.", "goto": 1 },
{ "text": "Police Squad. Hands where I can see them.", "goto": 1 }
]
},
{
"says": "He takes his hands out of his pockets. This is, on reflection, the one time all week that has been the thing you wanted.",
"choices": [{ "text": "Good.", "goto": -1 }]
}
]
},
{
"name": "wife",
"sprite": "wife",
"x": 122,
"y": 138,
"look": "Ellie Kessler, brought in through the side door by an officer in two leg casts who will not explain how he got up the stairs at the Alvarado and who will never be asked.",
"synonyms": "ellie woman girl kessler",
"visible_flag": "wife_safe",
"use_text": "You walk her down to the apron and you stand her where a twenty-four-year-old fighter carrying a man through the fourth round can see her. He sees her in the last nine seconds of the round. He does not celebrate. He does not point. He puts his glove on the top rope and he breathes out, and then he goes and wins a boxing match."
},
{
"name": "promoter",
"sprite": "promoter",
"x": 96,
"y": 146,
"look": "Sid Tannenbaum, four rows back, watching his eight thousand dollars fail to happen in real time in front of four thousand witnesses.",
"synonyms": "sid tannenbaum boss man cigar",
"requires_flag": "wife_safe",
"wins": true,
"points": 15,
"use_text": "You take Sid Tannenbaum at ringside in the fifth round, in front of four thousand people, and you advise him of his rights in the correct order and in full, because there is a ledger in a bad safe forty feet from a public gymnasium and it is going to be worth exactly as much as your arrest is clean. Eleven fights. Four years. Three men in the ground and one girl in a room on Alvarado, all of it in his own handwriting, because it never once occurred to him that anybody was going to ask. Captain Hocken asks how you kept the cover eleven days. You tell him the truth: a clerk in Sacramento processed a four-page form on a Monday morning, correctly, and never knew a thing about it, and will never be told. Somewhere behind you Officer Al says something that gets a laugh from everybody. Everybody freezes, smiling, holding it — except Nordberg, who is at the top of the Alvarado stairs, and who nobody has gone back for."
}
]
}

View File

@ -0,0 +1,59 @@
{
"_comment": "Shared Act I sprites (ego, hocken, nordberg, al, johnny, olson, badge, revolver, casefile, coffeepot, squadcar, evidence, shoeshine, phone, desk, filecabinet, body, counter) are copied from case-01. The tool skips any file that already exists, so only the new ones below are generated. Delete a PNG and re-run to regenerate it.",
"boxer": {
"h": 26,
"prompt": "A heavyweight boxer standing facing the viewer, bare chested, boxing gloves raised, satin trunks, flat nose, exhausted expression, black and white monochrome grayscale only"
},
"trainer": {
"h": 24,
"prompt": "An old wiry boxing trainer facing the viewer, flat cap, cardigan, towel over one shoulder, holding a water bottle, black and white monochrome grayscale only"
},
"promoter": {
"h": 26,
"prompt": "A heavyset 1950s boxing promoter facing the viewer, loud checked suit, fat cigar, pinky ring, wide crooked grin, black and white monochrome grayscale only"
},
"heavy": {
"h": 27,
"prompt": "A thickset 1950s mob enforcer facing the viewer, dark overcoat, fedora pulled low, hands in pockets, blank expression, black and white monochrome grayscale only"
},
"wife": {
"h": 24,
"prompt": "A frightened 1950s woman facing the viewer, headscarf and belted coat, hands clasped tightly together, black and white monochrome grayscale only"
},
"ring": {
"h": 30,
"prompt": "A boxing ring with corner posts and three rope lines, seen from the front, empty, black and white monochrome grayscale only"
},
"punchbag": {
"h": 26,
"prompt": "A heavy leather boxing punchbag hanging from a chain, seen from the side, black and white monochrome grayscale only"
},
"gloves": {
"h": 11,
"prompt": "A pair of laced leather boxing gloves tied together and lying flat, single object, black and white monochrome grayscale only"
},
"bucket": {
"h": 11,
"prompt": "A metal corner bucket with a sponge and a towel draped over the rim, single object, black and white monochrome grayscale only"
},
"ledger": {
"h": 11,
"prompt": "A hardbound accounts ledger book lying open flat with columns of handwritten figures, single object, black and white monochrome grayscale only"
},
"cornerstool": {
"h": 14,
"prompt": "A wooden boxing corner stool, three legs, seen from the side, single object, black and white monochrome grayscale only"
},
"poster": {
"h": 22,
"prompt": "A 1950s boxing match fight poster on a board, bold lettering and two fighter portraits, seen straight on, black and white monochrome grayscale only"
},
"safe": {
"h": 22,
"prompt": "A small heavy 1950s office floor safe with a combination dial, door closed, seen from the front, black and white monochrome grayscale only"
},
"guest": {
"h": 25,
"prompt": "A distinguished 1950s television actor in a dinner jacket facing the viewer, one arm raised mid-wave, broad showbiz smile, black and white monochrome grayscale only"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 841 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

View File

@ -151,7 +151,8 @@ def main():
todo = {
n: s for n, s in specs.items()
if (only is None or n in only)
if not n.startswith("_") # "_comment" etc. are notes, not sprites
and (only is None or n in only)
and (force or not os.path.exists(os.path.join(outdir, f"{n}.png")))
}
if not todo: