Source:NetHack 2.2a/monmove.c

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