Source:NetHack 2.3e/monmove.c

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; imtrack[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.