Psi Lab

The app

Pulse

There is no list of future marks. When you tap a cell, the clock at that instant names one cell on the grid. A hit is when those two are the same. Wait until a place feels like now, then tap.

Tap a cell when it feels like now.

A curve of the last 50 will appear here.

Play a few rounds, then see how you compare with chance.

FAQ

How is this different from Beacon?

Beacon hides a mark from a stream locked at the start of the session. Pulse names the mark at the instant you tap. There is no Right or Wrong switch: you are aiming at the cell the clock will name, not sensing that a place is empty.

How is the mark chosen?

A session salt is chosen when you start. Each tap takes the high-resolution clock at that moment, mixes it with the salt, and maps the result onto the grid. The same salt and time always name the same cell. A delay too small to notice can still name a different one. Copy proof saves those numbers so they can be checked later.

Infrequently asked questions

How would a person recompute pulseMark?

Copy proof puts JSON on the clipboard: the salt, the grid, and one row per tap with the clock time (timeMs), the cell you tapped (guess), and the cell the formula named (mark). Run the same function Pulse uses, in JavaScript. The browser console is enough.

function pulseMark(salt, timeMs, numCells) {
  const ticks = Math.floor(timeMs * 1000) >>> 0;
  let hash = (salt >>> 0) ^ ticks;
  hash = Math.imul(hash ^ (hash >>> 16), 0x7feb352d);
  hash = Math.imul(hash ^ (hash >>> 15), 0x846ca68b);
  hash = (hash ^ (hash >>> 16)) >>> 0;
  return (hash % numCells) + 1;
}

const proof = /* paste the copied JSON here */;
const salt = Number.parseInt(proof.salt, 16);
const numCells = proof.grid === "4x4" ? 16 : 9;

for (const tap of proof.taps) {
  const named = pulseMark(salt, tap.timeMs, numCells);
  console.log(named === tap.mark ? "ok" : "mismatch", named, tap.mark);
}

If every named cell matches mark, the log matches the formula. That proves the named cell was a function of salt and time, not of which square you touched. It does not prove you could not have waited to click. Use JavaScript for this: the >>> and Math.imul steps are 32-bit integer operations, and a spreadsheet can drift.