Source:NetHack 1.3d/monmove.c

Below is the full text to monmove.c from the source code of NetHack 1.3d. To link to a particular line, write [[NetHack 1.3d/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	1.3	87/07/14 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* monmove.c - version 1.0 */ 4.    5.    #include "hack.h"  6.    #include "mfndpos.h"  7.    #define	NULL	(char *) 0 8.    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, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); 36.  	mdat = mtmp->data; 37.  	if(mdat->mlevel < 0) 38.  		panic("bad monster %c (%d)",mdat->mlet,mdat->mlevel); 39.   40.   	/* regenerate monsters */ 41.  	if((!(moves%20) || index(MREGEN, mdat->mlet)) &&  42.   	    mtmp->mhp < mtmp->mhpmax) 43.  		mtmp->mhp++; 44.   45.   	if(mtmp->mfroz) { 46.  		if (Hallucination) pmon(mtmp); 47.  		return(0);	/* frozen monsters don't do anything */ 48.  	}  49.    50.   	if(mtmp->msleep)	/* there is a chance we will wake it */ 51.  		if(!disturb(mtmp)) return(0); 52.   53.   	/* not frozen or sleeping: wipe out texts written in the dust */ 54.  	wipe_engr_at(mtmp->mx, mtmp->my, 1); 55.   56.   	/* confused monsters get unconfused with small probability */ 57.  	if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0; 58.   59.   	/* some monsters teleport */ 60.  	if(mtmp->mflee && index("tNL", mdat->mlet) && !rn2(40)){ 61.  		rloc(mtmp); 62.  		return(0); 63.  	}  64.   	if(mdat->mmove < rnd(6)) return(0); 65.   66.   	/* fleeing monsters might regain courage */ 67.  	if(mtmp->mflee && !mtmp->mfleetim  68.   	    && mtmp->mhp == mtmp->mhpmax && !rn2(25)) 69.  		mtmp->mflee = 0; 70.   71.   	nearby = (dist(mtmp->mx, mtmp->my) < 3); 72.  	onscary = (sengr_at("Elbereth", u.ux, u.uy) ||  73.   			sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy)); 74.  	scared = (nearby && onscary && !mtmp->mtame && mtmp->mcansee); 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.  not_special: 232. 	if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1); 233. 	appr = 1; 234. 	if(mtmp->mflee) appr = -1; 235. 	if(mtmp->mconf || Invis ||  !mtmp->mcansee ||  236.  		(index("BIy", msym) && !rn2(3))) 237. 		appr = 0; 238. 	omx = mtmp->mx; 239. 	omy = mtmp->my; 240. 	gx = u.ux; 241. 	gy = u.uy; 242. 	if(msym == 'L' && appr == 1 && mtmp->mgold > u.ugold) 243. 		appr = -1; 244.  245.  	/* random criterion for 'smell' or track finding ability 246. 	   should use mtmp->msmell or sth 247. 	 */  248.  	if(msym == '@' ||  249.  	  ('a' <= msym && msym <= 'z')) { 250. 	extern coord *gettrack; 251. 	register coord *cp; 252. 	schar mroom; 253. 		mroom = inroom(omx,omy); 254. 		if(mroom < 0 || mroom != inroom(u.ux,u.uy)){ 255. 		    cp = gettrack(omx,omy); 256. 		    if(cp){ 257. 			gx = cp->x; 258. 			gy = cp->y; 259. 		    }  260.  		}  261.  	}  262.   263.  	/* look for gold or jewels nearby */ 264. #ifdef ROCKMOLE 265. 	likegold = (index("LODr", msym) != NULL); 266. 	likegems = (index("ODu", msym) != NULL); 267. 	likeobjs = (mtmp->mhide || msym == 'r'); 268. #else 269. 	likegold = (index("LOD", msym) != NULL); 270. 	likegems = (index("ODu", msym) != NULL); 271. 	likeobjs = mtmp->mhide; 272. #endif 273. #ifdef KAA 274. 	likerock = (msym == '9'); 275. #endif 276. #define	SRCHRADIUS	25 277. 	{ xchar mind = SRCHRADIUS;		/* not too far away */ 278. 	  register int dd; 279. 	  if(likegold){ 280. 		register struct gold *gold; 281. 		for(gold = fgold; gold; gold = gold->ngold) 282. 		  if((dd = DIST(omx,omy,gold->gx,gold->gy)) < mind){ 283. 		    mind = dd; 284. 		    gx = gold->gx; 285. 		    gy = gold->gy; 286. 		}  287.  	  }  288.  	  if(likegems || likeobjs  289.  #ifdef KAA  290.  				  || likerock  291.  #endif  292.  	    )  { 293. 		register struct obj *otmp; 294. 		for(otmp = fobj; otmp; otmp = otmp->nobj) 295. 		if(likeobjs  296.  		   || (likegems && otmp->olet == GEM_SYM)  297.  #ifdef KAA  298.  		   || (likerock && otmp->olet == ROCK_SYM)  299.  #endif  300.  			)  { 301. 			if(msym != 'u' || objects[otmp->otyp].g_val != 0) 302. 			    if((dd = DIST(omx,omy,otmp->ox,otmp->oy)) < mind){ 303. 				mind = dd; 304. 				gx = otmp->ox; 305. 				gy = otmp->oy; 306. 			    }  307.  			}  308.  	    }  309.  	  if(mind < SRCHRADIUS && appr == -1) { 310. 		if(dist(omx,omy) < 10) { 311. 		    gx = u.ux; 312. 		    gy = u.uy; 313. 		} else 314. 		    appr = 1; 315. 	  }  316.  	}  317.  	nix = omx; 318. 	niy = omy; 319. 	cnt = mfndpos(mtmp,poss,info,  320.  		msym == 'u' ? NOTONL :  321.  #ifdef ROCKMOLE  322.  		msym == 'r' ? ALLOW_WALL :  323.  #endif  324.  		(msym == '@' || msym == '1') ? (ALLOW_SSM | ALLOW_TRAPS) :  325.  		index(UNDEAD, msym) ? NOGARLIC :  326.  #ifdef KAA  327.  		    (msym == '9') ? (ALLOW_ROCK | ALLOW_TRAPS) : ALLOW_TRAPS); 328. #else 329. 		     ALLOW_TRAPS);  330.  #endif  331.  	chcnt = 0;  332.  	chi = -1;  333.  	for(i=0; imtrack[j].x && ny == mtmp->mtrack[j].y)  338.  				if(rn2(4*(cnt-j))) goto nxti;  339.  #ifdef STUPID  340.  		/* some stupid compilers think that this is too complicated */  341.  		{ int d1 = DIST(nx,ny,gx,gy);  342.  		  int d2 = DIST(nix,niy,gx,gy);  343.  		  nearer = (d1 < d2);  344.  		}  345.  #else  346.  		nearer = (DIST(nx,ny,gx,gy) < DIST(nix,niy,gx,gy));  347.  #endif  348.  		if((appr == 1 && nearer) || (appr == -1 && !nearer) || 349. 			!mmoved || 350. 			(!appr && !rn2(++chcnt))){  351.  			nix = nx;  352.  			niy = ny;  353.  			chi = i;  354.  			mmoved = 1;  355.  		}  356.  	nxti:	;  357.  	}  358.  	if(mmoved){  359.  		if(info[chi] & ALLOW_M){  360.  			mtmp2 = m_at(nix,niy);  361.  			if(hitmm(mtmp,mtmp2) == 1 && rn2(4) && 362. 			  hitmm(mtmp2,mtmp) == 2) return(2);  363.  			return(0);  364.  		}  365.  		if(info[chi] & ALLOW_U){  366.  		  (void) hitu(mtmp, d(mtmp->data->damn, mtmp->data->damd)+1);  367.  		  return(0);  368.  		}  369.  		mtmp->mx = nix;  370.  		mtmp->my = niy;  371.  		for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];  372.  		mtmp->mtrack[0].x = omx;  373.  		mtmp->mtrack[0].y = omy;  374.  #ifndef NOWORM  375.  		if(mtmp->wormno) worm_move(mtmp);  376.  #endif  377.  	} else {  378.  		if(msym == 'u' && rn2(2)){  379.  			rloc(mtmp);  380.  			return(0);  381.  		}  382.  #ifndef NOWORM  383.  		if(mtmp->wormno) worm_nomove(mtmp);  384.  #endif  385.  	}  386.  postmov:  387.  	if(mmoved == 1) {  388.  		if(mintrap(mtmp) == 2)	/* he died */  389.  			return(2);  390.  #ifdef ROCKMOLE  391.  	       /* Maybe a rock mole just ate something? */  392.  	       if(msym == 'r' && IS_ROCK(levl[mtmp->mx][mtmp->my].typ) && 393. 		  levl[mtmp->mx][mtmp->my].typ != POOL){  394.  		   register int pile = rnd(25);  395.  		   /* Just ate something. */  396.  		   if(levl[mtmp->mx][mtmp->my].typ == 0)  397.  		     levl[mtmp->mx][mtmp->my].typ = CORR;  398.  		   else if(IS_WALL(levl[mtmp->mx][mtmp->my].typ))  399.  		     levl[mtmp->mx][mtmp->my].typ = DOOR;  400.  		   mnewsym(mtmp->mx,mtmp->my);  401.  		   /* Left behind a pile? */  402.  		   if(pile < 5) {  403.  		       if(pile == 1)  404.  			mksobj_at(ENORMOUS_ROCK, mtmp->mx, mtmp->my);  405.  		      else  406.  			mksobj_at(ROCK, mtmp->mx, mtmp->my);  407.  		   }  408.  		  if(cansee(mtmp->mx, mtmp->my))  409.  		    atl(mtmp->mx,mtmp->my,fobj->olet);  410.  	       }  411.  	       /* Maybe a rock mole just ate some gold or armor? */  412.  	       if(msym == 'r') meatgold(mtmp);  413.  #endif /* ROCKMOLE /**/  414.  		if(likegold) mpickgold(mtmp); 415. #ifdef KAA 416. 		if(likerock || likegems) mpickgems(mtmp); 417. #else 418. 		if(likegems) mpickgems(mtmp); 419. #endif 420. 		if(mtmp->mhide) mtmp->mundetected = 1; 421. 	}  422.  	pmon(mtmp); 423. 	return(mmoved); 424. }  425.