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