Skip to content

Backport NetHack fix: lookat() no longer clobbers bhitpos - #132

Open
lucien-ad-lucem wants to merge 1 commit into
NetHack-LE:mainfrom
lucien-ad-lucem:fix-lookat-bhitpos
Open

lucien-ad-lucem wants to merge 1 commit into
NetHack-LE:mainfrom
lucien-ad-lucem:fix-lookat-bhitpos

Conversation

@lucien-ad-lucem

@lucien-ad-lucem lucien-ad-lucem commented Oct 13, 2026 •

Copy link
Copy Markdown

NetHack 3.6.6's lookat() (src/pager.c) writes the global bhitpos, the position of a
missile in flight, for every monster glyph it describes. NetHack removed the write in commit
1dc9f73 ("fix #K4201 - bhitpos is clobbered by lookat()"); nothing reachable from lookat()
reads it. This PR applies the same four-line removal to the bundled source.

NLE reaches lookat() from rl_print_glyph() via do_screen_description() whenever
screen_descriptions is requested, so every screen flush describes every monster drawn.

Example: an unseen monster throws a boulder on a turn when visible monsters have moved. The
missile animation flushes the screen, the moved monsters are drawn, and each overwrites
bhitpos with its own square. The boulder continues from the last monster drawn and lands at
the wrong place; when that square is off the map, place_object() panics and the process
aborts with SIGABRT.

🤖 Generated with Claude Code

lookat() wrote bhitpos, the position of a missile in flight, for every
monster glyph it described, and nothing reachable from it reads the
value. NLE describes every printed glyph when screen_descriptions is
requested, so a missile's animation flushes overwrote its own position
with the squares of monsters drawn, sending it astray and, off the map,
into a place_object() panic. NetHack removed the write in 1dc9f73
("fix #K4201 - bhitpos is clobbered by lookat()"); this applies the
same removal to the bundled 3.6.6 source.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@lucien-ad-lucem

Copy link
Copy Markdown
Author

This also fixes #98 (segfault in launch_obj() when a monster triggers a rolling boulder trap), which #100 worked around with a bounds check.

launch_obj() animates each square of the roll with tmp_at(), which flushes the screen, so every monster drawn mid-roll moves bhitpos to its own square and the boulder continues from there. The trap's own path cannot leave the map (see the triage on NetHack/NetHack#1490: mkroll_launch() validates it).

I replayed the seed and the 352 recorded actions attached to #98 on NetHack 3.6.6 in two builds that differ only by this change (the action indices were mapped through the current action table). Without it: segfault on the last action, launch_obj called from mintrap. With it: the game continues with "You kill the bat! You hear rumbling in the distance.", the unseen-launch message. All observations before the last action are identical between the two runs.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant