We used to have the contents of chests and large boxes be immune to
water damage, oilskin sacks immune unless the sack was cursed, other
containers be vulnerable. Some reddit discussion about ice boxes in
unnethack indicates that they are treated like oilskin sacks, which
makes sense. This adds that to nethack and also makes chests and
large boxes behave similarly. So it's now: nothing is immune even
when cursed (except statues); oilskin sacks, ice boxes, and other
boxes are immune to water damage unless cursed; all other containers
vulnerable even when not cursed.
|
| Old New
|immune all statues, statues
| the time chests, large boxes
|
|immune when BU, oilskin sacks oilskin sacks,
| vulnerable if C ice boxes,
| chests, large boxes
|
|vulnerable ordinary sacks, ordinary sacks,
| all the time bags of holding, bags of holding
| ice boxes
|
I suspect that the old ice box classification might have been an
accident caused by the Is_box() predicate yielding False for it.
The changes won't make much difference to actual play. Chests and
large boxes are rarely carried and never start out cursed, ice boxes
even more so, and sacks/bags haven't been changed. However, players
might intentionally curse a container to keep strong pets from
picking it up, or be carrying a box because they haven't found a bag
yet and then muck about with fountains or thrones and get it cursed.
'final_fpos' shouldn't have been moved to the 'g' struct. Even if
a game went all the way through topten and was restarted as a new
game that also went all the way through topten, 'final_fpos' would
get a new value rather than being messed up by a stale old one.
When swallowed and blind, the swallowing monster is described
accurately, but being held rather than swallowed describes the
monster as "it". That's normal, but the status feedback section
of ^X output lists
|You are held by it.
which looks pretty weird. Change that to be
|You are held by an unseen creature.
Zapping wand of opening or spell of knock at engulfer while swallowed
would make the engulfer expel the hero; this change makes zapping
other holders release their hold. Zapping self now achieves the same
effect, as does breaking a non-empty wand of opening. When poly'd
hero is holding a monster rather than being held, that monster will
be released.
Engulfers can't re-engulf for 1 or 2 turns after releasing the hero
in order to prevent hero from being immediately re-engulfed. Impose
the same limitation on other holders.
From newsgroup discussion where slash'em changes have revealed a
latent nethack bug: prevent placing level teleporters in single-
level branches. The Knox level doesn't have any level teleporters
(or random traps) but wizard mode wishing could create them there.
They wouldn't do anything because the only possible destination
would be the same level. Pushing a boulder onto one used to trigger
an infinite loop (and still does in slash'em, which has other
single-level branches besides Ft.Ludios) trying to relocate it.
Boulder pushing was changed 15 years ago to prevent the infinite
loop and to avoid giving "the boulder disappears" message when a
level teleporter failed, but rolling boulder traversal lacked that
same change--it wasn't vulnerable to looping but could give an
inaccurate message claiming that the boulder disappeared when it
actually didn't. Fixing this is a bit late; rolling boulder trap
creation was recently changed to not choose a path that rolls over
teleportation or level tele traps any more.
Change Trollsbane versus troll corpse revival: instead of revival
failing if Trollsbane is wielded at time of revival attempt, mark
the corpse no-revive if killed by Trollsbane (whether by the hero
or a monster).
If a no-revive corpse is within view when time to revive occurs,
give "the troll corpse twitches feebly" even when the hero isn't
responsible. That used to only apply if the hero zapped the
corpse with undead turning, which would have become inoperative
because now being zapped by undead turning clears the no-revive
flag and revives as normal. In other words, undead turning magic
overrides killed-by-Trollsbane or non-ice troll having been in an
ice box.
Player's pet killed a troll with Trollsbane and the corpse later
revived. He assumed that killing a troll with Trollsbane is what
prevents troll corpse revival but that is inhibited by the hero
be wielding Trollsbane at the time revival is attempted.
Having killed-by-Trollsbane be the reason for blocking revival
would be much better but looks like a lot of work for something
which was supposed to be a one-line enhancement to an under-used
artifact. This extends revival inhibition to having anyone on
the level be wielding Trollsbane rather than just the hero.
Not a proper fix but I think it's better than nothing.
Closes#475
I accidentally toggled the 'altmeta' option On and got this
non sequitur result when trying to toggle it back Off:
|The altmeta option may not both have a value and be negated.
Apply visibility fixups for monsters triggering door trap
explosions or digging through doors similar to the monster-opens-
door-handling from a couple of days. Again, the issue is that
hero/player can see a closed door in situations where they can't
see an open one, and messages about the door being opened or
destroyed need to take that into account when seeing a closed
door go away.
Not as thoroughly tested as monster just opening closed door.
Incorporate the changes from pull request #467, which itself
incorporates a fix for issue #441. Allows hands/self to be an
acceptable but hidden choice (don't think any command actually
needs this). When 'force_invent' option is on, show all the
acceptable but usually hidden choices if no ordinary candidates
are available instead of having an empty menu. Also, omit
force_invent's "* - (list everything)" extra menu entry if the
menu already contains everything.
Cleans up a couple of whitespace issues too. I changed at least
one more and added a couple of comments. I'm not sure about the
comment change that I made in hack.h; the original said "foo is
identical to foo" but the revision might not be accurate.
Fixes#467Fixes#441
The pull request that fixed a couple of instances where it was
possible to have multiple entries for gold in inventory indirectly
pointed out that the error checking was clumsy. If you executed
the #adjust command while having two '$' items in inventory, you
were told twice that you had multiple stacks of gold in inventory.
Change how that's handled so that the warning appears at most once
for any given #adjust command. Also avoids having #adjust's use
of getobj() re-scan entire invent for every item in invent.
Also, if player did manage to get two or more '$' entries, #adjust
would allow moving any but the last to a letter entry. Once in a
letter, further #adjust with count specified could split the letter
gold entries into even more gold entries. Now, if the player picks
gold as the #adjust 'from' item (which is only possible when there
are wrong letter gold entries or multiple ones or both) then #adjust
will now force 'to' slot to be '$' (without asking player to pick).
Lastly, the inventory check for multiple and/or wrong slot gold is
now performed by wizard mode sanity_check() in addition to #adjust.
Change the '|'/#perminv final positioning for X11 to be the same
as for curses: finishing with <escape> leaves the current view,
with <return> resets to unscrolled.
Actually getting ESC and RET to the right place wasn't trivial;
down the rabbit hole and out the other side. Using yn_function()
to get the #perminv keystrokes is less than ideal. (curses also
started that way but switched to raw character input for this.)
Add new '|' command, aka #perminv, which allows the player to
send menu scrolling keystrokes to the persistent inventory window.
Implemented for X11, where its usefulness is limited, and for
curses, where it is more needed and also more fully functional.
The interface can either prompt for one keystroke, act upon it,
and return to normal play, or it can loop for multiple keystrokes
until player types <return> or <escape>. X11 does the former if
the 'slow' application resource is False so that prompting uses
popups, and the latter when 'slow' is True where prompting is in
a fixed spot and doesn't end up causing the persistent inventory
window to be stacked behind the map window. curses always does
the loop-until-done approach. It also accepts up and down arrow
keys to scroll one line at a time.
Also adds two new menu scrolling commands, menu_shift_right (key
'}' by default) and menu_shift_left ('{') if wincap2 flags contain
WC2_MENU_SHIFT. Shifting allows different substrings of too-long
lines to be seen.
For X11, neither works because their handling requires a horizontal
scrollbar and for some reason that escapes me our menus don't have
one of those. If they did, shifts could work for all menus but a
shifted window would hide the selection letters. So shifting would
be most usefully done as: pan right, read more of any long lines,
immediately pan back to the left.
For curses, they only apply to the persistent inventory window.
Shift right redraws it with class headers and inventory letters
shown normally but the item descriptions omit their leftmost
portion, showing more text towards the end. Shift left reverses
that and does nothing if the beginning is already in view. Forward
and backward scrolling while shifted leave the shift in place.
Give the window-port side of *_update_inventory() an argument.
Calls in the core still omit that; invent.c's update_inventory()
is the only place that cares.
Looking up scrollbars did not work as intended. The code wanted an
ancestor widget that had both horizontal and vertical scrollbars,
but menus either have none or just vertical. The lookup code found
some top level widget and returned bad data.
OPTIONS=menu_previous_page:\mv
BINDINGS=M-v:menu_previous_page
both worked, but
OPTIONS=menu_previous_page:M-v
BINDINGS=\mv:menu_previous_page
both failed. Make all four variations work. Tiny change made large
by the need to move some things around.
The option definition for menu_first_page had a couple of its flag
bits swapped. I didn't try to figure out whether that had any impact.
When panictrace feedback occurs due to catching a signal rather
than controlled panic, the backtrace is useless when running the
curses interface unless the terminal gets reset first. Let's
just hope that the signal triggering a panictrace doesn't occur
while resetting the terminal.
Some warnings were mentioned
Add a prototype ahead of the function
Use a non-const copy of SERVER_ADMIN_MSG
quick-tested by:
- uncommenting the following in include/unixconf.h
/* #define SERVER_ADMIN_MSG "adminmsg" */
- building NetHack
- creating a test message:
echo "server_admin: system is going down at 2 pm" >~/nh/install/games/lib/nethackdir/adminmsg
- playtested and received the desired message
des.region() accepted booleans for the joined field, whereas des.room
accepted xchars. These were only being used as truth values, so this
converts the room ones into booleans for consistency. I don't think
accidentally using an int or a boolean wrongly would actually crash the
level generator, but consistency is good.
This converts an schar field in struct mkroom into a boolean; on most
systems these are probably 1-byte types and save files won't be broken,
but it might be best to treat this as a save breaker anyway.
Its value is only used as a boolean, so there's no real need to keep it
as a confusing int.
Shouldn't be a save-breaking change; it doesn't look like g.coder is
saved.
"Demote" wizmgender from an obscure wizard mode extended command
to an obscure wizard mode boolean option. Behaves the same except
that no message is given when the value gets toggled.
When persistent inventory window is up, remove it if 'perm_invent'
option gets set to False. This has a side-effect of fixing the
end-of-game prompting problem it caused.
Under curses interface, provide a way to get a little more space
for perm_invent without turning off windowborders entirely.
Possible 'windowborders' values:
0 = no borders, max screen space available for useful info
1 = full borders, two lines and two columns wasted for each window
2 = contingent borders, show if screen is big enough, else hide
New:
3 = as 1 except no borders for perm_invent window
4 = as 2 except never borders for perm_invent window
3 and 4 let the map, message, and status windows have borders while
providing two extra lines and two extra columns on each line for
persistent inventory. It's not much but better than nothing when
borders are enabled.
Instead of inexplicably paralyzing the player for the duration of their
engraving. Many a character has died by trying to engrave something and
then sitting there diligently writing it while monsters surround and
attack them. (This was especially prominent back in the 3.4.3 era when
repeated Elbereths were viable, but it still occurs today with e.g.
using a hard stone to engrave Elbereth). There were also some other
oddities - for instance, if something teleported the player away while
they were engraving, they would continue to "engrave" (be paralyzed) on
their new location, but would not produce any text there; the full
engraving would be placed on their initial position.
In this commit, I have converted engraving to use the occupation
framework, which treats it as an interruptible activity. This
necessitated some logical restructuring, mostly involving the engraving
being written out in chunks as the player spends more uninterrupted time
on it.
I've tried to keep this free of regressions except for those inherent to
the occupation system.
What has NOT changed:
- The rate of engraving is still 10 characters per turn, or 1 character
using slow methods.
- The formulas for determining how much a bladed weapon or marker can
engrave before getting exhausted are kept. Though this is a bit
convoluted, and if it's not considered important to preserve the
existing behavior, I would recommend simplifying it by decreasing the
maximum engraving length for weapons by 1 so that each point of
enchantment simply gets you 2 characters' worth of engraving (e.g. a
-2 weapon will only engrave 1 or 2 characters before dulling to -3,
rather than giving it a third "grace character".
- The input buffer is still modified based on confusion/blindness/etc
only at the time when the player inputs it (if they gain a
debilitating status while engraving, it will not affect the text). My
personal preference is to make the text affected in scenarios like
that, but it's not strictly necessary to do here, so I didn't.
- Wand messages such as "The floor is riddled by bullet holes", and
blinding from engraving lightning, still appear before the hero starts
to take any time engraving. As noted above, getting blinded by the
wand still has no effect on accurately engraving the text, unless the
hero was already blind or impaired.
What has changed:
- Moving off the engraving or losing the object being engraved with
causes the player to stop engraving.
- Wands can still engrave an arbitrary amount of text using a single
charge, but if the hero is interrupted and decides to start engraving
again, they will consume a second charge.
As it adds a new field to g.context, this is a save-breaking change.
Implement a better fix for commit 2f4f7d22d ("Fix align type
mixup wth align mask") which was reverted in commit 4e35e8b5a
("Revert "Fix align type mixup wth align mask"").
In the present code, the field align in both struct altar and
struct monster is not an aligntyp, but an align mask with extra flags.
Change the type to match its actual use and improve the naming.
Consolidate duplicated code into a single routine.
Change the return type of induced_align() to be unsigned to match
amask usage.
Change the special level align mask values to be separate from
the normal align mask values.
option ‘-Wimplicit’ is valid for C/ObjC but not for C++
option ‘-Wimplicit-function-declaration’ is valid for C/ObjC but not for C++
option ‘-Wimplicit-int’ is valid for C/ObjC but not for C++
option ‘-Wmissing-prototypes’ is valid for C/ObjC but not for C++
option ‘-Wmissing-parameter-type’ is valid for C/ObjC but not for C++
option ‘-Wold-style-definition’ is valid for C/ObjC but not for C++
option ‘-Wstrict-prototypes’ is valid for C/ObjC but not for C++
We have a struct called mkroom and a function called mkroom()
so c++ complains about the mkroom() function hiding the
initializer for the struct.
Similarly, we have a struct called attack and a function
called attack().
There may be a more elegant way of eliminating those two
warnings, but renaming mkroom() to do_mkroom() and
attack() to do_attack() was straightforward enough.
Whitelist all the verified existing triggers:
makedefs.c: In function ‘name_file’
attrib.c: one compiler balks at a ? b : c for fmtstring
cmd.c: In function ‘extcmd_via_menu’
cmd.c: In function ‘wiz_levltyp_legend’
do.c: In function ‘goto_level’
do_name.c: In function ‘coord_desc’
dungeon.c: In function ‘overview_stats’
eat.c: one compiler balks at a ? b : c for fmtstring
end.c: one compiler balks at a ? b : c for fmtstring
engrave.c: In function ‘engr_stats’
hack:c one compiler balks at a ? b : c for fmtstring
hacklib.c: one compiler balks at a ? b : c for fmtstring
insight.c: one compiler balks at a ? b : c for fmtstring
invent.c: In function ‘let_to_name’
light.c: In function ‘light_stats’
mhitm.c: In function ‘missmm’
options.c: In function ‘handler_symset’
options.c: In function ‘basic_menu_colors’
options.c: In function ‘optfn_o_autopickup_exceptions’
options.c: In function ‘optfn_o_menu_colors’
options.c: In function ‘optfn_o_message_types’
options.c: In function ‘optfn_o_status_cond’
options.c: In function ‘optfn_o_status_hilites’
options.c: In function ‘doset’
options.c: In function ‘doset_add_menu’
options.c: In function ‘show_menu_controls’
options.c: In function ‘handle_add_list_remove’
pager.c: In function ‘do_supplemental_info’
pager.c: In function ‘dohelp’
region.c: In function ‘region_stats’
rumors.c: sscanf usage
sounds.c: In function ‘domonnoise’
spell.c: In function ‘dospellmenu’
timeout.c: In function ‘timer_stats’
topten.c: In function ‘outentry’, fscanf, sscanf, fprintf usage
windows.c: In function ‘genl_status_update’
zap.c: one compiler balks at a ? b : c for fmtstring
win/curses/cursstat.c: In function ‘curses_status_update’
win/tty/wintty.c: In function ‘tty_status_update’
win/win32/mswproc.c: In function ‘mswin_status_update’
It turns out that macOS barked when a POP was issued without
a prior PUSH, so since the DISABLE_WARNING_CONDEXPR_IS_CONSTANT
expanded to an empty macro on that platform.
Include a corresponding
RESTORE_WARNING_CONDEXPR_IS_CONSTANT macro for use with that
particular warning.
Microsoft and other non-GNU compilers don't recognize gcc tricks
like /*NOTREACHED*/ to suppress individual warnings. clang recognizes most
of them because it tries to be gcc-compatible. Because of that, a lot of
potentially useful warnings have had to be completely suppressed in the
past in all source files when using the non-gcc compatible compilers.
Now that the code is C99, take advantage of a way to suppress warnings for
individual functions, a big step up from suppressing the warnings
altogether.
Unfortunately, it does require a bit of ugliness caused by the
insertion of some macros in a few spots, but I'm not aware of
a cleaner alternative that still allows warnings to be enabled
in general, while suppressing a warning for known white-listed
instances.
Prior to the warning-tiggering function, place whichever one of
the following is needed to suppress the warning being encountered:
DISABLE_WARNING_UNREACHABLE_CODE
DISABLE_WARNING_CONDEXPR_IS_CONSTANT
After the warning-triggering function, place this:
RESTORE_WARNINGS
Under the hood, the compiler-appropriate warning-disabling
mechanics involve the use of C99 _Pragma, which can be used
in macros.
For unrecognized or inappropriate compilers, or if
DISABLE_WARNING_PRAGMAS is defined, the macros expand
to nothing.
After the most recent round of moving old stuff to 'outdated',
src/windows.c contained two references to non-existent files.
That broke 'make depend'. Updating it to turn those two into
comments seems risky because someone might add an include for
some new interface later in the file. So comment them out in
the source instead. Also, redo previous 'make depend' update
from about three weeks ago to do the same thing.