id: tick-tock-overtime engine: defuse category: co-op title: "Tick Tock: Overtime" tagline: Six modules. Four levels. A manual that fights back. estimatedMinutes: 20 difficulty: 4 players: { min: 2, max: 2 } theme: { primary: "#ff3b30", accent: "#00d1ff", background: "#0a0a0a", headingFont: "JetBrains Mono" } roles: A: name: Technician blurb: You see the device. You can't see the manual. Describe everything, exactly. B: name: Expert blurb: You have the manual. You can't see the device. Ask the right questions, in the right order. intro: | Remember the training device? This is the sequel. Someone upgraded it. New modules, new rules, indicator lights, and a manual written by someone who clearly hates couples. **Technician:** start by reading out the serial number, battery count, and every indicator (lit and unlit). **Expert:** you'll need all of it. # ---------- Device definition ---------- ruleset: overtime # which manual the server's solver implements (server/src/engines/defuse.ts) device: serial: length: 6 alphabet: "ABCDEFGHJKLMNPQRSTUVWXYZ0123456789" # last char is ALWAYS a digit batteries: { min: 0, max: 4 } indicators: labels: [LUV, HUG, BAE, XOX, DTE] count: { min: 1, max: 3 } # each shown indicator is randomly lit or unlit levels: - id: lvl1 title: Warm-up (that isn't) timeSeconds: 240 modules: [wires, button, keypad] keyName: Spark Key - id: lvl2 title: Words & Waves timeSeconds: 270 modules: [wires, passwords, morse] keyName: Frequency Key - id: lvl3 title: Say It Back timeSeconds: 300 modules: [wires, button, passwords, simon] keyName: Echo Key - id: lvl4 title: Overtime timeSeconds: 360 strikesOverride: 2 # only 2 strikes on this level modules: [wires, button, keypad, passwords, morse, simon] keyName: Overtime Key strikes: { max: 3, speedUpPerStrike: 0.25 } # ---------- Module generation ---------- modules: wires: count: { min: 3, max: 6 } colors: [red, blue, yellow, green, white, black] # Technician: wires top to bottom, colour swatch + colour NAME label. Action { type: "cut", index } button: labels: [HOLD, PRESS, ABORT, DETONATE, LOVE] colors: [red, blue, white, yellow] stripColors: [blue, white, yellow, red] # Strip only shown WHILE holding. Actions: tap | hold → release { timerText } keypad: symbols: heart: "♥ Heart" star: "★ Star" moon: "☾ Moon" sun: "☀ Sun" club: "♣ Club" flower: "✿ Flower" key: "⚷ Key" umbrella: "☂ Umbrella" plane: "✈ Plane" music: "♫ Music note" anchor: "⚓ Anchor" crown: "♛ Crown" diamond: "♦ Diamond" spade: "♠ Spade" bolt: "⚡ Bolt" cloud: "☁ Cloud" columns: - [heart, star, moon, sun, club, flower, key] - [umbrella, heart, plane, music, star, anchor, crown] - [diamond, sun, spade, umbrella, flower, music, bolt] - [anchor, spade, club, plane, moon, diamond, key] - [crown, bolt, heart, diamond, plane, sun, cloud] - [cloud, music, key, spade, club, crown, star] # Generator: pick a column, pick 4 of its symbols, shuffle. Re-roll if any OTHER column also # contains all 4 (validated: no 4-subset of these columns is ambiguous). passwords: columnsCount: 5 lettersPerColumn: 6 words: [ADORE, ANGEL, BLISS, BLUSH, CANDY, CHARM, CRUSH, DANCE, DREAM, FLAME, FLIRT, HEART, HONEY, LOVER, MATCH, PEACH, RINGS, ROSES, SMILE, SPARK, SUGAR, SWEET, TEDDY, TRUST, TULIP, UNITY, WALTZ, BLOOM, CHOSE, PEARL, VOWED, QUEEN] # Technician sees 5 columns with up/down arrows; each column cycles through 6 letters. # Generator: pick a target word; fill each column with its letter + 5 random letters; re-roll until # EXACTLY ONE word in the list can be formed. Action { type: "submit", word } morse: # Technician sees a blinking light (reuse the signal renderer, §6.3) and a frequency dial # from 3.500 to 3.600 MHz in 0.001 steps + a TX button. Action { type: "transmit", frequency } words: HUG: "3.505" KISS: "3.515" LOVE: "3.522" DATE: "3.532" RING: "3.535" ROSE: "3.542" WINE: "3.545" DUET: "3.552" DANCE: "3.555" HEART: "3.565" SWEET: "3.572" HONEY: "3.575" CUDDLE: "3.582" SPARK: "3.592" VOWS: "3.595" BLISS: "3.600" simon: colors: [red, blue, green, yellow] stages: { min: 3, max: 5 } # Device flashes a sequence; each stage adds one flash. Technician presses the MAPPED colours # for the whole sequence so far. Mapping depends on (serial has a vowel) and CURRENT strike count. # Action { type: "press", color } # ---------- The manual (shown ONLY to the Expert) ---------- manual: | # Defusal Manual: Overtime Edition **Before anything else, ask for:** serial number · battery count · every indicator and whether it's **lit**. A "vowel" means A, E, I, O or U. --- ## Module: Wires (3 to 6 wires) Wires are numbered **top to bottom** from 1. Cut exactly one. Find the section for the number of wires, then use the **first** rule that applies. **3 wires** 1. If all three wires are **different colours** → cut the **second** wire. 2. If there are **two or more blue** → cut the **first blue** wire. 3. If the serial contains a **vowel** → cut the **last** wire. 4. Otherwise → cut the **first** wire. **4 wires** 1. If there is **exactly one green** wire and **2 or more batteries** → cut the **green** wire. 2. If the **first and last** wires are the **same colour** → cut the **third** wire. 3. If there are **no white** wires → cut the **second** wire. 4. Otherwise → cut the **last white** wire. **5 wires** 1. If there are **more black than red** wires → cut the **first black** wire. 2. If the serial's **last digit is odd** → cut the **fourth** wire. 3. If there is **exactly one yellow** → cut the wire **directly after** the yellow (if yellow is last, cut the **first**). 4. Otherwise → cut the **second** wire. **6 wires** 1. If there's a **lit LUV** indicator → cut the **sixth** wire. 2. If there are **exactly three red** wires → cut the **third red** wire. 3. If there are **no yellow** wires → cut the **third** wire. 4. Otherwise → cut the **fifth** wire. --- ## Module: The Button First rule that applies: 1. **Blue** button that says **ABORT** → **hold**. 2. **More than 1 battery** and says **DETONATE** → **tap**. 3. **White** button and a **lit BAE** → **hold**. 4. **More than 2 batteries** and a **lit HUG** → **tap**. 5. **Yellow** button → **hold**. 6. **Red** button that says **HOLD** → **tap**. 7. Otherwise → **hold**. **If holding**, a strip lights up. Release when the timer shows this digit **anywhere**: Blue → **4** · White → **1** · Yellow → **5** · Red → **3** --- ## Module: Keypad Exactly one column below contains all four symbols on the device. Press them in the order they appear **top to bottom** in that column. | 1 | 2 | 3 | 4 | 5 | 6 | |---|---|---|---|---|---| | ♥ Heart | ☂ Umbrella | ♦ Diamond | ⚓ Anchor | ♛ Crown | ☁ Cloud | | ★ Star | ♥ Heart | ☀ Sun | ♠ Spade | ⚡ Bolt | ♫ Music note | | ☾ Moon | ✈ Plane | ♠ Spade | ♣ Club | ♥ Heart | ⚷ Key | | ☀ Sun | ♫ Music note | ☂ Umbrella | ✈ Plane | ♦ Diamond | ♠ Spade | | ♣ Club | ★ Star | ✿ Flower | ☾ Moon | ✈ Plane | ♣ Club | | ✿ Flower | ⚓ Anchor | ♫ Music note | ♦ Diamond | ☀ Sun | ♛ Crown | | ⚷ Key | ♛ Crown | ⚡ Bolt | ⚷ Key | ☁ Cloud | ★ Star | --- ## Module: Passwords The Technician can cycle five letter columns. Exactly **one** word below can be spelled. Find it and have them submit it. ADORE · ANGEL · BLISS · BLOOM · BLUSH · CANDY · CHARM · CHOSE · CRUSH · DANCE · DREAM FLAME · FLIRT · HEART · HONEY · LOVER · MATCH · PEACH · PEARL · QUEEN · RINGS · ROSES SMILE · SPARK · SUGAR · SWEET · TEDDY · TRUST · TULIP · UNITY · VOWED · WALTZ *Tip: ask for the letters in column 1 first, then 2. That usually narrows it down fast.* --- ## Module: Morse Light The light blinks a word in Morse, over and over, with a long pause between repeats. Short = dot · Long = dash. Decode the word, then have them tune and transmit: | Word | MHz | Word | MHz | |------|-----|------|-----| | HUG | 3.505 | DUET | 3.552 | | KISS | 3.515 | DANCE | 3.555 | | LOVE | 3.522 | HEART | 3.565 | | DATE | 3.532 | SWEET | 3.572 | | RING | 3.535 | HONEY | 3.575 | | ROSE | 3.542 | CUDDLE | 3.582 | | WINE | 3.545 | SPARK | 3.592 | | BLISS | 3.600 | VOWS | 3.595 | `A .- B -... C -.-. D -.. E . F ..-. G --. H .... I .. J .--- K -.- L .-.. M --` `N -. O --- P .--. Q --.- R .-. S ... T - U ..- V ...- W .-- X -..- Y -.-- Z --..` --- ## Module: Say It Back (Simon) The device flashes colours. The Technician must press the **mapped** colour for every flash so far. ⚠️ The mapping **changes with the strike count**. Re-check after every strike. **Serial HAS a vowel** | Strikes | Red → | Blue → | Green → | Yellow → | |---------|-------|--------|---------|----------| | 0 | Blue | Red | Yellow | Green | | 1 | Yellow | Green | Blue | Red | | 2 | Green | Red | Yellow | Blue | **Serial has NO vowel** | Strikes | Red → | Blue → | Green → | Yellow → | |---------|-------|--------|---------|----------| | 0 | Blue | Yellow | Green | Red | | 1 | Red | Blue | Yellow | Green | | 2 | Yellow | Green | Blue | Red | # ---------- Solver fixtures (MUST pass as unit tests) ---------- # Generated from the reference solver (GAMES-NEW.md, Appendix A), which implements the manual # above exactly. Its TypeScript port is the `overtime` ruleset in server/src/engines/defuse.ts. fixtures: wires: - {"serial": "TK4L82", "batteries": 1, "indicators": {"lit": [], "unlit": []}, "wires": ["red", "blue", "yellow"], "expect": {"type": "cut", "index": 2}} - {"serial": "QX7M35", "batteries": 0, "indicators": {"lit": [], "unlit": []}, "wires": ["blue", "red", "blue"], "expect": {"type": "cut", "index": 1}} - {"serial": "ZP2R44", "batteries": 2, "indicators": {"lit": [], "unlit": []}, "wires": ["red", "red", "white"], "expect": {"type": "cut", "index": 1}} - {"serial": "BC2D48", "batteries": 1, "indicators": {"lit": [], "unlit": []}, "wires": ["red", "red", "green"], "expect": {"type": "cut", "index": 1}} - {"serial": "AB9C11", "batteries": 2, "indicators": {"lit": [], "unlit": []}, "wires": ["green", "red", "blue", "white"], "expect": {"type": "cut", "index": 1}} - {"serial": "LM3N06", "batteries": 1, "indicators": {"lit": [], "unlit": []}, "wires": ["blue", "red", "yellow", "blue"], "expect": {"type": "cut", "index": 3}} - {"serial": "RT5W22", "batteries": 0, "indicators": {"lit": [], "unlit": []}, "wires": ["red", "yellow", "red", "black"], "expect": {"type": "cut", "index": 2}} - {"serial": "HK8P71", "batteries": 0, "indicators": {"lit": [], "unlit": []}, "wires": ["red", "white", "blue", "white"], "expect": {"type": "cut", "index": 4}} - {"serial": "XY3Z45", "batteries": 1, "indicators": {"lit": [], "unlit": []}, "wires": ["black", "black", "red", "blue", "white"], "expect": {"type": "cut", "index": 1}} - {"serial": "PQ7R18", "batteries": 1, "indicators": {"lit": [], "unlit": []}, "wires": ["red", "blue", "yellow", "white", "green"], "expect": {"type": "cut", "index": 4}} - {"serial": "PQ7R12", "batteries": 1, "indicators": {"lit": [], "unlit": []}, "wires": ["red", "blue", "yellow", "white", "green"], "expect": {"type": "cut", "index": 4}} - {"serial": "PQ7R12", "batteries": 1, "indicators": {"lit": [], "unlit": []}, "wires": ["red", "blue", "white", "white", "yellow"], "expect": {"type": "cut", "index": 1}} - {"serial": "ST4V20", "batteries": 1, "indicators": {"lit": [], "unlit": []}, "wires": ["red", "white", "blue", "green", "black"], "expect": {"type": "cut", "index": 2}} - {"serial": "BC1D20", "batteries": 3, "indicators": {"lit": ["LUV"], "unlit": []}, "wires": ["red", "red", "red", "blue", "white", "green"], "expect": {"type": "cut", "index": 6}} - {"serial": "BC1D20", "batteries": 3, "indicators": {"lit": [], "unlit": ["LUV"]}, "wires": ["red", "blue", "red", "white", "red", "green"], "expect": {"type": "cut", "index": 5}} - {"serial": "BC1D20", "batteries": 3, "indicators": {"lit": [], "unlit": []}, "wires": ["blue", "blue", "white", "green", "black", "red"], "expect": {"type": "cut", "index": 3}} - {"serial": "BC1D20", "batteries": 3, "indicators": {"lit": [], "unlit": []}, "wires": ["yellow", "blue", "white", "green", "black", "red"], "expect": {"type": "cut", "index": 5}} button: - {"batteries": 0, "indicators": {"lit": [], "unlit": []}, "label": "ABORT", "color": "blue", "strip": "yellow", "expect": {"type": "hold", "releaseDigit": 5}} - {"batteries": 2, "indicators": {"lit": [], "unlit": []}, "label": "DETONATE", "color": "red", "strip": "blue", "expect": {"type": "tap"}} - {"batteries": 1, "indicators": {"lit": ["BAE"], "unlit": []}, "label": "LOVE", "color": "white", "strip": "red", "expect": {"type": "hold", "releaseDigit": 3}} - {"batteries": 3, "indicators": {"lit": ["HUG"], "unlit": []}, "label": "PRESS", "color": "red", "strip": "white", "expect": {"type": "tap"}} - {"batteries": 0, "indicators": {"lit": [], "unlit": []}, "label": "PRESS", "color": "yellow", "strip": "blue", "expect": {"type": "hold", "releaseDigit": 4}} - {"batteries": 1, "indicators": {"lit": [], "unlit": []}, "label": "HOLD", "color": "red", "strip": "white", "expect": {"type": "tap"}} - {"batteries": 1, "indicators": {"lit": [], "unlit": ["HUG"]}, "label": "LOVE", "color": "white", "strip": "red", "expect": {"type": "hold", "releaseDigit": 3}} keypad: - {"symbols": ["star", "flower", "heart", "sun"], "expect": ["heart", "star", "sun", "flower"]} - {"symbols": ["spade", "plane", "anchor", "moon"], "expect": ["anchor", "spade", "plane", "moon"]} - {"symbols": ["music", "umbrella", "diamond", "sun"], "expect": ["diamond", "sun", "umbrella", "music"]} - {"symbols": ["cloud", "crown", "bolt", "plane"], "expect": ["crown", "bolt", "plane", "cloud"]} - {"symbols": ["star", "key", "club", "crown"], "expect": ["key", "club", "crown", "star"]} passwords: - {"columns": ["XAPUDI", "RVCSEX", "TGAHRQ", "RASIYZ", "CDGKYL"], "expect": "PEARL"} - {"columns": ["BZRWXO", "GLTUAS", "YHCDLJ", "FVTGIL", "OFZIUM"], "expect": "WALTZ"} - {"columns": ["KYBZTH", "UPOMRG", "SLXUMN", "SEFZUD", "ROTIAQ"], "expect": "TRUST"} morse: - {"signal": "..../..-/--.", "expect": {"word": "HUG", "frequency": "3.505"}} - {"signal": "...././.-/.-./-", "expect": {"word": "HEART", "frequency": "3.565"}} - {"signal": "-.../.-../../.../...", "expect": {"word": "BLISS", "frequency": "3.600"}} - {"signal": "...-/---/.--/...", "expect": {"word": "VOWS", "frequency": "3.595"}} simon: - {"serial": "TK4E82", "strikes": 0, "flashes": ["red", "green", "yellow"], "expect": ["blue", "yellow", "green"]} - {"serial": "TK4E82", "strikes": 1, "flashes": ["red", "green", "yellow"], "expect": ["yellow", "blue", "red"]} - {"serial": "ZP2R44", "strikes": 0, "flashes": ["blue", "blue", "green", "yellow"], "expect": ["yellow", "yellow", "green", "red"]} - {"serial": "ZP2R44", "strikes": 2, "flashes": ["yellow", "red", "green"], "expect": ["red", "yellow", "blue"]}