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>
73 lines
3.2 KiB
Text
73 lines
3.2 KiB
Text
# nav_heap_test.ludic - Recast's and Detour's own memory, counted in the shim (plan 25): a player
|
|
# crossing the map and coming back, again and again, leaves the resident tiles and the native bytes
|
|
# where the first crossing left them; walkers in and out of a crowd grow nothing; a reset gives it back
|
|
import "ludic.nav"
|
|
import "ludic.base"
|
|
import "fakes/meadow.ludic"
|
|
program NavHeapTest {
|
|
numbers float
|
|
|
|
# a 128 m meadow as four 64 m tiles, saved as a file the index reads
|
|
function saved(nav_st: mut NavState, path: string) -> void {
|
|
let g = ground(128, 0)
|
|
expect(nav_tiled(nav_st, NAV_PERSON, 0.0, 0.0, 64.0, 16, 4096))
|
|
for tz in 0 .. 2 { for tx in 0 .. 2 { expect(nav_tile_build(nav_st, NAV_PERSON, tx, tz, g, new NavConfig) > 0) } }
|
|
expect(nav_save_file(nav_st, NAV_PERSON, path))
|
|
nav_reset(nav_st)
|
|
}
|
|
# one crossing: from the near corner to the far one and back, the ring kept at each end
|
|
function cross(nav_st: NavState, xs: []float, zs: []float) -> int {
|
|
var changed = 0
|
|
xs[0] = 110.0
|
|
zs[0] = 110.0
|
|
changed += nav_tiles_keep(nav_st, NAV_PERSON, xs, zs, 1, 60.0, 90.0)
|
|
xs[0] = 20.0
|
|
zs[0] = 20.0
|
|
changed += nav_tiles_keep(nav_st, NAV_PERSON, xs, zs, 1, 60.0, 90.0)
|
|
return changed
|
|
}
|
|
|
|
test "crossing the map and coming back fifty times holds the tiles and the native bytes of the first crossing" (nav_st: mut NavState) {
|
|
let path = Os.temp_dir() + "/ludic_nav_heap.navmesh"
|
|
saved(nav_st, path)
|
|
let before = nav_heap_bytes()
|
|
expect(nav_load_index(nav_st, NAV_PERSON, path))
|
|
let xs = floats(1)
|
|
let zs = floats(1)
|
|
xs[0] = 20.0
|
|
zs[0] = 20.0
|
|
nav_tiles_keep(nav_st, NAV_PERSON, xs, zs, 1, 60.0, 90.0)
|
|
expect(cross(nav_st, xs, zs) > 0)
|
|
let tiles = nav_tiles_in(nav_st, NAV_PERSON)
|
|
let held = nav_heap_bytes()
|
|
let peak = nav_heap_peak()
|
|
var changed = 0
|
|
for k in 0 .. 50 { changed += cross(nav_st, xs, zs) }
|
|
print(`nav heap: {before} bytes before the index, {held} after one crossing, {nav_heap_bytes()} after fifty more ({changed} tiles in or out), peak {peak} -> {nav_heap_peak()}`)
|
|
expect(changed >= 100)
|
|
expect_eq(nav_tiles_in(nav_st, NAV_PERSON), tiles)
|
|
expect(nav_heap_bytes() == held)
|
|
expect(nav_heap_peak() == peak)
|
|
nav_reset(nav_st)
|
|
expect(nav_heap_bytes() == before)
|
|
}
|
|
|
|
test "walkers in and out of a crowd a thousand times grow nothing, and the crowd goes with its mesh" (nav_st: mut NavState) {
|
|
let before = nav_heap_bytes()
|
|
expect(nav_build(nav_st, NAV_PERSON, ground(40, 0), new NavConfig))
|
|
expect(nav_crowd_start(nav_st, NAV_PERSON, 16, 0.6))
|
|
for k in 0 .. 10 { nav_crowd_remove(nav_st, NAV_PERSON, nav_crowd_add(nav_st, NAV_PERSON, 5.0, 0.0, 5.0, 0.35, 1.8, 1.4, 0, 2.0)) }
|
|
let held = nav_heap_bytes()
|
|
for k in 0 .. 1000 {
|
|
let a = nav_crowd_add(nav_st, NAV_PERSON, 5.0 + float(k % 30), 0.0, 5.0, 0.35, 1.8, 1.4, 0, 2.0)
|
|
expect(a >= 0)
|
|
nav_crowd_target(nav_st, NAV_PERSON, a, 30.0, 0.0, 30.0)
|
|
nav_crowd_step(nav_st, 1.0 / 60.0)
|
|
nav_crowd_remove(nav_st, NAV_PERSON, a)
|
|
}
|
|
print(`nav heap: a crowd's {held} bytes, {nav_heap_bytes()} after a thousand walkers came and went`)
|
|
expect(nav_heap_bytes() == held)
|
|
nav_reset(nav_st)
|
|
expect(nav_heap_bytes() == before)
|
|
}
|
|
}
|