Makes Sokoban far less tedious when you don't have to worry about
monsters randomly popping up in the trap hallway while you're pushing
the boulder.
Adds a new exclusion zone for monster generation, and the goodpos
routine avoids the zones when GP_AVOID_MONPOS is used.
I forgot to add the code to flip the exclusion zones when implementing them.
Also improve the zone coordinates so they're correct outside of map contents.
If the saved game menu has more than 13 games, it won't be able to
use 'n' for "new game" and 'q' for "quit". Switch to 'N' and 'Q'
instead of just using the next letters in sequence. Only resort to
next-letters if there are more than 39 games.
tty and curses handle a list of many save files via menu pagination.
X11 does so with one long page possessing a scroll bar. If there
are more than 52 entries, selection via mouse is needed beyond 'Z'.
Qt has one page without any scroll bar so won't provide access to
the full set of save files when there are too many to fit on the
screen.
Slightly simplify yesterday's message adjustment made when a monster
takes off a piece of armor and puts on a different instance of the
same type of armor. ("a|an <something>" -> "another <something>")
On the Windows GUI (nethackw.exe), while running the fuzzer,
if the NetHack window gets minimized, or someone minimizes all
desktop windows, the NetHack window stops responding and won't
even repaint itself. The NetHack process continues to use the
CPU.
A break in the debugger shows that it is caught in a do loop.
I didn't delve into the issue of why minimizing the window
triggers a condition that leads to the endless loop. This
just adds a kludge to exit the loop while fuzzing.
While testing the Demonbane change, I saw
| The Angel of Crom removes a robe and puts on a robe.
which looks a bit silly. Change that to be
| The Angel of Crom removes a robe and puts on another robe.
when the two items have the same formatted description. (The second
robe evidently has a better enchantment than the first one.)
Back then Demonbane was a long sword, lawful Angels and Archons
could get either it or Sunsword as part of their starting equipment.
After it got changed into a mace instead, they could only get
Sunsword. Rather than always giving them a long sword, sometimes
give them a mace so that they get back the chance to start with
Demonbane.
Since mace is quite a bit weaker that long sword against large
opponents, provide a better enchantment for maces given to lawful
minions.
The role, race, gender, and alignment string values are 3 letters
preceded by a dash. I was looking at "name-race-role-gend-algn"
and mistakenly treated them as 4 letters preceded by a dash.
Fixing that changes PL_NSIZ_PLUS and there is one item of that size
written into save files, so the fix invalidates existing save files.
Instead of a menu listing
a - hero1
b - hero2
n - New game
q - Quit
show
a - hero1-role1-race1-gend1-algn1
b - hero2-role2-race2-gend2-algn2
n - New game
q - Quit
or
a - - hero1-role1-race1-gend1-algn1
b - X hero2-role2-race2-gend2-algn2
c - D wizard-role3-race3-gend3-algn3
n - New game
q - Quit
when any game in the list wasn't saved during normal play. (Those
are sorted by character name; the playmode is just coincidence.)
The dash for 'normal' doesn't look great but -/X/D are codes used in
entries written to paniclog. The whole playmode prefix doesn't look
particularly good but I suspect that most players relying on restore
via menu won't see it.
It should work when the character name has dashes in it but that
hasn't been properly tested.
The gender and alignment suffices reflect their value at the time of
save rather than at the start of the game. That might be considered
a bug but it was easiest.
Increments EDITLEVEL; existing save and bones files are invalidated.
sys/windows/windsys.c(419): warning C6387: 'hMod' could be '0':
this does not adhere to the specification for the function 'GetProcAddress'.
sys/windows/windsys.c(437): warning C28159:
Consider using 'GetTickCount64' instead of 'GetTickCount'.
Reason: GetTickCount overflows roughly every 49 days. Code that does not
take that into account can loop indefinitely.
GetTickCount64 operates on 64 bit values and does not have that
problem
sys/windows/consoletty.c: warning C6388: '&reserved' might not be '0':
this does not adhere to the specification for the function 'WriteConsoleA'.
sys/windows/consoletty.c(2514): warning C28159:
Consider using 'IsWindows*' instead of 'GetVersion'. Reason: Deprecated.
Use VerifyVersionInfo* or IsWindows* macros from VersionHelpers.
There must have been a reason once to guard against calling makelevel()
when the dungeon hasn't been initialized yet, but that doesn't seem to
be necessary these days. Calling Is_special() before init_dungeons()
is clearly a bug, so fix that.
The version of copy_bytes() in util/recover.c had fallen behind
the internal version in files.c which had received some
analyzer changes in 4bc5e26082 from
December 2022.
This synchronizes them, and addresses a couple of other static
analysis recommendations.
Make a macro version of suppress_map_output() to keep an extra
function call out of show_glyph().
Add a couple of missing '#undef's for onefile processing. display.c
still has a ton of macros that leak beyond its end of file.
The 'spot_monster' option (extra feedback for "accessibility") was
causing messages to be delivered during save, and they could end up
triggering unwanted "--More--" interruptions for tty.
I couldn't reproduce it but it was easy to see where it would happen.
This shuts such messages off in two ways. Only one should be needed
but I'm not sure which one it ought to be.
A pet with the hides-under attribute could hide under cursed objects
if it first moved reluctantly to their location. Also, the messages
seem contradictory:
| The cobra slithers reluctantly over a scroll labeled DUAM XNAHT.
| You see your cobra slither under a scroll labeled DUAM XNAHT.
First over, then under, but that was actually accurate; the monster
moved, then after it was on the pile it hid underneath.
Change hideunder() to not let pets hide under an object if it is
cursed or any object in its pile is cursed. Initially I was just
going to check the top item and the item directly beneath it, but
reluctance to move there extends to the whole pile so I made hiding
do so too.
Change the first message to move reluctantly "onto" an object since
"over" suggests that it has continued past the item, unless it is
actually flying or levitating so truly "over" the pile.
Crash triggered by fuzzer.
The Null value for not-hungry between "Satiated" and "Hungry" in the
array of possible hunger states caused a crash if C++ regex handling
was being used. With posixregex, it would pass benignly for tty but
crash for curses. I didn't check any other interface.
display.h -- bring an unused macro up to date
detect.c -- always call newsym() when searching or secret door
detection finds a trap rather than just when not blind
glyphs.c -- some formatting
pager.c -- lookat() behaves very strangely when single-stepping
in the debugger (gdb); this didn't help
Issue reported by ars3niy: an arrow trap covered by more than
one stack of arrows was described by farlook as "unexplored area".
Later simplified to any object pile with plain arrows on top; the
trap turned out to be irrelevant aside from producing a pile of
arrow stacks.
This problem turns out to be due to an off by 1 error introduced
into the xxx_is_piletop() macros when generic objects were added in
mid-January of last year, and plain arrow is the first real object
so suffered from the bug. Misclassifying the glyph at a specific
location also confused the #terrain command but it's the same bug.
Knowing what was wrong (map glyph was UNEXPLORED when it should
have been ARROW) wasn't sufficient to figure out the problem.
Without the simplified way of reproducing the problem, I would
never have managed to use 'git bisect' to find the offending commit
because that would have been too time consuming.
Fixes#1289
A poison gas breath attack that hits a wall would leave a 1x1 gas
cloud region at that wall spot.
Not always noticeable due to other spots along the zap path leaving
regions that blocked vision.
Changes to setuhpmax() a couple of days ago to deal with sanity_check
for "current hero health as monster better than maximum" ended up
triggering sanity_check about "current hero health better than maximum"
when gaining experience level(s) while polymorphed.
If the force_invmenu option is On for choosing an inventory item
and the set of likely candidates is only a subset of full inventory,
then "* (list everything)" is an extra menu choice. If the player
picks that, the menu is reissued showing entire inventory (with the
extra "* (list everyhing)" choice omitted this time).
When that happens, add "? (list likely candidates)" instead, so that
the menu can be toggled back to how it initially was.
If the menu allows choosing anything in inventory (the 'd' command,
for instance), it will already show full inventory and neither '*'
nor '?' gets included as helper choices.
Issue reported by ars3niy: non-fireproof water walking boots are
supposed to be destroyed if worn on lava, but a post-3.6 change
made that only happen if the hero died and left bones.
The boots remained intact if hero was fire resistant or survived
6d6 damage. Staying intact should only happen if they're fireproof.
This seems to work but each time lava_effects() gets modified it
becomes more fragile. Having deleted objects stick around doesn't
help with this problem, which is to keep an item which is being
stolen--and whose loss causes the hero to drop into lava--from
being burned up before being transferred to the thief's inventory.
Fixes#1291
timeout.c:550:1: warning: no previous prototype for ‘region_dialogue’ [-Wmissing-prototypes]
550 | region_dialogue(void)
| ^~~~~~~~~~~~~~~
../win/curses/curswins.c: In function ‘curses_destroy_win’:
../win/curses/curswins.c:202:33: warning: variable ‘dummyht’ set but not used [-Wunused-but-set-variable]
202 | int mapwidth = 0, winwidth, dummyht;
| ^~~~~~~
When hero is poly'd into a gremlin, using #monster at a fountain
location will clone a gremlin pet. Do the same at a pool location
(might not match the movie but if not, most likely because the
situation never came up). Also, do the same for #sit at either
fountain or pool.
Like stuck-in-wall, there might not be any place to move the hero
in order to escape a poison gas cloud. That could result in "fix
all troubles" becoming stuck in a loop. 3.6.something fixed the
stuck-in-wall case by temporarily conferring Passes_walls. Fix the
in-poison-region case by temporarily conferring Magical_breathing.
Not adequately tested...
I don't think that this fixes "#K4252: NH 3.7 Prayer Bug" where the
game hung during a couple out of scores of prayers. I didn't see
any other fix-trouble cases that seemed likely to remain unfixed
and end up with repair attempts retrying.