|
All checks were successful
docs / build-and-deploy (push) Successful in 2s
The type table lists fixeds (buffer of fixed values) and ptrs (buffer of pointers) alongside words, but they had no reference pages. Add both, with compilable examples; coverage inventory updated (types: 10 -> 12). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| .claude | ||
| .forgejo/workflows | ||
| assets | ||
| docs | ||
| examples | ||
| runtime | ||
| selfhost | ||
| tools | ||
| .gitignore | ||
| BOOTSTRAP.md | ||
| build-cli.sh | ||
| build.sh | ||
| COMPILING.md | ||
| EVENTS-DESIGN.md | ||
| LANGUAGE.md | ||
| LIFECYCLE-DESIGN.md | ||
| LUANTI-ROADMAP.md | ||
| MOBILE-DESIGN.md | ||
| NETWORKING-DESIGN.md | ||
| README.md | ||
| SCENES-DESIGN.md | ||
| SYNTAX-REDESIGN.md | ||
| test.sh | ||
Ludic
An AI-first, ahead-of-time compiled game language with an ECS core, a
deterministic fixed-point runtime, and a native 2D backend. ludicc lowers
Ludic to LLVM IR itself and emits a native binary — and ludicc is itself
written in Ludic.
.ludic ──► ludicc ──► LLVM IR ──► object ──► native binary
(in Ludic)
No C is generated, compiled or linked anywhere in a build. There is no
interpreter, no transpiler, and no C runtime: the framebuffer, sprites, PNG
decoding, TrueType text, the retained UI, the registers and the RNG are all
written in Ludic (runtime/native/*.ludic), and the macOS window is
hand-written LLVM IR (runtime/native/cocoa.ll). Beneath that sits only the
platform's own ABI — malloc, fwrite, objc_msgSend, CoreGraphics — reached by
compiler intrinsics, the same floor Rust and Swift stand on.
The compiler is written in Ludic. selfhost/*.ludic is a Ludic compiler —
lexer, parser and LLVM-IR backend — that compiles every example (including the
6-file JRPG) to the byte-exact same binary the original C compiler produced, and
compiles its own source to a fixpoint. It is built from a checked-in IR seed
(selfhost/ludicc.seed.ll) with clang alone; run ./selfhost/bootstrap-cfree.sh
to rebuild it with no C compiler in the loop. The former C compiler is gone.
Neither the compiler nor the games are C. Beneath both sits only the platform's own ABI — malloc, fwrite, objc_msgSend, CoreGraphics — reached by intrinsics, the same floor Rust and Swift stand on. (The wasm/cross-compile/shared-library driver paths lived in the old C compiler and are not yet re-implemented on the self-hosted native toolchain.)
Layout
| Path | What it is |
|---|---|
selfhost/*.ludic |
the compiler, written in Ludic — lexer, parser, and the LLVM-IR backend (ECS storage, queries, spawn, match/machine, UI, scenes, save/load, fixed-point). Concatenated by selfhost/build.sh; built from selfhost/ludicc.seed.ll |
selfhost/bootstrap-cfree.sh |
rebuild the compiler from the IR seed with no C compiler, and prove it reproduces its own IR |
runtime/native/core.ludic |
the runtime written in Ludic for the native path (framebuffer, text, registers, RNG, input) |
COMPILING.md |
the native pipeline: ludicc → LLVM IR → exe/dylib, module/export, cross-compilation, rt_* intrinsics |
runtime/native/image.ludic |
PNG decoding, images, sprites, alpha blending and 9-slice — in Ludic |
runtime/native/inflate.ludic |
DEFLATE decompression (RFC 1951), so PNG needs no zlib on any target |
runtime/native/truetype.ludic |
from-scratch TrueType loader + antialiased glyph rasterizer, in Q16.16 |
runtime/native/ui.ludic |
retained UI widget tree: layout, 9-slice, focus, events — in Ludic |
runtime/native/cocoa.ll |
the macOS window, written in LLVM IR (Objective-C runtime + CoreGraphics via their C ABI) |
runtime/web/wasm.ll |
the web's platform layer in LLVM IR: the allocator, bulk memory and strings, since wasm32 has no libc |
runtime/web/platform.js |
the browser's window — the same five win_* functions cocoa.ll implements, against a <canvas> |
runtime/web/index.html |
the page a web build is served from |
tools/ludic-web/run.mjs |
runs a headless wasm build under Node, so native and wasm output can be diffed |
examples/chronorift.ludic |
the JRPG written in Ludic (multi-file via import, model-based) |
examples/menu.ludic |
a retained-UI title screen (9-slice, TrueType, focusable buttons) |
examples/snake.ludic |
a second, unrelated game — proves the language is general (same toolchain, no engine hardcoding) |
build.sh |
./build.sh examples/<name>.ludic |
test.sh |
regression suite: builds the compiler, compiles/runs all examples, checks save/load + diagnostics (./test.sh) |
tools/ludic-tools/ |
the editor toolchain, in C: ludic-fmt (source formatter) and ludic-lsp (language server) — one lexer and one vocabulary shared by both |
tools/editors/ |
plugins for VS Code and JetBrains, plus configuration for Neovim, Helix, Emacs, Sublime and Zed (README) |
tools/test-tools.sh |
regression suite for the toolchain: proves formatting never changes a program, drives the language server over real LSP traffic |
Build & run
ludicc compiles Ludic straight to machine code via LLVM IR. See
COMPILING.md for the pipeline, shared libraries
(--shared), cross-compilation and the runtime protocol.
./build.sh examples/chronorift.ludic
./build/chronorift # opens a native window
Headless render (for testing / CI):
./build.sh examples/chronorift.ludic --headless
printf 'ddddwww' | ./build/chronorift_headless # writes out.ppm
sips -s format png out.ppm --out frame.png
A module compiles to a shared library instead of a program:
./build.sh examples/lib/combat.ludic --lib # -> build/libcombat.dylib
In a browser:
./build.sh examples/chronorift.ludic --web # -> build/web/
python3 -m http.server -d build/web 8000 # open http://localhost:8000/
build/web/ is a self-contained 116 KB directory — the 42 KB module, the loader,
a page, and the sprites the compiler saw the game name. Copy it to any static
host and it runs; it needs no server-side anything and no special headers. Saves
go to localStorage, so save()/load() survive a reload.
A wasm build needs an LLVM with the WebAssembly backend and wasm-ld — Linux
clang/lld have both, Apple's clang has neither (brew install llvm lld).
See COMPILING.md for the pipeline, who owns the frame
loop, and how assets are bundled.
Editor support
./tools/build-tools.sh # -> build/ludic-fmt, build/ludic-lsp
ludic-lsp speaks LSP 3.17 over stdio, so one binary serves every editor:
completion that knows whether you are after a ., inside a query [...] or in
a ui block; diagnostics from the compiler itself; go-to-definition and rename
across imported files; comment-preserving formatting. ludic-fmt is the same
formatter as a CLI, for pre-commit hooks and CI.
Plugins for VS Code and JetBrains IDEs (Community editions included) and
drop-in configuration for Neovim, Helix, Emacs, Sublime and Zed are in
tools/editors/. Both tools also understand
```ludic fences in Markdown, so this file and LANGUAGE.md get the
same highlighting, checking and formatting as the source tree.
Language features implemented
property(typed fields + defaults),system(phase,@annotations,reads/writesclauses),const,fn(withrequires/ensuresparsed).model— named entity kinds (bundles of properties); identity is one int per entity, replacing empty tag properties. Filter with{Kind}.import "file"— multi-file programs (fragments spliced in, include-guarded, per-file diagnostics).- ECS queries:
for (a, b) in query [A, B, {Tag}] where <expr> { … }. spawn/despawnwith entity-slot reuse; nested queries.- Control flow:
if/else,when,while, numericfor i in a .. b. - Types:
int,fixed(Q16.16, with correct*//lowering),bool,entity,str. Fixed-point vs int arithmetic is resolved by the typechecker. - Deterministic seeded RNG;
save()/load()snapshot of the whole ECS World. - 2D primitives:
clear,fill_rect,frame_rect,put_px,present,key. - TrueType text (
font_load,text_ttf) with full Unicode + anti-aliasing; arbitrary-size images +draw_9slice. ui— a retained widget tree declared as data (panels, labels, buttons, images; layout, 9-slice skins, keyboard focus + click events).match/machine+state+become— dispatch and state machines.scene/layer/enter— mutually-exclusive game states, each withon enter/on exithooks and layered systems (layer order = draw order).var— typed module-level state, included in save/load snapshots.module+@export fn— compile a .ludic file to a shared library whose exported functions are ordinary C-ABI symbols.extern fn … = "symbol"— call any C-ABI library, Ludic or otherwise.--target wasm32-unknown-unknown— the same game in a browser: the runtime, the ECS and the graphics stack compiled to wasm, rendering frames identical to the native build's.
The game: Chrono Rift
A playable co-op JRPG in examples/chronorift.ludic, using CC0
Kenney sprites (Tiny Town + Tiny Dungeon), decoded from
PNG at runtime by the Ludic-written PNG/DEFLATE decoder — no zlib, no external
dependency on any target.
Controls:
- Overworld:
WASDmove,Ksave,Lload. - Battle (local co-op): Player 1 / Knight —
W/Sselect,Spaceconfirm. Player 2 / Mage —I/Kselect,Jconfirm. Each player takes their own turn each round (Attack / Defend / Run; Mage has Attack / Heal / Defend).
Status
- Compiler pipeline: Ludic → LLVM IR → native binary / shared library
- No C generated, compiled or linked in a build; runtime written in Ludic
- Cross-compilation to ELF (x86-64, aarch64) and Windows COFF
- ECS runtime (properties, systems, phases, queries, entity pooling)
- Windowed 2D rendering (Cocoa driven from LLVM IR) + headless PPM verification
- CC0 Kenney PNG sprites (
png_load, decoder written in Ludic) + scrolling camera - Overworld: tilemap, movement, collision
- Random encounters + turn-based battle (HP/MP, seeded-RNG damage)
- Party + local co-op (P1 Knight, P2 Mage, per-player turns)
- Leveling (XP → stat growth) and game-over / respawn
- Self-hosting: a Ludic-written compiler compiles its own source to a byte-exact fixpoint, and rebuilds itself from a checked-in IR seed with no C compiler in the loop (
selfhost/,./selfhost/bootstrap-cfree.sh) - Snapshot save / load (full ECS World)
- Two maps (overworld + dungeon) with map switching via the arch
- Boss encounter (Rift Warden) + victory condition
- Item shop (gold → potions) at the house; potions usable in battle (Knight ITEM)
- More skills / enemy variety (future)