Source:NetHack 2.2a/mon.c
Jump to navigation
Jump to search
Below is the full text to mon.c from the source code of NetHack 2.2a. To link to a particular line, write [[NetHack 2.2a/mon.c#line123]], for example.
Warning! This is the source code from an old release. For the latest release, see Source code
Screenshots and source code from Hack are used under the CWI license.
1. /* SCCS Id: @(#)mon.c 2.1 87/10/17 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. 4. #include "hack.h" 5. #include "mfndpos.h" 6. extern struct monst *mkmon_at(); 7. extern struct trap *maketrap(); 8. extern struct obj *mkobj_at(), *mksobj_at(); 9. extern char *hcolor(); 10. #ifdef KAA 11. extern boolean stoned; 12. extern char mlarge[]; 13. #endif 14. #ifdef RPH 15. extern struct obj *mk_named_obj_at(); 16. #endif 17. 18. int warnlevel; /* used by movemon and dochugw */ 19. long lastwarntime; 20. int lastwarnlev; 21. char *warnings[] = { "white", "pink", "red", "ruby", "purple", "black" }; 22. 23. movemon() 24. { 25. register struct monst *mtmp; 26. register int fr; 27. 28. warnlevel = 0; 29. 30. while(1) { 31. /* find a monster that we haven't treated yet */ 32. /* note that mtmp or mtmp->nmon might get killed 33. while mtmp moves, so we cannot just walk down the 34. chain (even new monsters might get created!) */ 35. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 36. if(mtmp->mlstmv < moves) goto next_mon; 37. /* treated all monsters */ 38. break; 39. 40. next_mon: 41. mtmp->mlstmv = moves; 42. 43. /* most monsters drown in pools */ 44. { boolean inpool, iseel; 45. 46. inpool = (levl[mtmp->mx][mtmp->my].typ == POOL); 47. iseel = (mtmp->data->mlet == ';'); 48. if(inpool && !iseel) { 49. if(cansee(mtmp->mx,mtmp->my)) 50. pline("%s drowns.", Monnam(mtmp)); 51. mondead(mtmp); 52. continue; 53. } 54. /* but eels have a difficult time outside */ 55. if(iseel && !inpool) { 56. if(mtmp->mhp > 1) mtmp->mhp--; 57. mtmp->mflee = 1; 58. mtmp->mfleetim += 2; 59. } 60. } 61. if(mtmp->mblinded && !--mtmp->mblinded) 62. mtmp->mcansee = 1; 63. if(mtmp->mfleetim && !--mtmp->mfleetim) 64. mtmp->mflee = 0; 65. #ifdef HARD 66. /* unwatched mimics and piercers may hide again [MRS] */ 67. if(restrap(mtmp)) continue; 68. #endif 69. if(mtmp->mimic) continue; 70. if(mtmp->mspeed != MSLOW || !(moves%2)){ 71. /* continue if the monster died fighting */ 72. fr = -1; 73. if(Conflict && cansee(mtmp->mx,mtmp->my) 74. && (fr = fightm(mtmp)) == 2) 75. continue; 76. if(fr<0 && dochugw(mtmp)) 77. continue; 78. } 79. if(mtmp->mspeed == MFAST && dochugw(mtmp)) 80. continue; 81. } 82. 83. warnlevel -= u.ulevel; 84. if(warnlevel >= SIZE(warnings)) 85. warnlevel = SIZE(warnings)-1; 86. if(warnlevel >= 0) 87. if(warnlevel > lastwarnlev || moves > lastwarntime + 5){ 88. register char *rr; 89. switch((int) (Warning & (LEFT_RING | RIGHT_RING))){ 90. case LEFT_RING: 91. rr = "Your left ring glows"; 92. break; 93. case RIGHT_RING: 94. rr = "Your right ring glows"; 95. break; 96. case LEFT_RING | RIGHT_RING: 97. rr = "Both your rings glow"; 98. break; 99. default: 100. rr = "Your fingertips glow"; 101. break; 102. } 103. pline("%s %s!", rr, Hallucination ? hcolor() : warnings[warnlevel]); 104. lastwarntime = moves; 105. lastwarnlev = warnlevel; 106. } 107. 108. dmonsfree(); /* remove all dead monsters */ 109. } 110. 111. justswld(mtmp,name) 112. register struct monst *mtmp; 113. char *name; 114. { 115. 116. mtmp->mx = u.ux; 117. mtmp->my = u.uy; 118. u.ustuck = mtmp; 119. pmon(mtmp); 120. kludge("%s swallows you!",name); 121. more(); 122. seeoff(1); 123. u.uswallow = 1; 124. u.uswldtim = 0; 125. swallowed(); 126. } 127. 128. youswld(mtmp,dam,die,name) 129. register struct monst *mtmp; 130. register dam,die; 131. char *name; 132. { 133. if(mtmp != u.ustuck) return; 134. kludge("%s digests you!",name); 135. u.uhp -= dam; 136. if(u.uswldtim++ >= die){ /* a3 */ 137. pline("It totally digests you!"); 138. u.uhp = -1; 139. } 140. if(u.uhp < 1) done_in_by(mtmp); 141. /* flags.botlx = 1; /* should we show status line ? */ 142. } 143. 144. #ifdef ROCKMOLE 145. meatgold(mtmp) register struct monst *mtmp; { 146. register struct gold *gold; 147. register int pile; 148. register struct obj *otmp; 149. #ifdef KJSMODS 150. if(dlevel < 4) return; 151. #endif 152. /* Eats gold if it is there */ 153. while(gold = g_at(mtmp->mx, mtmp->my)){ 154. freegold(gold); 155. /* Left behind a pile? */ 156. pile = rnd(25); 157. if(pile < 3) mksobj_at(ROCK, mtmp->mx, mtmp->my); 158. newsym(mtmp->mx, mtmp->my); 159. } 160. /* Eats armor if it is there */ 161. otmp = o_at(mtmp->mx,mtmp->my); 162. if((otmp) && (otmp->otyp >= PLATE_MAIL) && (otmp->otyp <= RING_MAIL)){ 163. freeobj(otmp); 164. /* Left behind a pile? */ 165. pile = rnd(25); 166. if(pile < 3) mksobj_at(ROCK, mtmp->mx, mtmp->my); 167. newsym(mtmp->mx, mtmp->my); 168. } 169. } 170. #endif /* ROCKMOLE /**/ 171. 172. mpickgold(mtmp) register struct monst *mtmp; { 173. register struct gold *gold; 174. while(gold = g_at(mtmp->mx, mtmp->my)){ 175. mtmp->mgold += gold->amount; 176. freegold(gold); 177. if(levl[mtmp->mx][mtmp->my].scrsym == GOLD_SYM) 178. newsym(mtmp->mx, mtmp->my); 179. } 180. } 181. 182. /* Now includes giants which pick up enormous rocks. KAA */ 183. mpickgems(mtmp) register struct monst *mtmp; { 184. register struct obj *otmp; 185. for(otmp = fobj; otmp; otmp = otmp->nobj) 186. if(otmp->olet == 187. #ifdef KAA 188. (mtmp->data->mlet=='9' ? ROCK_SYM : GEM_SYM)) 189. #else 190. GEM_SYM) 191. #endif 192. if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my) 193. if(mtmp->data->mlet != 'u' || objects[otmp->otyp].g_val != 0){ 194. freeobj(otmp); 195. mpickobj(mtmp, otmp); 196. #ifndef KAA 197. if(levl[mtmp->mx][mtmp->my].scrsym == GEM_SYM) 198. #endif 199. newsym(mtmp->mx, mtmp->my); /* %% */ 200. return; /* pick only one object */ 201. } 202. } 203. 204. /* return number of acceptable neighbour positions */ 205. mfndpos(mon,poss,info,flag) 206. register struct monst *mon; 207. coord poss[9]; 208. long info[9], flag; 209. { 210. register int x,y,nx,ny,cnt = 0,ntyp; 211. register struct monst *mtmp; 212. int nowtyp; 213. boolean pool; 214. 215. x = mon->mx; 216. y = mon->my; 217. nowtyp = levl[x][y].typ; 218. 219. pool = (mon->data->mlet == ';'); 220. nexttry: /* eels prefer the water, but if there is no water nearby, 221. they will crawl over land */ 222. if(mon->mconf) { 223. flag |= ALLOW_ALL; 224. flag &= ~NOTONL; 225. } 226. for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) 227. if(nx != x || ny != y) if(isok(nx,ny)) 228. #ifdef ROCKMOLE 229. if(!IS_ROCK(ntyp = levl[nx][ny].typ) || (flag & ALLOW_WALL)) 230. #else 231. if(!IS_ROCK(ntyp = levl[nx][ny].typ)) 232. #endif 233. if(!(nx != x && ny != y && (nowtyp == DOOR || ntyp == DOOR))) 234. if((ntyp == POOL) == pool) { 235. info[cnt] = 0; 236. if(nx == u.ux && ny == u.uy){ 237. if(!(flag & ALLOW_U)) continue; 238. info[cnt] = ALLOW_U; 239. } else if(mtmp = m_at(nx,ny)){ 240. if(!(flag & ALLOW_M)) continue; 241. info[cnt] = ALLOW_M; 242. if(mtmp->mtame){ 243. if(!(flag & ALLOW_TM)) continue; 244. info[cnt] |= ALLOW_TM; 245. } 246. } 247. if(sobj_at(CLOVE_OF_GARLIC, nx, ny)) { 248. if(flag & NOGARLIC) continue; 249. info[cnt] |= NOGARLIC; 250. } 251. if(sobj_at(SCR_SCARE_MONSTER, nx, ny) || 252. (!mon->mpeaceful && sengr_at("Elbereth", nx, ny))) { 253. if(!(flag & ALLOW_SSM)) continue; 254. info[cnt] |= ALLOW_SSM; 255. } 256. if(sobj_at(ENORMOUS_ROCK, nx, ny)) { 257. if(!(flag & ALLOW_ROCK)) continue; 258. info[cnt] |= ALLOW_ROCK; 259. } 260. if(!Invis && online(nx,ny)){ 261. if(flag & NOTONL) continue; 262. info[cnt] |= NOTONL; 263. } 264. /* we cannot avoid traps of an unknown kind */ 265. { register struct trap *ttmp = t_at(nx, ny); 266. register long tt; 267. if(ttmp) { 268. tt = 1L << ttmp->ttyp; 269. /* below if added by GAN 02/06/87 to avoid 270. * traps out of range 271. */ 272. if(!(tt & ALLOW_TRAPS)) { 273. impossible("A monster looked at a very strange trap"); 274. continue; 275. } 276. if(mon->mtrapseen & tt){ 277. if(!(flag & tt)) continue; 278. info[cnt] |= tt; 279. } 280. } 281. } 282. poss[cnt].x = nx; 283. poss[cnt].y = ny; 284. cnt++; 285. } 286. if(!cnt && pool && nowtyp != POOL) { 287. pool = FALSE; 288. goto nexttry; 289. } 290. return(cnt); 291. } 292. 293. dist(x,y) int x,y; { 294. return((x-u.ux)*(x-u.ux) + (y-u.uy)*(y-u.uy)); 295. } 296. 297. poisoned(string, pname) 298. register char *string, *pname; 299. { 300. register i, plural; 301. 302. plural = (string[strlen(string) - 1] == 's')? 1 : 0; 303. if(Blind) { 304. if (plural) pline("They were poisoned."); 305. else pline("It was poisoned."); 306. } else { 307. if (plural) pline("The %s were poisoned!", string); 308. else pline("The %s was poisoned!", string); 309. } 310. 311. if(Poison_resistance) { 312. pline("The poison doesn't seem to affect you."); 313. return; 314. } 315. i = rn2(10); 316. if(i == 0) { 317. u.uhp = -1; 318. pline("I am afraid the poison was deadly ..."); 319. } else if(i <= 5) { 320. losestr(rn1(3,3)); 321. } else { 322. losehp(rn1(10,6), pname); 323. } 324. if(u.uhp < 1) { 325. killer = pname; 326. done("died"); 327. } 328. } 329. 330. mondead(mtmp) 331. register struct monst *mtmp; 332. { 333. relobj(mtmp,1); 334. unpmon(mtmp); 335. relmon(mtmp); 336. unstuck(mtmp); 337. #ifdef KOPS 338. if(mtmp->data->mlet == 'K' && 339. !strcmp(mtmp->data->mname,"Keystone Kop")) { 340. /* When a Kop dies, he probably comes back. */ 341. switch(rnd(3)) { 342. 343. case 1: /* returns near the stairs */ 344. mkmon_at('K',xdnstair,ydnstair); 345. break; 346. case 2: /* randomly */ 347. mkmon_at('K',0,0); 348. break; 349. default: 350. break; 351. } 352. } 353. #endif 354. if(mtmp->isshk) shkdead(mtmp); 355. if(mtmp->isgd) gddead(); 356. #ifndef NOWORM 357. if(mtmp->wormno) wormdead(mtmp); 358. #endif 359. #ifdef HARD 360. if(mtmp->data->mlet == '1') wizdead(mtmp); 361. #endif 362. monfree(mtmp); 363. } 364. 365. /* called when monster is moved to larger structure */ 366. replmon(mtmp,mtmp2) 367. register struct monst *mtmp, *mtmp2; 368. { 369. relmon(mtmp); 370. monfree(mtmp); 371. mtmp2->nmon = fmon; 372. fmon = mtmp2; 373. if(u.ustuck == mtmp) u.ustuck = mtmp2; 374. if(mtmp2->isshk) replshk(mtmp,mtmp2); 375. if(mtmp2->isgd) replgd(mtmp,mtmp2); 376. } 377. 378. relmon(mon) 379. register struct monst *mon; 380. { 381. register struct monst *mtmp; 382. 383. if (fmon == 0) panic ("relmon: no fmon available."); 384. 385. if(mon == fmon) fmon = fmon->nmon; 386. else { 387. for(mtmp = fmon; mtmp->nmon != mon; mtmp = mtmp->nmon) ; 388. mtmp->nmon = mon->nmon; 389. } 390. } 391. 392. /* we do not free monsters immediately, in order to have their name 393. available shortly after their demise */ 394. struct monst *fdmon; /* chain of dead monsters, need not to be saved */ 395. 396. monfree(mtmp) register struct monst *mtmp; { 397. mtmp->nmon = fdmon; 398. fdmon = mtmp; 399. } 400. 401. dmonsfree(){ 402. register struct monst *mtmp; 403. while(mtmp = fdmon){ 404. fdmon = mtmp->nmon; 405. free((char *) mtmp); 406. } 407. } 408. 409. unstuck(mtmp) 410. register struct monst *mtmp; 411. { 412. if(u.ustuck == mtmp) { 413. if(u.uswallow){ 414. u.ux = mtmp->mx; 415. u.uy = mtmp->my; 416. u.uswallow = 0; 417. setsee(); 418. docrt(); 419. } 420. u.ustuck = 0; 421. } 422. } 423. 424. killed(mtmp) 425. register struct monst *mtmp; 426. { 427. xkilled(mtmp, 1); 428. } 429. 430. xkilled(mtmp, dest) 431. register struct monst *mtmp; 432. int dest; 433. /* Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse 434. either; dest=3, message but no corpse */ 435. { 436. #ifdef LINT 437. #define NEW_SCORING 438. #endif 439. register int tmp,tmp2,nk,x,y; 440. register struct permonst *mdat = mtmp->data; 441. extern long newuexp(); 442. #ifdef RPH 443. int old_nlth; 444. char old_name[BUFSZ]; 445. #endif 446. 447. if(mtmp->cham) mdat = PM_CHAMELEON; 448. if (dest & 1) { 449. if(Blind) pline("You destroy it!"); 450. else { 451. pline("You destroy %s!", 452. mtmp->mtame ? amonnam(mtmp, "poor") : monnam(mtmp)); 453. } 454. } 455. if(u.umconf) { 456. if(!Blind) 457. { 458. pline("Your hands stop glowing %s.", 459. Hallucination ? hcolor() : "blue"); 460. } 461. u.umconf = 0; 462. } 463. 464. /* count killed monsters */ 465. #define MAXMONNO 100 466. nk = 1; /* in case we cannot find it in mons */ 467. tmp = mdat - mons; /* index in mons array (if not 'd', '@', ...) */ 468. if(tmp >= 0 && tmp < CMNUM+2) { 469. extern char fut_geno[]; 470. u.nr_killed[tmp]++; 471. if((nk = u.nr_killed[tmp]) > MAXMONNO && 472. #ifdef HARD 473. # ifdef KOPS 474. !index("KkO&", mdat->mlet) && 475. # else 476. !index("kO&", mdat->mlet) && 477. # endif 478. #endif 479. !index(fut_geno, mdat->mlet)) 480. charcat(fut_geno, mdat->mlet); 481. } 482. 483. /* punish bad behaviour */ 484. if(mdat->mlet == '@') { 485. HTelepat = 0; 486. u.uluck -= 2; 487. } 488. if(mtmp->mpeaceful || mtmp->mtame) u.uluck--; 489. if(mdat->mlet == 'u') u.uluck -= 5; 490. if((int)u.uluck < LUCKMIN) u.uluck = LUCKMIN; 491. 492. /* give experience points */ 493. tmp = 1 + mdat->mlevel * mdat->mlevel; 494. if(mdat->ac < 3) tmp += 2*(7 - mdat->ac); 495. if(index( 496. #ifdef RPH 497. # ifdef KAA 498. "AcsSDXaeRTVWU&In:P89", 499. # else 500. "AcsSDXaeRTVWU&In:P8", 501. # endif 502. #else 503. # ifdef KAA 504. "AcsSDXaeRTVWU&In:P9", 505. # else 506. "AcsSDXaeRTVWU&In:P", 507. # endif 508. #endif 509. mdat->mlet)) tmp += 2*mdat->mlevel; 510. 511. if(index("DeV&P",mdat->mlet)) tmp += (7*mdat->mlevel); 512. if(mdat->mlevel > 6) tmp += 50; 513. if(mdat->mlet == ';') tmp += 1000; 514. 515. #ifdef NEW_SCORING 516. /* ------- recent addition: make nr of points decrease 517. when this is not the first of this kind */ 518. { int ul = u.ulevel; 519. int ml = mdat->mlevel; 520. 521. if(ul < 14) /* points are given based on present and future level */ 522. for(tmp2 = 0; !tmp2 || ul + tmp2 <= ml; tmp2++) 523. if(u.uexp + 1 + (tmp + ((tmp2 <= 0) ? 0 : 4<<(tmp2-1)))/nk 524. >= 10*pow((unsigned)(ul-1))) 525. if(++ul == 14) break; 526. 527. tmp2 = ml - ul -1; 528. tmp = (tmp + ((tmp2 < 0) ? 0 : 4<<tmp2))/nk; 529. if(!tmp) tmp = 1; 530. } 531. /* note: ul is not necessarily the future value of u.ulevel */ 532. /* ------- end of recent valuation change ------- */ 533. #endif /* NEW_SCORING /**/ 534. 535. more_experienced(tmp,0); 536. flags.botl = 1; 537. while(u.ulevel < 14 && u.uexp >= newuexp()){ 538. #ifdef RPH 539. /* make experience gaining simiar to d&d, whereby you */ 540. /* can at most go up by one level at a time, extra expr */ 541. /* possibly helping you along. Afterall, how much real */ 542. /* experience does one get shooting a wand of death at */ 543. /* a dragon created w/ a poymorph?? */ 544. u.ulevel++; 545. if (u.uexp >= newuexp()) 546. u.uexp = newuexp() - 1; 547. pline("Welcome to experience level %u.", u.ulevel); 548. #else 549. pline("Welcome to experience level %u.", ++u.ulevel); 550. #endif 551. tmp = rnd(10); 552. if(tmp < 3) tmp = rnd(10); 553. u.uhpmax += tmp; 554. u.uhp += tmp; 555. #ifdef SPELLS 556. tmp = rnd(u.ulevel/2+1) + 1; /* M. Stephenson */ 557. u.uenmax += tmp; 558. u.uen += tmp; 559. #endif 560. flags.botl = 1; 561. } 562. 563. /* dispose of monster and make cadaver */ 564. x = mtmp->mx; y = mtmp->my; 565. #ifdef RPH 566. old_nlth = mtmp->mnamelth; 567. if (old_nlth > 0) (void) strcpy (old_name, NAME(mtmp)); 568. #endif 569. mondead(mtmp); 570. tmp = mdat->mlet; 571. if(tmp == 'm') { /* he killed a minotaur, give him a wand of digging */ 572. /* note: the dead minotaur will be on top of it! */ 573. mksobj_at(WAN_DIGGING, x, y); 574. /* if(cansee(x,y)) atl(x,y,fobj->olet); */ 575. stackobj(fobj); 576. } else 577. #ifndef NOWORM 578. if(tmp == 'w') { 579. mksobj_at(WORM_TOOTH, x, y); 580. stackobj(fobj); 581. } else 582. #endif 583. #ifdef KJSMODS 584. if(tmp == 'N') { 585. mksobj_at(POT_OBJECT_DETECTION, x, y); 586. stackobj(fobj); 587. } else 588. #endif 589. #ifdef KAA 590. if(tmp == '&') (void) mkobj_at(0, x, y); 591. else 592. if(stoned == FALSE && (!letter(tmp) || (!index("9&1", tmp) && !rn2(3)))) tmp = 0; 593. if(dest & 2) { 594. newsym(x,y); 595. return; 596. } 597. #else 598. if(!letter(tmp) || (!index("mw", tmp) && !rn2(3))) tmp = 0; 599. #endif 600. tmp2 = rn2(5); 601. #ifdef KJSMODS 602. /* if a kobold or a giant rat does not become treasure, do 603. * not make a corpse. */ 604. # ifdef KOPS 605. if(mdat->mlet == 'K' 606. && !strcmp(mdat->mname,"kobold") && tmp) tmp2 = 0; 607. # endif 608. # ifdef ROCKMOLE 609. if((mdat->mlet == 'r' && dlevel < 4) && tmp) tmp2 = 0; 610. # endif 611. #endif 612. if(!ACCESSIBLE(levl[x][y].typ)) { 613. /* might be mimic in wall or dead eel*/ 614. newsym(x,y); 615. } else if(x != u.ux || y != u.uy) { 616. /* might be here after swallowed */ 617. #ifdef KAA 618. if(stoned) { 619. register int typetmp; 620. if(index(mlarge, tmp)) typetmp = ENORMOUS_ROCK; 621. else typetmp = ROCK; 622. mksobj_at(typetmp, x, y); 623. if(cansee(x,y)) 624. atl(x, y, Hallucination ? rndobjsym() : 625. objects[typetmp].oc_olet); 626. } else 627. #endif 628. if(index("NTVm&w",mdat->mlet) || tmp2) { 629. #ifndef RPH 630. register struct obj *obj2 = mkobj_at(tmp,x,y); 631. #else 632. register struct obj *obj2; 633. if (letter(tmp)) 634. obj2 = mk_named_obj_at(tmp, x, y, 635. old_name, old_nlth); 636. # ifdef KOPS 637. else if (mdat->mlet == 'K') 638. obj2 = mksobj_at((rn2(4) ? CLUB : WHISTLE), x, y); 639. # endif 640. else 641. obj2 = mkobj_at(tmp,x,y); 642. #endif /* RPH /**/ 643. if(cansee(x,y)) 644. atl(x, y, Hallucination ? rndobjsym() : obj2->olet); 645. stackobj(obj2); 646. } 647. } 648. } 649. 650. kludge(str,arg) 651. register char *str,*arg; 652. { 653. if(Blind) { 654. if(*str == '%') pline(str,"It"); 655. else pline(str,"it"); 656. } else pline(str,arg); 657. } 658. 659. rescham() /* force all chameleons to become normal */ 660. { 661. register struct monst *mtmp; 662. 663. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 664. if(mtmp->cham) { 665. mtmp->cham = 0; 666. (void) newcham(mtmp, PM_CHAMELEON); 667. } 668. } 669. 670. #ifdef DGKMOD 671. /* Let the chameleons change again -dgk */ 672. restartcham() 673. { 674. register struct monst *mtmp; 675. 676. for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) 677. if (mtmp->data->mlet == ':') 678. mtmp->cham = 1; 679. } 680. #endif 681. 682. newcham(mtmp,mdat) /* make a chameleon look like a new monster */ 683. /* returns 1 if the monster actually changed */ 684. register struct monst *mtmp; 685. register struct permonst *mdat; 686. { 687. register mhp, hpn, hpd; 688. 689. if(mdat == mtmp->data) return(0); /* still the same monster */ 690. #ifndef NOWORM 691. if(mtmp->wormno) wormdead(mtmp); /* throw tail away */ 692. #endif 693. hpn = mtmp->mhp; 694. hpd = (mtmp->data->mlevel)*8; if(!hpd) hpd = 4; 695. mhp = (mdat->mlevel)*8; if(!mhp) mhp = 4; 696. 697. /* new hp: same fraction of max as before */ 698. mtmp->mhp = (hpn*mhp)/hpd; 699. if (mhp > hpd && mtmp->mhp < hpn) mtmp->mhp = 127; 700. /* Not totally foolproof. A 2HD monster with 80 HP that changes into a 6HD 701. monster that really should have 240 and actually should have 127, the 702. maximum possible, will wind up having 113. */ 703. if (!mtmp->mhp) mtmp->mhp = 1; 704. /* Unlikely but not impossible; a 1HD creature with 1HP that changes into a 705. 0HD creature will require this statement */ 706. mtmp->data = mdat; 707. /* and the same for maximum hit points */ 708. hpn = mtmp->mhpmax; 709. mtmp->mhpmax = (hpn*mhp)/hpd; 710. if (mhp > hpd && mtmp->mhpmax < hpn) mtmp->mhp = 127; 711. if (!mtmp->mhp) mtmp->mhp = 1; 712. 713. mtmp->minvis = (mdat->mlet == 'I') ? 1 : 0; 714. /* only snakes and scorpions can hide under things -dgk */ 715. /* also generated by GAN */ 716. mtmp->mhide = (mdat->mlet == 'S' || mdat->mlet == 's') ? 1 : 0; 717. if (!mtmp->mhide) mtmp->mundetected = 0; 718. #ifndef NOWORM 719. if(mdat->mlet == 'w' && getwn(mtmp)) initworm(mtmp); 720. /* perhaps we should clear mtmp->mtame here? */ 721. #endif 722. unpmon(mtmp); /* necessary for 'I' and to force pmon */ 723. pmon(mtmp); 724. return(1); 725. } 726. 727. mnexto(mtmp) /* Make monster mtmp next to you (if possible) */ 728. struct monst *mtmp; 729. { 730. coord mm; 731. enexto(&mm, u.ux, u.uy); 732. mtmp->mx = mm.x; 733. mtmp->my = mm.y; 734. pmon(mtmp); 735. } 736. 737. ishuman(mtmp) register struct monst *mtmp; { 738. return(mtmp->data->mlet == '@'); 739. } 740. 741. setmangry(mtmp) register struct monst *mtmp; { 742. if(!mtmp->mpeaceful) return; 743. if(mtmp->mtame) return; 744. mtmp->mpeaceful = 0; 745. if(ishuman(mtmp)) pline("%s gets angry!", Monnam(mtmp)); 746. } 747. 748. /* not one hundred procent correct: now a snake may hide under an 749. invisible object */ 750. canseemon(mtmp) 751. register struct monst *mtmp; 752. { 753. return((!mtmp->minvis || See_invisible) 754. && (!mtmp->mhide || !o_at(mtmp->mx,mtmp->my)) 755. && cansee(mtmp->mx, mtmp->my)); 756. } 757. 758. disturb(mtmp) /* awaken monsters while in the same room. 759. * return a 1 if they have been woken. 760. */ 761. register struct monst *mtmp; 762. { 763. /* wake up, or get out of here. */ 764. /* ettins are hard to surprise */ 765. /* Nymphs and Leprechauns do not easily wake up */ 766. if(cansee(mtmp->mx,mtmp->my) && 767. (!Stealth || (mtmp->data->mlet == 'e' && rn2(10))) && 768. (!index("NL",mtmp->data->mlet) || !rn2(50)) && 769. #ifdef RPH 770. (Aggravate_monster || index("8d1", mtmp->data->mlet) 771. #else 772. (Aggravate_monster || index("d1", mtmp->data->mlet) 773. #endif 774. || (!rn2(7) && !mtmp->mimic))) { 775. mtmp->msleep = 0; 776. return(1); 777. } 778. if(Hallucination) pmon(mtmp); 779. return(0); 780. } 781. 782. #ifdef HARD 783. restrap(mtmp) /* unwatched mimics and piercers may hide again, 784. * if so, a 1 is returned. 785. */ 786. register struct monst *mtmp; 787. { 788. if(mtmp->data->mlet == 'M' && !mtmp->mimic && !mtmp->cham 789. && !mtmp->mcan && !cansee(mtmp->mx, mtmp->my) 790. && !rn2(3)) { 791. mtmp->mimic = 1; 792. mtmp->mappearance = (levl[mtmp->mx][mtmp->my].typ == DOOR) ? DOOR_SYM : GOLD_SYM; 793. return(1); 794. } 795. 796. if(mtmp->data->mlet == 'p' && !mtmp->cham 797. && !mtmp->mcan && !cansee(mtmp->mx, mtmp->my) 798. && !rn2(3)) { 799. 800. if(levl[mtmp->mx][mtmp->my].typ == ROOM) { 801. 802. maketrap(mtmp->mx, mtmp->my, PIERC); 803. mondead(mtmp); 804. return(1); 805. } 806. } 807. return(0); 808. } 809. #endif