Φ
Game Development

NUMEN-1

We stopped borrowing somebody else’s machine. NUMEN-1 is our console: our instruction set, our rasterizer, our palette, our cartridge format, our sound. It is written in freestanding integer C with no standard library, compiled to 13,412 bytes of WebAssembly with zero floating-point instructions and zero imports, and it is running in this tab right now.

The source language is not C and it is not Python. A game on this machine is a seven-word sentence in ReL, our own language — one word per chakra band, ROOT to CROWN. The sentence is the game. Everything else is a compiler.

256 x 192
pixels, one byte each
64
colours, eight families of eight
44
opcodes, all integer
16
registers, 32 bit
16,384
bytes of cartridge RAM
400,000
instruction budget per frame
13,412
bytes of WebAssembly
0
float instructions, 0 imports

A sentence, compiled and played

Type a seed. The seed presses the ReL keyboard seven times, once inside each chakra band. The seven glyphs that come back decide the arena, the motion, the behaviour, what touching means, the palette, the hazard and the tempo. Those decisions are assembled into NUMEN-1 machine code in your browser and handed straight to the machine. No server, no engine, no asset pack.

seed
SOFT ENGINEframe 0instr 0score 00 fpsrunningarrows / WASD move · space fires · enter starts
booting the machine…
SOFT ENGINE
seed 0x67b13a8c · -- byte cartridge
ROOTARENA
R:OR-GRO^
PILLARS
idx 23 · prime 89 · gate G · oracle · phi 0.4278
SACRALMOTION
S:OR-GRO^
STEP
idx 54 · prime 257 · gate G · oracle · phi 0.5069
SOLARBEHAVIOUR
M:OR-GRO^
ORBIT
idx 69 · prime 349 · gate G · oracle · phi 0.5452
HEARTCONTACT
H:OR-GRO=
COLLECT
idx 89 · prime 463 · gate G · oracle · phi 0.5962
THROATPALETTE
V:AR-CYC=
ORCHID
idx 127 · prime 719 · gate C · architect · phi 0.6932
THIRD_EYEHAZARD
A:AR-CYC=
BEAM
idx 159 · prime 941 · gate C · architect · phi 0.7748
CROWNTEMPO
C:AR-CYC*
SPEED 4 / 6 BODIES / TARGET 30
idx 183 · prime 1097 · gate C · architect · phi 0.8360

The instruction set

Fixed 32-bit words. [op:8][ra:4][rb:4][rc:4][pad:12] for register forms, [op:8][ra:4][rb:4][imm:16] for immediates. No flags register, no interrupts, no undefined behaviour: every out-of-range load reads zero and every out-of-range store is dropped. A frame ends at SYNC, at HALT, or when the budget runs out.

00 HALT
01 NOP
02 MOVI
03 MOVH
04 MOV
05 ADD
06 SUB
07 MUL
08 DIV
09 MOD
10 AND
11 OR
12 XOR
13 SHL
14 SHR
15 NEG
16 ADDI
17 ANDI
18 SLT
19 SEQ
20 SGT
21 JMP
22 JZ
23 JNZ
24 CALL
25 RET
26 LDB
27 LDW
28 STB
29 STW
30 IN
31 OUT
32 GPUSH
33 GDRAW
34 RND
35 SYNC
36 ABS
37 MIN
38 MAX
39 SND
40 MULI
41 SHLI
42 SHRI
43 SIN
The drawing stack

There is no framebuffer access from code. You push arguments with GPUSH and issue one of twelve draw kinds with GDRAW. The rasterizer is integer-only: an edge function for triangles, a midpoint circle for discs and rings, Bresenham for lines, a 4x6 font of 40 glyphs for text and numbers.

0 CLEAR1 PIXEL2 RECT3 BOX4 LINE5 DISC6 RING7 SPR8 TEXT9 NUM10 TRI11 GRAD
The cartridge

A .n1 file is a 64-byte header — the magic NUM1, a version, the code word count, the data length, the tile count, a seed, and a 40-character ASCII title — followed by little-endian code words, the data image that lands at RAM address zero, and 64 bytes per 8x8 tile. The whole state of the machine, registers and RAM and stacks and audio, is 17,220 bytes, which is why the search brain can snapshot it and rewind.

Three hundred sentences, measured

We generated 300 seeds, compiled every one, loaded every one into the machine and ran 120 frames of scripted input through each. Nothing was hand-picked and nothing was thrown away.

300
cartridges compiled
0
failed to load
300
still drawing at frame 120
14,470,671
instructions executed
189
distinct titles
5/5
arenas reached
5/5
behaviours reached
4/4 4/4 4/4
motions, contacts, hazards

arenas OPEN BORDER PILLARS LANES RINGS · motions GLIDE THRUST STEP ORBIT · behaviours CHASE FLEE FALL ORBIT BOUNCE · contacts COLLECT AVOID ABSORB PARRY · hazards NONE BEAM PULSE SPINNER · palettes ASH BLOOD EMBER GOLD JADE TIDE AMETHYST ORCHID

What this is not

  • The prime carries the choice, not the meaning. Each glyph has a voice, a gate and a chakra. Inside a single chakra band the gate and the voice barely move, so they cannot select anything — we tried, and every sentence produced the same game. What varies is the glyph’s sigma-prime address, its unique coordinate in the 207-symbol alphabet. So the selector is ((prime >> 1) + index) mod n. The voice and gate shown next to each word are its identity, not its vote.
  • Every sigma prime is odd. Our first version used prime mod 4 and could only ever return 1 or 3, so half the motions, contacts and hazards were unreachable across 300 seeds. That is a real bug we shipped and then measured our way out of. The number above is from the fixed selector.
  • These are small games. One player, a handful of bodies, one hazard, a score bar. The claim is not that NUMEN-1 competes with a modern engine. The claim is that the machine, the language, the compiler and the games are all ours, top to bottom.
  • Sound exists in the machine and is not wired to the page. NUMEN-1 has four voices — square, triangle, sine, noise — and the SND opcode drives them. Nothing on this page plays audio yet. When it does, we will say so here.
  • Python built the scaffolding and is now gone. The Atari forge on the previous page was written in Python to prove the idea. This one is TypeScript in your browser and C in the machine. There is no Python anywhere in this pipeline.