docs: migrate README to API-Doc-Convention (S2-cascade.libs)
Restructured per ADR-0038: Abstract + bold-list Badges + Topology H2 + H3-API-Subsections (one per public function) + Conventions/Consumer pattern/CHANGELOG/References. Topology auto-populated via Sporel.exe --lint --fix. Pre-commit hook installed via --install-hooks. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
153
README.md
153
README.md
@@ -1,20 +1,145 @@
|
||||
# lib-core.maps
|
||||
|
||||
P.0 single-tile-grid-map implementation. Loads JSON map + tilemap files,
|
||||
provides tile-fetch + walkability queries.
|
||||
Single tile-grid map implementation. Loads JSON map + tilemap files, registers maps by id, and provides tile-fetch + walkability + size queries with current-map sugar.
|
||||
|
||||
- Lib-ID: `lib-core.maps`
|
||||
- Version: `0.1.0`
|
||||
- Spec: `meta/docs/superpowers/specs/2026-05-09-p0-lib-maps-design.md`
|
||||
**Version:** 0.1.1
|
||||
**Lib-ID:** lib-core.maps
|
||||
**Requires:** (none)
|
||||
**Tags:** maps, tile-grid, walkability, tilemap
|
||||
|
||||
Forward-compat stubs (DEPRECATED-MVP) for multi-map graph, lifecycle states,
|
||||
walls, sprite-fields, generators, save-integration. See
|
||||
`meta/docs/architecture/map-topology.md` for the full target spec.
|
||||
## Topology
|
||||
|
||||
<!-- topology:start (auto-generated; do not edit) -->
|
||||
```mermaid
|
||||
graph LR
|
||||
this["lib-core.maps"]
|
||||
engine["engine.*"]
|
||||
this --> engine
|
||||
```
|
||||
<!-- topology:end -->
|
||||
|
||||
## API
|
||||
- `maps.load(path)` — load + register a map from JSON
|
||||
- `maps.create(table)` — programmatic creation (tests, procedural)
|
||||
- `maps.tile_at(map_id, tx, ty)` / `maps.tile_at(tx, ty)` — current-map sugar
|
||||
- `maps.is_walkable(...)`, `maps.size(...)`, `maps.tile_size(...)`
|
||||
- `maps.current()`, `maps.set_current(id)`, `maps.list()`
|
||||
- Stubs (deferred): `maps.state()`, `maps.pin()`
|
||||
|
||||
### `maps.load(path)`
|
||||
**Syntax:** `maps.load(path: string) -> string`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
local id = maps.load("maps/forest.json")
|
||||
maps.set_current(id)
|
||||
```
|
||||
|
||||
**Description:** Loads a JSON map-file from disk, resolves + loads its referenced tilemap (local module-tilemap-id or fully-qualified), validates the map-table, and registers it. Returns the map-id. Errors if the id is already registered.
|
||||
|
||||
### `maps.create(t)`
|
||||
**Syntax:** `maps.create(t: {id: string, tilemap_table: table, ...}) -> string`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
local id = maps.create({
|
||||
id = "test-tiny",
|
||||
size = { w = 4, h = 4 },
|
||||
tile_size = { w = 16, h = 16 },
|
||||
tilemap_table = my_tilemap,
|
||||
tiles = { 0,0,0,0, 0,1,1,0, 0,1,1,0, 0,0,0,0 },
|
||||
})
|
||||
```
|
||||
|
||||
**Description:** Programmatic creation for tests + procedural generators. Caller must supply a fully-built `tilemap_table` (not a path/id reference). Otherwise identical to `load`.
|
||||
|
||||
### `maps.size(map_id)`
|
||||
**Syntax:** `maps.size(map_id: string | nil) -> {w: integer, h: integer}`
|
||||
|
||||
**Description:** Returns map-size in tiles. Falls back to current-map when `map_id` is nil. Errors if no current map.
|
||||
|
||||
### `maps.tile_size(map_id)`
|
||||
**Syntax:** `maps.tile_size(map_id: string | nil) -> {w: integer, h: integer}`
|
||||
|
||||
**Description:** Returns tile-size in pixels. Falls back to current-map when nil.
|
||||
|
||||
### `maps.tile_at(a, b, c)`
|
||||
**Syntax:** `maps.tile_at(map_id: string, tx: integer, ty: integer) -> table | nil` *(also: `maps.tile_at(tx, ty)` uses current-map)*
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
local tile = maps.tile_at(5, 3)
|
||||
if tile then engine.print(tile.id) end
|
||||
```
|
||||
|
||||
**Description:** Arity-flex sugar: `tile_at(tx, ty)` uses current-map; `tile_at(map_id, tx, ty)` is explicit. Returns the resolved tile-record from the tilemap, or `nil` if out-of-bounds.
|
||||
|
||||
### `maps.is_walkable(a, b, c)`
|
||||
**Syntax:** `maps.is_walkable(map_id: string, tx: integer, ty: integer) -> bool` *(also: `is_walkable(tx, ty)` uses current-map)*
|
||||
|
||||
**Description:** Convenience: returns `true` iff the tile exists and has `walkable == true`. Out-of-bounds is `false`.
|
||||
|
||||
### `maps.tilemap_id(map_id)`
|
||||
**Syntax:** `maps.tilemap_id(map_id: string | nil) -> string`
|
||||
|
||||
**Description:** Returns the fully-qualified tilemap-id referenced by a map.
|
||||
|
||||
### `maps.current()`
|
||||
**Syntax:** `maps.current() -> string | nil`
|
||||
|
||||
**Description:** Returns the currently-active map-id, or `nil` if none.
|
||||
|
||||
### `maps.set_current(map_id)`
|
||||
**Syntax:** `maps.set_current(map_id: string) -> void`
|
||||
|
||||
**Description:** Switches the current-map pointer. Errors if `map_id` is not registered.
|
||||
|
||||
### `maps.list()`
|
||||
**Syntax:** `maps.list() -> string[]`
|
||||
|
||||
**Description:** Returns an array of all registered map-ids.
|
||||
|
||||
### `maps.state(map_id)`
|
||||
**Syntax:** `maps.state(map_id: string) -> string`
|
||||
|
||||
**Description:** DEPRECATED-MVP stub. Always returns `"Active"` in v0.1.x. Full lifecycle (`Virgin`/`Inert`/`Passive`/`Active`/`Pinned`) lands in the multi-map slice.
|
||||
|
||||
### `maps.pin(map_id, reason)`
|
||||
**Syntax:** `maps.pin(map_id: string, reason: string) -> void`
|
||||
|
||||
**Description:** DEPRECATED-MVP stub. Emits a warn in v0.1.x. Pinning prevents lifecycle-eviction in the multi-map slice.
|
||||
|
||||
## Conventions
|
||||
|
||||
- Pixel-coords + tile-coords kept distinct: `size`/`tiles` index in tile-units; `tile_size` is the conversion to pixels.
|
||||
- Tilemap-ids may be local (`<this-module-id>.<name>`) or fully-qualified; `load()` resolves both.
|
||||
- `tile_at` is bounds-checked: out-of-bounds returns `nil` (not error).
|
||||
- Y-down-positive per ADR-0031.
|
||||
|
||||
## Consumer pattern
|
||||
|
||||
```lua
|
||||
local maps = require("lib-core.maps")
|
||||
|
||||
local id = maps.load("maps/forest.json")
|
||||
maps.set_current(id)
|
||||
|
||||
local sz = maps.size()
|
||||
for ty = 0, sz.h - 1 do
|
||||
for tx = 0, sz.w - 1 do
|
||||
if not maps.is_walkable(tx, ty) then
|
||||
-- mark blocked cell
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## CHANGELOG
|
||||
|
||||
### v0.1.1
|
||||
- Tilemap-id resolution handles module-ids with dots (prefix-match instead of first-dot split).
|
||||
|
||||
### v0.1.0 (P.0)
|
||||
- Initial release: load/create + tile_at + is_walkable + current-map management.
|
||||
|
||||
## References
|
||||
|
||||
- Spec v0.1.0 (P.0): `meta/docs/superpowers/specs/2026-05-09-p0-lib-maps-design.md`
|
||||
- Architecture: `meta/docs/architecture/map-topology.md`
|
||||
- ADR-0001 (engine knows verbs, libs bring nouns)
|
||||
- ADR-0031 (pixel-convention: Y-down-positive)
|
||||
- ADR-0038 (API-Doc-Convention)
|
||||
|
||||
Reference in New Issue
Block a user