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>
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>
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 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>