Add a theme room with multiple visible teleportation traps
which will always teleport to specific locations in the same level.
Teleport trap change from xNetHack by copperwater <aosdict@gmail.com>.
if Wizard escapes the dungeon
Reported by vultur-cadens: a fix to prevent quest feedback when quest
nemesis is removed from the game during bones creation introduced a
regression for an earlier fix that kept context.no_of_wizards up to
date if the Wizard of Yendor escapes the dungeon without dying.
Change 'wizdead()' to 'wizdeadorgone()' and call it from m_detach()
for mongone() as well as for mondead().
Fixes#1256
Pull request from mkuoppal: avoid integer overflow when user types
digits and they're combined into a number by successively multiplying
intermediate value by 10 and adding new digit. Needed to avoid
triggering undefined behavior if the value overflows the largest
signed integer (actually long int).
This is a much more general fix than the code in the pull request,
which imposed an arbitrary limit for one aspect of tty input.
I'm not convinced that integer.h was the right place to add the new
AppendLongDigit() macro. I may not have caught all the places where
it is needed. files.c accumulates a value from digits but uses
unsigned int, so overflow won't trigger undefined behavior (although
it presumably ends up with a different value than what was intended).
options.c and coloratt.c accumulate smaller integers and have a limit
on the number of digits they'll use, so can't overflow.
Fixes#1254
I was trying to examine gi.invent (via
print ((struct instance_globals_i *)&gi).invent
don't ask...) and gdb gave me very confusing rejections that don't
occur with other g<letter>.variables. It turned out that gdb was
treating 'gi' as a type rather than as a variable reference.
I suspect it was because Qt was included so linking used C++ mode,
and C++ handles struct names differently from C. Anyway, renaming
'struct gi' to 'struct glyphinfo' made the mystery problem go away.
Restoring was hiding unhidden mimics and if that chose an object
other than boulder of gold pieces, it called mkobj() before an
array used by that routine was initialized. The result was warning
"rnd(0) attempted" when NH_DEVEL_STATUS wasn't set to 'released' or
divide by 0 crash if it was set to that.
Restore should not be catching up for lost time when unpacking a
save file into individual level files, and if it hadn't done that
it wouldn't hide mimics who aren't currently hidden.
In addition to avoiding that, this also moves the initialization of
the offending mkobj array sooner.
[3.6 didn't use that array so wasn't susceptible to this. It is
hiding unhidden mimics during what should be a strictly bookkeeping
operation though.]
This makes it easier to understand what is happening in each of those
places, and also much easier to find the places that conversion between
hero and monster resistances happens (since you can now just grep for
"res_to_mr"). I think I got all the instances where the macro should be
used but I'm not 100% sure since there wasn't a single unique term to
search for to find them all.
I replaced the modifications to give_u_to_m_resistances made in the
previous commit, so that it now uses the same macro as other
conversions, since otherwise it would be much harder to find the
complete list of places where conversions between hero and monster
properties happen.
For curses, behave like tty by keeping a count of messages issued via
raw_print, then if that is non-zero issue a prompt and require the
player to acknowledge them before it erases the screen. Mainly so
that complaints during RC file processing will be seen.
For tty, force getret() to be an unconditional routine instead of
sometimes a routine, sometimes a macro which calls another routine.
Add the shop type variations used for automatically generated
annotations to the shop structure and get rid of the switch that
has been being used to pick them.
Make object deletion work similarly to monster deletion:
it's marked for deletion (by setting the where-field to OBJ_DELETED
and moved to specific deleted-objects chain), but they're actually
freed at the beginning of turn.
This may need some more tweaking, especially in places that iterate
over object chains, but fuzzing did not find any obvious problems.
Fix a case of accessing freed memory: a monster breathed at hero,
destroying some items. The code stored the next item in the chain
(a cloak), but a ring of levitation was destroyed, causing hero to
plop down into lava, destroying the cloak. The item destruction
code then tried to access the destroyed cloak object.
Make the code check the object where-field - which will be different
if the object was marked for deletion. Also removed an extra loop
going through the whole object chain looking for the items to
destroy.
Add a way to request that unpaid_cost() produce the cost for a single
item, which is necessary for the price adjustment made in
bill_dummy_object. Another option would be to simply divide by quan in
bill_dummy_object, but this might be more future-proof in case
unpaid_cost ever involves more than simple multiplication by quan
(e.g. the use of alternate units vs the base price, as are used for
globs).
Fixes#1236
underneath gets boiled away
Pull request by disperse: when a water walking hero zaps a wand of
fire downward and it boils away the water, hero should fall into the
resulting pit.
The PR commit didn't handle monsters (who don't zap wands downward
but could be on/in water that's boiled out from under them). And
while testing it I noticed that the existing code had message
sequencing issues (being enveloped in a cloud of steam before seeing
the water evaporate). This ended up redoing the fix rather than
using the commit.
Fixes#1238
Give a resistance animation if you #invoke Sunsword while it's
wielded and direct its blinding ray at yourself. Flashing a camera
at a monster who is wielding it will also produce the animation.
Prevent glyph change messages while loading a level file.
Otherwise a monster hiding under an item triggered a vision recalc
before light sources were linked to their sources, leading into
strange errors looking like pointer corruption.
getlev -> hide_monst -> hideunder -> newsym -> show_glyph ->
pline_xy -> vision_recalc -> do_light_sources -> get_obj_location
Add in_getlev program state variable, analogous to in_mklev
When a monster mimicks another monster (traditionally Double Trouble
Wizard, since 3.6.x also pet that eats a mimic corpse), using farlook
or getpos+autodescribe revealed the monster's real identity. Hard to
believe that nobody ever noticed, but it was obvious when a pet dog
quick-mimicked a cat or vice versa.
Add an extra x_monnam() flag to ignore monst->m_ap_type==M_AP_MONSTER
plus monst->mappearance. Only the m_monnam() variation of x_monnam()
includes it (via EXACT_NAME); monnam() and the rest will now describe
an M_AP_MONSTER by its appearance rather than as its true self.
When a camera flash hit a mimic which was posing as something, the
feedback mentioned the mimic but didn't bring it out of hiding.
Change to make light pass over a mimic impersonating an object but
unhide one impersonating furniture. Ones impersonating some other
monster are woken up but wakeup doesn't force it back to mimic shape.
Trying to get the messages right brought on more code changes than
antipated. I changed one of the arguments to mhidden_description()
so had to change its callers; fortunately there aren't very many.
It was too early to call the windowport change_color() routine
while processing the config file. The windowport was not yet
fully operational.
Now the palette option processing will just place the rgb
value into the appropriate ga.altpalette[CLR_MAX] entry.
init_sound_disp_gamewindows(void) [allmain.c] calls
change_palette() [coloratt.c] and it will call the windowport
change_color() function for each ga.altpalette[] entry that
has been set.
Notes:
The rgb values stored in ga.altpalette[] have the NH_ALTPALETTE bit set
so that the rgb value of 0 can be stored and be distinguishable from
a "not set" entry.
The NH_ALTPALETTE bit is cleared from the rgb value in change_palette()
prior to calling the windowport change_color() function.
The syntax for palette is colorname/r-g-b.
For example: palette:black/12-12-12
colorname must be one of the NH_BASIC_COLOR names or a suitable
alias for one of those 16 entries.
Some of the windowport CHANGE_COLOR functions had the wrong parameters,
perhaps due to bitrot. Those have been corrected to match the prototype.
For tty, make hitpointbar blink if current HP falls to the critical
HP threshold. Doesn't require status highlighting. Not changed:
when status highlighting is active, use the HP color but force the
attribute to be inverse (plus blink if the criterium is met) rather
than whatever the HP highlight specifies.
For curses, do the same thing. It used to honor HP attribute for
hitpointbar, now it behaves the same as tty: always inverse, maybe
combined with blink. The new code assumes that inverse and color
can be turned off without turning off active blink in the process.
I had intended to make hitpointbar be a full-fledged status field
(which happens to be rendered on top of title) so that it could be
highlighted differently from hit points (mainly so that one could
highlight up and down changes while the other showed percentages).
This is less versatile than that but much simpler.
I enabled 'extmenu' and went through all the extended commands under
curses and try to find out what github issue #1229 refers to and
didn't spot anything out of the ordinary, except for #wizmondiff
which reported that the calculated diffculty ratings for ice devil
and barbed devil didn't match the values in their definitions. They
were each given an extra ability about 6 months ago and it was enough
to have a higher rating.
Issue #1239 remains open.
The curses colorpair rework I did changed the pile hilite background
color from blue to red. Change it back to blue, and use a function
to get the color pair instead of hardcoding the value.
A couple of predicates in sym.h didn't cover all the relevant map
symbols.
is_cmap_stairs() only affects the MS-DOS position-bar. It appears
that it would have been overlooking the extra stairs to the mines
and to sokoban but I have no way to verify that.
is_cmap_lava() affects getpos() and #lookaround. lava-wall wasn't
being treated as lava.
In 3.6.2 parts of the wakeup code were merged together, and this
caused pets consider any noise made by the hero - such as hitting
iron bars or digging - as whistling for them to come to the hero.
Change it to only consider actual whistling and ringing a bell.
Use vi (cursor_invisible) and ve (cursor_normal) to hide and show
cursor, if the terminal supports those. This way on a slower
connection the cursor doesn't jump all over the place when doing
map or menu updates.