ludic/examples
Orkuncakilkaya ab0b84b87e feat(lang): 27.3 - a reducer on a table's row: reducer T in S.table on A, @Target, Row<T>, @RowVerb, @Column
An action names one row of a ludic.base Table<T> by its handle, in a field marked @Target, and
`reducer Deer in Herd.deer on Spook(r: mut Row<Deer>, n: Noise, a: Spook)` runs once, for that row
alone (the table may sit down a path, S.w.tab). The drain resolves the handle (tb_row) and hands the
reducer a Row<T> - new in ludic.base: tb, row, h, rec - that the queue keeps, one per row reducer,
filled in place, so a targeted action allocates nothing; a stale handle runs nothing, and
LUDIC_ACTIONS_LOG=1 prints a line for it (@alloc_ok). Row reducers order among an action's by their
state's name, then the table's path.

Checked at compile time (actions_rows.ludic): the row reaches r.rec and r.h only - r.tb / r.row
refused, the view never assigned, stored, copied or handed on except to a @RowVerb (a function of
the record's own module taking Row<T> first; any other function taking a row is refused); a field
marked @Column (a table column mirrors it) is not written through r.rec; only the module owning the
state declares a row reducer; one @Target, an int, per action; the states between the row and the
action are read. `mut` is allowed on a Row<T> parameter.

ludic schema's code section gains row_reducers (record, table, state, action, target, predicted,
net, module, at) and row_verbs (name, record, module, at), and every action its target; row
reducers are left out of `reducers`. ludic deps and ludic-lsp name a row reducer
`reducer Deer in Herd.deer on Spook`. vocab: @Target, @Column, @RowVerb; docs/language pages;
LANGUAGE.md "A reducer on a row"; examples actions/rows and ten rejects; test.ludic feat, reject and
schema cases (not run); changes/row-reducers.md. Reseeded; bootstrap-cfree fixpoint holds (307497
lines); Maroon Lake's `ludic build --check` is clean against this tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:14:59 +03:00
..
actions feat(lang): 27.3 - a reducer on a table's row: reducer T in S.table on A, @Target, Row<T>, @RowVerb, @Column 2026-09-30 16:14:59 +03:00
ecs refactor(runtime,packages,examples): named constants, package enums, idiom sweep 2026-09-05 01:12:26 +03:00
events wip(0.S3): packages and examples migrated again from their pre-0.S sources in one run 2026-09-25 15:31:34 +03:00
functions checker: a function named like a built-in a call always takes is refused at its declaration - function words(st, k) compiled and every call became words(n) with a pointer for n (invalid IR, far from the cause); the table is selfhost/check/check_builtins.ludic, emit_call's built-ins no find_fn guard lets a declared function take, and ludic-dev syntax --check holds it to emit_call both ways; every other built-in (buffer, floats, double, ...) yields to a declared function in the checker as it already did in codegen. string_temps' keep and cross_heap_test's keep renamed (hand, keep_cell); rejected/builtin_call_name and functions/builtin_yield with their cases (added, not run); reseeded, bootstrap-cfree fixpoint holds 2026-09-30 01:10:24 +03:00
games wip(0.S3): packages and examples migrated again from their pre-0.S sources in one run 2026-09-25 15:31:34 +03:00
lang i18n: a key used only in a listener counts as used - the key check walked prog but not the bodies kept beside it (@On listeners, the lifecycle hooks, tests, computed fields, scenes), so their keys were never checked against en.po and ludic schema listed them unused (the game's 15 itemuse.* keys, emitted through ItemPlace); they are walked now as privates.ludic walks them. examples/lang/i18n_listen and its schema case (added, not run); reseeded, bootstrap-cfree fixpoint holds 2026-09-30 03:12:25 +03:00
library ludic.ui: t(key, holes...) in a template - the key marked (byte 1, a marked key kept as it is) and each hole's value after a byte 31, the text the translator decodes at draw time; joined through the text memo, so nothing is made while it reads the same (phase 26) 2026-09-29 23:16:05 +03:00
modules escape (fix): kept memory is HEAP, so what is pushed through an alias of it is kept 2026-09-28 21:15:32 +03:00
networking parser: an attribute before export is kept - @ToClients export event E was a local event (the attributes read in front of export were dropped when the declaration was parsed afresh one call down), as were @Sync / @Owned / @Server / @On / @Public ... before export; and export @ToClients event was refused. Attributes and export now read in either order into one declaration, and a wrapper marks what it added exported (g_at_keep goes); examples/networking/net_export and three schema cases (added, not run); reseeded, bootstrap-cfree fixpoint holds 2026-09-30 01:03:44 +03:00
rejected feat(lang): 27.3 - a reducer on a table's row: reducer T in S.table on A, @Target, Row<T>, @RowVerb, @Column 2026-09-30 16:14:59 +03:00
rendering runtime (macOS): MoltenVK opened first, so a process holds one - the SDK's loader in /usr/local/lib loaded its own MoltenVK beside the linked one and the program drew through it; the loader only when a layer is asked for, pinned to ours (VK_DRIVER_FILES, lib/macos-arm64/MoltenVK_icd.json) unless a driver is named. steady's stream round: a 300-cell warm-up, then the least of three 150-cell windows 2026-09-30 00:41:27 +03:00
state feat(cli): 0.R5 - ludic deps says what a function can come to change (widest_write_reach, --wreach N); a port member and a registry field reach only themselves 2026-09-26 23:19:54 +03:00
README.md refactor(cli)!: split the contributor tool out of the ludic CLI 2026-09-05 23:15:12 +03:00

Examples

A curated tour of Ludic, grouped by intent. Every example here is exercised by the test suite (bin/ludic-dev test / bin/ludic-dev selfhost-test), so nothing in this directory silently rots.

Run any program straight from the repository root (so assets/ resolves):

bin/ludic build examples/games/snake.ludic              # compile + open a real window
bin/ludic build 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 the Networking design; 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/operators.ludic Compound assignment on every type, unary minus, char escapes, list literals.
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.