The challenge
Thirteen steps forward. Funny how that works out.
The question, word for word Day 1's (A Little Based):
Decode the assigned blob completely. What exact answer slug does its final non-empty decoded line instruct you to submit?
Answer format: word-word-word-NN, trimmed. Mastery: 8 blobs (Day 1 had 3).
Reading the prompt: what it said we'd need
| Clue | What it pointed to | What I did about it |
|---|---|---|
| "Thirteen steps forward" | ROT13: shift each letter 13 places | Add a ROT13 step to Day 1's decoder |
| "Half a turn" (the title) | 13 is half of the alphabet's 26 | — |
| "Funny how that works out" | ROT13 is its own inverse: applying it twice gives back the original | Never apply ROT13 twice in a row; that would undo it |
| The question is identical to Day 1's | A compounding day: Day 1's Base64 and labels may come back, combined with ROT13 | Build on Day 1's solver rather than starting over |
| Mastery's 8 blobs | More variety, more chances for mixing | Test mixed chains before any timed run |
What was in the files
Every blob decoded to Day 1's familiar sentence: "Nice work decoding this warmup! To solve, submit this exact answer to the Game Master: <slug>". Only the wrapping changed between modes:
| Mode | Delivered as | Raw format |
|---|---|---|
| Single Solve | blob., 108 B |
The whole sentence in ROT13 |
| Time Trial | blob., 107 B |
The whole sentence in ROT13 |
| Mastery | One zip of blob- (1,891 B) |
Two labelled lines per blob, with a different encoding on each: 01<TAB> Base64 + 02<TAB> ROT13 |
The Single Solve blob, raw and decoded:
Avpr jbex qrpbqvat guvf jnezhc! Gb fbyir, fhozvg guvf rknpg nafjre gb gur Tnzr Znfgre: cyhpxl-pybpx-syvag-94
Nice work decoding this warmup! To solve, submit this exact answer to the Game Master: plucky-clock-flint-94
How to spot ROT13 by eye: the word lengths and punctuation survive, so it looks like a sentence in a strange language. Short common words map to fixed tells: gur = "the", gb = "to", guvf = "this".
A Mastery blob, the sentence split mid-word across two encodings:
01<TAB>TmljZSB3b3JrIGRlY29kaW5nIHRoaXMgd2FybXVwISBUbyBzb2x2ZSwgc3VibWl0IHRoaXMgZQ==
02<TAB>knpg nafjre gb gur Tnzr Znfgre: avzoyr-puvzarl-syvag-30
| Line | Encoding | Decodes to |
|---|---|---|
01 |
Base64 | "Nice work decoding this warmup! To solve, submit this e" |
02 |
ROT13 | "xact answer to the Game Master: nimble-chimney-flint-30" |
The trap: ROT13 output always "looks valid"
Base64 fails loudly on text that isn't Base64. ROT13 never fails: it maps any letters to other letters. Worse, ROT13 of a slug is another slug-shaped string. The raw Single Solve blob already ends in cyhpxl-pybpx-syvag-94, which fits word-word-word-NN perfectly and is wrong.
So the solver doesn't accept the first slug it sees. It only stops when the final line also reads as the instruction, containing "submit" or "answer", and holds exactly one slug.
Single Solve: CORRECT in 15 seconds
Started at 23:39:18 UTC. The blob was downloaded with its SHA-256 matching, ROT13-decoded, and submitted. CORRECT at 23:39:33, flag e90dccd2…58e0.
The solver
Our Day 2 solver reuses Day 1's decoder (Base64, hex, Base32, Base85, line labels), loading it by path, and alternates it with a ROT13 step until the final line is a real instruction. It never applies ROT13 twice in a row, and it stops rather than guess.
8 tests, all passing before any timed run: - the real blob; - the ROT13-slug trap; - a Day 1-style blob; - Base64 of ROT13, and ROT13 of Base64; - labels plus Base64 of ROT13 of Base64; - garbage, which it refuses; - Mastery as a zip and as separate files.
One snag along the way: both days' solver files had the same module name, so a plain import found itself and recursed. Loading Day 1's file by its path, under a unique name, fixed it.
Time Trial: 1.56 s of a 5-second clock
Day 2's clocks are tighter: the server's deadline was 5 s, where every Day 1 deadline was 30 s.
started_at 2026-10-02T23:41:24.193Z deadline 2026-10-02T23:41:29.193Z
artifact blob.txt 107 bytes sha256 f8018b4f1aea09d1… (checked)
message: jazzy-garden-dune-29
start 653 ms
artifact 348 ms
solve 0 ms
submit 560 ms
TOTAL 1562 ms
result CORRECT flag c2d67597…a335
Before Mastery, our shared runner got parallel downloads. If 8 blobs arrived as separate files, fetching them one by one through the Homebase relay would take about 3 s, too close to a 5 s clock. Measured live: 8 downloads in 2.0 s in parallel, against about 10.9 s one after another.
Mastery: 1.48 s of 5 s, first attempt
started_at 2026-10-02T23:42:28.802Z deadline 2026-10-02T23:42:33.802Z
artifact warmups-day-02-mastery.zip 1891 bytes sha256 91c67c329d4ade03… (checked)
set1.message: nimble-chimney-flint-30
…
set8.message: lucky-sparrow-trail-88
start 597 ms
artifact 319 ms
solve 1 ms
submit 564 ms
TOTAL 1481 ms
result CORRECT flag 30410789…303e
⚠️ An honest note: the answers were right, but partly by luck
The Mastery blobs mixed encodings per line, which the solver wasn't built for. Day 1's decoder couldn't handle the mixed text, so the solver ROT13'd the whole blob. That garbled the Base64 line, but turned the ROT13 line into plain English holding "answer" and the slug. It worked only because the slug sat in the final, ROT13-encoded line. If the slug had been in the Base64 line, the solver would have stopped safely, but the attempt would have expired.
The fix before Day 3: decode each labelled line with its own encoding, join the chunks in label order, and only then look for the instruction.
Update, 2026-10-07: the fix is done, and it mattered. Day 3's Mastery (Hex Appeal) had three lines per blob (Base64, ROT13, hex) with the slug in the hex line every time. The fixed solver passed it first try. See the Hex Appeal write-up.
Time to solve
All three modes were solved on 2026-10-02 by 23:42:30 UTC, 3 min 12 s after the first start. The Single Solve was CORRECT in 15 s, and the Time Trial (1.56 s of 5 s) and the Mastery (1.48 s of 5 s) each went through on the first submit, with the solver extended and the downloads made parallel in between.
Takeaways
- A decode that can't fail can't be trusted on its own. ROT13 always produces letters. Check that the output means something before accepting it.
- A pattern match isn't proof. ROT13 of a slug is still slug-shaped. Pair the pattern with a context cue ("submit", "answer").
- Reuse earlier days' solvers. Compounding days repeat earlier encodings. Building on Day 1 made this a 3-minute challenge.
- Check how much time the clock actually gives. Day 2 dropped from 30 s to 5 s. Making the downloads parallel before Mastery kept the run well inside the limit.
- Look at what got the answer right, not just whether it was right. Inspecting the accepted Mastery blobs showed the per-line mixing, a weakness that would have failed in a slightly different layout.