Phase 3: object tracker
Game-file footprint unchanged: still one line in main.lua.
Three-level navigation as specified in D2: Ctrl+PageUp/Down cycles categories,
PageUp/Down cycles kinds, Shift+PageUp/Down cycles instances of that kind, Home
announces where it is.
- categories.lua: flag-first classification into Creatures, Items, Alchemy,
Interactables, Exits and Terrain features, reusing the game's own 'exit' tag
and excluding the six nameless mechanical templates.
- tracker.lua: scan, cache, navigation, announcements.
Caching keys on level name, player position and turn: position because
everything sorts by distance to the player, turn because creatures move and
containers empty. Scans run on keypress, never per frame.
FoV is respected throughout -- creatures only when currently visible, tiles when
visible or remembered -- so the tracker never becomes a cheat.
Home reports path length alongside the offset, via the game's own
calculatePathFromPlayer. Straight-line distance is misleading indoors, where a
chest three tiles north through a wall can be twenty steps away.
Corrects D4 in docs/05-decisions.md. I had claimed tile.tryInteract cleanly
separates 'the player can do something here' from scenery. It does not: 'wall'
carries a flavour-only tryInteractFunction ('You touch the wall. It's cold and
rough.'), so every wall segment was promoted into Interactables -- 13 in the
starting house, burying the chest and cauldron. Structural tiles
(blocksMovement and blocksVision) are now excluded before the tryInteract test;
containers and furniture block movement but not sight, so they survive.
12 kinds/19 instances instead of 13/32.
13/13 testbed checks, history unit tests passing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8b1eb44c38
commit
c17c5277d4
@@ -109,13 +109,50 @@ Every other template resolves to a name/description and lands in a category. **T
|
||||
| `isPushable` / `isBreakableByHand` | 17 / 17 | Interactables |
|
||||
| `isWallFeature` | 22 | Terrain |
|
||||
|
||||
Critically, `modules/tile.lua:234` defines the runtime flag as:
|
||||
`modules/tile.lua:234` defines the runtime flag as:
|
||||
|
||||
```lua
|
||||
self.tryInteract = (self.loot or self.tryInteractFunction) and function(self,actor) ... end
|
||||
```
|
||||
|
||||
So **`tile.tryInteract` alone cleanly separates "the player can do something here" from scenery** — exactly the flag-first classification proposed in `03-implementation-plan.md`, and it's authoritative rather than heuristic.
|
||||
> ### ⚠ Correction (found during Phase 3 implementation)
|
||||
>
|
||||
> I originally claimed here that **`tile.tryInteract` alone cleanly separates
|
||||
> "the player can do something here" from scenery.** That is **wrong**, and the
|
||||
> tracker was visibly worse for it.
|
||||
>
|
||||
> Plenty of templates carry a *flavour-only* `tryInteractFunction`. `wall` is the
|
||||
> worst offender:
|
||||
>
|
||||
> ```lua
|
||||
> wall = {
|
||||
> name = "a stone wall",
|
||||
> blocksMovement = true, blocksVision = true,
|
||||
> tryInteractFunction = function(self, actor)
|
||||
> console.print("You touch the wall. It's cold and rough.")
|
||||
> return 1
|
||||
> end,
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> So flag-first classification promoted **every wall segment** into
|
||||
> Interactables — 13 of them in the starting house, burying the chest, cauldron
|
||||
> and alchemy table under identical noise.
|
||||
>
|
||||
> `tryInteract` means *"something happens if you press interact"*, **not**
|
||||
> *"this is worth walking to"*.
|
||||
>
|
||||
> **Fix:** exclude structural tiles — `blocksMovement and blocksVision` — before
|
||||
> the `tryInteract` test. That is the solid shell (walls, rock); containers and
|
||||
> furniture block movement but not sight, so they survive. Walls are already
|
||||
> served by the wall tones and the surroundings scan.
|
||||
>
|
||||
> Result in the starting house: 13 kinds / 32 instances → **12 kinds / 19
|
||||
> instances**, all of them things you would actually want to find.
|
||||
>
|
||||
> The flag-first *approach* still holds — it just needs this one structural
|
||||
> filter ahead of it. The lesson is that flags encode what the game engine does,
|
||||
> not what the player cares about.
|
||||
|
||||
**Residual hand-maintained list** is therefore small: the 6 exclusions above, the existing `exit` tag set (`way_out`, `building_door`, `horse`, `ladder_up`, `ladder_down`), and an ingredient-node list to split **Alchemy** out of **Items**. Dozens of entries, not hundreds — and new content in future versions falls through to a sensible default category rather than vanishing.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
**Read this first on any handoff.** Living document: update it whenever state changes, before ending a turn.
|
||||
|
||||
Last updated: 2026-08-01 · Currently: **Phases 0–1 done, menus + dialogue done.
|
||||
Phase 2 (tile examination) next.**
|
||||
Phase 3 done. Phase 4 (remaining menus) next.**
|
||||
|
||||
**Game is now playable start-to-finish by ear** from main menu through the intro
|
||||
conversation into gameplay — verified by the testbed, 9/9 checks.
|
||||
@@ -127,6 +127,10 @@ needs a human at the keyboard — Talon to test.
|
||||
| `/` | Scan all 8 neighbours, clockwise from north (terse) |
|
||||
| `;` | Where am I — level, in-game time, coordinates |
|
||||
| `Ctrl`+numpad 1–9 | Probe that direction without moving (`Ctrl+kp5` = standing on) |
|
||||
| `Ctrl+PageUp` / `Ctrl+PageDown` | Tracker: previous / next **category** |
|
||||
| `PageUp` / `PageDown` | Tracker: previous / next **kind** |
|
||||
| `Shift+PageUp` / `Shift+PageDown` | Tracker: previous / next **instance** |
|
||||
| `Home` | Tracker: distance, direction and path length to current instance |
|
||||
|
||||
Game keys worth knowing: **`x`** enters examine mode (not `e`), `f` finds exits
|
||||
while examining, `j` journal, `i` inventory, `c` character, `a` actions menu.
|
||||
@@ -278,10 +282,56 @@ require time — reading its public fields is the decoupled route.)*
|
||||
`love.event.push`, so without this seam every modifier-gated hotkey would be
|
||||
untestable. The testbed swaps them per keypress.
|
||||
|
||||
### Done — Phase 3: object tracker
|
||||
|
||||
- `accessibility/categories.lua` — flag-first classification into the six
|
||||
categories, plus the 6-template exclusion list and reuse of the game's `exit`
|
||||
tag.
|
||||
- `accessibility/tracker.lua` — scan, cache, three-level navigation, announcements.
|
||||
|
||||
Verified in the starting house:
|
||||
```
|
||||
Interactables, 12 kinds
|
||||
a bed, 1, nearest 1 tile south-west, 2 of 12
|
||||
an open door 1 of 1, 2 tiles north-west
|
||||
an open door, 2 tiles north-west, 2 steps by path <- Home
|
||||
```
|
||||
|
||||
**Caching:** signature is `level name : player x : player y : turn`. Position
|
||||
matters because everything sorts by distance; turn matters because creatures move
|
||||
and containers empty. Scans run on keypress only, never per frame.
|
||||
|
||||
**FoV respected** — creatures only when currently visible, tiles when visible or
|
||||
remembered. The tracker never reveals what a sighted player couldn't see.
|
||||
|
||||
**`Home` reports path length, not just offset.** Straight-line distance is badly
|
||||
misleading indoors: a chest 3 tiles north through a wall can be 20 steps away.
|
||||
Uses the game's own `calculatePathFromPlayer`.
|
||||
|
||||
#### ⚠ Correction to D4 — `tryInteract` is NOT a clean "worth tracking" signal
|
||||
`wall` carries a **flavour-only** `tryInteractFunction` ("You touch the wall.
|
||||
It's cold and rough."), so flag-first classification promoted every wall segment
|
||||
into Interactables — 13 in the starting house, burying the chest and cauldron.
|
||||
**Fix: exclude structural tiles (`blocksMovement and blocksVision`) before the
|
||||
`tryInteract` test.** Containers and furniture block movement but not sight, so
|
||||
they survive. 13 kinds/32 instances → 12 kinds/19 instances.
|
||||
`docs/05-decisions.md` D4 has been amended.
|
||||
|
||||
*(Not a bug: Items/Alchemy are empty in the tutorial house because
|
||||
`chest_tutorial` literally prints "find nothing of use for now" — it has no loot
|
||||
yet. Verify against a later area before trusting those two categories.)*
|
||||
|
||||
### Known gaps (next up)
|
||||
- **Phase 3: object tracker** — the headline feature, not started.
|
||||
- Wall tone retrigger fix not yet confirmed by ear.
|
||||
- `ingame` itself has no descriptor (player status: HP, statuses, current action).
|
||||
- **Phase 4**: descriptors for `worldmap`, `journal`, `character`, `research`,
|
||||
`inventory`, `craft`, `refine`, `trade`, `actions_menu`, `alchemy_table`,
|
||||
`keybindings_menu`, `config_menu`, `menu_text`, `ingame_message`,
|
||||
`menu_message`. (`inventory`/`craft`/`refine`/`trade` are partly covered
|
||||
already by the `inventoryCursorPopup` patch.)
|
||||
- **Phase 5**: player status key (HP, statuses, current action), popup
|
||||
announcements, damage alerts, mod settings.
|
||||
- `ingame` itself has no descriptor.
|
||||
- Tracker categories Items/Alchemy/Exits/Creatures/Terrain unverified against a
|
||||
populated area — the tutorial house has none of them.
|
||||
- `worldmap`, `journal`, `character`, `research`, `inventory`, `craft`, `refine`,
|
||||
`trade`, `actions_menu`, `alchemy_table`, `keybindings_menu`, `config_menu`,
|
||||
`menu_text`, `ingame_message`, `menu_message` still have no descriptors.
|
||||
|
||||
Reference in New Issue
Block a user