Reflex · arena

Fast enough to play live.

Every lane plays the same seeded game and picks every move itself — nothing scripted, bad picks get played. No install needed: the Reflex boards run in this tab.

TL;DR loading the measured results from the benchmark…
laya (Python) — laya (Rust) — Reflex · modelless — raw — Reflex · rulebook (tab) — Reflex · rulebook (edge) — checking for a local engine…

The final result — no need to wait for the replays

loading the recorded games…

Seed 607, re-scored from each lane's recorded moves. ✕ topped out · ● still alive when recording stopped. Latency is log scale (each grid step = 10×).

candidate spot — brighter = higher P(clean) · chosen spot, in the piece's own color
laya lane (Python) · torch referencerec — the original open-weights reference · recorded offline, never shippedSCORE0000LINES000
pieces 0 · decisions 0 · p50 — ms · errors 0
SOURCE—
STATE SENT—
QUESTION—
ANSWER—
ACTION—
TIMING—
laya lane (Rust) · model-basedrec — our Rust port of the same weights · reads a sentence per spotSCORE0000LINES000
pieces 0 · decisions 0 · p50 — ms · errors 0
SOURCE—
STATE SENT—
QUESTION—
ANSWER—
ACTION—
TIMING—
Reflex · modellessrec — corpus-fitted heads · live in this tab (WebAssembly) or your engineSCORE0000LINES000
pieces 0 · decisions 0 · p50 — ms · errors 0
SOURCE—
STATE SENT—
QUESTION—
ANSWER—
ACTION—
TIMING—
Reflex · rulebook · in this tabin-tab — rulebook search, no model · plans 3 pieces aheadSCORE0000LINES000
pieces 0 · decisions 0 · p50 — ms · errors 0
SOURCE—
STATE SENT—
QUESTION—
ANSWER—
ACTION—
TIMING—
Reflex · rulebook · Cloudflare edgeedge — the same engine bytes on a Worker · capsule = live round tripSCORE0000LINES000
pieces 0 · decisions 0 · p50 — ms · errors 0
SOURCE—
STATE SENT—
QUESTION—
ANSWER—
ACTION—
TIMING—
raw baseline · heads skippedrec — the engine without fitted heads · abstains play random — the floorSCORE0000LINES000
pieces 0 · decisions 0 · p50 — ms · errors 0
SOURCE—
STATE SENT—
QUESTION—
ANSWER—
ACTION—
TIMING—

How each lane picks a spot

Same game for everyone (seeded 7-bag, hard drop, guideline scoring) — only the pick differs. Source: tetris_lane_flows.md. Press play on any figure to walk one recorded turn of the seed-607 game — every walk's input and output is replayed from the recorded games, never typed.

The laya lane, numbered along the path in three lanes. 1 the turn arrives — board plus falling piece from the seeded 7-bag. 2 list every spot — each rotation in each column. 3 say it in words — one sentence per spot. 4 the model reads — a laya forward pass per sentence. 5 P(clean) per spot. 6 play the highest.
laya (Rust / Python) — one forward pass per spot sentence; sees only the falling piece.
Step by step: what goes in and what comes out
  1. 1 · The turn arrives

    One turn of the recorded seed-607 game: the board, the falling piece, and the nine landing spots the harness will judge. Every lane in the arena plays this same stream — what differs is only how the pick is made.

    IN · the recorded opening turn

    {
      "grammar": "laya-tetris-v3",
      "question": "Does the stack look clean?",
      "state": "The stack stands low and the surface is mostly flat. There are no holes under the blocks. The square piece is falling.",
      "piece": "O",
      "board": [
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        ".........."
      ],
      "landing_spots": 9
    }

    recorded from the laya (Rust) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_laya · scripts/record_demo_walks.mjs · the opening turn (turn 0)

  2. 2 · List every spot

    The harness enumerates every legal landing: each rotation of the piece in each column, hard-dropped. For the opening O piece that is nine distinct futures — the count rides the recorded turn above.

  3. 3 · Say it in words

    Each spot becomes one English sentence — the holes it leaves, how it meets the surface, where it lands, how tall the stack stands. The words are pinned by the grammar; every lane reads the same ones.

  4. 4 · The model reads

    The laya model runs one forward pass per sentence. Rust is the served port; Python is the torch reference it is measured against — the same open weights either way.

  5. 5 · P(clean) per spot

    Every landing spot comes back with a cleanliness probability. The recorded opening turn's nine answers are below — watch how flat they are on an empty board: the model is nearly indifferent, and small differences decide the pick.

    OUT · P(clean) per spot · the pick

    {
      "p_clean_per_spot": [0.6832, 0.6832, 0.6888, 0.6888, 0.691, 0.691, 0.6379, 0.6379, 0.6581],
      "pick": 4
    }

    recorded from the laya (Rust) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_laya · scripts/record_demo_walks.mjs · the opening turn's answer

  6. 6 · Play the highest

    The highest-probability spot is played and the piece drops; the next turn starts the loop again. One model forward per spot is the whole cost of this lane.

    OUT · the played spot

    {
      "p_clean_per_spot": [0.6832, 0.6832, 0.6888, 0.6888, 0.691, 0.691, 0.6379, 0.6379, 0.6581],
      "pick": 4
    }

    recorded from the laya (Rust) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_laya · scripts/record_demo_walks.mjs · the opening turn's answer

The Reflex modelless lane, numbered along the path in three lanes. 1 the same sentence laya reads, unchanged. 2 decode to features — holes, flat, height, side, clears. 3 a tiny linear head fitted on laya's recorded answers. 4 play the highest — microseconds in your tab.
Reflex · modelless — laya's recorded answers distilled into a tiny linear head that runs in this tab.
Step by step: what goes in and what comes out
  1. 1 · The same sentence

    The distillation changes nothing about the input: the very same recorded opening turn the laya lane reads. That is the point — same question, a different (much cheaper) answerer.

    IN · the same recorded opening turn

    {
      "grammar": "laya-tetris-v3",
      "question": "Does the stack look clean?",
      "state": "The stack stands low and the surface is mostly flat. There are no holes under the blocks. The square piece is falling.",
      "piece": "O",
      "board": [
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        ".........."
      ],
      "landing_spots": 9
    }

    recorded from the KatGPT modelless lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_head · scripts/record_demo_walks.mjs · the opening turn (turn 0)

  2. 2 · Decode to features

    The sentence is decoded back into the board features it came from: holes left, how flat the surface sits, stack height, which side it lands on, lines cleared. A handful of numbers — no words reach the head.

  3. 3 · A tiny linear head

    A small linear head, fitted offline on laya's recorded answers, scores the features. It imitates laya — 44 of 120 picks agree on the pinned corpus — so it plays like laya, only about a hundred-thousand times faster.

    OUT · the head's answer to the same turn

    {
      "p_clean_per_spot": [0.5325405, 0.5325405, 0.534729, 0.534729, 0.53691745, 0.53691745, 0.5391059, 0.5391059, 0.54129434],
      "pick": 8
    }

    recorded from the KatGPT modelless lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_head · scripts/record_demo_walks.mjs · the opening turn's answer

  4. 4 · Play the highest

    The top-scoring spot drops. The head runs as WebAssembly in your tab — it is the lane playing live in the arena below, one pick per piece at microsecond cost.

    OUT · the played spot

    {
      "p_clean_per_spot": [0.5325405, 0.5325405, 0.534729, 0.534729, 0.53691745, 0.53691745, 0.5391059, 0.5391059, 0.54129434],
      "pick": 8
    }

    recorded from the KatGPT modelless lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_head · scripts/record_demo_walks.mjs · the opening turn's answer

The Reflex rulebook search, numbered along the path in two lanes. 1 the piece in play — every legal landing spot. 2 the preview piece chained, best six kept. 3 the unknown third piece — branch over every piece left in the bag. 4 score end boards with the strategy rulebook. 5 average over the unknown, pick the sturdiest plan. 6 play the first move, then re-plan from scratch.
Reflex · rulebook — no model: plans three pieces ahead, averaging the unknown third over the bag.
Step by step: what goes in and what comes out
  1. 1 · Look ahead — the falling piece

    The rulebook never reacts one piece at a time. It starts by listing every legal landing spot for the piece in play — every rotation in every column — and treats each one as a possible future board.

    IN · the recorded seed-607 clear turn

    {
      "lane": "Reflex · rulebook (the search champion)",
      "genome_id": "68cae9d382014662",
      "piece": "I",
      "board": [
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..####....",
        "########..",
        "#########.",
        "#########.",
        "#########.",
        "#########."
      ],
      "landing_spots": 17,
      "depth": 3
    }

    recorded from the Reflexer (rulebook search) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_rulebook · katgpt-rs examples/tetris_09_site_walk.rs · turn 32 (the recorded turn with the biggest clear)

  2. 2 · Chain the preview piece

    Each candidate board is paired with every landing spot of the preview piece — and the tree is pruned hard: only the best six boards survive each level, so the search stays tiny instead of exploding.

  3. 3 · Cover the unknown third piece

    The piece after that is not known yet. Rather than gamble on a single guess, the plan plays out every piece the bag could still deal — the search branches over all of them.

  4. 4 · Score every end board

    Each final board is scored by the strategy rulebook — holes, bumpiness, stack height, wells, lines cleared — the instincts of a careful human player, written as numbers.

  5. 5 · Average over the unknown · pick the plan

    A plan is only as good as its worst realistic draw: scores are averaged across the possible third pieces, so a line-clear that needs the I-piece rates low — it usually does not come. The sturdiest plan wins.

    OUT · per-spot scores · the winning plan

    {
      "spot_scores": [0.0677, 0.119, 0.2616, 0.1489, 0.0577, 0.0152, 0.0317, 0.2808, 0.188, 0.2341, 0.2328, 0.2383, 0.2324, 0.2605, 0.1837, 0.2417, 0.5],
      "pick": 16,
      "ms_per_decision": [0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014],
      "scores_note": "sigmoid((v − max v) / std(v)) over the champion's per-option root values (std floor 1e-9) — the pick reads 0.5; a display map, not a probability"
    }

    recorded from the Reflexer (rulebook search) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_rulebook · katgpt-rs examples/tetris_09_site_walk.rs · turn 32's answer (scores are the recorded display map)

  6. 6 · Play the first move — then re-plan

    Only the winning plan's first move is played; the very next piece restarts the whole search from scratch. All of it runs in about a third of a millisecond — a thousand-plus searches would fit inside one 60 Hz frame.

    OUT · the recorded tetris landing

    {
      "lines_cleared": 4,
      "lines_so_far": 12,
      "score_so_far": 1560,
      "pieces_so_far": 33
    }

    recorded from the Reflexer (rulebook search) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_rulebook · katgpt-rs examples/tetris_09_site_walk.rs · after turn 32's pick lands (replayed off the record)

The rulebook's play modes as a cycle. 1 BUILD — nine flat plus one open well, waiting for tetrises. On 3+ covered holes it branches to 2a DOWNSTACK — dig them back out; on a 12+ row stack to 2b SURVIVE — take any line, stay low; both hand back to BUILD when the board recovers.
The rulebook's modes — build for tetrises only while safe; found by self-evolution, not hand-coded.
Step by step: what goes in and what comes out
  1. 1 · BUILD — the default mode

    On a clean, low stack it builds a 9-1 stack: nine columns packed flat plus one open well on the right edge, saving I-pieces to clear four lines at once. The 9-1 shape was self-evolved — nobody hand-coded it; it fell out of the training climb.

    IN · a real recorded build position

    {
      "mode": "BUILD",
      "board": [
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..#..#....",
        "#########.",
        "#########.",
        "#########.",
        "#########.",
        "#########.",
        "#########.",
        "#########.",
        "#########."
      ],
      "covered_holes": 0,
      "stack_height": 9
    }

    recorded from the Reflexer (rulebook search) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_rulebook · katgpt-rs examples/tetris_09_site_walk.rs · turn 271 (the strongest 9-1 build position)

  2. 2a · Trouble #1 — covered holes → DOWNSTACK

    Three or more holes buried under the stack and building stops paying: every new piece makes it worse. The mode flips to DOWNSTACK, which deliberately clears the lines sitting above the holes to dig them back out.

    IN · the most-buried recorded position

    {
      "board": [
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        ".........#",
        "......####",
        "...#######",
        "#.########",
        "#.########",
        "##.###.###",
        "######.##.",
        "######.##.",
        "#########.",
        "#########.",
        "#########.",
        "#########.",
        "#########.",
        "#########."
      ],
      "covered_holes": 12
    }

    recorded from the Reflexer (rulebook search) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_rulebook · katgpt-rs examples/tetris_09_site_walk.rs · turn 62 (the most-buried recorded position)

    OUT · the measured trigger vs the genome's threshold

    {
      "mode": "DOWNSTACK",
      "covered_holes": 12,
      "trigger_at_holes": 3
    }

    recorded from the Reflexer (rulebook search) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_rulebook · katgpt-rs examples/tetris_09_site_walk.rs · counted off turn 62's board; threshold from the recorded genome

  3. 2b · Trouble #2 — tall stack → SURVIVE

    A stack twelve rows high is one bad piece from topping out. SURVIVE takes any line it can and keeps the board low — scoring gives way to staying alive. (Survive wins when both exits fire at once.)

    IN · the tallest recorded position

    {
      "board": [
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        ".........#",
        "........##",
        "....##..##",
        "....######",
        "....######",
        "....######",
        "....##.###",
        "...###.##.",
        "...###.##.",
        "#########.",
        "#########.",
        "#########.",
        "#########.",
        "#########.",
        "#########."
      ],
      "stack_height": 15
    }

    recorded from the Reflexer (rulebook search) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_rulebook · katgpt-rs examples/tetris_09_site_walk.rs · turn 56 (the tallest recorded position)

    OUT · the measured height vs the genome's threshold

    {
      "mode": "SURVIVE",
      "stack_height": 15,
      "trigger_at_rows": 12
    }

    recorded from the Reflexer (rulebook search) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_rulebook · katgpt-rs examples/tetris_09_site_walk.rs · measured off turn 56's board; threshold from the recorded genome

  4. 1 · Recovery — both modes hand back to BUILD

    Holes dug out, or the stack back under twelve — either way the mode returns to BUILD and the cycle starts over. The board is re-read before every single piece, so the switch is never late.

    IN · a real recovered position

    {
      "mode": "BUILD (recovered)",
      "board": [
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "...#......",
        "#.#####...",
        "#######...",
        "########..",
        "#########.",
        "#########."
      ],
      "covered_holes": 0,
      "stack_height": 6
    }

    recorded from the Reflexer (rulebook search) lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_rulebook · katgpt-rs examples/tetris_09_site_walk.rs · turn 80 (holes dug out, stack back under 12)

  5. 1 · 2a · 2b · One search, three weights

    The modes are not three different AIs — it is the same placement search wearing different score weights: self-evolved builder weights while safe, proven survival weights in trouble. That is the whole trick behind the rulebook lane.

The raw baseline, numbered along the path in three lanes with one branch. 1 the same sentence, sent to the bare engine. 2 corpus engine — no fitted heads, nearest corpus neighbours only. In corpus, 3a play the highest; off corpus, 3b abstain — and the abstain plays a labelled random spot, the honest floor.
raw baseline — no fitted heads: it abstains, and the abstain plays a random spot.
Step by step: what goes in and what comes out
  1. 1 · The same sentence

    The same recorded opening turn, sent to the engine with every fitted head removed. Only the corpus remains: nearest-neighbour lookup over what it has literally seen before.

    IN · the same recorded opening turn

    {
      "grammar": "laya-tetris-v3",
      "question": "Does the stack look clean?",
      "state": "The stack stands low and the surface is mostly flat. There are no holes under the blocks. The square piece is falling.",
      "piece": "O",
      "board": [
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        "..........",
        ".........."
      ],
      "landing_spots": 9
    }

    recorded from the raw baseline lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_raw · scripts/record_demo_walks.mjs · the opening turn (turn 0)

  2. 2 · Corpus engine

    With no heads, the engine can only compare the sentence against its corpus. The spot sentences of a real game are almost all new — so this branch is the one the recorded raw game took, five hundred and fifteen times in a row.

  3. 3a · In corpus → play the highest

    When a sentence lands close to something the corpus holds, the engine answers like laya would and the highest-probability neighbour wins. In the whole recorded raw game this path never fired — that honesty is what makes it the floor.

  4. 3b · Off corpus → abstain, play random

    Every outcome comes back null — the engine abstains rather than guess. The abstain plays a random legal spot from a separate seeded stream, labelled as random in the replay so nothing pretends to be a decision.

    OUT · every P(clean) null · a recorded random pick

    {
      "p_clean_per_spot": [
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null
      ],
      "pick": 6,
      "abstained": true,
      "policy": "argmax, abstain → Rng(seed+1) random spot"
    }

    recorded from the raw baseline lane, seed 607, 2026-09-25, arena/demo_oracle.json _meta.sources.tetris_raw · scripts/record_demo_walks.mjs · the opening turn's answer

laya lane (Python) · torch referencePIPES000CRASHES000
STATE SENT—
ANSWER—
ACTION—
laya lane (Rust) · model-basedPIPES000CRASHES000
STATE SENT—
ANSWER—
ACTION—
Reflex · modellessPIPES000CRASHES000
STATE SENT—
ANSWER—
ACTION—
raw baseline · heads skippedPIPES000CRASHES000
STATE SENT—
ANSWER—
ACTION—
Why ask what it sees, not what to do?

The game writes where the bird is — “The bird is a little below the gap center, falling. The gap is narrow. The pipe is just ahead.” — and asks one typed question per action: “Will the bird pass through the gap cleanly?” over the frozen v2 option sentences. The bird does the action with the higher P(clean). Asked which way to move, decision models answer backwards; asked where things are, they read cleanly.

laya lane (Python) · torch referenceSTEPS000CRASHES000
STATE SENT—
ANSWER—
ACTION—
laya lane (Rust) · model-basedSTEPS000CRASHES000
STATE SENT—
ANSWER—
ACTION—
Reflex · modellessSTEPS000CRASHES000
STATE SENT—
ANSWER—
ACTION—
raw baseline · heads skippedSTEPS000CRASHES000
STATE SENT—
ANSWER—
ACTION—
Does wording matter?

A lot. Each barrier row is described in plain English and the engine answers “Is this lane safe to run?” per lane; the runner takes the highest P(safe). Even the noun moves the answer (“a barrier” vs “a train” for the same lane), so the grammar pins ONE noun per obstacle class — and the fitted head absorbs the rest.

Notes & sources

What's live, what's recorded, and how it is checked
  • With your engine connected, every board except laya (Python) plays live on your machine; the page reaches only 127.0.0.1:7331.
  • Without an engine, Reflex · modelless plays live in-tab from compiled WebAssembly heads, each parity-checked against the recorded engine play before any board moves. arena_head_parity.mjs — Tetris bit-exact, Flappy and three-lanes pinned to their published agreement
  • Reflex · rulebook runs the public reflexer engine as WebAssembly — in this tab and on a Cloudflare Worker (stateless, no storage). Both replay the recorded walk pick-for-pick. reflexer_parity.mjs gist-rs/riir-reflexer
  • Recorded boards (laya, raw, and any lane without its host) replay committed runs through the same wire — labelled, never mixed with live results. demo_oracle.json
  • laya (Rust) is our Rust port of the open-weights model, G5-parity-gated against its reference checkpoints; no Python ships anywhere. laya (Python) is that reference, recorded offline for comparison only. laya_riir_parity.rs laya
  • The TL;DR above is computed from data/bench.json on load — never typed. arena_tldr.js