viewwatch: announce objects entering and leaving view while walking
Walking blind, the hard part is not "what is next to me" -- that is `/` --
but "what changed when I moved". Rounding a corner reveals a room, stepping
back hides it, a rat walks into sight behind you, and none of it is spoken.
Shift+/ cycles three modes:
settled (default) changes accumulate while moving, spoken once you have
stood still for 0.4s
always every step reports its own change
off
`settled` diffs against the state at the last ANNOUNCEMENT, not the last
step, so a long walk gives one combined summary that is a genuine net
change: something that came into view mid-walk and left again before you
stopped is not mentioned, and something visible throughout is mentioned
once. Summing per-step diffs would report both. A single step is the
degenerate case -- you are already standing still.
Arrivals and departures are deliberately asymmetric. Membership is current
FoV only (never rememberedFoV), but furniture drops out of FoV constantly
indoors as walls come between you and it, and "the bed is out of view"
every other step is noise. Arrivals are reported for every watched
category; departures only for creatures.
Terrain is unwatched by default -- water arrives dozens of tiles at a time.
Step detection polls playerActor.x/y as walltones does, so pathing, portals
and pushes are covered with no game function wrapped; the scan is a 14-tile
box and runs only on a step or a due settle, never per frame.
snapshot() and diffText() are pure and exposed so the testbed can assert
the wording and the FoV invariant directly instead of capturing speech.
34/34 testbed checks, 0 failures. Game footprint unchanged: main.lua | 1 +.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
86c71fc001
commit
973e62c8fe
@@ -592,6 +592,55 @@ local function scenario()
|
||||
"slider patch applied but not exercised")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- View watch (Shift+/): what comes in and out of view while walking
|
||||
--
|
||||
-- Asserted on the pure seam (snapshot / diffText) rather than on
|
||||
-- speech, because whether a given step actually reveals anything
|
||||
-- depends on where the earlier part of the scenario left the player.
|
||||
-- The invariant and the wording are checkable regardless.
|
||||
------------------------------------------------------------------
|
||||
if currentState() == "ingame" then
|
||||
local viewwatch = require("accessibility.viewwatch")
|
||||
|
||||
local snapshot, level = viewwatch.snapshot()
|
||||
local count = 0
|
||||
local leaked = nil
|
||||
|
||||
for _, entry in pairs(snapshot or {}) do
|
||||
count = count + 1
|
||||
if not (level.FoV and level.FoV[entry.x] and level.FoV[entry.x][entry.y]) then
|
||||
leaked = entry.name
|
||||
end
|
||||
end
|
||||
|
||||
check("viewwatch sees the room", count > 0, count .. " things in view")
|
||||
|
||||
-- Invariant 4: nothing outside FoV may ever be reported.
|
||||
check("viewwatch reports nothing outside FoV", leaked == nil,
|
||||
leaked and ("leaked " .. leaked) or "clean")
|
||||
|
||||
-- Diff against an empty baseline: everything visible is "entered".
|
||||
local player = level.playerActor
|
||||
local text = viewwatch.diffText({}, snapshot, player.x, player.y)
|
||||
check("viewwatch phrases arrivals",
|
||||
text ~= nil and text:find("In view: ") == 1,
|
||||
tostring(text))
|
||||
|
||||
-- Nothing changed against itself: no announcement.
|
||||
check("viewwatch is silent when nothing changed",
|
||||
viewwatch.diffText(snapshot, snapshot, player.x, player.y) == nil,
|
||||
"nil")
|
||||
|
||||
local startMode = viewwatch.getMode()
|
||||
for _ = 1, 3 do
|
||||
viewwatch.cycleMode()
|
||||
end
|
||||
check("Shift+/ cycles three modes back to the start",
|
||||
viewwatch.getMode() == startMode, viewwatch.getMode())
|
||||
print("[testbed] viewwatch: " .. tostring(text))
|
||||
end
|
||||
|
||||
if sliderTested then
|
||||
check("slider announces value changes", true, "via ingame_wait")
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user