RL — Player of Games
AlphaGo came out right around the time I left Uber. I was so excited about AI when I joined Numerai, but honestly I knew very little about deep learning. My interview day was actually a company party (strange, right?). There was an ex-DeepMind researcher there, and I basically asked him: why can't we just do what AlphaZero did, and we'll have the best returns? He looked at me like I was stupid and crazy.
This page is the long answer to why.
I should be honest about games too. I love playing them, but I'm not that great. Not compared to the pros, not even compared to my friends. If I'm ever going to be good at a game, it's going to be through AI. And watching AI beat games never gets old for me. AlphaZero. The OpenAI Dota team. AlphaStar. Games have always been the dream path of RL.
OpenAI's hide and seek video was seminal for me too. But I saw it too early. I didn't yet understand what RL was, what deep learning was, what a neural net even is. I understand it now. Getting there is what the rest of this page is about.
The project is named after my favorite book.
“It’s insurance. You heard of that? No? Never mind. It’s like gambling in reverse.” — Iain M. Banks
The books
In 2023 I was on parental leave and went through Karpathy's Zero to Hero course. My notes are here. At the same time I was reading Sutton & Barto. The first real exercise in the book is tic-tac-toe, so I wrote it: a tabular TD learner playing against an imperfect opponent.
I also watched all of Steve Brunton's RL lectures, though I didn't take detailed notes. Honestly the math was a bit beyond me, and I had a young baby 😅
And I kept watching people on the internet make AI beat their games.
Somewhere in here I started investigating drone racing, which pulled me into a completely different hole: robotics and hardware. ALOHA, Physical Intelligence, the Tesla Bot, 1X. That hole leads out of software entirely, and it's where I landed. Today I build fabs.
One more thing from that year. At a party during leave I ended up in a corner with two people: a very senior, very celebrated AI person, and a peer I really respect. I asked the group: what are we most excited about in AI? I said RL. My peer said robotics. The elder said LLMs, applied inside applications — he believed the embedded agent within each application would win. I believed the opposite: increasing returns to a single, all-powerful agent that acts on your behalf, instead of me having to talk to your app's support agent. And on RL he didn't hesitate. Dude, nobody cares about RL anymore. It's all LLMs now.
I wasn't sure if I was right. It really did feel like RL winter. But I bet RL.
By hand
Then I wanted to do it myself. I gave myself one rule: no looking up answers. Read the environment, think it through, write the code.
Mountain car stopped me. The reward is −1 every step until you reach the flag, and the episode cuts off at 200 steps. Until you reach the flag once, every policy scores exactly −200. There is nothing to learn from.
I got around this in two ways, and I felt bad about both. I added a +200 bonus for reaching the flag, which is just reward shaping. And I hand-coded a momentum rule (push in the direction you're already moving) to feed successful episodes into the replay buffer. That rule solves the game by itself, so what exactly is the agent learning?
Even the observation bothered me. Position and velocity are features somebody already extracted for me. So really it was the same problem at three depths: the reward, the data, and the representation, all with human knowledge smuggled in. The learning wasn't doing the work.
The DQN never reached the flag. Not once in 500 episodes. Exactly −200.00 every time. Going back this year I finally found out why: target = reward + gamma + max_q. A plus where a times should be. Also lr=1 on Adam. On a sparse reward, a broken learner and a slow learner produce identical output, so the bug was invisible.
So the tic-tac-toe learner from the book worked, my from-scratch DQN didn't, and I wasn't willing to fake the difference. Then a new job started, and this all went dormant.
LLMs play the games
When I came back to it at the end of 2025, LLMs had happened. I tried three things.
First, I had a local Qwen model literally pick the actions, one observation at a time. I did this on purpose as a “this is stupid” baseline. It's the wrong way to use an LLM and I wanted to see it fail for myself.
Second, I built an OaK agent after Sutton's architecture. Honestly, I vibe-coded it. It ran, but I didn't understand it deeply enough to be interested in my own code, which felt like a signal to read more before copying more.
Third, I built a harness for League of Legends. Screen capture, input control, the works. Then I researched the anticheat and got convinced it was never getting past it. That dead-end sent me down a computer use research hole instead.
The insight that finally stuck came mostly from my day job, watching agents work all day: the model shouldn't act, it should write code that acts. Not think, then act. Think, then write code.
Autoresearch
Karpathy released autoresearch: an agent edits train.py overnight on a 5-minute training budget, keeps what improves the metric, discards what doesn't. I ported it to MLX so it could run on my Mac.
The interesting part is that you don't edit the Python anymore. You edit program.md, the instructions. The research process itself becomes the thing you iterate on.
What learning actually costs
I wanted Atari next. So I wrote a PPO from scratch in one readable file, plus a loop where Claude proposes the next experiment's hyperparameters with a hypothesis. And for calibration, I ran the canonical SB3 baseline.
The baseline beats Breakout: 33.85 mean reward, above human level. It needs 40.5 million environment steps to get there. Learning works. It just costs 40 million steps.
The rematch
The 2024 environments were still unbeaten, and that bothered me more than it should have. So: player-of-games. The agent doesn't play moves anymore. It writes solution.py. I write instructions.md and the grader. The grader trains the agent's code from a pristine copy under a wall-clock budget and scores it on 100 held-out seeds. No pretrained weights, no cached checkpoints. The same rule I gave myself in 2024, except now it's enforced by code.
All twelve classic control games fell in 13 days. Mountain car took one attempt: −99.08 against a −110 threshold, inside a 60-second budget. It did it by reading the physics out of gymnasium's source and running value iteration on the exact dynamics. My 2024 discomfort, inverted. Maximum prior, zero gradients, zero guilt. And completely legal under rules I wrote.
| solved game | best | threshold | attempts | best attempt, from results.tsv |
|---|---|---|---|---|
| cartpole | 499.98 | 475 | 2 | robustness gate: only trust theta with perfect min over 30… |
| mountaincar | -99.08 | -110 | 1 | model-based value iteration (GRID=900), 1-step lookahead +… |
| mountaincar_continuous | 97.097 | 90 | 3 | restrict candidates to failure-free band {0.4,0.45,0.5}; p… |
| pendulum | -134.285 | -200 | 7 | grid768 VI + dense 301-action policy lookahead; +0.2 over … |
| acrobot | -81.94 | -100 | 3 | larger CEM pop(32)/elite(8)/8 seeds per gen; marginal gain… |
| lunarlander | 247.573 | 200 | 2 | Double DQN MLP128x2, soft target, best-snapshot; 91% eps>=… |
| lunarlander_continuous | 273.958 | 200 | 4 | Double DQN on 3x3 (main x side) action grid; reuse of disc… |
| bipedal_walker | 303.95 | 300 | 11 | N=24/b=12: better gradient -> better linear optimum, SOLVE… |
| car_racing | 918.44 | 900 | 11 | v_max 16->18: speedometer caps at 16 but car goes faster; … |
| frozenlake | 0.74 | 0.7 | 1 | model-based VI: explore to learn P/R, value iteration for … |
| taxi | 7.9 | 7 | 2 | exact deterministic model by probing all 500 states x 6 ac… |
| blackjack | -0.015 | -0.05 | 3 | exact model-based VI from known rules; deterministic optim… |
| atari_pong | 10.9 | 0 | 13 | carry reflected vy across y-bounce seeds fit; fixes blind-… |
| atari_freeway | 27.7 | 15 | 4 | reactive dodger ahead=11 hw=7 thr=0; NOOP when colorful ca… |
Then the wall. Two out of 104 Atari games. Where you can't read the mechanism out of the pixels, the scripted-controller strategy dies. And the agent never switched to learning.
| unsolved (most attempted) | attempts | best | best attempt, from results.tsv |
|---|---|---|---|
| atari_enduro | 19 | 158.7 | dodge hysteresis: hold committed dead-ahead side vs frame … |
| atari_breakout | 17 | 24.3 | loss-classifier + hold-during-bricks + serve delay 20; min… |
| atari_phoenix | 16 | 6519 | boss bomb-dodge hw 7->8 (interacts w/ loose detect); +774 |
| atari_gopher | 15 | 16864 | ALIGN 8->5 with velocity-lead active (lead positions preci… |
| atari_turmoil | 12 | 1103.5 | band-width 7..13 identical (enemies within +-7 of lane cen… |
| atari_galaxian | 10 | 2207 | EARLY_R0 130->129; seed7 1840->2170; mean 2174->2207. Turn… |
| atari_venture | 9 | 600 | alternate macro A(R40,L64) and B(R48,L72) across room entr… |
| atari_journey_escape | 8 | -700 | aggressive UP-accel (thr=3.0): UP unless own-column hazard… |
The thread
2024: a network learns the policy. 2025: the LLM is the policy. March 2026: the LLM runs the experiments. June: it proposes them. July: it writes the solver. Every project moves the model one level up the stack.
Is this recursive self-improvement? No. I'm still the outer loop. My own README says so: instructions.md is “the spec — YOU edit this.” Nothing improves the improver yet.
But I think I finally understand the look that researcher gave me at the party. AlphaZero needs a perfect simulator, fixed rules, and a game you can self-play a billion times. Markets have none of those. Games have all of them. That's why games are the dream path of RL, and why they keep pulling me back.
And the bet from that party? The scoreboard is funny. My peer said robotics, and that's where I ended up working. The elder said LLM agents inside applications, and those agents built everything on this page. And somehow RL is back. Dwarkesh had Sutton on. Coding agents, the math results, RLVR. The entire industry is pivoting into RL wrapped around LLMs. Nobody cares about RL anymore, right?