·Python · PyTorch · ViZDoom · CUDA
Deep RL plays Doom
A from-scratch PPO agent that learns to play Doom from raw pixels — and Doom you can play yourself.
?
The questions
- Can a neural network, seeing only the screen, learn to play Doom well — from nothing but a reward signal?
- And can it learn a whole level? Not a scenario arena — E1M1, the opening map of Knee-Deep in the Dead, spawn to exit switch.
▶
The agents playing
Three agents, one from-scratch PPO, the same pixels-in reward-out setup — but very different jobs. One holds its ground; one has to move; the last has to find its way out of a whole level.
◇
Inside the build
Each stage of the calculation. Click one to expand its full write-up and validation figure.
01the environment — pixels in, actions out
02parallel environments — feeding the GPU
03the policy network — a convolutional actor-critic
04PPO — the learning algorithm
05training & recording — watching it learn
06a whole level — why E1M1 is a different problem
07the reverse curriculum — teaching the last mile first
08keeping the policy — the run that solved it, and nearly lost it
◇
Figures
Click any figure to enlarge. Use ← → to move through the set.
◇
What it shows
- Yes — with nothing but pixels and a reward signal, PPO learns a genuinely competent Doom policy. The learning curve is the clean, monotonic climb you hope for, plateauing near return 11 after about a million steps.
- The engineering matters as much as the algorithm. The single biggest lever here was not a hyperparameter but realizing ViZDoom releases the GIL, so the environments could be stepped in parallel threads for a 10× throughput win — the difference between a feasible run and a two-day one.
- The same agent, two very different skills. A turret that learns to hold ground and an explorer that learns to navigate and fight down a corridor come out of the identical PPO — the difference is only the action set and reward. And because ViZDoom exposes the agent’s position, the explorer’s learning can be watched in space: early paths die at the spawn, later ones push all the way to the exit.
- Written from scratch — the CNN actor-critic, GAE, and the clipped PPO objective are all in ~200 lines, no RL library — so the whole pipeline is legible end to end: pixels in, a Doom-playing policy out.
- A whole level needs curriculum, not more compute. Sixty million steps of straight PPO on E1M1 found the exit zero times; the same algorithm, handed a human route to walk backwards, was exiting within fifteen thousand. The lesson generalises past Doom: when reward is one event at the end of a long horizon, the fix is usually to move the starting line, not to train longer.
- The level is solved: 19 exits in 20 attempts from the real map start, in about 19 seconds a run. The human demonstration it learned the route from took 168 seconds, so the student beat the teacher by roughly ninefold — and then stopped needing the lesson. In two of ten recorded runs the agent leaves the human’s route entirely and still reaches the exit; it found a shortcut the demonstration never took, which the route-progress metric scores as failure right up until the exit bonus lands.
- It solved the level by refusing to play it. The agent finishes with 88–101 health out of 100 and, almost always, zero kills — it does not fight anything, it runs. That was never specified; it falls out of the arithmetic. A kill pays +1 and the exit pays +100, and dying forfeits the 100 outright, so combat is a bad trade twice over while speed is nearly free. What emerged is exactly what human Doom speedrunners do on this map. And it is the same network that learned, on defend_the_center, to stand still and shoot everything that moved — because there the reward paid per kill and there was no door to run to. Identical algorithm, opposite temperament, and the only thing that differed was what the reward paid for.
- The most useful engineering lesson was the least clever one. This agent oscillates: it learns to finish the level, forgets, relearns, forgets, indefinitely. Annealing the entropy bonus dampened that considerably and did not stop it, and the run that produced the result above still ended, four hours later, unable to finish the level at all. What saved it was keeping a separate snapshot of the best policy — scored only on episodes from the real map start — instead of the most recent one. The final checkpoint of that run exits 0 times in 12. The snapshot taken seventeen minutes in exits 19 times in 20. On a task whose learning curve is not monotonic, deciding what to keep matters as much as what to train.
▶
Now you play
The same game, for you — the original Doom (shareware episode 1, “Knee-Deep in the Dead”), running in your browser through a self-hosted DOS emulator. Nothing is installed or streamed from elsewhere; it opens in a new tab so it has the whole screen.
Play Doom ↗ opens in a new tabWASD move · mouse aim · click to shoot · Space opens doors · click the game to capture the mouse