Source:Hack.c

Below is the full text to src/hack.c from NetHack 3.4.3. To link to a particular line, write [[hack.c#line123 ]], for example. 1.   /*	SCCS Id: @(#)hack.c	3.4	2003/04/30	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.

5.   #include "hack.h"  6. 7.   #ifdef OVL1 8.   STATIC_DCL void NDECL(maybe_wail); 9.   #endif /*OVL1*/ 10.  STATIC_DCL int NDECL(moverock); 11.  STATIC_DCL int FDECL(still_chewing,(XCHAR_P,XCHAR_P)); 12.  #ifdef SINKS 13.  STATIC_DCL void NDECL(dosinkfall); 14.  #endif 15.  STATIC_DCL boolean FDECL(findtravelpath, (BOOLEAN_P)); 16.  STATIC_DCL boolean FDECL(monstinroom, (struct permonst *,int)); 17.   18.   STATIC_DCL void FDECL(move_update, (BOOLEAN_P)); 19.   20.   #define IS_SHOP(x)	(rooms[x].rtype >= SHOPBASE) 21.   22.   #ifdef OVL2 23.   24.   boolean 25.  revive_nasty(x, y, msg) 26.  int x,y; 27.  const char *msg; 28.  {  29.       register struct obj *otmp, *otmp2; 30.      struct monst *mtmp; 31.      coord cc; 32.      boolean revived = FALSE; 33.   34.       for(otmp = level.objects[x][y]; otmp; otmp = otmp2) { 35.  	otmp2 = otmp->nexthere; 36.  	if (otmp->otyp == CORPSE &&  37.   	    (is_rider(&mons[otmp->corpsenm]) || 38.  	     otmp->corpsenm == PM_WIZARD_OF_YENDOR)) { 39.  	    /* move any living monster already at that location */ 40.  	    if((mtmp = m_at(x,y)) && enexto(&cc, x, y, mtmp->data)) 41.  		rloc_to(mtmp, cc.x, cc.y); 42.  	    if(msg) Norep("%s", msg); 43.  	    revived = revive_corpse(otmp); 44.  	}  45.       }  46.    47.       /* this location might not be safe, if not, move revived monster */ 48.      if (revived) { 49.  	mtmp = m_at(x,y); 50.  	if (mtmp && !goodpos(x, y, mtmp, 0) &&  51.   	    enexto(&cc, x, y, mtmp->data)) { 52.  	    rloc_to(mtmp, cc.x, cc.y); 53.  	}  54.   	/* else impossible? */ 55.       }  56.    57.       return (revived); 58.  }  59.    60.   STATIC_OVL int 61.  moverock 62.  {  63.       register xchar rx, ry, sx, sy; 64.      register struct obj *otmp; 65.      register struct trap *ttmp; 66.      register struct monst *mtmp; 67.   68.       sx = u.ux + u.dx,  sy = u.uy + u.dy;	/* boulder starting position */ 69.      while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) { 70.  	/* make sure that this boulder is visible as the top object */ 71.  	if (otmp != level.objects[sx][sy]) movobj(otmp, sx, sy); 72.   73.   	rx = u.ux + 2 * u.dx;	/* boulder destination position */ 74.  	ry = u.uy + 2 * u.dy; 75.  	nomul(0); 76.  	if (Levitation || Is_airlevel(&u.uz)) { 77.  	    if (Blind) feel_location(sx, sy); 78.  	    You("don't have enough leverage to push %s.", the(xname(otmp))); 79.  	    /* Give them a chance to climb over it? */ 80.   	    return -1; 81.  	}  82.   	if (verysmall(youmonst.data)  83.   #ifdef STEED  84.   		 && !u.usteed  85.   #endif  86.   				    ) { 87.  	    if (Blind) feel_location(sx, sy); 88.  	    pline("You're too small to push that %s.", xname(otmp)); 89.  	    goto cannot_push; 90.  	}  91.   	if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&  92.   	    levl[rx][ry].typ != IRONBARS &&  93.   	    (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) || (  94.   #ifdef REINCARNATION  95.   		!Is_rogue_level(&u.uz) &&  96.   #endif  97.   		(levl[rx][ry].doormask & ~D_BROKEN) == D_NODOOR)) &&  98.   	    !sobj_at(BOULDER, rx, ry)) { 99.  	    ttmp = t_at(rx, ry); 100. 	    mtmp = m_at(rx, ry); 101.  102.  		/* KMH -- Sokoban doesn't let you push boulders diagonally */ 103. 	    if (In_sokoban(&u.uz) && u.dx && u.dy) { 104. 	    	if (Blind) feel_location(sx,sy); 105. 	    	pline("%s won't roll diagonally on this %s.",  106.  	        		The(xname(otmp)), surface(sx, sy)); 107. 	    	goto cannot_push; 108. 	    }  109.   110.  	    if (revive_nasty(rx, ry, "You sense movement on the other side.")) 111. 		return (-1); 112.  113.  	    if (mtmp && !noncorporeal(mtmp->data) &&  114.  		    (!mtmp->mtrapped || 115. 			 !(ttmp && ((ttmp->ttyp == PIT) || 116. 				    (ttmp->ttyp == SPIKED_PIT))))) { 117. 		if (Blind) feel_location(sx, sy); 118. 		if (canspotmon(mtmp)) 119. 		    pline("There's %s on the other side.", a_monnam(mtmp)); 120. 		else { 121. 		    You_hear("a monster behind %s.", the(xname(otmp))); 122. 		    map_invisible(rx, ry); 123. 		}  124.  		if (flags.verbose) 125. 		    pline("Perhaps that's why %s cannot move it.",  126.  #ifdef STEED  127.  				u.usteed ? y_monnam(u.usteed) :  128.  #endif  129.  				"you"); 130. 		goto cannot_push; 131. 	    }  132.   133.  	    if (ttmp) 134. 		switch(ttmp->ttyp) { 135. 		case LANDMINE: 136. 		    if (rn2(10)) { 137. 			obj_extract_self(otmp); 138. 			place_object(otmp, rx, ry); 139. 			unblock_point(sx, sy); 140. 			newsym(sx, sy); 141. 			pline("KAABLAMM!!!  %s %s land mine.",  142.  			      Tobjnam(otmp, "trigger"),  143.  			      ttmp->madeby_u ? "your" : "a"); 144. 			blow_up_landmine(ttmp); 145. 			/* if the boulder remains, it should fill the pit */ 146. 			fill_pit(u.ux, u.uy); 147. 			if (cansee(rx,ry)) newsym(rx,ry); 148. 			continue; 149. 		    }  150.  		    break; 151. 		case SPIKED_PIT: 152. 		case PIT: 153. 		    obj_extract_self(otmp); 154. 		    /* vision kludge to get messages right; 155. 		       the pit will temporarily be seen even 156. 		       if this is one among multiple boulders */ 157. 		    if (!Blind) viz_array[ry][rx] |= IN_SIGHT; 158. 		    if (!flooreffects(otmp, rx, ry, "fall")) { 159. 			place_object(otmp, rx, ry); 160. 		    }  161.  		    if (mtmp && !Blind) newsym(rx, ry); 162. 		    continue; 163. 		case HOLE: 164. 		case TRAPDOOR: 165. 		    if (Blind) 166. 			pline("Kerplunk!  You no longer feel %s.",  167.  				the(xname(otmp))); 168. 		    else 169. 			pline("%s%s and %s a %s in the %s!",  170.  			  Tobjnam(otmp, 171. 			   (ttmp->ttyp == TRAPDOOR) ? "trigger" : "fall"), 172.  			  (ttmp->ttyp == TRAPDOOR) ? nul : " into",  173.  			  otense(otmp, "plug"),  174.  			  (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",  175.  			  surface(rx, ry)); 176. 		    deltrap(ttmp); 177. 		    delobj(otmp); 178. 		    bury_objs(rx, ry); 179. 		    if (cansee(rx,ry)) newsym(rx,ry); 180. 		    continue; 181. 		case LEVEL_TELEP: 182. 		case TELEP_TRAP: 183. #ifdef STEED 184. 		    if (u.usteed) 185. 			pline("%s pushes %s and suddenly it disappears!",  186.  			      upstart(y_monnam(u.usteed)), the(xname(otmp))); 187. 		    else 188. #endif 189. 		    You("push %s and suddenly it disappears!",  190.  			the(xname(otmp))); 191. 		    if (ttmp->ttyp == TELEP_TRAP) 192. 			rloco(otmp); 193. 		    else { 194. 			int newlev = random_teleport_level; 195. 			d_level dest; 196.  197.  			if (newlev == depth(&u.uz) || In_endgame(&u.uz)) 198. 			    continue; 199. 			obj_extract_self(otmp); 200. 			add_to_migration(otmp); 201. 			get_level(&dest, newlev); 202. 			otmp->ox = dest.dnum; 203. 			otmp->oy = dest.dlevel; 204. 			otmp->owornmask = (long)MIGR_RANDOM; 205. 		    }  206.  		    seetrap(ttmp); 207. 		    continue; 208. 		}  209.  	    if (closed_door(rx, ry)) 210. 		goto nopushmsg; 211. 	    if (boulder_hits_pool(otmp, rx, ry, TRUE)) 212. 		continue; 213. 	    /*  214.  	     * Re-link at top of fobj chain so that pile order is preserved 215. 	     * when level is restored. 216. 	     */  217.  	    if (otmp != fobj) { 218. 		remove_object(otmp); 219. 		place_object(otmp, otmp->ox, otmp->oy); 220. 	    }  221.   222.  	    {  223.  #ifdef LINT /* static long lastmovetime; */ 224. 		long lastmovetime; 225. 		lastmovetime = 0; 226. #else 227. 		/* note: reset to zero after save/restore cycle */ 228. 		static NEARDATA long lastmovetime; 229. #endif 230. #ifdef STEED 231. 		if (!u.usteed) { 232. #endif 233. 		  if (moves > lastmovetime+2 || moves < lastmovetime) 234. 		    pline("With %s effort you move %s.",  235.  			  throws_rocks(youmonst.data) ? "little" : "great",  236.  			  the(xname(otmp))); 237. 		  exercise(A_STR, TRUE); 238. #ifdef STEED 239. 		} else 240. 		    pline("%s moves %s.",  241.  			  upstart(y_monnam(u.usteed)), the(xname(otmp))); 242. #endif 243. 		lastmovetime = moves; 244. 	    }  245.   246.  	    /* Move the boulder *after* the message. */ 247.  	    if (glyph_is_invisible(levl[rx][ry].glyph)) 248. 		unmap_object(rx, ry); 249. 	    movobj(otmp, rx, ry);	/* does newsym(rx,ry) */ 250. 	    if (Blind) { 251. 		feel_location(rx,ry); 252. 		feel_location(sx, sy); 253. 	    } else { 254. 		newsym(sx, sy); 255. 	    }  256.  	} else { 257. 	nopushmsg: 258. #ifdef STEED 259. 	  if (u.usteed) 260. 	    pline("%s tries to move %s, but cannot.",  261.  		  upstart(y_monnam(u.usteed)), the(xname(otmp))); 262. 	  else 263. #endif 264. 	    You("try to move %s, but in vain.", the(xname(otmp))); 265. 	    if (Blind) feel_location(sx, sy); 266. 	cannot_push: 267. 	    if (throws_rocks(youmonst.data)) { 268. #ifdef STEED 269. 		if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) { 270. 		    You("aren't skilled enough to %s %s from %s.",  271.  			(flags.pickup && !In_sokoban(&u.uz))  272.  			    ? "pick up" : "push aside",  273.  			the(xname(otmp)), y_monnam(u.usteed)); 274. 		} else 275. #endif 276. 		{  277.  		    pline("However, you can easily %s.",  278.  			(flags.pickup && !In_sokoban(&u.uz))  279.  			    ? "pick it up" : "push it aside"); 280. 		    if (In_sokoban(&u.uz)) 281. 			change_luck(-1);	/* Sokoban guilt */ 282. 		    break; 283. 		}  284.  		break; 285. 	    }  286.   287.  	    if (  288.  #ifdef STEED  289.  		!u.usteed &&  290.  #endif	     291.  		(((!invent || inv_weight <= -850) &&  292.  		 (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][sy].typ)  293.  				     && IS_ROCK(levl[sx][u.uy].typ)))) 294. 		|| verysmall(youmonst.data))) { 295. 		pline("However, you can squeeze yourself into a small opening."); 296. 		if (In_sokoban(&u.uz)) 297. 		    change_luck(-1);	/* Sokoban guilt */ 298. 		break; 299. 	    } else 300. 		return (-1); 301. 	}  302.      }  303.      return (0); 304. }  305.   306.  /*  307.   *  still_chewing 308.  *  309.   *  Chew on a wall, door, or boulder. Returns TRUE if still eating, FALSE 310.  *  when done. 311.  */  312.  STATIC_OVL int 313. still_chewing(x,y) 314.     xchar x, y;  315. { 316.      struct rm *lev = &levl[x][y]; 317.     struct obj *boulder = sobj_at(BOULDER,x,y); 318.     const char *digtxt = (char *)0, *dmgtxt = (char *)0; 319.  320.      if (digging.down)		/* not continuing previous dig (w/ pick-axe) */ 321. 	(void) memset((genericptr_t)&digging, 0, sizeof digging); 322.  323.      if (!boulder && IS_ROCK(lev->typ) && !may_dig(x,y)) { 324. 	You("hurt your teeth on the %s.",  325.  	    IS_TREE(lev->typ) ? "tree" : "hard stone"); 326. 	nomul(0); 327. 	return 1; 328.     } else if (digging.pos.x != x || digging.pos.y != y ||  329.  		!on_level(&digging.level, &u.uz)) { 330. 	digging.down = FALSE; 331. 	digging.chew = TRUE; 332. 	digging.warned = FALSE; 333. 	digging.pos.x = x;  334. digging.pos.y = y; 335. assign_level(&digging.level, &u.uz); 336. 	/* solid rock takes more work & time to dig through */ 337. 	digging.effort = 338. 	    (IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + u.udaminc; 339. 	You("start chewing %s %s.",  340.  	    (boulder || IS_TREE(lev->typ)) ? "on a" : "a hole in the",  341.  	    boulder ? "boulder" :  342.  	    IS_TREE(lev->typ) ? "tree" : IS_ROCK(lev->typ) ? "rock" : "door"); 343. 	watch_dig((struct monst *)0, x, y, FALSE); 344. 	return 1; 345.     } else if ((digging.effort += (30 + u.udaminc)) <= 100)  { 346. 	if (flags.verbose) 347. 	    You("%s chewing on the %s.",  348.  		digging.chew ? "continue" : "begin",  349.  		boulder ? "boulder" :  350.  		IS_TREE(lev->typ) ? "tree" :  351.  		IS_ROCK(lev->typ) ? "rock" : "door"); 352. 	digging.chew = TRUE; 353. 	watch_dig((struct monst *)0, x, y, FALSE); 354. 	return 1; 355.     }  356.   357.      /* Okay, you've chewed through something */ 358.     u.uconduct.food++; 359.     u.uhunger += rnd(20); 360.  361.      if (boulder) { 362. 	delobj(boulder);		/* boulder goes bye-bye */ 363. 	You("eat the boulder.");	/* yum */ 364.  365.  	/*  366.  	 *  The location could still block because of  367. *	1. More than one boulder 368. 	 *	2. Boulder stuck in a wall/stone/door. 369. 	 *  370.  	 *  [perhaps use does_block below (from vision.c)] 371. 	 */  372.  	if (IS_ROCK(lev->typ) || closed_door(x,y) || sobj_at(BOULDER,x,y)) { 373. 	    block_point(x,y);	/* delobj will unblock the point */ 374. 	    /* reset dig state */ 375. 	    (void) memset((genericptr_t)&digging, 0, sizeof digging); 376. 	    return 1; 377. 	}  378.   379.      } else if (IS_WALL(lev->typ)) { 380. 	if (*in_rooms(x, y, SHOPBASE)) { 381. 	    add_damage(x, y, 10L * ACURRSTR); 382. 	    dmgtxt = "damage"; 383. 	}  384.  	digtxt = "chew a hole in the wall."; 385. 	if (level.flags.is_maze_lev) { 386. 	    lev->typ = ROOM; 387. 	} else if (level.flags.is_cavernous_lev && !in_town(x, y)) { 388. 	    lev->typ = CORR; 389. 	} else { 390. 	    lev->typ = DOOR; 391. 	    lev->doormask = D_NODOOR; 392. 	}  393.      } else if (IS_TREE(lev->typ)) { 394. 	digtxt = "chew through the tree."; 395. 	lev->typ = ROOM; 396.     } else if (lev->typ == SDOOR) { 397. 	if (lev->doormask & D_TRAPPED) { 398. 	    lev->doormask = D_NODOOR; 399. 	    b_trapped("secret door", 0); 400. 	} else { 401. 	    digtxt = "chew through the secret door."; 402. 	    lev->doormask = D_BROKEN; 403. 	}  404.  	lev->typ = DOOR; 405.  406.      } else if (IS_DOOR(lev->typ)) { 407. 	if (*in_rooms(x, y, SHOPBASE)) { 408. 	    add_damage(x, y, 400L); 409. 	    dmgtxt = "break"; 410. 	}  411.  	if (lev->doormask & D_TRAPPED) { 412. 	    lev->doormask = D_NODOOR; 413. 	    b_trapped("door", 0); 414. 	} else { 415. 	    digtxt = "chew through the door."; 416. 	    lev->doormask = D_BROKEN; 417. 	}  418.   419.      } else { /* STONE or SCORR */ 420. 	digtxt = "chew a passage through the rock."; 421. 	lev->typ = CORR; 422.     }  423.   424.      unblock_point(x, y);	/* vision */ 425.     newsym(x, y); 426.     if (digtxt) You(digtxt);	/* after newsym */ 427.     if (dmgtxt) pay_for_damage(dmgtxt, FALSE); 428.     (void) memset((genericptr_t)&digging, 0, sizeof digging); 429.     return 0; 430. }  431.   432.  #endif /* OVL2 */ 433. #ifdef OVLB 434.  435.  void 436. movobj(obj, ox, oy) 437. register struct obj *obj; 438. register xchar ox, oy; 439. {  440.  	/* optimize by leaving on the fobj chain? */ 441.  	remove_object(obj); 442. 	newsym(obj->ox, obj->oy); 443. 	place_object(obj, ox, oy); 444. 	newsym(ox, oy); 445. }  446.   447.  #ifdef SINKS 448. static NEARDATA const char fell_on_sink[] = "fell onto a sink"; 449.  450.  STATIC_OVL void 451. dosinkfall 452. {  453.  	register struct obj *obj; 454.  455.  	if (is_floater(youmonst.data) || (HLevitation & FROMOUTSIDE)) { 456. 	    You("wobble unsteadily for a moment."); 457. 	} else { 458. 	    long save_ELev = ELevitation, save_HLev = HLevitation; 459.  460.  	    /* fake removal of levitation in advance so that final 461. 	       disclosure will be right in case this turns out to  462. be fatal; fortunately the fact that rings and boots 463. 	       are really still worn has no effect on bones data */ 464. 	    ELevitation = HLevitation = 0L; 465. 	    You("crash to the floor!"); 466. 	    losehp(rn1(8, 25 - (int)ACURR(A_CON)),  467.  		   fell_on_sink, NO_KILLER_PREFIX); 468. 	    exercise(A_DEX, FALSE); 469. 	    selftouch("Falling, you"); 470. 	    for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) 471. 		if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) { 472. 		    You("fell on %s.", doname(obj)); 473. 		    losehp(rnd(3), fell_on_sink, NO_KILLER_PREFIX); 474. 		    exercise(A_CON, FALSE); 475. 		}  476.  	    ELevitation = save_ELev; 477. 	    HLevitation = save_HLev; 478. 	}  479.   480.  	ELevitation &= ~W_ARTI; 481. 	HLevitation &= ~(I_SPECIAL|TIMEOUT); 482. 	HLevitation++; 483. 	if(uleft && uleft->otyp == RIN_LEVITATION) { 484. 	    obj = uleft; 485. 	    Ring_off(obj); 486. 	    off_msg(obj); 487. 	}  488.  	if(uright && uright->otyp == RIN_LEVITATION) { 489. 	    obj = uright; 490. 	    Ring_off(obj); 491. 	    off_msg(obj); 492. 	}  493.  	if(uarmf && uarmf->otyp == LEVITATION_BOOTS) { 494. 	    obj = uarmf; 495. 	    (void)Boots_off; 496. 	    off_msg(obj); 497. 	}  498.  	HLevitation--; 499. }  500.  #endif 501.  502.  boolean 503. may_dig(x,y) 504. register xchar x,y; 505. /* intended to be called only on ROCKs */ 506. {  507.      return (boolean)(!(IS_STWALL(levl[x][y].typ) && 508. 			(levl[x][y].wall_info & W_NONDIGGABLE))); 509. }  510.   511.  boolean 512. may_passwall(x,y) 513. register xchar x,y; 514. {  515.     return (boolean)(!(IS_STWALL(levl[x][y].typ) && 516. 			(levl[x][y].wall_info & W_NONPASSWALL))); 517. }  518.   519.  #endif /* OVLB */ 520. #ifdef OVL1 521.  522.  boolean 523. bad_rock(mdat,x,y) 524. struct permonst *mdat; 525. register xchar x,y; 526. {  527.  	return((boolean) ((In_sokoban(&u.uz) && sobj_at(BOULDER,x,y)) || 528. 	       (IS_ROCK(levl[x][y].typ)  529.  		    && (!tunnels(mdat) || needspick(mdat) || !may_dig(x,y))  530.  		    && !(passes_walls(mdat) && may_passwall(x,y))))); 531. }  532.   533.  boolean 534. invocation_pos(x, y)  535. xchar x, y; 536. { 537.  	return((boolean)(Invocation_lev(&u.uz) && x == inv_pos.x && y == inv_pos.y)); 538. }  539.   540.  #endif /* OVL1 */ 541. #ifdef OVL3 542.  543.  /* return TRUE if (dx,dy) is an OK place to move 544.  * mode is one of DO_MOVE, TEST_MOVE or TEST_TRAV 545.  */  546.  boolean 547. test_move(ux, uy, dx, dy, mode) 548. int ux, uy, dx, dy; 549. int mode; 550. {  551.      int x = ux+dx; 552.     int y = uy+dy; 553.     register struct rm *tmpr = &levl[x][y]; 554.     register struct rm *ust; 555.  556.      /*  557.       *  Check for physical obstacles. First, the place we are going. 558.      */  559.      if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) { 560. 	if (Blind && mode == DO_MOVE) feel_location(x,y); 561. 	if (Passes_walls && may_passwall(x,y)) { 562. 	    ;	/* do nothing */ 563. 	} else if (tmpr->typ == IRONBARS) { 564. 	    if (!(Passes_walls || passes_bars(youmonst.data))) 565. 		return FALSE; 566. 	} else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { 567. 	    /* Eat the rock. */ 568.  	    if (mode == DO_MOVE && still_chewing(x,y)) return FALSE; 569. 	} else if (flags.autodig && !flags.run && !flags.nopick &&  570.  		   uwep && is_pick(uwep)) { 571. 	/* MRKR: Automatic digging when wielding the appropriate tool */ 572. 	    if (mode == DO_MOVE) 573. 		(void) use_pick_axe2(uwep); 574. 	    return FALSE; 575. 	} else { 576. 	    if (mode == DO_MOVE) { 577. 		if (Is_stronghold(&u.uz) && is_db_wall(x,y)) 578. 		    pline_The("drawbridge is up!"); 579. 		if (Passes_walls && !may_passwall(x,y) && In_sokoban(&u.uz)) 580. 		    pline_The("Sokoban walls resist your ability."); 581. 	    }  582.  	    return FALSE; 583. 	}  584.      } else if (IS_DOOR(tmpr->typ)) { 585. 	if (closed_door(x,y)) { 586. 	    if (Blind && mode == DO_MOVE) feel_location(x,y); 587. 	    if (Passes_walls) 588. 		;	/* do nothing */ 589. 	    else if (can_ooze(&youmonst)) { 590. 		if (mode == DO_MOVE) You("ooze under the door."); 591. 	    } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { 592. 		/* Eat the door. */ 593.  		if (mode == DO_MOVE && still_chewing(x,y)) return FALSE; 594. 	    } else { 595. 		if (mode == DO_MOVE) { 596. 		    if (amorphous(youmonst.data)) 597. 			You("try to ooze under the door, but can't squeeze your possessions through."); 598. 		    else if (x == ux || y == uy) { 599. 			if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) { 600. #ifdef STEED 601. 			    if (u.usteed) { 602. 				You_cant("lead %s through that closed door.",  603.  				         y_monnam(u.usteed)); 604. 			    } else 605. #endif 606. 			    {  607.  			        pline("Ouch!  You bump into a door."); 608. 			        exercise(A_DEX, FALSE); 609. 			    }  610.  			} else pline("That door is closed."); 611. 		    }  612.  		} else if (mode == TEST_TRAV) goto testdiag; 613. 		return FALSE; 614. 	    }  615.  	} else { 616. 	testdiag: 617. 	    if (dx && dy && !Passes_walls  618.  		&& ((tmpr->doormask & ~D_BROKEN) 619. #ifdef REINCARNATION 620. 		    || Is_rogue_level(&u.uz) 621. #endif 622. 		    || block_door(x,y))) { 623. 		/* Diagonal moves into a door are not allowed. */ 624.  		if (Blind && mode == DO_MOVE) 625. 		    feel_location(x,y); 626. 		return FALSE; 627. 	    }  628.  	}  629.      }  630.      if (dx && dy  631.  	    && bad_rock(youmonst.data,ux,y) && bad_rock(youmonst.data,x,uy)) { 632. 	/* Move at a diagonal. */ 633.  	if (In_sokoban(&u.uz)) { 634. 	    if (mode == DO_MOVE) 635. 		You("cannot pass that way."); 636. 	    return FALSE; 637. 	}  638.  	if (bigmonst(youmonst.data)) { 639. 	    if (mode == DO_MOVE) 640. 		Your("body is too large to fit through."); 641. 	    return FALSE; 642. 	}  643.  	if (invent && (inv_weight + weight_cap > 600)) { 644. 	    if (mode == DO_MOVE) 645. 		You("are carrying too much to get through."); 646. 	    return FALSE; 647. 	}  648.      }  649.      /* Pick travel path that does not require crossing a trap. 650.      * Avoid water and lava using the usual running rules. 651.      * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */ 652.     if (flags.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) { 653. 	struct trap* t = t_at(x, y); 654.  655.  	if ((t && t->tseen) ||  656.  	    (!Levitation && !Flying && 657. 	     !is_clinger(youmonst.data) && 658. 	     (is_pool(x, y) || is_lava(x, y)) && levl[x][y].seenv)) 659. 	    return FALSE; 660.     }  661.   662.      ust = &levl[ux][uy]; 663.  664.      /* Now see if other things block our way. . */ 665.      if (dx && dy && !Passes_walls  666.  		     && (IS_DOOR(ust->typ) && ((ust->doormask & ~D_BROKEN)  667.  #ifdef REINCARNATION  668.  			     || Is_rogue_level(&u.uz)  669.  #endif  670.  			     || block_entry(x, y)) 671. 			 )) {  672.  	/* Can't move at a diagonal out of a doorway with door. */ 673.  	return FALSE; 674.     }  675.   676.      if (sobj_at(BOULDER,x,y) && (In_sokoban(&u.uz) || !Passes_walls)) { 677. 	if (!(Blind || Hallucination) && (flags.run >= 2) && mode != TEST_TRAV) 678. 	    return FALSE; 679. 	if (mode == DO_MOVE) { 680. 	    /* tunneling monsters will chew before pushing */ 681. 	    if (tunnels(youmonst.data) && !needspick(youmonst.data) &&  682.  		!In_sokoban(&u.uz)) { 683. 		if (still_chewing(x,y)) return FALSE; 684. 	    } else 685. 		if (moverock < 0) return FALSE; 686. 	} else if (mode == TEST_TRAV) { 687. 	    struct obj* obj; 688.  689.  	    /* don't pick two boulders in a row, unless there's a way thru */ 690. 	    if (sobj_at(BOULDER,ux,uy) && !In_sokoban(&u.uz)) { 691. 		if (!Passes_walls &&  692.  		    !(tunnels(youmonst.data) && !needspick(youmonst.data)) &&  693.  		    !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK) &&  694.  		    !((obj = carrying(WAN_DIGGING)) && 695. 		      !objects[obj->otyp].oc_name_known)) 696. 		    return FALSE; 697. 	    }  698.  	}  699.  	/* assume you'll be able to push it when you get there... */ 700.      }  701.   702.      /* OK, it is a legal place to move. */ 703.      return TRUE; 704. }  705.   706.  /*  707.   * Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy). 708.  * A shortest path is returned. If guess is TRUE, consider various 709.  * inaccessible locations as valid intermediate path points. 710.  * Returns TRUE if a path was found. 711.  */  712.  static boolean 713. findtravelpath(guess) 714. boolean guess; 715. {  716.      /* if travel to adjacent, reachable location, use normal movement rules */ 717.     if (!guess && iflags.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1) { 718. 	flags.run = 0; 719. 	if (test_move(u.ux, u.uy, u.tx-u.ux, u.ty-u.uy, TEST_MOVE)) { 720. 	    u.dx = u.tx-u.ux; 721. 	    u.dy = u.ty-u.uy; 722. 	    nomul(0); 723. 	    iflags.travelcc.x = iflags.travelcc.y = -1; 724. 	    return TRUE; 725. 	}  726.  	flags.run = 8; 727.     }  728.      if (u.tx != u.ux || u.ty != u.uy) { 729. 	xchar travel[COLNO][ROWNO]; 730. 	xchar travelstepx[2][COLNO*ROWNO]; 731. 	xchar travelstepy[2][COLNO*ROWNO]; 732. 	xchar tx, ty, ux, uy; 733. 	int n = 1;			/* max offset in travelsteps */ 734. 	int set = 0;			/* two sets current and previous */ 735. 	int radius = 1;			/* search radius */ 736. 	int i;  737. 738. 	/* If guessing, first find an "obvious" goal location. The obvious 739. 	 * goal is the position the player knows of, or might figure out 740. 	 * (couldsee) that is closest to the target on a straight path. 741. 	 */  742.  	if (guess) { 743. 	    tx = u.ux; ty = u.uy; ux = u.tx; uy = u.ty; 744. 	} else { 745. 	    tx = u.tx; ty = u.ty; ux = u.ux; uy = u.uy; 746. 	}  747.   748.      noguess: 749. 	(void) memset((genericptr_t)travel, 0, sizeof(travel)); 750. 	travelstepx[0][0] = tx; 751. 	travelstepy[0][0] = ty; 752.  753.  	while (n != 0) { 754. 	    int nn = 0; 755.  756.  	    for (i = 0; i < n; i++) { 757. 		int dir; 758. 		int x = travelstepx[set][i]; 759. 		int y = travelstepy[set][i]; 760. 		static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 }; 761. 		/* no diagonal movement for grid bugs */ 762. 		int dirmax = u.umonnum == PM_GRID_BUG ? 4 : 8; 763.   764.  		for (dir = 0; dir < dirmax; ++dir) { 765. 		    int nx = x+xdir[ordered[dir]]; 766. 		    int ny = y+ydir[ordered[dir]]; 767.  768.  		    if (!isok(nx, ny)) continue; 769. 		    if ((!Passes_walls && !can_ooze(&youmonst) && 770. 			closed_door(x, y)) || sobj_at(BOULDER, x, y)) { 771. 			/* closed doors and boulders usually 772. 			 * cause a delay, so prefer another path */ 773. 			if (travel[x][y] > radius-3) { 774. 			    travelstepx[1-set][nn] = x;  775. travelstepy[1-set][nn] = y; 776. /* don't change travel matrix! */ 777.  			    nn++; 778. 			    continue; 779. 			}  780.  		    }  781.  		    if (test_move(x, y, nx-x, ny-y, TEST_TRAV) &&  782.  			(levl[nx][ny].seenv || (!Blind && couldsee(nx, ny)))) { 783. 			if (nx == ux && ny == uy) { 784. 			    if (!guess) { 785. 				u.dx = x-ux; 786. 				u.dy = y-uy; 787. 				if (x == u.tx && y == u.ty) { 788. 				    nomul(0); 789. 				    /* reset run so domove run checks work */ 790. 				    flags.run = 8; 791. 				    iflags.travelcc.x = iflags.travelcc.y = -1; 792. 				}  793.  				return TRUE; 794. 			    }  795.  			} else if (!travel[nx][ny]) { 796. 			    travelstepx[1-set][nn] = nx; 797. 			    travelstepy[1-set][nn] = ny; 798. 			    travel[nx][ny] = radius; 799. 			    nn++; 800. 			}  801.  		    }  802.  		}  803.  	    }  804.  	     805.  	    n = nn; 806. 	    set = 1-set; 807. 	    radius++; 808. 	}  809.   810.  	/* if guessing, find best location in travel matrix and go there */ 811. 	if (guess) { 812. 	    int px = tx, py = ty;	/* pick location */ 813. 	    int dist, nxtdist, d2, nd2; 814.  815.  	    dist = distmin(ux, uy, tx, ty); 816. 	    d2 = dist2(ux, uy, tx, ty); 817. 	    for (tx = 1; tx < COLNO; ++tx) 818. 		for (ty = 0; ty < ROWNO; ++ty) 819. 		    if (travel[tx][ty]) { 820. 			nxtdist = distmin(ux, uy, tx, ty); 821. 			if (nxtdist == dist && couldsee(tx, ty)) { 822. 			    nd2 = dist2(ux, uy, tx, ty); 823. 			    if (nd2 < d2) { 824. 				/* prefer non-zigzag path */ 825. 				px = tx; py = ty; 826. 				d2 = nd2; 827. 			    }  828.  			} else if (nxtdist < dist && couldsee(tx, ty)) { 829. 			    px = tx; py = ty; 830. 			    dist = nxtdist; 831. 			    d2 = dist2(ux, uy, tx, ty); 832. 			}  833.  		    }  834.   835.  	    if (px == u.ux && py == u.uy) { 836. 		/* no guesses, just go in the general direction */ 837. 		u.dx = sgn(u.tx - u.ux); 838. 		u.dy = sgn(u.ty - u.uy); 839. 		if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE)) 840. 		    return TRUE; 841. 		goto found; 842. 	    }  843.  	    tx = px; 844. 	    ty = py; 845. 	    ux = u.ux; 846. 	    uy = u.uy; 847. 	    set = 0; 848. 	    n = radius = 1; 849. 	    guess = FALSE; 850. 	    goto noguess; 851. 	}  852.  	return FALSE; 853.     }  854.   855.  found: 856.     u.dx = 0; 857.     u.dy = 0; 858.     nomul(0); 859.     return FALSE; 860. }  861.   862.  void 863. domove 864. {  865.  	register struct monst *mtmp; 866. 	register struct rm *tmpr; 867. 	register xchar x,y; 868. 	struct trap *trap; 869. 	int wtcap; 870. 	boolean on_ice; 871. 	xchar chainx, chainy, ballx, bally;	/* ball&chain new positions */ 872. 	int bc_control;				/* control for ball&chain */ 873. 	boolean cause_delay = FALSE;	/* dragging ball will skip a move */ 874. 	const char *predicament; 875.  876.  	u_wipe_engr(rnd(5)); 877.  878.  	if (flags.travel) { 879. 	    if (!findtravelpath(FALSE)) 880. 		(void) findtravelpath(TRUE); 881. 	    iflags.travel1 = 0; 882. 	}  883.   884.  	if(((wtcap = near_capacity) >= OVERLOADED 885. 	    || (wtcap > SLT_ENCUMBER &&  886.  		(Upolyd ? (u.mh < 5 && u.mh != u.mhmax) 887. 			: (u.uhp < 10 && u.uhp != u.uhpmax))))  888.  	   && !Is_airlevel(&u.uz)) { 889. 	    if(wtcap < OVERLOADED) { 890. 		You("don't have enough stamina to move."); 891. 		exercise(A_CON, FALSE); 892. 	    } else 893. 		You("collapse under your load."); 894. 	    nomul(0); 895. 	    return; 896. 	}  897.  	if(u.uswallow) { 898. 		u.dx = u.dy = 0; 899. 		u.ux = x = u.ustuck->mx; 900. 		u.uy = y = u.ustuck->my; 901. 		mtmp = u.ustuck; 902. 	} else { 903. 		if (Is_airlevel(&u.uz) && rn2(4) &&  904.  			!Levitation && !Flying) { 905. 		    switch(rn2(3)) { 906. 		    case 0: 907. 			You("tumble in place."); 908. 			exercise(A_DEX, FALSE); 909. 			break; 910. 		    case 1: 911. 			You_cant("control your movements very well."); break; 912. 		    case 2: 913. 			pline("It's hard to walk in thin air."); 914. 			exercise(A_DEX, TRUE); 915. 			break; 916. 		    }  917.  		    return; 918. 		}  919.   920.  		/* check slippery ice */ 921. 		on_ice = !Levitation && is_ice(u.ux, u.uy); 922. 		if (on_ice) { 923. 		    static int skates = 0; 924. 		    if (!skates) skates = find_skates; 925. 		    if ((uarmf && uarmf->otyp == skates)  926.  			    || resists_cold(&youmonst) || Flying  927.  			    || is_floater(youmonst.data) || is_clinger(youmonst.data)  928.  			    || is_whirly(youmonst.data)) 929. 			on_ice = FALSE; 930. 		    else if (!rn2(Cold_resistance ? 3 : 2)) { 931.  			HFumbling |= FROMOUTSIDE; 932. 			HFumbling &= ~TIMEOUT; 933. 			HFumbling += 1;  /* slip on next move */ 934. 		    }  935.  		}  936.  		if (!on_ice && (HFumbling & FROMOUTSIDE)) 937. 		    HFumbling &= ~FROMOUTSIDE; 938.  939.  		x = u.ux + u.dx; 940. 		y = u.uy + u.dy; 941. 		if(Stunned || (Confusion && !rn2(5))) { 942. 			register int tries = 0; 943.  944.  			do { 945. 				if(tries++ > 50) { 946. 					nomul(0); 947. 					return; 948. 				}  949.  				confdir; 950. 				x = u.ux + u.dx; 951. 				y = u.uy + u.dy; 952. 			} while(!isok(x, y) || bad_rock(youmonst.data, x, y)); 953. 		}  954.  		/* turbulence might alter your actual destination */ 955. 		if (u.uinwater) { 956. 			water_friction; 957. 			if (!u.dx && !u.dy) { 958. 				nomul(0); 959. 				return; 960. 			}  961.  			x = u.ux + u.dx; 962. 			y = u.uy + u.dy; 963. 		}  964.  		if(!isok(x, y)) { 965. 			nomul(0); 966. 			return; 967. 		}  968.  		if (((trap = t_at(x, y)) && trap->tseen) ||  969.  		    (Blind && !Levitation && !Flying && 970. 		     !is_clinger(youmonst.data) && 971. 		     (is_pool(x, y) || is_lava(x, y)) && levl[x][y].seenv)) { 972. 			if(flags.run >= 2) { 973. 				nomul(0); 974. 				flags.move = 0; 975. 				return; 976. 			} else 977. 				nomul(0); 978. 		}  979.   980.  		if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) { 981. 		    if (distu(u.ustuck->mx, u.ustuck->my) > 2) { 982. 			/* perhaps it fled (or was teleported or ... ) */ 983. 			u.ustuck = 0; 984. 		    } else if (sticks(youmonst.data)) { 985. 			/* When polymorphed into a sticking monster, 986. 			 * u.ustuck means it's stuck to you, not you to it. 987. 			 */  988.  			You("release %s.", mon_nam(u.ustuck)); 989. 			u.ustuck = 0; 990. 		    } else { 991. 			/* If holder is asleep or paralyzed: 992. 			 *	37.5% chance of getting away, 993. 			 *	12.5% chance of waking/releasing it; 994. 			 * otherwise: 995. 			 *	 7.5% chance of getting away. 996. 			 * [strength ought to be a factor] 997. 			 * If holder is tame and there is no conflict, 998. 			 * guaranteed escape. 999. 			 */  1000. 			switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) { 1001. 			case 0: case 1: case 2: 1002. 			pull_free: 1003. 			   You("pull free from %s.", mon_nam(u.ustuck)); 1004. 			   u.ustuck = 0; 1005. 			   break; 1006. 			case 3: 1007. 			   if (!u.ustuck->mcanmove) { 1008. 				/* it's free to move on next turn */ 1009. 				u.ustuck->mfrozen = 1; 1010. 				u.ustuck->msleeping = 0; 1011. 			   }  1012. 			    /*FALLTHRU*/ 1013. 			default: 1014. 			   if (u.ustuck->mtame &&  1015. 				!Conflict && !u.ustuck->mconf) 1016. 				goto pull_free; 1017. 			   You("cannot escape from %s!", mon_nam(u.ustuck)); 1018. 			   nomul(0); 1019. 			   return; 1020. 			} 1021. 		    }  1022. 		}  1023.  1024. 		mtmp = m_at(x,y); 1025. 		if (mtmp) { 1026. 			/* Don't attack if you're running, and can see it */ 1027. 			/* We should never get here if forcefight */ 1028. 			if (flags.run && 1029. 			    ((!Blind && mon_visible(mtmp) &&  1030. 			      ((mtmp->m_ap_type != M_AP_FURNITURE &&  1031. 				mtmp->m_ap_type != M_AP_OBJECT) || 1032. 			      Protection_from_shape_changers)) || 1033. 			    sensemon(mtmp))) { 1034. 				nomul(0); 1035. 				flags.move = 0; 1036. 				return; 1037. 			} 1038. 		}  1039. 	}  1040.  1041. 	u.ux0 = u.ux; 1042. 	u.uy0 = u.uy; 1043. 	bhitpos.x = x; 1044. bhitpos.y = y; 1045. tmpr = &levl[x][y]; 1046. 1047. 	/* attack monster */ 1048. 	if(mtmp) { 1049. 	   nomul(0); 1050. 	   /* only attack if we know it's there */ 1051. 	   /* or if we used the 'F' command to fight blindly */ 1052. 	   /* or if it hides_under, in which case we call attack to print 1053. 	    * the Wait! message. 1054. 	    * This is different from ceiling hiders, who aren't handled in  1055. * attack. 1056. 	    */  1057.  1058. 	    /* If they used a 'm' command, trying to move onto a monster 1059. 	    * prints the below message and wastes a turn. The exception is 1060. * if the monster is unseen and the player doesn't remember an 1061. * invisible monster--then, we fall through to attack and 1062. 	    * attack_check, which still wastes a turn, but prints a  1063. * different message and makes the player remember the monster. */ 1064. 	    if(flags.nopick &&  1065. 		  (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))){ 1066. 		if(mtmp->m_ap_type && !Protection_from_shape_changers 1067. 						    && !sensemon(mtmp)) 1068. 		   stumble_onto_mimic(mtmp); 1069. 		else if (mtmp->mpeaceful && !Hallucination) 1070. 		   pline("Pardon me, %s.", m_monnam(mtmp)); 1071. 		else 1072. 		   You("move right into %s.", mon_nam(mtmp)); 1073. 		return; 1074. 	   }  1075. 	    if(flags.forcefight || !mtmp->mundetected || sensemon(mtmp) ||  1076. 		    ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL) && 1077. 			!is_safepet(mtmp))){ 1078. 		gethungry; 1079. 		if(wtcap >= HVY_ENCUMBER && moves%3) { 1080. 		   if (Upolyd && u.mh > 1) { 1081. 			u.mh--; 1082. 		   } else if (!Upolyd && u.uhp > 1) { 1083. 			u.uhp--; 1084. 		   } else { 1085. 			You("pass out from exertion!"); 1086. 			exercise(A_CON, FALSE); 1087. 			fall_asleep(-10, FALSE); 1088. 		   }  1089. 		}  1090. 		if(multi < 0) return;	/* we just fainted */ 1091. 1092. 		/* try to attack; note that it might evade */ 1093. 		/* also, we don't attack tame when _safepet_ */ 1094. 		if(attack(mtmp)) return; 1095. 	   }  1096. 	}  1097.  1098. 	/* specifying 'F' with no monster wastes a turn */ 1099. 	if (flags.forcefight || 1100. 	    /* remembered an 'I' && didn't use a move command */  1101. 	    (glyph_is_invisible(levl[x][y].glyph) && !flags.nopick)) { 1102. 		boolean expl = (Upolyd && attacktype(youmonst.data, AT_EXPL)); 1103. 	   	char buf[BUFSZ]; 1104. 		Sprintf(buf,"a vacant spot on the %s", surface(x,y)); 1105. 		You("%s %s.", 1106. 		    expl ? "explode at" : "attack",  1107. 		    !Underwater ? "thin air" :  1108. 		    is_pool(x,y) ? "empty water" : buf); 1109. 		unmap_object(x, y); /* known empty -- remove 'I' if present */ 1110. 		newsym(x, y); 1111. 		nomul(0); 1112. 		if (expl) { 1113. 		   u.mh = -1;		/* dead in the current form */ 1114. 		   rehumanize; 1115. 		} 1116. 		return; 1117. 	} 1118. 	if (glyph_is_invisible(levl[x][y].glyph)) { 1119. 	   unmap_object(x, y); 1120. 	   newsym(x, y); 1121. 	} 1122. 	/* not attacking an animal, so we try to move */ 1123. #ifdef STEED 1124. 	if (u.usteed && !u.usteed->mcanmove && (u.dx || u.dy)) { 1125. 		pline("%s won't move!", upstart(y_monnam(u.usteed))); 1126. 		nomul(0); 1127. 		return; 1128. 	} else 1129. #endif 1130. 	if(!youmonst.data->mmove) { 1131. 		You("are rooted %s.", 1132. 		    Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?  1133. 		    "in place" : "to the ground"); 1134. 		nomul(0); 1135. 		return; 1136. 	} 1137. 	if(u.utrap) { 1138. 		if(u.utraptype == TT_PIT) { 1139. 		   if (!rn2(2) && sobj_at(BOULDER, u.ux, u.uy)) { 1140. 			Your("%s gets stuck in a crevice.", body_part(LEG)); 1141. 			display_nhwindow(WIN_MESSAGE, FALSE); 1142. 			clear_nhwindow(WIN_MESSAGE); 1143. 			You("free your %s.", body_part(LEG)); 1144. 		   } else if (!(--u.utrap)) { 1145. 			You("%s to the edge of the pit.", 1146. 				(In_sokoban(&u.uz) && Levitation) ?  1147. 				"struggle against the air currents and float" :  1148. #ifdef STEED  1149. 				u.usteed ? "ride" :  1150. #endif  1151. 				"crawl"); 1152. 			fill_pit(u.ux, u.uy); 1153. 			vision_full_recalc = 1;	/* vision limits change */ 1154. 		   } else if (flags.verbose) { 1155. #ifdef STEED 1156. 			if (u.usteed) 1157. 			   Norep("%s is still in a pit.",  1158. 				  upstart(y_monnam(u.usteed))); 1159. 			else 1160. #endif 1161. 			Norep( (Hallucination && !rn2(5)) ? 1162. 				"You've fallen, and you can't get up." :  1163. 				"You are still in a pit." ); 1164. 		   }  1165. 		} else if (u.utraptype == TT_LAVA) { 1166. 		   if(flags.verbose) { 1167. 			predicament = "stuck in the lava"; 1168. #ifdef STEED 1169. 			if (u.usteed) 1170. 			   Norep("%s is %s.", upstart(y_monnam(u.usteed)),  1171. 				  predicament); 1172. 			else 1173. #endif 1174. 			Norep("You are %s.", predicament); 1175. 		   }  1176. 		    if(!is_lava(x,y)) { 1177. 			u.utrap--; 1178. 			if((u.utrap & 0xff) == 0) { 1179. #ifdef STEED 1180. 			   if (u.usteed) 1181. 				You("lead %s to the edge of the lava.", 1182. 				    y_monnam(u.usteed)); 1183. 			   else 1184. #endif 1185. 			    You("pull yourself to the edge of the lava."); 1186. 			   u.utrap = 0; 1187. 			} 1188. 		    }  1189. 		    u.umoved = TRUE; 1190. 		} else if (u.utraptype == TT_WEB) { 1191. 		   if(uwep && uwep->oartifact == ART_STING) { 1192. 			u.utrap = 0; 1193. 			pline("Sting cuts through the web!"); 1194. 			return; 1195. 		   }  1196. 		    if(--u.utrap) { 1197. 			if(flags.verbose) { 1198. 			   predicament = "stuck to the web"; 1199. #ifdef STEED 1200. 			   if (u.usteed) 1201. 				Norep("%s is %s.", upstart(y_monnam(u.usteed)), 1202. 				      predicament); 1203. 			   else 1204. #endif 1205. 			   Norep("You are %s.", predicament); 1206. 			} 1207. 		    } else { 1208. #ifdef STEED 1209. 			if (u.usteed) 1210. 			   pline("%s breaks out of the web.",  1211. 				  upstart(y_monnam(u.usteed))); 1212. 			else 1213. #endif 1214. 			You("disentangle yourself."); 1215. 		   }  1216. 		} else if (u.utraptype == TT_INFLOOR) { 1217. 		   if(--u.utrap) { 1218. 			if(flags.verbose) { 1219. 			   predicament = "stuck in the"; 1220. #ifdef STEED 1221. 			   if (u.usteed) 1222. 				Norep("%s is %s %s.", 1223. 				      upstart(y_monnam(u.usteed)),  1224. 				      predicament, surface(u.ux, u.uy)); 1225. 			   else 1226. #endif 1227. 			   Norep("You are %s %s.", predicament,  1228. 				  surface(u.ux, u.uy)); 1229. 			} 1230. 		    } else { 1231. #ifdef STEED 1232. 			if (u.usteed) 1233. 			   pline("%s finally wiggles free.",  1234. 				  upstart(y_monnam(u.usteed))); 1235. 			else 1236. #endif 1237. 			You("finally wiggle free."); 1238. 		   }  1239. 		} else { 1240. 		   if(flags.verbose) { 1241. 			predicament = "caught in a bear trap"; 1242. #ifdef STEED 1243. 			if (u.usteed) 1244. 			   Norep("%s is %s.", upstart(y_monnam(u.usteed)),  1245. 				  predicament); 1246. 			else 1247. #endif 1248. 			Norep("You are %s.", predicament); 1249. 		   }  1250. 		    if((u.dx && u.dy) || !rn2(5)) u.utrap--; 1251. 		} 1252. 		return; 1253. 	} 1254.  1255. 	if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, DO_MOVE)) { 1256. 	   flags.move = 0; 1257. 	   nomul(0); 1258. 	   return; 1259. 	} 1260.  1261. 	/* Move ball and chain. */ 1262. 	if (Punished) 1263. 	   if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy, 1264. 			&cause_delay, TRUE)) 1265. 		return; 1266. 1267. 	/* Check regions entering/leaving */ 1268. 	if (!in_out_region(x,y)) 1269. 	   return; 1270. 1271.  	/* now move the hero */ 1272. 	mtmp = m_at(x, y); 1273. 	u.ux += u.dx; 1274. 	u.uy += u.dy; 1275. #ifdef STEED 1276. 	/* Move your steed, too */ 1277. 	if (u.usteed) { 1278. 		u.usteed->mx = u.ux; 1279. 		u.usteed->my = u.uy; 1280. 		exercise_steed; 1281. 	} 1282. #endif 1283. 1284. 	/*  1285. 	 * If safepet at destination then move the pet to the hero's  1286. * previous location using the same conditions as in attack. 1287. 	 * there are special extenuating circumstances: 1288. 	 * (1) if the pet dies then your god angers, 1289. 	 * (2) if the pet gets trapped then your god may disapprove, 1290. 	 * (3) if the pet was already trapped and you attempt to free it 1291. * not only do you encounter the trap but you may frighten your 1292. 	 * pet causing it to go wild! moral: don't abuse this privilege. 1293. 	 * 1294. 	 * Ceiling-hiding pets are skipped by this section of code, to  1295. * be caught by the normal falling-monster code. 1296. 	 */ 1297. 	if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) { 1298. 	   /* if trapped, there's a chance the pet goes wild */ 1299. 	   if (mtmp->mtrapped) { 1300. 		if (!rn2(mtmp->mtame)) { 1301. 		   mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0; 1302. 		   if (mtmp->mleashed) m_unleash(mtmp, TRUE); 1303. 		   growl(mtmp); 1304. 		} else { 1305. 		   yelp(mtmp); 1306. 		} 1307. 	    }  1308. 	    mtmp->mundetected = 0; 1309. 	   if (mtmp->m_ap_type) seemimic(mtmp); 1310. 	   else if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my); 1311. 1312. 	    if (mtmp->mtrapped &&  1313. 		    (trap = t_at(mtmp->mx, mtmp->my)) != 0 &&  1314. 		    (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) &&  1315. 		    sobj_at(BOULDER, trap->tx, trap->ty)) { 1316. 		/* can't swap places with pet pinned in a pit by a boulder */ 1317. 		u.ux = u.ux0, u.uy = u.uy0;	/* didn't move after all */ 1318. 	   } else if (u.ux0 != x && u.uy0 != y &&  1319. 		       bad_rock(mtmp->data, x, u.uy0) &&  1320. 		       bad_rock(mtmp->data, u.ux0, y) &&  1321. 		       (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) { 1322. 		/* can't swap places when pet won't fit thru the opening */ 1323. 		u.ux = u.ux0, u.uy = u.uy0;	/* didn't move after all */ 1324. 		You("stop. %s won't fit through.", upstart(y_monnam(mtmp))); 1325. 	   } else { 1326. 		char pnambuf[BUFSZ]; 1327. 1328. 		/* save its current description in case of polymorph */ 1329. 		Strcpy(pnambuf, y_monnam(mtmp)); 1330. 		mtmp->mtrapped = 0; 1331. 		remove_monster(x, y); 1332. 		place_monster(mtmp, u.ux0, u.uy0); 1333. 1334. 		/* check for displacing it into pools and traps */ 1335. 		switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) { 1336. 		case 0: 1337. 		   You("%s %s.", mtmp->mtame ? "displaced" : "frightened",  1338. 			pnambuf); 1339. 		   break; 1340. 		case 1:		/* trapped */ 1341. 		case 3:		/* changed levels */ 1342. 		   /* there's already been a trap message, reinforce it */ 1343. 		   abuse_dog(mtmp); 1344. 		   adjalign(-3); 1345. 		   break; 1346. 		case 2: 1347. 		   /* it may have drowned or died. that's no way to 1348. * treat a pet! your god gets angry. 1349. 		    */  1350. 		    if (rn2(4)) { 1351. 			You_feel("guilty about losing your pet like this."); 1352. 			u.ugangr++; 1353. 			adjalign(-15); 1354. 		   }  1355.  1356. 		    /* you killed your pet by direct action. 1357. 		    * minliquid and mintrap don't know to do this 1358. 		    */  1359. 		    u.uconduct.killer++; 1360. 		   break; 1361. 		default: 1362. 		   pline("that's strange, unknown mintrap result!"); 1363. 		   break; 1364. 		} 1365. 	    }  1366. 	}  1367.  1368. 	reset_occupations; 1369. 	if (flags.run) { 1370. 	   if ( flags.run < 8 ) 1371. 		if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) || 1372. 			IS_FURNITURE(tmpr->typ)) 1373. 		   nomul(0); 1374. 	} 1375.  1376. 	if (hides_under(youmonst.data)) 1377. 	   u.uundetected = OBJ_AT(u.ux, u.uy); 1378. 	else if (youmonst.data->mlet == S_EEL) 1379. 	   u.uundetected = is_pool(u.ux, u.uy) && !Is_waterlevel(&u.uz); 1380. 	else if (u.dx || u.dy) 1381. 	   u.uundetected = 0; 1382. 1383. 	/*  1384. 	 * Mimics (or whatever) become noticeable if they move and are 1385. 	 * imitating something that doesn't move. We could extend this 1386. 	 * to non-moving monsters... 1387. */ 1388. 	if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT 1389. 				|| youmonst.m_ap_type == M_AP_FURNITURE)) 1390. 	   youmonst.m_ap_type = M_AP_NOTHING; 1391. 1392. 	check_leash(u.ux0,u.uy0); 1393. 1394. 	if(u.ux0 != u.ux || u.uy0 != u.uy) { 1395. 	   u.umoved = TRUE; 1396. 	   /* Clean old position -- vision_recalc will print our new one. */ 1397. 	    newsym(u.ux0,u.uy0); 1398. 	   /* Since the hero has moved, adjust what can be seen/unseen. */ 1399. 	    vision_recalc(1);	/* Do the work now in the recover time. */ 1400. 	    invocation_message; 1401. 	} 1402.  1403. 	if (Punished)				/* put back ball and chain */ 1404. 	   move_bc(0,bc_control,ballx,bally,chainx,chainy); 1405. 1406. 	spoteffects(TRUE); 1407. 1408. 	/* delay next move because of ball dragging */ 1409. 	/* must come after we finished picking up, in spoteffects */ 1410. 	if (cause_delay) { 1411. 	   nomul(-2); 1412. 	   nomovemsg = ""; 1413. 	} 1414.  1415. 	if (flags.run && iflags.runmode != RUN_TPORT) { 1416. 	   /* display every step or every 7th step depending upon mode */ 1417. 	   if (iflags.runmode != RUN_LEAP || !(moves % 7L)) { 1418. 		if (flags.time) flags.botl = 1; 1419. 		curs_on_u; 1420. 		delay_output; 1421. 		if (iflags.runmode == RUN_CRAWL) { 1422. 		   delay_output; 1423. 		   delay_output; 1424. 		   delay_output; 1425. 		   delay_output; 1426. 		} 1427. 	    }  1428. 	}  1429. }  1430.  1431. void 1432. invocation_message 1433. { 1434. 	/* a special clue-msg when on the Invocation position */ 1435. 	if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) { 1436. 	   char buf[BUFSZ]; 1437. 	   struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION); 1438. 1439. 	    nomul(0);		/* stop running or travelling */ 1440. #ifdef STEED 1441. 	   if (u.usteed) Sprintf(buf, "beneath %s", y_monnam(u.usteed)); 1442. 	   else 1443. #endif 1444. 	   if (Levitation || Flying) Strcpy(buf, "beneath you"); 1445. 	   else Sprintf(buf, "under your %s", makeplural(body_part(FOOT))); 1446. 1447. 	    You_feel("a strange vibration %s.", buf); 1448. 	   if (otmp && otmp->spe == 7 && otmp->lamplit) 1449. 		pline("%s %s!", The(xname(otmp)), 1450. 		    Blind ? "throbs palpably" : "glows with a strange light"); 1451. 	} 1452. }  1453.  1454. #endif /* OVL3 */ 1455. #ifdef OVL2 1456. 1457. void 1458. spoteffects(pick) 1459. boolean pick; 1460. { 1461. 	register struct monst *mtmp; 1462. 1463. 	if(u.uinwater) { 1464. 		int was_underwater; 1465. 1466. 		if (!is_pool(u.ux,u.uy)) { 1467. 			if (Is_waterlevel(&u.uz)) 1468. 				You("pop into an air bubble."); 1469. 			else if (is_lava(u.ux, u.uy)) 1470. 				You("leave the water...");	/* oops! */ 1471. 			else 1472. 				You("are on solid %s again.", 1473. 				    is_ice(u.ux, u.uy) ? "ice" : "land"); 1474. 		} 1475. 		else if (Is_waterlevel(&u.uz)) 1476. 			goto stillinwater; 1477. 		else if (Levitation) 1478. 			You("pop out of the water like a cork!"); 1479. 		else if (Flying) 1480. 			You("fly out of the water."); 1481. 		else if (Wwalking) 1482. 			You("slowly rise above the surface."); 1483. 		else 1484. 			goto stillinwater; 1485. 		was_underwater = Underwater && !Is_waterlevel(&u.uz); 1486. 		u.uinwater = 0;		/* leave the water */ 1487. 		if (was_underwater) {	/* restore vision */ 1488. 			docrt; 1489. 			vision_full_recalc = 1; 1490. 		} 1491. 	}  1492. stillinwater:; 1493. 	if (!Levitation && !u.ustuck && !Flying) { 1494. 	   /* limit recursive calls through teleds */ 1495. 	   if (is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) { 1496. #ifdef STEED 1497. 		if (u.usteed && !is_flyer(u.usteed->data) && 1498. 			!is_floater(u.usteed->data) &&  1499. 			!is_clinger(u.usteed->data)) { 1500. 		   dismount_steed(Underwater ?  1501. 			    DISMOUNT_FELL : DISMOUNT_GENERIC); 1502. 		   /* dismount_steed -> float_down -> pickup */ 1503. 		   if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) 1504. 			pick = FALSE; 1505. 		} else 1506. #endif 1507. 		if (is_lava(u.ux, u.uy)) { 1508. 		   if (lava_effects) return; 1509. 		} else if (!Wwalking && drown) 1510. 		   return; 1511. 	   }  1512. 	}  1513. 	check_special_room(FALSE); 1514. #ifdef SINKS 1515. 	if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation) 1516. 		dosinkfall; 1517. #endif 1518. 	if (!in_steed_dismounting) { /* if dismounting, we'll check again later */ 1519. 		struct trap *trap = t_at(u.ux, u.uy); 1520. 		boolean pit; 1521. 		pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)); 1522. 		if (trap && pit) 1523. 			dotrap(trap, 0);	/* fall into pit */ 1524. 		if (pick) (void) pickup(1); 1525. 		if (trap && !pit) 1526. 			dotrap(trap, 0);	/* fall into arrow trap, etc. */ 1527. 	} 1528. 	if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) { 1529. 		mtmp->mundetected = mtmp->msleeping = 0; 1530. 		switch(mtmp->data->mlet) { 1531. 		   case S_PIERCER: 1532. 			pline("%s suddenly drops from the %s!", 1533. 			      Amonnam(mtmp), ceiling(u.ux,u.uy)); 1534. 			if(mtmp->mtame) /* jumps to greet you, not attack */ 1535. 			   ;  1536. 			else if(uarmh && is_metallic(uarmh)) 1537. 			   pline("Its blow glances off your helmet."); 1538. 			else if (u.uac + 3 <= rnd(20)) 1539. 			   You("are almost hit by %s!",  1540. 				x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE)); 1541. 			else { 1542. 			   int dmg; 1543. 			   You("are hit by %s!",  1544. 				x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE)); 1545. 			   dmg = d(4,6); 1546. 			   if(Half_physical_damage) dmg = (dmg+1) / 2; 1547. 			   mdamageu(mtmp, dmg); 1548. 			} 1549. 			break; 1550. 		   default:	/* monster surprises you. */ 1551. 			if(mtmp->mtame) 1552. 			   pline("%s jumps near you from the %s.",  1553. 					Amonnam(mtmp), ceiling(u.ux,u.uy)); 1554. 			else if(mtmp->mpeaceful) { 1555. 				You("surprise %s!", 1556. 				    Blind && !sensemon(mtmp) ?  1557. 				    something : a_monnam(mtmp)); 1558. 				mtmp->mpeaceful = 0; 1559. 			} else 1560. 			   pline("%s attacks you by surprise!",  1561. 					Amonnam(mtmp)); 1562. 			break; 1563. 		} 1564. 		mnexto(mtmp); /* have to move the monster */ 1565. 	} 1566. }  1567.  1568. STATIC_OVL boolean 1569. monstinroom(mdat,roomno) 1570. struct permonst *mdat; 1571. int roomno; 1572. { 1573. 	register struct monst *mtmp; 1574. 1575. 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 1576. 		if(!DEADMONSTER(mtmp) && mtmp->data == mdat && 1577. 		   index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET)) 1578. 			return(TRUE); 1579. 	return(FALSE); 1580. } 1581.  1582. char * 1583. in_rooms(x, y, typewanted) 1584. register xchar x, y; 1585. register int typewanted; 1586. { 1587. 	static char buf[5]; 1588. 	char rno, *ptr = &buf[4]; 1589. 	int typefound, min_x, min_y, max_x, max_y_offset, step; 1590. 	register struct rm *lev; 1591. 1592. #define goodtype(rno) (!typewanted || \  1593. 	     ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) || \  1594. 	     ((typewanted == SHOPBASE) && (typefound > SHOPBASE))) \ 1595. 1596. 	switch (rno = levl[x][y].roomno) { 1597. 		case NO_ROOM: 1598. 			return(ptr); 1599. 		case SHARED: 1600. 			step = 2; 1601. 			break; 1602. 		case SHARED_PLUS: 1603. 			step = 1; 1604. 			break; 1605. 		default:			/* i.e. a regular room # */ 1606. 			if (goodtype(rno)) 1607. 				*(--ptr) = rno; 1608. 			return(ptr); 1609. 	} 1610.  1611. 	min_x = x - 1; 1612. 	max_x = x + 1; 1613. 	if (x < 1) 1614. 		min_x += step; 1615. 	else 1616. 	if (x >= COLNO) 1617. 		max_x -= step; 1618. 1619. 	min_y = y - 1; 1620. 	max_y_offset = 2; 1621. 	if (min_y < 0) { 1622. 		min_y += step; 1623. 		max_y_offset -= step; 1624. 	} else 1625. 	if ((min_y + max_y_offset) >= ROWNO) 1626. 		max_y_offset -= step; 1627. 1628. 	for (x = min_x; x <= max_x; x += step) { 1629. 		lev = &levl[x][min_y]; 1630. 		y = 0; 1631. 		if (((rno = lev[y].roomno) >= ROOMOFFSET) && 1632. 		    !index(ptr, rno) && goodtype(rno)) 1633. 			*(--ptr) = rno; 1634. 		y += step; 1635. 		if (y > max_y_offset) 1636. 			continue; 1637. 		if (((rno = lev[y].roomno) >= ROOMOFFSET) && 1638. 		    !index(ptr, rno) && goodtype(rno)) 1639. 			*(--ptr) = rno; 1640. 		y += step; 1641. 		if (y > max_y_offset) 1642. 			continue; 1643. 		if (((rno = lev[y].roomno) >= ROOMOFFSET) && 1644. 		    !index(ptr, rno) && goodtype(rno)) 1645. 			*(--ptr) = rno; 1646. 	} 1647. 	return(ptr); 1648. } 1649.  1650. /* is (x,y) in a town? */ 1651. boolean 1652. in_town(x, y) 1653. register int x, y; 1654. { 1655. 	s_level *slev = Is_special(&u.uz); 1656. 	register struct mkroom *sroom; 1657. 	boolean has_subrooms = FALSE; 1658. 1659. 	if (!slev || !slev->flags.town) return FALSE; 1660. 1661. 	/*  1662. 	 * See if (x,y) is in a room with subrooms, if so, assume it's the 1663. 	 * town. If there are no subrooms, the whole level is in town. 1664. 	 */ 1665. 	for (sroom = &rooms[0]; sroom->hx > 0; sroom++) { 1666. 	   if (sroom->nsubrooms > 0) { 1667. 		has_subrooms = TRUE; 1668. 		if (inside_room(sroom, x, y)) return TRUE; 1669. 	   }  1670. 	}  1671.  1672. 	return !has_subrooms; 1673. } 1674.  1675. STATIC_OVL void 1676. move_update(newlev) 1677. register boolean newlev; 1678. { 1679. 	char *ptr1, *ptr2, *ptr3, *ptr4; 1680. 1681. 	Strcpy(u.urooms0, u.urooms); 1682. 	Strcpy(u.ushops0, u.ushops); 1683. 	if (newlev) { 1684. 		u.urooms[0] = '\0'; 1685. 		u.uentered[0] = '\0'; 1686. 		u.ushops[0] = '\0'; 1687. 		u.ushops_entered[0] = '\0'; 1688. 		Strcpy(u.ushops_left, u.ushops0); 1689. 		return; 1690. 	} 1691. 	Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0)); 1692. 1693. 	for (ptr1 = &u.urooms[0],  1694. 	     ptr2 = &u.uentered[0],  1695. 	     ptr3 = &u.ushops[0],  1696. 	     ptr4 = &u.ushops_entered[0];  1697. 	     *ptr1; ptr1++) { 1698. 		if (!index(u.urooms0, *ptr1)) 1699. 			*(ptr2++) = *ptr1; 1700. 		if (IS_SHOP(*ptr1 - ROOMOFFSET)) { 1701. 			*(ptr3++) = *ptr1; 1702. 			if (!index(u.ushops0, *ptr1)) 1703. 				*(ptr4++) = *ptr1; 1704. 		} 1705. 	}  1706. 	*ptr2 = '\0'; 1707. 	*ptr3 = '\0'; 1708. 	*ptr4 = '\0'; 1709. 1710. 	/* filter u.ushops0 -> u.ushops_left */ 1711. 	for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++) 1712. 		if (!index(u.ushops, *ptr1)) 1713. 			*(ptr2++) = *ptr1; 1714. 	*ptr2 = '\0'; 1715. } 1716.  1717. void 1718. check_special_room(newlev) 1719. register boolean newlev; 1720. { 1721. 	register struct monst *mtmp; 1722. 	char *ptr; 1723. 1724. 	move_update(newlev); 1725. 1726. 	if (*u.ushops0) 1727. 	   u_left_shop(u.ushops_left, newlev); 1728. 1729. 	if (!*u.uentered && !*u.ushops_entered)		/* implied by newlev */ 1730. 	   return;		/* no entrance messages necessary */ 1731. 1732. 	/* Did we just enter a shop? */ 1733. 	if (*u.ushops_entered) 1734. 	   u_entered_shop(u.ushops_entered); 1735. 1736. 	for (ptr = &u.uentered[0]; *ptr; ptr++) { 1737. 	   register int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype; 1738. 1739. 	    /* Did we just enter some other special room? */ 1740. 	    /* vault.c insists that a vault remain a VAULT, 1741. 	    * and temples should remain TEMPLEs, 1742. 	    * but everything else gives a message only the first time */ 1743. 	   switch (rt) { 1744. 		case ZOO: 1745. 		   pline("Welcome to David's treasure zoo!"); 1746. 		   break; 1747. 		case SWAMP: 1748. 		   pline("It %s rather %s down here.",  1749. 			  Blind ? "feels" : "looks",  1750. 			  Blind ? "humid" : "muddy"); 1751. 		   break; 1752. 		case COURT: 1753. 		   You("enter an opulent throne room!"); 1754. 		   break; 1755. 		case LEPREHALL: 1756. 		   You("enter a leprechaun hall!"); 1757. 		   break; 1758. 		case MORGUE: 1759. 		   if(midnight) { 1760. 			const char *run = locomotion(youmonst.data, "Run"); 1761. 			pline("%s away! %s away!", run, run); 1762. 		   } else 1763. 			You("have an uncanny feeling..."); 1764. 		   break; 1765. 		case BEEHIVE: 1766. 		   You("enter a giant beehive!"); 1767. 		   break; 1768. 		case COCKNEST: 1769. 		   You("enter a disgusting nest!"); 1770. 		   break; 1771. 		case ANTHOLE: 1772. 		   You("enter an anthole!"); 1773. 		   break; 1774. 		case BARRACKS: 1775. 		   if(monstinroom(&mons[PM_SOLDIER], roomno) ||  1776. 			monstinroom(&mons[PM_SERGEANT], roomno) ||  1777. 			monstinroom(&mons[PM_LIEUTENANT], roomno) ||  1778. 			monstinroom(&mons[PM_CAPTAIN], roomno)) 1779. 			You("enter a military barracks!"); 1780. 		   else 1781. 			You("enter an abandoned barracks."); 1782. 		   break; 1783. 		case DELPHI: 1784. 		   if(monstinroom(&mons[PM_ORACLE], roomno)) 1785. 			verbalize("%s, %s, welcome to Delphi!", 1786. 					Hello((struct monst *) 0), plname); 1787. 		   break; 1788. 		case TEMPLE: 1789. 		   intemple(roomno + ROOMOFFSET); 1790. 		   /* fall through */ 1791. 		default: 1792. 		   rt = 0; 1793. 	   }  1794.  1795. 	    if (rt != 0) { 1796. 		rooms[roomno].rtype = OROOM; 1797. 		if (!search_special(rt)) { 1798. 			/* No more room of that type */ 1799. 			switch(rt) { 1800. 			   case COURT: 1801. 				level.flags.has_court = 0; 1802. 				break; 1803. 			   case SWAMP: 1804. 				level.flags.has_swamp = 0; 1805. 				break; 1806. 			   case MORGUE: 1807. 				level.flags.has_morgue = 0; 1808. 				break; 1809. 			   case ZOO: 1810. 				level.flags.has_zoo = 0; 1811. 				break; 1812. 			   case BARRACKS: 1813. 				level.flags.has_barracks = 0; 1814. 				break; 1815. 			   case TEMPLE: 1816. 				level.flags.has_temple = 0; 1817. 				break; 1818. 			   case BEEHIVE: 1819. 				level.flags.has_beehive = 0; 1820. 				break; 1821. 			} 1822. 		}  1823. 		if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO) 1824. 		   for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 1825. 			if (!DEADMONSTER(mtmp) && !Stealth && !rn2(3)) mtmp->msleeping = 0; 1826. 	   }  1827. 	}  1828.  1829. 	return; 1830. } 1831.  1832. #endif /* OVL2 */ 1833. #ifdef OVLB 1834. 1835. int 1836. dopickup 1837. { 1838. 	int count; 1839. 	struct trap *traphere = t_at(u.ux, u.uy); 1840. 	/* awful kludge to work around parse's pre-decrement */ 1841. 	count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0; 1842. 	multi = 0;	/* always reset */ 1843. 	/* uswallow case added by GAN 01/29/87 */ 1844. 	if(u.uswallow) { 1845. 	   if (!u.ustuck->minvent) { 1846. 		if (is_animal(u.ustuck->data)) { 1847. 		   You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck))); 1848. 		   pline("But it's kind of slimy, so you drop it."); 1849. 		} else 1850. 		   You("don't %s anything in here to pick up.",  1851. 			  Blind ? "feel" : "see"); 1852. 		return(1); 1853. 	   } else { 1854. 	   	int tmpcount = -count; 1855. 		return loot_mon(u.ustuck, &tmpcount, (boolean *)0); 1856. 	   }  1857. 	}  1858. 	if(is_pool(u.ux, u.uy)) { 1859. 	   if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)  1860. 			|| (Flying && !Breathless)) { 1861. 		You("cannot dive into the water to pick things up."); 1862. 		return(0); 1863. 	   } else if (!Underwater) { 1864. 		You_cant("even see the bottom, let alone pick up %s.", 1865. 				something); 1866. 		return(0); 1867. 	   }  1868. 	}  1869. 	if (is_lava(u.ux, u.uy)) { 1870. 	   if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)  1871. 			|| (Flying && !Breathless)) { 1872. 		You_cant("reach the bottom to pick things up."); 1873. 		return(0); 1874. 	   } else if (!likes_lava(youmonst.data)) { 1875. 		You("would burn to a crisp trying to pick things up."); 1876. 		return(0); 1877. 	   }  1878. 	}  1879. 	if(!OBJ_AT(u.ux, u.uy)) { 1880. 		There("is nothing here to pick up."); 1881. 		return(0); 1882. 	} 1883. 	if (!can_reach_floor) { 1884. #ifdef STEED 1885. 		if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) 1886. 		   You("aren't skilled enough to reach from %s.",  1887. 			y_monnam(u.usteed)); 1888. 		else 1889. #endif 1890. 		You("cannot reach the %s.", surface(u.ux,u.uy)); 1891. 		return(0); 1892. 	} 1893.  1894.  	if (traphere && traphere->tseen) { 1895. 		/* Allow pickup from holes and trap doors that you escaped from 1896. 		 * because that stuff is teetering on the edge just like you, but 1897. 		 * not pits, because there is an elevation discrepancy with stuff 1898. 		 * in pits. 1899. 		 */ 1900. 		if ((traphere->ttyp == PIT || traphere->ttyp == SPIKED_PIT) &&  1901. 		     (!u.utrap || (u.utrap && u.utraptype != TT_PIT))) { 1902. 			You("cannot reach the bottom of the pit."); 1903. 			return(0); 1904. 		} 1905. 	}  1906.  1907. 	return (pickup(-count)); 1908. } 1909.  1910. #endif /* OVLB */ 1911. #ifdef OVL2 1912. 1913. /* stop running if we see something interesting */ 1914. /* turn around a corner if that is the only way we can proceed */ 1915. /* do not turn left or right twice */ 1916. void 1917. lookaround 1918. { 1919.     register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9; 1920.    register int corrct = 0, noturn = 0; 1921.    register struct monst *mtmp; 1922.    register struct trap *trap; 1923. 1924.     /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */ 1925.    /* they polymorphed while in the middle of a long move. */ 1926.     if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) { 1927. 	nomul(0); 1928. 	return; 1929.    }  1930.  1931.     if(Blind || flags.run == 0) return; 1932.    for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) { 1933. 	if(!isok(x,y)) continue; 1934. 1935. 	if(u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy) continue; 1936. 1937. 	if(x == u.ux && y == u.uy) continue; 1938. 1939. 	if((mtmp = m_at(x,y)) &&  1940. 		    mtmp->m_ap_type != M_AP_FURNITURE &&  1941. 		    mtmp->m_ap_type != M_AP_OBJECT &&  1942. 		    (!mtmp->minvis || See_invisible) && !mtmp->mundetected) { 1943. 	   if((flags.run != 1 && !mtmp->mtame)  1944. 					|| (x == u.ux+u.dx && y == u.uy+u.dy)) 1945. 		goto stop; 1946. 	} 1947.  1948. 	if (levl[x][y].typ == STONE) continue; 1949. 	if (x == u.ux-u.dx && y == u.uy-u.dy) continue; 1950. 1951. 	if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) ||  1952. 	    IS_AIR(levl[x][y].typ)) 1953. 	   continue; 1954. 	else if (closed_door(x,y) || 1955. 		 (mtmp && mtmp->m_ap_type == M_AP_FURNITURE && 1956. 		 (mtmp->mappearance == S_hcdoor ||  1957. 		   mtmp->mappearance == S_vcdoor))) { 1958. 	   if(x != u.ux && y != u.uy) continue; 1959. 	   if(flags.run != 1) goto stop; 1960. 	   goto bcorr; 1961. 	} else if (levl[x][y].typ == CORR) { 1962. bcorr: 1963. 	   if(levl[u.ux][u.uy].typ != ROOM) { 1964. 		if(flags.run == 1 || flags.run == 3 || flags.run == 8) { 1965. 		   i = dist2(x,y,u.ux+u.dx,u.uy+u.dy); 1966. 		   if(i > 2) continue; 1967. 		   if(corrct == 1 && dist2(x,y,x0,y0) != 1) 1968. 			noturn = 1; 1969. 		   if(i < i0) { 1970. 			i0 = i; 1971. x0 = x; 1972. y0 = y; 1973. m0 = mtmp ? 1 : 0; 1974. 		    }  1975. 		}  1976. 		corrct++; 1977. 	   }  1978. 	    continue; 1979. 	} else if ((trap = t_at(x,y)) && trap->tseen) { 1980. 	   if(flags.run == 1) goto bcorr;	/* if you must */ 1981. 	   if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop; 1982. 	   continue; 1983. 	} else if (is_pool(x,y) || is_lava(x,y)) { 1984. 	   /* water and lava only stop you if directly in front, and stop 1985. 	    * you even if you are running 1986. 	    */  1987. 	    if(!Levitation && !Flying && !is_clinger(youmonst.data) &&  1988. 				x == u.ux+u.dx && y == u.uy+u.dy) 1989. 			/* No Wwalking check; otherwise they'd be able 1990. 			 * to test boots by trying to SHIFT-direction 1991. 			 * into a pool and seeing if the game allowed it 1992. */ 1993. 			goto stop; 1994. 	   continue; 1995. 	} else {		/* e.g. objects or trap or stairs */ 1996. 	   if(flags.run == 1) goto bcorr; 1997. 	   if(flags.run == 8) continue; 1998. 	   if(mtmp) continue;		/* d */ 1999. 	   if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) ||  2000. 	       ((y == u.uy - u.dy) && (x != u.ux + u.dx))) 2001. 	      continue; 2002. 	} 2003. stop: 2004. 	nomul(0); 2005. 	return; 2006.    } /* end for loops */ 2007. 2008.     if(corrct > 1 && flags.run == 2) goto stop; 2009.    if((flags.run == 1 || flags.run == 3 || flags.run == 8) &&  2010. 	!noturn && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) 2011.    {  2012. 	/* make sure that we do not turn too far */ 2013. 	if(i0 == 2) { 2014. 	   if(u.dx == y0-u.uy && u.dy == u.ux-x0) 2015. 		i = 2;		/* straight turn right */ 2016. 	   else 2017. 		i = -2;		/* straight turn left */ 2018. 	} else if(u.dx && u.dy) { 2019. 	   if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy)) 2020. 		i = -1;		/* half turn left */ 2021. 	   else 2022. 		i = 1;		/* half turn right */ 2023. 	} else { 2024. 	   if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy)) 2025. 		i = 1;		/* half turn right */ 2026. 	   else 2027. 		i = -1;		/* half turn left */ 2028. 	} 2029.  2030. 	i += u.last_str_turn; 2031. 	if(i <= 2 && i >= -2) { 2032. 	   u.last_str_turn = i;  2033. u.dx = x0-u.ux; 2034. 	   u.dy = y0-u.uy; 2035. 	} 2036.     }  2037. }  2038.  2039. /* something like lookaround, but we are not running */ 2040. /* react only to monsters that might hit us */ 2041. int 2042. monster_nearby 2043. { 2044. 	register int x,y; 2045. 	register struct monst *mtmp; 2046. 2047. 	/* Also see the similar check in dochugw in monmove.c */ 2048. 	for(x = u.ux-1; x <= u.ux+1; x++) 2049. 	   for(y = u.uy-1; y <= u.uy+1; y++) { 2050. 		if(!isok(x,y)) continue; 2051. 		if(x == u.ux && y == u.uy) continue; 2052. 		if((mtmp = m_at(x,y)) && 2053. 		   mtmp->m_ap_type != M_AP_FURNITURE &&  2054. 		   mtmp->m_ap_type != M_AP_OBJECT &&  2055. 		   (!mtmp->mpeaceful || Hallucination) &&  2056. 		   (!is_hider(mtmp->data) || !mtmp->mundetected) &&  2057. 		   !noattacks(mtmp->data) &&  2058. 		   mtmp->mcanmove && !mtmp->msleeping &&  /* aplvax!jcn */  2059. 		   !onscary(u.ux, u.uy, mtmp) &&  2060. 		   canspotmon(mtmp)) 2061. 			return(1); 2062. 	} 2063. 	return(0); 2064. } 2065.  2066. void 2067. nomul(nval) 2068. 	register int nval; 2069. { 2070. 	if(multi < nval) return;	/* This is a bug fix by ab@unido */ 2071. 	u.uinvulnerable = FALSE;	/* Kludge to avoid ctrl-C bug -dlc */ 2072. 	u.usleep = 0; 2073. 	multi = nval; 2074. 	flags.travel = iflags.travel1 = flags.mv = flags.run = 0; 2075. } 2076.  2077. /* called when a non-movement, multi-turn action has completed */ 2078. void 2079. unmul(msg_override) 2080. const char *msg_override; 2081. { 2082. 	multi = 0;	/* caller will usually have done this already */ 2083. 	if (msg_override) nomovemsg = msg_override; 2084. 	else if (!nomovemsg) nomovemsg = You_can_move_again; 2085. 	if (*nomovemsg) pline(nomovemsg); 2086. 	nomovemsg = 0; 2087. 	u.usleep = 0; 2088. 	if (afternmv) (*afternmv); 2089. 	afternmv = 0; 2090. } 2091.  2092. #endif /* OVL2 */ 2093. #ifdef OVL1 2094. 2095. STATIC_OVL void 2096. maybe_wail 2097. { 2098.     static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES, 2099. 			     SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES, 2100. 			     TELEPORT_CONTROL, STEALTH, FAST, INVIS }; 2101. 2102.     if (moves <= wailmsg + 50) return; 2103. 2104.     wailmsg = moves; 2105.    if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) { 2106. 	const char *who; 2107. 	int i, powercnt; 2108. 2109. 	who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? 2110. 		urole.name.m : "Elf"; 2111. 	if (u.uhp == 1) { 2112. 	   pline("%s is about to die.", who); 2113. 	} else { 2114. 	   for (i = 0, powercnt = 0; i < SIZE(powers); ++i) 2115. 		if (u.uprops[powers[i]].intrinsic & INTRINSIC) ++powercnt; 2116. 2117. 	    pline(powercnt >= 4 ? "%s, all your powers will be lost..."  2118. 				: "%s, your life force is running out.", who); 2119. 	} 2120.     } else { 2121. 	You_hear(u.uhp == 1 ? "the wailing of the Banshee..." 2122. 			    : "the howling of the CwnAnnwn..."); 2123.    }  2124. }  2125.  2126. void 2127. losehp(n, knam, k_format) 2128. register int n; 2129. register const char *knam; 2130. boolean k_format; 2131. { 2132. 	if (Upolyd) { 2133. 		u.mh -= n; 2134. if (u.mhmax < u.mh) u.mhmax = u.mh; 2135. 		flags.botl = 1; 2136. 		if (u.mh < 1) 2137. 		   rehumanize; 2138. 		else if (n > 0 && u.mh*10 < u.mhmax && Unchanging) 2139. 		   maybe_wail; 2140. 		return; 2141. 	} 2142.  2143. 	u.uhp -= n;  2144. if(u.uhp > u.uhpmax) 2145. 		u.uhpmax = u.uhp;	/* perhaps n was negative */ 2146. 	flags.botl = 1; 2147. 	if(u.uhp < 1) { 2148. 		killer_format = k_format; 2149. 		killer = knam;		/* the thing that killed you */ 2150. 		You("die..."); 2151. 		done(DIED); 2152. 	} else if (n > 0 && u.uhp*10 < u.uhpmax) { 2153. 		maybe_wail; 2154. 	} 2155. }  2156.  2157. int 2158. weight_cap 2159. { 2160. 	register long carrcap; 2161. 2162. 	carrcap = 25*(ACURRSTR + ACURR(A_CON)) + 50; 2163. 	if (Upolyd) { 2164. 		/* consistent with can_carry in mon.c */ 2165. 		if (youmonst.data->mlet == S_NYMPH) 2166. 			carrcap = MAX_CARR_CAP; 2167. 		else if (!youmonst.data->cwt) 2168. 			carrcap = (carrcap * (long)youmonst.data->msize) / MZ_HUMAN; 2169. 		else if (!strongmonst(youmonst.data) 2170. 			|| (strongmonst(youmonst.data) && (youmonst.data->cwt > WT_HUMAN))) 2171. 			carrcap = (carrcap * (long)youmonst.data->cwt / WT_HUMAN); 2172. 	} 2173.  2174. 	if (Levitation || Is_airlevel(&u.uz)    /* pugh@cornell */  2175. #ifdef STEED  2176. 			|| (u.usteed && strongmonst(u.usteed->data))  2177. #endif  2178. 	) 2179. 		carrcap = MAX_CARR_CAP; 2180. 	else { 2181. 		if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP; 2182. 		if (!Flying) { 2183. 			if(EWounded_legs & LEFT_SIDE) carrcap -= 100; 2184. 			if(EWounded_legs & RIGHT_SIDE) carrcap -= 100; 2185. 		} 2186. 		if (carrcap < 0) carrcap = 0; 2187. 	} 2188. 	return((int) carrcap); 2189. } 2190.  2191. static int wc;	/* current weight_cap; valid after call to inv_weight */ 2192. 2193. /* returns how far beyond the normal capacity the player is currently. */ 2194. /* inv_weight is negative if the player is below normal capacity. */ 2195. int 2196. inv_weight 2197. { 2198. 	register struct obj *otmp = invent; 2199. 	register int wt = 0; 2200. 2201. #ifndef GOLDOBJ 2202. 	/* when putting stuff into containers, gold is inserted at the head 2203. 	  of invent for easier manipulation by askchain & co, but it's also 2204. 	  retained in u.ugold in order to keep the status line accurate; we  2205. mustn't add its weight in twice under that circumstance */ 2206. 	wt = (otmp && otmp->oclass == COIN_CLASS) ? 0 : 2207. 		(int)((u.ugold + 50L) / 100L); 2208. #endif 2209. 	while (otmp) { 2210. #ifndef GOLDOBJ 2211. 		if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data)) 2212. #else 2213. 		if (otmp->oclass == COIN_CLASS) 2214. 			wt += (int)(((long)otmp->quan + 50L) / 100L); 2215. 		else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data)) 2216. #endif 2217. 			wt += otmp->owt; 2218. 		otmp = otmp->nobj; 2219. 	} 2220. 	wc = weight_cap; 2221. 	return (wt - wc); 2222. } 2223.  2224. /*  2225.  * Returns 0 if below normal capacity, or the number of "capacity units" 2226. * over the normal capacity the player is loaded. Max is 5. 2227. */  2228. int 2229. calc_capacity(xtra_wt) 2230. int xtra_wt; 2231. { 2232.     int cap, wt = inv_weight + xtra_wt; 2233. 2234.     if (wt <= 0) return UNENCUMBERED; 2235.    if (wc <= 1) return OVERLOADED; 2236.    cap = (wt*2 / wc) + 1; 2237.    return min(cap, OVERLOADED); 2238. } 2239.  2240. int 2241. near_capacity 2242. { 2243.     return calc_capacity(0); 2244. } 2245.  2246. int 2247. max_capacity 2248. { 2249.     int wt = inv_weight; 2250. 2251.     return (wt - (2 * wc)); 2252. } 2253.  2254. boolean 2255. check_capacity(str) 2256. const char *str; 2257. { 2258.     if(near_capacity >= EXT_ENCUMBER) { 2259. 	if(str) 2260. 	   pline(str); 2261. 	else 2262. 	   You_cant("do that while carrying so much stuff."); 2263. 	return 1; 2264.    }  2265.     return 0; 2266. } 2267.  2268. #endif /* OVL1 */ 2269. #ifdef OVLB 2270. 2271. int 2272. inv_cnt 2273. { 2274. 	register struct obj *otmp = invent; 2275. 	register int ct = 0; 2276. 2277. 	while(otmp){ 2278. 		ct++; 2279. 		otmp = otmp->nobj; 2280. 	} 2281. 	return(ct); 2282. } 2283.  2284. #ifdef GOLDOBJ 2285. /* Counts the money in an object chain. */ 2286. /* Intended use is for your or some monsters inventory, */ 2287. /* now that u.gold/m.gold is gone.*/ 2288. /* Counting money in a container might be possible too. */ 2289. long 2290. money_cnt(otmp) 2291. struct obj *otmp; 2292. { 2293.         while(otmp) { 2294. 	       /* Must change when silver & copper is implemented: */ 2295. 	        if (otmp->oclass == COIN_CLASS) return otmp->quan; 2296.  	        otmp = otmp->nobj; 2297. 	} 2298. 	return 0; 2299. } 2300. #endif 2301. #endif /* OVLB */ 2302. 2303. /*hack.c*/