Picked arbitrarily; there weren't any unresolved analyzer complaints
for trap.c. I wonder why the onefile analysis isn't complaining here.
'in_sight' may have been relevant before the trapeffect_xyz() code
was split apart, but it isn't useful for trapeffect_hole() despite
the comment about it.
release_holding_trap() is fairly convoluted and the complaints being
addressed here were relevant.
This cleans up analyzer feedback in shk.c, based on the set of
warnings specified by hints/MacOS.370 and the lower level hints it
applies, rather than anything specified during periodic 'onefile'
processing.
shk.c is the only file I've analyzed, to try again to figure out
how to suppress the old complaint that has been causing a special
case in Genonefile. It isn't triggering during my testing but that
might be due to something in use by onefile but not by normal hints.
I'm running ccc-analyzer from llvm-16; I don't know whether that
matches Genonefile.
Casting charm monster with pets nearby could reset the edog struct.
If the pet ate a mimic corpse and was pretending to be something else
when that edog reset happened, the sanity checking would issue an impossible.
The error happened because meating was reset, but the pet appearance was not,
but the edog struct reset is the part being wrong. Lets not do that.
To reproduce, turn on sanity checking, create a tame dog, give it a mimic corpse
to eat, #wizcast charm monster next to it.
Reported by paxed. A potion of oil, that was already in the midst of exploding,
got picked up through spot_effects(), which led to it merging with
another potion of oil and the freeing of the original obj.
The original obj pointer was still held by breakobj(), and breakobj()
proceeded to delete the obj (again).
Function nesting:
1 spelleffects()
2 -> weffects()
3 -> bhit()
4 -> bhitpile()
5 -> bhito(obj ...)
6 -> hero_breaks(obj ...)
7 -> breakobj(obj ...)
8 -> explode_oil(obj ...)
9 -> splatter_burning_oil()
10 -> explode()
11 -> zap_over_floor()
12 -> melt_ice()
13 -> spot_effects()
14 -> pickup()
15 -> pickup_object(obj ...)
16 -> pick_obj(obj ...)
17 -> addinv(obj ...)
18 -> addinv_core0(obj ...)
19 -> merged(obj ...)
20 -> obfree(obj ...)
21 -> dealloc_obj(obj ...)
8 -> delobj(obj ...)
9 -> delobj_core(obj ...)
10 -> obfree(obj ...)
11 -> dealloc_obj(obj ...)
12 -> impossible("obj already deleted)
This marks the exploding potion with LOST_EXPLODING, so that it won't
get picked up, or merged with another object during the long
sequence of functions, and that should take care of 15-21 above.
Previously, the code for monster healing was repeated every time it
was needed; this commit sends it all through a common function, which
will make it easier to make changes to how monster healing works in
the future.
This is just a code reorganisation and won't have any gameplay
effect unless I made a mistake.
The new EXTRA_SANITY_CHECK for a monster mimicking a monster. It
falsely triggered if the hero was hallucinating. Just add an
assertion that the monster index is within valid range.
The report (sent directly to devteam) stated that the bump-into-mimic
code might crash when bumping into a mimic that is masqueraing as
some other monster. Mimics don't actually do that, but the Wizard
of Yendor mimics another monster via Double Trouble. All I got from
it though is
|Wait! That's <other monster>!
which won't crash but is a fairly useless message.
This changes it to be
|Wait! That <other monster> is <the Wizard of Yendor>!
which seems a bit bland but provides useful information.
Use ESHK(shkp)->bill_p consistently. The bill[] array field is used
to initialize the bill_p pointer field rather than be used directly
when manipulating shop bills.
While in there, get rid of some '#if DUMB' from pre-standard C days.
I couldn't reproduce the reported problem but the backtrace suggests
that defsyms[monst->mappearance] was probably out of bounds so that
nh_snprintf() got bad data. That might conceivably happen if the
glyph didn't match the mimic's mappearance, but I not sure how that
would occur.
This avoids using mappearance as an index into defsyms[] and should
give an impossible if that situation does come up.
This time the no_charge object was being carried by a pet.
To trigger, drop an object into shop, decline to sell it,
pick up an object belonging to shopkeeper, decline to buy it,
wait for your pet to pick up the no_charge object you dropped,
teleport out of the shop, wait for shopkeeper to walk out of
the shop.
- Add a vision sanity checking routine
- Recalc block point when digging a door for temporary clouds
- Add recalc_block_point after cvt_sdoor_to_door, because doorways
on the Rogue level have no doors, and otherwise the sanity checking
would complain. This doesn't actually change how the Rogue level
vision works, as it uses a different vision system
- Monster using a trap in a secret corridor revealed the corridor,
but didn't unblock the vision unless you saw the location
Sanity checking was complaining about a no_charge obj in untended shop.
Angry shopkeeper was accepting thrown items as no_charge objects:
To reproduce the impossible, kick down the shop door angering
the shopkeeper. While the shopkeeper is still in their shop,
throw an item they don't want into the shop. Wait for the shopkeeper
to get out of the shop.
Move the anger checking before the sell auto-accept code,
so the shopkeeper will charge for the object.