home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
nethack2.3
/
part06
/
mon.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-10-17
|
21KB
|
837 lines
/* SCCS Id: @(#)mon.c 2.3 87/12/12
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
#include "hack.h"
#include "mfndpos.h"
extern struct monst *makemon(), *mkmon_at();
extern struct trap *maketrap();
extern struct obj *mkobj_at(), *mksobj_at();
extern char *hcolor();
#ifdef KAA
extern boolean stoned;
extern char mlarge[];
#endif
#ifdef RPH
extern struct obj *mk_named_obj_at();
#endif
int warnlevel; /* used by movemon and dochugw */
long lastwarntime;
int lastwarnlev;
char *warnings[] = { "white", "pink", "red", "ruby", "purple", "black" };
movemon()
{
register struct monst *mtmp;
register int fr;
warnlevel = 0;
while(1) {
/* find a monster that we haven't treated yet */
/* note that mtmp or mtmp->nmon might get killed
while mtmp moves, so we cannot just walk down the
chain (even new monsters might get created!) */
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
if(mtmp->mlstmv < moves) goto next_mon;
/* treated all monsters */
break;
next_mon:
mtmp->mlstmv = moves;
/* most monsters drown in pools */
{ boolean inpool,infountain,iseel,isgremlin;
extern struct permonst pm_gremlin;
inpool = (levl[mtmp->mx][mtmp->my].typ == POOL);
iseel = (mtmp->data->mlet == ';');
isgremlin = (mtmp->data->mlet == 'G' && mtmp->isgremlin);
infountain = (levl[mtmp->mx][mtmp->my].typ == FOUNTAIN);
if((inpool || infountain) && isgremlin && rn2(3)) {
coord mm;
enexto(&mm, mtmp->mx, mtmp->my);
if(cansee(mtmp->mx,mtmp->my) &&
makemon(PM_GREMLIN, mm.x, mm.y))
pline("%s multiplies.", Monnam(mtmp));
if (infountain) dryup();
}
if(inpool && !iseel && !isgremlin) {
if(cansee(mtmp->mx,mtmp->my))
pline("%s drowns.", Monnam(mtmp));
mondead(mtmp);
continue;
}
/* but eels have a difficult time outside */
if(iseel && !inpool) {
if(mtmp->mhp > 1) mtmp->mhp--;
mtmp->mflee = 1;
mtmp->mfleetim += 2;
}
}
if(mtmp->mblinded && !--mtmp->mblinded)
mtmp->mcansee = 1;
if(mtmp->mfleetim && !--mtmp->mfleetim)
mtmp->mflee = 0;
#ifdef HARD
/* unwatched mimics and piercers may hide again [MRS] */
if(restrap(mtmp)) continue;
#endif
if(mtmp->mimic) continue;
if(mtmp->mspeed != MSLOW || !(moves%2)){
/* continue if the monster died fighting */
fr = -1;
if(Conflict && cansee(mtmp->mx,mtmp->my)
&& (fr = fightm(mtmp)) == 2)
continue;
#ifdef STOOGES
if((mtmp->isstooge) && cansee(mtmp->mx,mtmp->my)
&& (fr = fightm(mtmp)) == 2)
continue;
#endif
if(fr<0 && dochugw(mtmp))
continue;
}
if(mtmp->mspeed == MFAST && dochugw(mtmp))
continue;
}
warnlevel -= u.ulevel;
if(warnlevel >= SIZE(warnings))
warnlevel = SIZE(warnings)-1;
if(warnlevel >= 0)
if(warnlevel > lastwarnlev || moves > lastwarntime + 5){
register char *rr;
switch((int) (Warning & (LEFT_RING | RIGHT_RING))){
case LEFT_RING:
rr = "Your left ring glows";
break;
case RIGHT_RING:
rr = "Your right ring glows";
break;
case LEFT_RING | RIGHT_RING:
rr = "Both your rings glow";
break;
default:
rr = "Your fingertips glow";
break;
}
pline("%s %s!", rr, Hallucination ? hcolor() : warnings[warnlevel]);
lastwarntime = moves;
lastwarnlev = warnlevel;
}
dmonsfree(); /* remove all dead monsters */
}
justswld(mtmp,name)
register struct monst *mtmp;
char *name;
{
mtmp->mx = u.ux;
mtmp->my = u.uy;
u.ustuck = mtmp;
pmon(mtmp);
kludge("%s swallows you!",name);
more();
seeoff(1);
u.uswallow = 1;
u.uswldtim = 0;
swallowed();
}
youswld(mtmp,dam,die,name)
register struct monst *mtmp;
register dam,die;
char *name;
{
if(mtmp != u.ustuck) return;
kludge("%s digests you!",name);
u.uhp -= dam;
if(u.uswldtim++ >= die){ /* a3 */
pline("It totally digests you!");
u.uhp = -1;
}
if(u.uhp < 1) done_in_by(mtmp);
/* flags.botlx = 1; /* should we show status line ? */
}
#ifdef ROCKMOLE
meatgold(mtmp) register struct monst *mtmp; {
register struct gold *gold;
register int pile;
register struct obj *otmp;
#ifdef KJSMODS
if(dlevel < 4) return;
#endif
/* Eats gold if it is there */
while(gold = g_at(mtmp->mx, mtmp->my)){
freegold(gold);
/* Left behind a pile? */
pile = rnd(25);
if(pile < 3) mksobj_at(ROCK, mtmp->mx, mtmp->my);
newsym(mtmp->mx, mtmp->my);
}
/* Eats armor if it is there */
otmp = o_at(mtmp->mx,mtmp->my);
if((otmp) && (otmp->otyp >= PLATE_MAIL) && (otmp->otyp <= RING_MAIL)){
freeobj(otmp);
/* Left behind a pile? */
pile = rnd(25);
if(pile < 3) mksobj_at(ROCK, mtmp->mx, mtmp->my);
newsym(mtmp->mx, mtmp->my);
}
}
#endif /* ROCKMOLE /**/
mpickgold(mtmp) register struct monst *mtmp; {
register struct gold *gold;
while(gold = g_at(mtmp->mx, mtmp->my)){
mtmp->mgold += gold->amount;
freegold(gold);
if(levl[mtmp->mx][mtmp->my].scrsym == GOLD_SYM)
newsym(mtmp->mx, mtmp->my);
}
}
/* Now includes giants which pick up enormous rocks. KAA */
mpickgems(mtmp) register struct monst *mtmp; {
register struct obj *otmp;
for(otmp = fobj; otmp; otmp = otmp->nobj)
if(otmp->olet ==
#ifdef KAA
(mtmp->data->mlet=='9' ? ROCK_SYM : GEM_SYM))
#else
GEM_SYM)
#endif
if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my)
if(mtmp->data->mlet != 'u' || objects[otmp->otyp].g_val != 0){
freeobj(otmp);
mpickobj(mtmp, otmp);
#ifndef KAA
if(levl[mtmp->mx][mtmp->my].scrsym == GEM_SYM)
#endif
newsym(mtmp->mx, mtmp->my); /* %% */
return; /* pick only one object */
}
}
/* return number of acceptable neighbour positions */
mfndpos(mon,poss,info,flag)
register struct monst *mon;
coord poss[9];
long info[9], flag;
{
register int x,y,nx,ny,cnt = 0,ntyp;
register struct monst *mtmp;
int nowtyp;
boolean pool;
x = mon->mx;
y = mon->my;
nowtyp = levl[x][y].typ;
pool = (mon->data->mlet == ';');
nexttry: /* eels prefer the water, but if there is no water nearby,
they will crawl over land */
if(mon->mconf) {
flag |= ALLOW_ALL;
flag &= ~NOTONL;
}
for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++)
if(nx != x || ny != y) if(isok(nx,ny))
#ifdef ROCKMOLE
if(!IS_ROCK(ntyp = levl[nx][ny].typ) || (flag & ALLOW_WALL))
#else
if(!IS_ROCK(ntyp = levl[nx][ny].typ))
#endif
if(!(nx != x && ny != y && (nowtyp == DOOR || ntyp == DOOR)))
if((ntyp == POOL) == pool) {
info[cnt] = 0;
if(nx == u.ux && ny == u.uy){
if(!(flag & ALLOW_U)) continue;
info[cnt] = ALLOW_U;
} else if(mtmp = m_at(nx,ny)){
if(!(flag & ALLOW_M)) continue;
info[cnt] = ALLOW_M;
if(mtmp->mtame){
if(!(flag & ALLOW_TM)) continue;
info[cnt] |= ALLOW_TM;
}
}
if(sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
if(flag & NOGARLIC) continue;
info[cnt] |= NOGARLIC;
}
if(sobj_at(SCR_SCARE_MONSTER, nx, ny) ||
(!mon->mpeaceful && sengr_at("Elbereth", nx, ny))) {
if(!(flag & ALLOW_SSM)) continue;
info[cnt] |= ALLOW_SSM;
}
if(sobj_at(ENORMOUS_ROCK, nx, ny)) {
if(!(flag & ALLOW_ROCK)) continue;
info[cnt] |= ALLOW_ROCK;
}
if(!Invis && online(nx,ny)){
if(flag & NOTONL) continue;
info[cnt] |= NOTONL;
}
/* we cannot avoid traps of an unknown kind */
{ register struct trap *ttmp = t_at(nx, ny);
register long tt;
if(ttmp) {
/* tt = 1L << ttmp->ttyp;*/
/* why don't we just have code look like what it's supposed to do? then it
/* might start working for every case. try this instead: -sac */
tt = (ttmp->ttyp < TRAPNUM && ttmp->ttyp > 0);
/* below if added by GAN 02/06/87 to avoid
* traps out of range
*/
if(!(tt & ALLOW_TRAPS)) {
impossible("A monster looked at a very strange trap of type %d.", ttmp->ttyp);
continue;
}
if(mon->mtrapseen & tt){
if(!(flag & tt)) continue;
info[cnt] |= tt;
}
}
}
poss[cnt].x = nx;
poss[cnt].y = ny;
cnt++;
}
if(!cnt && pool && nowtyp != POOL) {
pool = FALSE;
goto nexttry;
}
return(cnt);
}
dist(x,y) int x,y; {
return((x-u.ux)*(x-u.ux) + (y-u.uy)*(y-u.uy));
}
poisoned(string, pname)
register char *string, *pname;
{
register i, plural;
plural = (string[strlen(string) - 1] == 's')? 1 : 0;
if(Blind) {
if (plural) pline("They were poisoned.");
else pline("It was poisoned.");
} else {
if (plural) pline("The %s were poisoned!", string);
else pline("The %s was poisoned!", string);
}
if(Poison_resistance) {
pline("The poison doesn't seem to affect you.");
return;
}
i = rn2(10);
if(i == 0) {
u.uhp = -1;
pline("I am afraid the poison was deadly ...");
} else if(i <= 5) {
losestr(rn1(3,3));
} else {
losehp(rn1(10,6), pname);
}
if(u.uhp < 1) {
killer = pname;
done("died");
}
}
mondead(mtmp)
register struct monst *mtmp;
{
relobj(mtmp,1);
unpmon(mtmp);
relmon(mtmp);
unstuck(mtmp);
#ifdef KOPS
if(mtmp->data->mlet == 'K' &&
!strcmp(mtmp->data->mname,"Keystone Kop")) {
/* When a Kop dies, he probably comes back. */
switch(rnd(3)) {
case 1: /* returns near the stairs */
mkmon_at('K',xdnstair,ydnstair);
break;
case 2: /* randomly */
mkmon_at('K',0,0);
break;
default:
break;
}
}
#endif
if(mtmp->isshk) shkdead(mtmp);
if(mtmp->isgd) gddead();
#ifndef NOWORM
if(mtmp->wormno) wormdead(mtmp);
#endif
#ifdef HARD
if(mtmp->data->mlet == '1') wizdead(mtmp);
#endif
monfree(mtmp);
}
/* called when monster is moved to larger structure */
replmon(mtmp,mtmp2)
register struct monst *mtmp, *mtmp2;
{
relmon(mtmp);
monfree(mtmp);
mtmp2->nmon = fmon;
fmon = mtmp2;
if(u.ustuck == mtmp) u.ustuck = mtmp2;
if(mtmp2->isshk) replshk(mtmp,mtmp2);
if(mtmp2->isgd) replgd(mtmp,mtmp2);
}
relmon(mon)
register struct monst *mon;
{
register struct monst *mtmp;
if (fmon == 0) panic ("relmon: no fmon available.");
if(mon == fmon) fmon = fmon->nmon;
else {
for(mtmp = fmon; mtmp && mtmp->nmon != mon; mtmp = mtmp->nmon) ;
mtmp->nmon = mon->nmon;
}
}
/* we do not free monsters immediately, in order to have their name
available shortly after their demise */
struct monst *fdmon; /* chain of dead monsters, need not to be saved */
monfree(mtmp) register struct monst *mtmp; {
mtmp->nmon = fdmon;
fdmon = mtmp;
}
dmonsfree(){
register struct monst *mtmp;
while(mtmp = fdmon){
fdmon = mtmp->nmon;
free((char *) mtmp);
}
}
unstuck(mtmp)
register struct monst *mtmp;
{
if(u.ustuck == mtmp) {
if(u.uswallow){
u.ux = mtmp->mx;
u.uy = mtmp->my;
u.uswallow = 0;
setsee();
docrt();
}
u.ustuck = 0;
}
}
killed(mtmp)
register struct monst *mtmp;
{
xkilled(mtmp, 1);
}
xkilled(mtmp, dest)
register struct monst *mtmp;
int dest;
/* Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse
either; dest=3, message but no corpse */
{
#ifdef LINT
#define NEW_SCORING
#endif
register int tmp,tmp2,nk,x,y;
register struct permonst *mdat = mtmp->data;
extern long newuexp();
#ifdef RPH
int old_nlth;
char old_name[BUFSZ];
#endif
if(mtmp->cham) mdat = PM_CHAMELEON;
if (dest & 1) {
if(Blind) pline("You destroy it!");
else {
pline("You destroy %s!",
mtmp->mtame ? amonnam(mtmp, "poor") : monnam(mtmp));
}
}
if(u.umconf) {
if(!Blind)
{
pline("Your hands stop glowing %s.",
Hallucination ? hcolor() : "blue");
}
u.umconf = 0;
}
/* count killed monsters */
#define MAXMONNO 100
nk = 1; /* in case we cannot find it in mons */
tmp = mdat - mons; /* index in mons array (if not 'd', '@', ...) */
if(tmp >= 0 && tmp < CMNUM+2) {
extern char fut_geno[];
u.nr_killed[tmp]++;
if((nk = u.nr_killed[tmp]) > MAXMONNO &&
#ifdef HARD
# ifdef KOPS
!index("KkO&", mdat->mlet) &&
# else
!index("kO&", mdat->mlet) &&
# endif
#endif
!index(fut_geno, mdat->mlet))
charcat(fut_geno, mdat->mlet);
}
/* punish bad behaviour */
if(mdat->mlet == '@') {
HTelepat = 0;
change_luck(-2);
}
if(mtmp->mpeaceful || mtmp->mtame) change_luck(-1);
if(mdat->mlet == 'u') change_luck(-5);
/* give experience points */
tmp = 1 + mdat->mlevel * mdat->mlevel;
if(mdat->ac < 3) tmp += 2*(7 - mdat->ac);
if(index("AcsSDXaeRTVWU&In:P389",mdat->mlet)) tmp += 2*mdat->mlevel;
if(index("DeV&P",mdat->mlet)) tmp += (7*mdat->mlevel);
if(mdat->mlevel > 6) tmp += 50;
if(mdat->mlet == ';') tmp += 1000;
#ifdef NEW_SCORING
/* ------- recent addition: make nr of points decrease
when this is not the first of this kind */
{ int ul = u.ulevel;
int ml = mdat->mlevel;
if(ul < 14) /* points are given based on present and future level */
for(tmp2 = 0; !tmp2 || ul + tmp2 <= ml; tmp2++)
if(u.uexp + 1 + (tmp + ((tmp2 <= 0) ? 0 : 4<<(tmp2-1)))/nk
>= 10*pow((unsigned)(ul-1)))
if(++ul == 14) break;
tmp2 = ml - ul -1;
tmp = (tmp + ((tmp2 < 0) ? 0 : 4<<tmp2))/nk;
if(!tmp) tmp = 1;
}
/* note: ul is not necessarily the future value of u.ulevel */
/* ------- end of recent valuation change ------- */
#endif /* NEW_SCORING /**/
more_experienced(tmp,0);
flags.botl = 1;
while(u.ulevel < 14 && u.uexp >= newuexp()){
#ifdef RPH
/* make experience gaining simiar to d&d, whereby you */
/* can at most go up by one level at a time, extra expr */
/* possibly helping you along. Afterall, how much real */
/* experience does one get shooting a wand of death at */
/* a dragon created w/ a poymorph?? */
u.ulevel++;
if (u.uexp >= newuexp())
u.uexp = newuexp() - 1;
pline("Welcome to experience level %u.", u.ulevel);
#else
pline("Welcome to experience level %u.", ++u.ulevel);
#endif
tmp = rnd(10);
if(tmp < 3) tmp = rnd(10);
u.uhpmax += tmp;
u.uhp += tmp;
#ifdef SPELLS
tmp = rnd(u.ulevel/2+1) + 1; /* M. Stephenson */
u.uenmax += tmp;
u.uen += tmp;
#endif
flags.botl = 1;
}
/* dispose of monster and make cadaver */
x = mtmp->mx; y = mtmp->my;
#ifdef RPH
old_nlth = mtmp->mnamelth;
if (old_nlth > 0) (void) strcpy (old_name, NAME(mtmp));
#endif
if (mdat->mlet == '&' && mtmp->isdjinni) { /* no djinni corpse */
mondead(mtmp);
return;
}
if (mdat->mlet == 'G' && mtmp->isgremlin) { /* no gremlin corpse */
mondead(mtmp);
return;
}
mondead(mtmp);
tmp = mdat->mlet;
if(tmp == 'm') { /* he killed a minotaur, give him a wand of digging */
/* note: the dead minotaur will be on top of it! */
mksobj_at(WAN_DIGGING, x, y);
/* if(cansee(x,y)) atl(x,y,fobj->olet); */
stackobj(fobj);
} else
#ifndef NOWORM
if(tmp == 'w') {
mksobj_at(WORM_TOOTH, x, y);
stackobj(fobj);
} else
#endif
#ifdef KJSMODS
if(tmp == 'N') {
mksobj_at(POT_OBJECT_DETECTION, x, y);
stackobj(fobj);
} else
#endif
#ifdef SAC
if(tmp == '3') {
; /* don't do anything special- keep it from failing on */
/* call to letter(tmp) */
} else
#endif /* SAC */
#ifdef KAA
if(tmp == '&') (void) mkobj_at(0, x, y);
else
if(stoned == FALSE && (!letter(tmp) || (!index("9&1", tmp) && !rn2(3)))) tmp = 0;
if(dest & 2) {
newsym(x,y);
return;
}
#else
if(!letter(tmp) || (!index("mw", tmp) && !rn2(3))) tmp = 0;
#endif
tmp2 = rn2(5);
#ifdef KJSMODS
/* if a kobold or a giant rat does not become treasure, do
* not make a corpse. */
# ifdef KOPS
if(mdat->mlet == 'K'
&& !strcmp(mdat->mname,"kobold") && tmp) tmp2 = 0;
# endif
# ifdef ROCKMOLE
if((mdat->mlet == 'r' && dlevel < 4) && tmp) tmp2 = 0;
# endif
#endif
if(!ACCESSIBLE(levl[x][y].typ)) {
/* might be mimic in wall or dead eel*/
newsym(x,y);
} else if(x != u.ux || y != u.uy) {
/* might be here after swallowed */
#ifdef KAA
if(stoned) {
register int typetmp;
if(index(mlarge, tmp)) typetmp = ENORMOUS_ROCK;
else typetmp = ROCK;
mksobj_at(typetmp, x, y);
if(cansee(x,y))
atl(x, y, Hallucination ? rndobjsym() :
objects[typetmp].oc_olet);
} else
#endif
if(index("NTVm&w",mdat->mlet) || tmp2) {
#ifndef RPH
register struct obj *obj2 = mkobj_at(tmp,x,y);
#else
register struct obj *obj2;
if (letter(tmp))
obj2 = mk_named_obj_at(tmp, x, y,
old_name, old_nlth);
# ifdef KOPS
else if (mdat->mlet == 'K')
obj2 = mksobj_at((rn2(2) ? CLUB :
(rn2(2)) ? WHISTLE : BADGE), x, y);
# endif
else
obj2 = mkobj_at(tmp,x,y);
#endif /* RPH /**/
if(cansee(x,y))
atl(x, y, Hallucination ? rndobjsym() : obj2->olet);
stackobj(obj2);
}
}
}
kludge(str,arg)
register char *str,*arg;
{
if(Blind) {
if(*str == '%') pline(str,"It");
else pline(str,"it");
} else pline(str,arg);
}
rescham() /* force all chameleons to become normal */
{
register struct monst *mtmp;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
if(mtmp->cham) {
mtmp->cham = 0;
(void) newcham(mtmp, PM_CHAMELEON);
}
}
#ifdef DGKMOD
/* Let the chameleons change again -dgk */
restartcham()
{
register struct monst *mtmp;
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
if (mtmp->data->mlet == ':')
mtmp->cham = 1;
}
#endif
newcham(mtmp,mdat) /* make a chameleon look like a new monster */
/* returns 1 if the monster actually changed */
register struct monst *mtmp;
register struct permonst *mdat;
{
register mhp, hpn, hpd;
#ifdef RPH
/* mdat = 0 -> caller wants a random monster shape */
if (mdat == 0) {
/* ie. minimum shape is mons[15], minimum random range */
/* is 3, and randomness tails off as you descend into the */
/* depths max shape is mons[CMNUM-1] */
mdat = &mons[CMNUM-1-rn2((CMNUM-17) - (CMNUM-20)*dlevel/MAXLEVEL)];
}
#endif
if(mdat == mtmp->data) return(0); /* still the same monster */
#ifndef NOWORM
if(mtmp->wormno) wormdead(mtmp); /* throw tail away */
#endif
hpn = mtmp->mhp;
hpd = (mtmp->data->mlevel)*8; if(!hpd) hpd = 4;
mhp = (mdat->mlevel)*8; if(!mhp) mhp = 4;
/* new hp: same fraction of max as before */
mtmp->mhp = (hpn*mhp)/hpd;
if (mhp > hpd && mtmp->mhp < hpn) mtmp->mhp = 127;
/* Not totally foolproof. A 2HD monster with 80 HP that changes into a 6HD
monster that really should have 240 and actually should have 127, the
maximum possible, will wind up having 113. */
if (!mtmp->mhp) mtmp->mhp = 1;
/* Unlikely but not impossible; a 1HD creature with 1HP that changes into a
0HD creature will require this statement */
mtmp->data = mdat;
/* and the same for maximum hit points */
hpn = mtmp->mhpmax;
mtmp->mhpmax = (hpn*mhp)/hpd;
if (mhp > hpd && mtmp->mhpmax < hpn) mtmp->mhp = 127;
if (!mtmp->mhp) mtmp->mhp = 1;
mtmp->minvis = (mdat->mlet == 'I') ? 1 : 0;
/* only snakes and scorpions can hide under things -dgk */
/* also generated by GAN */
mtmp->mhide = (mdat->mlet == 'S' || mdat->mlet == 's') ? 1 : 0;
if (!mtmp->mhide) mtmp->mundetected = 0;
#ifndef NOWORM
if(mdat->mlet == 'w' && getwn(mtmp)) initworm(mtmp);
/* perhaps we should clear mtmp->mtame here? */
#endif
unpmon(mtmp); /* necessary for 'I' and to force pmon */
pmon(mtmp);
return(1);
}
mnexto(mtmp) /* Make monster mtmp next to you (if possible) */
struct monst *mtmp;
{
coord mm;
enexto(&mm, u.ux, u.uy);
mtmp->mx = mm.x;
mtmp->my = mm.y;
pmon(mtmp);
}
ishuman(mtmp) register struct monst *mtmp; {
return(mtmp->data->mlet == '@');
}
setmangry(mtmp) register struct monst *mtmp; {
if(!mtmp->mpeaceful) return;
if(mtmp->mtame) return;
mtmp->mpeaceful = 0;
if(ishuman(mtmp)) pline("%s gets angry!", Monnam(mtmp));
}
/* not one hundred procent correct: now a snake may hide under an
invisible object */
canseemon(mtmp)
register struct monst *mtmp;
{
return((!mtmp->minvis || See_invisible)
&& (!mtmp->mhide || !o_at(mtmp->mx,mtmp->my))
&& cansee(mtmp->mx, mtmp->my));
}
disturb(mtmp) /* awaken monsters while in the same room.
* return a 1 if they have been woken.
*/
register struct monst *mtmp;
{
/* wake up, or get out of here. */
/* ettins are hard to surprise */
/* Nymphs and Leprechauns do not easily wake up */
if(cansee(mtmp->mx,mtmp->my) &&
(!Stealth || (mtmp->data->mlet == 'e' && rn2(10))) &&
(!index("NL",mtmp->data->mlet) || !rn2(50)) &&
#ifdef RPH
(Aggravate_monster || index("8d1", mtmp->data->mlet)
#else
(Aggravate_monster || index("d1", mtmp->data->mlet)
#endif
|| (!rn2(7) && !mtmp->mimic))) {
mtmp->msleep = 0;
return(1);
}
if(Hallucination) pmon(mtmp);
return(0);
}
#ifdef HARD
restrap(mtmp) /* unwatched mimics and piercers may hide again,
* if so, a 1 is returned.
*/
register struct monst *mtmp;
{
if(mtmp->data->mlet == 'M' && !mtmp->mimic && !mtmp->cham
&& !mtmp->mcan && !cansee(mtmp->mx, mtmp->my)
&& !rn2(3)) {
mtmp->mimic = 1;
mtmp->mappearance = (levl[mtmp->mx][mtmp->my].typ == DOOR) ? DOOR_SYM : GOLD_SYM;
return(1);
}
if(mtmp->data->mlet == 'p' && !mtmp->cham
&& !mtmp->mcan && !cansee(mtmp->mx, mtmp->my)
&& !rn2(3)) {
if(levl[mtmp->mx][mtmp->my].typ == ROOM) {
maketrap(mtmp->mx, mtmp->my, PIERC);
mondead(mtmp);
return(1);
}
}
return(0);
}
#endif