Source:NetHack 3.0.0/monmove.c

Below is the full text to monmove.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/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	3.0	88/11/10 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6.    #include "mfndpos.h"  7.    #ifdef NAMED_ITEMS 8.   #  include "artifact.h"  9.    #endif 10.   11.   static boolean /* TRUE : mtmp died */ 12.  mb_trapped(mtmp) 13.  register struct monst *mtmp; 14.  {  15.   	if (flags.verbose) { 16.  	    if (cansee(mtmp->mx, mtmp->my)) 17.  	       pline("KABOOM!!  You see a door explode."); 18.  	    else if (flags.soundok) 19.                 You("hear a distant explosion."); 20.  	}  21.   	mtmp->mstun = 1; 22.  	mtmp->mhp -= rnd(15); 23.  	if(mtmp->mhp <= 0) { 24.  		mondied(mtmp); 25.  		return(TRUE); 26.  	}  27.   	return(FALSE); 28.  }  29.    30.   boolean 31.  mdig_tunnel(mtmp)  /* FALSE: monster died */ 32.  register struct monst *mtmp; 33.  {  34.   	register struct rm *here; 35.  	register int pile = rnd(12); 36.  	boolean canseeit = cansee(mtmp->mx, mtmp->my); 37.  	here = &levl[mtmp->mx][mtmp->my]; 38.   39.   	if(IS_ROCK(here->typ)) { 40.  	    /* Just ate something. */ 41.   	    if(here->typ == STONE) here->typ = CORR; 42.  	    else if(IS_WALL(here->typ) &&  43.   			!(here->diggable & W_NONDIGGABLE)) { 44.  		if(flags.soundok && flags.verbose && !rn2(5)) 45.  		       You("hear the sound of crashing rock."); 46.  		here->typ = DOOR; 47.  		here->doormask = D_NODOOR; 48.  	    }  49.   	}  50.   	/* Eats away door if present & closed or locked */ 51.  	else if(IS_DOOR(here->typ) &&  52.   		(here->doormask & (D_LOCKED | D_CLOSED))) { 53.  		if(here->doormask & D_TRAPPED) { 54.  		    here->doormask = D_NODOOR; 55.  		    if(mb_trapped(mtmp)) return(FALSE); 56.  		} else { 57.  		    if(!rn2(3) && flags.verbose) /* not too often.. */ 58.   		        You("feel an unexpected draft of air."); 59.  		    here->doormask = D_BROKEN; 60.  		}  61.   	    }  62.   	else pile = 12; /* it doesn't leave rocks if it didn't dig */ 63.   64.   	/* Left behind a pile? */ 65.   	if(pile < 5) { 66.  	    if(pile == 1) 67.  		(void) mksobj_at(BOULDER, mtmp->mx, mtmp->my); 68.  	    else 69.  		(void) mksobj_at(ROCK, mtmp->mx, mtmp->my); 70.  	}  71.   	if(canseeit) { 72.  	    here->seen = TRUE; 73.  	    newsym(mtmp->mx,mtmp->my); 74.  	} else 75.  	    mnewsym(mtmp->mx,mtmp->my); 76.  	return(TRUE); 77.  }  78.    79.   int 80.  dochugw(mtmp) 81.  	register struct monst *mtmp; 82.  {  83.   	register int x = mtmp->mx; 84.  	register int y = mtmp->my; 85.  	register int rd = dochug(mtmp); 86.  	register int dd; 87.   88.   	if(!rd && !mtmp->mpeaceful &&  89.   			(dd = dist(mtmp->mx,mtmp->my)) < dist(x,y) &&  90.   			dd < 100 && !canseemon(mtmp)) { 91.  #ifdef NAMED_ITEMS 92.  	    /* Note: this assumes we only want to warn against the monster which 93.  	     * the weapon does extra damage to, as there is no "monster which  94.   	     * the weapon warns against" field. 95.  	     */  96.   		if(spec_ability(uwep,SPFX_WARN) && spec_dbon(uwep,mtmp->data,1)) 97.  			warnlevel = 100; 98.  		else 99.  #endif 100. 		if (Warning && mtmp->m_lev > warnlevel) 101. 			warnlevel = mtmp->m_lev; 102. 	}  103.  	return(rd); 104. }  105.   106.  boolean 107. onscary(x, y, mtmp) 108. int x, y;  109. struct monst *mtmp; 110. {  111.  	if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee ||  112.  			mtmp->data->mlet == S_HUMAN || mtmp->mpeaceful) 113. 		return(FALSE); 114. 	return(  115.  #ifdef ELBERETH  116.  		   sengr_at("Elbereth", x, y) ||  117.  #endif  118.  		    sobj_at(SCR_SCARE_MONSTER, x, y) != (struct obj *)0); 119. }  120.   121.  /* returns 1 if monster died moving, 0 otherwise */ 122. int 123. dochug(mtmp) 124. 	register struct monst *mtmp; 125. {  126.  	register struct permonst *mdat = mtmp->data; 127. 	register int tmp=0, inrange, nearby, scared, seescaryx, 128. 		seescaryy; 129.  130.  /*	Pre-movement adjustments	*/ 131.  132.  	if(mtmp->cham && !rn2(6))	/* polymorph chameleons */ 133. 	    (void) newcham(mtmp, (struct permonst *)0); 134.  135.  	/* regenerate monsters */ 136. 	if((!(moves%20) || regenerates(mdat)) && mtmp->mhp < mtmp->mhpmax) 137. 		mtmp->mhp++; 138. 	if(mtmp->mspec_used) mtmp->mspec_used--; 139.  140.  	/* polymorph lycanthropes */ 141. 	were_change(mtmp); 142.  143.  	if(mtmp->mfroz) { 144. 		if (Hallucination) pmon(mtmp); 145. 		return(0);	/* frozen monsters don't do anything */ 146. 	}  147.   148.  	if(mtmp->msleep)	/* there is a chance we will wake it */ 149. 		if(!disturb(mtmp)) return(0); 150.  151.  	/* not frozen or sleeping: wipe out texts written in the dust */ 152. 	wipe_engr_at(mtmp->mx, mtmp->my, 1); 153.  154.  	/* confused monsters get unconfused with small probability */ 155. 	if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0; 156.  157.  	/* stunned monsters get un-stunned with larger probability */ 158. 	if(mtmp->mstun && !rn2(10)) mtmp->mstun = 0; 159.  160.  	/* some monsters teleport */ 161. 	if(mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz) { 162. 		rloc(mtmp); 163. 		return(0); 164. 	}  165.  	if(mdat->mmove < rnd(6)) return(0); 166.  167.  	/* fleeing monsters might regain courage */ 168. 	if(mtmp->mflee && !mtmp->mfleetim  169.  	   && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0; 170.  171.  	set_apparxy(mtmp); 172. 	/* Must be done after you move and before the monster does. The 173. 	 * set_apparxy call in m_move doesn't suffice since the variables 174. 	 * inrange, etc... all depend on stuff set by set_apparxy. 175. 	 */  176.   177.  	/* The Wizard's prime directive */ 178. 	/* may teleport, so do it before inrange is set */ 179. 	if(mtmp->iswiz) 180. 		(void) wiz_get_amulet(mtmp); 181.  182.  	inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=  183.  							(BOLT_LIM * BOLT_LIM)); 184. 	nearby = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) < 3); 185. 	/* Note: if your image is displaced, the monster sees the Elbereth 186. 	 * at your displaced position, thus never attacking your displaced 187. 	 * position, but possibly attacking you by accident. If you are 188. 	 * invisible, it sees the Elbereth at your real position, thus never 189. 	 * running into you by accident but possibly attacking the spot 190. 	 * where it guesses you are. 191. 	 */  192.  	if (Invis && !perceives(mdat)) { 193. 		seescaryx = mtmp->mux; 194. 		seescaryy = mtmp->muy; 195. 	} else { 196. 		seescaryx = u.ux; 197. 		seescaryy = u.uy; 198. 	}  199.  	scared = (nearby && onscary(seescaryx, seescaryy, mtmp)); 200.  201.  	if(scared && !mtmp->mflee) { 202. #ifdef POLYSELF 203. 		if (!sticks(uasmon)) 204. #endif 205. 			unstuck(mtmp);	/* monster lets go when fleeing */ 206. 		mtmp->mflee = 1; 207. 		mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100)); 208. 	}  209.   210.  #ifdef HARD	/* Demonic Blackmail!!! */ 211.  	if(nearby && is_demon(mdat) && mtmp->mpeaceful && !mtmp->mtame) { 212. 		if (mtmp->mux != u.ux || mtmp->muy != u.uy) { 213. 			pline("%s whispers something to thin air.",  214.  			    cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It"); 215. #ifdef POLYSELF 216. 			if (is_demon(uasmon)) rloc(mtmp); 217. 			  /* "Good hunting, brother" */ 218. 			else 219. #endif 220. 			if (is_lord(mdat) || is_prince(mdat)) { 221. 			  /* use is_lord instead of is_dlord */ 222. 			    mtmp->minvis = 0; 223. 			    /* Why? For the same reason in real demon talk */ 224. 			    pline("%s gets angry.", Xmonnam(mtmp)); 225. 			    mtmp->mpeaceful = 0; 226. 			    /* since no way is an image going to pay it off */ 227. 			}  228.  		} else if(demon_talk(mtmp)) return(1);	/* you paid it off */ 229. 	}  230.  #endif 231.  232.  /*	Now the actual movement phase	*/ 233.  234.  	if(!nearby || mtmp->mflee || scared ||  235.  	   mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) ||  236.  	   (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) ||  237.  	   (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) ||  238.  	   (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) { 239.  240.  		tmp = m_move(mtmp, 0); 241. 		nearby = (dist(mtmp->mx, mtmp->my) < 3);	/* recalc */ 242. 		scared = (nearby && onscary(seescaryx, seescaryy, mtmp)); 243. 		switch (tmp) { 244.  245.  		    case 0:	/* no movement, but it can still attack you */ 246. 		    case 3:	/* absolutely no movement */ 247. 				/* for pets, case 0 and 3 are equivalent */ 248.  			/* During hallucination, monster appearance should 249.  			 * still change - even if it doesn't move. 250.   			 */  251.   			if(Hallucination) pmon(mtmp); 252.  			break; 253.  		    case 1:	/* monster moved */ 254.  			if(!nearby && ranged_attk(mdat)) break; 255.  			else if(mdat->mmove <= 12) return(0); 256.  			break; 257.  		    case 2:	/* monster died */ 258.  			return(1); 259.  		}  260.   261.  		inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <=  262.  							(BOLT_LIM * BOLT_LIM)); 263. 		if(scared && !mtmp->mflee) { 264. 			mtmp->mflee = 1; 265. 			mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100)); 266. 		}  267.  	}  268.   269.  /*	Now, attack the player if possible - one attack set per monst	*/ 270.  271.  	if(inrange && !noattacks(mdat) &&  272.  	   !mtmp->mpeaceful && !mtmp->mtame && u.uhp > 0 && !scared && tmp != 3) 273. 	    if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */ 274.  275.  #ifdef WORM 276. 	if(mtmp->wormno && !mtmp->mtame) wormhit(mtmp); 277. #endif 278.  279.  	/* extra movement for fast monsters */ 280. 	if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp, 1); 281. 	return(tmp == 2); 282. }  283.   284.  static const char practical[] = { WEAPON_SYM, GEM_SYM, FOOD_SYM, 0 }; 285. static const char magical[] = { 286. 	AMULET_SYM, POTION_SYM, SCROLL_SYM, WAND_SYM, RING_SYM, 287. #ifdef SPELLS 288. 	SPBOOK_SYM, 289. #endif 290. 	0 };  291.  static const char indigestion[] = { BALL_SYM, ROCK_SYM, 0 }; 292.  293.  #ifdef POLYSELF 294. static boolean 295. itsstuck(mtmp) 296. register struct monst *mtmp; 297. {  298.  	if (sticks(uasmon) && mtmp==u.ustuck && !u.uswallow) { 299. 		kludge("%s cannot escape from you!", Monnam(mtmp)); 300. 		return(TRUE); 301. 	}  302.  	return(FALSE); 303. }  304.  #endif 305.  306.  int 307. m_move(mtmp, after) 308. register struct monst *mtmp; 309. register int after; 310. {  311.  	register struct monst *mtmp2; 312. 	register int nx,ny,omx,omy,appr,nearer,cnt,i,j; 313. 	xchar gx,gy,nix,niy,chcnt; 314. 	schar chi; 315. 	boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0; 316. 	boolean likerock=0, can_tunnel=0; 317. 	struct permonst *ptr = mtmp->data; 318. 	schar mmoved = 0;	/* not strictly nec.: chi >= 0 will do */ 319. 	coord poss[9]; 320. 	long info[9]; 321. 	long flag; 322.  323.  	if(mtmp->mtrapped) { 324. 	    i = mintrap(mtmp); 325. 	    if(i == 2) return(2);	/* it died */ 326. 	    if(i == 1) return(0);	/* still in trap, so didn't move */ 327. 	}  328.  	if(mtmp->mhide &&  329.  	   (levl[mtmp->mx][mtmp->my].omask || levl[mtmp->mx][mtmp->my].gmask) &&  330.  	   rn2(10)) 331. 	    return(0);		/* do not leave hiding place */ 332. 	if(mtmp->meating) { 333. 	    mtmp->meating--; 334. 	    return(3);			/* still eating */ 335. 	}  336.   337.  	set_apparxy(mtmp); 338. 	/* where does mtmp think you are? */ 339.  	/* Not necessary if m_move called from here, but necessary in  340. * other calls of m_move (i.e. leprechauns dodging) 341. 	 */  342.  	can_tunnel = tunnels(ptr) && 343. #ifdef REINCARNATION 344. 		     dlevel != rogue_level && 345. #endif 346. 		     (!needspick(ptr) || m_carrying(mtmp, PICK_AXE)); 347. #ifdef WORM 348. 	if(mtmp->wormno) goto not_special; 349. #endif 350. 	/* my dog gets a special treatment */ 351. 	if(mtmp->mtame) return( dog_move(mtmp, after) ); 352.  353.  	/* likewise for shopkeeper */ 354. 	if(mtmp->isshk) { 355. 	    mmoved = shk_move(mtmp); 356. 	    if(mmoved == -2) return(2); 357. 	    if(mmoved >= 0) goto postmov; 358. 	    mmoved = 0;		/* follow player outside shop */ 359. 	}  360.   361.  	/* and for the guard */ 362. 	if(mtmp->isgd) { 363. 	    mmoved = gd_move; 364. 	    goto postmov; 365. 	}  366.   367.  	/* and the wiz already got special treatment */ 368. 	if(mtmp->iswiz) { 369. 	    mmoved = 0; 370. 	    goto postmov; 371. 	}  372.  #if defined(ALTARS) && defined(THEOLOGY) 373. 	/* and for the priest */ 374. 	if(mtmp->ispriest) { 375. 	    mmoved = pri_move(mtmp); 376. 	    if(mmoved == -2) return(2); 377. 	    if(mmoved >= 0) goto postmov; 378. 	    mmoved = 0; 379. 	}  380.  #endif 381. #ifdef MAIL 382. 	if(ptr == &mons[PM_MAIL_DAEMON]) { 383. 	    if(flags.soundok && canseemon(mtmp)) 384. 		pline("\"I'm late!\""); 385. 	    mongone(mtmp); 386. 	    return(2); 387. 	}  388.  #endif 389.  390.  	/* teleport if that lies in our nature */ 391. 	if(ptr == &mons[PM_TENGU] && !rn2(5)) { 392. 	    if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2)) 393. 		rloc(mtmp); 394. 	    else 395. 		mnexto(mtmp); 396. 	    mmoved = 1; 397. 	    goto postmov; 398. 	}  399.  #ifdef WORM 400. not_special: 401. #endif 402. 	if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1); 403. 	appr = 1; 404. 	if(mtmp->mflee) appr = -1; 405. 	if(mtmp->mconf || (Invis && !perceives(ptr)) ||  !mtmp->mcansee ||  406.  	   (mtmp->mpeaceful && !mtmp->isshk) ||	/* allow shks to follow */  407.  	   ((ptr->mlet == S_STALKER || ptr->mlet == S_BAT ||  408.  	     ptr->mlet == S_YLIGHT) && !rn2(3))) 409. 	    appr = 0; 410. 	omx = mtmp->mx; 411. 	omy = mtmp->my; 412. 	gx = mtmp->mux; 413. 	gy = mtmp->muy; 414. 	if(ptr == &mons[PM_LEPRECHAUN] && appr == 1 && mtmp->mgold > u.ugold) 415. 	    appr = -1; 416.  417.  	if(can_track(ptr)) { 418. 	    register coord *cp; 419. 	    schar mroom; 420.  421.  	    mroom = inroom(omx,omy); 422. 	    if(mroom < 0 || mroom != inroom(u.ux,u.uy)){ 423. 		cp = gettrack(omx,omy); 424. 		if(cp){ 425. 		    gx = cp->x; 426. 		    gy = cp->y; 427. 		}  428.  	    }  429.  	}  430.   431.  #ifdef REINCARNATION 432. 	if (dlevel != rogue_level) 433. #endif 434. 	{  435.  		register int pctload = (curr_mon_load(mtmp) * 100) / 436. 			max_mon_load(mtmp); 437.  438.  		/* look for gold or jewels nearby */ 439. 		likegold = (likes_gold(ptr) && pctload < 95); 440. 		likegems = (likes_gems(ptr) && pctload < 85); 441. 		likeobjs = (likes_objs(ptr) && pctload < 75); 442. 		likemagic = (likes_magic(ptr) && pctload < 85); 443. 		likerock = (throws_rocks(ptr) && pctload < 50); 444. 		conceals = hides_under(ptr); 445. 	}  446.   447.  #define	SRCHRADIUS	25 448.  449.        { xchar mind = SRCHRADIUS;		/* not too far away */ 450. 	register int dd; 451.  452.  	/* cut down the search radius if it thinks character is closer. */ 453.  	if(dist2(mtmp->mux, mtmp->muy, omx, omy) < SRCHRADIUS &&  454.  	    !mtmp->mtame && !mtmp->mpeaceful)	 mind /= 2; 455.  456.  	if(likegold){ 457. 	    register struct gold *gold; 458.  459.  	    for(gold = fgold; gold; gold = gold->ngold) 460. 		if((dd = dist2(omx,omy,gold->gx,gold->gy)) < mind){ 461. 		    mind = dd; 462. 		    gx = gold->gx; 463. 		    gy = gold->gy; 464. 		}  465.  	}  466.  	if((likegems || likeobjs || likemagic || likerock || conceals)  467.  	      && (!in_shop(omx, omy) || (!rn2(25) && !mtmp->isshk))) { 468. 	    register struct obj *otmp; 469.  470.  	    for(otmp = fobj; otmp; otmp = otmp->nobj) 471. 		if((likeobjs && index(practical, otmp->olet)) ||  472.  		   (likemagic && index(magical, otmp->olet)) ||  473.  		   (likerock && otmp->otyp == BOULDER) ||  474.  		   (likegems && otmp->olet == GEM_SYM && 475. 			otmp->otyp < LAST_GEM + 5) ||  476.  		   (conceals && !cansee(otmp->ox,otmp->oy)) ||  477.  		   (ptr == &mons[PM_GELATINOUS_CUBE] && 478. 					!index(indigestion, otmp->olet))  479.  		  ) { 480. 			if(can_carry(mtmp,otmp)) 481. 			if(ptr->mlet != S_UNICORN ||  482.  					objects[otmp->otyp].g_val != 0) 483. 			    if((dd = dist2(omx,omy,otmp->ox,otmp->oy)) < mind){ 484. 				mind = dd; 485. 				gx = otmp->ox; 486. 				gy = otmp->oy; 487. 			    }  488.  		}  489.  	}  490.  	if(mind < SRCHRADIUS && appr == -1) { 491. 	    if(dist2(omx,omy,mtmp->mux,mtmp->muy) < 10) { 492. 		gx = mtmp->mux; 493. 		gy = mtmp->muy; 494. 	    } else 495. 		appr = 1; 496. 	}  497.        }  498.  	nix = omx; 499. 	niy = omy; 500. 	flag = ALLOW_TRAPS; 501. 	if (mtmp->mpeaceful) flag |= (ALLOW_SANCT | ALLOW_SSM); 502. 	else flag |= ALLOW_U; 503. 	if (ptr->mlet == S_UNICORN) flag |= NOTONL; 504. 	if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK); 505. 	if (can_tunnel) flag |= ALLOW_DIG; 506. 	if (is_human(ptr)) flag |= ALLOW_SSM; 507. 	if (is_undead(ptr)) flag |= NOGARLIC; 508. 	if (throws_rocks(ptr)) flag |= ALLOW_ROCK; 509. 	cnt = mfndpos(mtmp, poss, info, flag); 510. 	chcnt = 0; 511. 	chi = -1; 512.  513.  	for(i=0; i < cnt; i++) { 514. 	    nx = poss[i].x;  515. ny = poss[i].y; 516. 517. 	    for(j=0; j < MTSZ && j < cnt-1; j++) 518. 		if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)  519. if(rn2(4*(cnt-j))) goto nxti; 520.  521.  	    nearer = (dist2(nx,ny,gx,gy) < dist2(nix,niy,gx,gy)); 522.  523.  	    if((appr == 1 && nearer) || (appr == -1 && !nearer) ||  524.  		   	!mmoved || (!appr && !rn2(++chcnt))) { 525. 		nix = nx; 526. 		niy = ny; 527. 		chi = i;  528. mmoved = 1; 529. 	    }  530.  	nxti:	; 531. 	}  532.   533.  	if(mmoved) { 534. #ifdef POLYSELF 535. 	    if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp)) 536. 		return(3); 537. #endif 538. 	    if((info[chi] & ALLOW_U) || (nix == u.ux && niy == u.uy)) { 539. 		mtmp->mux = u.ux; 540. 		mtmp->muy = u.uy; 541. 		return(0); 542. 	    }  543.  	    /* The monster may attack another based on 1 of 2 conditions: 544. 	     * 1 - He may be under the "conflict" influence. 545. 	     * 2 - He may mistake the monster for your (displaced) image. 546. 	     * Pets get taken care of above and shouldn't reach this code. 547. 	     */  548.  	    if((info[chi] & ALLOW_M) ||  549.  		   (nix == mtmp->mux && niy == mtmp->muy)) { 550. 		mtmp2 = 551. 		    (levl[nix][niy].mmask ? m_at(nix,niy) : (struct monst *)0); 552. 		if(mattackm(mtmp, mtmp2) == 1 && rn2(4) &&  553.  			mtmp2->mlstmv != moves && mattackm(mtmp2, mtmp) == 2) 554. 		    return(2); 555. 		return(3); 556. 	    }  557.  #ifdef WORM 558. 	    /* The square now has a worm segment and must keep its mmask */ 559. 	    if (!mtmp->wormno) 560. #endif 561. 		    levl[omx][omy].mmask = 0; 562. 	    levl[nix][niy].mmask = 1; 563. 	    mtmp->mx = nix; 564. 	    mtmp->my = niy; 565. 	    for(j = MTSZ-1; j > 0; j--) 566. 		mtmp->mtrack[j] = mtmp->mtrack[j-1]; 567. 	    mtmp->mtrack[0].x = omx; 568. 	    mtmp->mtrack[0].y = omy; 569. #ifdef WORM 570. 	    if(mtmp->wormno) worm_move(mtmp); 571. #endif 572. 	} else { 573. 	    if(ptr->mlet == S_UNICORN && rn2(2)) { 574. 		rloc(mtmp); 575. 		return(1); 576. 	    }  577.  #ifdef WORM 578. 	    if(mtmp->wormno) worm_nomove(mtmp); 579. #endif 580. 	}  581.  postmov: 582. 	if(mmoved == 1) { 583. 	    boolean canseeit = cansee(mtmp->mx, mtmp->my); 584. 	    boolean abstain = (mtmp->mpeaceful && !mtmp->mtame); 585.  586.  	    if(mintrap(mtmp) == 2) return(2);	/* he died */ 587.  588.  	    /* open a door, or crash through it, if you can */ 589. 	    if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ)  590.  		    && !passes_walls(ptr) /* doesn't need to open doors */  591.  	            && !amorphous(ptr) /* ditto */  592.  		    && !can_tunnel /* taken care of below */  593.  		  ) { 594. 		struct rm *here = &levl[mtmp->mx][mtmp->my]; 595. 		boolean btrapped = (here->doormask & D_TRAPPED); 596.  597.  		if(here->doormask & D_LOCKED && mtmp->isshk) { 598. 			/* can't lock out shk */ 599. 		    if(btrapped) { 600. 			here->doormask = D_NODOOR; 601. 			if(mb_trapped(mtmp)) return(2); 602. 		    } else { 603. 			if (flags.verbose) { 604. 			    if (canseeit) 605. 			       You("see a door being unlocked and opened."); 606. 			    else if (flags.soundok) 607. 			       You("hear a door being unlocked and opened."); 608. 		        }  609.  		        here->doormask = D_ISOPEN; 610. 		    }  611.  		} else if (here->doormask == D_CLOSED &&  612.  					!nohands(mtmp->data)) { 613. 		    if(btrapped) { 614. 			here->doormask = D_NODOOR; 615. 			if(mb_trapped(mtmp)) return(2); 616. 		    } else { 617. 		        if (flags.verbose) { 618. 			    if (canseeit) 619. 			         You("see a door being opened."); 620. 			    else if (flags.soundok) 621. 			         You("hear the sound of a door opening."); 622. 		        }  623.  		        here->doormask = D_ISOPEN; 624. 		    }  625.  		} else if(here->doormask & (D_LOCKED | D_CLOSED)) { 626. 			/* mfndpos guarantees monster is a giant */ 627. 		    if(btrapped) { 628. 			here->doormask = D_NODOOR; 629. 			if(mb_trapped(mtmp)) return(2); 630. 		    } else { 631. 		        if (flags.verbose) { 632. 			    if (canseeit) 633. 			        You("see a door crash open."); 634. 			    else if (flags.soundok) 635. 			        You("hear the sound of a door crashing open."); 636. 		        }  637.  		        if (here->doormask & D_LOCKED && !rn2(2)) 638. 			        here->doormask = D_NODOOR; 639. 		        else here->doormask = D_BROKEN; 640. 		    }  641.  		}  642.  	    }  643.  	    /* Maybe a rock mole just ate something? */ 644.  	    if(can_tunnel) if(!mdig_tunnel(mtmp)) return(2); /* died? */ 645.   646.  	    if(levl[mtmp->mx][mtmp->my].gmask == 1) { 647. 		/* Maybe a rock mole just ate some gold */ 648. 		if(ptr == &mons[PM_ROCK_MOLE]) meatgold(mtmp); 649. 		if(likegold && (!abstain || !rn2(10))) mpickgold(mtmp); 650. 	    }  651.  	    if(levl[mtmp->mx][mtmp->my].omask == 1) { 652. 		/* Maybe a rock mole just ate some metal object */ 653. 		if(ptr == &mons[PM_ROCK_MOLE]) meatgold(mtmp); 654. 		/* Maybe a cube ate just about anything */ 655. 		if(ptr == &mons[PM_GELATINOUS_CUBE]) meatobj(mtmp); 656.  657.  		if ((!abstain || !rn2(10))  658.  			&& (!in_shop(mtmp->mx, mtmp->my) || !rn2(25))) { 659. 		    if(likeobjs) mpickstuff(mtmp, practical); 660. 		    if(likemagic) mpickstuff(mtmp, magical); 661. 		    if(likerock || likegems) mpickgems(mtmp); 662. 		}  663.  	    }  664.  	    if(mtmp->mhide) mtmp->mundetected = (levl[mtmp->mx][mtmp->my].omask  665.  					|| levl[mtmp->mx][mtmp->my].gmask); 666.  667.  	    /* set also in domove, hack.c */ 668. 	    if(u.uswallow && mtmp == u.ustuck) { 669. 		u.ux = mtmp->mx; 670. 		u.uy = mtmp->my; 671. 	        if(mtmp->mx != mtmp->mdx || mtmp->my != mtmp->mdy) { 672. 		    swallowed(0); 673. 		    mtmp->mdx = mtmp->mx; 674. 		    mtmp->mdy = mtmp->my; 675. 		}  676.  	    }  677.  	}  678.  	pmon(mtmp); 679. 	return(mmoved); 680. }  681.   682.  void 683. set_apparxy(mtmp)		/* where does mtmp think you are standing? */ 684.  	register struct monst *mtmp; 685. {  686.  #define notseen (Invis && !perceives(mtmp->data)) 687. /*	add cases as required. eg. Displacement ... */ 688.  	register int disp = (notseen ? 1 : Displaced ? 2 : 0); 689.  690.  /* 	without something like the following, invis. and displ. are too */ 691. /*	powerful. */ 692.  	register boolean gotu = 693. 		(notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE); 694.  695.  /*	Monsters which know where you are don't suddenly forget, if you 696. 	didn't move away. */ 697.  	if (mtmp->mux==u.ux && mtmp->muy==u.uy) gotu = 1; 698.  699.  /* 	your dog follows your smell */ 700. 	if(!disp || mtmp->mtame || gotu ||  701.  /*	If invisible but not displaced, staying around gets you 'discovered' */  702.  	    (!Displaced && u.dx == 0 && u.dy == 0)) { 703. 		mtmp->mux = u.ux; 704. 		mtmp->muy = u.uy; 705. 	}  706.  	else do { 707. 		mtmp->mux = u.ux - disp + rn2(2*disp+1); 708. 		mtmp->muy = u.uy - disp + rn2(2*disp+1); 709. 	} while((mtmp->mux != u.ux || mtmp->muy != u.uy) &&  710.  	       (  (!passes_walls(mtmp->data) &&  711.  		      (!ACCESSIBLE(levl[mtmp->mux][mtmp->muy].typ) || 712. 		       (IS_DOOR(levl[mtmp->mux][mtmp->muy].typ) &&  713.  			(levl[mtmp->mux][mtmp->muy].doormask & (D_LOCKED | D_CLOSED)) &&  714.  			!amorphous(mtmp->data)  715.  		      ))  716.  		  ) || 717. 		  (disp==1 && mtmp->mux == mtmp->mx && mtmp->muy == mtmp->my) 718. 	       )  719.  	);  720.  }