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: }