Dampé Blink Calculator

candidates (RNG state × Link's blink phase)
8,388,608 × 99
–
New try (R)
More

Counting is optional: a tap alone counts as "not sure". A 3/4 tap sets the count of your latest flutter. Count what you see, not what the page expects.

Validated on the ares emulator (8 of 8 Heart Pieces, NTSC 1.2, ±2-frame tap noise, strict matching); real-hardware test pending. On a console, the frame rate, the TV's display lag and your own tap timing are not measured yet: see "Timing" below. The tolerant matching, "1 tap ignored", the later commit and the press margins have only been tested in simulation. There they gave 0 wrong windows in 150 runs (25 each: clean, one flipped count, one bad tap, one missed flutter, a 19.94 fps console, a press 6 frames late); DMP2's version gave 10 wrong in the same 150 (pipeline/dmp4/notes.md). Anything worse than one mistake makes the page say "inconsistent" or keep asking for flutters; in those sims it never gave a wrong window.

Setup rules (break one and the read is wrong)
  • Version: N64 NTSC 1.0 or 1.2 (1.2 tested on ares; 1.0 has identical code for everything involved). PAL 1.0/1.1 uses the same 23-bit RNG, so the model applies but is untested (set the frame rate to about 16.67). GameCube and iQue use different RNG bits: does not apply. Wii VC runs the 1.2 ROM, but its frame pacing is untested.
  • Child Link, Kakariko Graveyard at night (Dampé digs 18:00-21:00). No mask: with any mask Dampé gives his mask line instead of the Yes/No box.
  • Wall Gold Skulltula dead. It keeps drawing random numbers even while you talk. No live soil Gold Skulltula (from planting bugs) either.
  • No released bugs in the graveyard.
  • No rain: no Song of Storms, and don't go near the east side (royal tomb, Nocturne pad, Shadow Temple stairs) before the read. The graveyard storm tag starts rain and lightning there, and rain draws random numbers every frame. If it rained, wait until it has fully stopped.
  • More than 1 heart. At 1 heart or less, the camera's low-health wiggle can draw random numbers.
  • Navi settled: wait until she stops sparkling, plus 1 s. Her sparkles draw random numbers.
  • Stand still once you start tapping: no stick, no camera, no walking (walking dust draws random numbers).
  • Never pause. The game stops but the phone clock keeps running, so the read is dead: Restart.
How to use it
  1. Pay Dampé, stop him on a soil patch and talk until "Do you want me to dig here? Yes / No" is up with Yes highlighted.
  2. Wait until Navi stops sparkling, plus 1 s. Then watch Dampé's eyes. He blinks in quick flutters of 3 or 4 blinks, about 1.5-3 s apart.
  3. Press 3 or 4 once per flutter, as soon as it is over. A 4th blink means 4: press 4 right on it (4 is the most there can be). No 4th blink means 3: press 3 as soon as the eyes stay open. That one press is both the timing and the count. Pressed 3 and then a 4th blink came? Just press 4 (a press within 1 s replaces the last). Not sure of the count: 0. (On a phone: the big 3 blinks / 4 blinks buttons. The old way, Space at the first blink and then 3 / 4, is under Timing → Input: two inputs.)
  4. If a flutter went by without a press, tap I missed one (M) right away. One unnoticed missed flutter and one wrong count are tolerated anyway.
  5. Once few enough states fit (from 8 flutters), the page asks for 5 more to confirm and shows when the next one should come. Usually 13-17 flutters, about 35-45 s.
  6. Then a countdown appears with beeps at 3, 2, 1 and a long beep (plus a vibration on Android). Press A (Yes) together with the long beep, anticipating it like a rhythm game, not reacting to it. The green part of the bar is the safe window, the line is the target.
  7. If you keep tapping flutters during the countdown, each one is checked. A tap that disagrees with the prediction cancels the window.
  8. "1 tap ignored" means one of your taps didn't fit and the page left it out; it needs 5 fresh confirmations. "Inconsistent: restart" means no state explains your taps even then: Restart (the dialog can stay open).

First person only does not work (T5 on ares, Q-DMP3-1): reading in C-up before talking is clean, but leaving first person respawns a grass ring (12 random numbers) and talking makes Navi fly over and sparkle (about 390 more). A window carried over from first person is therefore wrong. Use the hybrid read mode instead (DMP5, simulation only so far):

  1. Set "Read mode" to Hybrid. Stand 70-90 units straight in front of Dampé (no stick), C-up, and tap his flutters as above. His eyes are about 3× larger there.
  2. When the page says "First person done" (usually after 12-15 flutters, 3 of them confirmations), leave first person, walk in and talk until the Yes/No box is up.
  3. Wait for Navi's second sparkle trail. About 0.7 s after the Yes/No arrow appears she flies over Dampé leaving a short trail of sparkles; each sparkle uses 38 random numbers. Press IN THE BOX NOW 3 s after the arrow appears (at least 1 s after that trail ends), then tap the next flutters in the box as usual. (DMP7: T5's ares runs pressed it in the gap between Navi's two trails, so the second trail fell inside the box read and 5 of 7 re-syncs failed.)
  4. The page re-syncs over Navi's sparkle count: 12 grass + 38 per sparkle (8-30) + a small part set from the time between your last first-person tap and your first box tap. It needs about 11-12 box flutters (6 of them confirmations). If nothing fits it tries 0-110 sparkles (13+ box flutters), and if that fails too it carries on as a plain box read with the same taps.
Timing, calibration and settings

The window is timed from your taps, so anything that makes every tap late also makes the press late, unless it is subtracted: tap delay (your reaction to an unexpected blink, typically 150-250 ms; measure it below) and display lag. Display lag is how much later the blink reaches your eyes than the game frame that drew it. The N64 shows a frame about 1 game frame after drawing it, the fully closed eye that people notice comes about 1 frame after the blink starts, and a TV in game mode adds about 1 more (a CRT about 0, an upscaler or a TV outside game mode more). Default: 3 game frames (150 ms). Your press on the long beep isn't a reaction, so neither of these applies to it. Its own offset (audio latency, pressing a bit late or early) is the press offset. Measure it with the metronome below, wearing the same headphones or speaker. Bluetooth audio can lag 150-250 ms: use wired or the phone speaker.

wait…
One key (DMP8, default): one press per flutter, as soon as it is over. The page takes the timing from that press and subtracts the flutter's length (3 blinks = 9 game frames, 4 = 12) and your reaction. Two inputs: DMP4's original mode.
Likelihood (DMP9): every state is scored by how well it explains all your presses (timing scatter, a misread 3/4 costs a little, one outlier press costs more) and the page locks only when every state within a safe margin of the best agrees on the Heart Piece moment. A wrong count no longer ends the read; when nothing fits any more, the oldest presses age out and the read goes on. Strict: DMP4/DMP8 (1 wrong count and 1 ignored tap, then "Inconsistent").
From Cohen's first 17 tries (2026-10-30, lane DMP9): presses scatter about 1.7 frames (85 ms) and about 7-15% of counts are misread. The scatter is widened automatically when a read scatters more.
Measured from the moment the eye opens after the last blink. The same reaction is assumed for 3 and 4 (Cohen); if your 3 presses come later (waiting for a 4th blink that doesn't come), the extra goes here. Measure both with "Measure my 3/4 press", or let a read teach it (the page offers a value after it has fitted 4+ of each). A wrong value costs flutters, not a wrong window (sims: pipeline/dmp8/).
200 = a typical reaction; measure yours (above).
The real NTSC console rate is not measured yet (Q-DMP3-3). A wrong rate makes the search give up ("inconsistent"); it doesn't make it press wrong. PAL ≈ 16.67 (untested).
Off by default: in DMP3's sims, a wrong rate already breaks the search before a fit can help. The fitted value is shown once a window is found.
Flutters after the candidates first fit. REV1: 2 gave a wrong window in 8 of 50 runs with one bad input; 5 gave 0.
DMP8: with taps ±3-4 frames, 2 of about 1500 simulated reads locked onto a wrong state after an outlier had dropped the true one. ±2-frame taps (RMS about 1.4) rarely trigger this, so it costs careful runners nothing.
The early margin grows by this share of the wait (0.3% of 30 s = 1.8 frames). Only the early side: the console can't run faster than 20 fps (the VI rate is at most 60 Hz and lag frames only slow it), so a clock error always makes the press early.
DMP7 (from T5's 7 ares runs): 12 grass + 38 per Navi sparkle + about 0.06 per frame of the gap (Link's and Dampé's own blinks, Navi's speed rolls). Navi's sparkle count is not fixed (15-20 on ares when you start after her second trail), so the page searches 8-30 sparkles with the small part set from the time between your last first-person tap and your first box tap, then 0-110 sparkles. "Fixed" is DMP5's old centre ± spread below.
After at least 4 box flutters fit. 3 gave a wrong window in 9 of 200 sims where the setup's count was off; 5 gave 0 of 200.
0 / 0 / 0 = DMP1's ares-validated strict matching.
Off by default: if you know the expected count, an unsure count tends to follow it, and that would hide exactly the mistake the check is there to catch. The count is shown after you enter yours.

Model (decomp 05e9046, measured on ares): per frame in the Yes/No box, Link's blink timer (FaceChange_UpdateBlinking(20, 80, 6), z_player.c:11793) runs before Dampé's (EnTk_UpdateEyes, z_en_tk.c:207-220: 2 random numbers at the end of each flutter, the wait 30 + 30u frames and 4 blinks if u > 0.5). The roll comes 34 frames after Yes, after 4 more random numbers for the dig dust, and gives the Heart Piece when the next random number is at least 0.9 (z_en_tk.c:417). Only the low 23 bits of the state matter on the N64 (qrand.c:106), so the calculator tries all 8,388,608 states × 99 blink phases. Sources: pipeline/dmp1/calc.py (model, robust_step), pipeline/dmp3/scan3.c and pipeline/dmp4/scan4.c (tolerant matching).

What changed (DMP9 likelihood solver, 2026-10-31; earlier: DMP8 one key, DMP5/DMP7 hybrid, DMP4)

2026-10-31, DMP9: likelihood solver (new default). Cohen's first 17 tries showed the strict solver ending "Inconsistent" on 9 of the 11 long reads: a second misread 3/4 emptied it, while his timing was good (about ±1.7 frames). Now every state is ranked by how well it explains all presses: timing scatter, a misread count costs a little (12 % by default), one outlier press costs more, and the page locks only when every state within a safe margin of the best agrees on the Heart Piece moment (and the rest hold less than 0.2 % of the weight, 3 flutters in a row). One-key presses are matched to each state's own flutter end, so a misread no longer shifts the timing by 3 frames. It never dead-ends: when nothing fits, the oldest presses age out and the read goes on. The 3 extra default is now 60 ms (Cohen's 3 presses came about 1.2 frames later than his 4 presses). New input option: one button, pressed when the blinks start and again when they end. Strict matching stays under Settings → Solver. Details: pipeline/dmp9/, write-up section 7.

2026-10-30, DMP8: one key per flutter (new default). Press 3 or 4 once, as soon as the flutter is over. That press is both the timing and the count: the page subtracts the flutter's length (the eye reopens after the last blink 8 frames after the start for 3 blinks, 11 for 4) and one reaction (default 200 ms, the same for 3 and 4, plus an optional "3 extra"). A press within 1 s replaces the last one, so 3-then-4 corrects itself. New: "Measure my 3/4 press" (a drawn eye flutters like Dampé's); the page offers a learned 3 extra after a read; 3 more confirmations when presses scatter (RMS above 1.6 frames); a per-try log (H / N / X to mark, Export log); in one-key mode the game's keys (Space, Enter, arrows, W/A/S/D, J, Q, E, P, Shift) do nothing here. Sims (150 runs per row): one key at ±2 frames = two inputs at ±2 (140 HP, 0 wrong, 10 gave up; 15 flutters); with the extra confirmations 0 wrong in 750 runs up to ±4 frames and with a 3-vs-4 offset of −2 or +3 frames. The old Space-then-count mode is under Timing → Input. Details: pipeline/dmp8/, write-up section 7.

DMP5/DMP7: hybrid read mode (simulation and replayed ares logs; the DMP7 rule is not run live on ares yet). T5 tested a first-person-only read on ares and it fails: the C-up read itself is clean, but leaving first person respawns a grass ring (12 random numbers) and the talk makes Navi fly over and sparkle (about 390 more), between Dampé's renewals. The hybrid mode keeps the first-person read (until 64 or fewer states fit, plus 3 confirmations), then re-syncs with about 10 flutters in the Yes/No box (a plain box read needs 14-17). In 350 simulated runs it gave 0 wrong windows, but it takes longer overall (about 80-90 s against 55-60 s): use it only if the box eyes are too small to read reliably. It searches each first-person candidate × the number of random numbers used in between × Link's blink phase. DMP7 (T5's 7 ares runs): that number is 12 grass + 38 per Navi sparkle + about 0.06 per frame, and Navi's sparkle count varies (her dash when you leave first person), so the page searches a 38-step lattice; start the box read only after Navi's second trail (3 s after the Yes/No arrow). Details: pipeline/dmp5/notes.md, GLITCH_HYPOTHESES.md Q-DMP7-1.

After REV1's review (pipeline/rev1/review.md): one bad input used to give a confident wrong window in about 1 run in 5-8. Now one bad input costs time instead: in 150 simulated runs (clean taps, and one flipped count, bad tap, missed flutter, 19.94 fps console or 6-frame-late press), 0 wrong windows against 10 for the previous version. Details: pipeline/dmp4/notes.md.

  • Later commit. The window appears only after 5 more flutters once the candidates first fit (was 2). The number is a setting.
  • Predictions. While confirming, the page shows when the next flutter should come. After a window is shown, every further tap is checked against the prediction. If one disagrees, the window is dropped and confirmation starts over.
  • Residual check, "1 tap ignored", "inconsistent". If no state explains every tap, the page tries once more ignoring one tap and says which one it ignored. It then needs 5 fresh confirmations. If that fails too, it says inconsistent: restart. If even the best-fitting state leaves the taps more scattered than human noise (RMS above 2.5 frames), there is no window until more taps settle it.
  • Timing. Tap delay now defaults to 200 ms (a typical reaction) instead of 0. There is a new display-lag setting (default 3 frames). The press margin is asymmetric (4 frames early, 8 late), because late presses are the common error. The early side also grows by 0.3% of the wait: a console can only run slower than 20 fps, so a clock error always makes the press early. Beeps are scheduled on the audio clock with the device's output latency subtracted. There is a new press calibration (tap along with a metronome), an fps choice (20 / 19.94 / custom) and an optional fps fit.
  • Fixes. The PAL note was wrong: PAL uses the same 23-bit RNG, so the model applies (untested). The setup rules now include REV1's and DMP3's lists. ?mute=1 silences all sound.
  • Hidden test. The replay test now also runs REV1's stress scenarios through the live decision code.
self-test · replay of the 8 ares trials + stress

A: the recorded noisy taps (pipeline/dmp1/runs/validate_ntsc-1.2.jsonl) with strict matching vs calc.py, every prefix. A2: tolerant matching vs DMP3's scan3.c. A3: "1 tap ignored" matching vs scan4.c. H: the DMP5 hybrid core vs calc.py (T5's ares take 3, and 4 synthetic box reads). B: REV1's stress scenarios through the live decision code, page settings vs DMP2's old defaults. Add #replay=25 to the address for 25 runs per scenario (default 6). Always silent.