SHITTY DOOM
Loading DOOM...

click anywhere to close

How it works

Every frame you see is a real prime number. The digits are arranged in a grid and colored so they recreate the game image — but the underlying number is (probably) prime. You can select and copy it.

1. Capture & downsample

Each frame from the DOOM engine (running in WebAssembly) is captured and downsampled to a small grid — e.g. 40 columns by 30 rows = 1,200 cells. Each cell gets the average color of the source pixels it covers.

2. Color quantization (k-means)

We have 10 digits (0–9) and need 10 colors. An adaptive k-means algorithm clusters the grid's colors into 10 groups, sorted by luminance: digit 0 gets the darkest color, digit 9 the brightest. Each cell is assigned the digit of its nearest cluster.

Frame pixels → downsample → k-means(k=10) → digit grid 8855533111 8865431111 8888654321 ← each digit = a color

The palette is adaptive per frame — colors shift naturally with the scene. To avoid flicker, each frame's k-means is seeded with the previous frame's centroids (warm start, 2 iterations instead of 5).

3. Find a prime

The 1,200-digit string isn't prime yet. We fix the first digit to be nonzero and the last digit to 1 (so the number is odd and not divisible by 5), then search for a prime by varying only the last few "free" digits.

8855533111...████1 ↑↑↑↑↑ free digits — try 0000 → 0001 → ... until prime

A sieve over the first 168 primes (up to 997) eliminates ~92% of candidates cheaply. The survivors are tested with the Miller-Rabin probabilistic primality test. Only the tail digits change — the image stays visually identical.

4. Miller-Rabin & the primality slider

Miller-Rabin is a probabilistic test: each round has at most a 25% chance of incorrectly calling a composite "prime." Multiple rounds compound:

The Primality slider lets you trade speed for certainty in real time.

5. Optimizations for real-time

6. The stack

DOOMdoomgeneric C engine compiled to WASM via Emscripten + SDL2.
Prime engine — Rust compiled to WASM via wasm-pack. Uses num-bigint for arbitrary-precision arithmetic.
Frontend — vanilla JS. Digits are real DOM <span> elements (not canvas), so you can select and copy them.

Game Controls

Click the preview above to focus, then:
Move   Ctrl Fire   Space Open doors
Enter Menu select   Esc Menu

What am I looking at?

Every frame of DOOM is converted into a giant prime number. The digits are colored to recreate the image. You can select and copy them — it's real text, not a picture.
Hit ? in the toolbar for the full algorithm breakdown.
Loading DOOM engine...