# 2.11BSD#431 - /usr/src/games/hack/hack.mon.c

##### Functions

    canseemon         X
    dist              X
    dmonsfree         X
    dochug            X
    dochugw           X
    ishuman           X
    justswld          X
    killed            X
    kludge            X
    m_move            X
    mfndpos           X
    mnexto            X
    mondead           X
    monfree           X
    movemon           X
    mpickgems         X
    mpickgold         X
    newcham           X
    poisoned          X
    relmon            X
    replmon           X
    rescham           X
    setmangry         X
    unstuck           X
    youswld           X

##### Variables

    fdmon             X
    lastwarnlev       X
    lastwarntime      X
    warnings          X
    warnlevel         X

##### Macros

    MAXMONNO          X
    NEW_SCORING       X
    NULL              X
    SRCHRADIUS        X

       1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
       2: /* hack.mon.c - version 1.0.3 */
       3:
       4: #include "hack.h"
       5: #include "hack.mfndpos.h"
       6: #define NULL    (char *) 0
       7: extern struct monst *makemon();
       8: extern struct obj *mkobj_at();
       9:
      10: int warnlevel;      /* used by movemon and dochugw */
      11: long lastwarntime;
      12: int lastwarnlev;
      13: char *warnings[] = {
      14:     "white", "pink", "red", "ruby", "purple", "black"
      15: };
      16:
      17: movemon()
      18: {
      19:     register struct monst *mtmp;
      20:     register int fr;
      21:
      22:     warnlevel = 0;
      23:
      24:     while(1) {
      25:         /* find a monster that we haven't treated yet */
      26:         /* note that mtmp or mtmp->nmon might get killed
      27: 		   while mtmp moves, so we cannot just walk down the
      28: 		   chain (even new monsters might get created!) */
      29:         for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
      30:             if(mtmp->mlstmv < moves) goto next_mon;
      31:         /* treated all monsters */
      32:         break;
      33:
      34:     next_mon:
      35:         mtmp->mlstmv = moves;
      36:
      37:         /* most monsters drown in pools */
      38:         { boolean inpool, iseel;
      39:
      40:           inpool = (levl[mtmp->mx][mtmp->my].typ == POOL);
      41:           iseel = (mtmp->data->mlet == ';');
      42:           if(inpool && !iseel) {
      43:             if(cansee(mtmp->mx,mtmp->my))
      44:                 pline("%s drowns.", Monnam(mtmp));
      45:             mondead(mtmp);
      46:             continue;
      47:           }
      48:         /* but eels have a difficult time outside */
      49:           if(iseel && !inpool) {
      50:             if(mtmp->mhp > 1) mtmp->mhp--;
      51:             mtmp->mflee = 1;
      52:             mtmp->mfleetim += 2;
      53:           }
      54:         }
      55:         if(mtmp->mblinded && !--mtmp->mblinded)
      56:             mtmp->mcansee = 1;
      57:         if(mtmp->mfleetim && !--mtmp->mfleetim)
      58:             mtmp->mflee = 0;
      59:         if(mtmp->mimic) continue;
      60:         if(mtmp->mspeed != MSLOW || !(moves%2)){
      61:             /* continue if the monster died fighting */
      62:             fr = -1;
      63:             if(Conflict && cansee(mtmp->mx,mtmp->my)
      64:                 && (fr = fightm(mtmp)) == 2)
      65:                 continue;
      66:             if(fr<0 && dochugw(mtmp))
      67:                 continue;
      68:         }
      69:         if(mtmp->mspeed == MFAST && dochugw(mtmp))
      70:             continue;
      71:     }
      72:
      73:     warnlevel -= u.ulevel;
      74:     if(warnlevel >= SIZE(warnings))
      75:         warnlevel = SIZE(warnings)-1;
      76:     if(warnlevel >= 0)
      77:     if(warnlevel > lastwarnlev || moves > lastwarntime + 5){
      78:         register char *rr;
      79: /* KLUDGE -- can't switch on longs!!
      80: 	    switch(Warning & (LEFT_RING | RIGHT_RING)){
      81: 	    case LEFT_RING:
      82: 		rr = "Your left ring glows";
      83: 		break;
      84: 	    case RIGHT_RING:
      85: 		rr = "Your right ring glows";
      86: 		break;
      87: 	    case LEFT_RING | RIGHT_RING:
      88: 		rr = "Both your rings glow";
      89: 		break;
      90: 	    default:
      91: 		rr = "Your fingertips glow";
      92: 		break;
      93: 	    }
      94: */
      95:         long swtval = Warning & (LEFT_RING | RIGHT_RING);
      96:              if(swtval == LEFT_RING)         rr = "Your left ring glows";
      97:         else if(swtval == RIGHT_RING)        rr = "Your right ring glows";
      98:         else if(swtval == LEFT_RING
      99:                         | RIGHT_RING)        rr = "Both your rings glow";
     100:         else                                 rr = "Your fingertips glow";
     101:         pline("%s %s!", rr, warnings[warnlevel]);
     102:         lastwarntime = moves;
     103:         lastwarnlev = warnlevel;
     104:     }
     105:
     106:     dmonsfree();    /* remove all dead monsters */
     107: }
     108:
     109: justswld(mtmp,name)
     110: register struct monst *mtmp;
     111: char *name;
     112: {
     113:
     114:     mtmp->mx = u.ux;
     115:     mtmp->my = u.uy;
     116:     u.ustuck = mtmp;
     117:     pmon(mtmp);
     118:     kludge("%s swallows you!",name);
     119:     more();
     120:     seeoff(1);
     121:     u.uswallow = 1;
     122:     u.uswldtim = 0;
     123:     swallowed();
     124: }
     125:
     126: youswld(mtmp,dam,die,name)
     127: register struct monst *mtmp;
     128: register dam,die;
     129: char *name;
     130: {
     131:     if(mtmp != u.ustuck) return;
     132:     kludge("%s digests you!",name);
     133:     u.uhp -= dam;
     134:     if(u.uswldtim++ >= die){    /* a3 */
     135:         pline("It totally digests you!");
     136:         u.uhp = -1;
     137:     }
     138:     if(u.uhp < 1) done_in_by(mtmp);
     139:     /* flags.botlx = 1;		/* should we show status line ? */
     140: }
     141:
     142: dochugw(mtmp) register struct monst *mtmp; {
     143: register x = mtmp->mx;
     144: register y = mtmp->my;
     145: register d = dochug(mtmp);
     146: register dd;
     147:     if(!d)      /* monster still alive */
     148:     if(Warning)
     149:     if(!mtmp->mpeaceful)
     150:     if(mtmp->data->mlevel > warnlevel)
     151:     if((dd = dist(mtmp->mx,mtmp->my)) < dist(x,y))
     152:     if(dd < 100)
     153:     if(!canseemon(mtmp))
     154:         warnlevel = mtmp->data->mlevel;
     155:     return(d);
     156: }
     157:
     158: /* returns 1 if monster died moving, 0 otherwise */
     159: dochug(mtmp)
     160: register struct monst *mtmp;
     161: {
     162:     register struct permonst *mdat;
     163:     register tmp, nearby, scared;
     164:
     165:     if(mtmp->cham && !rn2(6))
     166:         (void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]);
     167:     mdat = mtmp->data;
     168:     if(mdat->mlevel < 0)
     169:         panic("bad monster %c (%d)",mdat->mlet,mdat->mlevel);
     170:
     171:     /* regenerate monsters */
     172:     if((!(moves%20) || index(MREGEN, mdat->mlet)) &&
     173:         mtmp->mhp < mtmp->mhpmax)
     174:         mtmp->mhp++;
     175:
     176:     if(mtmp->mfroz) return(0); /* frozen monsters don't do anything */
     177:
     178:     if(mtmp->msleep) {
     179:         /* wake up, or get out of here. */
     180:         /* ettins are hard to surprise */
     181:         /* Nymphs and Leprechauns do not easily wake up */
     182:         if(cansee(mtmp->mx,mtmp->my) &&
     183:             (!Stealth || (mdat->mlet == 'e' && rn2(10))) &&
     184:             (!index("NL",mdat->mlet) || !rn2(50)) &&
     185:             (Aggravate_monster || index("d1", mdat->mlet)
     186:                 || (!rn2(7) && !mtmp->mimic)))
     187:             mtmp->msleep = 0;
     188:         else return(0);
     189:     }
     190:
     191:     /* not frozen or sleeping: wipe out texts written in the dust */
     192:     wipe_engr_at(mtmp->mx, mtmp->my, 1);
     193:
     194:     /* confused monsters get unconfused with small probability */
     195:     if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
     196:
     197:     /* some monsters teleport */
     198:     if(mtmp->mflee && index("tNL", mdat->mlet) && !rn2(40)){
     199:         rloc(mtmp);
     200:         return(0);
     201:     }
     202:     if(mdat->mmove < rnd(6)) return(0);
     203:
     204:     /* fleeing monsters might regain courage */
     205:     if(mtmp->mflee && !mtmp->mfleetim
     206:         && mtmp->mhp == mtmp->mhpmax && !rn2(25))
     207:         mtmp->mflee = 0;
     208:
     209:     nearby = (dist(mtmp->mx, mtmp->my) < 3);
     210:     scared = (nearby && (sengr_at("Elbereth", u.ux, u.uy) ||
     211:             sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy)));
     212:     if(scared && !mtmp->mflee) {
     213:         mtmp->mflee = 1;
     214:         mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100));
     215:     }
     216:
     217:     if(!nearby ||
     218:         mtmp->mflee ||
     219:         mtmp->mconf ||
     220:         (mtmp->minvis && !rn2(3)) ||
     221:         (index("BIuy", mdat->mlet) && !rn2(4)) ||
     222:         (mdat->mlet == 'L' && !u.ugold && (mtmp->mgold || rn2(2))) ||
     223:         (!mtmp->mcansee && !rn2(4)) ||
     224:         mtmp->mpeaceful
     225:        ) {
     226:         tmp = m_move(mtmp,0);   /* 2: monster died moving */
     227:         if(tmp == 2 || (tmp && mdat->mmove <= 12))
     228:             return(tmp == 2);
     229:     }
     230:
     231:     if(!index("Ea", mdat->mlet) && nearby &&
     232:      !mtmp->mpeaceful && u.uhp > 0 && !scared) {
     233:         if(mhitu(mtmp))
     234:             return(1);  /* monster died (e.g. 'y' or 'F') */
     235:     }
     236:     /* extra movement for fast monsters */
     237:     if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp,1);
     238:     return(tmp == 2);
     239: }
     240:
     241: m_move(mtmp,after)
     242: register struct monst *mtmp;
     243: {
     244:     register struct monst *mtmp2;
     245:     register nx,ny,omx,omy,appr,nearer,cnt,i,j;
     246:     xchar gx,gy,nix,niy,chcnt;
     247:     schar chi;
     248:     boolean likegold, likegems, likeobjs;
     249:     char msym = mtmp->data->mlet;
     250:     schar mmoved = 0;   /* not strictly nec.: chi >= 0 will do */
     251:     coord poss[9];
     252:     int info[9];
     253:
     254:     if(mtmp->mfroz || mtmp->msleep)
     255:         return(0);
     256:     if(mtmp->mtrapped) {
     257:         i = mintrap(mtmp);
     258:         if(i == 2) return(2);   /* he died */
     259:         if(i == 1) return(0);   /* still in trap, so didnt move */
     260:     }
     261:     if(mtmp->mhide && o_at(mtmp->mx,mtmp->my) && rn2(10))
     262:         return(0);      /* do not leave hiding place */
     263:
     264: #ifndef NOWORM
     265:     if(mtmp->wormno)
     266:         goto not_special;
     267: #endif NOWORM
     268:
     269:     /* my dog gets a special treatment */
     270:     if(mtmp->mtame) {
     271:         return( dog_move(mtmp, after) );
     272:     }
     273:
     274:     /* likewise for shopkeeper */
     275:     if(mtmp->isshk) {
     276:         mmoved = shk_move(mtmp);
     277:         if(mmoved >= 0)
     278:             goto postmov;
     279:         mmoved = 0;     /* follow player outside shop */
     280:     }
     281:
     282:     /* and for the guard */
     283:     if(mtmp->isgd) {
     284:         mmoved = gd_move();
     285:         goto postmov;
     286:     }
     287:
     288: /* teleport if that lies in our nature ('t') or when badly wounded ('1') */
     289:     if((msym == 't' && !rn2(5))
     290:     || (msym == '1' && (mtmp->mhp < 7 || (!xdnstair && !rn2(5))
     291:         || levl[u.ux][u.uy].typ == STAIRS))) {
     292:         if(mtmp->mhp < 7 || (msym == 't' && rn2(2)))
     293:             rloc(mtmp);
     294:         else
     295:             mnexto(mtmp);
     296:         mmoved = 1;
     297:         goto postmov;
     298:     }
     299:
     300:     /* spit fire ('D') or use a wand ('1') when appropriate */
     301:     if(index("D1", msym))
     302:         inrange(mtmp);
     303:
     304:     if(msym == 'U' && !mtmp->mcan && canseemon(mtmp) &&
     305:         mtmp->mcansee && rn2(5)) {
     306:         if(!Confusion)
     307:             pline("%s's gaze has confused you!", Monnam(mtmp));
     308:         else
     309:             pline("You are getting more and more confused.");
     310:         if(rn2(3)) mtmp->mcan = 1;
     311:         Confusion += d(3,4);        /* timeout */
     312:     }
     313: not_special:
     314:     if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1);
     315:     appr = 1;
     316:     if(mtmp->mflee) appr = -1;
     317:     if(mtmp->mconf || Invis ||  !mtmp->mcansee ||
     318:         (index("BIy", msym) && !rn2(3)))
     319:         appr = 0;
     320:     omx = mtmp->mx;
     321:     omy = mtmp->my;
     322:     gx = u.ux;
     323:     gy = u.uy;
     324:     if(msym == 'L' && appr == 1 && mtmp->mgold > u.ugold)
     325:         appr = -1;
     326:
     327:     /* random criterion for 'smell' or track finding ability
     328: 	   should use mtmp->msmell or sth
     329: 	 */
     330:     if(msym == '@' ||
     331:       ('a' <= msym && msym <= 'z')) {
     332:     extern coord *gettrack();
     333:     register coord *cp;
     334:     schar mroom;
     335:         mroom = inroom(omx,omy);
     336:         if(mroom < 0 || mroom != inroom(u.ux,u.uy)){
     337:             cp = gettrack(omx,omy);
     338:             if(cp){
     339:             gx = cp->x;
     340:             gy = cp->y;
     341:             }
     342:         }
     343:     }
     344:
     345:     /* look for gold or jewels nearby */
     346:     likegold = (index("LOD", msym) != NULL);
     347:     likegems = (index("ODu", msym) != NULL);
     348:     likeobjs = mtmp->mhide;
     349: #define SRCHRADIUS  25
     350:     { xchar mind = SRCHRADIUS;      /* not too far away */
     351:       register int dd;
     352:       if(likegold){
     353:         register struct gold *gold;
     354:         for(gold = fgold; gold; gold = gold->ngold)
     355:           if((dd = DIST(omx,omy,gold->gx,gold->gy)) < mind){
     356:             mind = dd;
     357:             gx = gold->gx;
     358:             gy = gold->gy;
     359:         }
     360:       }
     361:       if(likegems || likeobjs){
     362:         register struct obj *otmp;
     363:         for(otmp = fobj; otmp; otmp = otmp->nobj)
     364:         if(likeobjs || otmp->olet == GEM_SYM)
     365:         if(msym != 'u' ||
     366:             objects[otmp->otyp].g_val != 0)
     367:         if((dd = DIST(omx,omy,otmp->ox,otmp->oy)) < mind){
     368:             mind = dd;
     369:             gx = otmp->ox;
     370:             gy = otmp->oy;
     371:         }
     372:       }
     373:       if(mind < SRCHRADIUS && appr == -1) {
     374:         if(dist(omx,omy) < 10) {
     375:             gx = u.ux;
     376:             gy = u.uy;
     377:         } else
     378:             appr = 1;
     379:       }
     380:     }
     381:     nix = omx;
     382:     niy = omy;
     383:     cnt = mfndpos(mtmp,poss,info,
     384:         msym == 'u' ? NOTONL :
     385:         (msym == '@' || msym == '1') ? (ALLOW_SSM | ALLOW_TRAPS) :
     386:         index(UNDEAD, msym) ? NOGARLIC : ALLOW_TRAPS);
     387:         /* ALLOW_ROCK for some monsters ? */
     388:     chcnt = 0;
     389:     chi = -1;
     390:     for(i=0; i<cnt; i++) {
     391:         nx = poss[i].x;
     392:         ny = poss[i].y;
     393:         for(j=0; j<MTSZ && j<cnt-1; j++)
     394:             if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
     395:                 if(rn2(4*(cnt-j))) goto nxti;
     396: #ifdef STUPID
     397:         /* some stupid compilers think that this is too complicated */
     398:         { int d1 = DIST(nx,ny,gx,gy);
     399:           int d2 = DIST(nix,niy,gx,gy);
     400:           nearer = (d1 < d2);
     401:         }
     402: #else
     403:         nearer = (DIST(nx,ny,gx,gy) < DIST(nix,niy,gx,gy));
     404: #endif STUPID
     405:         if((appr == 1 && nearer) || (appr == -1 && !nearer) ||
     406:             !mmoved ||
     407:             (!appr && !rn2(++chcnt))){
     408:             nix = nx;
     409:             niy = ny;
     410:             chi = i;
     411:             mmoved = 1;
     412:         }
     413:     nxti:   ;
     414:     }
     415:     if(mmoved){
     416:         if(info[chi] & ALLOW_M){
     417:             mtmp2 = m_at(nix,niy);
     418:             if(hitmm(mtmp,mtmp2) == 1 && rn2(4) &&
     419:               hitmm(mtmp2,mtmp) == 2) return(2);
     420:             return(0);
     421:         }
     422:         if(info[chi] & ALLOW_U){
     423:           (void) hitu(mtmp, d(mtmp->data->damn, mtmp->data->damd)+1);
     424:           return(0);
     425:         }
     426:         mtmp->mx = nix;
     427:         mtmp->my = niy;
     428:         for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
     429:         mtmp->mtrack[0].x = omx;
     430:         mtmp->mtrack[0].y = omy;
     431: #ifndef NOWORM
     432:         if(mtmp->wormno) worm_move(mtmp);
     433: #endif NOWORM
     434:     } else {
     435:         if(msym == 'u' && rn2(2)){
     436:             rloc(mtmp);
     437:             return(0);
     438:         }
     439: #ifndef NOWORM
     440:         if(mtmp->wormno) worm_nomove(mtmp);
     441: #endif NOWORM
     442:     }
     443: postmov:
     444:     if(mmoved == 1) {
     445:         if(mintrap(mtmp) == 2)  /* he died */
     446:             return(2);
     447:         if(likegold) mpickgold(mtmp);
     448:         if(likegems) mpickgems(mtmp);
     449:         if(mtmp->mhide) mtmp->mundetected = 1;
     450:     }
     451:     pmon(mtmp);
     452:     return(mmoved);
     453: }
     454:
     455: mpickgold(mtmp) register struct monst *mtmp; {
     456: register struct gold *gold;
     457:     while(gold = g_at(mtmp->mx, mtmp->my)){
     458:         mtmp->mgold += gold->amount;
     459:         freegold(gold);
     460:         if(levl[mtmp->mx][mtmp->my].scrsym == '$')
     461:             newsym(mtmp->mx, mtmp->my);
     462:     }
     463: }
     464:
     465: mpickgems(mtmp) register struct monst *mtmp; {
     466: register struct obj *otmp;
     467:     for(otmp = fobj; otmp; otmp = otmp->nobj)
     468:     if(otmp->olet == GEM_SYM)
     469:     if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my)
     470:     if(mtmp->data->mlet != 'u' || objects[otmp->otyp].g_val != 0){
     471:         freeobj(otmp);
     472:         mpickobj(mtmp, otmp);
     473:         if(levl[mtmp->mx][mtmp->my].scrsym == GEM_SYM)
     474:             newsym(mtmp->mx, mtmp->my); /* %% */
     475:         return; /* pick only one object */
     476:     }
     477: }
     478:
     479: /* return number of acceptable neighbour positions */
     480: mfndpos(mon,poss,info,flag)
     481: register struct monst *mon;
     482: coord poss[9];
     483: int info[9], flag;
     484: {
     485:     register int x,y,nx,ny,cnt = 0,ntyp;
     486:     register struct monst *mtmp;
     487:     int nowtyp;
     488:     boolean pool;
     489:
     490:     x = mon->mx;
     491:     y = mon->my;
     492:     nowtyp = levl[x][y].typ;
     493:
     494:     pool = (mon->data->mlet == ';');
     495: nexttry:    /* eels prefer the water, but if there is no water nearby,
     496: 		   they will crawl over land */
     497:     if(mon->mconf) {
     498:         flag |= ALLOW_ALL;
     499:         flag &= ~NOTONL;
     500:     }
     501:     for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++)
     502:     if(nx != x || ny != y) if(isok(nx,ny))
     503:     if(!IS_ROCK(ntyp = levl[nx][ny].typ))
     504:     if(!(nx != x && ny != y && (nowtyp == DOOR || ntyp == DOOR)))
     505:     if((ntyp == POOL) == pool) {
     506:         info[cnt] = 0;
     507:         if(nx == u.ux && ny == u.uy){
     508:             if(!(flag & ALLOW_U)) continue;
     509:             info[cnt] = ALLOW_U;
     510:         } else if(mtmp = m_at(nx,ny)){
     511:             if(!(flag & ALLOW_M)) continue;
     512:             info[cnt] = ALLOW_M;
     513:             if(mtmp->mtame){
     514:                 if(!(flag & ALLOW_TM)) continue;
     515:                 info[cnt] |= ALLOW_TM;
     516:             }
     517:         }
     518:         if(sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
     519:             if(flag & NOGARLIC) continue;
     520:             info[cnt] |= NOGARLIC;
     521:         }
     522:         if(sobj_at(SCR_SCARE_MONSTER, nx, ny) ||
     523:            (!mon->mpeaceful && sengr_at("Elbereth", nx, ny))) {
     524:             if(!(flag & ALLOW_SSM)) continue;
     525:             info[cnt] |= ALLOW_SSM;
     526:         }
     527:         if(sobj_at(ENORMOUS_ROCK, nx, ny)) {
     528:             if(!(flag & ALLOW_ROCK)) continue;
     529:             info[cnt] |= ALLOW_ROCK;
     530:         }
     531:         if(!Invis && online(nx,ny)){
     532:             if(flag & NOTONL) continue;
     533:             info[cnt] |= NOTONL;
     534:         }
     535:         /* we cannot avoid traps of an unknown kind */
     536:         { register struct trap *ttmp = t_at(nx, ny);
     537:           register int tt;
     538:             if(ttmp) {
     539:                 tt = 1 << ttmp->ttyp;
     540:                 if(mon->mtrapseen & tt){
     541:                     if(!(flag & tt)) continue;
     542:                     info[cnt] |= tt;
     543:                 }
     544:             }
     545:         }
     546:         poss[cnt].x = nx;
     547:         poss[cnt].y = ny;
     548:         cnt++;
     549:     }
     550:     if(!cnt && pool && nowtyp != POOL) {
     551:         pool = FALSE;
     552:         goto nexttry;
     553:     }
     554:     return(cnt);
     555: }
     556:
     557: dist(x,y) int x,y; {
     558:     return((x-u.ux)*(x-u.ux) + (y-u.uy)*(y-u.uy));
     559: }
     560:
     561: poisoned(string, pname)
     562: register char *string, *pname;
     563: {
     564:     register int i;
     565:
     566:     if(Blind) pline("It was poisoned.");
     567:     else pline("The %s was poisoned!",string);
     568:     if(Poison_resistance) {
     569:         pline("The poison doesn't seem to affect you.");
     570:         return;
     571:     }
     572:     i = rn2(10);
     573:     if(i == 0) {
     574:         u.uhp = -1;
     575:         pline("I am afraid the poison was deadly ...");
     576:     } else if(i <= 5) {
     577:         losestr(rn1(3,3));
     578:     } else {
     579:         losehp(rn1(10,6), pname);
     580:     }
     581:     if(u.uhp < 1) {
     582:         killer = pname;
     583:         done("died");
     584:     }
     585: }
     586:
     587: mondead(mtmp)
     588: register struct monst *mtmp;
     589: {
     590:     relobj(mtmp,1);
     591:     unpmon(mtmp);
     592:     relmon(mtmp);
     593:     unstuck(mtmp);
     594:     if(mtmp->isshk) shkdead(mtmp);
     595:     if(mtmp->isgd) gddead();
     596: #ifndef NOWORM
     597:     if(mtmp->wormno) wormdead(mtmp);
     598: #endif NOWORM
     599:     monfree(mtmp);
     600: }
     601:
     602: /* called when monster is moved to larger structure */
     603: replmon(mtmp,mtmp2)
     604: register struct monst *mtmp, *mtmp2;
     605: {
     606:     relmon(mtmp);
     607:     monfree(mtmp);
     608:     mtmp2->nmon = fmon;
     609:     fmon = mtmp2;
     610:     if(u.ustuck == mtmp) u.ustuck = mtmp2;
     611:     if(mtmp2->isshk) replshk(mtmp,mtmp2);
     612:     if(mtmp2->isgd) replgd(mtmp,mtmp2);
     613: }
     614:
     615: relmon(mon)
     616: register struct monst *mon;
     617: {
     618:     register struct monst *mtmp;
     619:
     620:     if(mon == fmon) fmon = fmon->nmon;
     621:     else {
     622:         for(mtmp = fmon; mtmp->nmon != mon; mtmp = mtmp->nmon) ;
     623:         mtmp->nmon = mon->nmon;
     624:     }
     625: }
     626:
     627: /* we do not free monsters immediately, in order to have their name
     628:    available shortly after their demise */
     629: struct monst *fdmon;    /* chain of dead monsters, need not to be saved */
     630:
     631: monfree(mtmp) register struct monst *mtmp; {
     632:     mtmp->nmon = fdmon;
     633:     fdmon = mtmp;
     634: }
     635:
     636: dmonsfree(){
     637: register struct monst *mtmp;
     638:     while(mtmp = fdmon){
     639:         fdmon = mtmp->nmon;
     640:         free((char *) mtmp);
     641:     }
     642: }
     643:
     644: unstuck(mtmp)
     645: register struct monst *mtmp;
     646: {
     647:     if(u.ustuck == mtmp) {
     648:         if(u.uswallow){
     649:             u.ux = mtmp->mx;
     650:             u.uy = mtmp->my;
     651:             u.uswallow = 0;
     652:             setsee();
     653:             docrt();
     654:         }
     655:         u.ustuck = 0;
     656:     }
     657: }
     658:
     659: killed(mtmp)
     660: register struct monst *mtmp;
     661: {
     662: #ifdef lint
     663: #define NEW_SCORING
     664: #endif lint
     665:     register int tmp,tmp2,nk,x,y;
     666:     register struct permonst *mdat = mtmp->data;
     667:     extern long newuexp();
     668:
     669:     if(mtmp->cham) mdat = PM_CHAMELEON;
     670:     if(Blind) pline("You destroy it!");
     671:     else {
     672:         pline("You destroy %s!",
     673:             mtmp->mtame ? amonnam(mtmp, "poor") : monnam(mtmp));
     674:     }
     675:     if(u.umconf) {
     676:         if(!Blind) pline("Your hands stop glowing blue.");
     677:         u.umconf = 0;
     678:     }
     679:
     680:     /* count killed monsters */
     681: #define MAXMONNO    100
     682:     nk = 1;           /* in case we cannot find it in mons */
     683:     tmp = mdat - mons;    /* index in mons array (if not 'd', '@', ...) */
     684:     if(tmp >= 0 && tmp < CMNUM+2) {
     685:         extern char fut_geno[];
     686:         u.nr_killed[tmp]++;
     687:         if((nk = u.nr_killed[tmp]) > MAXMONNO &&
     688:         !index(fut_geno, mdat->mlet))
     689:             charcat(fut_geno,  mdat->mlet);
     690:     }
     691:
     692:     /* punish bad behaviour */
     693:     if(mdat->mlet == '@') Telepat = 0, u.uluck -= 2;
     694:     if(mtmp->mpeaceful || mtmp->mtame) u.uluck--;
     695:     if(mdat->mlet == 'u') u.uluck -= 5;
     696:     if((int)u.uluck < LUCKMIN) u.uluck = LUCKMIN;
     697:
     698:     /* give experience points */
     699:     tmp = 1 + mdat->mlevel * mdat->mlevel;
     700:     if(mdat->ac < 3) tmp += 2*(7 - mdat->ac);
     701:     if(index("AcsSDXaeRTVWU&In:P", mdat->mlet))
     702:         tmp += 2*mdat->mlevel;
     703:     if(index("DeV&P",mdat->mlet)) tmp += (7*mdat->mlevel);
     704:     if(mdat->mlevel > 6) tmp += 50;
     705:     if(mdat->mlet == ';') tmp += 1000;
     706:
     707: #ifdef NEW_SCORING
     708:     /* ------- recent addition: make nr of points decrease
     709: 		   when this is not the first of this kind */
     710:     { int ul = u.ulevel;
     711:       int ml = mdat->mlevel;
     712:
     713:     if(ul < 14)    /* points are given based on present and future level */
     714:         for(tmp2 = 0; !tmp2 || ul + tmp2 <= ml; tmp2++)
     715:         if(u.uexp + 1 + (tmp + ((tmp2 <= 0) ? 0 : 4<<(tmp2-1)))/nk
     716:             >= 10*pow((unsigned)(ul-1)))
     717:             if(++ul == 14) break;
     718:
     719:     tmp2 = ml - ul -1;
     720:     tmp = (tmp + ((tmp2 < 0) ? 0 : 4<<tmp2))/nk;
     721:     if(!tmp) tmp = 1;
     722:     }
     723:     /* note: ul is not necessarily the future value of u.ulevel */
     724:     /* ------- end of recent valuation change ------- */
     725: #endif NEW_SCORING
     726:
     727:     more_experienced(tmp,0);
     728:     flags.botl = 1;
     729:     while(u.ulevel < 14 && u.uexp >= newuexp()){
     730:         pline("Welcome to experience level %u.", ++u.ulevel);
     731:         tmp = rnd(10);
     732:         if(tmp < 3) tmp = rnd(10);
     733:         u.uhpmax += tmp;
     734:         u.uhp += tmp;
     735:         flags.botl = 1;
     736:     }
     737:
     738:     /* dispose of monster and make cadaver */
     739:     x = mtmp->mx;   y = mtmp->my;
     740:     mondead(mtmp);
     741:     tmp = mdat->mlet;
     742:     if(tmp == 'm') { /* he killed a minotaur, give him a wand of digging */
     743:             /* note: the dead minotaur will be on top of it! */
     744:         mksobj_at(WAN_DIGGING, x, y);
     745:         /* if(cansee(x,y)) atl(x,y,fobj->olet); */
     746:         stackobj(fobj);
     747:     } else
     748: #ifndef NOWORM
     749:     if(tmp == 'w') {
     750:         mksobj_at(WORM_TOOTH, x, y);
     751:         stackobj(fobj);
     752:     } else
     753: #endif	NOWORM
     754:     if(!letter(tmp) || (!index("mw", tmp) && !rn2(3))) tmp = 0;
     755:
     756:     if(ACCESSIBLE(levl[x][y].typ))  /* might be mimic in wall or dead eel*/
     757:         if(x != u.ux || y != u.uy)  /* might be here after swallowed */
     758:         if(index("NTVm&",mdat->mlet) || rn2(5)) {
     759:         register struct obj *obj2 = mkobj_at(tmp,x,y);
     760:         if(cansee(x,y))
     761:             atl(x,y,obj2->olet);
     762:         stackobj(obj2);
     763:     }
     764: }
     765:
     766: kludge(str,arg)
     767: register char *str,*arg;
     768: {
     769:     if(Blind) {
     770:         if(*str == '%') pline(str,"It");
     771:         else pline(str,"it");
     772:     } else pline(str,arg);
     773: }
     774:
     775: rescham()   /* force all chameleons to become normal */
     776: {
     777:     register struct monst *mtmp;
     778:
     779:     for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
     780:         if(mtmp->cham) {
     781:             mtmp->cham = 0;
     782:             (void) newcham(mtmp, PM_CHAMELEON);
     783:         }
     784: }
     785:
     786: newcham(mtmp,mdat)  /* make a chameleon look like a new monster */
     787:             /* returns 1 if the monster actually changed */
     788: register struct monst *mtmp;
     789: register struct permonst *mdat;
     790: {
     791:     register mhp, hpn, hpd;
     792:
     793:     if(mdat == mtmp->data) return(0);   /* still the same monster */
     794: #ifndef NOWORM
     795:     if(mtmp->wormno) wormdead(mtmp);    /* throw tail away */
     796: #endif NOWORM
     797:     hpn = mtmp->mhp;
     798:     hpd = (mtmp->data->mlevel)*8;
     799:     if(!hpd) hpd = 4;
     800:     mtmp->data = mdat;
     801:     mhp = (mdat->mlevel)*8;
     802:     /* new hp: same fraction of max as before */
     803:     mtmp->mhp = 2 + (hpn*mhp)/hpd;
     804:     hpn = mtmp->mhpmax;
     805:     mtmp->mhpmax = 2 + (hpn*mhp)/hpd;
     806:     mtmp->minvis = (mdat->mlet == 'I') ? 1 : 0;
     807: #ifndef NOWORM
     808:     if(mdat->mlet == 'w' && getwn(mtmp)) initworm(mtmp);
     809:             /* perhaps we should clear mtmp->mtame here? */
     810: #endif NOWORM
     811:     unpmon(mtmp);   /* necessary for 'I' and to force pmon */
     812:     pmon(mtmp);
     813:     return(1);
     814: }
     815:
     816: mnexto(mtmp)    /* Make monster mtmp next to you (if possible) */
     817: struct monst *mtmp;
     818: {
     819:     extern coord enexto();
     820:     coord mm;
     821:     mm = enexto(u.ux, u.uy);
     822:     mtmp->mx = mm.x;
     823:     mtmp->my = mm.y;
     824:     pmon(mtmp);
     825: }
     826:
     827: ishuman(mtmp) register struct monst *mtmp; {
     828:     return(mtmp->data->mlet == '@');
     829: }
     830:
     831: setmangry(mtmp) register struct monst *mtmp; {
     832:     if(!mtmp->mpeaceful) return;
     833:     if(mtmp->mtame) return;
     834:     mtmp->mpeaceful = 0;
     835:     if(ishuman(mtmp)) pline("%s gets angry!", Monnam(mtmp));
     836: }
     837:
     838: /* not one hundred procent correct: now a snake may hide under an
     839:    invisible object */
     840: canseemon(mtmp)
     841: register struct monst *mtmp;
     842: {
     843:     return((!mtmp->minvis || See_invisible)
     844:         && (!mtmp->mhide || !o_at(mtmp->mx,mtmp->my))
     845:         && cansee(mtmp->mx, mtmp->my));
     846: }

#### Defined functions

canseemon defined in line 840; used 7 times

- in line 153, 304
- in /usr/src/games/hack/hack.fight.c line 347
- in /usr/src/games/hack/hack.pri.c line 475, 540
- in /usr/src/games/hack/hack.wizard.c line 108, 120

dist defined in line 557; used 29 times

- in line 151(2), 209, 374
- in /usr/src/games/hack/hack.apply.c line 86, 220, 260
- in /usr/src/games/hack/hack.c line 117, 582, 620
- in /usr/src/games/hack/hack.dog.c line 58, 146, 218-219(2)
- in /usr/src/games/hack/hack.fight.c line 36
- in /usr/src/games/hack/hack.potion.c line 239
- in /usr/src/games/hack/hack.read.c line 224, 394, 513
- in /usr/src/games/hack/hack.shk.c line 314, 798, 860, 964
- in /usr/src/games/hack/hack.steal.c line 46
- in /usr/src/games/hack/hack.unix.c line 337, 361(2)
- in /usr/src/games/hack/hack.vault.c line 174
- in /usr/src/games/hack/hack.wizard.c line 28

dmonsfree defined in line 636; used 1 times

- in line 106

dochug defined in line 159; used 2 times

- in line 145
- in /usr/src/games/hack/hack.shk.c line 210

dochugw defined in line 142; used 2 times

- in line 66-69(2)

ishuman defined in line 827; used 1 times

- in line 835

justswld defined in line 109; used 3 times

- in /usr/src/games/hack/hack.mhitu.c line 86-89(2), 228

killed defined in line 659; used 6 times

- in /usr/src/games/hack/hack.fight.c line 189, 217
- in /usr/src/games/hack/hack.read.c line 399
- in /usr/src/games/hack/hack.zap.c line 32, 44, 470

kludge defined in line 766; used 7 times

- in line 118, 132
- in /usr/src/games/hack/hack.mhitu.c line 135, 146, 163, 170, 219

m_move defined in line 241; used 3 times

- in line 226, 237
- in /usr/src/games/hack/hack.fight.c line 262

mfndpos defined in line 480; used 3 times

- in line 383
- in /usr/src/games/hack/hack.dog.c line 267
- in /usr/src/games/hack/hack.shk.c line 881

mnexto defined in line 816; used 9 times

- in line 295
- in /usr/src/games/hack/hack.apply.c line 236
- in /usr/src/games/hack/hack.do.c line 210, 232
- in /usr/src/games/hack/hack.dog.c line 45
- in /usr/src/games/hack/hack.main.c line 271
- in /usr/src/games/hack/hack.makemon.c line 70
- in /usr/src/games/hack/hack.potion.c line 382
- in /usr/src/games/hack/hack.zap.c line 196

mondead defined in line 587; used 13 times

- in line 45, 740
- in /usr/src/games/hack/hack.fight.c line 80, 94
- in /usr/src/games/hack/hack.lev.c line 198
- in /usr/src/games/hack/hack.mhitu.c line 159, 305
- in /usr/src/games/hack/hack.read.c line 204
- in /usr/src/games/hack/hack.shk.c line 351
- in /usr/src/games/hack/hack.unix.c line 343
- in /usr/src/games/hack/hack.vault.c line 55, 127, 141

monfree defined in line 631; used 3 times

- in line 599, 607
- in /usr/src/games/hack/hack.worm.c line 142

movemon defined in line 17; used 1 times

- in /usr/src/games/hack/hack.main.c line 306

mpickgems defined in line 465; used 1 times

- in line 448

mpickgold defined in line 455; used 1 times

- in line 447

newcham defined in line 786; used 4 times

- in line 166, 782
- in /usr/src/games/hack/hack.makemon.c line 82
- in /usr/src/games/hack/hack.zap.c line 49

poisoned defined in line 561; used 4 times

- in /usr/src/games/hack/hack.mhitu.c line 184, 251-256(2)
- in /usr/src/games/hack/hack.trap.c line 104

relmon defined in line 615; used 4 times

- in line 592, 606
- in /usr/src/games/hack/hack.dog.c line 60, 70

replmon defined in line 603; used 2 times

- in /usr/src/games/hack/hack.do_name.c line 90
- in /usr/src/games/hack/hack.dog.c line 411

rescham defined in line 775; used 1 times

- in /usr/src/games/hack/hack.do_wear.c line 219

setmangry defined in line 831; used 2 times

- in /usr/src/games/hack/hack.apply.c line 90
- in /usr/src/games/hack/hack.search.c line 121

unstuck defined in line 644; used 2 times

- in line 593
- in /usr/src/games/hack/hack.zap.c line 195

youswld defined in line 126; used 3 times

- in /usr/src/games/hack/hack.mhitu.c line 35-42(3)

#### Defined variables

fdmon defined in line 629; used 4 times

- in line 632-639(4)

lastwarnlev defined in line 12; never used
lastwarntime defined in line 11; never used
warnings defined in line 13; used 3 times

- in line 74-75(2), 101

warnlevel defined in line 10; used 10 times

- in line 22, 73-77(5), 101-103(2), 150-154(2)

#### Defined macros

MAXMONNO defined in line 681; used 1 times

- in line 687

NEW_SCORING defined in line 663; used 1 times

- in line 707

NULL defined in line 6; used 2 times

- in line 346-347(2)

SRCHRADIUS defined in line 349; used 2 times

- in line 350, 373

Last modified: 1985-10-14 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2241 |