Tiled P6 — infinite/chunked maps, .world stitching, base64+zstd #74

Closed
opened 2026-09-01 12:30:10 +02:00 by orkun · 1 comment
Owner

Follow-up P6 of the Tiled design (#66). Design record: Design: Tiled maps §3.10.

Scope — scale

  • Infinite / chunked maps: decode <chunk x y width height> (TMX) and JSON chunks[] (default 16×16) and flatten into the rt_tmap dense array (or a sparse chunk store if memory demands).
  • .world stitching: maps[] {fileName,x,y} and patterns[] {regexp,multiplier,offset,mapWidth,mapHeight}, onlyShowAdjacentMaps — for streaming/large levels (JSON, reuses Json.parse).
  • base64 + zstd: the one remaining compression (gzip landed in P0). A self-contained pure-Ludic zstd decoder — the largest single item; explicitly last.

Golden fixtures

Hand-authored infinite/<chunk> (TMX + JSON chunks[]); sticker-knight.world; base64+zstd fixture (design §4).

Acceptance

  • An infinite map's chunks flatten to the correct dense layer.
  • A .world stitches its member maps at the right offsets.
  • A zstd-compressed layer decompresses correctly.

Depends on #69. Priority low.

Follow-up P6 of the Tiled design (#66). Design record: [Design: Tiled maps](https://git.workshopsoft.io/workshopsoft/ludic/wiki/Design%2FTiled) §3.10. ## Scope — scale - **Infinite / chunked maps**: decode `<chunk x y width height>` (TMX) and JSON `chunks[]` (default 16×16) and flatten into the `rt_tmap` dense array (or a sparse chunk store if memory demands). - **`.world` stitching**: `maps[] {fileName,x,y}` and `patterns[] {regexp,multiplier,offset,mapWidth,mapHeight}`, `onlyShowAdjacentMaps` — for streaming/large levels (JSON, reuses `Json.parse`). - **base64 + zstd**: the one remaining compression (gzip landed in P0). A self-contained pure-Ludic zstd decoder — the largest single item; explicitly last. ## Golden fixtures Hand-authored infinite/`<chunk>` (TMX + JSON `chunks[]`); `sticker-knight.world`; base64+zstd fixture (design §4). ## Acceptance - [ ] An infinite map's chunks flatten to the correct dense layer. - [ ] A `.world` stitches its member maps at the right offsets. - [ ] A zstd-compressed layer decompresses correctly. Depends on #69. Priority low.
orkun added the
priority:low
area:stdlib
labels 2026-09-01 12:30:10 +02:00
Author
Owner

P6 landed in main (764a029) — the final Tiled phase.

  • Infinite / chunked maps — <chunk x y width height> (TMX) and JSON chunks[] decode and flatten into the dense layer array, sized to the chunk union; the map's 0/0 header dimensions fall back to the flattened bounds.
  • .world stitching — Tiled.world / Tiled.world_count / Tiled.world_map read a .world (JSON, reusing Json.parse) and list its member maps at their world offsets.
  • base64 + zstd — a self-contained pure-Ludic Zstandard decompressor (runtime/native/zstd.ludic, RFC 8878, z_zstd): frame header + raw/RLE/compressed blocks; raw/RLE + direct-weight Huffman literals; the full FSE sequence path — predefined tables (transcribed verbatim from zstd's hardcoded constants, since the encoder shares a specific spread that isn't reproducible by rebuilding from the default distributions), RLE, and FSE-described — with repeat offsets and sequence execution. It decodes the low-entropy GID streams a tilemap produces; a high-entropy FSE-compressed-Huffman-weights block fails cleanly with -1 rather than emitting wrong bytes (documented scope).

Acceptance

  • An infinite map's chunks flatten to the correct dense layer — two 16×16 <chunk>s (and the JSON chunks[] equivalent) flatten to the same 32×16 layer.
  • A .world stitches its member maps at the right offsets — demo.world lists zstd_map.tmx @ x=0 and grid_maze.tmx @ x=384.
  • A zstd-compressed layer decompresses correctly — a real zstd-compressed tile layer decodes byte-exactly to its CSV baseline.

Proven by examples/library/tiled_p6.ludic (12 assertions) in x test (97 passed).


This completes the whole Tiled arc (#67–#74). Native TMX/TSX/TX and TMJ/TSJ/TJ both read onto one Value-tree intermediate → the rt_tmap runtime model; the Tiled.* namespace covers load, GID resolve (flips), render (with animation + tile objects), per-tile / property / layer collision into esys_move, objects/shapes/properties/custom-types/templates/opt-in-spawn, image/group layers, iso/hex/staggered coords, Wang GIDs, chunks, .world, and gzip/zlib/zstd compression. x test is at 97 passed; check-impl/check-docs/check-vocabulary green; the self-host bootstrap fixpoint is intact.

**P6 landed** in `main` (764a029) — the final Tiled phase. - **Infinite / chunked maps** — `<chunk x y width height>` (TMX) and JSON `chunks[]` decode and flatten into the dense layer array, sized to the chunk union; the map's `0/0` header dimensions fall back to the flattened bounds. - **`.world` stitching** — `Tiled.world` / `Tiled.world_count` / `Tiled.world_map` read a `.world` (JSON, reusing `Json.parse`) and list its member maps at their world offsets. - **base64 + zstd** — a self-contained pure-Ludic Zstandard decompressor (`runtime/native/zstd.ludic`, RFC 8878, `z_zstd`): frame header + raw/RLE/compressed blocks; raw/RLE + direct-weight Huffman literals; the full FSE sequence path — **predefined** tables (transcribed verbatim from zstd's hardcoded constants, since the encoder shares a specific spread that isn't reproducible by rebuilding from the default distributions), **RLE**, and **FSE-described** — with repeat offsets and sequence execution. It decodes the low-entropy GID streams a tilemap produces; a high-entropy FSE-compressed-Huffman-weights block fails cleanly with `-1` rather than emitting wrong bytes (documented scope). ### Acceptance - [x] An infinite map's chunks flatten to the correct dense layer — two 16×16 `<chunk>`s (and the JSON `chunks[]` equivalent) flatten to the same 32×16 layer. - [x] A `.world` stitches its member maps at the right offsets — `demo.world` lists `zstd_map.tmx` @ x=0 and `grid_maze.tmx` @ x=384. - [x] A zstd-compressed layer decompresses correctly — a real zstd-compressed tile layer decodes byte-exactly to its CSV baseline. Proven by `examples/library/tiled_p6.ludic` (12 assertions) in `x test` (97 passed). --- **This completes the whole Tiled arc (#67–#74).** Native TMX/TSX/TX and TMJ/TSJ/TJ both read onto one `Value`-tree intermediate → the `rt_tmap` runtime model; the `Tiled.*` namespace covers load, GID resolve (flips), render (with animation + tile objects), per-tile / property / layer collision into `esys_move`, objects/shapes/properties/custom-types/templates/opt-in-spawn, image/group layers, iso/hex/staggered coords, Wang GIDs, chunks, `.world`, and gzip/zlib/zstd compression. `x test` is at 97 passed; `check-impl`/`check-docs`/`check-vocabulary` green; the self-host bootstrap fixpoint is intact.
orkun closed this issue 2026-09-01 15:07:32 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: workshopsoft/ludic#74
No description provided.