When using '/' or ';' and picking--not just viewing the autodescribe
feedback for--a space or '#' on the map, the game would produce
That can be many things (stone)
or
That can be many things (corridor)
unlike the usual
- the interior of a monster or a wall or an open door (wall)
when the symbol matched more than 4 things. I first changed it to
append the full sentence's missing period, but ultimately switched to
# can be many things (corridor)
so that the symbol that "many things" refers to isn't hidden. This
works better for ^P where player isn't looking at the symbol anymore.
There was a post-3.6.2 discussion on a forum where someone had
tried to copy the NetHack 3.6.2 exe file overtop of an
existing NetHack 3.6.0 playground, and then try to run it.
We have never suggested trying that, nor do we attempt to
provide any backward or forward compatibility between the
supporting files found in nhdat that would allow that. Any
particular version of NetHack expects to have matching
support files designed and matched to that version.
This adds optional support for helping to prevent the
opening of nhdat containing support files from an
unmatched version of NetHack.
If you #define VERSION_IN_DLB_FILENAME in your
platform's include/*conf.h file, it will use a
name such as nhdat362, instead of plain nhdat, and
will exit more gracefully than the fault/crash
mentioned in the discussion if it doesn't find the
file it is looking for.
Developers - please note that if you do
to cause NetHack to look for an nhdat* file with
the version info appended to the name, you will likely
have to modify your build/clean/spotless mechanics
beyond the C compile itself to properly deal with the
new generated file name.
When place_object() puts a non-boulder underneath a boulder, make it
put the non-boulder under all the boulders there rather than just under
the topmost one. Otherwise the map display will show the non-boulder
rather than the 2nd boulder if the top boulder gets moved away by some
means other than pushing. (Pushing explicitly brings lower boulder to
top of pile in order to try to push it next.)
Reproduce by: wish for boulder--it will drop. Drop something else--
the something-else will end up under the boulder. Repeat. The second
boulder will be on top but the second something-else will be next in
the pile, above the first boulder. Now polymorph into a giant and pick
up the first boulder, then move away from that spot. Map will show
second something-else instead of the remaining boulder.
This fairly simple fix should work reliably on new games since boulders
will end up being consecutive on the top of piles. For old games,
boulders after the topmost could be anywhere and still yield a display
glitch, but since that's all the problem is (I hope...), we ought to
be able to live with that until old games eventually go away.
[A map display glitch doesn't explain a corrupted 'uball' so this fix
doesn't solve that.]
Being turned into green slime never drops hero's inventory so invent
objects shouldn't be subject to obj_not_held() handling.
obj_not_held() does apply to undead. Arising as a mummy or vampire
doesn't go through the trouble of dropping everything and picking it
back up, but there is a point in the die...arise sequence where the
hero is implicitly a corpse so nobody is holding his/her stuff.
Add a bc sanity check. It seems to work ok--in other words, not
trigger--under normal punishment. I don't have any test cases to
exercise its warnings.
This dragged in a couple of minor bc changes that were pending. I
should have cleared those out before tackling the sanity checking.
When cloning a monster, clear the clone trapped and hiding states.
When splitting a monster (eg. a black pudding), the clone could
be placed on a trap, so do mintrap.
When removing a monster from the map, clear the trapped state.
Fixes#188
The change to fix setting SEDUCE=0 in sysconf broke chatting with
seductive demons by unintentionally changing the way Null attack
argument was handled. It's still handled differently than it used
to be, but I think this difference is correct.
Fixes#187
Qt5 gave "status 'reassess' before init" panic at start of new game.
Don't call status_initialize(REASSESS) from set_usamon()--used for
hero setup as well as for hero polymorph--unless it was previously
called from display_gamewindows() with !REASSESS [which happens when
windowprocs.wincap2 has WC2_STATUS_HILITES or WC2_FLUSH_STATUS set].
If a poly'd hero spits venom and it lands at a 'soft' spot such as
water, it would remain as an intact venom object. (Venom spat by
monsters seems to always be used up regardless of where it lands.)
Vlad keeps his own form when carrying the Candelabrum, but if you
manage to get that away from him he should behave like other vampires.
He wasn't though; a high level wizard casting polymorph on him would
change him into an arbitrary monster rather than into a wolf/bat/cloud
that revives as Vlad when killed.
|The seemingly dead vampire bat rises as a vampire.
was overriding hallucination when describing both old and new forms.
In 3.6.0 it only overrode the dying shape (explicitly so, presumeably
because the feature was brand new) and honored hallucination for the
revived shape. The 3.6.1 fix to prevent non-hallucinating: 'The
seemingly dead Foo rises as Foo.' for a named vampire unintentionally
overrode hallucination for the revived shape.
Change it to honor hallucination for both before and after monsters
|The seemingly dead grid bug rises as a microscopic space fleet.
Preserve temporary fake object's previous dknown value by storing it
as a flag value within the m_ap_type field of the posing monster, and
recalling it when it is needed.
This is intended to help eliminate observable differences in price display
between real objects and mimics posing as objects.
98% of this is just switching the code to utilize macro M_AP_TYPE(mon)
everywhere to ensure that the flag bits are stripped off when needed.
Noticed while looking over mimic hiding. When on an object, a mimic
will hide as that type of object. But for a corpse, it picked a random
monster type and could choose one that doesn't leave a corpse. Also as
a tin it would always be an empty one, but there doesn't seem to be any
way for a player to learn that.
Noticed while trying to find the reason for the wildmiss impossible(),
you could be teleported and then drop dead at the destination. A QM's
AD_TLPT hit also does 1d4 physical damage which gets applied after the
teleport. Getting "You die." seemed pretty strange, particularly after
picking the destination with telport control. This makes sure that the
damage will never be fatal when teleport is attempted.
Showing the price of a shop object when examining it with '/' or ';'
didn't include a price if it was actually a mimic. This makes fake
objects have prices when appropriate, but it is only a partial fix
because moving away from a mimic causes nethack to forget the fake
object's dknown flag for most types of objects.
That could be solved by adding an mobj field to mon->mextra, which
will break save compatibility, or by adding a whole extra set of
object glyphs for object-with-dknown-set. The latter could probably
be done without breaking backwards save compatibility (new program
using old files) but it seems like more effort that it'd be worth and
it would break forwards save compatibility (old program attempting to
use new files--something we've never claimed to support).
During shop repair, give a message about the shopkeeper using a spell
(if hero is close enough) before "Suddenly, <various repairs occur>."
And when shop repair is for a single untrap of landmine or bear trap
adjacent to shk (and the hero can see it happen), say "<Shk> untraps
<trap>" rather than just "Suddenly, a trap is removed from the floor!"
For the inventory of a probed monster, if the probing took place in
a shop the inventory display would have selling price appended to
all the items. That wouldn't really be a problem if it was just for
a pet who was carrying one shop item, but it applied to every item
being carried by any probed monster (including shopkeeper) with no
regard for whether the shop actually claimed ownership.
[I accidentally left this out of the earlier patch.]
Change in meaning of mnearto()'s return value wasn't progagated to
shkcatch(). Make it an int instead of boolean so that it can
communicate both 'moved successfully' and 'moved but had to move
another monster out of the way to do so'.
Change in meaning of mnearto()'s return value wasn't progagated to
shkcatch(). Make it an int instead of boolean so that it can
communicate both 'moved successfully' and 'moved but had to move
another monster out of the way to do so'.
The curses interface wouldn't build with HILITE_STATUS disabled. I
started adapting it to handle genl_status_update() but that was taking
too much effort with each niggling detail leading to another. This
goes the opposite direction: forcing the old STATUS_VIA_WINDOWPORT
behavior without having that #define available. That dragged along a
bunch of unexpected changes too.
mon_arrive() -> m_into_limbo() -> migrate_to_level() -> wormgone()
followed by place_monster() "for relmon". relmon() was changed (last
November, cc5bb44a9a) to not require
the monster be on the map, so just get rid of the place_monster() that
was trying to put the "gone" long worm at <0,0>.
Also, another m_into_limbo() bit: make mdrop_special_objs() check the
location and send any dropped items to random locations if the monster
dropping things isn't on the map, instead of placing them at <0,0>.
Take care of a minor 'TODO' and make another stab at getting truncated
encumbrance and/or level-description to reset to full size when enough
space becomes available.
Put the prototypes for routines in botl.c into the same order as the
corresponding functions are in the file. Also a few were missing and
another few used STATIC_OVL when STATIC_DCL was appropriate.
I didn't noticed this because I've been building for tty+curses+X11
and either of the first two cause iflags.extmenu to exist. Make it
unconditional; there's not much benefit from trying to suppress it
for configurations that don't need it.
When the 'time' option is on and context.botl isn't already set,
call a simpler status update routine that ignores all other fields.
When that flag is already set, full status update takes care of time
along with the other fields.
Expected to reduce bottom lines processing time but not screen I/O.
Only lightly tested.
I finally figured out why status gets updated periodically even if
none of the fields have changed. Once a temporary highlight times
out, it starts a cycle of timeouts every 'statushilites' turns. When
I worked on this before, it was convoluted but not this convoluted.
In moveloop, if 'context.botl' call bot; in bot
call evaluate_and_notify_windowport;
for each field, call evaluate_and_notify_windowport_field:
call hilite_reset_needed and set 'reset' to the result;
if 'reset' is True then do status_update
and set 'curr->chg' and 'prev->chg' to True.
Then in moveloop call status_eval_next_unhilite:
for each field
if 'curr->chg' set 'curr->time' to moves+hilite_delta;
on the call after hilite_delta ('statushilites') moves,
call hilite_reset_needed which returns True if there is any
rule for temporary highlight and set 'context.botl'.
Go back to start. If multiple fields had temporary timeouts and
they were activated on different turns so expired on different turns
you could conceivably end up with context.botl being set every turn.
My first writeup trying to explain all this was wrong. I won't
testify about the accuracy of this one in court....
This extends the highlighting data structure to track the current
rule that's in use. And for that to make sense, it eliminates the
merging of settings from multiple matching rules. So anybody with
hit-points/up/inverse
hit-points/up/green
hit-points/up/bold
will need to manually merge their rules like
hit-points/up/green&inverse+bold
or else whichever rule matches last will be the only one in effect.
There are a lot of miscellaneous changes made as I flailed about.
The three most significant ones are that there is no guesswork over
what kind of highlight rule is in effect, status_eval_next_unhilite
will only set a timeout value if the current rule is for a temporary
highlight, and hilite_reset_needed will only return True if a timeout
is for a temporary highlight (probably moot after the _next_unhilite
change).
Status formatting used to truncate the Name portion of "Name the Rank"
or "Name the Monster-type" at 10 characters even if the rank or monster
portion left room for more. Change that to keep as much of the name as
will fit. The truncation might vary over time as new experience levels
produce new rank titles of differing lengths, but I don't think that's
a problem. For truncated names, it still keeps at least 10 characters
even if that leaves the field longer than the target length for title
(which used to be 29 but now is 30).
Noticed while testing statuslines on a small terminal window. Using
the cursor to pick locations that panned the map to view a new subset
would end up showing a new view of the regular map rather than a
different section of what was currently displayed. For farlook that
caused monsters to take on new hallucinatory forms which was fairly
inconsequential, but for #terrain and various forms of detection it
reverted to the ordinary map instead of showing the map features that
the player requested or the temporarily revealed monsters and such.
Most interfaces keep track of the whole map and just show their view
of the new subset when panning, similar to redisplay after being
covered up and then re-exposed, but tty isn't doing that. I made
same change to Amiga as to tty since the code it was using was very
similar. I haven't touched any of the other interfaces and assume
that they don't need this. I've verified that curses and X11 don't.
Implement the 'statuslines' option for tty. 2 and 3 line status are
similar to curses. Tty's version doesn't include insertion of extra
spaces for enhanced readability, or ignoring 'showexp' when space is
needed for other fields, or right justifying 'score' and suppressing
it when there isn't room for the entire number. It continues to have
abbreviated condition and encumbrance descriptions that curses lacks
which get used when the normal ones take up too much space.
'statuslines' can be set with 'O' so it is feasible to switch back
and forth between 2 and 3 lines on the fly. But only if the display
is at least 25 lines (actually ROWNO+4) or else CLIPPING is enabled
at build time.
This fixes the bug where after resorting to abbreviated condition
values it sometimes (always?) wouldn't switch back after more room
became available. Abbreviated encumbrance values had problems too
(lack of leading space and not changing value if encumbrance changed
to anything other than unencumbered) and this fixes that as well.
Fixes#179
The Valkyrie goal level has two drawbridges and one of them was set to
have 50:50 chance to be closed (raised). But 'random' for drawbridge
open/closed (or lowered/raised) state was always choosing open (lowered).
This fixes that and also changes that level to have the old settings
(southern open, northern 50:50) for 75% of the time and new settings
(both 50:50) for 25% of the time. So there's now a 12.5% chance that
both will be closed instead of both always being open (due to the bug
with handling random).
Back in December, a change was made to suppress status when u.uhp == -1.
But if the hero died with exactly that amount, the status display would
be blanked out during end of game disclosure. Force u.uhp to be 0 when
dying. That was already happening if death occurred while hero still
had positive HP, but not when damage took him/her to negative.
Cleaver's ability to hit up to three adjacent targets could kill a
long worm and then try to cut it in two. When this was first reported
I was unable to reproduce it, but this time I've managed to do so.
But not reliably, so it's hard to claim that it's now fixed. However,
the new report's explanation of why it happens and suggested fix was a
big help. I had been trying to hit three tail segments, but you need
to attack a segment next to the head, then have Cleaver hit and kill
the head first (50:50 chance depending upon whether current swing is
clockwise or counter). Worm cutting would be looking at the location
of the targetted segment but there won't be any monster there when the
head dies. (Cleaver's attack itself already copes the situation where
its 2nd and/or 3rd potential targets aren't there any more by the time
it's ready to try to hit them.)
curses uses 'reversed' (LIFO) style when displaying previous messages.
Use the existing (previously tty-only) 'msg_window' option to also
support 'full' (FIFO). The actual code needed as just a couple of
lines; tweaking options parsing and the documentation was more work.