From: PatR Date: Sat, 11 Sep 2021 10:04:04 +0000 (-0700) Subject: fix github issue #589 - gremlin crash X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d118ac52af45519cf756d84d79c3dc07aaf00f91;p=nethack fix github issue #589 - gremlin crash when fleeing hero who was wearing gold dragon scales/mail and not wielding any weapon. When a gremlin was made to flee "artifact light", code originally intended for Sunsword attempted to format 'uwep' as an artifact. For gold scales/mail instead of that, it gave a sane but inappropriate value if wielding something or segfaulted if not wielding anything. Fixes #589 --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index a4eef3c38..bb8844097 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -802,6 +802,7 @@ if an invisible monster put on or took off armor while out of hero's sight spurious message "Suddenly you cannot see it" would be given an item thrown or dropped while swallowed was treated as being picked up by an unseen monster so object fields {known, dknown, bknown} got cleared +segfault if gremlin fled weaponless hero wearing gold dragon scales/mail curses: 'msg_window' option wasn't functional for curses unless the binary also included tty support diff --git a/src/monmove.c b/src/monmove.c index bbf771276..1e944953e 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -298,13 +298,15 @@ bee_eat_jelly(struct monst* mon, struct obj* obj) return -1; /* a queen is already present; ordinary bee hasn't moved yet */ } +/* FIXME: gremlins don't flee from monsters wielding Sunsword or wearing + gold dragon scales/mail, nor from gold dragons, only from the hero */ #define flees_light(mon) \ - ((mon)->data == &mons[PM_GREMLIN] \ - && ((uwep && uwep->lamplit && artifact_light(uwep)) \ - || (uarm && uarm->lamplit && artifact_light(uarm)))) -/* we could include this in the above macro, but probably overkill/overhead */ -/* && (!(which_armor((mon), W_ARMC) != 0 */ -/* && which_armor((mon), W_ARMH) != 0)) */ + ((mon)->data == &mons[PM_GREMLIN] \ + && ((uwep && uwep->lamplit && artifact_light(uwep)) \ + || (uarm && uarm->lamplit && artifact_light(uarm))) \ + /* not applicable if mon can't see or hero isn't in line of sight */ \ + && mon->mcansee && couldsee(mon->mx, mon->my)) \ + /* doesn't matter if hero is invisible--light being emitted isn't */ /* monster begins fleeing for the specified time, 0 means untimed flee * if first, only adds fleetime if monster isn't already fleeing @@ -343,13 +345,28 @@ monflee( if (!mtmp->mcanmove || !mtmp->data->mmove) { pline("%s seems to flinch.", Adjmonnam(mtmp, "immobile")); } else if (flees_light(mtmp)) { - if (rn2(10) || Deaf) + if (Unaware) { + /* tell the player even if the hero is unconscious */ + pline("%s is frightened.", Monnam(mtmp)); + } else if (rn2(10) || Deaf) { + /* via flees_light(), will always be either via uwep + (Sunsword) or uarm (gold dragon scales/mail) or both; + TODO? check for both and describe the one which is + emitting light with a bigger radius */ + const char *lsrc = (uwep && artifact_light(uwep)) + ? bare_artifactname(uwep) + : (uarm && artifact_light(uarm)) + ? yname(uarm) + : "[its imagination?]"; + pline("%s flees from the painful light of %s.", - Monnam(mtmp), bare_artifactname(uwep)); - else + Monnam(mtmp), lsrc); + } else { verbalize("Bright light!"); - } else + } + } else { pline("%s turns to flee.", Monnam(mtmp)); + } } mtmp->mflee = 1; }