Files
alchemist-accessibility/accessibility/states/ingame_observe.lua
T
Accessibility ModandClaude Opus 5 8b1eb44c38 Phase 2: tile examination and surroundings
Game-file footprint unchanged: still one line in main.lua.

- describe.lua: shared spatial formatting. 8-point compass and Chebyshev
  distance, since the game moves 8-directionally and Euclidean would overstate
  diagonal travel. Verbosity setting, because sweeping eight neighbours and
  inspecting a single tile want different amounts of detail.
- states/ingame_observe.lua: narrates the game's existing examine cursor.
- surroundings.lua: probe one direction, scan all eight, or report location,
  without moving anything or touching game state.
- patches/popups.lua: wraps inventoryCursorPopup.set, covering inventory, craft,
  refine and trade in a single patch.

Q3 resolved as augment rather than relay: the game's descriptions carry no
position, which is fine on screen and useless by ear, so distance and direction
are appended.

Examine mode is polled rather than driven by levelCursorPopup. That popup is set
from an animation-completion callback, so unless the player has enabled the
game's quickExaminationPopup option the text arrives a full keypress late -- in
testing you heard the previous tile while standing on the next. Polling
level.cursorX/Y is same-frame and setting-independent.

hotkeys.isCtrlDown/isShiftDown are now overridable fields rather than direct
love.keyboard calls: real hardware state cannot be faked by love.event.push, so
without that seam every modifier-gated hotkey would be untestable.

11/11 testbed checks, history unit tests passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 21:26:35 +02:00

44 lines
1.4 KiB
Lua

-- states/ingame_observe.lua — the examine cursor.
--
-- Reads the cursor position straight off the level model rather than listening to
-- levelCursorPopup.set.
--
-- Why: the popup is set from an animation-completion callback (`onFinish`), so
-- unless the player has turned on the game's "quickExaminationPopup" option, the
-- text arrives only after the cursor finishes gliding. In testing that put each
-- announcement a full keypress behind -- you would hear the previous tile while
-- standing on the next one. Polling cursorX/cursorY announces on the same frame
-- the cursor moves, regardless of that setting, and needs no game edit.
--
-- The level model is a closure instance rather than a module, so it cannot be
-- patched at require time; reading its public fields is the decoupled route.
local describe = require("accessibility.describe")
return {
read = function()
local ok, world = pcall(require, "models.world")
if not ok or not world.currentLevel then
return nil, nil
end
local level = world.currentLevel
local x, y = level.cursorX, level.cursorY
if type(x) ~= "number" or type(y) ~= "number" then
return nil, nil
end
local player = level.playerActor
local px = player and player.x
local py = player and player.y
local text = describe.tile(level, x, y, px, py)
if not text or text == "" then
return nil, nil
end
return text, x .. "," .. y
end,
}