vampshifter messages

If you've just received the "dead bat revives as a vampire" message,
suppress the rather obscure "Maybe not..." message given when an unseen
creature gets life-saved since it ends up being out of sequence.  You
could get them both when the death/revival was sensed via telepathy
without being in sight.

Also, some formatting cleanup and a couple miscellaneous code tweaks.
This commit is contained in:
PatR
2015-07-06 18:24:13 -07:00
parent c64036c97b
commit fe09f7156d
+211 -202
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mon.c $NHDT-Date: 1433457072 2015/06/04 22:31:12 $ $NHDT-Branch: master $:$NHDT-Revision: 1.178 $ */ /* NetHack 3.6 mon.c $NHDT-Date: 1436232245 2015/07/07 01:24:05 $ $NHDT-Branch: master $:$NHDT-Revision: 1.181 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -11,6 +11,8 @@
#include "mfndpos.h" #include "mfndpos.h"
#include <ctype.h> #include <ctype.h>
STATIC_VAR boolean vamp_rise_msg;
STATIC_DCL boolean FDECL(restrap, (struct monst *)); STATIC_DCL boolean FDECL(restrap, (struct monst *));
STATIC_DCL long FDECL(mm_aggression, (struct monst *, struct monst *)); STATIC_DCL long FDECL(mm_aggression, (struct monst *, struct monst *));
STATIC_DCL long FDECL(mm_displacement, (struct monst *, struct monst *)); STATIC_DCL long FDECL(mm_displacement, (struct monst *, struct monst *));
@@ -22,6 +24,9 @@ STATIC_DCL boolean FDECL(isspecmon, (struct monst *));
STATIC_DCL boolean FDECL(validspecmon, (struct monst *, int)); STATIC_DCL boolean FDECL(validspecmon, (struct monst *, int));
STATIC_DCL boolean FDECL(validvamp, (struct monst *, int *, int)); STATIC_DCL boolean FDECL(validvamp, (struct monst *, int *, int));
STATIC_DCL struct permonst *FDECL(accept_newcham_form, (int)); STATIC_DCL struct permonst *FDECL(accept_newcham_form, (int));
STATIC_DCL struct obj *FDECL(make_corpse, (struct monst *, unsigned));
STATIC_DCL void FDECL(m_detach, (struct monst *, struct permonst *));
STATIC_DCL void FDECL(lifesaved_monster, (struct monst *));
#define LEVEL_SPECIFIC_NOCORPSE(mdat) \ #define LEVEL_SPECIFIC_NOCORPSE(mdat) \
(Is_rogue_level(&u.uz) \ (Is_rogue_level(&u.uz) \
@@ -34,10 +39,6 @@ const char *warnings[] = {
}; };
#endif /* 0 */ #endif /* 0 */
STATIC_DCL struct obj *FDECL(make_corpse, (struct monst *, unsigned));
STATIC_DCL void FDECL(m_detach, (struct monst *, struct permonst *));
STATIC_DCL void FDECL(lifesaved_monster, (struct monst *));
/* convert the monster index of an undead to its living counterpart */ /* convert the monster index of an undead to its living counterpart */
int int
undead_to_corpse(mndx) undead_to_corpse(mndx)
@@ -141,6 +142,7 @@ int mndx, mode;
default: default:
if (mndx >= LOW_PM && mndx < NUMMONS) { if (mndx >= LOW_PM && mndx < NUMMONS) {
struct permonst *ptr = &mons[mndx]; struct permonst *ptr = &mons[mndx];
if (is_human(ptr)) if (is_human(ptr))
mndx = PM_HUMAN; mndx = PM_HUMAN;
else if (is_elf(ptr)) else if (is_elf(ptr))
@@ -175,14 +177,13 @@ int mndx;
/* for deciding whether corpse will carry along full monster data */ /* for deciding whether corpse will carry along full monster data */
#define KEEPTRAITS(mon) \ #define KEEPTRAITS(mon) \
( \ ((mon)->isshk || (mon)->mtame || unique_corpstat((mon)->data) \
(mon)->isshk || (mon)->mtame || unique_corpstat(mon->data) \
|| is_reviver((mon)->data) \ || is_reviver((mon)->data) \
|| /* normally leader the will be unique, */ /* but he might have \ /* normally quest leader will be unique, */ \
been polymorphed */ \ /* but he or she might have been polymorphed */ \
(mon)->m_id == quest_status.leader_m_id \ || (mon)->m_id == quest_status.leader_m_id \
|| /* special cancellation handling for these */ \ /* special cancellation handling for these */ \
(dmgtype((mon)->data, AD_SEDU) || dmgtype((mon)->data, AD_SSEX))) || (dmgtype((mon)->data, AD_SEDU) || dmgtype((mon)->data, AD_SSEX)))
/* Creates a monster corpse, a "special" corpse, or nothing if it doesn't /* Creates a monster corpse, a "special" corpse, or nothing if it doesn't
* leave corpses. Monsters which leave "special" corpses should have * leave corpses. Monsters which leave "special" corpses should have
@@ -225,7 +226,6 @@ unsigned corpseflags;
obj->cursed = obj->blessed = FALSE; obj->cursed = obj->blessed = FALSE;
} }
goto default_1; goto default_1;
case PM_WHITE_UNICORN: case PM_WHITE_UNICORN:
case PM_GRAY_UNICORN: case PM_GRAY_UNICORN:
case PM_BLACK_UNICORN: case PM_BLACK_UNICORN:
@@ -318,18 +318,18 @@ unsigned corpseflags;
obj = mksobj_at(SCR_BLANK_PAPER, x, y, TRUE, FALSE); obj = mksobj_at(SCR_BLANK_PAPER, x, y, TRUE, FALSE);
free_mname(mtmp); free_mname(mtmp);
break; break;
/* expired puddings will congeal into a large blob /* expired puddings will congeal into a large blob;
like dragons, relies on the order remaining consistent */ like dragons, relies on the order remaining consistent */
case PM_GRAY_OOZE: case PM_GRAY_OOZE:
case PM_BROWN_PUDDING: case PM_BROWN_PUDDING:
case PM_GREEN_SLIME: case PM_GREEN_SLIME:
case PM_BLACK_PUDDING: case PM_BLACK_PUDDING:
/* we have to do this here because most other places /* we have to do this here because most other places
* expect there to be an object coming back; not this one */ expect there to be an object coming back; not this one */
obj = mksobj_at(GLOB_OF_BLACK_PUDDING - (PM_BLACK_PUDDING - mndx), x, obj = mksobj_at(GLOB_OF_BLACK_PUDDING - (PM_BLACK_PUDDING - mndx),
y, TRUE, FALSE); x, y, TRUE, FALSE);
while ((obj && (otmp = obj_nexto(obj)) != (struct obj *) 0)) { while (obj && (otmp = obj_nexto(obj)) != (struct obj *) 0) {
pudding_merge_message(obj, otmp); pudding_merge_message(obj, otmp);
obj = obj_meld(&obj, &otmp); obj = obj_meld(&obj, &otmp);
} }
@@ -338,15 +338,16 @@ unsigned corpseflags;
break; break;
default_1: default_1:
default: default:
if (mvitals[mndx].mvflags & G_NOCORPSE) if (mvitals[mndx].mvflags & G_NOCORPSE) {
return (struct obj *) 0; return (struct obj *) 0;
else { } else {
corpstatflags |= CORPSTAT_INIT; corpstatflags |= CORPSTAT_INIT;
/* preserve the unique traits of some creatures */ /* preserve the unique traits of some creatures */
obj = mkcorpstat(CORPSE, KEEPTRAITS(mtmp) ? mtmp : 0, mdat, x, y, obj = mkcorpstat(CORPSE, KEEPTRAITS(mtmp) ? mtmp : 0,
corpstatflags); mdat, x, y, corpstatflags);
if (burythem) { if (burythem) {
boolean dealloc; boolean dealloc;
(void) bury_an_obj(obj, &dealloc); (void) bury_an_obj(obj, &dealloc);
newsym(x, y); newsym(x, y);
return (dealloc ? NULL : obj); return (dealloc ? NULL : obj);
@@ -387,16 +388,17 @@ register struct monst *mtmp;
{ {
boolean inpool, inlava, infountain; boolean inpool, inlava, infountain;
inpool = is_pool(mtmp->mx, mtmp->my) && !is_flyer(mtmp->data) /* [what about ceiling clingers?] */
&& !is_floater(mtmp->data); inpool = (is_pool(mtmp->mx, mtmp->my)
inlava = is_lava(mtmp->mx, mtmp->my) && !is_flyer(mtmp->data) && !(is_flyer(mtmp->data) || is_floater(mtmp->data)));
&& !is_floater(mtmp->data); inlava = (is_lava(mtmp->mx, mtmp->my)
&& !(is_flyer(mtmp->data) || is_floater(mtmp->data)));
infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ); infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ);
/* Flying and levitation keeps our steed out of the liquid */ /* Flying and levitation keeps our steed out of the liquid */
/* (but not water-walking or swimming) */ /* (but not water-walking or swimming) */
if (mtmp == u.usteed && (Flying || Levitation)) if (mtmp == u.usteed && (Flying || Levitation))
return (0); return 0;
/* Gremlin multiplying won't go on forever since the hit points /* Gremlin multiplying won't go on forever since the hit points
* keep going down, and when it gets to 1 hit point the clone * keep going down, and when it gets to 1 hit point the clone
@@ -410,6 +412,7 @@ register struct monst *mtmp;
return (0); return (0);
} else if (mtmp->data == &mons[PM_IRON_GOLEM] && inpool && !rn2(5)) { } else if (mtmp->data == &mons[PM_IRON_GOLEM] && inpool && !rn2(5)) {
int dam = d(2, 6); int dam = d(2, 6);
if (cansee(mtmp->mx, mtmp->my)) if (cansee(mtmp->mx, mtmp->my))
pline("%s rusts.", Monnam(mtmp)); pline("%s rusts.", Monnam(mtmp));
mtmp->mhp -= dam; mtmp->mhp -= dam;
@@ -418,10 +421,10 @@ register struct monst *mtmp;
if (mtmp->mhp < 1) { if (mtmp->mhp < 1) {
mondead(mtmp); mondead(mtmp);
if (mtmp->mhp < 1) if (mtmp->mhp < 1)
return (1); return 1;
} }
water_damage_chain(mtmp->minvent, FALSE); water_damage_chain(mtmp->minvent, FALSE);
return (0); return 0;
} }
if (inlava) { if (inlava) {
@@ -452,7 +455,7 @@ register struct monst *mtmp;
(void) rloc(mtmp, FALSE); (void) rloc(mtmp, FALSE);
return 0; return 0;
} }
return (1); return 1;
} }
} else if (inpool) { } else if (inpool) {
/* Most monsters drown in pools. flooreffects() will take care of /* Most monsters drown in pools. flooreffects() will take care of
@@ -476,7 +479,7 @@ register struct monst *mtmp;
(void) rloc(mtmp, FALSE); (void) rloc(mtmp, FALSE);
return 0; return 0;
} }
return (1); return 1;
} }
} else { } else {
/* but eels have a difficult time outside */ /* but eels have a difficult time outside */
@@ -487,7 +490,7 @@ register struct monst *mtmp;
monflee(mtmp, 2, FALSE, FALSE); monflee(mtmp, 2, FALSE, FALSE);
} }
} }
return (0); return 0;
} }
int int
@@ -575,22 +578,22 @@ movemon()
register boolean somebody_can_move = FALSE; register boolean somebody_can_move = FALSE;
/* /*
Some of you may remember the former assertion here that * Some of you may remember the former assertion here that
because of deaths and other actions, a simple one-pass * because of deaths and other actions, a simple one-pass
algorithm wasn't possible for movemon. Deaths are no longer * algorithm wasn't possible for movemon. Deaths are no longer
removed to the separate list fdmon; they are simply left in * removed to the separate list fdmon; they are simply left in
the chain with hit points <= 0, to be cleaned up at the end * the chain with hit points <= 0, to be cleaned up at the end
of the pass. * of the pass.
*
The only other actions which cause monsters to be removed from * The only other actions which cause monsters to be removed from
the chain are level migrations and losedogs(). I believe losedogs() * the chain are level migrations and losedogs(). I believe losedogs()
is a cleanup routine not associated with monster movements, and * is a cleanup routine not associated with monster movements, and
monsters can only affect level migrations on themselves, not others * monsters can only affect level migrations on themselves, not others
(hence the fetching of nmon before moving the monster). Currently, * (hence the fetching of nmon before moving the monster). Currently,
monsters can jump into traps, read cursed scrolls of teleportation, * monsters can jump into traps, read cursed scrolls of teleportation,
and drink cursed potions of raise level to change levels. These are * and drink cursed potions of raise level to change levels. These are
all reflexive at this point. Should one monster be able to level * all reflexive at this point. Should one monster be able to level
teleport another, this scheme would have problems. * teleport another, this scheme would have problems.
*/ */
for (mtmp = fmon; mtmp; mtmp = nmtmp) { for (mtmp = fmon; mtmp; mtmp = nmtmp) {
@@ -745,8 +748,7 @@ register struct monst *mtmp;
delobj(otmp); delobj(otmp);
ptr = mtmp->data; ptr = mtmp->data;
if (poly) { if (poly) {
if (newcham(mtmp, (struct permonst *) 0, FALSE, if (newcham(mtmp, (struct permonst *) 0, FALSE, FALSE))
FALSE))
ptr = mtmp->data; ptr = mtmp->data;
} else if (grow) { } else if (grow) {
ptr = grow_up(mtmp, (struct monst *) 0); ptr = grow_up(mtmp, (struct monst *) 0);
@@ -778,8 +780,9 @@ register struct monst *mtmp;
} }
/* monster eats a pile of objects */ /* monster eats a pile of objects */
int meatobj(mtmp) /* for gelatinous cubes */ int
register struct monst *mtmp; meatobj(mtmp) /* for gelatinous cubes */
struct monst *mtmp;
{ {
register struct obj *otmp, *otmp2; register struct obj *otmp, *otmp2;
struct permonst *ptr, *original_ptr = mtmp->data; struct permonst *ptr, *original_ptr = mtmp->data;
@@ -805,23 +808,23 @@ register struct monst *mtmp;
/* untouchable (or inaccessible) items */ /* untouchable (or inaccessible) items */
} else if ((otmp->otyp == CORPSE } else if ((otmp->otyp == CORPSE
&& touch_petrifies(&mons[otmp->corpsenm]) && touch_petrifies(&mons[otmp->corpsenm])
&& !resists_ston(mtmp)) || && !resists_ston(mtmp))
/* don't engulf boulders and statues or ball&chain */ /* don't engulf boulders and statues or ball&chain */
otmp->oclass == ROCK_CLASS || otmp == uball || otmp->oclass == ROCK_CLASS
|| otmp == uchain) { || otmp == uball || otmp == uchain) {
/* do nothing--neither eaten nor engulfed */ /* do nothing--neither eaten nor engulfed */
continue; continue;
/* inedible items -- engulf these */ /* inedible items -- engulf these */
} else if (!is_organic(otmp) || obj_resists(otmp, 5, 95) } else if (!is_organic(otmp) || obj_resists(otmp, 5, 95)
|| !touch_artifact(otmp, mtmp) || || !touch_artifact(otmp, mtmp)
/* redundant due to non-organic composition but /* redundant due to non-organic composition but
included for emphasis */ included for emphasis */
(otmp->otyp == AMULET_OF_STRANGULATION || (otmp->otyp == AMULET_OF_STRANGULATION
|| otmp->otyp == RIN_SLOW_DIGESTION) || || otmp->otyp == RIN_SLOW_DIGESTION)
/* cockatrice corpses handled above; this /* cockatrice corpses handled above; this
touch_petrifies() check catches eggs */ touch_petrifies() check catches eggs */
((otmp->otyp == CORPSE || otmp->otyp == EGG) || ((otmp->otyp == CORPSE || otmp->otyp == EGG)
&& ((touch_petrifies(&mons[otmp->corpsenm]) && ((touch_petrifies(&mons[otmp->corpsenm])
&& !resists_ston(mtmp)) && !resists_ston(mtmp))
|| (otmp->corpsenm == PM_GREEN_SLIME || (otmp->corpsenm == PM_GREEN_SLIME
@@ -853,6 +856,7 @@ register struct monst *mtmp;
} }
if (Has_contents(otmp)) { if (Has_contents(otmp)) {
register struct obj *otmp3; register struct obj *otmp3;
/* contents of eaten containers become engulfed; this /* contents of eaten containers become engulfed; this
is arbitrary, but otherwise g.cubes are too powerful */ is arbitrary, but otherwise g.cubes are too powerful */
while ((otmp3 = otmp->cobj) != 0) { while ((otmp3 = otmp->cobj) != 0) {
@@ -891,10 +895,10 @@ register struct monst *mtmp;
if (cansee(mtmp->mx, mtmp->my) && flags.verbose && buf[0]) if (cansee(mtmp->mx, mtmp->my) && flags.verbose && buf[0])
pline1(buf); pline1(buf);
else if (flags.verbose) else if (flags.verbose)
You_hear("%s slurping sound%s.", ecount == 1 ? "a" : "several", You_hear("%s slurping sound%s.",
ecount == 1 ? "" : "s"); (ecount == 1) ? "a" : "several", plur(ecount));
} }
return ((count > 0) || (ecount > 0)) ? 1 : 0; return (count > 0 || ecount > 0) ? 1 : 0;
} }
void void
@@ -931,8 +935,7 @@ register const char *str;
for (otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) { for (otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
otmp2 = otmp->nexthere; otmp2 = otmp->nexthere;
/* Nymphs take everything. Most monsters don't pick up corpses. /* Nymphs take everything. Most monsters don't pick up corpses. */
*/
if (!str ? searches_for_item(mtmp, otmp) if (!str ? searches_for_item(mtmp, otmp)
: !!(index(str, otmp->oclass))) { : !!(index(str, otmp->oclass))) {
if (otmp->otyp == CORPSE && mtmp->data->mlet != S_NYMPH && if (otmp->otyp == CORPSE && mtmp->data->mlet != S_NYMPH &&
@@ -970,10 +973,10 @@ register const char *str;
int int
curr_mon_load(mtmp) curr_mon_load(mtmp)
register struct monst *mtmp; struct monst *mtmp;
{ {
register int curload = 0; int curload = 0;
register struct obj *obj; struct obj *obj;
for (obj = mtmp->minvent; obj; obj = obj->nobj) { for (obj = mtmp->minvent; obj; obj = obj->nobj) {
if (obj->otyp != BOULDER || !throws_rocks(mtmp->data)) if (obj->otyp != BOULDER || !throws_rocks(mtmp->data))
@@ -985,9 +988,10 @@ register struct monst *mtmp;
int int
max_mon_load(mtmp) max_mon_load(mtmp)
register struct monst *mtmp; struct monst *mtmp;
{ {
register long maxload; long maxload;
/* Base monster carrying capacity is equal to human maximum /* Base monster carrying capacity is equal to human maximum
* carrying capacity, or half human maximum if not strong. * carrying capacity, or half human maximum if not strong.
* (for a polymorphed player, the value used would be the * (for a polymorphed player, the value used would be the
@@ -1031,7 +1035,6 @@ struct obj *otmp;
int otyp = otmp->otyp, newload = otmp->owt; int otyp = otmp->otyp, newload = otmp->owt;
struct permonst *mdat = mtmp->data; struct permonst *mdat = mtmp->data;
short nattk = 0; short nattk = 0;
boolean glomper = FALSE;
if (notake(mdat)) if (notake(mdat))
return 0; /* can't carry anything */ return 0; /* can't carry anything */
@@ -1048,19 +1051,25 @@ struct obj *otmp;
/* monsters without hands can't pick up multiple objects at once /* monsters without hands can't pick up multiple objects at once
* unless they have an engulfing attack * unless they have an engulfing attack
* *
* ...dragons, of course, can always carry gold pieces somehow */ * ...dragons, of course, can always carry gold pieces and gems somehow */
if (otmp->quan > 1) { if (otmp->quan > 1) {
for (nattk = 0; nattk < NATTK; nattk++) boolean glomper = FALSE;
glomper = (glomper || mtmp->data->mattk[nattk].aatyp == AT_ENGL);
if ((mtmp->data->mflags1 & M1_NOHANDS) && !glomper if (mtmp->data->mlet == S_DRAGON
&& (!(mtmp->data->mlet == S_DRAGON && (otmp->oclass == COIN_CLASS
&& otmp->oclass == COIN_CLASS))) { || otmp->oclass == GEM_CLASS))
glomper = TRUE;
else
for (nattk = 0; nattk < NATTK; nattk++)
if (mtmp->data->mattk[nattk].aatyp == AT_ENGL) {
glomper = TRUE;
break;
}
if ((mtmp->data->mflags1 & M1_NOHANDS) && !glomper)
return 1; return 1;
} }
}
/* Steeds don't pick up stuff (to avoid shop abuse) */ /* steeds don't pick up stuff (to avoid shop abuse) */
if (mtmp == u.usteed) if (mtmp == u.usteed)
return 0; return 0;
if (mtmp->isshk) if (mtmp->isshk)
@@ -1077,7 +1086,7 @@ struct obj *otmp;
/* nymphs deal in stolen merchandise, but not boulders or statues */ /* nymphs deal in stolen merchandise, but not boulders or statues */
if (mdat->mlet == S_NYMPH) if (mdat->mlet == S_NYMPH)
return otmp->oclass == ROCK_CLASS ? 0 : otmp->quan; return (otmp->oclass == ROCK_CLASS) ? 0 : otmp->quan;
if (curr_mon_load(mtmp) + newload > max_mon_load(mtmp)) if (curr_mon_load(mtmp) + newload > max_mon_load(mtmp))
return 0; return 0;
@@ -1088,15 +1097,16 @@ struct obj *otmp;
/* return number of acceptable neighbour positions */ /* return number of acceptable neighbour positions */
int int
mfndpos(mon, poss, info, flag) mfndpos(mon, poss, info, flag)
register struct monst *mon; struct monst *mon;
coord *poss; /* coord poss[9] */ coord *poss; /* coord poss[9] */
long *info; /* long info[9] */ long *info; /* long info[9] */
long flag; long flag;
{ {
struct permonst *mdat = mon->data; struct permonst *mdat = mon->data;
register xchar x, y, nx, ny; register struct trap *ttmp;
register int cnt = 0; xchar x, y, nx, ny;
register uchar ntyp; int cnt = 0;
uchar ntyp;
uchar nowtyp; uchar nowtyp;
boolean wantpool, poolok, lavaok, nodiag; boolean wantpool, poolok, lavaok, nodiag;
boolean rockok = FALSE, treeok = FALSE, thrudoor; boolean rockok = FALSE, treeok = FALSE, thrudoor;
@@ -1175,15 +1185,14 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
if ((is_pool(nx, ny) == wantpool || poolok) if ((is_pool(nx, ny) == wantpool || poolok)
&& (lavaok || !is_lava(nx, ny))) { && (lavaok || !is_lava(nx, ny))) {
int dispx, dispy; int dispx, dispy;
boolean monseeu = boolean monseeu = (mon->mcansee
(mon->mcansee && (!Invis || perceives(mdat))); && (!Invis || perceives(mdat)));
boolean checkobj = OBJ_AT(nx, ny); boolean checkobj = OBJ_AT(nx, ny);
/* Displacement also displaces the Elbereth/scare monster, /* Displacement also displaces the Elbereth/scare monster,
* as long as you are visible. * as long as you are visible.
*/ */
if (Displaced && monseeu && (mon->mux == nx) if (Displaced && monseeu && mon->mux == nx && mon->muy == ny) {
&& (mon->muy == ny)) {
dispx = u.ux; dispx = u.ux;
dispy = u.uy; dispy = u.uy;
} else { } else {
@@ -1231,8 +1240,8 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
info[cnt] |= ALLOW_MDISP; info[cnt] |= ALLOW_MDISP;
} }
} }
/* Note: ALLOW_SANCT only prevents movement, not */ /* Note: ALLOW_SANCT only prevents movement, not
/* attack, into a temple. */ attack, into a temple. */
if (level.flags.has_temple && *in_rooms(nx, ny, TEMPLE) if (level.flags.has_temple && *in_rooms(nx, ny, TEMPLE)
&& !*in_rooms(x, y, TEMPLE) && !*in_rooms(x, y, TEMPLE)
&& in_your_sanctuary((struct monst *) 0, nx, ny)) { && in_your_sanctuary((struct monst *) 0, nx, ny)) {
@@ -1261,17 +1270,14 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
&& bad_rock(mdat, nx, y) && cant_squeeze_thru(mon)) && bad_rock(mdat, nx, y) && cant_squeeze_thru(mon))
continue; continue;
/* The monster avoids a particular type of trap if it's /* The monster avoids a particular type of trap if it's
* familiar * familiar with the trap type. Pets get ALLOW_TRAPS
* with the trap type. Pets get ALLOW_TRAPS and checking is * and checking is done in dogmove.c. In either case,
* done in dogmove.c. In either case, "harmless" traps are * "harmless" traps are neither avoided nor marked in info[].
* neither avoided nor marked in info[].
*/ */
{ if ((ttmp = t_at(nx, ny)) != 0) {
register struct trap *ttmp = t_at(nx, ny);
if (ttmp) {
if (ttmp->ttyp >= TRAPNUM || ttmp->ttyp == 0) { if (ttmp->ttyp >= TRAPNUM || ttmp->ttyp == 0) {
impossible("A monster looked at a very strange " impossible(
"trap of type %d.", "A monster looked at a very strange trap of type %d.",
ttmp->ttyp); ttmp->ttyp);
continue; continue;
} }
@@ -1279,22 +1285,19 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
|| mdat == &mons[PM_IRON_GOLEM]) || mdat == &mons[PM_IRON_GOLEM])
&& ttmp->ttyp != STATUE_TRAP && ttmp->ttyp != STATUE_TRAP
&& ((ttmp->ttyp != PIT && ttmp->ttyp != SPIKED_PIT && ((ttmp->ttyp != PIT && ttmp->ttyp != SPIKED_PIT
&& ttmp->ttyp != TRAPDOOR && ttmp->ttyp != TRAPDOOR && ttmp->ttyp != HOLE)
&& ttmp->ttyp != HOLE)
|| (!is_flyer(mdat) && !is_floater(mdat) || (!is_flyer(mdat) && !is_floater(mdat)
&& !is_clinger(mdat)) || Sokoban) && !is_clinger(mdat)) || Sokoban)
&& (ttmp->ttyp != SLP_GAS_TRAP && (ttmp->ttyp != SLP_GAS_TRAP || !resists_sleep(mon))
|| !resists_sleep(mon))
&& (ttmp->ttyp != BEAR_TRAP && (ttmp->ttyp != BEAR_TRAP
|| (mdat->msize > MZ_SMALL && !amorphous(mdat) || (mdat->msize > MZ_SMALL && !amorphous(mdat)
&& !is_flyer(mdat) && !is_whirly(mdat) && !is_flyer(mdat) && !is_floater(mdat)
&& !unsolid(mdat))) && !is_whirly(mdat) && !unsolid(mdat)))
&& (ttmp->ttyp != FIRE_TRAP || !resists_fire(mon)) && (ttmp->ttyp != FIRE_TRAP || !resists_fire(mon))
&& (ttmp->ttyp != SQKY_BOARD || !is_flyer(mdat)) && (ttmp->ttyp != SQKY_BOARD || !is_flyer(mdat))
&& (ttmp->ttyp != WEB && (ttmp->ttyp != WEB
|| (!amorphous(mdat) && !webmaker(mdat))) || (!amorphous(mdat) && !webmaker(mdat)))
&& (ttmp->ttyp != ANTI_MAGIC && (ttmp->ttyp != ANTI_MAGIC || !resists_magm(mon))) {
|| !resists_magm(mon))) {
if (!(flag & ALLOW_TRAPS)) { if (!(flag & ALLOW_TRAPS)) {
if (mon->mtrapseen & (1L << (ttmp->ttyp - 1))) if (mon->mtrapseen & (1L << (ttmp->ttyp - 1)))
continue; continue;
@@ -1302,7 +1305,6 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
info[cnt] |= ALLOW_TRAPS; info[cnt] |= ALLOW_TRAPS;
} }
} }
}
poss[cnt].x = nx; poss[cnt].x = nx;
poss[cnt].y = ny; poss[cnt].y = ny;
cnt++; cnt++;
@@ -1312,7 +1314,7 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
wantpool = FALSE; wantpool = FALSE;
goto nexttry; goto nexttry;
} }
return (cnt); return cnt;
} }
/* Monster against monster special attacks; for the specified monster /* Monster against monster special attacks; for the specified monster
@@ -1349,29 +1351,28 @@ struct monst *magr, /* monster that is currently deciding where to move */
do so, otherwise they might just end up swapping places do so, otherwise they might just end up swapping places
again when defender gets its chance to move */ again when defender gets its chance to move */
if ((pa->mflags3 & M3_DISPLACES) != 0 && (pd->mflags3 & M3_DISPLACES) == 0 if ((pa->mflags3 & M3_DISPLACES) != 0 && (pd->mflags3 & M3_DISPLACES) == 0
&&
/* no displacing grid bugs diagonally */ /* no displacing grid bugs diagonally */
!(magr->mx != mdef->mx && magr->my != mdef->my && NODIAG(monsndx(pd))) && !(magr->mx != mdef->mx && magr->my != mdef->my
&& && NODIAG(monsndx(pd)))
/* no displacing trapped monsters or multi-location longworms */ /* no displacing trapped monsters or multi-location longworms */
!mdef->mtrapped && (!mdef->wormno || !count_wsegs(mdef)) && && !mdef->mtrapped && (!mdef->wormno || !count_wsegs(mdef))
/* riders can move anything; others, same size or smaller only */ /* riders can move anything; others, same size or smaller only */
(is_rider(pa) || pa->msize >= pd->msize)) && (is_rider(pa) || pa->msize >= pd->msize))
return ALLOW_MDISP; return ALLOW_MDISP;
return 0L; return 0L;
} }
/* Is the square close enough for the monster to move or attack into? */
boolean boolean
monnear(mon, x, y) monnear(mon, x, y)
register struct monst *mon; struct monst *mon;
register int x, y; int x, y;
/* Is the square close enough for the monster to move or attack into? */
{ {
register int distance = dist2(mon->mx, mon->my, x, y); int distance = dist2(mon->mx, mon->my, x, y);
if (distance == 2 && NODIAG(mon->data - mons)) if (distance == 2 && NODIAG(mon->data - mons))
return 0; return 0;
return ((boolean)(distance < 3)); return (boolean) (distance < 3);
} }
/* really free dead monsters */ /* really free dead monsters */
@@ -1392,15 +1393,15 @@ dmonsfree()
} }
if (count != iflags.purge_monsters) if (count != iflags.purge_monsters)
impossible("dmonsfree: %d removed doesn't match %d pending", count, impossible("dmonsfree: %d removed doesn't match %d pending",
iflags.purge_monsters); count, iflags.purge_monsters);
iflags.purge_monsters = 0; iflags.purge_monsters = 0;
} }
/* called when monster is moved to larger structure */ /* called when monster is moved to larger structure */
void void
replmon(mtmp, mtmp2) replmon(mtmp, mtmp2)
register struct monst *mtmp, *mtmp2; struct monst *mtmp, *mtmp2;
{ {
struct obj *otmp; struct obj *otmp;
@@ -1424,8 +1425,7 @@ register struct monst *mtmp, *mtmp2;
/* since this is so rare, we don't have any `mon_move_light_source' */ /* since this is so rare, we don't have any `mon_move_light_source' */
new_light_source(mtmp2->mx, mtmp2->my, emits_light(mtmp2->data), new_light_source(mtmp2->mx, mtmp2->my, emits_light(mtmp2->data),
LS_MONSTER, monst_to_any(mtmp2)); LS_MONSTER, monst_to_any(mtmp2));
/* here we rely on the fact that `mtmp' hasn't actually been deleted /* here we rely on fact that `mtmp' hasn't actually been deleted */
*/
del_light_source(LS_MONSTER, monst_to_any(mtmp)); del_light_source(LS_MONSTER, monst_to_any(mtmp));
} }
mtmp2->nmon = fmon; mtmp2->nmon = fmon;
@@ -1445,10 +1445,10 @@ register struct monst *mtmp, *mtmp2;
maybe transfer it to one of the other monster lists */ maybe transfer it to one of the other monster lists */
void void
relmon(mon, monst_list) relmon(mon, monst_list)
register struct monst *mon; struct monst *mon;
struct monst **monst_list; /* &migrating_mons or &mydogs or null */ struct monst **monst_list; /* &migrating_mons or &mydogs or null */
{ {
register struct monst *mtmp; struct monst *mtmp;
boolean unhide = (monst_list != 0); boolean unhide = (monst_list != 0);
int mx = mon->mx, my = mon->my; int mx = mon->mx, my = mon->my;
@@ -1671,24 +1671,25 @@ register struct monst *mtmp;
if (is_vampshifter(mtmp)) { if (is_vampshifter(mtmp)) {
int mndx = mtmp->cham; int mndx = mtmp->cham;
int x = mtmp->mx, y = mtmp->my; int x = mtmp->mx, y = mtmp->my;
/* this only happens if shapeshifted */ /* this only happens if shapeshifted */
if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)) { if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)) {
char buf[BUFSZ]; char buf[BUFSZ];
boolean in_door = boolean in_door = (amorphous(mtmp->data)
amorphous(mtmp->data) && closed_door(mtmp->mx, mtmp->my); && closed_door(mtmp->mx, mtmp->my)),
/* alternate message phrasing for some monster types */
spec_mon = (nonliving(mtmp->data)
|| noncorporeal(mtmp->data)
|| amorphous(mtmp->data));
/* construct a format string before transformation */
Sprintf(buf, "The %s%s suddenly %s and rises as %%s!", Sprintf(buf, "The %s%s suddenly %s and rises as %%s!",
(nonliving(mtmp->data) || noncorporeal(mtmp->data) spec_mon ? "" : "seemingly dead ",
|| amorphous(mtmp->data))
? ""
: "seemingly dead ",
x_monnam(mtmp, ARTICLE_NONE, (char *) 0, x_monnam(mtmp, ARTICLE_NONE, (char *) 0,
SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION
| SUPPRESS_INVISIBLE | SUPPRESS_IT, | SUPPRESS_INVISIBLE | SUPPRESS_IT,
FALSE), FALSE),
(nonliving(mtmp->data) || noncorporeal(mtmp->data) spec_mon ? "reconstitutes" : "transforms");
|| amorphous(mtmp->data))
? "reconstitutes"
: "transforms");
mtmp->mcanmove = 1; mtmp->mcanmove = 1;
mtmp->mfrozen = 0; mtmp->mfrozen = 0;
if (mtmp->mhpmax <= 0) if (mtmp->mhpmax <= 0)
@@ -1699,6 +1700,7 @@ register struct monst *mtmp;
expels(mtmp, mtmp->data, FALSE); expels(mtmp, mtmp->data, FALSE);
if (in_door) { if (in_door) {
coord new_xy; coord new_xy;
if (enexto(&new_xy, mtmp->mx, mtmp->my, &mons[mndx])) { if (enexto(&new_xy, mtmp->mx, mtmp->my, &mons[mndx])) {
rloc_to(mtmp, new_xy.x, new_xy.y); rloc_to(mtmp, new_xy.x, new_xy.y);
} }
@@ -1708,8 +1710,10 @@ register struct monst *mtmp;
mtmp->cham = NON_PM; mtmp->cham = NON_PM;
else else
mtmp->cham = mndx; mtmp->cham = mndx;
if ((!Blind && canseemon(mtmp)) || sensemon(mtmp)) if (canspotmon(mtmp)) {
pline(buf, a_monnam(mtmp)); pline(buf, a_monnam(mtmp));
vamp_rise_msg = TRUE;
}
newsym(x, y); newsym(x, y);
return; return;
} }
@@ -1869,7 +1873,7 @@ register struct monst *mdef;
/* monster disappears, not dies */ /* monster disappears, not dies */
void void
mongone(mdef) mongone(mdef)
register struct monst *mdef; struct monst *mdef;
{ {
mdef->mhp = 0; /* can skip some inventory bookkeeping */ mdef->mhp = 0; /* can skip some inventory bookkeeping */
@@ -1880,7 +1884,6 @@ register struct monst *mdef;
/* hero is thrown from his steed when it disappears */ /* hero is thrown from his steed when it disappears */
if (mdef == u.usteed) if (mdef == u.usteed)
dismount_steed(DISMOUNT_GENERIC); dismount_steed(DISMOUNT_GENERIC);
/* drop special items like the Amulet so that a dismissed Kop or nurse /* drop special items like the Amulet so that a dismissed Kop or nurse
can't remove them from the game */ can't remove them from the game */
mdrop_special_objs(mdef); mdrop_special_objs(mdef);
@@ -1892,7 +1895,7 @@ register struct monst *mdef;
/* drop a statue or rock and remove monster */ /* drop a statue or rock and remove monster */
void void
monstone(mdef) monstone(mdef)
register struct monst *mdef; struct monst *mdef;
{ {
struct obj *otmp, *obj, *oldminvent; struct obj *otmp, *obj, *oldminvent;
xchar x = mdef->mx, y = mdef->my; xchar x = mdef->mx, y = mdef->my;
@@ -1920,11 +1923,13 @@ register struct monst *mdef;
if (obj->owornmask & W_WEP) if (obj->owornmask & W_WEP)
setmnotwielded(mdef, obj); setmnotwielded(mdef, obj);
obj->owornmask = 0L; obj->owornmask = 0L;
if (obj->otyp == BOULDER || if (obj->otyp == BOULDER
#if 0 /* monsters don't carry statues */ #if 0 /* monsters don't carry statues */
(obj->otyp == STATUE && mons[obj->corpsenm].msize >= mdef->data->msize) || || (obj->otyp == STATUE
&& mons[obj->corpsenm].msize >= mdef->data->msize)
#endif #endif
obj_resists(obj, 0, 0)) { /* invocation tools resist even with 0% resistance */
|| obj_resists(obj, 0, 0)) {
if (flooreffects(obj, x, y, "fall")) if (flooreffects(obj, x, y, "fall"))
continue; continue;
place_object(obj, x, y); place_object(obj, x, y);
@@ -1973,7 +1978,7 @@ register struct monst *mdef;
/* another monster has killed the monster mdef */ /* another monster has killed the monster mdef */
void void
monkilled(mdef, fltxt, how) monkilled(mdef, fltxt, how)
register struct monst *mdef; struct monst *mdef;
const char *fltxt; const char *fltxt;
int how; int how;
{ {
@@ -1999,7 +2004,7 @@ int how;
void void
unstuck(mtmp) unstuck(mtmp)
register struct monst *mtmp; struct monst *mtmp;
{ {
if (u.ustuck == mtmp) { if (u.ustuck == mtmp) {
if (u.uswallow) { if (u.uswallow) {
@@ -2018,7 +2023,7 @@ register struct monst *mtmp;
void void
killed(mtmp) killed(mtmp)
register struct monst *mtmp; struct monst *mtmp;
{ {
xkilled(mtmp, 1); xkilled(mtmp, 1);
} }
@@ -2027,11 +2032,8 @@ register struct monst *mtmp;
void void
xkilled(mtmp, dest) xkilled(mtmp, dest)
struct monst *mtmp; struct monst *mtmp;
/* int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
* Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse drop corpse either; dest==3, message but no corpse */
* either; dest=3, message but no corpse
*/
int dest;
{ {
int tmp, mndx, x = mtmp->mx, y = mtmp->my; int tmp, mndx, x = mtmp->mx, y = mtmp->my;
struct permonst *mdat; struct permonst *mdat;
@@ -2088,6 +2090,7 @@ int dest;
thrownobj = 0; thrownobj = 0;
} }
vamp_rise_msg = FALSE; /* might get set in mondead() */
/* dispose of monster and make cadaver */ /* dispose of monster and make cadaver */
if (stoned) if (stoned)
monstone(mtmp); monstone(mtmp);
@@ -2101,7 +2104,7 @@ int dest;
* appears). * appears).
*/ */
stoned = FALSE; stoned = FALSE;
if (!cansee(x, y)) if (!cansee(x, y) && !vamp_rise_msg)
pline("Maybe not..."); pline("Maybe not...");
return; return;
} }
@@ -2189,9 +2192,9 @@ cleanup:
adjalign(-(u.ualign.record + (int) ALIGNLIM / 2)); adjalign(-(u.ualign.record + (int) ALIGNLIM / 2));
pline("That was %sa bad idea...", pline("That was %sa bad idea...",
u.uevent.qcompleted ? "probably " : ""); u.uevent.qcompleted ? "probably " : "");
} else if (mdat->msound == MS_NEMESIS) /* Real good! */ } else if (mdat->msound == MS_NEMESIS) { /* Real good! */
adjalign((int) (ALIGNLIM / 4)); adjalign((int) (ALIGNLIM / 4));
else if (mdat->msound == MS_GUARDIAN) { /* Bad */ } else if (mdat->msound == MS_GUARDIAN) { /* Bad */
adjalign(-(int) (ALIGNLIM / 8)); adjalign(-(int) (ALIGNLIM / 8));
if (!Hallucination) if (!Hallucination)
pline("That was probably a bad idea..."); pline("That was probably a bad idea...");
@@ -2218,11 +2221,11 @@ cleanup:
adjalign(mtmp->malign); adjalign(mtmp->malign);
} }
/* changes the monster into a stone monster of the same type */ /* changes the monster into a stone monster of the same type
/* this should only be called when poly_when_stoned() is true */ this should only be called when poly_when_stoned() is true */
void void
mon_to_stone(mtmp) mon_to_stone(mtmp)
register struct monst *mtmp; struct monst *mtmp;
{ {
if (mtmp->data->mlet == S_GOLEM) { if (mtmp->data->mlet == S_GOLEM) {
/* it's a golem, and not a stone golem */ /* it's a golem, and not a stone golem */
@@ -2239,8 +2242,10 @@ register struct monst *mtmp;
impossible("Can't polystone %s!", a_monnam(mtmp)); impossible("Can't polystone %s!", a_monnam(mtmp));
} }
/* might place monst on far side of a wall or boulder */ /* make monster mtmp next to you (if possible);
void mnexto(mtmp) /* Make monster mtmp next to you (if possible) */ might place monst on far side of a wall or boulder */
void
mnexto(mtmp)
struct monst *mtmp; struct monst *mtmp;
{ {
coord mm; coord mm;
@@ -2303,10 +2308,10 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
xchar newx, newy; xchar newx, newy;
coord mm; coord mm;
if ((mtmp->mx == x) && (mtmp->my == y)) if (mtmp->mx == x && mtmp->my == y)
return FALSE; return FALSE;
if (move_other && (othermon = m_at(x, y))) { if (move_other && (othermon = m_at(x, y)) != 0) {
if (othermon->wormno) if (othermon->wormno)
remove_worm(othermon); remove_worm(othermon);
else else
@@ -2315,10 +2320,9 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
newx = x; newx = x;
newy = y; newy = y;
if (!goodpos(newx, newy, mtmp, 0)) { if (!goodpos(newx, newy, mtmp, 0)) {
/* actually we have real problems if enexto ever fails. /* Actually we have real problems if enexto ever fails.
* migrating_mons that need to be placed will cause * Migrating_mons that need to be placed will cause
* no end of trouble. * no end of trouble.
*/ */
if (!enexto(&mm, newx, newy, mtmp->data)) if (!enexto(&mm, newx, newy, mtmp->data))
@@ -2326,30 +2330,29 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
newx = mm.x; newx = mm.x;
newy = mm.y; newy = mm.y;
} }
rloc_to(mtmp, newx, newy); rloc_to(mtmp, newx, newy);
if (move_other && othermon) { if (move_other && othermon) {
xchar oldx = othermon->mx, oldy = othermon->my; xchar oldx = othermon->mx, oldy = othermon->my;
othermon->mx = othermon->my = 0; othermon->mx = othermon->my = 0;
if (!mnearto(othermon, x, y, FALSE)) { if (!mnearto(othermon, x, y, FALSE)) {
othermon->mx = oldx; othermon->mx = oldx;
othermon->my = oldy; othermon->my = oldy;
return FALSE; return FALSE;
} }
if (othermon->mx != x || othermon->my != y)
if ((othermon->mx != x) || (othermon->my != y))
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
/* monster responds to player action; not the same as a passive attack */ /* monster responds to player action; not the same as a passive attack;
/* assumes reason for response has been tested, and response _must_ be made */ assumes reason for response has been tested, and response _must_ be made */
void void
m_respond(mtmp) m_respond(mtmp)
register struct monst *mtmp; struct monst *mtmp;
{ {
if (mtmp->data->msound == MS_SHRIEK) { if (mtmp->data->msound == MS_SHRIEK) {
if (!Deaf) { if (!Deaf) {
@@ -2366,6 +2369,7 @@ register struct monst *mtmp;
} }
if (mtmp->data == &mons[PM_MEDUSA]) { if (mtmp->data == &mons[PM_MEDUSA]) {
register int i; register int i;
for (i = 0; i < NATTK; i++) for (i = 0; i < NATTK; i++)
if (mtmp->data->mattk[i].aatyp == AT_GAZE) { if (mtmp->data->mattk[i].aatyp == AT_GAZE) {
(void) gazemu(mtmp, &mtmp->data->mattk[i]); (void) gazemu(mtmp, &mtmp->data->mattk[i]);
@@ -2376,7 +2380,7 @@ register struct monst *mtmp;
void void
setmangry(mtmp) setmangry(mtmp)
register struct monst *mtmp; struct monst *mtmp;
{ {
mtmp->mstrategy &= ~STRAT_WAITMASK; mtmp->mstrategy &= ~STRAT_WAITMASK;
if (!mtmp->mpeaceful) if (!mtmp->mpeaceful)
@@ -2423,6 +2427,7 @@ register struct monst *mtmp;
} }
} }
/* wake up a monster, usually making it angry in the process */
void void
wakeup(mtmp) wakeup(mtmp)
register struct monst *mtmp; register struct monst *mtmp;
@@ -2521,8 +2526,8 @@ rescham()
new_were(mtmp); new_were(mtmp);
if (mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my)) { if (mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my)) {
seemimic(mtmp); seemimic(mtmp);
/* we pretend that the mimic doesn't */ /* we pretend that the mimic doesn't
/* know that it has been unmasked. */ know that it has been unmasked */
mtmp->msleeping = 1; mtmp->msleeping = 1;
} }
} }
@@ -2568,30 +2573,30 @@ struct monst *mon;
} }
} }
/* unwatched hiders may hide again; if so, a 1 is returned. */ /* unwatched hiders may hide again; if so, returns True */
STATIC_OVL boolean STATIC_OVL boolean
restrap(mtmp) restrap(mtmp)
register struct monst *mtmp; register struct monst *mtmp;
{ {
struct trap *t; struct trap *t;
if (mtmp->mcan || mtmp->m_ap_type || cansee(mtmp->mx, mtmp->my) || rn2(3) if (mtmp->mcan || mtmp->m_ap_type || cansee(mtmp->mx, mtmp->my)
|| (mtmp == u.ustuck) || || rn2(3) || mtmp == u.ustuck
/* can't hide while trapped except in pits */ /* can't hide while trapped except in pits */
(mtmp->mtrapped && (t = t_at(mtmp->mx, mtmp->my)) != 0 || (mtmp->mtrapped && (t = t_at(mtmp->mx, mtmp->my)) != 0
&& !(t->ttyp == PIT || t->ttyp == SPIKED_PIT)) && !(t->ttyp == PIT || t->ttyp == SPIKED_PIT))
|| (sensemon(mtmp) && distu(mtmp->mx, mtmp->my) <= 2)) || (sensemon(mtmp) && distu(mtmp->mx, mtmp->my) <= 2))
return (FALSE); return FALSE;
if (mtmp->data->mlet == S_MIMIC) { if (mtmp->data->mlet == S_MIMIC) {
set_mimic_sym(mtmp); set_mimic_sym(mtmp);
return (TRUE); return TRUE;
} else if (levl[mtmp->mx][mtmp->my].typ == ROOM) { } else if (levl[mtmp->mx][mtmp->my].typ == ROOM) {
mtmp->mundetected = 1; mtmp->mundetected = 1;
return (TRUE); return TRUE;
} }
return (FALSE); return FALSE;
} }
/* monster/hero tries to hide under something at the current location */ /* monster/hero tries to hide under something at the current location */
@@ -2895,7 +2900,8 @@ struct monst *mon;
mndx = (int) (Dragon_scales_to_pm(m_armr) - mons); mndx = (int) (Dragon_scales_to_pm(m_armr) - mons);
else if (m_armr && Is_dragon_mail(m_armr)) else if (m_armr && Is_dragon_mail(m_armr))
mndx = (int) (Dragon_mail_to_pm(m_armr) - mons); mndx = (int) (Dragon_mail_to_pm(m_armr) - mons);
} break; }
break;
} }
/* for debugging: allow control of polymorphed monster */ /* for debugging: allow control of polymorphed monster */
if (wizard && iflags.mon_polycontrol) { if (wizard && iflags.mon_polycontrol) {
@@ -3039,7 +3045,7 @@ boolean msg; /* "The oldmon turns into a newmon!" */
if (!tryct) if (!tryct)
return 0; return 0;
} else if (mvitals[monsndx(mdat)].mvflags & G_GENOD) } else if (mvitals[monsndx(mdat)].mvflags & G_GENOD)
return (0); /* passed in mdat is genocided */ return 0; /* passed in mdat is genocided */
mgender_from_permonst(mtmp, mdat); mgender_from_permonst(mtmp, mdat);
@@ -3051,13 +3057,13 @@ boolean msg; /* "The oldmon turns into a newmon!" */
* reasonable. * reasonable.
*/ */
char *p = index(MNAME(mtmp), ' '); char *p = index(MNAME(mtmp), ' ');
if (p) {
if (p)
*p = '\0'; *p = '\0';
} }
}
if (mdat == mtmp->data) if (mdat == mtmp->data)
return (0); /* still the same monster */ return 0; /* still the same monster */
if (mtmp->wormno) { /* throw tail away */ if (mtmp->wormno) { /* throw tail away */
wormgone(mtmp); wormgone(mtmp);
@@ -3190,7 +3196,7 @@ boolean msg; /* "The oldmon turns into a newmon!" */
} }
} }
return (1); return 1;
} }
/* sometimes an egg will be special */ /* sometimes an egg will be special */
@@ -3239,13 +3245,18 @@ boolean force_ordinary;
return mnum; return mnum;
} }
/* decide whether an egg of the indicated monster type is viable; */ /* decide whether an egg of the indicated monster type is viable;
/* also used to determine whether an egg or tin can be created... */ also used to determine whether an egg or tin can be created... */
boolean boolean
dead_species(m_idx, egg) dead_species(m_idx, egg)
int m_idx; int m_idx;
boolean egg; boolean egg;
{ {
int alt_idx;
/* generic eggs are unhatchable and have corpsenm of NON_PM */
if (m_idx < LOW_PM)
return TRUE;
/* /*
* For monsters with both baby and adult forms, genociding either * For monsters with both baby and adult forms, genociding either
* form kills all eggs of that monster. Monsters with more than * form kills all eggs of that monster. Monsters with more than
@@ -3253,11 +3264,9 @@ boolean egg;
* fortunately, none of them have eggs. Species extinction due to * fortunately, none of them have eggs. Species extinction due to
* overpopulation does not kill eggs. * overpopulation does not kill eggs.
*/ */
return (boolean)( alt_idx = egg ? big_to_little(m_idx) : m_idx;
m_idx >= LOW_PM return (boolean) ((mvitals[m_idx].mvflags & G_GENOD) != 0
&& ((mvitals[m_idx].mvflags & G_GENOD) != 0 || (mvitals[alt_idx].mvflags & G_GENOD) != 0);
|| (egg
&& (mvitals[big_to_little(m_idx)].mvflags & G_GENOD) != 0)));
} }
/* kill off any eggs of genocided monsters */ /* kill off any eggs of genocided monsters */
@@ -3315,8 +3324,8 @@ kill_genocided_monsters()
if (DEADMONSTER(mtmp)) if (DEADMONSTER(mtmp))
continue; continue;
mndx = monsndx(mtmp->data); mndx = monsndx(mtmp->data);
kill_cham = kill_cham = (mtmp->cham >= LOW_PM
(mtmp->cham >= LOW_PM && (mvitals[mtmp->cham].mvflags & G_GENOD)); && (mvitals[mtmp->cham].mvflags & G_GENOD));
if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham) { if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham) {
if (mtmp->cham >= LOW_PM && !kill_cham) if (mtmp->cham >= LOW_PM && !kill_cham)
(void) newcham(mtmp, (struct permonst *) 0, FALSE, FALSE); (void) newcham(mtmp, (struct permonst *) 0, FALSE, FALSE);
@@ -3370,10 +3379,10 @@ int damtype, dam;
boolean boolean
angry_guards(silent) angry_guards(silent)
register boolean silent; boolean silent;
{ {
register struct monst *mtmp; struct monst *mtmp;
register int ct = 0, nct = 0, sct = 0, slct = 0; int ct = 0, nct = 0, sct = 0, slct = 0;
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) if (DEADMONSTER(mtmp))
@@ -3408,15 +3417,15 @@ register boolean silent;
} else } else
You_hear("the shrill sound of a guard's whistle."); You_hear("the shrill sound of a guard's whistle.");
} }
return (TRUE); return TRUE;
} }
return (FALSE); return FALSE;
} }
void void
pacify_guards() pacify_guards()
{ {
register struct monst *mtmp; struct monst *mtmp;
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) if (DEADMONSTER(mtmp))
@@ -3563,7 +3572,7 @@ struct permonst *mdat;
break; break;
} }
} }
return (msg_given) ? TRUE : FALSE; return msg_given ? TRUE : FALSE;
} }
/*mon.c*/ /*mon.c*/