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