ludic migrate state packages <every example program> packages/ludic.lab/example/plate.ludic
1804 vars into 126 states, 64 into lets; 23498 edits in 460 files
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A local bound straight from another module's global (let t =
thing_cur), or from such a local, is followed within its function, and
a write through its field or element is listed as a warning after the
counted writes. A reference from a function's result is not followed.
Reseed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The parse, the types and the module rules (export, uses, layers, ports,
registries) run and nothing is emitted or linked: about three seconds
on Maroon Lake. In this mode the checker asks vis_check at each
reference it resolves, with a global's initializer and a registry's
entries seen from the files the emitter would use. Reseed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bind Purse { money: g_money } writes the getter bind_Purse_money in the
bind's own file, so a one-line wrapper per member is not needed; a
member that takes something is refused a variable. Reseed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The modules of one layer use each other freely and may go round;
anything outside the layer is held to the module's uses, and a layered
module with no uses reaches nothing outside it. The cycle check walks
the graph with each layer as one node, so a cycle leaving a layer is
refused. ludic deps shows the layers and counts the largest cycle
without their own edges. Reseed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every file is compiled, linked and every test block run as up to N jobs
at once (xargs -P; default the CPU count), each test with a TMPDIR of
its own, and the report is read back in file order. Windows keeps the
sequential path.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With LUDIC_DEPS=<file> the compiler records every reference the
visibility pass resolves (from module, to module) and every assignment
to another module's global. ludic deps prints the modules,
dependencies, largest cycle, cross writes and globals written from
outside, with --graph, --dot, --writes, --uses MOD, --check FILE and
--baseline FILE. Reseed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A property or event a module does not export no longer collides with
another module's of the same spelling: each private one is renamed for
its module, with the types, new, emit and @On written in that module.
Exported ones stay one namespace; two events of one spelling are now
refused. Generic records, entity components and component or view
records stay global. Reseed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A template literal nested in a {...} hole crashed the parser: the outer
literal ended at the inner backtick. The lexer (and ludic-fmt's) now
reads a hole as code, taking strings, chars and templates in it whole.
A decimal literal past 2147483647, or a hex one of more than eight
digits, was wrapped into a negative int; it is a long with its value
now, and giving one to an int is refused. Reseed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A scene is an entry in the open registry LabScenes, shown on a plate: a
flat lit disc, the package's own small sky with the sun at one hour, and
a frame clock. Headless each camera (lab_shot, lab_shot_at) settles and
is written as build/lab/<scene>/<shot>.png (a stored PNG, written here);
in a window N and P step through them. tools/lab/run.sh and sheet.py
make the contact sheet; tools/lab/plate_build.py makes plate/.
ludic.render3d gains r3d_plate_mode (no terrain, grass or water is made)
and r3d_sky_path. quit() in a program with no frame loop links. The
example takes ~120 MB resident, 417 MiB peak footprint. Reseed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The entries are read and checked against the registry's record as a
registry ... from file is, errors at the resource file's line, and they
are defs of the module that wrote the line: the registry must be open to
it, and they take that module's place in the stable order. Reseed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A private function, var or const no longer collides with the same
spelling in another module, in no module or in the runtime: where two
meet, each private one is renamed for its module (seed$shop), with every
reference its module writes that no local shadows. Exported names stay
one namespace. Nothing is renamed without a clash. Reseed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A line is cast at a point the FishingWorld port says is water (depth, or afloat), bait (asked,
then said as FISHING_BAIT_USED for the game to take) halves the wait, the bite picks a species -
a legend only on a lure, likelier in deep water and with skill, else an everyday one by weight -
and the fight is a marker, a green band that moves above Relaxed and closes on Hard or for a
fish whose data says so, a Gentle ring of one press, and a legend's runs and the line it takes
back. Length and weight come from FishSpecies data. The package never draws, speaks or touches
a pack; every step is a FishingFact (CAUGHT, BAIT_USED, LINE_SNAPPED, SLACK, MISSED, ...). Its
dice are its own Rng. A legend on Gentle fights as a legend (the old ring lost him at once).
Uses ludic.base only; thirteen tests over a fake lake.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Items (base price, sell fraction) and vendors (stock, buys, refuses) are the game's data handed
over at boot; standing, the day, a shortage and "buys beyond its list" are the ShopWorld port;
money is ShopPurse and the pack ShopPack. The week's wanted and glutted items come from an Rng
seeded by the week, never the world's. The balance invariants - a shop is not a fountain,
friction falls and never inverts, raw keeps its order - are the package's tests (nine).
ludic.crafting: its private names carry the package's prefix too (a private name is still one
global namespace with the game's - ludic.shop's `sp_seed` met the game's).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A recipe is `def CraftRecipes key { out, n, ins: [...], ns: [...], station, minutes, hold,
group, learned }`. The pack is the CraftPack port (count, take, add, room, and `leaves`: what
an item leaves once used, so water gives back its bottle); stations are CraftStations (ready,
start), unbound meaning hands only. craft_make hands a click recipe over or starts a timed one
at its station, refunding when the station refuses; the hold runs from the screen that shows it.
Uses ludic.base only; ten tests with a fake pack and fake stations.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Minutes of fuel that burn down in game time, twice as fast in the rain with
nothing over the ring, and the hours it held under cover. Lighting and feeding
are decided (fire_decide), costed in wood (fire_cost) and applied
(fire_apply) apart, so a machine that does not own the world can ask the one
that does. Warmth and cooking by distance are queries. FIRE_LIT,
FIRE_WENT_OUT and FIRE_LOW_FUEL are facts; the rain, the tarp, the ban and
who owns the world come through the FireWorld port. Its own save section.
Uses ludic_base only; 8 tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Warmth, food, water and energy as bars of 0..100; what an hour of doing something
costs them (the package's rates: a full bar is a day at a trip's median); the
countdown when one runs out, reported as NEEDS_CRITICAL / NEEDS_RESTORED /
NEEDS_COLLAPSED facts. The body's work, the air, clothing, the sun, the
difficulty and the effects come through the NeedsWorld port. Its own save
section. Uses ludic_base only; 13 tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A step is (kind, param, need) and a question about state: a kind has a
shape (yes, a count, a mask counted, every bit of a mask) and a pool
(world, any, sum, or, max, each), handed in by the game as StepsKind
records. An arc is chapters of up to STEPS_PER_CHAPTER steps; steps_check
sticks each met step of the current chapter (STEPS_MET) and opens the
next when all are (STEPS_CHAPTER), so a step met before its chapter
ticks at once. With company each seat's shares are held per chapter,
pooled as the kind says (steps_met, steps_party_got), counted for an
EACH step (steps_each, steps_lacking), and a leaver takes theirs along.
Port: StepsWorld { value(kind, param, player) (required), party,
present }. The package knows no kind's meaning and no chapter's words.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
latest.json asked once and polled (the newest version and its notes, in
a language or English); then Velopack's releases.<os>.json, the plan (the
delta chain when the installed full package is on disk, no delta is
missing and the chain weighs less than the full one; the newest full
package otherwise, named as the feed names it), each package streamed to
the packages folder with its bytes on a bar and an eased pace, its
SHA-256 by Get-FileHash or shasum in a child, Update patch per delta and
Update apply --waitPid. macOS keeps its packages outside the bundle and
names --rootDir and --packageDir; a translocated app is not installed.
Ports with the runtime as every default: UpdateWorld (platform, exe, pid,
now_ms), UpdateNet (get, download, poll, text, received, free),
UpdateProc (spawn, poll, free). Config: feed, app_id, version, root,
packages, mac_packages, scratch. It words nothing: states, UPDATE_ERR_*
codes and numbers, and UPDATE_STARTED / _STOPPED / _APPLYING facts - the
game exits on the last.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>