Answers given, and their consequences. Supersedes the corresponding entries in `04-open-questions.md`.
---
## D1 (was Q1) — Development uses system LÖVE
Dev setup: `C:\Program Files\LOVE\love.exe` (11.5, matches `build.lua`'s `love = '11.5'`), running the source folder directly. `lovec.exe` in the same directory gives a console window and is what we'll use for debugging.
Tolk DLLs therefore go **next to `love.exe` in `C:\Program Files\LOVE\`** — that's the executable directory the OS loader searches. (Copies available at `D:\code\cafe`, `D:\code\dragonrpg-mapmaker`, `D:\code\DragonWarriorAccess`.) Needs an elevated copy, one time.
Distribution deferred until the mod works. Noted for later: whatever we ship must place the DLLs beside the executable, so a plain `.love` file can never be the whole delivery.
| Instance | `Shift+PgUp` / `Shift+PgDn` | that specific rat at (12,7) |
| — | `Home` | announce distance + direction of current instance |
Categories accepted: **Creatures / Items / Exits / Interactables / Terrain features / Alchemy**, conditional on covering everything. See D4 for the coverage check.
---
## D3 (was Q7 + Q10) — Small patches now, upvalue probing kept as a fallback layer
Decision: use **small explicit patches** in game state files where they genuinely simplify things — but keep the option of switching to zero-edit operation, in case the game ships on Steam and editing files stops being practical for end users.
### Why Steam changes things
A Steam LÖVE release is normally a **fused executable** (the `.love` archive appended to `love.exe`). Editing game source then means unpack → patch → repack → replace the exe, which Steam's file integrity check may revert on next update. That's a bad end-user story, and it's exactly the scenario the upvalue technique was designed for.
### The design that keeps both doors open
Make the **state descriptor** the single abstraction, and let each descriptor declare *how* it gets focus — with two interchangeable backends:
```lua
-- accessibility/states/main_menu.lua
return{
title="Main menu",
-- Backend A (preferred): the patched game file calls access.announce(...) directly.
-- Backend B (fallback): read the same values as upvalues, no game edit needed.
return("%s, %d of %d%s"):format(entry.title,i,n,entry.isEnabledand""or", unavailable")
end,
}
```
`render` — the part that carries all the per-screen knowledge — is **identical for both backends**. Switching modes is a global config flag, not a rewrite:
-`mode = "patched"` → the driver trusts `access.announce(entry, i, n)` calls injected into game files.
-`mode = "probe"` → the driver wraps `states.keypressed`, reads upvalues via `debug.getupvalue`, and calls the same `render`.
This costs us little now (we write `render` either way, plus a ~40-line probe driver) and means a Steam release is a config change plus fixing whichever probes drifted — not a redesign.
### Consequences
- Patches stay **mechanical and uniform**: a single `access.announce(...)` line per focus-change site, nothing else. Easy to read in a diff, easy to re-apply.
- The git baseline (`vanilla-0.4.2` tag) becomes load-bearing — it's how we rebase patches onto a new version. Do this in Phase 0.
- The **startup self-test** is still required, and now checks both backends: which patch sites are present, and which probes still resolve. This is the version-bump canary either way.
- Upstreaming to Spellweaver stays viable, since the patches are small and additive. Worth revisiting once there's something working to show.
---
## D4 — Category coverage check (the condition on D2)
I classified all tile templates statically to confirm the six categories don't leave gaps.
**Scale is much smaller than the line counts suggested:**
231 tile templates is very tractable — the line count is inflated by inline behaviour functions, not by breadth.
**Parent inheritance is already flattened for us.**`modules/tile/preprocess.lua` copies every missing field down from `template.parent` at load time. Since `main.lua` runs `preprocessTileTemplates()` during `love.load`, by the time our code runs, `require("modules.tile.templates")` gives fully-resolved templates — we read `template.name` / `template.description` / flags directly with no chain-walking.
*(Minor upstream quirk noticed: the flatten is a single pass over `pairs()`, so a grandchild template may inherit from a not-yet-flattened parent depending on hash order. Pre-existing game behaviour, not ours to fix — but if a template ever looks oddly under-specified, this is why.)*
**Only 6 templates are genuinely un-nameable** (no name, no description, no parent) — all invisible mechanics that *should* be excluded from tracking:
**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.
---
## Still open
From `04-open-questions.md`: **Q3** (verbosity: relay vs. augment), **Q4** (console auto-speak policy), **Q5** (wall tone triggers), **Q6** (keybinding integration), **Q8** (full keyboard audit as explicit deliverable?), **Q9** (which screen reader; do you want me running the game during dev).
None of these block starting Phase 0. Q5 and Q9 become relevant at Phase 2; Q4 at Phase 1.