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 *);
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 *);
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;
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)
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)
int x, y;
struct trap *ttmp;
struct monst *mtmp;
- struct permonst *mptr;
struct fruit *f;
struct cemetery *newbones;
char c, *bonesid;
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 */
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
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
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);
}
/*
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);
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);
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)
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 */
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;
}
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
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)
{
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.");
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 *);
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 *);
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) \
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
}
}
-/* 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
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
#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);
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)
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] = {
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] = {
}
}
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))) {
}
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",
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)