An empty world at the game's size held 51839 KB of Jolt's heap (200000 bodies, 65536 pairs, 20480
contacts, a 32 MB temp heap), the jolt= floor under every walk. Pairs and contacts come from what
moves - drops, boats, a few walkers - and a valley's still things make none. Now 11743 KB at 200000
bodies and 8461 KB at the 98304 the game opens for (jolt_floor_test holds it under 16 MB). The temp heap
still falls back to malloc for a step that wants more.
lib/macos-arm64 rebuilt; lib/windows-x64 needs native/build.sh on the PC (jph_world_new's new sizes).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The user's walk showed the footprint rising outside the Ludic heap. Jolt's bytes were already counted;
the navmesh's were not, so nothing could see them. Now:
- ludic.nav nav_heap_test: fifty crossings of a four-tile map by the resident index hold the tiles in and
the native bytes to the first crossing's; a thousand crowd walkers in and out grow nothing; a reset
gives back every byte the mesh took.
- ludic.physics cross_heap_test: a 1 km map of 64 m chunks kept to a ring round a player crossing
corner to corner and back, each chunk a heightfield, twelve owned posts and six owned scaled hulls
as the game makes them: six more crossings hold the bodies, the shapes and Jolt's bytes and peak
exactly. (A post made as an offset of a cylinder, with only the offset owned, leaked the cylinder
every time: the game's solid_pillar owns its cylinder directly.)
lib/macos-arm64 rebuilt; lib/windows-x64 needs native/build.sh run on the PC for the new exports.
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>
ludic deps --allocs (25.2) found phys_float's five pushes per drop reaching the water and
phys_sink's filtered copies per removal.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Jolt's Allocate/Reallocate/Free/AlignedAllocate/AlignedFree go to libc's malloc with the size in a
16-byte header, and atomic counters keep live bytes, the peak and the blocks asked for (its job
threads allocate too). The fence reads the three exports extern_weak to judge Jolt by its plateau.
jolt_heap_test: a ground in and out 1100 times holds 46,482,514 bytes after the first 100 and after
all of them, the peak does not move, and a closed world gives back every byte it took. The macOS
library is rebuilt; the Windows DLL still has to be rebuilt on the PC.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A chunk's trunks and boulders put in and taken out made a new shape each time and freed none. The
table is by the body's index, made once at the world's size. tests/reuse_test: 1000 owned bodies put
and removed hold no more shapes and 32 bytes of heap.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests/reuse_test: 200 walkers made and removed hold one place and 0 bytes of heap (Os.heap_bytes);
twenty closes and opens keep the same shape and walker lists.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The per-frame sweep over physics, character, vehicles and nav found three fact makers that made a record per fact: contacts and splashes, the character's and the vehicles'. Each keeps a pool now, as wildlife's and npc's do (q_unheld). phys_sink, asked on every removal, built two new lists each time; it filters into a kept spare pair and swaps. ludic.nav's paths and crowds already allocate nothing, and none of the four builds a string per call. What remains at load, reset or a world swap is not per frame. vehicle_feed takes its state mut. vehicles_test: 1000 fed facts, drained turn by turn, use at most 4 records. All packages 421.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
phys_pose, phys_ray, phys_push and phys_walker_pose each made a new record per call, some several times a frame, and Ludic never gives one back. They now fill the caller's PhysPose / PhysHit / PhysPush / PhysWalk and return whether they found anything. phys_overlap returns a count; phys_overlap_id(i) reads each id back. The package's own uses (phys_resolve, phys_row, phys_walker_move) read the values buffer directly. Tests take small allocating helpers. physics 20, character 15, vehicles 8.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tools/native/lib.sh passes -implib rather than /implib: Git Bash rewrites an argument starting
with / into a Windows path, and lld-link was handed 'C:\Program Files\Git\implib;...'. Both DLLs
import KERNEL32 alone, so no C++ runtime ships beside them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The water floats the hull, the wind pushes every boat as a force, the lake bed stops it at the shore;
the swell takes the outward share of a stroke. ludic.physics: phys_hull_add (a buoyant box),
phys_row, phys_bow_speed, and a test that floats one a quarter under, rows, turns and grounds it.
The vehicles tests row a real Jolt hull on the fake shore; the horse moved to horse.ludic.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The package keeps the rules and hands them over each step: speed and heading, whether a jump
leaves, CHAR_STEP and the boots' slope limit. The walker (Jolt CharacterVirtual) does gravity,
landing, steps, slopes and following the ground down. Too steep is ground too steep facing the way
the body wanted to go; stepping off an edge is not. ludic.physics: phys_walker_move (follow the body
if something else moved it, then step), the slope limit, the jump always honoured. The character's
tests run on a real Jolt walker over the same fake world: 15 pass, a knee-high boulder now a step.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Five new tests: stand and walk at the asked speed, a low stone is a step and a tall one a wall, a
jump up and back, a crate shoved aside, a hull turned by a torque and carried by a force.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Our own shim (native/shim/jph_shim.cpp) over Jolt built from the pinned tag with cross-platform
determinism and no fp contraction: shapes as handles (box, sphere, capsule, cylinder, dome,
offset, heightfield, mesh), still/kinematic/dynamic bodies by id with real removal, rays,
top_at and push (what CharacterGround asks), overlaps, buoyancy against the PhysWater port,
contacts recorded in C and drained as PHYS_HIT / PHYS_SPLASH facts. Fixed 1/60 steps, at most four
a frame. Nine tests against the real library, including a pile run twice to the bit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>