]> granicus.if.org Git - nethack/commitdiff
Monster list iterator
authorPasi Kallinen <paxed@alt.org>
Sun, 24 Apr 2022 10:03:43 +0000 (13:03 +0300)
committerPasi Kallinen <paxed@alt.org>
Sun, 24 Apr 2022 10:03:47 +0000 (13:03 +0300)
Add some basic functions to iterate through the monster list,
ignoring dead monsters. Mainly just to allow splitting up code
into discrete functions.

Not quite happy with the get_iter_mons_xy - should probably have
a pointer to iterator data struct, which gets passed through instead,
but this works for now.

include/extern.h
src/apply.c
src/bones.c
src/display.c
src/do.c
src/dokick.c
src/fountain.c
src/mon.c
src/sounds.c
src/teleport.c

index 337d41e61eaaee8235d2fb29eb5e2eee62f606da..534f2a3ed335b7720992e581d481e29e0568a2c5 100644 (file)
@@ -1537,7 +1537,10 @@ extern void wakeup(struct monst *, boolean);
 extern void wake_nearby(void);
 extern void wake_nearto(int, int, int);
 extern void seemimic(struct monst *);
-extern void normal_shape(struct monst *mon);
+extern void normal_shape(struct monst *);
+extern void iter_mons(void (*)(struct monst *));
+extern struct monst *get_iter_mons(boolean (*)(struct monst *));
+extern struct monst *get_iter_mons_xy(boolean (*)(struct monst *, xchar, xchar), xchar, xchar);
 extern void rescham(void);
 extern void restartcham(void);
 extern void restore_cham(struct monst *);
index 2d025381e6b3f5a5f5adb6c7b043a32ea2eae4d6..e52c101337eed05ac9b3ea7990664133085b11ef 100644 (file)
@@ -12,6 +12,7 @@ static int use_stethoscope(struct obj *);
 static void use_whistle(struct obj *);
 static void use_magic_whistle(struct obj *);
 static int use_leash(struct obj *);
+static boolean mleashed_next2u(struct monst *);
 static int use_mirror(struct obj *);
 static void use_bell(struct obj **);
 static void use_candelabrum(struct obj *);
@@ -718,33 +719,38 @@ get_mleash(struct monst *mtmp)
     return otmp;
 }
 
-boolean
-next_to_u(void)
+static boolean
+mleashed_next2u(struct monst *mtmp)
 {
-    register struct monst *mtmp;
-    register struct obj *otmp;
-
-    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-        if (DEADMONSTER(mtmp))
-            continue;
-        if (mtmp->mleashed) {
-            if (!next2u(mtmp->mx, mtmp->my))
-                mnexto(mtmp, RLOC_NOMSG);
-            if (!next2u(mtmp->mx, mtmp->my)) {
-                for (otmp = g.invent; otmp; otmp = otmp->nobj)
-                    if (otmp->otyp == LEASH
-                        && (unsigned) otmp->leashmon == mtmp->m_id) {
-                        if (otmp->cursed)
-                            return FALSE;
-                        mtmp->mleashed = 0;
-                        otmp->leashmon = 0;
-                        update_inventory();
-                        You_feel("%s leash go slack.",
-                                 (number_leashed() > 1) ? "a" : "the");
-                    }
+    if (mtmp->mleashed) {
+        if (!next2u(mtmp->mx, mtmp->my))
+            mnexto(mtmp, RLOC_NOMSG);
+        if (!next2u(mtmp->mx, mtmp->my)) {
+            struct obj *otmp = get_mleash(mtmp);
+
+            if (!otmp) {
+                impossible("leashed-unleashed mon?");
+                return TRUE;
             }
+
+            if (otmp->cursed)
+                return TRUE;
+            mtmp->mleashed = 0;
+            otmp->leashmon = 0;
+            update_inventory();
+            You_feel("%s leash go slack.",
+                     (number_leashed() > 1) ? "a" : "the");
         }
     }
+    return FALSE;
+}
+
+boolean
+next_to_u(void)
+{
+    if (get_iter_mons(mleashed_next2u))
+        return FALSE;
+
     /* no pack mules for the Amulet */
     if (u.usteed && mon_has_amulet(u.usteed))
         return FALSE;
index 5d11ffd15e92dee3c4433a0653cda91c8e4c93f0..b56be0303a62940d709b68708348ff0d1e6d4533 100644 (file)
@@ -10,6 +10,7 @@ static void goodfruit(int);
 static void resetobjs(struct obj *, boolean);
 static void give_to_nearby_mon(struct obj *, int, int);
 static boolean fixuporacle(struct monst *);
+static void remove_mon_from_bones(struct monst *);
 
 static boolean
 no_bones_level(d_level *lev)
@@ -377,6 +378,20 @@ can_make_bones(void)
     return TRUE;
 }
 
+/* monster removed before saving a bones file,
+   in case these characters are not in their home bases */
+static void
+remove_mon_from_bones(struct monst *mtmp)
+{
+    struct permonst *mptr = mtmp->data;
+
+    if (mtmp->iswiz || mptr == &mons[PM_MEDUSA]
+        || mptr->msound == MS_NEMESIS || mptr->msound == MS_LEADER
+        || mptr == &mons[PM_VLAD_THE_IMPALER]
+        || (mptr == &mons[PM_ORACLE] && !fixuporacle(mtmp)))
+        mongone(mtmp);
+}
+
 /* save bones and possessions of a deceased adventurer */
 void
 savebones(int how, time_t when, struct obj *corpse)
@@ -384,7 +399,6 @@ savebones(int how, time_t when, struct obj *corpse)
     int x, y;
     struct trap *ttmp;
     struct monst *mtmp;
-    struct permonst *mptr;
     struct fruit *f;
     struct cemetery *newbones;
     char c, *bonesid;
@@ -413,17 +427,8 @@ savebones(int how, time_t when, struct obj *corpse)
 
  make_bones:
     unleash_all();
-    /* in case these characters are not in their home bases */
-    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-        if (DEADMONSTER(mtmp))
-            continue;
-        mptr = mtmp->data;
-        if (mtmp->iswiz || mptr == &mons[PM_MEDUSA]
-            || mptr->msound == MS_NEMESIS || mptr->msound == MS_LEADER
-            || mptr == &mons[PM_VLAD_THE_IMPALER]
-            || (mptr == &mons[PM_ORACLE] && !fixuporacle(mtmp)))
-            mongone(mtmp);
-    }
+    iter_mons(remove_mon_from_bones);
+
     if (u.usteed)
         dismount_steed(DISMOUNT_BONES);
     dmonsfree(); /* discard dead or gone monsters */
index d09b47fba3c75d8ea18dc2398645ec78ec51a11a..5463de710d35f5ab174ba2eab432406a0a1cb279 100644 (file)
@@ -131,6 +131,7 @@ static void display_warning(struct monst *);
 static int check_pos(int, int, int);
 static int get_bk_glyph(xchar x, xchar y);
 static int tether_glyph(int, int);
+static void mimic_light_blocking(struct monst *);
 #ifdef UNBUFFERED_GLYPHINFO
 static glyph_info *glyphinfo_at(xchar, xchar, int);
 #endif
@@ -1304,6 +1305,17 @@ see_monsters(void)
         newsym(u.ux, u.uy);
 }
 
+static void
+mimic_light_blocking(struct monst *mtmp)
+{
+    if (mtmp->minvis && is_lightblocker_mappear(mtmp)) {
+        if (See_invisible)
+            block_point(mtmp->mx, mtmp->my);
+        else
+            unblock_point(mtmp->mx, mtmp->my);
+    }
+}
+
 /*
  * Block/unblock light depending on what a mimic is mimicing and if it's
  * invisible or not.  Should be called only when the state of See_invisible
@@ -1312,18 +1324,7 @@ see_monsters(void)
 void
 set_mimic_blocking(void)
 {
-    register struct monst *mon;
-
-    for (mon = fmon; mon; mon = mon->nmon) {
-        if (DEADMONSTER(mon))
-            continue;
-        if (mon->minvis && is_lightblocker_mappear(mon)) {
-            if (See_invisible)
-                block_point(mon->mx, mon->my);
-            else
-                unblock_point(mon->mx, mon->my);
-        }
-    }
+    iter_mons(mimic_light_blocking);
 }
 
 /*
index 079b163d54175a522ff6aba6ce39173f16b3b9d1..d371dc26f5e53bbddf9d60d0d8a5bdf5a011b164 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -1839,14 +1839,8 @@ maybe_lvltport_feedback(void)
 static void
 final_level(void)
 {
-    struct monst *mtmp;
-
     /* reset monster hostility relative to player */
-    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-        if (DEADMONSTER(mtmp))
-            continue;
-        reset_hostility(mtmp);
-    }
+    iter_mons(reset_hostility);
 
     /* create some player-monsters */
     create_mplayers(rn1(4, 3), TRUE);
index c546b1bc1b8490df4479d7ed95bfdc2fe57d0742..32f3b2c5cf4816e79c02707a708ab03c75df7bab 100644 (file)
@@ -17,6 +17,8 @@ static void kick_monster(struct monst *, xchar, xchar);
 static int kick_object(xchar, xchar, char *);
 static int really_kick_object(xchar, xchar);
 static char *kickstr(char *, const char *);
+static boolean watchman_thief_arrest(struct monst *);
+static boolean watchman_door_damage(struct monst *, xchar, xchar);
 static void otransit_msg(struct obj *, boolean, boolean, long);
 static void drop_to(coord *, schar, xchar, xchar);
 
@@ -768,6 +770,36 @@ kickstr(char *buf, const char *kickobjnam)
     return strcat(strcpy(buf, "kicking "), what);
 }
 
+static boolean
+watchman_thief_arrest(struct monst *mtmp)
+{
+    if (is_watch(mtmp->data) && couldsee(mtmp->mx, mtmp->my)
+        && mtmp->mpeaceful) {
+        mon_yells(mtmp, "Halt, thief!  You're under arrest!");
+        (void) angry_guards(FALSE);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static boolean
+watchman_door_damage(struct monst *mtmp, xchar x, xchar y)
+{
+    if (is_watch(mtmp->data) && mtmp->mpeaceful
+        && couldsee(mtmp->mx, mtmp->my)) {
+        if (levl[x][y].looted & D_WARNED) {
+            mon_yells(mtmp,
+                      "Halt, vandal!  You're under arrest!");
+            (void) angry_guards(FALSE);
+        } else {
+            mon_yells(mtmp, "Hey, stop damaging that door!");
+            levl[x][y].looted |= D_WARNED;
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
 /* the #kick command */
 int
 dokick(void)
@@ -1291,16 +1323,7 @@ dokick(void)
             pay_for_damage("break", FALSE);
         }
         if (in_town(x, y))
-            for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-                if (DEADMONSTER(mtmp))
-                    continue;
-                if (is_watch(mtmp->data) && couldsee(mtmp->mx, mtmp->my)
-                    && mtmp->mpeaceful) {
-                    mon_yells(mtmp, "Halt, thief!  You're under arrest!");
-                    (void) angry_guards(FALSE);
-                    break;
-                }
-            }
+            (void) get_iter_mons(watchman_thief_arrest);
     } else {
         if (Blind)
             feel_location(x, y); /* we know we hit it */
@@ -1310,22 +1333,7 @@ dokick(void)
            hear; we've kept the extra 'm's and one of the extra '!'s */
         pline("%s!!", (Deaf || !rn2(3)) ? "Thwack" : "Whammm");
         if (in_town(x, y))
-            for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-                if (DEADMONSTER(mtmp))
-                    continue;
-                if (is_watch(mtmp->data) && mtmp->mpeaceful
-                    && couldsee(mtmp->mx, mtmp->my)) {
-                    if (levl[x][y].looted & D_WARNED) {
-                        mon_yells(mtmp,
-                                  "Halt, vandal!  You're under arrest!");
-                        (void) angry_guards(FALSE);
-                    } else {
-                        mon_yells(mtmp, "Hey, stop damaging that door!");
-                        levl[x][y].looted |= D_WARNED;
-                    }
-                    break;
-                }
-            }
+            (void) get_iter_mons_xy(watchman_door_damage, x, y);
     }
     return ECMD_TIME;
 }
index 7f315e972b95b0f630fda926e8092076a083b4dc..46a0b8eb1a017719b63854690ef49d50fbec0679 100644 (file)
@@ -11,6 +11,7 @@ static void dowaterdemon(void);
 static void dowaternymph(void);
 static void gush(int, int, genericptr_t);
 static void dofindgem(void);
+static boolean watchman_warn_fountain(struct monst *);
 
 DISABLE_WARNING_FORMAT_NONLITERAL
 
@@ -163,6 +164,28 @@ dofindgem(void)
     exercise(A_WIS, TRUE); /* a discovery! */
 }
 
+static boolean
+watchman_warn_fountain(struct monst *mtmp)
+{
+    if (is_watch(mtmp->data) && couldsee(mtmp->mx, mtmp->my)
+        && mtmp->mpeaceful) {
+        if (!Deaf) {
+            pline("%s yells:", Amonnam(mtmp));
+            verbalize("Hey, stop using that fountain!");
+        } else {
+            pline("%s earnestly %s %s %s!",
+                  Amonnam(mtmp),
+                  nolimbs(mtmp->data) ? "shakes" : "waves",
+                  mhis(mtmp),
+                  nolimbs(mtmp->data)
+                  ? mbodypart(mtmp, HEAD)
+                  : makeplural(mbodypart(mtmp, ARM)));
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
 void
 dryup(xchar x, xchar y, boolean isyou)
 {
@@ -173,26 +196,7 @@ dryup(xchar x, xchar y, boolean isyou)
 
             SET_FOUNTAIN_WARNED(x, y);
             /* Warn about future fountain use. */
-            for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-                if (DEADMONSTER(mtmp))
-                    continue;
-                if (is_watch(mtmp->data) && couldsee(mtmp->mx, mtmp->my)
-                    && mtmp->mpeaceful) {
-                    if (!Deaf) {
-                        pline("%s yells:", Amonnam(mtmp));
-                        verbalize("Hey, stop using that fountain!");
-                    } else {
-                        pline("%s earnestly %s %s %s!",
-                              Amonnam(mtmp),
-                              nolimbs(mtmp->data) ? "shakes" : "waves",
-                              mhis(mtmp),
-                              nolimbs(mtmp->data)
-                                      ? mbodypart(mtmp, HEAD)
-                                      : makeplural(mbodypart(mtmp, ARM)));
-                    }
-                    break;
-                }
-            }
+            mtmp = get_iter_mons(watchman_warn_fountain);
             /* You can see or hear this effect */
             if (!mtmp)
                 pline_The("flow reduces to a trickle.");
index 93ec686e0e49f4b323637956bdf634fa92d10ac8..c7ea09be52aea2a02a85cacf0d4a310a82524c62 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -10,6 +10,7 @@
 static void sanity_check_single_mon(struct monst *, boolean, const char *);
 static struct obj *make_corpse(struct monst *, unsigned);
 static int minliquid_core(struct monst *);
+static void m_calcdistress(struct monst *);
 static boolean monlineu(struct monst *, int, int);
 static long mm_2way_aggression(struct monst *, struct monst *);
 static long mm_aggression(struct monst *, struct monst *);
@@ -21,6 +22,7 @@ static void lifesaved_monster(struct monst *);
 static void migrate_mon(struct monst *, xchar, xchar);
 static boolean ok_to_obliterate(struct monst *);
 static void deal_with_overcrowding(struct monst *);
+static void m_restartcham(struct monst *);
 static boolean restrap(struct monst *);
 static int pick_animal(void);
 static int pickvampshape(struct monst *);
@@ -28,6 +30,7 @@ static boolean isspecmon(struct monst *);
 static boolean validspecmon(struct monst *, int);
 static struct permonst *accept_newcham_form(struct monst *, int);
 static void kill_eggs(struct obj *);
+static void pacify_guard(struct monst *);
 
 #define LEVEL_SPECIFIC_NOCORPSE(mdat) \
     (Is_rogue_level(&u.uz)            \
@@ -907,42 +910,41 @@ mcalcmove(
 void
 mcalcdistress(void)
 {
-    struct monst *mtmp;
-
-    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-        if (DEADMONSTER(mtmp))
-            continue;
+    iter_mons(m_calcdistress);
+}
 
-        /* must check non-moving monsters once/turn in case they managed
-           to end up in water or lava; note: when not in liquid they regen,
-           shape-shift, timeout temporary maladies just like other monsters */
-        if (mtmp->data->mmove == 0) {
-            if (g.vision_full_recalc)
-                vision_recalc(0);
-            if (minliquid(mtmp))
-                continue;
-        }
+static void
+m_calcdistress(struct monst *mtmp)
+{
+    /* must check non-moving monsters once/turn in case they managed
+       to end up in water or lava; note: when not in liquid they regen,
+       shape-shift, timeout temporary maladies just like other monsters */
+    if (mtmp->data->mmove == 0) {
+        if (g.vision_full_recalc)
+            vision_recalc(0);
+        if (minliquid(mtmp))
+            return;
+    }
 
-        /* regenerate hit points */
-        mon_regen(mtmp, FALSE);
+    /* regenerate hit points */
+    mon_regen(mtmp, FALSE);
 
-        /* possibly polymorph shapechangers and lycanthropes */
-        if (mtmp->cham >= LOW_PM)
-            decide_to_shapeshift(mtmp, (canspotmon(mtmp)
-                                        || engulfing_u(mtmp))
-                                          ? SHIFT_MSG : 0);
-        were_change(mtmp);
+    /* possibly polymorph shapechangers and lycanthropes */
+    if (mtmp->cham >= LOW_PM)
+        decide_to_shapeshift(mtmp, (canspotmon(mtmp)
+                                    || engulfing_u(mtmp))
+                             ? SHIFT_MSG : 0);
+    were_change(mtmp);
 
-        /* gradually time out temporary problems */
-        if (mtmp->mblinded && !--mtmp->mblinded)
-            mtmp->mcansee = 1;
-        if (mtmp->mfrozen && !--mtmp->mfrozen)
-            mtmp->mcanmove = 1;
-        if (mtmp->mfleetim && !--mtmp->mfleetim)
-            mtmp->mflee = 0;
+    /* gradually time out temporary problems */
+    if (mtmp->mblinded && !--mtmp->mblinded)
+        mtmp->mcansee = 1;
+    if (mtmp->mfrozen && !--mtmp->mfrozen)
+        mtmp->mcanmove = 1;
+    if (mtmp->mfleetim && !--mtmp->mfleetim)
+        mtmp->mflee = 0;
 
-        /* FIXME: mtmp->mlstmv ought to be updated here */
-    }
+    /* FIXME: mtmp->mlstmv ought to be updated here */
 }
 
 int
@@ -3801,38 +3803,81 @@ normal_shape(struct monst *mon)
     }
 }
 
-/* force all chameleons and mimics to become themselves and werecreatures
-   to revert to human form; called when Protection_from_shape_changers gets
-   activated via wearing or eating ring */
+/* iterate all living monsters on current level, calling func for each. */
 void
-rescham(void)
+iter_mons(void (*func)(struct monst *))
 {
-    register struct monst *mtmp;
+    struct monst *mtmp;
 
     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
         if (DEADMONSTER(mtmp))
             continue;
-        normal_shape(mtmp);
+        func(mtmp);
     }
 }
 
-/* let chameleons change and mimics hide again; called when taking off
-   ring of protection from shape changers */
-void
-restartcham(void)
+
+/* iterate all living monsters on current level, calling func for each.
+   if func returns TRUE, stop and return that monster. */
+struct monst *
+get_iter_mons(boolean (*func)(struct monst *))
 {
-    register struct monst *mtmp;
+    struct monst *mtmp;
 
     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
         if (DEADMONSTER(mtmp))
             continue;
-        if (!mtmp->mcan)
-            mtmp->cham = pm_to_cham(monsndx(mtmp->data));
-        if (mtmp->data->mlet == S_MIMIC && mtmp->msleeping) {
-            set_mimic_sym(mtmp);
-            newsym(mtmp->mx, mtmp->my);
-        }
+        if (func(mtmp))
+            return mtmp;
     }
+    return (struct monst *) 0;
+}
+
+/* iterate all living monsters on current level, calling func for each,
+   passing x,y to the function.
+   if func returns TRUE, stop and return that monster. */
+struct monst *
+get_iter_mons_xy(boolean (*func)(struct monst *, xchar, xchar),
+                xchar x, xchar y)
+{
+    struct monst *mtmp;
+
+    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+        if (DEADMONSTER(mtmp))
+            continue;
+        if (func(mtmp, x, y))
+            return mtmp;
+    }
+    return (struct monst *) 0;
+}
+
+
+/* force all chameleons and mimics to become themselves and werecreatures
+   to revert to human form; called when Protection_from_shape_changers gets
+   activated via wearing or eating ring */
+void
+rescham(void)
+{
+    iter_mons(normal_shape);
+}
+
+static void
+m_restartcham(struct monst *mtmp)
+{
+    if (!mtmp->mcan)
+        mtmp->cham = pm_to_cham(monsndx(mtmp->data));
+    if (mtmp->data->mlet == S_MIMIC && mtmp->msleeping) {
+        set_mimic_sym(mtmp);
+        newsym(mtmp->mx, mtmp->my);
+    }
+}
+
+/* let chameleons change and mimics hide again; called when taking off
+   ring of protection from shape changers */
+void
+restartcham(void)
+{
+    iter_mons(m_restartcham);
 }
 
 /* called when restoring a monster from a saved level; protection
@@ -4812,17 +4857,17 @@ angry_guards(boolean silent)
     return FALSE;
 }
 
+static void
+pacify_guard(struct monst *mtmp)
+{
+    if (is_watch(mtmp->data))
+        mtmp->mpeaceful = 1;
+}
+
 void
 pacify_guards(void)
 {
-    struct monst *mtmp;
-
-    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-        if (DEADMONSTER(mtmp))
-            continue;
-        if (is_watch(mtmp->data))
-            mtmp->mpeaceful = 1;
-    }
+    iter_mons(pacify_guard);
 }
 
 void
index 786d36f29971efeb659442f4ed1f8fd05785c233..be921f91d89005e136fa9043cc31ae96f8614fe3 100644 (file)
@@ -4,6 +4,11 @@
 
 #include "hack.h"
 
+static boolean throne_mon_sound(struct monst *);
+static boolean beehive_mon_sound(struct monst *);
+static boolean morgue_mon_sound(struct monst *);
+static boolean zoo_mon_sound(struct monst *);
+static boolean temple_priest_sound(struct monst *);
 static boolean mon_is_gecko(struct monst *);
 static int domonnoise(struct monst *);
 static int dochat(void);
@@ -20,7 +25,170 @@ mon_in_room(struct monst* mon, int rmtyp)
     return FALSE;
 }
 
-DISABLE_WARNING_FORMAT_NONLITERAL
+
+static boolean
+throne_mon_sound(struct monst *mtmp)
+{
+    if ((mtmp->msleeping || is_lord(mtmp->data)
+         || is_prince(mtmp->data)) && !is_animal(mtmp->data)
+        && mon_in_room(mtmp, COURT)) {
+        static const char *const throne_msg[4] = {
+            "the tones of courtly conversation.",
+            "a sceptre pounded in judgment.",
+            "Someone shouts \"Off with %s head!\"",
+            "Queen Beruthiel's cats!",
+        };
+        int which = rn2(3) + (Hallucination ? 1 : 0);
+
+        if (which != 2)
+            You_hear1(throne_msg[which]);
+        else {
+            DISABLE_WARNING_FORMAT_NONLITERAL
+            pline(throne_msg[2], uhis());
+            RESTORE_WARNING_FORMAT_NONLITERAL
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
+
+static boolean
+beehive_mon_sound(struct monst *mtmp)
+{
+    if ((mtmp->data->mlet == S_ANT && is_flyer(mtmp->data))
+        && mon_in_room(mtmp, BEEHIVE)) {
+        int hallu = Hallucination ? 1 : 0;
+
+        switch (rn2(2) + hallu) {
+        case 0:
+            You_hear("a low buzzing.");
+            break;
+        case 1:
+            You_hear("an angry drone.");
+            break;
+        case 2:
+            You_hear("bees in your %sbonnet!",
+                     uarmh ? "" : "(nonexistent) ");
+            break;
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static boolean
+morgue_mon_sound(struct monst *mtmp)
+{
+    if ((is_undead(mtmp->data) || is_vampshifter(mtmp))
+        && mon_in_room(mtmp, MORGUE)) {
+        int hallu = Hallucination ? 1 : 0;
+        const char *hair = body_part(HAIR); /* hair/fur/scales */
+
+        switch (rn2(2) + hallu) {
+        case 0:
+            You("suddenly realize it is unnaturally quiet.");
+            break;
+        case 1:
+            pline_The("%s on the back of your %s %s up.", hair,
+                      body_part(NECK), vtense(hair, "stand"));
+            break;
+        case 2:
+            pline_The("%s on your %s %s to stand up.", hair,
+                      body_part(HEAD), vtense(hair, "seem"));
+            break;
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static boolean
+zoo_mon_sound(struct monst *mtmp)
+{
+    if ((mtmp->msleeping || is_animal(mtmp->data))
+        && mon_in_room(mtmp, ZOO)) {
+        int hallu = Hallucination ? 1 : 0;
+        static const char *const zoo_msg[3] = {
+            "a sound reminiscent of an elephant stepping on a peanut.",
+            "a sound reminiscent of a seal barking.", "Doctor Dolittle!",
+        };
+        You_hear1(zoo_msg[rn2(2) + hallu]);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static boolean
+temple_priest_sound(struct monst *mtmp)
+{
+    if (mtmp->ispriest && inhistemple(mtmp)
+        /* priest must be active */
+        && !helpless(mtmp)
+        /* hero must be outside this temple */
+        && temple_occupied(u.urooms) != EPRI(mtmp)->shroom) {
+        /* Generic temple messages; no attempt to match topic or tone
+           to the pantheon involved, let alone to the specific deity.
+           These are assumed to be coming from the attending priest;
+           asterisk means that the priest must be capable of speech;
+           pound sign (octathorpe,&c--don't go there) means that the
+           priest and the altar must not be directly visible (we don't
+           care if telepathy or extended detection reveals that the
+           priest is not currently standing on the altar; he's mobile). */
+        static const char *const temple_msg[] = {
+            "*someone praising %s.", "*someone beseeching %s.",
+            "#an animal carcass being offered in sacrifice.",
+            "*a strident plea for donations.",
+        };
+        const char *msg;
+        int hallu = Hallucination ? 1 : 0;
+        int trycount = 0,
+            ax = EPRI(mtmp)->shrpos.x,
+            ay = EPRI(mtmp)->shrpos.y;
+        boolean speechless = (mtmp->data->msound <= MS_ANIMAL),
+            in_sight = canseemon(mtmp) || cansee(ax, ay);
+
+        do {
+            msg = temple_msg[rn2(SIZE(temple_msg) - 1 + hallu)];
+            if (index(msg, '*') && speechless)
+                continue;
+            if (index(msg, '#') && in_sight)
+                continue;
+            break; /* msg is acceptable */
+        } while (++trycount < 50);
+        while (!letter(*msg))
+            ++msg; /* skip control flags */
+        if (index(msg, '%')) {
+            DISABLE_WARNING_FORMAT_NONLITERAL
+            You_hear(msg, halu_gname(EPRI(mtmp)->shralign));
+            RESTORE_WARNING_FORMAT_NONLITERAL
+        } else
+            You_hear1(msg);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static boolean
+oracle_sound(struct monst *mtmp)
+{
+    if (mtmp->data != &mons[PM_ORACLE])
+        return FALSE;
+
+    /* and don't produce silly effects when she's clearly visible */
+    if (Hallucination || !canseemon(mtmp)) {
+        int hallu = Hallucination ? 1 : 0;
+        static const char *const ora_msg[5] = {
+            "a strange wind.",     /* Jupiter at Dodona */
+            "convulsive ravings.", /* Apollo at Delphi */
+            "snoring snakes.",     /* AEsculapius at Epidaurus */
+            "someone say \"No more woodchucks!\"",
+            "a loud ZOT!" /* both rec.humor.oracle */
+        };
+        You_hear1(ora_msg[rn2(3) + hallu * 2]);
+    }
+    return TRUE;
+}
 
 void
 dosounds(void)
@@ -48,27 +216,8 @@ dosounds(void)
         You_hear1(sink_msg[rn2(2) + hallu]);
     }
     if (g.level.flags.has_court && !rn2(200)) {
-        static const char *const throne_msg[4] = {
-            "the tones of courtly conversation.",
-            "a sceptre pounded in judgment.",
-            "Someone shouts \"Off with %s head!\"", "Queen Beruthiel's cats!",
-        };
-        for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-            if (DEADMONSTER(mtmp))
-                continue;
-            if ((mtmp->msleeping || is_lord(mtmp->data)
-                 || is_prince(mtmp->data)) && !is_animal(mtmp->data)
-                && mon_in_room(mtmp, COURT)) {
-                /* finding one is enough, at least for now */
-                int which = rn2(3) + hallu;
-
-                if (which != 2)
-                    You_hear1(throne_msg[which]);
-                else
-                    pline(throne_msg[2], uhis());
-                return;
-            }
-        }
+        if (get_iter_mons(throne_mon_sound))
+            return;
     }
     if (g.level.flags.has_swamp && !rn2(200)) {
         static const char *const swamp_msg[3] = {
@@ -115,51 +264,12 @@ dosounds(void)
         return;
     }
     if (g.level.flags.has_beehive && !rn2(200)) {
-        for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-            if (DEADMONSTER(mtmp))
-                continue;
-            if ((mtmp->data->mlet == S_ANT && is_flyer(mtmp->data))
-                && mon_in_room(mtmp, BEEHIVE)) {
-                switch (rn2(2) + hallu) {
-                case 0:
-                    You_hear("a low buzzing.");
-                    break;
-                case 1:
-                    You_hear("an angry drone.");
-                    break;
-                case 2:
-                    You_hear("bees in your %sbonnet!",
-                             uarmh ? "" : "(nonexistent) ");
-                    break;
-                }
-                return;
-            }
-        }
+        if (get_iter_mons(beehive_mon_sound))
+            return;
     }
     if (g.level.flags.has_morgue && !rn2(200)) {
-        for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-            if (DEADMONSTER(mtmp))
-                continue;
-            if ((is_undead(mtmp->data) || is_vampshifter(mtmp))
-                && mon_in_room(mtmp, MORGUE)) {
-                const char *hair = body_part(HAIR); /* hair/fur/scales */
-
-                switch (rn2(2) + hallu) {
-                case 0:
-                    You("suddenly realize it is unnaturally quiet.");
-                    break;
-                case 1:
-                    pline_The("%s on the back of your %s %s up.", hair,
-                              body_part(NECK), vtense(hair, "stand"));
-                    break;
-                case 2:
-                    pline_The("%s on your %s %s to stand up.", hair,
-                              body_part(HEAD), vtense(hair, "seem"));
-                    break;
-                }
-                return;
-            }
-        }
+        if (get_iter_mons(morgue_mon_sound))
+            return;
     }
     if (g.level.flags.has_barracks && !rn2(200)) {
         static const char *const barracks_msg[4] = {
@@ -185,19 +295,8 @@ dosounds(void)
         }
     }
     if (g.level.flags.has_zoo && !rn2(200)) {
-        static const char *const zoo_msg[3] = {
-            "a sound reminiscent of an elephant stepping on a peanut.",
-            "a sound reminiscent of a seal barking.", "Doctor Dolittle!",
-        };
-        for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-            if (DEADMONSTER(mtmp))
-                continue;
-            if ((mtmp->msleeping || is_animal(mtmp->data))
-                && mon_in_room(mtmp, ZOO)) {
-                You_hear1(zoo_msg[rn2(2) + hallu]);
-                return;
-            }
-        }
+        if (get_iter_mons(zoo_mon_sound))
+            return;
     }
     if (g.level.flags.has_shop && !rn2(200)) {
         if (!(sroom = search_special(ANY_SHOP))) {
@@ -217,78 +316,15 @@ dosounds(void)
     }
     if (g.level.flags.has_temple && !rn2(200)
         && !(Is_astralevel(&u.uz) || Is_sanctum(&u.uz))) {
-        for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-            if (DEADMONSTER(mtmp))
-                continue;
-            if (mtmp->ispriest && inhistemple(mtmp)
-                /* priest must be active */
-                && !helpless(mtmp)
-                /* hero must be outside this temple */
-                && temple_occupied(u.urooms) != EPRI(mtmp)->shroom)
-                break;
-        }
-        if (mtmp) {
-            /* Generic temple messages; no attempt to match topic or tone
-               to the pantheon involved, let alone to the specific deity.
-               These are assumed to be coming from the attending priest;
-               asterisk means that the priest must be capable of speech;
-               pound sign (octathorpe,&c--don't go there) means that the
-               priest and the altar must not be directly visible (we don't
-               care if telepathy or extended detection reveals that the
-               priest is not currently standing on the altar; he's mobile). */
-            static const char *const temple_msg[] = {
-                "*someone praising %s.", "*someone beseeching %s.",
-                "#an animal carcass being offered in sacrifice.",
-                "*a strident plea for donations.",
-            };
-            const char *msg;
-            int trycount = 0, ax = EPRI(mtmp)->shrpos.x,
-                ay = EPRI(mtmp)->shrpos.y;
-            boolean speechless = (mtmp->data->msound <= MS_ANIMAL),
-                    in_sight = canseemon(mtmp) || cansee(ax, ay);
-
-            do {
-                msg = temple_msg[rn2(SIZE(temple_msg) - 1 + hallu)];
-                if (index(msg, '*') && speechless)
-                    continue;
-                if (index(msg, '#') && in_sight)
-                    continue;
-                break; /* msg is acceptable */
-            } while (++trycount < 50);
-            while (!letter(*msg))
-                ++msg; /* skip control flags */
-            if (index(msg, '%'))
-                You_hear(msg, halu_gname(EPRI(mtmp)->shralign));
-            else
-                You_hear1(msg);
+        if (get_iter_mons(temple_priest_sound))
             return;
-        }
     }
     if (Is_oracle_level(&u.uz) && !rn2(400)) {
-        /* make sure the Oracle is still here */
-        for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-            if (DEADMONSTER(mtmp))
-                continue;
-            if (mtmp->data == &mons[PM_ORACLE])
-                break;
-        }
-        /* and don't produce silly effects when she's clearly visible */
-        if (mtmp && (hallu || !canseemon(mtmp))) {
-            static const char *const ora_msg[5] = {
-                "a strange wind.",     /* Jupiter at Dodona */
-                "convulsive ravings.", /* Apollo at Delphi */
-                "snoring snakes.",     /* AEsculapius at Epidaurus */
-                "someone say \"No more woodchucks!\"",
-                "a loud ZOT!" /* both rec.humor.oracle */
-            };
-            You_hear1(ora_msg[rn2(3) + hallu * 2]);
-        }
-        return;
+        if (get_iter_mons(oracle_sound))
+            return;
     }
 }
 
-RESTORE_WARNING_FORMAT_NONLITERAL
-
 static const char *const h_sounds[] = {
     "beep",   "boing",   "sing",   "belche", "creak",   "cough",
     "rattle", "ululate", "pop",    "jingle", "sniffle", "tinkle",
index 2d3ffbc5ed11be47596aba57b01c2613eba5ae5d..82d49e425263dd4286de25264d0b7618b0c61b58 100644 (file)
@@ -12,18 +12,25 @@ static void vault_tele(void);
 static boolean rloc_pos_ok(int, int, struct monst *);
 static void rloc_to_core(struct monst *, int, int, unsigned);
 static void mvault_tele(struct monst *);
+static boolean m_blocks_teleporting(struct monst *);
+
+/* does monster block others from teleporting? */
+static boolean
+m_blocks_teleporting(struct monst *mtmp)
+{
+    if (is_dlord(mtmp->data) || is_dprince(mtmp->data))
+        return TRUE;
+    return FALSE;
+}
 
 /* teleporting is prevented on this level for this monster? */
 boolean
 noteleport_level(struct monst* mon)
 {
-    struct monst *mtmp;
-
     /* demon court in Gehennom prevent others from teleporting */
     if (In_hell(&u.uz) && !(is_dlord(mon->data) || is_dprince(mon->data)))
-        for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
-            if (is_dlord(mtmp->data) || is_dprince(mtmp->data))
-                return TRUE;
+        if (get_iter_mons(m_blocks_teleporting))
+            return TRUE;
 
     /* natural no-teleport level */
     if (g.level.flags.noteleport)