Files
alchemist-accessibility/accessibility/docs
Accessibility ModandClaude Opus 5 81a209b600 tracker: sticky selection and Ctrl+Home walk-to; walltones: conventional volume
Tracker selection now survives a rescan. The scan is rebuilt every turn and
both lists are distance-sorted, so holding a bare index meant one step by the
player silently re-pointed the selection at a different rat. The tracker now
remembers identity instead -- the actor table for creatures, coordinates for
tiles -- and re-derives the indices in reanchor() after each rescan. Selection
is dropped only when the thing genuinely stops being reported (out of FoV,
killed, picked up), and the existing clamp then falls back to the nearest.

Ctrl+Home walks to the selection, reusing the exact shape of the game's own
click-to-path in ingame.mousepressed: calculatePathFromPlayer, then either
bufferInput or playerInput for a one-step path. Interruptions and threatened-
player truncation therefore behave the way a mouse click does. Most things
worth tracking stand on impassable tiles, which calculatePathFromPlayer refuses
outright, so we fall back to the cheapest of the 8 neighbours and say "next to"
rather than "to". Guarded on states.getCurrent() == "ingame": elsewhere the
input buffer belongs to another state and feeding it moves would be a bug.

Wall tones now follow the usual proximity convention -- a near wall is loud,
one out at radius is quiet. It was inverted, which read backwards in play since
a nearby wall is the more urgent fact. config.louderWhenFurther still flips it.

Testbed covers both: selection identity across a forced rescan, and that
Ctrl+Home moves the player without breaking out of the map.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 01:00:25 +02:00
..
2026-08-01 22:25:09 +02:00
2026-08-01 21:34:13 +02:00
2026-08-01 22:25:09 +02:00

Accessibility mod — developer documentation

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 first. It is the living handoff document: current state, every bug found and why, and the traps.

Doc Contents
scratch.md Start here. Working state, bugs found, gotchas, keymap, how to run the testbed.
01-architecture.md How the game is built: states, console, level model, keybindings.
02-hooking-strategy.md How the mod attaches with (near) zero edits to game files.
03-implementation-plan.md The original six-phase plan, with outcomes.
04-open-questions.md Questions raised; see 05 for answers.
05-decisions.md Decisions made, and the D4 correction.

Status

Phases 0–5 complete. 23 state descriptors, 5 patches, 26/26 testbed checks, history unit tests passing.

Game-file footprint: one line in main.lua. Verify at any time:

git diff --stat vanilla-0.4.2 -- . ':!accessibility' ':!.gitignore'

The three findings that shaped everything

  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 required 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.