wildlife_set_crowd(a, true) hands a walker to a crowd. Its step no longer moves it, and its want is two fields on it: goal_x / goal_z (the point it heads for or faces) and goal_speed (0 when it stands). A route reads those and hands back where the crowd put it through wildlife_moved(a, x, z, vx, vz). That sets its place, its ground, its heading from its velocity and its prints, and updates its row's columns so the spatial index finds it there. Nothing allocates per animal per frame: the want is the animal's own fields, and moved writes in place. The prints and the turn counters moved to walked.ludic (steer.ludic was at the 100-line limit). crowd_test holds it; with crowd off every old test is unchanged. wildlife 26/26. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| ludic.aim | ||
| ludic.anim | ||
| ludic.audio | ||
| ludic.base | ||
| ludic.character | ||
| ludic.clock | ||
| ludic.compass | ||
| ludic.core | ||
| ludic.crafting | ||
| ludic.dungeon | ||
| ludic.effects | ||
| ludic.fire | ||
| ludic.fishing | ||
| ludic.gameplay | ||
| ludic.gear | ||
| ludic.hints | ||
| ludic.i18n | ||
| ludic.inventory | ||
| ludic.jobs | ||
| ludic.lab | ||
| ludic.minimap | ||
| ludic.nativeecho | ||
| ludic.nav | ||
| ludic.needs | ||
| ludic.net | ||
| ludic.npc | ||
| ludic.npcai | ||
| ludic.photo | ||
| ludic.physics | ||
| ludic.platformer | ||
| ludic.prefs | ||
| ludic.render3d | ||
| ludic.rpg | ||
| ludic.save | ||
| ludic.session | ||
| ludic.settings | ||
| ludic.shooter | ||
| ludic.shop | ||
| ludic.steps | ||
| ludic.telemetry | ||
| ludic.things | ||
| ludic.tracks | ||
| ludic.ui | ||
| ludic.update | ||
| ludic.vehicles | ||
| ludic.wallet | ||
| ludic.weather | ||
| ludic.wildlife | ||
| README.md | ||
packages
The Ludic packages that ship with the toolchain, found by import "ludic.<name>" from
$LUDIC_HOME/packages (or a project's ludic_modules). Each has a README of its own.
ludic test packages runs every package's tests, each test block in a process of its own.
The mechanic packages
A mechanic says module ludic_<name> uses ludic_base and so reaches nothing else; it asks the game
through ports (bind ClockWorld { ... }), reports through queues of facts, and saves its own
section. The rules are in ludic.base.
| ludic.base | the shared vocabulary: Tick and phases, Queue<T>, rng streams, the save tree, the system runner (Systems, an open registry) |
| ludic.aim | what the crosshair is on: a forgiving ray against cylinders, the ground in front, reach floors, which thing the use key means |
| ludic.anim | glTF animation clips sampled and cross-faded onto a render3d Skin (uses ludic_render3d) |
| ludic.character | a third-person walking body: gait, steps and slopes, a jump, wading, swimming, sitting, a safe put-down, the orbit camera |
| ludic.audio | world sounds with a gain, pan and pitch from a listener port, flat interface sounds, packed clips loaded, the one door to Audio.* |
| ludic.compass | bearing marks on a strip: gathered from registered providers, gated by tier, sorted by priority, bearings, distances and a radar |
| ludic.clock | the hour, the day, the moon and a calendar of seasons |
| ludic.crafting | recipes: what goes in and out, where and how long, making, refunding, hold-to-make |
| ludic.effects | timed modifiers that run down in game time (a meal's warmth, a drink's legs) |
| ludic.fire | a camp fire: fuel, the rain on it, warmth at a distance, whether it will cook |
| ludic.fishing | a rod at the water: cast, bite, the reel's fight, the landing; species as an open registry |
| ludic.hints | a rail of what is true now, most urgent first, each a card that teaches it and can be muted by key |
| ludic.i18n | a game in any language: gettext .po files, patterns with holes, plurals, a mod folder, a font per language |
| ludic.inventory | a pack: a count per kind, with room the game decides |
| ludic.minimap | a map's logic: the explored fog over a grid and its land share, the player's marks, and the view (world to map and back, zoom, pan, the camp, you, focus) |
| ludic.needs | a body's warmth, food, water and energy, and the countdown to a collapse |
| ludic.npc | the other people in a place: a routine by the hour, walking round what is in the way, facing a player who comes near, lines as data, a guest's copy |
| ludic.physics | rigid bodies, removable still shapes, queries and buoyancy over Jolt Physics (a native library, phase 16) |
| ludic.nav | a navmesh per kind of walker and the ways across it, over Recast & Detour (a native library, phase 17) |
| ludic.photo | a camera's photographs: what is in the frame, a grade on size, framing, light and the moment, the roll, its worth, the best of each subject |
| ludic.save | versioned save files: a migration chain the game declares, torn writes told apart, a backup, a newer file refused and read-only |
| ludic.settings | a game's settings as data: one store, a fact per change, ranges, a safe set |
| ludic.shop | vendors: prices by standing and weekly demand, stock, buying and selling |
| ludic.steps | chapters of steps (kind, param, need), progress, and a party's shares pooled |
| ludic.telemetry | events queued, batched to a PostHog-shaped endpoint, backed off when offline |
| ludic.things | the placed things of a world and their kinds (an open registry), queries, facts, a save |
| ludic.tracks | prints and sign animals leave, their age, and reading them |
| ludic.update | a Velopack-installed game updating itself a frame at a time |
| ludic.vehicles | each player's boat and horse: called to berths and bays, owner and rider, riding, getting off onto a safe spot |
| ludic.wallet | money carried: earned, spent, lost, every change a fact |
| ludic.weather | spells of weather described as data: odds, wetness, wind, storms, a forecast |
| ludic.wildlife | a valley's animals: ranges, their day, senses and alert, feeding, lures, spawning |
Engine and UI
| ludic.render3d | the physically based 3D renderer over OpenGL and Vulkan (named ludic_render3d under uses) |
| ludic.ui | components: templates, stylesheets, layout, input and focus (module ludic_ui) |
| ludic.lab | the visual lab: a scene on a lit plate, fixed cameras, PNG shots and a contact sheet |
| ludic.core | the canonical engine-ABI components |
| ludic.prefs | a small key=value store for preferences and records |
| ludic.nativeecho | the worked example of a package carrying a native library: a C sum over a slice, callbacks drained as facts |
Native libraries
A package may carry a C or C++ library (native lines in its package.ludic,
docs/PACKAGES.md).
The library is never bound directly: a thin C shim in the package's native/shim/ is, and every
shim keeps the same shape so the Ludic side stays safe.
- Only
int,long,floatand opaque handles cross. A Ludicfloatis a Cfloat, alonganint64_t, apointeravoid *. No struct is passed by value, no C++ type, no exception: the shim catches and turns it into a return code. - A handle is the library's pointer, kept in the package's state and never exported. The game names what the package hands it - an int id - and the package maps it to the handle.
- Nothing calls back into Ludic. No function pointer crosses the boundary. What a library
reports through a callback (a contact, a finished path, a mixed buffer) the shim records in a
buffer of its own, and the package drains it after the call returns (
ne_scanthenne_drain), pushing each record onto its facts queue. A record that did not fit is counted, not dropped silently. - Bulk data crosses as a slice the package owns. A
[]floator[]intpassed where the shim takes a pointer is its data; the package makes it once and reuses it (L7), and passes its length beside it. - Errors are return codes. 0 is success and a negative number says what failed; nothing aborts, nothing prints.
- Threads a library starts stay inside C (a job system, an audio device). The Ludic side is called on the game's thread only.
- The symbols are prefixed with the package's short name (
ne_,jph_), exported explicitly (__attribute__((visibility("default"))),__declspec(dllexport)), and everything else is hidden.
native/build.sh builds lib/<target>/ from the pinned upstream source and the shim through
tools/native/lib.sh; run it on the Mac and, in Git Bash, on the PC.
The package's tests run the real library - there is no fake for it.
The builtin controllers
| ludic.gameplay | the shared foundation of the builtin gameplay controllers |
| ludic.platformer | the Platformer controller |
| ludic.shooter | the top-down Shooter controller |
| ludic.rpg | the RPG systems suite |
| ludic.dungeon | arena rooms for a room-to-room roguelite |
| ludic.npcai | NPC AI: perception, decision, action |