Engulfing pets were getting a double chance to get an intrinsic from a
digestion attack, because they got the mon_givit call in mhitm_ad_dgst
and then also the one in mdamagem.
There is a bit of inconsistency here, in that mhitm_ad_dgst requires
corpse creation to grant nutrition, but the non-nutrition effects of
eating a corpse like polymorph, extra health, etc, in mdamagem don't
have any such requirement. As a result, one of the mon_givit calls
required a corpse to be "created" before granting an intrinsic, and the
other didn't. In choosing which one to remove, I figured intrinsic
granting is probably closer to those special effects than providing
nutrition (and also putting it in mhitm_ad_dgst is not ideal w/r/t
message ordering: it causes the 'intrinsic granted' message to appear
before the monster kill message).
Change trappers and lurkers above to remove digestion damage. They
fold themselves around rather than swallow the victim. There were
are lot of places that assumed that an engulfer which is an animal
would swallow and digest the victim. In hindsight, it might have
been simpler to take the M1_ANIMAL flag off of trappers and lurkers
above.
This adds a new digests() predicate for creatures with AT_ENGL+AD_DGST
(purple worm) and also enfolds() for AT_ENGL+AD_WRAP (both 't'-class
critters).
There are several minor fixes mixed in with this. I didn't record
them as I went along but the two I remember are
1) if poly'd into a holder and holding on to a monster, the '<' and
'>' commands refursed to work; release the held creature first
and then treat those commands as normal;
2) throwing a non-weapon while engulfed by an ochre jelly reported
"the <item> vanishes into the ochre jelly's /currents/".
This needs a lot more testing. I found and fixed multiple minor
details before my own testing burned out.
The only effect of a new moon was to make hearing a cockatrice's
hissing (whichs happens with 1 in 3 chance) always start the turn to
stone sequence instead just having a 1 in 10 chance to do so, but
that was negated by carrying a lizard corpse.
Keep the hiss-always-starts-petficiation part and remove the
carrying-a-lizard-corpse-negates-that part. So the effect of a new
moon no longer gets controlled by the contents of hero's inventory.
hero is invisible without being able to see invisible
Issue reported by EndHack: you could see your hands glow red when
reading a scroll of confuse monster or casting the spell of confuse
monster even if you were unable to see yourself.
Switch to the blind feedback (tingling instead of glowing red) if
invisible without see invisible.
Also, have uncursed scroll or low skilled spell confer 1..2 turns
of glowing hands instead of always just 1. (Blessed/highly skilled
stays at 2..9 turns.)
Fixes#828
When a monster at least two sizes larger hits another one,
there's a chance the smaller defender will be knocked back.
This applies also to hero, attacking when polymorphed to
a large monster, or defending from a large monster.
Most of the monsters that can knock back are giants and dragons.
Idea and some of the code from EvilHack.
When naming the weapon in the livelog message for breaking "never
hit with wielded weapon" conduct, avoid xname() because it includes
"<item> named <something or other>". That's partly censorship and
partly keeping the message from being longer than necessary. Long
messages on tty cause '#chronicle' output to become ugly.
...because I think it would be interesting to see how many monks break
it with a pick-axe.
Also fix a bug related to logging the conduct:
* If the first hit was a joust that didn't kill the monster, the
conduct would be double-logged.
I lifted the call to first_weapon_hit() out of mhurtle_to_doom() in
order to log the weapon before it broke.
Add possible pet intrinsic gain from swallowing a monster in one gulp
(in situations where a corpse is created and eaten by the engulfer),
making it equivalent in this regard to eating the corpse off the floor.
One possible extension or modification would be to reduce the chance of
receiving an intrinsic when the corpse is consumed via digestion attack,
similar to how the corpse nutrition is 50% of its normal value. I
didn't incorporate that into this commit since the chance of receiving
an intrinsic is tied to monster level rather than nutrition, so I wasn't
sure if it made sense.
Switch to using a macro invocation Verbos(n, s) in place of the
flags.verbose checks.
Provide the mechanics for individual suppression of any of the
existing messages that were considered verbose.
Mechanics only - this code update does not provide any means of
setting the suppression bits.
iflags.verbose = 0
is still a master suppression of all the verbose messages.
iflags.verbose = 1
turns on the verbose messages only for those whose suppression
bit is 0 (not set).
Issue #745 by k2: when using two-weapon combat, the second attack
would still take place even if the first attack caused the hero to
become paralyzed (hitting a floating eye or g.cube).
Cleaver's up-to-three attacks had the same problem but did stop if
the hero underwent life-saving after some fatally damaging counter-
attack. Two-weapons didn't. Make them both stop early if either
paralysis or life-save occurs.
Multiple attacking monster against monster and against poly'd hero
already deal with paralysis; life-saving doesn't apply.
Fixes#745
The "hit with a wielded weapon for the first time" livelog line could be
produced repeatedly: it was triggered by hitting a monster with a
wielded object of any sort, but the u.uconduct.weaphit counter was only
incremented if hitting with an actual 'weapon' (a WEAPON_CLASS or
is_weptool item). As a result, if a non-weapon-using hero whipped out a
non-weapon item -- a cockatrice corpse, for example -- and started going
to town on some monsters, the livelog message would be repeated with
every hit.
Log artifacts found on the floor, or carried by monsters if hero sees
those monsters do something with them. Shown to player via #chronicle
and included in dumplog.
For most cases, finding is based on having the artifact object be
formatted for display. So walking across one won't notice it if pile
size inhibits showing items at its location, even if the artifact is
on top. Taking stuff out of a container won't notice an artifact if a
subset of the contents chosen by class or BUCX filter doesn't include
it unless player has used ':' to look inside. Seeing an artifact be
picked up by a monster (even if the monster itself is unseen) or being
dropped (possibly upon death) will find an artifact even if beyond the
normal range of having it be treated as seen up close. Random treasure
drop items are excluded since they are placed directly on the floor
rather than going into a dying monster's inventory and then dropped
with its other stuff.
If the first monster the hero kills is killed by the hero's first hit
with a wielded weapon, report the hit first and kill second instead of
the other way around. Not as hard to manage as I feared, but bound to
be more fragile than the simpler handling that produced the odd order.
Also while testing it I knocked something into a polymorph trap and it
changed form without any feedback. Give foo-changes-into-bar message
if the hero is moving and can see it happening. It isn't needed with
a monster moves deliberately into a polymorph trap but probably would
be useful when that's is unintentional.
The "<hero> enters the dungeon" log message had a trailing period but
other log messages don't have sentence punctuation, so take that off.
Log game events, such as entering a new dungeon level, breaking
a conduct, or killing a unique monster, in a new "Major events"
chronicle. The entries record the turn when the event happened.
The log can be viewed with #chronicle -command, and the entries
also show up in the end-of-game dump, if that is available.
This feature is on by default, but can be disabled by
defining NO_CHRONICLE compile-time option.
This also contains "live logging", writing the events as they
happen into a single livelog-file. This is mostly useful for
public servers. The livelog is off by default, and must be
compiled in with LIVELOG, and then turned on in sysconf.
Mostly this a version of livelogging from the Hardfought server,
with some changes.
Implement the suggestion that falling rock traps and rolling boulder
traps be harmless to xorns. I've extended that to all missiles made
of stone (rocks, gems, boulders, a handful of other things that will
only matter if poly'd hero throws in '<' direction or is hit by stuff
scattered by an explosion).
I excluded ghosts because they would become even harder to kill and
the missile handling would need extra checks to test for blessed objs.
Throwing silver or blessed non-weapons upward and having them fall
back onto susceptible hero's head wasn't adding the extra bonus damage
that a weapon would get in that situation.
Make hitting vulnerable monsters with blessed just-about-anything get
the 1d4 bonus that blessed weapons get for that. Doesn't apply to
things that have their own special handing, like potions or eggs.
When hitting with a wielded wet towel, use "you lash <mon>" like
bullwhip. If you continue with the towel after it has dried out,
message reverts to ordinary "you hit <mon>".
Enhance damage slightly and double the wetness bonus when target
is an iron golem. Damage was (tmp=rnd(1..7), max(tmp,6)); now it's
rnd(1 + 1..7) for other monsters, rnd(1 + 2*(1..7)) for iron golem,
with no cap of 6 for either.
Sequencing: defer "your towel dries" until after the lash message.
djgpp cross-compiler was griping about several.
This also removes these lines from sys/unix/hints/include/compiler.370.
CFLAGS+=-Wno-format-nonliteral
CCXXFLAGS+=-Wno-format-nonliteral
-Wformat-nonliteral should not be incompatible with the printf
argument-checking capabilities on literal format strings and there
shouldn't be any new warnings created.
-- &< --
artifact.c: In function 'artifact_hit':
artifact.c:1309:23: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1309 | mon_nam(mdef));
| ^~~~~~~
artifact.c:1328:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1328 | pline(behead_msg[rn2(SIZE(behead_msg))], wepdesc, "you");
| ^~~~~
ball.c: In function 'drop_ball':
ball.c:896:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
896 | pline(pullmsg, "pit");
| ^~~~~
ball.c:899:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
899 | pline(pullmsg, "web");
| ^~~~~
ball.c:904:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
904 | pline(pullmsg, hliquid("lava"));
| ^~~~~
ball.c:908:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
908 | pline(pullmsg, "bear trap");
| ^~~~~
dig.c: In function 'liquid_flow':
dig.c:747:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
747 | pline(fillmsg, hliquid(typ == LAVAPOOL ? "lava" : "water"));
| ^~~~~
fountain.c: In function 'floating_above':
fountain.c:28:5: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
28 | You(umsg, what);
| ^~~
invent.c: In function 'hold_another_object':
invent.c:1018:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1018 | pline(drop_fmt, drop_arg);
| ^~~~~
invent.c:1073:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1073 | pline(drop_fmt, drop_arg);
| ^~~~~
invent.c: In function 'silly_thing':
invent.c:1811:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1811 | pline(silly_thing_to, word);
| ^~~~~
lock.c: In function 'pick_lock':
lock.c:375:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
375 | pline(no_longer, "hold the", what);
| ^~~~~~~~~
lock.c:379:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
379 | pline(no_longer, "reach the", "lock");
| ^~~~~~~~~
lock.c: In function 'pick_lock':
lock.c:375:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
375 | pline(no_longer, "hold the", what);
| ^~~~~~~~~
lock.c:379:19: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
379 | pline(no_longer, "reach the", "lock");
| ^~~~~~~~~
mcastu.c: In function 'cast_cleric_spell':
mcastu.c:670:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
670 | pline(fmt, Monnam(mtmp), what);
| ^~~~~
mhitu.c: In function 'hitmsg':
mhitu.c:68:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
68 | pline(pfmt, Monst_name);
| ^~~~~
mkobj.c: In function 'insane_object':
mkobj.c:2848:20: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2848 | impossible(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
| ^~~~~~
mkobj.c:2852:20: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2852 | objnm);
| ^~~~~
mon.c: In function 'mon_givit':
mon.c:1469:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1469 | pline(msg, Monnam(mtmp));
| ^~~~~
mon.c: In function 'mondead':
mon.c:2485:33: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2485 | | SUPPRESS_INVISIBLE), FALSE));
| ^
muse.c: In function 'mon_reflects':
muse.c:2438:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2438 | pline(str, s_suffix(mon_nam(mon)), "shield");
| ^~~~~
muse.c:2445:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2445 | pline(str, s_suffix(mon_nam(mon)), "weapon");
| ^~~~~
muse.c:2450:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2450 | pline(str, s_suffix(mon_nam(mon)), "amulet");
| ^~~~~
muse.c:2458:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2458 | pline(str, s_suffix(mon_nam(mon)), "armor");
| ^~~~~
muse.c:2464:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2464 | pline(str, s_suffix(mon_nam(mon)), "scales");
| ^~~~~
muse.c: In function 'ureflects':
muse.c:2476:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2476 | pline(fmt, str, "shield");
| ^~~~~
muse.c:2483:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2483 | pline(fmt, str, "weapon");
| ^~~~~
muse.c:2487:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2487 | pline(fmt, str, "medallion");
| ^~~~~
muse.c:2493:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2493 | pline(fmt, str, uskin ? "luster" : "armor");
| ^~~~~
muse.c:2497:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2497 | pline(fmt, str, "scales");
| ^~~~~
polyself.c: In function 'polyman':
polyself.c:201:5: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
201 | urgent_pline(fmt, arg);
| ^~~~~~~~~~~~
potion.c: In function 'make_hallucinated':
potion.c:423:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
423 | pline(message, verb);
| ^~~~~
potion.c: In function 'peffect_gain_level':
potion.c:1033:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1033 | You(riseup, ceiling(u.ux, u.uy));
| ^~~
potion.c:1044:21: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1044 | You(riseup, ceiling(u.ux, u.uy));
| ^~~
priest.c: In function 'intemple':
priest.c:487:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
487 | You(msg1, msg2);
| ^~~
read.c: In function 'doread':
read.c:522:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
522 | pline(silly_thing_to, "read");
| ^~~~~
shk.c: In function 'shk_names_obj':
shk.c:2576:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2576 | pline(fmtbuf, obj_name, (obj->quan > 1L) ? "them" : "it", amt,
| ^~~~~~
shk.c:2579:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2579 | You(fmt, obj_name, amt, plur(amt), arg);
| ^~~
shk.c: In function 'shk_chat':
shk.c:4506:13: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
4506 | pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))], shkname(shkp));
| ^~~~~
shk.c: In function 'check_unpaid_usage':
shk.c:4633:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
4633 | verbalize(fmt, arg1, arg2, tmp, currency(tmp));
| ^~~~~~~~~
sounds.c: In function 'dosounds':
sounds.c:66:21: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
66 | pline(throne_msg[2], uhis());
| ^~~~~
sounds.c:259:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
259 | You_hear(msg, halu_gname(EPRI(mtmp)->shralign));
| ^~~~~~~~
timeout.c: In function 'choke_dialogue':
timeout.c:269:26: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
269 | body_part(NECK));
| ^~~~~~~~~
timeout.c:274:17: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
274 | urgent_pline(str, hcolor(NH_BLUE));
| ^~~~~~~~~~~~
timeout.c: In function 'levitation_dialogue':
timeout.c:339:26: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
339 | danger ? surface(u.ux, u.uy) : "air");
| ^~~~~~
timeout.c: In function 'slime_dialogue':
timeout.c:379:34: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
379 | urgent_pline(buf, hcolor(NH_GREEN));
| ^~~
timeout.c:381:30: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
381 | urgent_pline(buf, an(Hallucination ? rndmonnam(NULL)
| ^~~
uhitm.c: In function 'hmon_hitmon':
uhitm.c:1398:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1398 | pline(fmt, whom);
| ^~~~~
uhitm.c:1421:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1421 | pline(fmt, whom);
| ^~~~~
uhitm.c: In function 'stumble_onto_mimic':
uhitm.c:5301:9: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
5301 | pline(fmt, what);
| ^~~~~
../win/tty/wintty.c: In function 'tty_clear_nhwindow':
../win/tty/wintty.c:1649:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
1649 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_display_nhwindow':
../win/tty/wintty.c:2339:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2339 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_dismiss_nhwindow':
../win/tty/wintty.c:2432:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2432 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_destroy_nhwindow':
../win/tty/wintty.c:2477:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2477 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_curs':
../win/tty/wintty.c:2503:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2503 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_putsym':
../win/tty/wintty.c:2599:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2599 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_add_menu':
../win/tty/wintty.c:2967:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
2967 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_end_menu':
../win/tty/wintty.c:3032:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
3032 | panic(winpanicstr, window);
| ^~~~~~~~~~~
../win/tty/wintty.c: In function 'tty_select_menu':
../win/tty/wintty.c:3140:15: warning: format not a string literal, argument types not checked [-Wformat-nonliteral]
3140 | panic(winpanicstr, window);
| ^~~~~~~~~~~
Get rid of set-but-not-otherwise-used variable 'nsum'. At one time
it was used to figure out hmonas()'s return value, but that changed
three years ago. And hmonas()'s only caller discards that return
value anyway.
emcc: error: linker setting ignored during compilation: 'ASSERTIONS' [-Wunused-command-line-argument] [-Werror]
make[1]: *** [Makefile:1306: ../targets/wasm/allmain.o] Error 1
wasm-ld: error: ../targets/wasm/version.o: undefined symbol: nomakedefs
These ones look like actual NetHack issues that this particular compile is catching due to
default -Wunused-but-set-variable.
In the interest of time today, I mostly resorted to using nhUse() on them for now, but a
follow-up by someone might be useful.
options.c:6069:13: error: variable 'ret' set but not used [-Werror,-Wunused-but-set-variable]
boolean ret = FALSE;
^
restore.c:903:9: error: variable 'len' set but not used [-Werror,-Wunused-but-set-variable]
int len = 0;
^
uhitm.c:4539:43: error: variable 'nsum' set but not used [-Werror,-Wunused-but-set-variable]
int i, tmp, armorpenalty, sum[NATTK], nsum = MM_MISS,
^
Special abilities conferred by wearing dragon armor was implemented in
a somewhat half-assed fashion; extend it to 3/4-assed. Abilities came
from wearing dragon armor but not from being poly'd into a dragon or
for monsters that were wearing dragon armor or actually were dragons.
This covers much of that.
There are umpteen calls of 'resists_foo(mon)' and some are now
'resists_foo(mon) || defended(mon, AD_FOO)' but the second part ought
to be incorporated into update_mon_intrinics() so that the extra
'|| defended()' doesn't have to be spread all over the place and the
ones being put in now could/should be removed.
While testing, I noticed that a monster wielding Fire Brand did not
resist being hit by a wand of fire. This fixes that and should also
fix various comparable situations for other artifacts. But so far it
has only been done for zapping (and any other actions which use the
zapping code). Folding defended() checks into update_mon_intrinsics()
matters more than that probably sounds.
When testing the urgent message for having weapon be snagged by a
bullwhip, in between the occasional weapon grabs (which mention
flicking the bullwhip) I saw lots of regular attacks that said
"<mon> swings his bullwhip." That is accurate but seems odd, so
change it to "<mon> lashes his bullwhip." Do same for the hero.
While working on that, I discovered that monsters using a polearm
for a ranged attack always showed "<mon> thrusts <a polearm>" even
for ones that aren't defined as piercing so should be swung rather
that thrust. And they're allowed to do that when adjacent where
there isn't enough room to thrust or swing a long polearm. Now it's
"<mon> bashes with <a polearm>" in that situation.
Now I've remembered why I didn't follow through with these back when
I originally laid the groundwork. New urgent messages:
having an item of armor be destroyed
having weapon be grabbed by a monster's bullwhip
becoming engulfed
being grabbed by an eel
subsequently being drowned by an eel
dying of petrification
turning into slime then dying due to genocide
dying due to fatal illness
There are lots more candidates.
If you have a function named like that, and it goes and
changes the monster state, that's just wrong.
Move waking up the monster from the hit into separate function.
Teleporting a monster only updated the map. Give a message
so blind players can get the same information.
Making a monster invisible gives the same message, if you
cannot detect invisible.
Several other places where monsters teleported themselves
now also give the same message.
Keep track of the highest value that u.uhpmax and u.uenmax have
attained, in new u.uhppeak and u.uenpeak. They aren't used for
anything yet. u.mhmax (max HP while polymorphed) isn't interesting
enough to track.
Not save and bones compatible so increments EDITLEVEL.
Reported by entrez: applying a bullwhip towards a medium or small
peaceful monster used to be an attack but that stopped working when
'safepet' was extended to peacefuls in order for the hero to be able
to swap places which those. Also, side-effects were different when
hero applied the whip from within a pit compared to when not in one.
This allows the hero trapped in a pit to try to snag furniture or a
boulder even when a small or medium is present, and escaping that
pit if successful. (It still snags big monsters in preference to
furniture/boulder at their location.) When no such non-monster
target is available, it attacks the monster if hostile or peaceful
but not when tame. When revealing a previously unseen monster it
prevents snagging that monster's wielded weapon because hero couldn't
possibly target the weapon in that situation.
This makes other changes, mostly dealing with finding and exposing
concealed monsters, which may introduce some new bugs.
Since I was already in the right place, implement snagging an item
off the floor while flying. It isn't necessary since a flyer can
pick things up off the floor directly, but there isn't any pressing
reason to disallow it. Supersedes the commit in pull request #632
by RojjaCebolla.
Closes#632
by the Riders that only damage the hero, not other monsters.
Noticed and diagnosed by vultur-cadens. Attacks dishing out the
damage type AD_DETH (Death), AD_FAMN (Famine), AD_PEST (Pestilence),
and also AD_DISE (Demogorgon, Juiblex, Scorpius) did 0 damage if
inflicted against monsters. That made Death harmless to other
monsters. The others have additional attacks (in the two Rider's
cases, only if both instances of their special attack hit on the
same move so that the second one is converted into a stun attack)
and could manage to kill other monsters.
The uhitm case can't happen. I suspect that the mhitm case was
originally intentionally omitted as something which won't happen,
but that's just a guess.
Fixes#594
From 8 or so years ago, hitting a disenchanter without wielding a
weapon and without wearing gloves while wearing a possitively
'charged' ring should reduce the ring's enchantment. This doesn't
fix that, it just adds a brief comment about it.
Attacking a monster which has a passive attack (e.g. a red mold) with a
wielded potion that breaks during the attack, the variable weapon would
not be correctly reset and passive() would be called with the pointer to the
freed object.