Pull request by elunna with assistance by entrez tried to fix up
wand of striking discovery when the wand is zapped by a monster.
The fix didn't match the intended behavior (which may or may not be
the desired behavior...), so this skips the code in the pull request.
[I can't post comments on github anymore since I declined to switch
to their 2-factor authentication. But I can still read submissions
without logging in.]
This also tries to fix a couple of inconsistencies between zapping
by the hero versus by a monster. If the zap "boinged" :-) due to
target's magic resistance, zap by hero didn't discover the wand but
zap by monster did. Conversely, a zap by the hero that reached a
target and missed did discover it but one by a monster did not.
Now a zap of not-yet-discovered wand of striking by the hero which
hits, whether or not the hit gets resisted, will become discovered
provided that the spot where target is hit can be seen (the target
itself need not be), and one which misses or which can't be seen
hitting something will no longer be.
Supersedes #1223Closes#1223
Reported directly to devteam: if a magic trap gave its uncurse
effect, scroll of remove curse could become discovered.
Turns out that it would happen if hero was wielding a stack of
unholy water potions. It didn't matter whether they were known
as water or known to be cursed or whether hero was carrying any
scrolls of remove curse.
Using
|OPTIONS=windowtype:Foo
|OPTIONS=perm_invent
or
|NETHACKOPTIONS='perm_invent,windowtype:Foo'
would enable perm_invent if interface "Foo" supported it, but using
|OPTIONS=perm_invent
|OPTIONS=windowtype:Foo
or
|NETHACKOPTIONS='windowtype:Foo,perm_invent'
or combined
|OPTIONS=perm_invent
|NETHACKOPTIONS='windowtype:Foo'
would only enable perm_invent if both "Foo" and the default interface
supported it.
Using '--windowtyp:Foo' on the command line didn't have this issue
because command line interface selection replaces the default one
before configuration file and environment options are processed.
From a reddit thread: a 'mausoleum' theme room picked a vampire for
its occupant and applied the wait-for-you strategy to it. Hero's ESP
or monster detection showed a meditating vampire bat. Change monster
creation by the special level loader (which also handles theme rooms)
to force such a creature into its normal vampire form.
That revealed an older bug which wouldn't have been exercized prior
to theme rooms: a meditating vampire could and would shape change
without ceasing meditation. Make it not shape change rather come out
of its trance.
If moving on ice causes the hero to hurtle an extra step in a random
direction, don't allow that to be backward to where hero started.
Also, if hero is in grid bug form, only allow hurtling forward.
It was allowing slips in a diagonal direction, which seems wrong
for grid bug, and even when it slipped in an orthogonal direction,
buffered screen updating made the combined step+hurtle appear to be
a single diagonal step.
I'm not a fan of this seemingly simple change. The hurtle/second
step comes after the "you slip on the ice" vs "you slip off the ice"
messaging and might put the hero in a location which contradicts it.
Replace tabs, split 'if (condtion) do_something' across two lines,
insert lots of spaces in things like 'if(condition){'. I changed
a lot of C++ style comments to traditional C style, but left quite
a few of those as-is.
This also rewrites the code that pull request #1216 purports to fix.
I still can't make sense of the original and the patched edition.
Supersedes #1216Closes#1216
The prolog comment for hurtle() ends with
* dx and dy should be the direction of the hurtle, not of the original
* kick or throw and be only.
The clause "and be only" is incomplete and was added sometime between
3.3.0 and 3.4.0.
I suspect it was meant to say "and be only -1 or 0 or +1" but the code
enforces that with sgn(dx) and sgn(dy) so if that's the case, it isn't
necessary. Whether that guess is right or wrong, remove the clause
since as it stands now, it makes no sense.
Reported almost 9 years ago: if an adjacent statue was in a pit,
you could use a pick-axe to break it even though if you managed to
move to the pit location without falling in, you wouldn't be able
to reach objects there including the statue.
Allow a pick to reach if hero is in a conjoined pit, or if it is a
mattock rather than an ordinary pick-axe. Otherwise you'll get the
"you swing at thin air" result. Similarly when hero is in a pit and
and adjacent statue or boulder is on the floor: mattock will work
but pick-axe now yields "you can't reach".
Replace tabs, split 'if (condtion) do_something' across two lines,
insert lots of spaces in things like 'if(condition){'. I changed
a lot of C++ style comments to traditional C style, but left quite
a few of those as-is.
This also rewrites the code that pull request #1216 purports to fix.
I still can't make sense of the original and the patched edition.
Supersedes #1216Closes#1216
Noticed when testing the OPTIONS=symset:blank fix, map spots holding
engravings weren't blank.
Are there any other relatively recently added symbols that need to be
added to the blank set?
Any plain text symbol set specified in .nethackrc or NETHACKOPTIONS
didn't get loaded but did set the symset name.
Faulty 'if' logic excluded loading of symbol sets that used the
default handling type of H_UNK.
The wishy-washy warning for case BL_VERS was "may fall through" when
it always fell through, and there was no mention of the fact that the
assignment had no effect because it was immediately overwritten by
similar assignment for the fall through cases.
It may have 'spacing = 2' rather than 1 at some point, but since that
field is right justified it wouldn't make any difference.
Don't include the new 'showvers' option in the short 'O' menu.
optlist.h doesn't start with the usual line with substitutable fields
but I haven't attempted to amend that.
Add options 'showvers' (boolean) and 'versinfo' (numeric mask) to
show nethack's version on the status lines during play. It won't be
particularly interesting to ordinary players but should be useful
when making screenshots or video to be streamed, or for someone who
switches between git branches or between nethack and variants.
I worked on this several months back but it was combined with
unfinished changes to 'hitpointbar'. I've separated it out so that
it can be put into use. When enabled, one or more components of
"<name> <branch> <version>" will be shown right justified after
status conditions. At present the default is "<branch>" if that is
available and overall status isn't 'released', or "<version>" if
'released' or if branch isn't available. That might need some
refinement.
It works as intended for tty and curses, although some abbreviation
mechanism would be useful if/when the program resorts to abbreviating
status conditions to make things narrow enough to fit.
For X11, it works ok for fancy_status:True (the default, controlled
via NetHack.ad settings) but is messed up for tty-style status. The
text is positioned correctly but there are gaps in it, making it
appear garbled, similar to what I saw when I tried and failed to
implement statuslines:3 for X11. [It might be due to having empty
condition widgets be 1 pixel wide instead of being totally removed
but I don't think the situation is that simple.]
For Qt, if the text needs to be truncated in order to fit, the center
portion of the string will be shown, discarding parts from the left
and right. That ought to discard from left and retain rightmost
portion instead.
For win32|mswin|Win GUI, no attempt to support it has been included.
Things should be ok when 'showvers' is left as False (the default)
but I don't know what will happen if that gets toggled to True. At a
minimum, the version info won't be right justified. The information,
or at least some of it, is displayed in the game window's title bar
so there isn't any pressing need to add it to status, but toggling
the option will need to behave sensibly if it doesn't already.
Insert a space between cast operator and target.
For 'x | y' expression spanning multiple lines, split with bitwise OR
operator at the beginning of second line instead at the end of first.
I changed a macro that was expanding to 'expr_1; expr_2' into
'(expr_1, expr_2)'. Both expressions modify arg 'a' which would be
a no-no within a single expression, but the comma operator provides a
sequence point that guarantees that the first expression will be fully
evaluated with side-effects--assignment to 'a'--completed before the
second one starts, making both assignments be well defined.
A bunch of routines return a pointer which is never Null but weren't
telling the compiler that such was the case. A couple (strsubst(),
stripchars()) were accepting Null output argument and then returning
Null, but callers had no reason to use them that way, so they've been
changed. (upstart() could have been changed similarly; I've already
forgotten why I left it as-is.)
The recent "trap.c reformatting" commit included a non-formatting
change switching from gb.bhitpos.x,.y to local x,y in the rolling
boudler trap routine. The part of that routine used when a rolling
boulder hits another boulder and transfers its remaining momentum
to that other one got switched to wrong x,y and the first boulder
basically kept going, possibly hitting itself at each new position.
Monstly changing '<type>* <var>' to '<type> *<var>'. Wrap or shorten
a few wide lines.
One of the rolling boulder routines accessed gb.bhitpos.x,y many times;
change that to use local x,y instead.
If a termcap entry for ending attributes and color also contains
the code to switch from secondary font back to primary (HE_resets_AS
hack), maybe strip the AS code out of HE (and clear the HE_resets_AS
flag) when setting up DECgraphics. Affects whether nethack sends
extra AS sequences while rendering a run of VT line-drawing chars.
My HE doesn't reset AS so that aspect hasn't been exercized.
When switching back and forth between normal and line-drawing,
defer the switch away from line-drawing if the character will be
rendered the same in both character sets (uppercase letter, digit,
most punctuation). That might just defer the AE, but could skip it
and next AS depending on what characters are written. The cycle
might repeat an arbitrary number of times, avoiding sending many
AS+AE combinations rather than just one.
Both of these optimizations are pretty small but reducing the number
of characters sent from a server to a remote user is worthwhile.
If a punished hero's inventory is empty, have a nymph usually take
off the attached chain and indirectly fix punishment. If hero is
trapped by being chained to a buried iron ball, sometimes take off
the implicit chain and indirectly release hero from the trap.
Monkeys won't do this and nymphs will only do so if there is no
inventory (aside from gold and/or embedded dragon scales which they
aren't allowed to target).
It's a lot simpler than I was expecting when I wrote the TODO about
it recently.
If a trap is blocking levitation or flight and you use wand of opening
or spell of knock to get out, you'd get things like
|You start to float in the air!
|You are released from the bear trap.
Give the release message before the actual untrapping.
Add a comment about something that occurred to me when fixing the
^C-during-DECgraphics-output situation several days ago. I don't
think there's any compelling reason to avoid this optimization, but
this only describes it without actually implementing it.
Simplify the valid-position highlighting via '$' by combining the
tmp_at(start) and tmp_at(populate) steps.
Add highlighting for a couple of targetting operations that would
give valid/invalid feedback via autodescribe but weren't displaying
highlight markers for $.
I made several jumping changes, most of them dealing with picking
hero's own spot.
Redo getpos() highlighting. If bgcolors is Off, '$' toggles between
no highlighting and showing dollar signs at valid spots. ^R removes
those if they're present. When bgcolors is On, '$' cycles among
three settings: highlighting via background color, no highlighting,
and highlighting by drawing dollar sign characters. ^R switches to
background color mode.
This doesn't directly solve the problem of background color causing
conflict with the foreground color of some objects or monsters, but
being able to get rid of the background with a keystroke should be an
improvement.
'bgcolors' defaults to On, which was a problem for tty when 'color'
was Off. Turn it Off (in the core) for text map if color is Off and
bgcolors hasn't been explicitly set. Conversely, Qt was leaving
color Off and then using color with abandon. Turn in On (in the core)
for tiled map if it hasn't been given an explicit value. Those two
changes should cope with most situations and still let the player
override.
Change the goodpos symbol, which is used to mark valid locations for
some operations when getpos() is having the player pick a spot, from
green question mark to blue dollar sign. Dollar sign is the default
keystroke to toggle those markers off and on.
Add the 'dump' argument to the existing '--version' command-line
option to display the magic numbers used when validating save and
bones files for compatibility.
Nothing exciting, just a line of 5 hex values. I was going to also
list the values for however many save and bones files are specified
on the command line but it seems to need more effort than I care to
expend. And I hadn't made up my mind whether that should be done by
nethack, recover, or some new standalone program. [Single line of
relatively raw output is so that they could be compared more easily.]
nethack --version:bad-argument was writing a message to stdout and
then starting play--which immediately overwrites stdout. Have it
quit instead. Player wasn't trying to start a game and quitting is
what it does with --version:good-argument.
'uskin' isn't part of worn[] so wasn't being checked with the other
slot pointers. Add that, although it'll be excluded by default and
need to have EXTRA_SANITY_CHECKS defined to include it.
Check the various uarm, uwep, and so forth pointers to make sure that
they point to items in hero's inventory and that those items have the
corresponding W_ARM, W_WEP, &c bit set in their owornmask field.
Also check whether any other items in inventory have the same bit set.
[Some of this is already handled by sanity_check_worn() in mkobj.c.]
Also validate two-weapon combat mode. I don't recall ever seeing any
problems reported about it though.
Does not validate ball and chain. Those should have their own sanity
checks that validate a bunch of other stuff besides just worn slots.
They already get some checking by the normal object tests.
This works ok with 'sanity_check' set and items worn and wielded
normally. The only insane situation tested was by reverting the
confused-looting-with-quivered-gold fix from earlier today. I haven't
used a debugger to force other such problems so this isn't very
thoroughly tested.
Noticed while testing confused #loot: when using 'Q' to populate
quiver, or 'f' when quiver is empty, don't bother asking what to
ready/fire if inventory is empty.
And when inventory isn't empty, don't list '-' as a likely candidate
if quiver is already empty.
'w' behaves differently. '-' is treated as a likely candidate when
already not wielding anything, and even when inventory is completely
empty.
lava_effects() item destrunction had the logic for handling Book of
the Dead wrong. (However, that didn't matter since the obj_resists()
check earlier would prevent it from being burned up. Fix it anyway.)
If gold is moved into throne's coffer chest (or added to exchequer
monster's minvent) while quivered by the hero, it wasn't being unworn
to remove it from quiver slot. That could lead to a crash. Example
was segfault during 'f' command.
freeinv() expects caller to unwear item being removed from inventory;
reverse_loot() wasn't doing so.
If any part of a long worm is within a posion gas cloud region,
include it just once no matter how many segments are inside. The
tail will take harm from poison gas, but only once rather than for
repeated for every segment inside the region.
Unlike with detection, show long worm tail if hero is adjacent to
it in a gas cloud region and would see that tail segment if the
region wasn't inhibiting visibility.
I've been building tty-only for a while in order to speed up
builds, so a recent change to the curses interface that broke
compile on older OSX went unnoticed. The <curses.h> on my
OSX 10.11.6 system does not define A_ITALIC.
Reported yesterday as issue #1207 by elunna and over four years ago
in #H9430: monsters in gas clouds that should be shown by Warning
aren't. And in some discussion of #H9430 back then: monsters
adjacent to the hero while in gas clouds aren't shown on the map,
but combat and other interaction describes them as if they were.
There have been changes since then--to prevent seeing things on the
far side of gas clouds as if there were no clouds in the way--but
the basic problems with warning and adjacency weren't addressed.
This is a band-aid (tm) that probably makes things livable. Don't
allow gas region display to override monsters that are sensed via
warning or when the hero is next to them. That part doesn't work
correctly if the hero isn't blind and is inside the cloud while the
monster is adjacent but outside. I think it will take more than a
band-aid to deal with that sensibly.
Closes#1207
Reported by elunna: a poison gas breath attack that was reflected
by the target still left that target enveloped in a poison gas cloud.
This makes the gas trail not extend to the target if the attack hits
and is reflected. But if the attack misses then the cloud does reach
the target, which seems weird to me. However, being in the cloud is
a separate event that isn't deterred by reflection.
Closes#1204
Teleporting due to loss of protection against water or lava isn't
the only way a visible thief might produce "It stole <item>" prior
to the fixup the comment explains.
The late comment about uball and uchain becoming Null was there to
explain why they weren't referenced when inserting the phrase
| (was_punished && !Punished) ? " removed your chain and" : "",
into "<Mon> stole a heavy iron ball." That isn't there anymore so
get rid of the comment.
Yesterday's commit to add a "<Mon> takes off <item>" during theft
of a worn item used uchain instead of uball when the item was uball.
That works as intended when uball is just carried, but if it is also
wielded, alt-wielded, or quivered then the pointers for those weapon
slots weren't updated (because uchain doesn't have the corresponding
owornmask bits set when removal performs unpunish()). Check for that
and call remove_worn_item() again if necessary.
Also, the subsequent "<Mon|She> stole <item>" message was inserting
"removed the chain and" before "stole" when item is uball, but that
isn't needed anymore since the preface message "<Mon> takes off the
iron chain (attached to you)" will have just been given.
When a nymph or monkey successfully steals a worn item from hero,
first the item is unworn, side-effects of that take place (most
noticeably descending when losing levitation or flight) including
feedback about such side-effects, finally "<Mon> steals <item>" and
transfer from invent to thief's minvent. If the side-effects were
fatal (such as drowning or burning up in lava), the player wouldn't
see any explanation for why that happened.
When a thief removes a worn item, give a message to that effect:
"<Mon> takes off your <item>." That will usually be immediately
followed by "She stole <item>." When the thief isn't a nymph or if
any messages were delivered after the "takes off" one, the monster
will be described by name: "<Mon> stole <item>."
Having an item that allowed being in/on water/lava be stolen could
result in the hero teleporting. If the thief wasn't visible from
hero's new location, the message given was "It stole <whatever>."
Save the thief's name/description before removing the item and
potentially dropping hero into trouble and triggering teleport, then
use that in the eventual message.
Three months ago to prevent an "object lost" panic situation when
stealing an item that let hero survive water (several candidates)
would result in drowning, remove_worn_item() was changed to flag the
item being removed as in_use and emergency_disrobe() was changed to
avoid dropping in_use items while drowning. That seemed to work ok.
But for lava instead of water, in_use is a flag to destroy the item
(set in advance, before issuing messages that can give the player a
chance to trigger a hangup save). So instead of keeping the item
around for theft to finish, it was deallocating it. steal() would
format the freed object and then access some of its fields, leading
to havoc.
This adds a hack to allow one item already flagged as in_use to be
treated differently by lava_effects() from the ones it flags for
destruction. This also seems to work ok, but we may need to start
putting freed items on a deferred deallocation list similar to how
dead monsters are kept around for the rest of the current move.
The fix/hack has revealed two more bugs that this doesn't address.
An item being stolen is removed without any message, then if that
removal doesn't kill the hero a theft message is given. The message
sequencing is wrong. Flying hero who loses amulet of flying just
gets affected by lava; player is only told why after life saving.
The other issue is that life-saving from lava can teleport the hero
to where the thief can no longer be seen, yielding "It steals <item>"
even though "It" was visible when the theft started.
For tty, if ^C interrupt occurred while the terminal was displaying
VT line drawing characters, it wouldn't finish updating the map and
switch back to regular characters, so the "Really quit?" prompt was
illegible.
Rather than muck about with the signal handler, just add a fixup to
tty_putstr() since prompting ultimately uses putstr(WIN_MESSAGE).
Reproducing the situation isn't straightforward; I didn't even try.
Lembas wafers give more than normal nutrition for elves and less than
normal for orcs. Cram rations give more that nomral for dwarves. The
way that was implemented affected the weight of those items, at least
after they were partly eaten. Polymorphing to or from any of the
affected races resulted in inconsistent partly eaten food.
Change how the nutritional bonus or penalty is applied so that there
isn't any affect on item weight.
I haven't incremented EDITLEVEL, so any wafers/rations with incorrect
weight in existing save files will continue to have that wrong weight.
I suppose that it matters more for bones files but even they should be
ok living with this instead of being forced to be thrown away.
merge_choice() doesn't need the address of its list argument, just to
return Null if that list is Null. Could have been solved by having
its callers check for Null invent and skip the call if necessary but
this is simpler.
Finishes reverting commit 378648bd9c.
This reverts commit 378648bd9c.
The problem was triggered by marking the 'objlist' argument in
merge_choice() prototype with __attribute__((nonnull)) when it
shouldn't have been, then a followup which relied on that. The
'objlist' argument might be Null. Instead of passing its address to
force it to be non-Null, remove the attribute.
Reported directly to dev-team: vapor cloud dissipation didn't always
update vision properly.
Region removal affecting visibility needs to make two passes, the
first unblocking all no longer blocked spots, then the second deciding
whether spots are visible.
Attempting to do that in one pass was doing
| unblock <x1,y1>
| if cansee <x1,y1> whatever
| unblock <x2,y2>
| if cansee <x2,y2> whatever
and the cansee <x1,y1> test wasn't accurate if <x2,y2> blocked it and
hadn't been unblocked yet.
Testing with steam didn't seem to trigger the problem but with poison
vapor trail from green dragon breath did. The order of evaporation
mattered too; sometimes the single pass unblocking plus vision-testing
worked ok by coincidence.
Eliminate the 'goto' for human corpse added a day or two ago.
If a dead gnome is generated with a candle, light it if/when the spot
is dark. (Testing never managed to verify that this works as intended.)
mkcorpstat() never returns Null.
Re-use the array allocated for iterating over all monsters during
monster movement much of the time. It was being allocated from
scratch for each round of monster movement, then freed after they
moved, then repeated the next round.
Update some potential weight issues. Eggs won't hatch when in
containers so they weren't affected but add some bulletproofing.
Corpse revival from inside containers was already ok too, so
effectively there's no change except for making container_weight() be
global instead of local to mkobj.c.
When a low-level trap is created with a dead pseudo-adventurer,
usually make a player monster when the human case gets picked.
They have default level and no inventory. They should probably be
given montraits that force low level but this doesn't do that.
The recent acurr() changes introduced a bug that caused Str less
than 25 to be limited to 18/07. 25 was treated correctly as a
special case but 18/01 through 18/100 and 19 through 24 were not.
The cap of 25 imposed on the other characteristics is the same as
encoded Str 18/07.
Restore its ability to reject a string longer than will fit within
size_t that was lost by moving away from strnlen(). Determine the
length inline rather than using strlen().
Move it from hacklib.c to alloc.c so that utility programs have easy
access, and remove the copy of it from dlb_main.c.
Fix a logic bug in str_start_is(). If a string was considered to
be too long, it exited the loop when n was 0 but also performed
post-decrement. So after the loop, n would be -1 and the 'if (n==0)'
test would fail. panic() would occur if the initial string matched
and happened to be LARGEST_INT-1 characters long.
Previously reported via github pull request #1188 as an out of bounds
access to u.uhpinc[], followed by issue #1189 when it was closed, the
backtrace accompanying new assertion failure provided more information
that led to figuring out the problem.
Only mattered for the debug fuzzer; wouldn't happen in regular play.
When the hero dies during fuzzing, the fuzzer sometimes restores lost
levels via blessed potion of restore ability. If that happened to a
hero who died by being life-drained while at level 1 then losexp()'s
assumption that life-saved hero was still level 1 got violated. If
levels had been lost all the way down from a peak of 30, restoration
to u.ulevel==30 resulted in invalid array indexing into u.uhpinc[],
then failure of 'assert(u.ulevel >= 0 && u.ulevel < MAXULEV)' which
was added to avoid that.
Pull request #1188 and issue #1189 are already closed, but they hadn't
actually been solved yet.
Fixes#1188Fixes#1189
+/-N for charged rings with known enchantment was clobbering the
BUC formatting that had occurred earlier. #K4088 thought it was a
problem with the implicit_cursed option; followup #K4089 from same
user correctly pointed out that the problem was present for any BUC
state.
This is the same line of code that inadvertently omitted the space
between +/-N and "ring of <type>". That was fixed by commit
1a2b2a8cae a couple of days ago.
While in doname(), fix a potential issue calling corpse_xname().
That assigns a new value to gx.xnamep, clobbering the value that
doname() relied on when it was first called (but doesn't look at
again, so doesn't matter now but could conceivably in the future).
Have alloc() treat a request for 0 bytes as if it was one for
'sizeof (long)' bytes so that the issue of malloc(0) maybe yielding
NULL becomes moot.
I think instances of attempting to allocate 0 bytes should probably
still be checked for and made to avoid calling alloc(0). Assuming
that alloc() will clean up requests for nothing feels sloppy.
While hunting for a memory leak in object allocation--which I haven't
found yet--I discovered one in monster movement. iter_mons_safe()
allocates an array of (monst *) pointers for the monsters on the
current level, loops over that array to call a function for each
one, then frees the array. But if the game ends while that called
function is running, execution never returns to iter_mons_safe() so
it wasn't able to free the memory.
Since that can happen at most once per game, it wasn't a signifcant
leak. This fixes it anyway.
There was a second issue: make sure that iter_mons_safe() doesn't
call alloc(0) to make the temporary array for zero monsters when
there aren't any on the level. That might not be able to happen for
monster movement but the routine is written to be more general than
just movement. alloc(0) could confuse the MONITOR_HEAP code. In
C89/C90 I think malloc(0) is allowed to return NULL (don't recall
for sure; maybe that was just known pre-standard behavior for some
implementations). Null return would trigger a panic even without
MONITOR_HEAP. Don't know about C99 and later.
Changing the quantity to 2 (50:50 chance) when creating a potion of
healing (also 50:50 chance for each attempt) to place inside a supply
chest wasn't updating the potion stack's weight, resulting in the odd
encumbrance behavior that was reported last December.
Taking the stack out of the container doesn't fix the weight but
drinking one of the potions splits the stack of 2 into two stacks
of 1 and does update the weight for both. That gives the hero higher
encumbrance when the formerly weightless one has its proper weight.
Finishing drinking the potion uses it up, removing second potion's
weight again. When below an encumbrance threshold by the weight of
one potion or less, player will see encumbrance increase and then
decrease, with healing message given before both due to sequencing.
Supply chests weren't having their own weight updated when they were
populated, so would behave as if empty if hero carried them around.
Removing something, breaking something by kicking the chest, or adding
something would update its weight to match its contents.
I also noticed a refutation (or should that be rebuttable?) to my own
remarks in this:
| commit cd91d0630b
| Author: PatR <rankin@nethack.org>
| Date: Sat Dec 30 17:10:39 2023 -0800
|
| github issue #1180 - humans and murder
|
| Issue reported by Umbire: reviving a human corpse into a human
| monster and then killing it entails murder penalty even when it is
| hostile.
|
| This is probably a non-issue. Human monsters tend to not leave
| human corpses, they leave shopkeeper corpses or sergeant corpses
[...]
Dead fake hero corpses placed at trap locations on early levels are
leaving plain human|dwarf|elf|gnome|orc corpses rather than fake
player monster ones (which are always human but resurrect as player
monsters rather than as plain humans), so there are more plain human
corpses now than there were in 3.6.x or early to-be-3.7. I've added
a comment about the situation.
Pull request from entrez: revise the Platinum Yendorian Express Card
data.base entry for style and remove out of date assertion that it is
unreadable.
Closes#1178
Pull request from entrez: some old trap code became obsolete or
at least less useful when the trap routine was split into separate
routines for each type of trap. The type of trap currently being
handled is already known by each of those routines.
Closes#1174
Pull request from janne-hmp: defer releasing the memory for the
current level by having savebones() using write mode rather than
write+free mode. nh_terminate() -> freedyanmicdata() will free the
current level.
Matters for 3rd party html dumplog (which nethack doesn't support).
The commit message is misformatted and misleading but it's a bit
late to fix that now.
Closes#1177
If your inventory is full and you aren't already carrying a loadstone,
you can pick one up into the overflow slot. But if you are already
carrying one and the one you're trying to pick up won't merge with it
(only criterium that matters would be BUC state, I think), you can't
pick it up and get a message saying so. If loadstone isn't known
yet, the message always referred to it as "gray stone" rather than
"stone called <whatever-you-called-it>".
Replace the single strnlen() use with strlen() so as not to require
something from posix.1 (2008) when we supposedly only require c99.
If someone manages to produce a string that's longer than will fit
within size_t, strlen()'s length count will wrap and Strlen_() might
not notice. Since size_t has to be at least 32 bits, that doesn't
seem like something to worry about.
If checking for size_t overflow is considered essential, we should
just switch to counting the length via an in-line loop that imposes
a similar limit to strnlen().
When ready to return, check for overlooked overflow (shouldn't happen)
and panic, or report the first excessively long but not overflown
description to paniclog, similar to xname.
Make ConcUpdate() more robust by not needing bp_eos to be previously
set. Less efficient but I think that boat has left the barn? :=}
Fix a comment typo.
Issue reported by Umbire: suggestion to always destroy adjacent webs
via 'F'<dir> if wielding Sting or Fire Brand.
Sting already did that; this adds Fire Brand.
This also augments the #untrap command when wielding either of those,
or any other blade. And rephrases successful untrap message
"You remove {the or your} {bear trap or webbing} from Fido." to
"You extract Fido from {the or your} {bear trap or web}." since the
trap remains intact.
Forcefight and #untrap against webs ought to be reconciled to remove
[some of] their differences and/or share code. But not by me...
Closes#1201
Avoid two new warnings in xname_flags() about strncpy() not supplying
a terminating '\0'. That's exactly why strncpy() was being used.
The gcc manual lists -Wno-stringop-truncation to suppress the warning
but not -Wstringup-truncation to voluntarily enable it, so the pragma
stuff in warnings.h probably won't work for this. Just switch from
strncpy() to memcpy() instead even though it seems like obfuscation.
PR #1140 added checking the thrown, stolen, and dropped flags of an
item when testing whether it would merge (at my suggestion...) with
a stack in the target list (hero's invent). That interferred with
picking it back up--whether via autopickup or explicit pickup--while
inventory was full even when the item would otherwise be mergable.
There was some trial and error involved when trying to figure where
to put the fix but things seem to be working.
This replaces a static analyzer workaround and could possibly bring
its unwarranted complaint back.
Try harder to prevent buffer overflow when formatting objects.
I don't have any test cases where overflow has been happening so
don't really know whether this works reliably. And it doesn't try
to check prefix construction by doname(). [Yet?]
"blue potion" wasn't a very good example for an item in a container;
plain "blue" isn't a potion description.
Add an extra sentence to make the association between a container's
"item count" that's really a stack count and the fact that inventory
slots are for stacks rather than for individual items too.
Style/usage bit: avoid using "another" twice in the same sentence.
Fix a typo in the spelling of "contents".
Have monster spells
| "shower of missiles" (AT_MAGC+AD_MAGM: Angels, Yeenoghu)
scuff an engraving at the hero's spot if there is one,
| "frost" (AT_MAGC+AD_COLD: only Asmodeus)
freeze water and lava terrain,
| "flames" (AT_MAGC+AD_FIRE: moot, no monster has this attack)
burn items on the floor at the hero's spot and melt ice terrain,
| "pillar of flame" (AT_MAGC+AD_CLRC+randomly chosen clerical spell)
which already burns floor items, melt ice too, and
| "lightning" (same casters as pillar of flame)
give a tiny chance of destroying iron bars. The chance to hit bars
is low and the hero has to be targeted while located on an iron bars
spot so probably won't happen before the sun burns out, but only
needed one extra line of code.
Only the first two have been thoroughly tested.
If a covetous monster tried to teleport adjacent to the hero but the
level was too full to move it from its current spot, it would be
sent off level to wait for the hero to leave and return instead just
staying put.
Issue reported by chappg: if a monster or object covered an engraving,
examining that monster or object with farlook would include the text
of the engraving even though it wasn't the thing being examined.
The report was for a bones level but that only mattered because it was
a ghost on top of a grave (and the engraving on its headstone) that was
being examined; bones data itself wasn't pertinent. It would happen
with any engraving once the spot was mapped as an engraving or a grave
provided that something else was currently displayed at the location.
Bug was introduced by commit 389f03e90e
two months ago. Mea culpa.
Closes#1200
Hero attempting to cut an adjacent web can so with secondary weapon
if dual wielding and primary isn't a blade.
Mostly message handling for the 'neither weapon is a blade' situation.
Change MON(name, ...) to MON(NAM(name), ...) and get rid of MON3(),
replacing it with MON(NAMS(malename,femalename,neutername), ...).
That eliminates the macro which uses 16 parameters. Standard C
allows compilers to impose a limit of 15, rejecting 16 or more while
still being in compliance.
That necessitated some reformatting since it made the first line of
each entry longer. Shorten that by having all entries start with
name(s) and symbol on the first line, then LVL() and generation flags
on the second line, then attacks start on the third.
Reformat attacks to change ATTK(one) + 4 * NO_ATTK on one line plus
an orphaned NO_ATTK on the next line to always use ATTK(one) on first
line and all 5 NO_ATTKs on the next line. Similarly, change ATTK(1of2)
ATTK(2of2) NO_ATTK on one line followed by 3 * NO_ATTK on the next line
into ATTK(1of2) ATTK(2of2) followed by 4 NO_ATTKS. For three attacks,
list two on the first line then the third and 3 * NO_ATTK on the next.
Four or more attacks use a third line; ATTK(1of4+) ATTK(2of4+) on the
first, ATTK(3of4+) ATTK(4of4+) on the second, and whatever's left on
the third. SIZ() follows on its own line for each of the cases.
Split the final line of each entry so that the difficulty value is the
first thing on that line, followed by color and enum tag. This may or
may not make moving the difficulty into LVL() easier someday (which
would have been an alternate way to reduce the 16 args that MON3 had).
The file gets stretched out by many lines but entries should be easier
to read (matter of taste, I suppose).
I didn't attempt to clean up M1_foo, M2_bar, M3_quux; too hard....
I also didn't touch SIZ() or resistances which are less cluttered than
the other stuff.
Add a couple of non-zero permonst flags to the terminator at the end
of mons[] in case some code using a pointer to mons[NUMMONS] for "not
a monster" unexpectedly references them.
Also, eliminate some obsolete handling for conditional color support
from monst.c.
Commit 7a533a911c about three weeks
ago reordered a couple of timers. The list of timers in nhlua.c was
overlooked at the time.
The theme room "Ice room" was affected. I'm surprised that sanity
checking while running the fuzzer didn't notice and complain.
Pull request from entrez: change erinyes from lame devils named
after the Furies of Greek myth into those Furies.
Bumps EDITLEVEL because of changes to saved data. I augmented the
new data.base entry.
Closes#1150