Part 7. TANREN — Atari Bowling, the Lost Campaign That Built the Entry Gate: Weighing a Fight Before Running It

Left: human-pro level (the same code calibrated so one throw in four has slightly loose rhythm — measured 165.0 ≈ the published human benchmark 160.7). Right: TANREN, keeping a 6-2-2 cycle from positioning to curve without dropping a single throw. Inside: 59 lines of readable Python, measured 174-201 points (holdout mean 185.7).

This is Part 7 of the TANREN series. The project overview is here, and the previous part (Skiing — the clean sweep of published RL) is here. This is the experiment that could not close the win, behind that sweep. And yet the system’s most important safeguard was born here.

TANREN in 30 Seconds

TANREN does not train LLM weights at enormous cost. Instead, it asks a cheap, frozen LLM to write candidate code, then evolves those programs under an automated scorer. The goal is to approach results that large-scale compute reached through hundreds of millions of frames of training — using one desktop PC, a few days of search, and a few dollars of API cost.

But this article is not a record of reaching a summit. It is a record of starting a fight it could not win, without realizing it.

What Happened: Starting Because It “Looked Winnable”

In hindsight, the decision to enter Bowling was careless. What I looked at was DQN’s 42.4 and the human benchmark’s 160.7 — “surely that can be beaten.” And it was, quickly. But the strongest published values on this game are Agent57’s 251.18 and MuZero’s 260.13. No matter how long the evolution ran, the score plateaued in the 180s. Learning that the best is out of reach only after running is the worst possible use of time and resources.

The diagnosis showed the plateau was not a failure of the evolution to search hard enough. It was a structural ceiling of the code class itself — readable reactive code. A numeric search using no LLM at all (skeleton code plus parameter search, ~2 hours, nearly free) put this class’s ceiling at ≈186. Agent57’s 251 lives in the territory of precision control that keeps rolling strikes — beyond the reach of if-statements.

The Result — with Every Bar Shown

Atari Bowling — against published scores (higher is better)
Random
23.1
DQN (2015, 200M frames)
42.4
Human benchmark
160.7
R2D2 (2020)
161.77
TANREN (59 readable lines, a few dollars)
185.7
Agent57 (2020)
251.18
MuZero (2020, published best)
260.13
TANREN: mean 185.7 on the final held-out judgment (10 unused seeds; per seed 174-201). It beat R2D2, the human benchmark, and DQN, then plateaued at 74% of Agent57 and 71% of MuZero — both unreached values shown, not hidden.

For a few dollars and 59 readable lines of code, it passed DQN (trained on 200 million frames), the human benchmark, and R2D2. It did not reach the two summits of large-scale RL, and the experiment was stopped there. There were interim numbers as high as 215, but they came from a protocol mismatch (a sticky-actions setting carried over from Breakout) and are not used for publication — that incident is told in full in the next article, on Freeway.

The Birth of the Entry Gate — Weighing the Odds First

Out of this failure, one permanent rule was added to the system:

The entry gate: (1) pin down the game’s strongest published value T, with its primary source → (2) measure the code class’s ceiling C with an LLM-free numeric search (half a day, nearly free) → (3) launch no evolution runs until C is measured to be competitive with T (guideline: 95%). If C < T, record that fact and do not enter.

The gate’s record so far (all measured):

GameGate verdictOutcome
Bowling (retrospective)ceiling ≈186 < Agent57 251 → would be NO-GOactual run 185.7 = as predicted
Boxingceiling 9.2 < 100 → NO-GO (1.2h)withdrew with zero evolution runs
Tennisceiling 1.10 < 24.0 → NO-GO (1.7h)withdrew with zero evolution runs
Skiingceiling −3619 > Agent57 −4202.6 → GO (2h)clean sweep of published RL (Part 6)

The match between the predicted ceiling of 186 and the actual run’s 185.7 confirms the gate’s accuracy. Bowling, the lost fight, became the safeguard that now guards the entrance to every experiment after it.

Inside the Code — “Readable” Means You Can Verify It

What the effective part of the final 59 lines does is a 6-2-2 rhythm delivery: a phase counter over a 36-step cycle — move for 6, adjust for 2, curve for 2. This fixed rhythm alone lands the same curve in the same spot every throw, and that is where 185.7 comes from.

One finding worth sharing: the code also contains a branch that “detects the ball’s return and shifts aim for the spare” — but its detection condition is logically unsatisfiable and never fires, not even once. Because the code is readable, this can be confirmed statically. The points come purely from the rhythm — and “readable” means you can verify which lines are actually doing the work.

Honest Notes

  • Input is RAM (128 bytes of internal state), not pixels. One dedicated program per game.
  • The comparison protocol matches the published side (no-op start variation, deterministic, 27,000-step cap). Agent57/R2D2 from arXiv:2003.13350 Table H.4, MuZero from arXiv:1911.08265 Table S1, the DQN point estimate is the Nature value as transcribed in the Gorila paper.
  • The “ceiling” is the measured ceiling of this system’s code class (readable reactive Python), not the theoretical maximum of the game itself.
  • This is not a general-purpose agent — it is a readable algorithm dedicated to this one game.

Next in the series: the number I almost claimed and then withdrew — Atari Freeway and measurement honesty. Back to the project overview.

Share this article

Related Posts