PatR [Sat, 31 Aug 2019 17:46:35 +0000 (10:46 -0700)]
fix #H9164 - menu colors for curses perm_invent
Commit e3af33c9db313d288f6b86a35b8ee705376aebfb in June changed
curses handling for perm_invent to strip off doname()'s "a ", "an ",
or "the " prefix in order to shorten inventory entries and get a
couple of significant extra characters before end-of-line truncation.
That had an unintended impact on menu colors pattern matching for
patterns which expected the article prefix. Do the matching before
stripping off the prefix instead of after so that the matching gives
the same results as when used on a normal inventory menu (even though
this means that from the user's perspective most perm_invent entries
will have invisible text at the start).
Also for menu colors, don't require curses-specific 'guicolor' option
be enabled when the general, more-specific 'menucolors' option exists
to control menu coloring. (curses was requiring that both be True.)
PatR [Sat, 31 Aug 2019 08:38:19 +0000 (01:38 -0700)]
'O' vs perm_invent (mostly)
Update persistent inventory window if 'implicit_uncursed', 'menucolors',
or 'guicolor' is toggled. (curses should be changed to use menucolors
instead of guicolor to decide whether menu coloring is used. Right now
it requires that both be On.)
Also, EDIT_GETLIN was providing junk default response when message type
or menu color looped and prompted for another entry after handling one.
Mixed in with this is a fix for easily induced buffer overflow which
has security ramifications....
PatR [Sat, 31 Aug 2019 01:11:43 +0000 (18:11 -0700)]
fix #H9164 - crash during restore when swallowed
Subject was "display crash while in curses mode". Restoring with
perm_invent set in config file or NETHACKOPTIONS when the save was
made while swallowed (regardless of perm_invent at that time) resulted
in a crash when invalid u.ustuck was referenced before restoration had
done its pointer fixups.
init_nhwindows() is called with perm_invent On;
restgamestate() temporarily turns it Off (3.6.2 restore hack);
if/when update_inventory() gets called, curses notices that the
persistent window has been disabled so it tears down all its windows
in order to redraw the screen without that one;
docrt() sees non-Null u.ustuck and calls swallowed();
swallowed() tries to use the value of that pointer rather than just
Null/non-Null but the value is from the previous game session, not
valid for the current session;
crash.
Make yet another attempt to prevent update_inventory() from being
called during restore. curses won't try to redraw and the crash
won't happen. But the invalid pointer is still lurking (until an
eventual fixup later during restore).
An earlier fix for update_inventory() during restore actually handled
this problem (for the most common trigger, setworn(), but not in
general), so the 3.6.2 behavior is a regression.
PatR [Wed, 21 Aug 2019 00:16:57 +0000 (17:16 -0700)]
sys/unix/hints/*: mkfontdir and cp -n
Change all the POSTINSTALL 'mkfontdir' to 'mkfontdir -x .lev' although
the mkfontdir version on my system didn't think $(HACKDIR)/*.lev were
font files when I built without dlb.
Also change the PREINSTALL 'cp -n win/X11/nethack.rc ~/.nethackrc' to
keep going if it fails. The linux hints use 'cp -n' for sysconf but
since it is doing so for the playground directory and 'make install'
starts out by clearing away everything in that directory, it shouldn't
fail. But some extra bullet proofing there may be warranted. Only
the initial cp is protected against clobbering an existing file; the
ownership+permission fixups that are applied to the copy of original
file still get applied to an existing one.
PatR [Thu, 15 Aug 2019 01:49:16 +0000 (18:49 -0700)]
fix #H9118 - stoning a sandestin
causes "dmonsfree: N removed doesn't match N+1 pending" warning. The
sandestin monster definition flags it as MR_STONE, immune to being
turned to stone. If the hero hit it with a cockatrice while it was
shape-changed into something which isn't MR_STONE, it had its mon->mhp
set to 0, so died, and its form (mon->data) was set back to sandestin.
known_hitum() decided that it didn't turn to stone because of MR_STONE
for that form so proceeded to kill it off due to lack of hit points,
causing it to die twice.
I started to change that so that it didn't kill off the critter a
second time, bit it really shouldn't be able to kill it by stoning in
the first place. So sandestin how shares some vampire code to revert
to innate form and not turn to stone when "killed" by stoning. It
only yields the normal visible polymorph message: "the <foo> turns
into a <bar>" without any attempt to explain why. Once in sandestin
form, smacking it with a cockatrice corpse doesn't do anything special
(due to MR_STONE now being unambiguously in effect). It will soon
shape-change to some other form and then become subject to being
forced back to innate shape by stoning again.
PatR [Mon, 12 Aug 2019 01:56:43 +0000 (18:56 -0700)]
fix #H9117 - bookeeping for fatal status condition
When Stoned, Slimed, Strangled, Sick (TermIll or FoodPois or both)
counts down to 0 without being cured, keep it listed as an active
condition while killing off the hero. It will show in the status
section when disclosing final attributes and in both that section
and map's status lines when producing a dumplog.
PatR [Thu, 8 Aug 2019 18:25:36 +0000 (11:25 -0700)]
fix github issue #211 - wrong parentheses
Fixes #211
dopickup() was getting the wrong value from pickup_checks() due
to misplaced closing parenthesis. But it didn't actually impact
play; picking things up from engulfer's minvent while swallowed
worked even though the special check for that was failing. The
code which was accidentally being skipped can probably go away but
I haven't gone that far.
PatR [Fri, 2 Aug 2019 18:51:26 +0000 (11:51 -0700)]
fix #H9084 - teleported boulder left stale screen
Report was for Sokoban but it applied anywhere: if a teleported
boulder landed in a pit or trap door or hole and flooreffects() used
it up (so returned True), rloco() didn't update the location it was
teleported from and it appeared not to have moved. (Line of sight was
updated to reflect its absence but map spot wasn't redrawn without it.)
PatR [Fri, 2 Aug 2019 17:42:26 +0000 (10:42 -0700)]
fix #H9082 - post-3.6.2 monster throwing crash
Changing
if (ammo_and_launcher(otmp, uwep) && mwep->otyp == ELVEN_BOW)
(with 'uwep' typo) to
if (mwep->otyp == ELVEN_BOW && ammo_and_launcher(otmp, mwep))
(with fixed 'mwep') moved ammo_and_launcher()'s hidden non-null
test to after 'mwep->otyp'. If mwep was Null (so monster must be
throwing non-ammo such as darts or daggers rather than shooting
with a launcher), a crash occurred. (Throwing such things while
the monster is wielding any weapon doesn't have this problem.)
I don't think 3.6.2 can crash here. If hero's uwep is a bow, otmp
must be arrows to get past pre-3.6.3's incorrect ammo_and_launcher()
check. And a monster won't shoot arrows unless wielding a bow, so
monster's mwep would be non-Null regardless of what uwep is.
I tested a kobold with darts and an elven bow. But I also gave it
one elven arrow to provoke it into wielding the bow and my test
didn't throw darts with nothing wielded....
A typo caused the bow and arrow check when a monster was wielding an
elven box to test the hero's weapon with monster's ammo. [I looked
at the old slash'em code where I think this came from and it doesn't
have the typo but does have a different bug. A monster could get a
multi-shot volley by wielding an elven bow when throwing darts or
spears. The extra bow and arrow check is intended to prevent that.
The typo was probably by me but I have no memory of that code....]
Elves with bows (or other monsters who manage to pick up and wield an
elven bow) will shoot bigger volleys after this fix. That will make
them more dangerous but also cause them to run out of arrows more
quickly.
From the newsgroup (reported for slash'em but applies to nethack too):
a chaotic monk was crowned and told he or she had been "chosen to
steal souls for My Glory!" while being given a spellbook of restore
ability which has nothing whatever to do with soul stealing. There's
alternate wording for when Stormbringer can't be given because it
already exists; also use that for when it's not going to be given
because the character is discouraged against wielding weapons.
Add the contributed code that checks for attempting to start a
duplicate timer. It's based on a comment which must have been there
at least 25 years and doesn't solve any known problems, but it is
conceptually similar to the large amount of sanity checking which has
gone into 3.6.x.
It didn't work as is because it was comparing two unions with '=='.
I don't know offhand whether C++ supports that but C doesn't (through
C11 at least; don't know about C17). The union ('anything') is simple
enough that two instances can be compared without jumping through hoops.
I've also added another check for timer 'kind' (level, object, monster,
or global).
Bart House [Sun, 14 Jul 2019 07:20:09 +0000 (00:20 -0700)]
Fuzzer improvements.
phase_of_moon and friday_13th determined using rn2() instead of local
time if fuzzing. Don't reseed using init_random() if fuzzing. Allow
set_random to be called outside of hacklib. rn2_on_display_rng uses
rn2 if fuzzing so that we have a single source of random that we can
ensure is reproducible. Implement rul() that returns a random unsigned
long. Fix bug in fuzzer handling of ntposkey which would cause us to use
unitialized values for x and y. Added command line arguments to allow
auto starting and stopping of fuzzer. Add a logging facility for the
fuzzer to use to record activity. Added some scripts used to automate
fuzzer testing on windows.
Bart House [Sat, 13 Jul 2019 23:00:14 +0000 (16:00 -0700)]
Add stopping in the debugger when nhassert() is hit in the windows port.
When stopping in the debugger after having called impossible, the windowing
state will have been modified since the assertion was hit. This made
examining state that caused the nhassert to fire no longer possible.
To avoid this issue, we now detect the debugger and stop in the debugger
prior to impossible.
Bart House [Sat, 13 Jul 2019 22:57:06 +0000 (15:57 -0700)]
Re-worked tty_putmsgistory and tty_getmsghistory.
When we were saving message history as part of a game save for insurance,
we were calling remember_topl() and thus inappropriately changing topline
state. This would cause us to mis-manage the topline in subsequent calls
to update the topline.
The code has been re-worked to fix the issue, reduce complexity and make
the code clearer.
Bart House [Sat, 13 Jul 2019 17:53:53 +0000 (10:53 -0700)]
Removing assertion that does not hold under all scenarios.
When we save gamestate as part of making an insurance snapshot, we will
save message history which will clear toplines but leaving window state
in tack including the need for more.
Bart House [Fri, 12 Jul 2019 04:04:29 +0000 (21:04 -0700)]
Fixed bug with inmore and toplin state management.
When fuzzing, we would increment ttyDisplay->inmore but then prematurely
exit more() leaving ttyDisplay->inmore set.
Under various conditions, we can request to remember the topline when
the topline had not yet been acknowledged leaving toplin state in an
inappropriate state.
Bart House [Fri, 12 Jul 2019 03:46:19 +0000 (20:46 -0700)]
Remove the remapping of snprintf to _snprintf when compiling with MSC.
_snprintf and snprintf have one very important semantic difference.
_snprintf does NOT add terminating null character when the buffer limit
is reached while snprintf guarantees a terminating null character. It
was a mistake to make this naming change hiding the fact that the
semantics don't match what the developer might expect.
I moved some stuff around after testing the changes in 58583cacf8511625fd805ecbb050481f28de9411 before committing it. It
accidentally ended up with 'gold' always being Null at the first
place it gets used (to vary the feedback when stealing everything
except gold).
Nymphs won't steal gold from the hero (so that their steal-item damage
isn't a superset of lerprechaun's steal-gold damage; straightforward
back when gold wasn't kept in inventory), but hero poly'd into a nymph
would steal gold from monsters.
3.6.2's attempts to fix turning off SEDUCE in 'sysconf' introduced
an unintentional change in behavior for hero poly'd into nymph form:
theft attack always angered the target. The actual change was
intentional but its ramifications were unexpected.
Asking curses to report whether the Ctrl key was being pressed during
a mouse click was sending mouse position reports--even those aren't
being requested--and actual Ctrl+Left_click was reporting a pair of
duplicate Ctrl+Mouse_position_report events when a click was actually
performed. So turn off Ctrl key reporting.
Mac with one-button mouse can be configured to send "secondary click"
for Ctrl+Click. A laptop trackpad handles that differently (press the
button while two fingers are on the touchpad to send secondary click)
and doesn't support Ctrl+Click as an alternate way to do that. If this
would work within curses then they could operate the same regardless
of how the user set the mouse or trackpad configuraiton. But I wasn't
able to make it work right.
The Guidebook claims that there's no symbol for 'S_strange_object'
which is literally true, but there is one for S_strange_obj. It has
been in place longer than the paragraph claiming that there's no way
to customize that symbol. I'm not sure why variant spelling was used.
Also, files.c doesn't use loadsyms[], it calls a routine which returns
a pointer to a specific element in that array.
would describe it as trapped if you could see its location, but if
the trap was unseen that trap would remain unseen, at least in some
circumstances. Mark the trap as seen.
Wizard mode ^E and any mode spell of detect unseen or wand of secret
door detection failed to find mon->mundetected monsters if they were
hiding under objects, and failed to find those or other hiders or
mimics when the hidden monster was at a trap location. The fix for
the latter initially only worked if the trap was known, so took two
tries when a monster hid at the location of an unseen trap. So this
makes the additional change to find both things at the same time; it
isn't manual searching that stops as soon as something is found.
Typing ^H actually passed a 16-bit value back to the core which got
interpreted as ^G after the extra bits were discarded. I don't think
any previous changes to the curses interface caused this. It's
astonishing that no one ever noticed; the world must be full of numpad
users.
Bart House [Sat, 6 Jul 2019 21:18:02 +0000 (14:18 -0700)]
mklev() set xxstairs_room pointers back to NULL upon completion.
When mklev() is called multiple times, previous state stored in the
xxstairs_room pointers can be mistakenly used when making decisions about
the new level being constructed. This caused non-deterministic level
creation behavior when replaying from a snapshot.
With 'popup_dialog' On, a prompt which exactly fills the available
width would start the next line with a space (to separate the prompt
from user's answer) and then have the cursor waiting after it. That's
unlike other behavior in the curses interface where the line split
would be instead of the separating space rather than in addition to it.
Old:
|long prompt?|
| X__________|
New:
|long prompt?|
|X___________|
where the X represents the cursor sitting over the start of blank space
waiting for user's answer.
When swallowed, you can take things from the engulfer's inventory, if
there are any, via pickup. Items might be worn by the engulfer and
when "picked up" those weren't being unworn before being added to
hero's inventory. Then they would be formatted as "(being worn)" and
could trigger warnings or worse.
Conceptually they should be worn on the outside and not be accessible
from the inside, so I've made attempts to pick up worn items fail
rather than fix up the unwearing.
Using ':' when swallowed to look at the engulfer's inventory describes
that inventory as "contents of <mon>'s stomach". That's weird for any
worn items, but the situation is so rare I haven't made any attempt to
deal with it.
Rescue some old code from bit rot. It may be useful if the shop
side of things ever gets fixed. (Itemized billing reveals container
contents. I'm sure that it's in the bugzilla list but can't find it.)
Noticed after building a curses-only binary; configuration setting
"terminal info library" is only of interest as an optional feature
when the build includes tty. There were several other settings that
apply to some interfaces and not others but would be listed if the
feature was defined (possibly after building for an interface which
supported it, then left in place when switching to another which
doesn't).
I left most of those with commented out conditionals in case other
interfaces start supporting them. So you might still get something
like "tiles file in XPM format" for a binary that doesn't support
tiles if USE_XPM has been defined for some reason.
Bart House [Wed, 3 Jul 2019 02:08:50 +0000 (19:08 -0700)]
Fix crash that can occur in decode_mixed.
If a player names an object with a name that ends in '\\', drops
that object on the floor nearby and does a look at nearby objects,
then the game will crash. This is caused by stack corruption when
the decode loop skips over the decode string terminator.
Extend support for highlight rules that specify percentages from HP
and spell power to experience level and experience points. For both
of those, the percentage is based on progress from the start of the
current Xp level to the start of the next Xp level. 100% isn't
possible so is used to enable highlighting a special case: 1 point
shy of next level, most likely to occur after losing a level.
This is something I had in mind a long time ago and then forgot all
about until fiddling with the final disclosure of experience points
recently. It turned out to be trickier than expected because it needs
to check whether Xp should have a status update when it hasn't changed
but Exp has gone up. The latter might hit a percentage threshold that
switches to another highlight rule. Fortunately changes to Exp, at
least that aren't part of level gain or loss (which always trigger
status updating), are all funnelled through a single place (I hope).
Highlighting via attributes got broken three months ago. May or
may not have been noticeable depending upon which attributes are
supported. Too many variations of attribute designations...
PatR [Sun, 30 Jun 2019 20:45:14 +0000 (13:45 -0700)]
wishing vs EDIT_GETLIN
If you ask for help when wishing, don't leave "help" in the buffer
for EDIT_GETLIN to use as default answer on next retry. It does still
leave anything rejected as unknown so that the player has a change to
review the spelling and conceivably add and/or remove from the end
witout having to retype everything.
PatR [Sun, 30 Jun 2019 18:50:08 +0000 (11:50 -0700)]
curses message history vs dumplog message history
When I implemented getmsghistory()/putmsghistory() for curses I was
assuming that DUMPLOG would only be used with tty, but it is interface
neutral and can be used with curses (or others). So curses message
history needs to behave like tty message history and be sure to pass
along messages that bypass pline() and the normal message window.
(Mainly one-line summaries of long quest messages, but also old
messages fetched from a save file and available to be re-saved without
having been shown if new session doesn't generate enough new messages
to flush them.)