Fix the regression that monster movement flag unification
introduced for monsters able to swap places with adjacent
monsters. It used to be restricted in order to prevent
Riders swapping places with other Riders so that they didn't
repeatedly exchange places when one was right behind the other
and the farther one moved first. Then when displacer beasts
were added, that restriction was extended to prevent them
swapping places with Riders (but not the other way around.)
The flags change inadvertently let any displacer swap with any
other displacer.
Prevent Qt from inserting an extra entry in the Help dropdown
menu displayed in the menu bar across the top of the screen
when nethack has focus. "Search [______]" lets the user enter
a string to search for but doesn't give nethack any control
over that so we can't have it.
I haven't found a sane way to get rid of it. The insane way
of not naming any menu "Help" works. This uses "\177Help" so
that it still looks like "Help" but won't match that string.
Death will revive faster than the other riders.
Make all the riders revive after 67 turns, instead of 500.
There was practically a zero chance a rider would revive at 500,
so keep it somewhat sensible.
Fire damage would dry out a wet towel but never all the way to 0.
Water damage would wet a towel but if it was already wet, its
wetness might decrease.
This uses the pull request's change for increasing the wetness
but changes dry_a_towel so that the original code for decreasing
that will work as is. Using wet_a_towel() to set wetness to 0
doesn't make much sense, so still won't do so; dry_a_towel() does
and now will.
This also adds missing perm_invent update for towels in inventory
changing wetness.
Fixes#418
If a container holds anything that a shop wouldn't ordinarily
buy and sell and you sell it for gold, the 'foreign' contents
are marked no_charge and hero still owns them. But selling the
same container+contents for credit instead of gold would take
shop possession of all the contents without increasing the
credit amount.
The fixes entry is longer than the fix. It solves cited case but
I won't be surprised much if it messes up some other case(s).
number_pad==1 adds
'5' => 'G'
M-5 => 'g'
'0' => 'i'
number_pad==2 swaps 5 and M-5 and adds M-0
'5' => 'g'
M-5 => 'G'
'0' => 'i'
M-0 => 'I'
M-5 and M-0 were missing from the bound key handling; they still
used hardcoded digits even though the actions for plain 5 and
plain 0 can be bound to other keys these days. This implements
the M-5 variation as NHKF_RUSH2. Changing numpad from 1 to 2
or vice versa will swap the NHKF_RUN2 and NHKF_RUSH2 actions
regardless of what keys they're assigned to. I haven't done
anything for unimplemented NHKF_DOINV2 though (and am not
planning to in case someone else wants to jump in...).
This also fixes the description of the 'I' command. The extended
command name for that still misleadingly refers to "type" rather
than "class" though.
When ?i shows key bindings, at the end of each group (movement,
prefixes, general, game, debug) report any commands for that
group which don't have any key assigned. Movement and prefixes
all have keys; they'd be pretty useless without and key bindings
won't override movement commands. For general, the "keyless" are
|#exploremode
|#herecmdmenu
|#therecmdmenu
after this adds the relevant flag to their command definitions;
for game, "#terrain" is the only one; the debug section has 20.
There is a known problem that I've going to pretend that I didn't
notice: if I use BIND=D:takeoffall then 'A' becomes unassigned,
'D' invokes #takeoffall, "#droptype" becomes keyless, and ?i
reports those correctly. But if I use BIND=M:takeoffall, 'A'
becomes unassigned, 'M' continues to be its usual prefix, and
the "#takeoffall" command is nowhere to be seen. The code that
tracks assignments is letting that case fall through the cracks.
'M' ends up assigned to both and the ?i code deliberately only
shows the first.
I was implementing a routine to show all the key bindings
when I discovered that we already have one. This fixes a few
small problems: 'n' prefix for number entry was missing for
number_pad mode. Meta+<direction> for running in number_pad
mode was missing too. ^A was present but being suppressed by
lack of #define for obsolete #if REDO. And ^C was shown as ^c
while all other ^ characters appear in upper case. Once ^A
appeared as the line before it, the inconsistency stood out.
I also changed the slightly verbose "Shift-<direction>" and
"Ctrl-<direction>" entries below the direction grid to use plus
instead of minus signs. Plus emphasizes that two things are
combined so seems more intuitive. (I left "M-c" alone.)
Provide a hook to inhibit unixconf.h from defining SUSPEND
without the need to modify it: #define NOSUSPEND in config.h
or add -DNOSUSPEND to CFLAGS. Similar to long-standing NOSHELL
for inhibiting SHELL.
Only quantum mechanics are supposed to have a chance of death-dropping the
Schroedinger's cat box.
Slash'Em already had this but it was missed when Genetic engineers were ported
over.
I couldn't reproduce this so can't confirm that this fix works,
but inspection of the code reveals that something was missing
in the unified mon movement flags code. I think what has been
happening is that a dwarf without a pick-axe might not bother
wielding that but movement behaved as if it had, then digging
decided it wasn't.
For Qt's pick-an-exetended-command dialog, allow a player to
toggle the grid layout from column-oriented to row-oriented
and vice versa and when in wizard mode to cycle the set of
shown (and typable) commands from 'all' to 'normal mode-only'
to 'wizard mode-only' back to 'all'. The most recent values
are saved by Qt along with tile size, font size, and some other
stuff. The extended command dialog has a Reset button to force
them (the two extended command values) back to their defaults.
The dialog layout has a slight change to conserve screen space
as well as three additional control buttons:
Was Now
| [ Cancel ] | [Cancel] [Filter][Layout][Reset ]
|# |# Grid Title
| Grid title | [cmd 1] [cmd R+1] [cmd 2*R+1] ...
| [cmd 1] [cmd R+1] [cmd 2*R+1] ... | [cmd 2] [cmd R+2]
| [cmd 2] [cmd R+2] |...
|... | [cmd R] [cmd 2*R]
| [cmd R] [cmd 2*R]
'#' is the prompt where typed text gets echoed and 'R' is the
number of rows in the grid and varies by the set of commands
from the current filter. Grid dimensions have been adjusted:
'all' is 13x9, 'normal' is 13x7, and 'wizard' is 7x4 or 4x7
depending on layout orientation.
The wizard mode-only filter setting probably isn't very useful
because you can only type--or click on--commands which are
visible. So when set to wizard mode-only, you can't #quit for
instance. (Via extended command; there are still menu choices
for that particular action. And it's trivial to change filter.)
Let tourists read cornuthaum ("WIZZARD") and dunce cap ("DUNCE").
One out of three will have those words, the other two will yield
"you can't find anything to read on this ___" where ___ is either
"conical hat" or "cornuthaum" or "dunce cap" depending upon hat
type and discovery status.
Even when a dunce cap says "DUNCE" it won't become discovered,
just offer the player an opportunity to apply a name.
Other roles still fall through to the "That's a silly thing to
read" feedback.
Not intended to be logical...
Rename "seegold" to "showgold". The character to invoke it ('$')
is similar to those for the various "seeXYZ" commands ('[','=',&c)
but unlike them, it isn't part of "seeall" ('*').
Expand or replace the one-line description of several commands
(shell, showgold, showtrap, suspend, versionshort).
The #version command is a leading substring of the #versionshort
command and for Qt, it couldn't be executed by typing, only via
mouse click or one of the Qt-specific menus. #version<return>
or #version<space> now works for that.
The #versionshort command ought to be renamed to something else.
I started activating new program_state.saving and discovered that
saving of ball and chain could access freed memory. The change
for the former and fix for the latter are mixed together here (but
easily distinguishable).
The saving flag inhibits status updating and perm_invent updating,
also map updating that goes through flush_screen(). That should
fix the exception triggered after an impossible warning was issued
during a save operation. impossible() goes through pline() which
tries to bring the screen up to date before issuing a message.
During save, data for that update can be in an inconsistent state.
The code to save ball and/or chain when not on floor or in invent
(I think swallowed is the only expected case) was examining the
memory pointed to by uball and uchain even if saving the level had
just freed floor objects and saving invent had just freed carried
objects. So for the usual cases, stale pointer values for uball
and uchain would be present and checking their obj->where field
was not reliable.
Noticed while working on Qt's extended command handling, there
are an awful lot of "seeXYZ" commands. Keep the inventory display
ones (named versions of ')' to show wielded weapon(s), '[' for
worn armor, '"' for worn amulet, &c) and rename the others:
| #seenv -> #wizseenv debugging command
| #seespells -> #showspells '+' command
| #seetrap -> #showtrap '^' command
Also, expand the descriptions of #shell and #suspend a bit in
the Guidebook. LaTeX version is untested.
Move the core's global restoring flag (not the same as main()'s
local resuming flag) to a more logical place. Add a saving flag
in the process, but it isn't being set or cleared anywhere yet.
(Once in use it will probably fix the exception during save that
was just reported, but before that it would be useful to figure
out what specifically caused the event.)
The program_state struct really ought to be standalone rather
than part of struct g but I haven't made that change.
Removing an unused variable for wishing and some reformatting
that whent along with it got mixed in. Removes some trailing
whitespace in sfstruct.c too.
Only lightly tested...
Multiple stints of flailing about without a clue finally led to
a breakthrough. When writing a new message to the multi-line
message window, force the view back to showing the starts of
lines if player has scrolled it to the side and left it that way.
Put another way, if it has been scrolled to the right, scroll it
as far as possible back to the left.
I was baffled about why moving the cursor across a fire elemental
kept putting up --More-- until I remembered that I once used
MSGTYPE=stop "[Ff]ire"
to test Qt's handling for that. Turns out that I left it in my
config file. autodescribe feedback should not be honoring that;
honoring MSGTYPE=norepeat is not as clear-cut but this disables
it too.
User sounds were also kept enabled during autodescribe but I have
no way to test them. Like norepeat, disabling just falls into
place.
The pline.c change is unrelated. It just eliminates a wide line
(from adding 'g.') in the source by using a shorter variable name.
This tries to fix the problem of the extra message when a tame
golem is completely destroyed (paper or straw golem burned, iron
golem rusted, wood or leather golem rotted) being issued at odd
times. I basically punted on the visibility aspect since the
original logic was strange: you had to be able to see both the
attacker's and defender's spots and at least one of those two
monsters. Now mon-attacks-mon visibility requires that you be
able to see one of the two and if you don't see both, the unseen
one will be referred to as "it". The "may the iron golem rust
in peace" message is independent of that and may be displayed
after "you have a sad feeling", but now that's intentional and
will refer to an unseen pet by name or monster type, not "it".
This needs a lot of testing and hasn't attempted to address
issue #402: only some attacks that should compeletely destroy
a golem actually do so. (So a hit by fire elemental against a
paper golem does, but passive fire counterattack when a paper
golem hits a fire elemental doesn't, nor does a wand of fire
or being hit by Firebrand.)
Fixes#401
The revamped options handling was't doing dynamic help properly.
After listing the booleans, it listed them again amongest the
compound options. Since their description field is Null, that
could be a big problem. sprintf(buf,"%s",NULL) on OSX produces
"(null)" but most sprintf()'s would probably crash instead.
The 'other' options (autopickup exceptions, menucolors, &c) were
not listed at all. (I don't remember whether that was also the
case before the revamp.) Now they're listed but not explained.
The 'msg_window' description was unhelpful; this replaces it.
A couple of others were longer than necessary so they've been
shortened. The rest of optlist.h is reformatting wide lines.
Recently added 'safe_wait' option was included in the Guidebook
but not in dat/opthelp; add it.
Kicking a container that had gold in it took the gold amount
away from hero's credit or added to hero's debt, then didn't
give a refund if the container and its gold landed within the
shop. Throwing behaved likewise, just less verbosely.
The problem is caused by addtobill() treating gold specially
and then subfrombill() not being able to perform a reverse
operation. Actually, it may be possible for subfrombill() to
do that, but verifying all its uses is too much work. This
moves the gold handling for drop+selling into its own routine
and adds calls to that for the throwing and kicking refunds.
The other calls to subfrombill() outside of shk.c appear to be
ok as-is. (The calls inside that file are the ones that still
need evaluation if the gold handling is to move to there.)
bill_dummy_object() now uses the same o_id assignment for its
dummy object as split_object() does for its new partial stack.
I don't know whether the old code led to any price glitches.
Noticed while working on Qt status highlighting: if levitation
and flying timed out at the same time, first Lev timeout called
float_down() which reported
You have stopped levitating and are now flying.
and then Fly timeout left stale "Fly" on the status line due to
an optimization which got subverted. ('was_flying' flag was
False due to Fly being blocked by Lev; that's correct behavior,
but the flag is effectively a cached value that becomes stale
when the Lev timeout code executes.)
The bug was wizard mode only because #wizintrinsic is the only
way to get timed flying.
commit 03d7d64d15:
| [...] but fixing this specific case is trivial.
Not trivial enough to avoid getting the details wrong. An old
commit log message (58137a608a,
June of 2006) claimed that this was fixed for bag of tricks but
that was for monsters in general; mimics could still be wrong.
Requested by a beta tester nearly four years ago: '$' is both an
inventory "letter" and a group accelator. The letter only works
if gold is on the current menu page and was taking precedence
over the group accelator. Allow '$' to toggle selection of gold
regardless of the page.
curses already behaves this way. X11 and Qt menus aren't
paginated so also pick gold even if the '$' entry in the menu
isn't visible at the time. No idea about Windows GUI...
When SCORE_ON_BOTL is enabled, you could tell how much gold is
inside a container with unknown contents by having 'showsore' On
and watching how much the score changed on the status line when
picking the container up.
Use horse/unicorn body parts. The result for HAIR is "mane"
which is appropriate. There's no field for SKIN so the question
of whether to specify "scales" is moot. (Snakes and dragons
describe HAIR as "scales" but that wouldn't be right for ki-rin.)
From an old bug report (sent directly to devteam, June of 2017):
wand or scroll of create monster becomes discovered if it makes
a mimic that is concealed as an object or as furniture within
the hero's view. Fixing this in the general case [when does
seeing a mimic as something other than a monster mean that the
mimic is being seen?] is a massive can of worms, but fixing this
specific case is trivial.
Let ki-rin cure themselves (of being stunned, confused, or blinded)
with their own horn, and make them be poison resistant. They
aren't unicorns but their horn is very much like a unicorn horn.
They're flagged no-corpse so this hasn't changed them to leave
behind a horn upon death.
They were flagged as animals who neighed but they are also spell
casters. I took the animal flag off (they're still no-hands so
shouldn't be able to use items; also, unicorns aren't flagged as
animals either) and changed sound to 'ms_spell'.
I though that I noticed a problem but later couldn't reproduce
it, so this might not be redundant. Update persistent inventory
when putting on a helmet causes it to become cursed.
Minor change: if blind at the time, hero loses knowledge of BUC
state.
Try to set the initial window sizes to be big enough to show the
full welcome line in the message window when the Qt settings
(Preferences on OSX) specify Large font (Huge/Medium/Small/Tiny
seemed ok but I wasn't systematic about checking them).
While at it, I added a long comment about the status window format
and noticed a bug with experience formatting there. Again only
seemed to matter for Large font but the change to fix ignores font
size.
Plus add a couple of Qt "issues", one old and one just discovered.
If a monster threw a cocktrice egg that hit and petrified another
monster, the hero would credit (experience) and blame (possible
alignment penalty, &c) for it.
Fixes#410
Use a linked list to store stair and ladder information, instead
of having fixed up/down stairs/ladders and a single "special" (branch)
stair.
Breaks saves and bones.
Adds information to migrating objects and monsters for the dungeon
and level where they are migrating from.
Breaking a wand didn't require the hero to have free hands.
That's definitely a bug when they're both welded to the same
two-handed weapon. It's debatable when welded separately to
a one-handed weapon and to a shield but simpler to pretend
there's no such distinction.
This also makes glass wand join balsa wand as "fragile". Hero
doesn't need as much strength to break them as other wands and
the wording for breaking them is slightly different.
My fixes entry initially had a trailing space. When I took
that out, I spotted a couple of others so take those out too.
Attacking a concealed mimic at range by applying a polearm
could make the hero be stuck to that mimic in addition to
bringing it out of hiding. Only do that when adjacent.
This also adds a new sanity check when setting u.ustuck.
It may get triggered by other sticking activity since only
attacking has been tested. The check must be explicitly
enabled by setting the wizard mode 'sanity_check' option.
Fixes#408
Some eggs and tins could cause an out of bounds index into the
mons[] array. Post-3.6 bug: the faulty part of the test is only
relevant for 3.7 genetic engineer monster. Earlier versions just
called pm_to_cham() which does it's own index validation.
Fixes#406
Text window search behaved very strangely: at some point after
selecting [Search], entering a search string, having the string
entry popup go away, and having the search performed, but before
the result could be shown, the text window got pushed behind the
main window (map+messages+paperdoll+status). Clicking on the
main window's minimize button hid the main window and gave access
to the text window behind it. That was still functional even
after having been inaccessible; another search could be performed
and/or it could be dismissed. I still don't know what causes
that or how to properly fix it, but using raise() is a workaround
to bring it to the front where it belongs. Unfortunately you can
see it go away and come back so searching for text is distracting.
Allow <return> (when not searching) to dismiss all text windows
including RIP. Accept ctrl+[ as ESC.
Make text window searching be case-insensitive.
Searching wouldn't find a match on the first line of text. Now
it will.
This also includes an attempt to fix github issue #400 (typing a
pickup command while "things that are here" popup text window is
displayed seems to hang the program), but since I can't reproduce
that, I can't tell whether the fix works. The issue description
says that pickup started executing and "things here" couldn't be
dismissed which is different from "things here" being behind the
map waiting for it to be dismissed. The attempted fix is for text
window handling to tell Qt that it wants control of the keyboard,
so nethack shouldn't see any attempted pickup command.
If player got Qt's saved game selection widget at startup but
picked "new game" there, the save file for the last character
in the list of saved games would be clobbered with the new
character's game if a save was performed. It wasn't necessarily
easy to spot because saved game selection shows the character
name from inside the file rather than from the file name, so the
next restore would look normal except for one older character
missing.
Noticed while testing: when you used the character selection
widget (either by picking "new game" in saved game selection or
because there aren't any save files), if you blanked out the
name field or it was already blanked because a generic name like
"player" had been specified, then clicked on "play", the program
would get stuck in a loop somewhere. I didn't try to figure out
where, just changed qt_askname() to revert to original name if
it ended up with a blank one.
This fixes the Qt popup widget for selecting among saved games.
The character name from each applicable save file is shown in a
button and clicking on one of those buttons restores corresponding
file. Previously all the buttons were written on top of each
other so only the final name was visible and the button for the
initial name received the click. The widget also has [quit] and
[new game] buttons.
This fixes restoring an existing save file if no character name
is supplied on the command line in the options. It does not fix
the problem where picking [new game] remembers the file name of
the last saved game in the popup's list and overwrites that file
(after requesting confirmation to do so) if/when you eventually
save. The resulting file will contain the character just saved
but be named for the earlier one. It may not be obvious because
on subsequent restores it will list names from inside the files
rather than deduce those from file names, so the clobbered/
misnamed file will just show up as the former new character.
I'm not sure whether any yn_function() calls include ampersand
in the list of acceptable choices but if any did, the button
for that character would have shown up blank. (Clicking on it
would have successfully produced '&' as player's input though.)