2026-08-01 22:25:09 +02:00
|
|
|
|
# Accessibility mod — developer documentation
|
2026-08-01 20:28:30 +02:00
|
|
|
|
|
2026-08-01 22:25:09 +02:00
|
|
|
|
Making *Sulphur Memories: Alchemist* 0.4.2 blind-accessible.
|
|
|
|
|
|
Player-facing keymap and setup: `accessibility/README.md`.
|
|
|
|
|
|
|
|
|
|
|
|
**Picking this up mid-stream? Read [scratch.md](scratch.md) first.** It is the
|
|
|
|
|
|
living handoff document: current state, every bug found and why, and the traps.
|
2026-08-01 20:28:30 +02:00
|
|
|
|
|
|
|
|
|
|
| Doc | Contents |
|
|
|
|
|
|
|---|---|
|
2026-08-01 22:25:09 +02:00
|
|
|
|
| [scratch.md](scratch.md) | **Start here.** Working state, bugs found, gotchas, keymap, how to run the testbed. |
|
2026-08-02 02:16:21 +02:00
|
|
|
|
| [00-dev-setup.md](00-dev-setup.md) | **Setting up.** The two trees, prerequisites, building the dev tree, everyday commands, publishing. |
|
2026-08-01 22:25:09 +02:00
|
|
|
|
| [01-architecture.md](01-architecture.md) | How the game is built: states, console, level model, keybindings. |
|
|
|
|
|
|
| [02-hooking-strategy.md](02-hooking-strategy.md) | How the mod attaches with (near) zero edits to game files. |
|
|
|
|
|
|
| [03-implementation-plan.md](03-implementation-plan.md) | The original six-phase plan, with outcomes. |
|
|
|
|
|
|
| [04-open-questions.md](04-open-questions.md) | Questions raised; see 05 for answers. |
|
|
|
|
|
|
| [05-decisions.md](05-decisions.md) | Decisions made, and the D4 correction. |
|
2026-08-01 20:28:30 +02:00
|
|
|
|
|
2026-08-01 22:25:09 +02:00
|
|
|
|
## Status
|
2026-08-01 20:28:30 +02:00
|
|
|
|
|
2026-08-02 02:16:21 +02:00
|
|
|
|
**Phases 0–5 complete.** 23 state descriptors, 5 patches, 34/34 testbed checks,
|
2026-08-01 22:25:09 +02:00
|
|
|
|
history unit tests passing.
|
2026-08-01 20:28:30 +02:00
|
|
|
|
|
2026-08-01 22:25:09 +02:00
|
|
|
|
**Game-file footprint: one line in `main.lua`.** Verify at any time:
|
2026-08-01 20:28:30 +02:00
|
|
|
|
|
2026-08-01 22:25:09 +02:00
|
|
|
|
```
|
2026-08-02 01:04:25 +02:00
|
|
|
|
git diff --stat vanilla-0.4.2 -- . ':!accessibility' ':!.gitignore' ':!CLAUDE.md'
|
2026-08-01 22:25:09 +02:00
|
|
|
|
```
|
2026-08-01 20:28:30 +02:00
|
|
|
|
|
2026-08-01 22:25:09 +02:00
|
|
|
|
## The three findings that shaped everything
|
2026-08-01 20:28:30 +02:00
|
|
|
|
|
2026-08-01 22:25:09 +02:00
|
|
|
|
1. **The game was already keyboard-complete.** All 28 states implement
|
|
|
|
|
|
`keypressed`, with a full rebindable-keys system. The gap was that nothing
|
|
|
|
|
|
*announced* what was focused — so the job was narration, not reimplementation.
|
|
|
|
|
|
|
|
|
|
|
|
2. **The game already writes the text.** `console.print` is a single chokepoint
|
|
|
|
|
|
for all log messages; `level.getCursorMessage()` describes tiles;
|
|
|
|
|
|
`inventoryCursorPopup.set` covers four screens. Mostly we re-route existing
|
|
|
|
|
|
strings to speech rather than writing a description engine.
|
|
|
|
|
|
|
|
|
|
|
|
3. **Everything is a `require`d singleton, and `debug.getupvalue` works.** Module
|
|
|
|
|
|
functions can be patched in place, and file-local focus variables
|
|
|
|
|
|
(`selectedOption`, …) are readable from outside. Hence the one-line footprint.
|
|
|
|
|
|
|
|
|
|
|
|
## Architecture in one breath
|
|
|
|
|
|
|
|
|
|
|
|
`main.lua` calls `require("accessibility").initialize()`. That patches module
|
|
|
|
|
|
singletons (`console.print`, `popupStack.add`, `inventoryCursorPopup.set`,
|
|
|
|
|
|
`modules.slider`), wraps `states.switch` / `update` / `keypressed` / `textinput`,
|
|
|
|
|
|
and installs a global hotkey layer. Per-screen narration lives in
|
|
|
|
|
|
`accessibility/states/<statename>.lua` descriptors, read via `debug.getupvalue`.
|
|
|
|
|
|
A startup self-test reports which patches and probes still resolve — the canary
|
|
|
|
|
|
for a future game version moving something.
|