]> granicus.if.org Git - nethack/commitdiff
fix github issue #589 - gremlin crash
authorPatR <rankin@nethack.org>
Sat, 11 Sep 2021 10:04:04 +0000 (03:04 -0700)
committerPatR <rankin@nethack.org>
Sat, 11 Sep 2021 10:04:04 +0000 (03:04 -0700)
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

doc/fixes37.0
src/monmove.c

index a4eef3c3831269d0d272b713e7605bd2b285bc74..bb8844097063e1292d29e498d4f37c01bb2a542a 100644 (file)
@@ -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
index bbf77127601e74184fcf9c00fe9cd9c6f5df7561..1e944953e5be971d105be6f9274780865c5fe8cc 100644 (file)
@@ -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;
     }