devlog.

Project · World engine

AsciiWorldEngine

A walkable ASCII city that runs in your terminal. The world, the camera, the raycaster and every glyph and colour on screen are written from scratch in Rust — one dependency, libc, and only so the terminal can be put in raw mode. The whole city is generated from a seed: --seed 42 gives you one city and --seed 1337 gives you a different one, the same on every machine and every build. There is no grid held in memory, so the map has no edge and walking further costs nothing. Public on GitHub.

0.584
ms/frame, 180×60 on the street
3.2
MB resident — no world grid, ever
14,390
Lines of Rust, 18 modules
1
dependency — libc, for the terminal only

A 1,710 fps ceiling at that frame cost, at 10,800 cells with 223 kept a frame by the occlusion cull. Indoors is cheaper still, 0.544 ms; riding a lift is the most expensive room in the building, at 0.611 ms.

git clone https://github.com/Alchemy86/AsciiWorldEngine.git && cd AsciiWorldEngine && ./play
./play finds a Rust toolchain, builds in release, and drops you onto a pavement. Everything after it goes straight to the binary: ./play --demo to watch the city walk itself, ./play --seed 1337 for a different city, ./play --help for the rest.
It opens where you would run it — a terminal. ./play types itself out, and the city comes up: down the avenue, up the towers, then in through a door and up the building's glass lift, riding out over the rooftops while the floors slide down past the window. Every frame is the running engine; the lift is the mechanic docs/lift.md describes. Cut and scored in ShowReel from those captures — the chiptune synthesised for it, nothing sampled.

What it does

Everything here is built and shipping.

The world

Nothing in memory, everything unbounded

  • Every cell is a pure function of its coordinate — height, hue, architecture, which building it belongs to — so there is no grid to hold and no edge to reach
  • Six building silhouettes (flat, stepped, tapered, crowned, spired, masted), and a seventh that means something: that tower has a lift in it
  • A building's name reads on its own facade, so the city is navigable rather than anonymous, and N points at the nearest lift
  • Traffic — carrying real, readable registration plates — pedestrians, lampposts, street trees and a star field, all drawn as billboards through the same per-column buffer the walls use
  • Weather: clear, rain or downpour, drawn through the same buffer everything else is, leaning with your own velocity

The insides

A door on every building that faces a street

  • Walk through a doorway and you are in a real room — ten families, from lobby and market to archive and bar, each with its own furniture and layout off the building's own seed
  • The street wall is glazed: there is no backdrop and no parallax faking it, the same raycast that found the wall carries on out into the real city beyond it
  • Furniture is baked-in geometry you collide with; a terminal, a notice board or an exit sign is a labelled fixture instead, with a verb and a reach
  • Inside and outside are one mode the engine is in, not two code paths — the raycaster, the collision and the renderer never learn there are two

The lift

One press, then hands off

  • About half the tall stock gets a glass lift, off the same seed as everything else — walk in, press the panel
  • One press commits the car to the whole journey and releases you, so you can turn round and watch the floors go past, or the city fall away out of the back glass
  • The car is world state, not a camera trick: it is a room with a base that moves, and each floor is generated the same way the ground floor always was
  • Ride mode (L) loads straight into a car that runs up and down on its own — a screensaver of the engine's own best view

Seeded

The same city, everywhere

  • Every cell is a hash of its coordinate and one seed, so a seed is a promise, not a hint: --seed 42 is the same streets, towers and traffic on every machine and in every build
  • The seed fixes everything off it at once — which towers are tall, which get a glass lift, the traffic and its plates, and every room behind every door
  • --variety 0..1 sets how much neighbouring plots may differ: 1 (the default) gives every plot its own windows, colours and roofline, 0 makes a whole district read as one regular grid
  • There is no save file because there is nothing to save — the seed is the city, and a different one is a different city

In the terminal, and beyond it

One core, more than one frontend

  • 24-bit ANSI, sizing itself to whatever terminal window it is given
  • The engine decides the whole picture and hands a frontend one flat buffer of characters and colours; a frontend only paints it
  • The terminal binary is the product, but it is not the only target: the same core compiles to WebAssembly (--no-default-features --features wasm), dropping the one dependency the terminal frontend needed
  • --film drives the engine through a readable script and writes every tick to disk as an .svg, ready for ffmpeg

The licence

Personal and noncommercial, free

PolyForm Noncommercial 1.0.0, fetched byte-for-byte rather than typed from memory. Personal and noncommercial use — study, hobby projects, forking it to see how a raycaster works — is free. Commercial use needs permission first, which is the one project on this site where that is true.

A street at night in AsciiWorldEngine: towers in six silhouettes rising on both sides, lit storefronts, and two cars on the road carrying registration plates.
Street level, the default seed: six tower silhouettes, lit storefronts, traffic on the road. The plates on the cars are real registrations, drawn from characters like everything else on screen rather than pasted on as a texture.

What it costs

600 frames at 180×60, release profile, one machine. Absolute numbers move 30% or more with machine load, so every delta below was measured interleaved against its own control, not quoted cold.

Where sim cast render paint total
On the street, weather clear (default)0.009 ms0.077 ms0.362 ms0.136 ms0.584 ms
Indoors0.544 ms
In a moving lift0.001 ms0.082 ms0.420 ms0.108 ms0.611 ms
Street, weather rain0.572 ms
Street, weather downpour0.608 ms

Weather costs +8% of a frame off (unasked, since clear is the default), +14% in rain and +21% in a downpour. Registration plates measured at +0.003 ms of a 0.546 ms frame — real, but inside a run-to-run spread wide enough that --no-plates is not measurably cheaper. Riding a lift's own +0.009 ms on the street is mostly the binary being bigger, not new work: paired --vista renders before and after are byte-identical.

The AsciiWorldEngine skyline generated from seed 42: towers in green, orange, cyan and red silhouettes, with buildings named ORBIT OFFICES and VECTOR LOBBY on their own facades.

--seed 42

The same viewpoint generated from seed 1337: a completely different skyline — a tall cyan tower on the right, a purple building, different names and silhouettes.

--seed 1337

The same viewpoint, two seeds. Nothing else changed — a different number is a different city.

Where it stands

Milestones

27 Aug 2026

Names, a shape you can see coming, and unmirrored floor numbers

A building's name now reads on its own facade. A tower with a lift gets a seventh, recognisable silhouette and a lit LIFT mark; one press commits the car and releases you; an upper floor's outer wall stopped being walkable into thin air.

27 Aug 2026

A glass lift in the tall buildings

Step in, press the panel, and the car rises — floors sliding past on one side of the shaft, the street falling away on the other, both drawn live rather than faked. Riding costs 0.599 ms a frame against the street's 0.582.

27 Aug 2026

Real registrations, and a real licence

Traffic started carrying 24 real private registrations from Regtransfers' own stock, shipped as an editable file rather than a literal in the renderer. The hand-written proprietary notice was replaced by PolyForm Noncommercial 1.0.0, fetched byte-for-byte.

27 Aug 2026

A walkable ASCII city, native Rust terminal engine

World, camera, projection, raycasting, interiors and renderer for a text-rendered first-person city walker — the first commit, and already a native terminal binary with an optional wasm target off the same core.


Where these numbers come from

Frame costs are the project's own --bench output, measured on the build in the repository; every delta on this page came from an interleaved before/after pair, not a cold absolute figure. Line and module counts are counted directly from the crate's own src/ tree. The street and plate frames are real .svg captures the engine wrote of itself, converted losslessly to PNG.

AsciiWorldEngine ships no third-party art or map data — the city, the traffic and the registration plates are all generated. The 24 plates in the committed default list are real private registrations currently for sale by their owner, credited to regtransfers.co.uk in the project's own documentation.

← All projects