56,000 lines of DOOM, in a language I made up

Hacker News Top Tools

Summary

The author built a joke programming language called bet that compiles via LLVM, uses arena-based memory management, and successfully runs the full DOOM game (56,000 lines) without code review, relying only on tests.

No content available
Original Article
View Cached Full Text

Cached at: 07/16/26, 04:52 PM

# About — betlang Source: [https://betlang.dev/about/](https://betlang.dev/about/) why I built bet bet is a small, real programming language: slang keywords on the surface, a serious compiler underneath\. It compiles to native code through LLVM, manages its own memory, self\-hosts, and runs DOOM\. I built it as a contained experiment, and ran it to completion\. I built bet on a break from trying to make something that sells\. I wanted a project with a clear edge to it, one I could actually finish, and building a compiler had been on my list for a long time\. A joke language gave me the excuse: keywords that read like a group chat, wrapped around a compiler that had to genuinely work\. I set one rule at the start: no research\. I never checked whether anyone had built this before, because I didn’t want the internet to kill the idea before I’d written a line\. As it turned out,[Geoffrey Huntley](https://betlang.dev/about/#prior-art)already had, and I didn’t learn that until later\. A language that only works at the level of syntax is really just a costume, so I gave it one real job\. Games allocate and release objects constantly, and both manual bookkeeping and garbage collection cost you frames you can’t spare\. bet handles that with arenas: allocate into a scope, use it for a frame, drop the whole scope at once\. The pattern itself isn’t new\. Zig ships an arena allocator that frees everything in one call, and Odin bakes the same arena and temp\-allocator idea in for game code\. I wanted bet to carry it as a first\-class feature with its own keywords, so the language would read as a design of its own rather than a slang reskin of something that already existed\. > It’s a joke\. I still wanted it to actually do something\. The other reason I built it was to run an experiment\. I wanted to see how far an AI coding agent could get on a hard, well\-specified project if I stayed out of the implementation\. My job was to be the architect: I set the problem and the acceptance criteria, then held the line on them\. I did zero code review\. A change shipped only if it passed its tests, met the acceptance criteria, and cleared the corpus\. That was the only gate\. The proof that it works is DOOM, ported in full\. id Software’s original C source for the renderer, the game logic, the WAD loading, and the audio was rewritten in bet: more than 56,000 lines, compiled to a native binary that runs the real shareware game in a window\. Launch it and DOOM plays itself in attract mode\. Those clips are the game’s original recorded inputs, replayed through the simulation\. Fixed\-point math is what makes that a real test: drift by a single step and the player starts walking into walls\. bet replays the inputs in lockstep with the reference C build, frame for frame, so the whole simulation comes out bit\-for\-bit identical\. Getting that far with no shortcuts is what separates a toy language from one that can carry real software, and it’s the result I trust most on a build I never code\-reviewed\. So it finished, end to end: the compiler, self\-hosting, documentation, and this site\. And that is where it stops\. If a feature request comes in I’ll review it, but there’s no roadmap and no version two on the way\. bet was a joke and an experiment and a way to learn what a build like this actually takes, and it did all of that\. If there’s one thing I want it to say about me, it’s that I finish what I start\. the part I took seriously Manual`free\(\)`bookkeeping and GC pauses both wreck a frame budget\. In bet you allocate into a`crib`, an arena scoped to the frame, and release the whole thing with`evict`in O\(1\)\. No per\-object tracking, no stall in the middle of a frame\. That is the experiment\. A joke on the surface, one hard problem solved properly underneath, and a build gated by nothing but its tests\. It compiles to native code, it self\-hosts, and it runs DOOM\. It was never meant to become a product, and it doesn't need to be one\. It's finished\. how it was builtReal numbers from a commit\-tracked timelog, counting active effort with idle time clamped out\. That clamping has one gap: three of the agents porting DOOM stalled on usage limits while the clock kept running, so the porting\-games row runs about 12 hours high\. Take those off and the real total is nearer 22\. porting games doom, oregon trail, pong 18h self\-hosting the compiler bet, compiling bet 4h security review cwage issues \#30–\#48 3h infra, tooling & site ci, docker, freeze, docs 3h frontend lexer · parser · grammar 2h language & collections keywords, types, containers 2h LLVM backend the actual hard part 1h arena memory crib · evict · the point 29m total· most of it on porting games

Similar Articles

DOOMQL

Simon Willison's Blog

Peter Gostev built a Doom-like game using SQLite as the game engine, with ray tracing via recursive CTE, and integrated with Datasette for a real-time web interface. The project was created using GPT-5.6 Sol and demonstrates the creative potential of using SQL for game logic.

Why fastDoom is fast

Fabien Sanglard

A detailed technical analysis of why the fastDOOM port achieves significant performance improvements over the original Doom executable, covering the history of Doom's source code lineage and specific optimization techniques.

Running ‘Doom’ on E. coli cells… very, very slowly

Lobsters Hottest

MIT researcher Lauren Ramlan published a paper demonstrating that the classic game Doom can be played on a display made from E. coli cells, though at an extremely slow frame rate that would take centuries to complete a single playthrough.