|
All checks were successful
docs / build-and-deploy (push) Successful in 2s
Make Ludic text correct-by-default over UTF-8, so player names, translated UI, and chat behave for every language instead of counting bytes and splitting characters in half. The byte-oriented Text.* stays for speed; Unicode.* is the layer that understands code points and (approximately) grapheme clusters. - len / byte_len code points vs bytes — the two lengths, kept distinct - is_valid_utf8 strict validation of untrusted input - char_at / chars code-point access by index; chars() -> []int - upper / lower case mapping (ASCII + Latin-1) - truncate first n code points, never a half-character - grapheme_len user-perceived characters (approx UAX#29) Pure integer/byte IR over NUL-terminated buffers; C-free, no data-table blob. Decoding and validation cover the full UTF-8 range (overlong/surrogate/>10FFFF rejected). grapheme_len collapses combining marks, variation selectors, ZWJ sequences (family emoji), and regional-indicator flag pairs. Documented v1 scope: wider-script/locale case rules (Latin-Extended, Greek, Cyrillic, Turkish i, German ß) and NFC normalization are follow-ups. - examples/library/unicode.ludic: asserts the invariants across ASCII, Latin-1 (é round-trips through upper/lower), a decomposed "café" (5 code points, 4 graphemes), a ZWJ family emoji (5 code points, 1 grapheme), and a flag (2 regional indicators, 1 grapheme). Wired into `x test` (now 55 passed). - docs: a new Unicode section + 9 per-symbol pages clarifying byte vs code point vs grapheme; inventory updated; every fence passes check-docs; site builds. - seed regenerated; `x bootstrap-cfree` fixpoint holds. Closes #13 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| ecs | ||
| events | ||
| games | ||
| lang | ||
| library | ||
| networking | ||
| rendering | ||
| README.md | ||
Examples
A curated tour of Ludic, grouped by intent. Every example here is exercised by
the test suite (bin/x test / bin/x selfhost-test), so nothing in this
directory silently rots.
Run any program straight from the repository root (so assets/ resolves):
bin/x app examples/games/snake.ludic # compile + open a real window
bin/x app examples/games/snake.ludic --headless # render one frame to build/out.ppm
bin/ludic examples/lang/offline_rewards.ludic # compile + run a plain program
games/ — complete, windowed games
| Example | What it shows |
|---|---|
games/snake.ludic |
A full game from primitives: input, grid, growth, collision, score. |
games/menu.ludic |
A retained-UI title screen — the UI declared as data. |
games/chronorift.ludic |
A 2D co-op JRPG: overworld, dungeon, random encounters, turn battle, boss, save. The entry file imports the modules under games/chronorift/. |
rendering/ — drawing primitives
| Example | What it shows |
|---|---|
rendering/draw_prims.ludic |
The extended Screen.* primitives — line, circle, triangle, fill, sprite. |
ecs/ — the entity-component world
| Example | What it shows |
|---|---|
ecs/hello.ludic |
The smallest program that exercises the ECS pipeline. |
ecs/world_get.ludic |
Reflection: read/write a component by name. |
ecs/world_scan.ludic |
Reflection: scan the world and identify each entity. |
ecs/world_query.ludic |
Reflection: iterate the world by property. |
ecs/world_spawn.ludic |
Reflection: a mod spawns a fresh entity by model id. |
ecs/world_mixed.ludic |
Reflection: get/set through real struct offsets. |
ecs/world_dyn.ludic |
Reflection: register a brand-new component at runtime. |
events/ — the event bus
| Example | What it shows |
|---|---|
events/events.ludic |
EV0: the event-bus core — declare, emit, @On. |
events/mod_events.ludic |
Two listeners on one event, driven from a mod. |
events/cancel.ludic |
EV3: cancellable (decision) events. |
events/recurse.ludic |
EV6: re-entrant emit is depth-bounded — no runaway cycle. |
events/promote.ludic |
EV1: @Public promotes a lifecycle hook to a public event. |
events/prop_events.ludic |
EV1 for properties: attach/detach events. |
events/scene_events.ludic |
EV1 for scenes: on-enter / on-exit events. |
events/program_events.ludic |
EV1 for the program scope: start/quit events. |
events/layer_events.ludic |
EV1 for layers + a public layer's show/hide events. |
events/scoped.ludic |
A despawned entity drops out of subsequent event work. |
networking/ — deterministic multiplayer (N0–N6)
Each maps to a stage of NETWORKING-DESIGN.md; all run
over the compiler's built-in loopback transport with zero foreign code.
| Example | What it shows |
|---|---|
networking/net_echo.ludic |
N0: the transport seam. |
networking/net_snapshot.ludic |
N1: whole-world snapshot to a memory buffer. |
networking/net_sync.ludic |
N2: @Sync replication codegen. |
networking/net_owner.ludic |
N3: entity ownership. |
networking/net_rpc.ludic |
N4: remote events / RPCs. |
networking/net_roles.ludic |
N5: handler roles + the drivable sim. |
networking/net_demo.ludic |
N6: a networked game end to end, in pure Ludic. |
networking/net_rt.ludic |
A blessed server-authoritative replication runtime. |
lang/ — language & standard-library tour
| Example | What it shows |
|---|---|
lang/annotations.ludic |
The annotation-first style: @Queries / @Computed / @OnSpawn / @Handles. |
lang/qdecl.ludic |
@Queries desugaring to the query system. |
lang/lifecycle.ludic |
The whole game lifecycle as @-hooks, in firing order. |
lang/detach.ludic |
Structural attach/detach + @OnAttach / @OnDetach. |
lang/reason.ludic |
Reason-carrying teardown (@OnDespawn: Despawned vs Quit). |
lang/toggle.ludic |
enable/disable at the three ECS scopes. |
lang/scenes.ludic |
One active scene at a time, handlers grouped into layers. |
lang/strings.ludic |
Strings as values: compare, join, interpolate, slice. |
lang/rng_demo.ludic |
The Random.* extensions (value/int/sign). |
lang/time_demo.ludic |
Time.frame / elapsed / delta. |
lang/offline_rewards.ludic |
A worked idle-game example over the Time/Date/Duration stdlib. |
library/ — building and linking a shared library
A how-to for compiling a .ludic module to a native .dylib/.so/.dll and
linking a second program against it via extern fn:
bin/ludicc examples/library/combat.ludic --shared -o build/libcombat.dylib
bin/ludicc examples/library/arena.ludic -o build/arena -Lbuild -lcombat
| Example | What it shows |
|---|---|
library/combat.ludic |
Exported functions callable across the C ABI. |
library/arena.ludic |
A program that links against the shared library. |