Files
alchemist-accessibility/accessibility/README.md
T
Accessibility ModandClaude Opus 5 5778e86e8e orientation: the travel map, unexplored ways, the nearest exit
Prompted by "do sighted players have a minimap we don't have access to?"
No widget, but two map surfaces were only half exposed: the world map
screen, and the level view itself, which IS the explored-floor map --
rememberedFoV keeps everything ever seen drawn, and a sighted player pans
over it and reads the fog edge at a glance.

The world map dropped the three things the picture carries: what kind of
place each area is (the icon shape), which way it lies, and how long
travelling there takes. The last is the number the decision turns on and
was only ever in the side panel. states/worldmap.lua is now a read() plus
details() rather than probe/render -- necessarily, because render() gets
no state table and the travel time needs the screen's currentAreaId, an
upvalue like options and selectedOption. Travel time is the game's own
getDistanceMessage, the same call the screen makes. The blurb runs to
several sentences, so it goes on = and the settle timer instead of the
focus line.

Two gotchas: options[i].icon is already an image object, so the icon id
string has to come off the model area; and describe.direction only tests
the sign of each delta, which on the map's floating-point coordinates
called almost everything diagonal, hence a 25% deadzone carrying the same
4/3 x-correction the game's own distance maths uses.

New frontier.lua answers "where haven't I been", which nothing did:
surroundings is local, examine is one tile, and the tracker only finds
things it already knows about. A frontier tile is seen, not blocking
movement, with an in-bounds unseen CARDINAL neighbour -- cardinal because
the diagonal test fires on the unseen tile behind every wall corner, so a
lit corridor would report an unexplored way per corner. Clustered
8-connected and reduced to each cluster's nearest member, so a wide
doorway is one way but two openings that both lie north stay two. Reads
only FoV/rememberedFoV and reports only THAT an opening exists, never
what is beyond it -- exactly what the fog edge shows.

Shift+End names the nearest exit without disturbing the tracker
selection. Note for later: level.exits does not exist at runtime, it is
packed as nil and never assigned. The primitive is the game's own
getListByTag("exit"), which already gates on FoV or rememberedFoV, skips
hidden tiles and sorts by distance. Exits were already a tracker
category, so this is a shortcut rather than a new capability.

"remembered" moves from verbose to normal verbosity. tileFacts reads
actors only when a tile is currently VISIBLE, so a remembered tile is
silent about whatever may be standing on it now, and at normal verbosity
that silence was indistinguishable from "nothing there". A safety flag,
not a nicety.

Also adds descriptor.probeNames: a read() descriptor has no probe table,
so menus.selfTest could only report "custom read()" and the version-bump
canary was lost on exactly the screens reaching for the most upvalues.
worldmap and research now declare their game locals and get the same
PROBE BROKEN check.

120 testbed checks, 0 failures. It caught two things review had not. The
world map said "You are currently here." twice, because
getDistanceMessage and getLastVisitedMessage return the same sentence for
the area you are standing in -- fine as two panels on screen, a stutter
in one utterance. And the first frontier check walked a step east and
demanded the numbers change; it failed on a run where nothing was wrong,
the step landing but both openings keeping the same Chebyshev distance.
Replaced with the deterministic property: every reported distance must
equal Chebyshev from the player's current position, nearest first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 16:05:15 +02:00

13 KiB
Raw Blame History

Accessibility mod — Sulphur Memories: Alchemist

Blind-accessibility mod adding screen-reader speech, an object tracker, tile exploration and directional wall tones.

Speech goes through Tolk, so it uses your running screen reader (NVDA, JAWS, System Access) and falls back to SAPI 5 if none is running.

Running

"C:\Program Files\LOVE\love.exe" "D:\code\Sulphur Memories Alchemist 0.4.2 sanctified"

Use lovec.exe instead of love.exe to get a console window — every spoken line is mirrored there, which is useful for reporting bugs.

The TTS libraries live in accessibility/lib/ and are loaded by absolute path, so nothing needs installing or copying into Program Files.

If speech does not work, check the console for the startup self-test:

[accessibility] TTS: available
[accessibility] speech channel: yes

speech channel: NO means Tolk loaded but found no screen reader and no SAPI.


Keys added by the mod

All of these are in addition to the game's own controls, and none of them replace a key the game uses.

Reading the message log

Key Action
[ Previous message
] Next message
Shift+[ Oldest message
Shift+] Newest message (and resume following new messages)
\ Repeat the current message
Shift+\ Copy the current message to the clipboard

New messages are spoken automatically. Pressing any key that does something in the game cancels whatever is still queued, so you are never stuck listening to a backlog. While you are moving through the history, new messages do not drag the cursor away — press Shift+] to return to the newest.

Looking around

Key Action
/ Scan all eight neighbouring tiles, clockwise from north
Shift+/ Cycle automatic announcements of what comes in and out of view
; Where am I — area name, in-game date and time, coordinates
Ctrl + numpad 1–9 Describe the tile in that direction without moving
Ctrl + numpad 5 Describe the tile you are standing on
End Unexplored ways — where there is still somewhere to go
Shift+End The nearest way out of this level

Getting your bearings on a whole floor (End)

/ and the numpad probes tell you about the tiles beside you. End tells you about the floor: it looks at everywhere you have already been, finds the places where explored ground runs up against ground you have never seen, and reads them out nearest first.

3 unexplored ways: 6 tiles north, 11 tiles south-west, 14 tiles east

Each "way" is one opening, so a wide doorway counts once rather than three times. When there is nowhere left to go you get No unexplored ways from here, which is usually the moment to take Shift+End and leave.

This never tells you anything about ground you have not seen — only that there is still a way through. It is the same thing a sighted player reads off the edge of the explored area on screen.

Shift+End names the nearest exit you know about, how far away it is, and how many steps it takes to walk there. Exits are also a tracker category (below), so Shift+End is a shortcut rather than the only route — and it deliberately leaves whatever you were tracking untouched.

Announcing things as they come into view (Shift+/)

/ tells you what is around you now. Shift+/ decides how much of that happens by itself as you walk, cycling three settings:

  • View announcements when you stop (the default) — changes pile up while you are moving and are read out once you have stood still for a moment. A single step reports as soon as the step lands. A ten-tile walk gives you one combined summary at the end rather than ten reports on top of each other, and it is a net change: something that came into view halfway along and went out again before you stopped is not mentioned.
  • View announcements on every step — each step reports its own change. Best when you are creeping along carefully; too talkative for crossing a room.
  • View announcements off.

You hear things arriving — In view: a rat, 4 tiles north-east. barrel, 3, nearest 2 tiles east — and creatures leaving: Out of view: a rat. Only creatures are reported when they leave. Furniture drops out of sight constantly as walls come between you and it, and being told the bed is out of view every other step would bury everything useful; a creature you can no longer see is worth knowing about.

These announcements are queued rather than urgent, so anything you asked for yourself is spoken first, and any key that acts in the game clears them.

Nothing outside your current field of view is ever reported.

Seeing inside containers (the game's own s)

The game's tutorial tells you to press s to see the contents of containers. For a sighted player that draws the icon of whatever is inside every chest, sack and pile you can see, straight onto the map. Pressing it now speaks the same thing, nearest first:

A wooden chest, 2 tiles east, A bunch of ivy leaves, 3, A torch.
A burlap sack, 5 tiles north-west, Coarse salt

or No loot in view when there is nothing to find, so you can tell the key worked rather than wondering whether it was dropped.

The icons can only show one item per container; you get the whole list. Each container is also pushed into the message history, so [, ] and \ walk back through a long list after it has been read out.

This is your own key — whatever you have Highlight loot bound to in the game's controls, and however you have set "highlight overlays require holding the key". Clicking the toolbar icon works too. It also works in examine mode and while aiming. Only containers you can currently see are reported.

The game's own examine mode (x) is also fully spoken: the arrow keys move a cursor around the map and each tile is described with its distance and direction from you. Press f in examine mode to jump between exits.

Object tracker

Finds everything you have seen, sorted by distance.

Key Action
Ctrl+PageUp / Ctrl+PageDown Previous / next category
PageUp / PageDown Previous / next kind of thing in that category
Shift+PageUp / Shift+PageDown Previous / next instance of that kind
Home Distance, direction, and number of steps by path
Ctrl+Home Walk to it
Shift+End The nearest exit, without changing your selection

Categories: Creatures, Items, Alchemy, Interactables, Exits, Terrain features.

So Ctrl+PageDown to reach "Creatures", PageDown to move between rat / beetle / guard, and Shift+PageDown to step through the individual rats. Home gives you the walking distance, which indoors is often very different from the straight-line distance.

Ctrl+Home does exactly what left-clicking the tile does with a mouse: it queues a walk along the game's own path. If the thing itself cannot be stood on — a creature, a chest, a bed — you walk to the nearest tile beside it instead, and the announcement says "next to" rather than "to". As with a mouse click, the walk stops early if something interrupts you, and while an enemy is in view the game only ever commits one step at a time.

Your selection sticks. The list is rebuilt and re-sorted by distance every turn, but the tracker follows the thing you picked rather than the slot it was in, so a rat you are tracking stays selected as it moves around. It is only let go when it genuinely stops being visible.

The tracker only ever reports things you have actually seen.

The journal (j)

The journal has three parts, and all three are spoken:

Key Moves
q / e Between tabs — Quests, Lore, Bestiary, Components, Recipes, Tutorials
Up / Down Between entries in the current tab
Left / Right Between pages of the selected entry

Selecting an entry reads its title, its position in the list, and then the text of the page itself. The tab name is only spoken when you change tabs, and the title only when you change entry, so flipping pages doesn't make you sit through the heading again.

Long entries run to several pages; you are told page 2 of 3 when there is more than one. The page text also goes into the message history, so [ and ] will walk back through it and \ re-reads a line — useful for a long lore entry you want to take in a piece at a time.

The inventory (i)

Moving the cursor reads the item under it, or empty, plus the slot number: a torch, slot 3. q / e change tab, and the tab name is spoken when it changes. An item you are currently wearing, wielding or have switched on is read as equipped.

Pressing enter (or z) on an item opens a small menu of the things you can do with that item right now — the list is different for every item, and changes with its state. It is read as, for example:

a torch, actions, Switch on, 1 of 2

Up and Down move through the actions, enter performs the selected one, and any other key closes the menu without doing anything. After the action runs you hear the item again, so Switch on is followed by a torch, equipped, slot 3 — that is your confirmation it worked.

Some items have no actions at all (plain crafting reagents, for instance). For those, enter does nothing whatsoever in the base game — not even a click — so the mod says a pinch of sulphur, no actions rather than leaving you wondering whether the key registered.

Common actions include Activate, Wield, Unwield, Wear, Take off, Switch on, Switch off, Drink, Eat, Apply, Read, Open, and Prepare for throwing / Pack away. Equipping is done from here — there is no separate equipment screen.

Item details (=)

Key Action
= Read the full details of the item under the cursor
Shift+= The same, including the item's name

Reading the cursor only tells you which item you are on. The details tell you what it is: what kind of thing it is, its condition if it can wear out, its description, and — the useful part for alchemy — what it turns into, listed per refinement method:

It is a raw material. Some fresh green leaves from ivy. They contain weak
poison. Yields: x1 when ground in a mortar. x0.2 when distilled.

On the crafting, refining and trading screens the details also read the panel beside the grid, which is where the game keeps the things you most need before committing: a recipe's components and whether you can afford them, what a refinement produces and how much of it you already have, and — in a shop — the price, which appears nowhere else.

The same key works on the research tree at the writing desk, where the focus line only tells you the node's name and whether you can afford it. The details read the rest of what is on screen: what it costs in knowledge and how much you are short by, which recipes it unlocks, and its description. Shift+= adds the node's name and your full knowledge stock across all four types.

Costs 5 practical, 2 academic, 2 occult knowledge, short 2 occult. Unlocks
Sinister gauntlets, Verdant sandals. Clothing with supernatural attributes can
be created by infusing the weave with magical powers.

You do not have to press = every time. Stop on an item for about half a second and the details are read to you automatically, which is what the game does for a sighted player: its own detail popup only appears after you have hovered a slot for a moment. Arrow through a tab quickly and you hear only the names, exactly as a sighted player sees only the icons.

Details also go into the message history, so [ and ] walk back through a long description a piece at a time and \ re-reads a line.

The travel map

The map of Rimesia you get when you leave an area is a picture: icons scattered across a painting, with a panel beside them. Arrowing through the list now reads what the picture says.

Blackreed Mire, swamp, 2 of 9, north-east, Travel will take 1 day and 6 hours,
Visited 3 days ago
  • what kind of place it is — town, crypt, mine, shipwreck, witchwood — which on screen is only the shape of the icon;
  • which way it lies from where you are standing now;
  • how long the journey takes, which is the number the decision actually turns on and which was previously only in the side panel;
  • when you were last there, which on a map full of similar-sounding names is often the only way to tell them apart.

The area's description is longer, so it is not read every time you move the cursor. = reads it, and stopping on an area for half a second reads it by itself — the same way item details work.

Your character

Key Action
' Health and active effects
, Currently selected action

You are also told automatically when you take damage or are healed.

Wall tones

Each step you take, a tone sounds from the direction of any wall within five tiles, positioned in 3D so you can hear where it is. Further walls are louder.


Reporting problems

Run with lovec.exe and include the console output. Lines beginning [speech] show exactly what was spoken and when:

  • [speech]! — interrupted whatever was being said
  • [speech]* — urgent alert, spoken immediately
  • [speech] — queued normally

If something is silent that should not be, that is the most useful thing to report, together with the screen you were on and the key you pressed.


For developers

See accessibility/docs/ — start with docs/README.md, and read docs/scratch.md first if you are picking the work up mid-stream.