Files
two-keys/content/games/tick-tock-overtime.yaml
joshuaandClaude Opus 5.5 db2653c1ab V1.2.1
Point the Overtime fixtures comment at the real solver: GAMES-NEW.md Appendix A
and its TypeScript port in server/src/engines/defuse.ts, not the missing
tools/reference/overtime_solver.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:48:20 +02:00

304 lines
15 KiB
YAML

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"]}