abstract
| - Below is the full text to monmove.c from the source code of NetHack 2.3e. To link to a particular line, write [[NetHack 2.3e/monmove.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)monmove.c 2.3 87/12/12 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. 4. #include "hack.h" 5. #include "mfndpos.h" 6. #define NULL (char *) 0 7. 8. extern struct obj *mksobj_at(); 9. extern int warnlevel; /* defined in mon.c */ 10. 11. dochugw(mtmp) register struct monst *mtmp; { 12. register x = mtmp->mx; 13. register y = mtmp->my; 14. register d = dochug(mtmp); 15. register dd; 16. if(!d) /* monster still alive */ 17. if(Warning) 18. if(!mtmp->mpeaceful) 19. if(mtmp->data->mlevel > warnlevel) 20. if((dd = dist(mtmp->mx,mtmp->my)) < dist(x,y)) 21. if(dd < 100) 22. if(!canseemon(mtmp)) 23. warnlevel = mtmp->data->mlevel; 24. return(d); 25. } 26. 27. /* returns 1 if monster died moving, 0 otherwise */ 28. dochug(mtmp) 29. register struct monst *mtmp; 30. { 31. register struct permonst *mdat; 32. register tmp, nearby, scared, onscary; 33. 34. if(mtmp->cham && !rn2(6)) 35. (void) newcham(mtmp, 36. #ifndef RPH 37. &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); 38. #else 39. (struct permonst *)0); 40. #endif 41. mdat = mtmp->data; 42. if(mdat->mlevel < 0) 43. panic("bad monster %c (%d)",mdat->mlet,mdat->mlevel); 44. 45. /* regenerate monsters */ 46. if((!(moves%20) || index(MREGEN, mdat->mlet)) && 47. mtmp->mhp < mtmp->mhpmax) 48. mtmp->mhp++; 49. 50. if(mtmp->mfroz) { 51. if (Hallucination) pmon(mtmp); 52. return(0); /* frozen monsters don't do anything */ 53. } 54. 55. if(mtmp->msleep) /* there is a chance we will wake it */ 56. if(!disturb(mtmp)) return(0); 57. 58. /* not frozen or sleeping: wipe out texts written in the dust */ 59. wipe_engr_at(mtmp->mx, mtmp->my, 1); 60. 61. /* confused monsters get unconfused with small probability */ 62. if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0; 63. 64. /* some monsters teleport */ 65. if(mtmp->mflee && index("tNL", mdat->mlet) && !rn2(40)){ 66. rloc(mtmp); 67. return(0); 68. } 69. if(mdat->mmove < rnd(6)) return(0); 70. 71. /* fleeing monsters might regain courage */ 72. if(mtmp->mflee && !mtmp->mfleetim 73. && mtmp->mhp == mtmp->mhpmax && !rn2(25)) 74. mtmp->mflee = 0; 75. 76. nearby = (dist(mtmp->mx, mtmp->my) < 3); 77. onscary = (sengr_at("Elbereth", u.ux, u.uy) || 78. sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy)); 79. scared = (nearby && onscary && !mtmp->mtame && mtmp->mcansee) 80. && (mdat->mlet != '1'); /* RPH: the wiz is never scared */ 81. if(scared && !mtmp->mflee) { 82. mtmp->mflee = 1; 83. mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100)); 84. } 85. 86. if(!nearby || 87. mtmp->mflee || scared || 88. mtmp->mconf || 89. (mtmp->minvis && !rn2(3)) || 90. #ifndef KOPS 91. (index("BIuy", mdat->mlet) && !rn2(4)) || 92. #else 93. (index("KBIuy", mdat->mlet) && !rn2(4)) || 94. #endif 95. (mdat->mlet == 'L' && !u.ugold && (mtmp->mgold || rn2(2))) || 96. (!mtmp->mcansee && !rn2(4)) || 97. mtmp->mpeaceful 98. ) { 99. tmp = m_move(mtmp,0); /* 2: monster died moving */ 100. if(tmp == 2 || (tmp && mdat->mmove <= 12)) 101. return(tmp == 2); 102. 103. if(Hallucination && tmp==0) pmon(mtmp); 104. /* If 0, this means the monster didn't move. During hallucination, its 105. appearance should still change. */ 106. 107. #ifdef HARD 108. /* Without this line, fast monsters don't hit you when they've 109. * caught up to you. -dgk 110. */ 111. nearby = (dist(mtmp->mx, mtmp->my) < 3); 112. scared = (nearby && onscary); 113. if(scared && !mtmp->mflee) { 114. mtmp->mflee = 1; 115. mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100)); 116. } 117. #endif 118. } 119. #ifdef HARD /* Demonic Blackmail!!! */ 120. if(mdat->mlet == '&' && mtmp->mpeaceful 121. && !mtmp->mtame && !mtmp->isdjinni) 122. if(demon_talk(mtmp)) 123. return(1); /* you paid it off */ 124. #endif 125. if(!index("Ea", mdat->mlet) && nearby && 126. !mtmp->mpeaceful && u.uhp > 0 && !scared) { 127. if(mhitu(mtmp)) 128. return(1); /* monster died (e.g. 'y' or 'F') */ 129. } 130. /* extra movement for fast monsters */ 131. if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp,1); 132. return(tmp == 2); 133. } 134. 135. m_move(mtmp,after) 136. register struct monst *mtmp; 137. { 138. #ifndef REGBUG 139. register 140. #endif 141. struct monst *mtmp2; 142. #ifndef REGBUG 143. register 144. #endif 145. int nx,ny,omx,omy,appr,nearer,cnt,i,j; 146. xchar gx,gy,nix,niy,chcnt; 147. schar chi; 148. boolean likegold, likegems, likeobjs; 149. #ifdef KAA 150. boolean likerock; 151. #endif 152. char msym = mtmp->data->mlet; 153. schar mmoved = 0; /* not strictly nec.: chi >= 0 will do */ 154. coord poss[9]; 155. long info[9]; 156. 157. if(mtmp->mfroz || mtmp->msleep) 158. return(0); 159. if(mtmp->mtrapped) { 160. i = mintrap(mtmp); 161. if(i == 2) return(2); /* he died */ 162. if(i == 1) return(0); /* still in trap, so didnt move */ 163. } 164. if(mtmp->mhide && o_at(mtmp->mx,mtmp->my) && rn2(10)) 165. return(0); /* do not leave hiding place */ 166. 167. #ifndef NOWORM 168. if(mtmp->wormno) 169. goto not_special; 170. #endif 171. 172. /* my dog gets a special treatment */ 173. if(mtmp->mtame) { 174. return( dog_move(mtmp, after) ); 175. } 176. 177. /* likewise for shopkeeper */ 178. if(mtmp->isshk) { 179. mmoved = shk_move(mtmp); 180. if(mmoved >= 0) 181. goto postmov; 182. mmoved = 0; /* follow player outside shop */ 183. } 184. 185. /* and for the guard */ 186. if(mtmp->isgd) { 187. mmoved = gd_move(); 188. goto postmov; 189. } 190. 191. /* teleport if that lies in our nature ('t') or when badly wounded ('1') */ 192. if((msym == 't' && !rn2(5)) 193. || (msym == '1' && (mtmp->mhp < 7 || (!xdnstair && !rn2(5)) 194. || levl[u.ux][u.uy].typ == STAIRS))) { 195. if(mtmp->mhp < 7 || (msym == 't' && rn2(2))) 196. rloc(mtmp); 197. else 198. mnexto(mtmp); 199. mmoved = 1; 200. goto postmov; 201. } 202. 203. /* spit fire ('D') or use a wand ('1') when appropriate */ 204. #ifdef DGKMOD 205. /* Add arrow and bolt throwing monsters */ 206. if (index( 207. # ifdef KAA 208. # ifdef KOPS 209. "D1OKC9", 210. # else 211. "D1KC9", 212. # endif 213. # else 214. # ifdef KOPS 215. "D1OKC", 216. # else 217. "D1KC", 218. # endif 219. # endif 220. msym)) 221. 222. if (!inrange(mtmp)) /* inrange returns 1 if OK for mon */ 223. return(0); /* to move after it zaps or throws */ 224. #else 225. if(index("D1", msym)) 226. inrange(mtmp); 227. #endif 228. 229. if(msym == 'U' && !mtmp->mcan && canseemon(mtmp) && 230. mtmp->mcansee && rn2(5)) { 231. if(!Confusion) 232. pline("%s's gaze has confused you!", Monnam(mtmp)); 233. else 234. pline("You are getting more and more confused."); 235. if(rn2(3)) mtmp->mcan = 1; 236. HConfusion += d(3,4); /* timeout */ 237. } 238. #ifdef RPH 239. if (msym == '8' && canseemon(mtmp)) { 240. if (mtmp->mcan) 241. pline ("You notice that %s isn't all that ugly.",monnam(mtmp)); 242. else if (rn2(3)) 243. pline ("You see the ugly back of %s.", monnam(mtmp)); 244. else { 245. pline ("You look upon %s.", monnam(mtmp)); 246. pline ("You turn to stone."); 247. done_in_by(mtmp); 248. } 249. } 250. #endif 251. not_special: 252. if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1); 253. appr = 1; 254. if(mtmp->mflee) appr = -1; 255. if(mtmp->mconf || Invis || !mtmp->mcansee || 256. (index("BIy", msym) && !rn2(3))) 257. appr = 0; 258. omx = mtmp->mx; 259. omy = mtmp->my; 260. gx = u.ux; 261. gy = u.uy; 262. if(msym == 'L' && appr == 1 && mtmp->mgold > u.ugold) 263. appr = -1; 264. 265. /* random criterion for 'smell' or track finding ability 266. should use mtmp->msmell or sth 267. */ 268. if(msym == '@' || 269. #ifdef RPH 270. uwep && !strcmp(ONAME(uwep), "Excalibur") || 271. #endif 272. ('a' <= msym && msym <= 'z')) { 273. extern coord *gettrack(); 274. register coord *cp; 275. schar mroom; 276. mroom = inroom(omx,omy); 277. if(mroom < 0 || mroom != inroom(u.ux,u.uy)){ 278. cp = gettrack(omx,omy); 279. if(cp){ 280. gx = cp->x; 281. gy = cp->y; 282. } 283. } 284. } 285. 286. /* look for gold or jewels nearby */ 287. #ifdef ROCKMOLE 288. likegold = (index("LODr", msym) != NULL); 289. likegems = (index("ODu", msym) != NULL); 290. # ifdef KJSMODS 291. likeobjs = (mtmp->mhide || (msym == 'r' && dlevel > 3)); 292. # else 293. likeobjs = (mtmp->mhide || msym == 'r'); 294. # endif 295. #else 296. likegold = (index("LOD", msym) != NULL); 297. likegems = (index("ODu", msym) != NULL); 298. likeobjs = mtmp->mhide; 299. #endif 300. #ifdef KAA 301. likerock = (msym == '9'); 302. #endif 303. #define SRCHRADIUS 25 304. { xchar mind = SRCHRADIUS; /* not too far away */ 305. register int dd; 306. if(likegold){ 307. register struct gold *gold; 308. for(gold = fgold; gold; gold = gold->ngold) 309. if((dd = DIST(omx,omy,gold->gx,gold->gy)) < mind){ 310. mind = dd; 311. gx = gold->gx; 312. gy = gold->gy; 313. } 314. } 315. if(likegems || likeobjs 316. #ifdef KAA 317. || likerock 318. #endif 319. ) { 320. register struct obj *otmp; 321. for(otmp = fobj; otmp; otmp = otmp->nobj) 322. if(likeobjs 323. || (likegems && otmp->olet == GEM_SYM) 324. #ifdef KAA 325. || (likerock && otmp->olet == ROCK_SYM) 326. #endif 327. ) { 328. if(msym != 'u' || objects[otmp->otyp].g_val != 0) 329. if((dd = DIST(omx,omy,otmp->ox,otmp->oy)) < mind){ 330. mind = dd; 331. gx = otmp->ox; 332. gy = otmp->oy; 333. } 334. } 335. } 336. if(mind < SRCHRADIUS && appr == -1) { 337. if(dist(omx,omy) < 10) { 338. gx = u.ux; 339. gy = u.uy; 340. } else 341. appr = 1; 342. } 343. } 344. nix = omx; 345. niy = omy; 346. cnt = mfndpos(mtmp,poss,info, 347. msym == 'u' ? NOTONL : 348. #ifdef ROCKMOLE 349. # ifdef KJSMODS 350. (msym == 'r' && dlevel > 3) ? ALLOW_WALL : 351. # else 352. msym == 'r' ? ALLOW_WALL : 353. # endif 354. #endif 355. (msym == '@' || msym == '1') ? (ALLOW_SSM | ALLOW_TRAPS) : 356. index(UNDEAD, msym) ? NOGARLIC : 357. #ifdef KAA 358. (msym == '9') ? (ALLOW_ROCK | ALLOW_TRAPS) : ALLOW_TRAPS); 359. #else 360. ALLOW_TRAPS); 361. #endif 362. chcnt = 0; 363. chi = -1; 364. for(i=0; i 365. nx = poss[i].x; 366. ny = poss[i].y; 367. for(j=0; j 368. if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y) 369. if(rn2(4*(cnt-j))) goto nxti; 370. #ifdef STUPID 371. /* some stupid compilers think that this is too complicated */ 372. { int d1 = DIST(nx,ny,gx,gy); 373. int d2 = DIST(nix,niy,gx,gy); 374. nearer = (d1 < d2); 375. } 376. #else 377. nearer = (DIST(nx,ny,gx,gy) < DIST(nix,niy,gx,gy)); 378. #endif 379. if((appr == 1 && nearer) || (appr == -1 && !nearer) || 380. !mmoved || 381. (!appr && !rn2(++chcnt))){ 382. nix = nx; 383. niy = ny; 384. chi = i; 385. mmoved = 1; 386. } 387. nxti: ; 388. } 389. if(mmoved){ 390. if(info[chi] & ALLOW_M){ 391. mtmp2 = m_at(nix,niy); 392. if(hitmm(mtmp,mtmp2) == 1 && rn2(4) && 393. hitmm(mtmp2,mtmp) == 2) return(2); 394. return(0); 395. } 396. if(info[chi] & ALLOW_U){ 397. (void) hitu(mtmp, d(mtmp->data->damn, mtmp->data->damd)+1); 398. return(0); 399. } 400. mtmp->mx = nix; 401. mtmp->my = niy; 402. for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1]; 403. mtmp->mtrack[0].x = omx; 404. mtmp->mtrack[0].y = omy; 405. #ifndef NOWORM 406. if(mtmp->wormno) worm_move(mtmp); 407. #endif 408. } else { 409. if(msym == 'u' && rn2(2)){ 410. rloc(mtmp); 411. return(0); 412. } 413. #ifndef NOWORM 414. if(mtmp->wormno) worm_nomove(mtmp); 415. #endif 416. } 417. postmov: 418. if(mmoved == 1) { 419. if(mintrap(mtmp) == 2) /* he died */ 420. return(2); 421. #ifdef ROCKMOLE 422. /* Maybe a rock mole just ate something? */ 423. if(msym == 'r' 424. # ifdef KJSMODS 425. && dlevel > 3 426. #endif 427. && IS_ROCK(levl[mtmp->mx][mtmp->my].typ) && 428. levl[mtmp->mx][mtmp->my].typ != POOL){ 429. register int pile = rnd(25); 430. /* Just ate something. */ 431. if(levl[mtmp->mx][mtmp->my].typ == 0) 432. levl[mtmp->mx][mtmp->my].typ = CORR; 433. else if(IS_WALL(levl[mtmp->mx][mtmp->my].typ)) 434. levl[mtmp->mx][mtmp->my].typ = DOOR; 435. mnewsym(mtmp->mx,mtmp->my); 436. /* Left behind a pile? */ 437. if(pile < 5) { 438. if(pile == 1) 439. mksobj_at(ENORMOUS_ROCK, mtmp->mx, mtmp->my); 440. else 441. mksobj_at(ROCK, mtmp->mx, mtmp->my); 442. } 443. if(cansee(mtmp->mx, mtmp->my)) 444. if(fobj) atl(mtmp->mx,mtmp->my,fobj->olet); 445. } 446. /* Maybe a rock mole just ate some gold or armor? */ 447. if(msym == 'r') meatgold(mtmp); 448. #endif /* ROCKMOLE /**/ 449. if(likegold) mpickgold(mtmp); 450. #ifdef KAA 451. if(likerock || likegems) mpickgems(mtmp); 452. #else 453. if(likegems) mpickgems(mtmp); 454. #endif 455. if(mtmp->mhide) mtmp->mundetected = 1; 456. } 457. pmon(mtmp); 458. return(mmoved); 459. } 460.
|