Monster list iterator
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.
This commit is contained in:
52
src/apply.c
52
src/apply.c
@@ -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;
|
||||
}
|
||||
|
||||
static boolean
|
||||
mleashed_next2u(struct monst *mtmp)
|
||||
{
|
||||
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)
|
||||
{
|
||||
register struct monst *mtmp;
|
||||
register struct obj *otmp;
|
||||
if (get_iter_mons(mleashed_next2u))
|
||||
return FALSE;
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* no pack mules for the Amulet */
|
||||
if (u.usteed && mon_has_amulet(u.usteed))
|
||||
return FALSE;
|
||||
|
||||
29
src/bones.c
29
src/bones.c
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
8
src/do.c
8
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);
|
||||
|
||||
60
src/dokick.c
60
src/dokick.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
|
||||
163
src/mon.c
163
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;
|
||||
iter_mons(m_calcdistress);
|
||||
}
|
||||
|
||||
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
|
||||
if (DEADMONSTER(mtmp))
|
||||
continue;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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 */
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
|
||||
/* FIXME: mtmp->mlstmv ought to be updated here */
|
||||
}
|
||||
|
||||
int
|
||||
@@ -3801,18 +3803,72 @@ normal_shape(struct monst *mon)
|
||||
}
|
||||
}
|
||||
|
||||
/* iterate all living monsters on current level, calling func for each. */
|
||||
void
|
||||
iter_mons(void (*func)(struct monst *))
|
||||
{
|
||||
struct monst *mtmp;
|
||||
|
||||
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
|
||||
if (DEADMONSTER(mtmp))
|
||||
continue;
|
||||
func(mtmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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 *))
|
||||
{
|
||||
struct monst *mtmp;
|
||||
|
||||
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
|
||||
if (DEADMONSTER(mtmp))
|
||||
continue;
|
||||
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)
|
||||
{
|
||||
register struct monst *mtmp;
|
||||
iter_mons(normal_shape);
|
||||
}
|
||||
|
||||
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
|
||||
if (DEADMONSTER(mtmp))
|
||||
continue;
|
||||
normal_shape(mtmp);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3821,18 +3877,7 @@ rescham(void)
|
||||
void
|
||||
restartcham(void)
|
||||
{
|
||||
register 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);
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
324
src/sounds.c
324
src/sounds.c
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user