Sixteen test programs under tests/*_pins_test.ludic, on today's code, each one tick from a set
state through the public step (wildlife_tick_ground / _bird / wildlife_tick, wildlife_release,
wildlife_new): the state it goes to, its timer, and how many of the package's rolls it took and
which (the next roll is read off a newborn's yaw, compared with a stream of the same seed). IDLE,
WANDER, ALERT, WARY, FLEE, CHARGE, GO_DRINK, GO_FEED, DRINK, APPROACH, EAT, TRAPPED, FLY, LAND,
PERCH; the droppings' roll before them; the newborn's seven (eight for a bird); what the step
leaves alone. tests/pin/ holds the shared step, the dice reader and two species of its own (a tame
horse, a crow that never lands on its own). Compiled, not run here: 27.2 holds to them unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zones_set / zones_clear / zones_merge, zones_contains / zones_nearest and the clusters' bounding circles,
over fixed arrays of ZONES_MAX (16). WildlifeWorld.active freezes an animal outside (no state change, no
dice), NpcWorld.active a walker (and no birth outside), VehicleWorld.active a moored boat, and
ThingsWorld.restocks keeps a morning's restock inside; every default is "everywhere", so an unbound game
is unchanged. Tests: the merge (near players one cluster, far two, a player leaving splits a chain),
contains, nearest, the radius; wildlife, npc, vehicles and things pass as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each morning's repopulation made a new WildAnimal (and the game a new drawing, actor and skeleton,
keyed by an ever-rising key) for every animal that had gone. A legend's record is never taken, nor
one still in a crowd. reuse_test: a hundred removes and makes are one record.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A frame holding a new peak of facts made a record and grew the free list; now nothing is made until
64 are held at once. The two record-count tests hold the 64.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
wl_fact made a new WildFact per fact, about one a frame, and Ludic never gives one back. ludic.base's q_unheld(q, pool, out) lists the records a queue no longer holds: neither waiting nor handed out by its last drain, which is good until the next drain. ludic.wildlife and ludic.npc now keep a pool, hand out a free record, and make a new one only when every record is held. Taking a record writes the state, so wl_fact / np_fact and the few callers holding their state read-only take it mut. Tests: q_unheld's rules (an empty drain holds on, the safe side); 3000 prints drained frame by frame use at most 4 records; 500 arrivals drained turn by turn use at most 4. base 37, wildlife 27, npc 17; all packages 420.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nav_crowd_add takes how hard a walker keeps its distance, and WildSpecies.spacing (default 2) is a species' room from others walking by, which the valley hands the crowd. Both libraries are rebuilt; nav 15/15 on the Mac and the PC, DLL KERNEL32 only. wildlife 26/26.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
17.10 found almost every animal turn-back was for a climb, where the navmesh (40-45 degrees) is stricter than the step's 1.2 per metre. So the frame-sized test was refusing a few centimetres of steep ground: a pebble a walker steps across. It also refused sooner the faster the frame rate. wl_climb takes the ground half a metre ahead along the way the step actually goes. climb_test holds it at 60 and 240 Hz: a pebble is crossed and a wall is not. Both tests fail under the old rule. wildlife 24/24.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The count is wildlife_turned(), the 75-degree fallback an animal takes when the way was not enough. It is a measure only and is not saved.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It sets a target straight away from the threat (40 m when it flees, 20 m when it is wary) and heads for it with wl_head, so the way port takes it round water and cliffs. Where the world gives no way, it still runs straight away as before. way_test now has a flee round the wall's end.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The living animals around a point from the grid (a rare species from its own list), into a list
the caller keeps in its own state, so a frame's proximity question walks the cells it covers
rather than every animal ever made. wildlife_alive_of is the species index's count.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Written while builds are held (agents share 16 GB; no build or run until the user lifts it), so
it has not been compiled or tested. The animals are rows of a ludic.base Table: x, z, species and
alive as columns, a 32 m grid over the living, the living by species, and a nid map.
wildlife_by_nid is a map lookup instead of a scan of every animal ever made, wildlife_count walks
only its species, wildlife_nearest asks the grid, wildlife_set_alive writes the flag and the row
together, and wildlife_refile files the tick's moves once after it (wildlife_verify holds the
columns to the records). A guest puts its whole table away and brings it back. A test case covers
them; to run once builds are allowed: ludic test packages/ludic.wildlife.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts with 0.R5's state defaults in ludic.wildlife resolved; wl_step writes the push's answer, so
its callers take WildlifeState mut again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ludic.wildlife: WildlifeWorld.push / pushed_x / pushed_z (defaults change nothing); a ground
walker's step is slid clear of a still thing with a body from its species' size and scale, and
a step that gets nowhere turns away as the water does. Birds are not pushed; no dice added.
- ludic.npc: NpcWorld.push / pushed_x / pushed_z (a person 0.35 m round) in npc_walk, and
NpcWorld.clear (default true), which npc_line_ok asks at 1 m so a detour does not cut a trunk.
- ludic.aim: AimView.clear replaces AimView.ground and the ground march; the pick asks the line
a body's width short of where the ray enters the thing (aim_clear_at(t, back)), so a solid
thing does not hide itself. probe.ludic (the ground-agreement probe) and AimView.dry are gone.
- ludic.photo: PhotoLens.clear replaces PhotoLens.ground, PhotoLens.trunk and the march.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ludic.base's Queue<T> carries a QueueTag (its name and pending count): queue_new(name), q_push(q, v),
q_drain(q), q_clear(q) take no BaseState, and core_undrained(tags) names the given queues still holding
facts. A reducer on a package's state can now call that package's verbs (wallet_earn(wallet_st, n)).
ludic migrate state --prune (ludicc --migrate-prune) takes out each state parameter a function no
longer uses, nor anything it calls, and the argument that fills it - including an argument for a
parameter the callee has dropped, which is taken out before the call is checked, so a generic's T is
told by the argument that says it. A reducer keeps its state. --dry-run now counts the edits it would
make. Every package was moved with it: 608 base_st parameters and their arguments, 1889 edits.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>