feat(ecs): chunks as a grouping - IntIndex takes sparse values; ludic.things' chunk column and things_drop_chunk

A streamed world loads and lets go of a chunk's entities together, so a chunk is a first-class
group: chunk_of(x, z, size) packs a chunk's cell into an int, tb_remove_all(tb, ix, v) removes every
row an index files under one value (the observers told of each). IntIndex kept one list per value
up to the largest, which a packed chunk number (hundreds of millions) turned into hundreds of
millions of empty lists and a 12 GB test run; a value past 1024 now gets its slot through an IntMap,
so a sparse value costs one list.

ludic.things files every Thing under its 256 m chunk (TH_CHUNK), kept by every move;
things_chunk_count and things_drop_chunk (the port and the facts told of each removal, as
thing_remove tells them) are what the memory budget's streamed chunks ask. The moves are their own
file (moves.ludic). Tests: ludic.base 35, ludic.things 8, all under a 2 GB cap (24 MB peak).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-27 22:07:26 +03:00
parent 7834b26ef8
commit f3fec88888
11 changed files with 186 additions and 65 deletions

View file

@ -178,4 +178,23 @@ program ThingsTest {
keep.x = 1.0
expect_eq(things_verify(things_st), 1)
}
test "a chunk's Things are counted and let go together; a move carries a Thing to its new chunk" (things_st: mut ThingsState, things_test_st: ThingsTestState) {
things_clear(things_st)
put(things_st, TH_BRANCH, 10.0, 10.0)
put(things_st, TH_BRANCH, 20.0, 30.0)
let far = put(things_st, TH_BRANCH, 600.0, 10.0)
let here = things_chunk(10.0, 10.0)
expect_eq(things_chunk_count(things_st, here), 2)
expect_eq(things_chunk_count(things_st, things_chunk(600.0, 10.0)), 1)
thing_move(far, 15.0, 15.0, 0.0)
expect_eq(things_chunk_count(things_st, here), 3)
facts(things_st)
let gone = things_test_st.gone
expect_eq(things_drop_chunk(things_st, here), 3)
expect_eq(things_count(things_st), 0)
expect_eq(things_test_st.gone, gone + 3)
expect_eq(len(facts(things_st)), 3)
expect_eq(things_verify(things_st), 0)
}
}