Source:NetHack 3.3.0/hack.c

Below is the full text to hack.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/hack.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)hack.c	3.3	1999/08/16	*/ 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.   STATIC_DCL int NDECL(moverock); 8.   STATIC_DCL int FDECL(still_chewing,(XCHAR_P,XCHAR_P)); 9.   #ifdef SINKS 10.  STATIC_DCL void NDECL(dosinkfall); 11.  #endif 12.  STATIC_DCL boolean FDECL(monstinroom, (struct permonst *,int)); 13.   14.   STATIC_DCL void FDECL(move_update, (BOOLEAN_P)); 15.   16.   #define IS_SHOP(x)	(rooms[x].rtype >= SHOPBASE) 17.   18.   #ifdef OVL2 19.   20.   boolean 21.  revive_nasty(x, y, msg) 22.  int x,y; 23.  const char *msg; 24.  {  25.       register struct obj *otmp, *otmp2; 26.      struct monst *mtmp; 27.      coord cc; 28.      boolean revived = FALSE; 29.   30.       for(otmp = level.objects[x][y]; otmp; otmp = otmp2) { 31.  	otmp2 = otmp->nexthere; 32.  	if (otmp->otyp == CORPSE &&  33.   	    (is_rider(&mons[otmp->corpsenm]) || 34.  	     otmp->corpsenm == PM_WIZARD_OF_YENDOR)) { 35.  	    /* move any living monster already at that location */ 36.  	    if((mtmp = m_at(x,y)) && enexto(&cc, x, y, mtmp->data)) 37.  		rloc_to(mtmp, cc.x, cc.y); 38.  	    if(msg) Norep("%s", msg); 39.  	    revived = revive_corpse(otmp); 40.  	}  41.       }  42.    43.       /* this location might not be safe, if not, move revived monster */ 44.      if (revived) { 45.  	mtmp = m_at(x,y); 46.  	if (mtmp && !goodpos(x, y, mtmp) &&  47.   	    enexto(&cc, x, y, mtmp->data)) { 48.  	    rloc_to(mtmp, cc.x, cc.y); 49.  	}  50.   	/* else impossible? */ 51.       }  52.    53.       return (revived); 54.  }  55.    56.   STATIC_OVL int 57.  moverock 58.  {  59.       register xchar rx, ry, sx, sy; 60.      register struct obj *otmp; 61.      register struct trap *ttmp; 62.      register struct monst *mtmp; 63.   64.       sx = u.ux + u.dx,  sy = u.uy + u.dy;	/* boulder starting position */ 65.      while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) { 66.  	/* make sure that this boulder is visible as the top object */ 67.  	if (otmp != level.objects[sx][sy]) movobj(otmp, sx, sy); 68.   69.   	rx = u.ux + 2 * u.dx;	/* boulder destination position */ 70.  	ry = u.uy + 2 * u.dy; 71.  	nomul(0); 72.  	if (Levitation || Is_airlevel(&u.uz)) { 73.  	    if (Blind) feel_location(sx, sy); 74.  	    You("don't have enough leverage to push %s.", the(xname(otmp))); 75.  	    /* Give them a chance to climb over it? */ 76.   	    return -1; 77.  	}  78.   	if (verysmall(youmonst.data)  79.   #ifdef STEED  80.   		 && !u.usteed  81.   #endif  82.   				    ) { 83.  	    if (Blind) feel_location(sx, sy); 84.  	    pline("You're too small to push that %s.", xname(otmp)); 85.  	    goto cannot_push; 86.  	}  87.   	if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&  88.   	    (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) || (  89.   #ifdef REINCARNATION  90.   		!Is_rogue_level(&u.uz) &&  91.   #endif  92.   		(levl[rx][ry].doormask & ~D_BROKEN) == D_NODOOR)) &&  93.   	    !sobj_at(BOULDER, rx, ry)) { 94.  	    ttmp = t_at(rx, ry); 95.  	    mtmp = m_at(rx, ry); 96.   97.   		/* KMH -- Sokoban doesn't let you push boulders diagonally */ 98.  	    if (In_sokoban(&u.uz) && u.dx && u.dy) { 99.  	    	if (Blind) feel_location(sx,sy); 100. 	    	pline("%s won't roll diagonally on this %s.",  101.  	        		The(xname(otmp)), surface(sx, sy)); 102. 	    	goto cannot_push; 103. 	    }  104.   105.  	    if (revive_nasty(rx, ry, "You sense movement on the other side.")) 106. 		return (-1); 107.  108.  	    if (mtmp && !noncorporeal(mtmp->data) &&  109.  		    (!mtmp->mtrapped || 110. 			 !(ttmp && ((ttmp->ttyp == PIT) || 111. 				    (ttmp->ttyp == SPIKED_PIT))))) { 112. 		if (canspotmon(mtmp)) 113. 		    pline("There's %s on the other side.", mon_nam(mtmp)); 114. 		else { 115. 		    if (Blind) feel_location(sx, sy); 116. 		    You_hear("a monster behind %s.", the(xname(otmp))); 117. 		    map_invisible(rx, ry); 118. 		}  119.  		if (flags.verbose) 120. 		    pline("Perhaps that's why %s cannot move it.",  121.  #ifdef STEED  122.  				u.usteed ? mon_nam(u.usteed) :  123.  #endif  124.  				"you"); 125. 		goto cannot_push; 126. 	    }  127.   128.  	    if (ttmp) 129. 		switch(ttmp->ttyp) { 130. 		case LANDMINE: 131. 		    if (rn2(10)) { 132. 			pline("KAABLAMM!!!  %s triggers %s land mine.",  133.  				The(xname(otmp)),  134.  				ttmp->madeby_u ? "your" : "a"); 135. 			obj_extract_self(otmp); 136. 			place_object(otmp, rx, ry); 137. 			deltrap(ttmp); 138. 			del_engr_at(rx,ry); 139. 			scatter(rx,ry, 4,  140.  				MAY_DESTROY|MAY_HIT|MAY_FRACTURE|VIS_EFFECTS,  141.  				(struct obj *)0); 142. 			if (cansee(rx,ry)) newsym(rx,ry); 143. 			continue; 144. 		    }  145.  		    break; 146. 		case SPIKED_PIT: 147. 		case PIT: 148. 		    obj_extract_self(otmp); 149. 		    /* vision kludge to get messages right; 150. 		       the pit will temporarily be seen even 151. 		       if this is one among multiple boulders */ 152. 		    if (!Blind) viz_array[ry][rx] |= IN_SIGHT; 153. 		    if (!flooreffects(otmp, rx, ry, "fall")) { 154. 			place_object(otmp, rx, ry); 155. 		    }  156.  		    if (mtmp && !Blind) newsym(rx, ry); 157. 		    continue; 158. 		case HOLE: 159. 		case TRAPDOOR: 160. 		    pline("%s %s and plugs a %s in the %s!",  161.  			  The(xname(otmp)),  162.  			  (ttmp->ttyp == TRAPDOOR) ? "triggers" : "falls into",  163.  			  (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",  164.  			  surface(rx, ry)); 165. 		    deltrap(ttmp); 166. 		    delobj(otmp); 167. 		    bury_objs(rx, ry); 168. 		    if (cansee(rx,ry)) newsym(rx,ry); 169. 		    continue; 170. 		case LEVEL_TELEP: 171. 		case TELEP_TRAP: 172. #ifdef STEED 173. 		    if (u.usteed) 174. 			pline("%s pushes %s and suddenly it disappears!",  175.  				Monnam(u.usteed), the(xname(otmp))); 176. 		    else 177. #endif 178. 		    You("push %s and suddenly it disappears!",  179.  			the(xname(otmp))); 180. 		    if (ttmp->ttyp == TELEP_TRAP) 181. 			rloco(otmp); 182. 		    else { 183. 			int newlev = random_teleport_level; 184. 			d_level dest; 185.  186.  			if (newlev == depth(&u.uz) || In_endgame(&u.uz)) 187. 			    continue; 188. 			obj_extract_self(otmp); 189. 			add_to_migration(otmp); 190. 			get_level(&dest, newlev); 191. 			otmp->ox = dest.dnum; 192. 			otmp->oy = dest.dlevel; 193. 			otmp->owornmask = (long)MIGR_RANDOM; 194. 		    }  195.  		    seetrap(ttmp); 196. 		    continue; 197. 		}  198.  	    if (closed_door(rx, ry)) 199. 		goto nopushmsg; 200. 	    if (boulder_hits_pool(otmp, rx, ry, TRUE)) 201. 		continue; 202. 	    /*  203.  	     * Re-link at top of fobj chain so that pile order is preserved 204. 	     * when level is restored. 205. 	     */  206.  	    if (otmp != fobj) { 207. 		remove_object(otmp); 208. 		place_object(otmp, otmp->ox, otmp->oy); 209. 	    }  210.   211.  	    {  212.  #ifdef LINT /* static long lastmovetime; */ 213. 		long lastmovetime; 214. 		lastmovetime = 0; 215. #else 216. 		static NEARDATA long lastmovetime; 217. #endif 218. 		/* note: this var contains garbage initially and 219. 		   after a restore */ 220. #ifdef STEED 221. 		if (!u.usteed) { 222. #endif 223. 		  if (moves > lastmovetime+2 || moves < lastmovetime) 224. 		    pline("With %s effort you move %s.",  225.  			  throws_rocks(youmonst.data) ? "little" : "great",  226.  			  the(xname(otmp))); 227. 		  exercise(A_STR, TRUE); 228. #ifdef STEED 229. 		} else 230. 		    pline("%s moves %s.", Monnam(u.usteed), the(xname(otmp))); 231. #endif 232. 		lastmovetime = moves; 233. 	    }  234.   235.  	    /* Move the boulder *after* the message. */ 236.  	    if (glyph_is_invisible(levl[rx][ry].glyph)) 237. 		unmap_object(rx, ry); 238. 	    movobj(otmp, rx, ry);	/* does newsym(rx,ry) */ 239. 	    if (Blind) { 240. 		feel_location(rx,ry); 241. 		feel_location(sx, sy); 242. 	    } else { 243. 		newsym(sx, sy); 244. 	    }  245.  	} else { 246. 	nopushmsg: 247. #ifdef STEED 248. 	  if (u.usteed) 249. 	    pline("%s tries to move %s, but cannot.",  250.  		  	Monnam(u.usteed), the(xname(otmp))); 251. 	  else 252. #endif 253. 	    You("try to move %s, but in vain.", the(xname(otmp))); 254. 	    if (Blind) feel_location(sx, sy); 255. 	cannot_push: 256. 	    if (throws_rocks(youmonst.data)) { 257. #ifdef STEED 258. 		if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) 259. 			You("aren't skilled enough to %s %s from %s.",  260.  				flags.pickup ? "pick up" : "push aside",  261.  				the(xname(otmp)), mon_nam(u.usteed)); 262. 		else 263. #endif 264. 		  pline("However, you can easily %s.",  265.  			flags.pickup ? "pick it up" : "push it aside"); 266. 		break; 267. 	    }  268.   269.  	    if (  270.  #ifdef STEED  271.  		!u.usteed &&  272.  #endif	     273.  		(((!invent || inv_weight <= -850) &&  274.  		 (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][sy].typ)  275.  				     && IS_ROCK(levl[sx][u.uy].typ)))) 276. 		|| verysmall(youmonst.data))) { 277. 		pline("However, you can squeeze yourself into a small opening."); 278. 		break; 279. 	    } else 280. 		return (-1); 281. 	}  282.      }  283.      return (0); 284. }  285.   286.  /*  287.   *  still_chewing 288.  *  289.   *  Chew on a wall, door, or boulder. Returns TRUE if still eating, FALSE 290.  *  when done. 291.  */  292.  STATIC_OVL int 293. still_chewing(x,y) 294.     xchar x, y;  295. { 296.      struct rm *lev = &levl[x][y]; 297.     struct obj *boulder = sobj_at(BOULDER,x,y); 298.     const char *digtxt = (char *)0, *dmgtxt = (char *)0; 299.  300.      if (digging.down)		/* not continuing previous dig (w/ pick-axe) */ 301. 	(void) memset((genericptr_t)&digging, 0, sizeof digging); 302.  303.      if (!boulder && IS_ROCK(lev->typ) && !may_dig(x,y)) { 304. 	You("hurt your teeth on the hard stone."); 305. 	nomul(0); 306. 	return 1; 307.     } else if (digging.pos.x != x || digging.pos.y != y ||  308.  		!on_level(&digging.level, &u.uz)) { 309. 	digging.down = FALSE; 310. 	digging.chew = TRUE; 311. 	digging.pos.x = x;  312. digging.pos.y = y; 313. assign_level(&digging.level, &u.uz); 314. 	/* solid rock takes more work & time to dig through */ 315. 	digging.effort = (IS_ROCK(lev->typ) ? 30 : 60) + u.udaminc; 316. 	You("start chewing %s %s.",  317.  	    boulder ? "on a" : "a hole in the",  318.  	    boulder ? "boulder" : IS_ROCK(lev->typ) ? "rock" : "door"); 319. 	return 1; 320.     } else if ((digging.effort += (30 + u.udaminc)) <= 100)  { 321. 	if (flags.verbose) 322. 	    You("%s chewing on the %s.",  323.  		digging.chew ? "continue" : "begin",  324.  		boulder ? "boulder" : IS_ROCK(lev->typ) ? "rock" : "door"); 325. 	digging.chew = TRUE; 326. 	return 1; 327.     }  328.   329.      if (boulder) { 330. 	delobj(boulder);		/* boulder goes bye-bye */ 331. 	You("eat the boulder.");	/* yum */ 332.  333.  	/*  334.  	 *  The location could still block because of  335. *	1. More than one boulder 336. 	 *	2. Boulder stuck in a wall/stone/door. 337. 	 *  338.  	 *  [perhaps use does_block below (from vision.c)] 339. 	 */  340.  	if (IS_ROCK(lev->typ) || closed_door(x,y) || sobj_at(BOULDER,x,y)) { 341. 	    block_point(x,y);	/* delobj will unblock the point */ 342. 	    /* reset dig state */ 343. 	    (void) memset((genericptr_t)&digging, 0, sizeof digging); 344. 	    return 1; 345. 	}  346.   347.      } else if (IS_WALL(lev->typ)) { 348. 	if (*in_rooms(x, y, SHOPBASE)) { 349. 	    add_damage(x, y, 10L * ACURRSTR); 350. 	    dmgtxt = "damage"; 351. 	}  352.  	digtxt = "chew a hole in the wall."; 353. 	if (level.flags.is_maze_lev) { 354. 	    lev->typ = ROOM; 355. 	} else if (level.flags.is_cavernous_lev) { 356. 	    lev->typ = CORR; 357. 	} else { 358. 	    lev->typ = DOOR; 359. 	    lev->doormask = D_NODOOR; 360. 	}  361.      } else if (lev->typ == SDOOR) { 362. 	if (lev->doormask & D_TRAPPED) { 363. 	    lev->doormask = D_NODOOR; 364. 	    b_trapped("secret door", 0); 365. 	} else { 366. 	    digtxt = "chew through the secret door."; 367. 	    lev->doormask = D_BROKEN; 368. 	}  369.  	lev->typ = DOOR; 370.  371.      } else if (IS_DOOR(lev->typ)) { 372. 	if (*in_rooms(x, y, SHOPBASE)) { 373. 	    add_damage(x, y, 400L); 374. 	    dmgtxt = "break"; 375. 	}  376.  	if (lev->doormask & D_TRAPPED) { 377. 	    lev->doormask = D_NODOOR; 378. 	    b_trapped("door", 0); 379. 	} else { 380. 	    digtxt = "chew through the door."; 381. 	    lev->doormask = D_BROKEN; 382. 	}  383.   384.      } else { /* STONE or SCORR */ 385. 	digtxt = "chew a passage through the rock."; 386. 	lev->typ = CORR; 387.     }  388.   389.      unblock_point(x, y);	/* vision */ 390.     newsym(x, y); 391.     if (digtxt) You(digtxt);	/* after newsym */ 392.     if (dmgtxt) pay_for_damage(dmgtxt); 393.     (void) memset((genericptr_t)&digging, 0, sizeof digging); 394.     return 0; 395. }  396.   397.  #endif /* OVL2 */ 398. #ifdef OVLB 399.  400.  void 401. movobj(obj, ox, oy) 402. register struct obj *obj; 403. register xchar ox, oy; 404. {  405.  	/* optimize by leaving on the fobj chain? */ 406.  	remove_object(obj); 407. 	newsym(obj->ox, obj->oy); 408. 	place_object(obj, ox, oy); 409. 	newsym(ox, oy); 410. }  411.   412.  #ifdef SINKS 413. static NEARDATA const char fell_on_sink[] = "fell onto a sink"; 414.  415.  STATIC_OVL void 416. dosinkfall 417. {  418.  	register struct obj *obj; 419.  420.  	if (is_floater(youmonst.data) || (HLevitation & FROMOUTSIDE)) { 421. 		You("wobble unsteadily for a moment."); 422. 	} else { 423. 		You("crash to the floor!"); 424. 		losehp((rn1(10, 20 - (int)ACURR(A_CON))),  425.  			fell_on_sink, NO_KILLER_PREFIX); 426. 		exercise(A_DEX, FALSE); 427. 		for(obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) 428. 		    if(obj->oclass == WEAPON_CLASS) { 429. 			You("fell on %s.",doname(obj)); 430. 			losehp(rnd(3), fell_on_sink, NO_KILLER_PREFIX); 431. 			exercise(A_CON, FALSE); 432. 		    }  433.  	}  434.   435.  	ELevitation &= ~W_ARTI; 436. 	HLevitation &= ~(I_SPECIAL|TIMEOUT); 437. 	HLevitation++; 438. 	if(uleft && uleft->otyp == RIN_LEVITATION) { 439. 	    obj = uleft; 440. 	    Ring_off(obj); 441. 	    off_msg(obj); 442. 	}  443.  	if(uright && uright->otyp == RIN_LEVITATION) { 444. 	    obj = uright; 445. 	    Ring_off(obj); 446. 	    off_msg(obj); 447. 	}  448.  	if(uarmf && uarmf->otyp == LEVITATION_BOOTS) { 449. 	    obj = uarmf; 450. 	    (void)Boots_off; 451. 	    off_msg(obj); 452. 	}  453.  	HLevitation--; 454. }  455.  #endif 456.  457.  boolean 458. may_dig(x,y) 459. register xchar x,y; 460. /* intended to be called only on ROCKs */ 461. {  462.      return (boolean)(!(IS_STWALL(levl[x][y].typ) && 463. 			(levl[x][y].wall_info & W_NONDIGGABLE))); 464. }  465.   466.  boolean 467. may_passwall(x,y) 468. register xchar x,y; 469. {  470.     return (boolean)(!(IS_STWALL(levl[x][y].typ) && 471. 			(levl[x][y].wall_info & W_NONPASSWALL))); 472. }  473.   474.  #endif /* OVLB */ 475. #ifdef OVL1 476.  477.  boolean 478. bad_rock(mdat,x,y) 479. struct permonst *mdat; 480. register xchar x,y; 481. {  482.  	return((boolean) ((In_sokoban(&u.uz) && sobj_at(BOULDER,x,y)) || 483. 	       (IS_ROCK(levl[x][y].typ)  484.  		    && (!tunnels(mdat) || needspick(mdat) || !may_dig(x,y))  485.  		    && !(passes_walls(mdat) && may_passwall(x,y))))); 486. }  487.   488.  boolean 489. invocation_pos(x, y)  490. xchar x, y; 491. { 492.  	return((boolean)(Invocation_lev(&u.uz) && x == inv_pos.x && y == inv_pos.y)); 493. }  494.   495.  #endif /* OVL1 */ 496. #ifdef OVL3 497.  498.  void 499. domove 500. {  501.  	register struct monst *mtmp; 502. 	register struct rm *tmpr,*ust; 503. 	register xchar x,y; 504. 	struct trap *trap; 505. 	int wtcap; 506. 	boolean on_ice; 507. 	xchar chainx, chainy, ballx, bally;	/* ball&chain new positions */ 508. 	int bc_control;				/* control for ball&chain */ 509. 	boolean cause_delay = FALSE;	/* dragging ball will skip a move */ 510.  511.  	u_wipe_engr(rnd(5)); 512.  513.  	if(((wtcap = near_capacity) >= OVERLOADED 514. 	    || (wtcap > SLT_ENCUMBER &&  515.  		(Upolyd ? (u.mh < 5 && u.mh != u.mhmax) 516. 			: (u.uhp < 10 && u.uhp != u.uhpmax))))  517.  	   && !Is_airlevel(&u.uz)) { 518. 	    if(wtcap < OVERLOADED) { 519. 		You("don't have enough stamina to move."); 520. 		exercise(A_CON, FALSE); 521. 	    } else 522. 		You("collapse under your load."); 523. 	    nomul(0); 524. 	    return; 525. 	}  526.  	if(u.uswallow) { 527. 		u.dx = u.dy = 0; 528. 		u.ux = x = u.ustuck->mx; 529. 		u.uy = y = u.ustuck->my; 530. 		mtmp = u.ustuck; 531. 	} else { 532. 		if (Is_airlevel(&u.uz) && rn2(4) &&  533.  			!Levitation && !Flying) { 534. 		    switch(rn2(3)) { 535. 		    case 0: 536. 			You("tumble in place."); 537. 			exercise(A_DEX, FALSE); 538. 			break; 539. 		    case 1: 540. 			You_cant("control your movements very well."); break; 541. 		    case 2: 542. 			pline("It's hard to walk in thin air."); 543. 			exercise(A_DEX, TRUE); 544. 			break; 545. 		    }  546.  		    return; 547. 		}  548.   549.  		/* check slippery ice */ 550. 		on_ice = !Levitation && is_ice(u.ux, u.uy); 551. 		if (on_ice) { 552. 		    static int skates = 0; 553. 		    if (!skates) skates = find_skates; 554. 		    if ((uarmf && uarmf->otyp == skates)  555.  			    || resists_cold(&youmonst) || Flying  556.  			    || is_floater(youmonst.data) || is_clinger(youmonst.data)  557.  			    || is_whirly(youmonst.data)) 558. 			on_ice = FALSE; 559. 		    else if (!rn2(Cold_resistance ? 3 : 2)) { 560.  			HFumbling |= FROMOUTSIDE; 561. 			HFumbling &= ~TIMEOUT; 562. 			HFumbling += 1;  /* slip on next move */ 563. 		    }  564.  		}  565.  		if (!on_ice && (HFumbling & FROMOUTSIDE)) 566. 		    HFumbling &= ~FROMOUTSIDE; 567.  568.  		x = u.ux + u.dx; 569. 		y = u.uy + u.dy; 570. 		if(Stunned || (Confusion && !rn2(5))) { 571. 			register int tries = 0; 572.  573.  			do { 574. 				if(tries++ > 50) { 575. 					nomul(0); 576. 					return; 577. 				}  578.  				confdir; 579. 				x = u.ux + u.dx; 580. 				y = u.uy + u.dy; 581. 			} while(!isok(x, y) || bad_rock(youmonst.data, x, y)); 582. 		}  583.  		/* turbulence might alter your actual destination */ 584. 		if (u.uinwater) { 585. 			water_friction; 586. 			if (!u.dx && !u.dy) { 587. 				nomul(0); 588. 				return; 589. 			}  590.  			x = u.ux + u.dx; 591. 			y = u.uy + u.dy; 592. 		}  593.  		if(!isok(x, y)) { 594. 			nomul(0); 595. 			return; 596. 		}  597.  		if((trap = t_at(x, y)) && trap->tseen) { 598. 			if(flags.run >= 2) { 599. 				nomul(0); 600. 				flags.move = 0; 601. 				return; 602. 			} else 603. 				nomul(0); 604. 		}  605.   606.  		if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) { 607. 		    if (distu(u.ustuck->mx, u.ustuck->my) > 2) { 608. 			/* perhaps it fled (or was teleported or ... ) */ 609. 			u.ustuck = 0; 610. 		    } else if (sticks(youmonst.data)) { 611. 			/* When polymorphed into a sticking monster, 612. 			 * u.ustuck means it's stuck to you, not you to it. 613. 			 */  614.  			You("release %s.", mon_nam(u.ustuck)); 615. 			u.ustuck = 0; 616. 		    } else { 617. 			/* If holder is asleep or paralyzed: 618. 			 *	37.5% chance of getting away, 619. 			 *	12.5% chance of waking/releasing it; 620. 			 * otherwise: 621. 			 *	 7.5% chance of getting away. 622. 			 * [strength ought to be a factor] 623. 			 */  624.  			switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) { 625.  			case 0: case 1: case 2: 626. 			    You("pull free from %s.", mon_nam(u.ustuck)); 627. 			    u.ustuck = 0; 628. 			    break; 629. 			case 3: 630. 			    if (!u.ustuck->mcanmove) { 631. 				/* it's free to move on next turn */ 632. 				u.ustuck->mfrozen = 1; 633. 				u.ustuck->msleeping = 0; 634. 			    }  635.  			    /*FALLTHRU*/ 636. 			default: 637. 			    You("cannot escape from %s!", mon_nam(u.ustuck)); 638. 			    nomul(0); 639. 			    return; 640. 			}  641.  		    }  642.  		}  643.   644.  		mtmp = m_at(x,y); 645. 		if (mtmp) { 646. 			/* Don't attack if you're running, and can see it */ 647. 			/* We should never get here if forcefight */ 648. 			if (flags.run &&  649.  			    ((!Blind && mon_visible(mtmp) &&  650.  			      ((mtmp->m_ap_type != M_AP_FURNITURE &&  651.  				mtmp->m_ap_type != M_AP_OBJECT) || 652. 			       Protection_from_shape_changers)) || 653. 			     sensemon(mtmp))) { 654. 				nomul(0); 655. 				flags.move = 0; 656. 				return; 657. 			}  658.  		}  659.  	}  660.   661.  	u.ux0 = u.ux; 662. 	u.uy0 = u.uy; 663. 	bhitpos.x = x;  664. bhitpos.y = y; 665. tmpr = &levl[x][y]; 666.  667.  	/* attack monster */ 668. 	if(mtmp) { 669. 	    nomul(0); 670. 	    /* only attack if we know it's there */ 671. 	    /* or if we used the 'F' command to fight blindly */ 672. 	    /* or if it hides_under, in which case we call attack to print 673. 	     * the Wait! message. 674. 	     * This is different from ceiling hiders, who aren't handled in  675. * attack. 676. 	     */  677.   678.  	    /* If they used a 'm' command, trying to move onto a monster 679. 	     * prints the below message and wastes a turn. The exception is 680. * if the monster is unseen and the player doesn't remember an 681. * invisible monster--then, we fall through to attack and 682. 	     * attack_check, which still wastes a turn, but prints a  683. * different message and makes the player remember the monster. */ 684.  	    if(flags.nopick &&  685.  		  (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))){ 686. 		if(mtmp->m_ap_type && !Protection_from_shape_changers  687.  						    && !sensemon(mtmp)) 688. 		    stumble_onto_mimic(mtmp); 689. 		else 690. 		    You("move right into %s.", mon_nam(mtmp)); 691. 		return; 692. 	    }  693.  	    if(flags.forcefight || !mtmp->mundetected || sensemon(mtmp) ||  694.  		    ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL) && 695. 			!is_safepet(mtmp))){ 696. 		gethungry; 697. 		if(wtcap >= HVY_ENCUMBER && moves%3) { 698. 		    if (Upolyd && u.mh > 1) { 699. 			u.mh--; 700. 		    } else if (!Upolyd && u.uhp > 1) { 701. 			u.uhp--; 702. 		    } else { 703. 			You("pass out from exertion!"); 704. 			exercise(A_CON, FALSE); 705. 			fall_asleep(-10, FALSE); 706. 		    }  707.  		}  708.  		if(multi < 0) return;	/* we just fainted */ 709.  710.  		/* try to attack; note that it might evade */ 711. 		/* also, we don't attack tame when _safepet_ */ 712. 		if(attack(mtmp)) return; 713. 	    }  714.  	}  715.   716.  	/* specifying 'F' with no monster wastes a turn */ 717. 	if (flags.forcefight ||  718.  	    /* remembered an 'I' && didn't use a move command */  719.  	    (glyph_is_invisible(levl[x][y].glyph) && !flags.nopick)) { 720. 		You("attack %s.", Underwater ? "empty water" : "thin air"); 721. 		unmap_object(x, y); /* known empty -- remove 'I' if present */ 722. 		newsym(x, y); 723. 		nomul(0); 724. 		return; 725. 	}  726.  	if (glyph_is_invisible(levl[x][y].glyph)) { 727. 	    unmap_object(x, y); 728. 	    newsym(x, y); 729. 	}  730.   731.  	/* not attacking an animal, so we try to move */ 732. #ifdef STEED 733. 	if (u.usteed && !u.usteed->mcanmove && (u.dx || u.dy)) { 734. 		pline("%s won't move!", Monnam(u.usteed)); 735. 		nomul(0); 736. 		return; 737. 	} else 738. #endif 739. 	if(!youmonst.data->mmove) { 740. 		You("are rooted %s.",  741.  		    Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?  742.  		    "in place" : "to the ground"); 743. 		nomul(0); 744. 		return; 745. 	}  746.  	if(u.utrap) { 747. 		if(u.utraptype == TT_PIT) { 748. 		    if (!rn2(2) && sobj_at(BOULDER, u.ux, u.uy)) { 749. 			Your("%s gets stuck in a crevice.", body_part(LEG)); 750. 			display_nhwindow(WIN_MESSAGE, FALSE); 751. 			clear_nhwindow(WIN_MESSAGE); 752. 			You("free your %s.", body_part(LEG)); 753. 		    } else if (!(--u.utrap)) { 754. 			You("crawl to the edge of the pit."); 755. 			fill_pit(u.ux, u.uy); 756. 			vision_full_recalc = 1;	/* vision limits change */ 757. 		    } else if (flags.verbose) 758. 			Norep( (Hallucination && !rn2(5)) ?  759.  				"You've fallen, and you can't get up." :  760.  				"You are still in a pit." ); 761. 		} else if (u.utraptype == TT_LAVA) { 762. 		    if(flags.verbose) 763. 			Norep("You are stuck in the lava."); 764. 		    if(!is_lava(x,y)) { 765. 			u.utrap--; 766. 			if((u.utrap & 0xff) == 0) { 767. 			    You("pull yourself to the edge of the lava."); 768. 			    u.utrap = 0; 769. 			}  770.  		    }  771.  		    u.umoved = TRUE; 772. 		} else if (u.utraptype == TT_WEB) { 773. 		    if(uwep && uwep->oartifact == ART_STING) { 774. 			u.utrap = 0; 775. 			pline("Sting cuts through the web!"); 776. 			return; 777. 		    }  778.  		    if(--u.utrap) { 779. 			if(flags.verbose) 780. 			    Norep("You are stuck to the web."); 781. 		    } else You("disentangle yourself."); 782. 		} else if (u.utraptype == TT_INFLOOR) { 783. 		    if(--u.utrap) { 784. 			if(flags.verbose) 785. 			    Norep("You are stuck in the floor."); 786. 		    } else You("finally wiggle free."); 787. 		} else { 788. 		    if(flags.verbose) 789. 			Norep("You are caught in a bear trap."); 790. 		    if((u.dx && u.dy) || !rn2(5)) u.utrap--; 791. 		}  792.  		return; 793. 	}  794.   795.   796.  	/*  797.  	 *  Check for physical obstacles. First, the place we are going. 798. 	 */  799.  	if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) { 800. 	    if (Blind) feel_location(x,y); 801. 	    if (Passes_walls && may_passwall(x,y)) { 802. 		;	/* do nothing */ 803. 	    } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { 804. 		/* Eat the rock. */ 805.  		if (still_chewing(x,y)) return; 806. 	    } else { 807. 		if (Is_stronghold(&u.uz) && is_db_wall(x,y)) 808. 		    pline_The("drawbridge is up!"); 809. 		flags.move = 0; 810. 		nomul(0); 811. 		return; 812. 	    }  813.  	} else if (IS_DOOR(tmpr->typ)) { 814. 	    if (closed_door(x,y)) { 815. 		if (Blind) feel_location(x,y); 816. 		if (Passes_walls) 817. 		    ;	/* do nothing */ 818. 		else if (can_ooze(&youmonst)) 819. 		    You("ooze under the door."); 820. 		else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { 821. 		    /* Eat the door. */ 822.  		    if (still_chewing(x,y)) return; 823. 		} else { 824. 		    flags.move = 0; 825. 		    if (amorphous(youmonst.data)) 826. 			You("try to ooze under the door, but can't squeeze your possessions through."); 827. 		    else if (x == u.ux || y == u.uy) { 828. 			if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) { 829. 			    pline("Ouch!  You bump into a door."); 830. 			    exercise(A_DEX, FALSE); 831. 			} else pline("That door is closed."); 832. 		    }  833.  		    nomul(0); 834. 		    return; 835. 		}  836.  	    } else if (u.dx && u.dy && !Passes_walls  837.  			&& ((tmpr->doormask & ~D_BROKEN) 838. #ifdef REINCARNATION 839. 					|| Is_rogue_level(&u.uz) 840. #endif 841. 					|| block_door(x,y))) { 842. 		/* Diagonal moves into a door are not allowed. */ 843.  		if (Blind) feel_location(x,y);	/* ?? */ 844.  		flags.move = 0; 845. 		nomul(0); 846. 		return; 847. 	    }  848.  	}  849.  	if (u.dx && u.dy  850.  		&& bad_rock(youmonst.data,u.ux,y) && bad_rock(youmonst.data,x,u.uy)) { 851. 	    /* Move at a diagonal. */ 852.  	    if (In_sokoban(&u.uz)) { 853. 	    	You("cannot pass that way."); 854. 	    	nomul(0); 855. 	    	return; 856. 	    }  857.  	    if (bigmonst(youmonst.data)) { 858. 		Your("body is too large to fit through."); 859. 		nomul(0); 860. 		return; 861. 	    }  862.  	    if (invent && (inv_weight + weight_cap > 600)) { 863. 		You("are carrying too much to get through."); 864. 		nomul(0); 865. 		return; 866. 	    }  867.  	}  868.   869.  	ust = &levl[u.ux][u.uy]; 870.  871.  	/* Now see if other things block our way. . */ 872.  	if (u.dx && u.dy && !Passes_walls  873.  			 && (IS_DOOR(ust->typ) && ((ust->doormask & ~D_BROKEN)  874.  #ifdef REINCARNATION  875.  				 || Is_rogue_level(&u.uz)  876.  #endif  877.  				 || block_entry(x, y)) 878. 			     )) {  879.  	    /* Can't move at a diagonal out of a doorway with door. */ 880.  	    flags.move = 0; 881. 	    nomul(0); 882. 	    return; 883. 	}  884.   885.  	if (sobj_at(BOULDER,x,y) && (In_sokoban(&u.uz) || !Passes_walls)) { 886. 	    if (!(Blind || Hallucination) && (flags.run >= 2)) { 887. 		nomul(0); 888. 		flags.move = 0; 889. 		return; 890. 	    }  891.  	    /* tunneling monsters will chew before pushing */ 892. 	    if (tunnels(youmonst.data) && !needspick(youmonst.data)) { 893. 		if (still_chewing(x,y)) return; 894. 	    } else 895. 		if (moverock < 0) return; 896. 	}  897.   898.  	/* OK, it is a legal place to move. */ 899.   900.  	/* Move ball and chain. */ 901.  	if (Punished) 902. 	    if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy, 903. 			&cause_delay)) 904. 		return; 905.  906.  	/* Check regions entering/leaving */ 907. 	if (!in_out_region(x,y)) 908. 	    return; 909.  910.   	/* now move the hero */ 911. 	mtmp = m_at(x, y); 912. 	u.ux += u.dx; 913. 	u.uy += u.dy; 914. #ifdef STEED 915. 	/* Move your steed, too */ 916. 	if (u.usteed) { 917. 		u.usteed->mx = u.ux; 918. 		u.usteed->my = u.uy; 919. 		exercise_steed; 920. 	}  921.  #endif 922.  923.  	/*  924.  	 * If safepet at destination then move the pet to the hero's  925. * previous location using the same conditions as in attack. 926. 	 * there are special extenuating circumstances: 927. 	 * (1) if the pet dies then your god angers, 928. 	 * (2) if the pet gets trapped then your god may disapprove, 929. 	 * (3) if the pet was already trapped and you attempt to free it  930. * not only do you encounter the trap but you may frighten your 931. 	 * pet causing it to go wild! moral: don't abuse this privilege. 932. 	 *  933.  	 * Ceiling-hiding pets are skipped by this section of code, to  934. * be caught by the normal falling-monster code. 935. 	 */  936.  	if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) { 937. 	    /* if trapped, there's a chance the pet goes wild */ 938. 	    if (mtmp->mtrapped) { 939. 		if (!rn2(mtmp->mtame)) { 940. 		    mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0; 941. 		    growl(mtmp); 942. 		} else { 943. 		    yelp(mtmp); 944. 		}  945.  	    }  946.  	    mtmp->mundetected = 0; 947. 	    if (mtmp->m_ap_type) seemimic(mtmp); 948. 	    else if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my); 949.  950.  	    if (mtmp->mtrapped &&  951.  		    (trap = t_at(mtmp->mx, mtmp->my)) != 0 &&  952.  		    (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) &&  953.  		    sobj_at(BOULDER, trap->tx, trap->ty)) { 954. 		/* can't swap places with pet pinned in a pit by a boulder */ 955. 		u.ux = u.ux0,  u.uy = u.uy0;	/* didn't move after all */ 956. 	    } else { 957. 		mtmp->mtrapped = 0; 958. 		remove_monster(x, y); 959. 		place_monster(mtmp, u.ux0, u.uy0); 960.  961.  		/* check for displacing it into pools and traps */ 962. 		switch (minwater(mtmp) ? 2 : mintrap(mtmp)) { 963. 		case 0: 964. 		    You("%s %s.", mtmp->mtame ? "displaced" : "frightened",  965.  			y_monnam(mtmp)); 966. 		    break; 967. 		case 1:		/* trapped */ 968. 		case 3:		/* changed levels */ 969. 		    /* there's already been a trap message, reinforce it */ 970. 		    abuse_dog(mtmp); 971. 		    adjalign(-3); 972. 		    break; 973. 		case 2: 974. 		    /* it may have drowned or died. that's no way to 975. * treat a pet! your god gets angry. 976. 		     */  977.  		    if (rn2(4)) { 978. 			You_feel("guilty about losing your pet like this."); 979. 			u.ugangr++; 980. 			adjalign(-15); 981. 		    }  982.  		    break; 983. 		default: 984. 		    pline("that's strange, unknown mintrap result!"); 985. 		    break; 986. 		}  987.  	    }  988.  	}  989.   990.  	reset_occupations; 991. 	if (flags.run) { 992. 		if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) ||  993.  			IS_FURNITURE(tmpr->typ)) 994. 		    nomul(0); 995. 	}  996.   997.  	if (hides_under(youmonst.data)) 998. 	    u.uundetected = OBJ_AT(u.ux, u.uy); 999. 	else if (youmonst.data->mlet == S_EEL) 1000. 	   u.uundetected = is_pool(u.ux, u.uy) && !Is_waterlevel(&u.uz); 1001. 	else if (u.dx || u.dy) 1002. 	   u.uundetected = 0; 1003. 1004. 	/*  1005. 	 * Mimics (or whatever) become noticeable if they move and are 1006. 	 * imitating something that doesn't move. We could extend this 1007. 	 * to non-moving monsters... 1008. */ 1009. 	if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT 1010. 				|| youmonst.m_ap_type == M_AP_FURNITURE)) 1011. 	   youmonst.m_ap_type = M_AP_NOTHING; 1012. 1013. 	check_leash(u.ux0,u.uy0); 1014. 1015. 	if(u.ux0 != u.ux || u.uy0 != u.uy) { 1016. 	   u.umoved = TRUE; 1017. 	   /* Clean old position -- vision_recalc will print our new one. */ 1018. 	    newsym(u.ux0,u.uy0); 1019. 	   /* Since the hero has moved, adjust what can be seen/unseen. */ 1020. 	    vision_recalc(1);	/* Do the work now in the recover time. */ 1021. 	    invocation_message; 1022. 	} 1023.  1024. 	if (Punished)				/* put back ball and chain */ 1025. 	   move_bc(0,bc_control,ballx,bally,chainx,chainy); 1026. 1027. 	spoteffects; 1028. 1029. 	/* delay next move because of ball dragging */ 1030. 	/* must come after we finished picking up, in spoteffects */ 1031. 	if (cause_delay) { 1032. 	   nomul(-2); 1033. 	   nomovemsg = ""; 1034. 	} 1035. }  1036.  1037. void 1038. invocation_message 1039. { 1040. 	/* a special clue-msg when on the Invocation position */ 1041. 	if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) { 1042. 	   struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION); 1043. 1044. 	    You_feel("a strange vibration under your %s.",  1045. 		    makeplural(body_part(FOOT))); 1046. 	   if (otmp && otmp->spe == 7 && otmp->lamplit) 1047. 		pline("%s %s!", The(xname(otmp)), 1048. 		    Blind ? "throbs palpably" : "glows with a strange light"); 1049. 	} 1050. }  1051.  1052. #endif /* OVL3 */ 1053. #ifdef OVL2 1054. 1055. void 1056. spoteffects 1057. { 1058. 	register struct trap *trap; 1059. 	register struct monst *mtmp; 1060. 1061. 	if(u.uinwater) { 1062. 		int was_underwater; 1063. 1064. 		if (!is_pool(u.ux,u.uy)) { 1065. 			if (Is_waterlevel(&u.uz)) 1066. 				You("pop into an air bubble."); 1067. 			else if (is_lava(u.ux, u.uy)) 1068. 				You("leave the water...");	/* oops! */ 1069. 			else 1070. 				You("are on solid %s again.", 1071. 				    is_ice(u.ux, u.uy) ? "ice" : "land"); 1072. 		} 1073. 		else if (Is_waterlevel(&u.uz)) 1074. 			goto stillinwater; 1075. 		else if (Levitation) 1076. 			You("pop out of the water like a cork!"); 1077. 		else if (Flying) 1078. 			You("fly out of the water."); 1079. 		else if (Wwalking) 1080. 			You("slowly rise above the surface."); 1081. 		else 1082. 			goto stillinwater; 1083. 		was_underwater = Underwater && !Is_waterlevel(&u.uz); 1084. 		u.uinwater = 0;		/* leave the water */ 1085. 		if (was_underwater) {	/* restore vision */ 1086. 			docrt; 1087. 			vision_full_recalc = 1; 1088. 		} 1089. 	}  1090. stillinwater:; 1091. 	if (!Levitation && !u.ustuck && !Flying) { 1092. 	   /* limit recursive calls through teleds */ 1093. 	   if(is_lava(u.ux,u.uy) && lava_effects) 1094. 		   return; 1095. 	   if(is_pool(u.ux,u.uy) && !Wwalking && drown) 1096. 		   return; 1097. 	} 1098. 	check_special_room(FALSE); 1099. #ifdef SINKS 1100. 	if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation) 1101. 		dosinkfall; 1102. #endif 1103. 	if (!in_steed_dismounting) 1104. 		pickup(1); 1105. 	if ((trap = t_at(u.ux,u.uy)) != 0) 1106. 		dotrap(trap);	/* fall into pit, arrow trap, etc. */ 1107. 	if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) { 1108. 		mtmp->mundetected = mtmp->msleeping = 0; 1109. 		switch(mtmp->data->mlet) { 1110. 		   case S_PIERCER: 1111. 			pline("%s suddenly drops from the %s!", 1112. 			      Amonnam(mtmp), ceiling(u.ux,u.uy)); 1113. 			if(mtmp->mtame) /* jumps to greet you, not attack */ 1114. 			   ;  1115. 			else if(uarmh) 1116. 			   pline("Its blow glances off your helmet."); 1117. 			else if (u.uac + 3 <= rnd(20)) 1118. 			   You("are almost hit by %s!",  1119. 				x_monnam(mtmp, 2, "falling", 1)); 1120. 			else { 1121. 			   int dmg; 1122. 			   You("are hit by %s!",  1123. 				x_monnam(mtmp, 2, "falling", 1)); 1124. 			   dmg = d(4,6); 1125. 			   if(Half_physical_damage) dmg = (dmg+1) / 2; 1126. 			   mdamageu(mtmp, dmg); 1127. 			} 1128. 			break; 1129. 		   default:	/* monster surprises you. */ 1130. 			if(mtmp->mtame) 1131. 			   pline("%s jumps near you from the %s.",  1132. 					Amonnam(mtmp), ceiling(u.ux,u.uy)); 1133. 			else if(mtmp->mpeaceful) { 1134. 				You("surprise %s!", 1135. 				    Blind && !sensemon(mtmp) ?  1136. 				    something : a_monnam(mtmp)); 1137. 				mtmp->mpeaceful = 0; 1138. 			} else 1139. 			   pline("%s attacks you by surprise!",  1140. 					Amonnam(mtmp)); 1141. 			break; 1142. 		} 1143. 		mnexto(mtmp); /* have to move the monster */ 1144. 	} 1145. }  1146.  1147. STATIC_OVL boolean 1148. monstinroom(mdat,roomno) 1149. struct permonst *mdat; 1150. int roomno; 1151. { 1152. 	register struct monst *mtmp; 1153. 1154. 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 1155. 		if(mtmp->data == mdat && 1156. 		   index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET)) 1157. 			return(TRUE); 1158. 	return(FALSE); 1159. } 1160.  1161. char * 1162. in_rooms(x, y, typewanted) 1163. register xchar x, y; 1164. register int typewanted; 1165. { 1166. 	static char buf[5]; 1167. 	char rno, *ptr = &buf[4]; 1168. 	int typefound, min_x, min_y, max_x, max_y_offset, step; 1169. 	register struct rm *lev; 1170. 1171. #define goodtype(rno) (!typewanted || \  1172. 	     ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) || \  1173. 	     ((typewanted == SHOPBASE) && (typefound > SHOPBASE))) \ 1174. 1175. 	switch (rno = levl[x][y].roomno) { 1176. 		case NO_ROOM: 1177. 			return(ptr); 1178. 		case SHARED: 1179. 			step = 2; 1180. 			break; 1181. 		case SHARED_PLUS: 1182. 			step = 1; 1183. 			break; 1184. 		default:			/* i.e. a regular room # */ 1185. 			if (goodtype(rno)) 1186. 				*(--ptr) = rno; 1187. 			return(ptr); 1188. 	} 1189.  1190. 	min_x = x - 1; 1191. 	max_x = x + 1; 1192. 	if (x < 1) 1193. 		min_x += step; 1194. 	else 1195. 	if (x >= COLNO) 1196. 		max_x -= step; 1197. 1198. 	min_y = y - 1; 1199. 	max_y_offset = 2; 1200. 	if (min_y < 0) { 1201. 		min_y += step; 1202. 		max_y_offset -= step; 1203. 	} else 1204. 	if ((min_y + max_y_offset) >= ROWNO) 1205. 		max_y_offset -= step; 1206. 1207. 	for (x = min_x; x <= max_x; x += step) { 1208. 		lev = &levl[x][min_y]; 1209. 		y = 0; 1210. 		if (((rno = lev[y].roomno) >= ROOMOFFSET) && 1211. 		    !index(ptr, rno) && goodtype(rno)) 1212. 			*(--ptr) = rno; 1213. 		y += step; 1214. 		if (y > max_y_offset) 1215. 			continue; 1216. 		if (((rno = lev[y].roomno) >= ROOMOFFSET) && 1217. 		    !index(ptr, rno) && goodtype(rno)) 1218. 			*(--ptr) = rno; 1219. 		y += step; 1220. 		if (y > max_y_offset) 1221. 			continue; 1222. 		if (((rno = lev[y].roomno) >= ROOMOFFSET) && 1223. 		    !index(ptr, rno) && goodtype(rno)) 1224. 			*(--ptr) = rno; 1225. 	} 1226. 	return(ptr); 1227. } 1228.  1229. STATIC_OVL void 1230. move_update(newlev) 1231. register boolean newlev; 1232. { 1233. 	char *ptr1, *ptr2, *ptr3, *ptr4; 1234. 1235. 	Strcpy(u.urooms0, u.urooms); 1236. 	Strcpy(u.ushops0, u.ushops); 1237. 	if (newlev) { 1238. 		u.urooms[0] = '\0'; 1239. 		u.uentered[0] = '\0'; 1240. 		u.ushops[0] = '\0'; 1241. 		u.ushops_entered[0] = '\0'; 1242. 		Strcpy(u.ushops_left, u.ushops0); 1243. 		return; 1244. 	} 1245. 	Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0)); 1246. 1247. 	for (ptr1 = &u.urooms[0],  1248. 	     ptr2 = &u.uentered[0],  1249. 	     ptr3 = &u.ushops[0],  1250. 	     ptr4 = &u.ushops_entered[0];  1251. 	     *ptr1; ptr1++) { 1252. 		if (!index(u.urooms0, *ptr1)) 1253. 			*(ptr2++) = *ptr1; 1254. 		if (IS_SHOP(*ptr1 - ROOMOFFSET)) { 1255. 			*(ptr3++) = *ptr1; 1256. 			if (!index(u.ushops0, *ptr1)) 1257. 				*(ptr4++) = *ptr1; 1258. 		} 1259. 	}  1260. 	*ptr2 = '\0'; 1261. 	*ptr3 = '\0'; 1262. 	*ptr4 = '\0'; 1263. 1264. 	/* filter u.ushops0 -> u.ushops_left */ 1265. 	for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++) 1266. 		if (!index(u.ushops, *ptr1)) 1267. 			*(ptr2++) = *ptr1; 1268. 	*ptr2 = '\0'; 1269. } 1270.  1271. void 1272. check_special_room(newlev) 1273. register boolean newlev; 1274. { 1275. 	register struct monst *mtmp; 1276. 	char *ptr; 1277. 1278. 	move_update(newlev); 1279. 1280. 	if (*u.ushops0) 1281. 	   u_left_shop(u.ushops_left, newlev); 1282. 1283. 	if (!*u.uentered && !*u.ushops_entered)		/* implied by newlev */ 1284. 	   return;		/* no entrance messages necessary */ 1285. 1286. 	/* Did we just enter a shop? */ 1287. 	if (*u.ushops_entered) 1288. 	   u_entered_shop(u.ushops_entered); 1289. 1290. 	for (ptr = &u.uentered[0]; *ptr; ptr++) { 1291. 	   register int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype; 1292. 1293. 	    /* Did we just enter some other special room? */ 1294. 	    /* vault.c insists that a vault remain a VAULT, 1295. 	    * and temples should remain TEMPLEs, 1296. 	    * but everything else gives a message only the first time */ 1297. 	   switch (rt) { 1298. 		case ZOO: 1299. 		   pline("Welcome to David's treasure zoo!"); 1300. 		   break; 1301. 		case SWAMP: 1302. 		   pline("It %s rather %s down here.",  1303. 			  Blind ? "feels" : "looks",  1304. 			  Blind ? "humid" : "muddy"); 1305. 		   break; 1306. 		case COURT: 1307. 		   You("enter an opulent throne room!"); 1308. 		   break; 1309. 		case LEPREHALL: 1310. 		   You("enter a leprechaun hall!"); 1311. 		   break; 1312. 		case MORGUE: 1313. 		   if(midnight) { 1314. 			const char *run = locomotion(youmonst.data, "Run"); 1315. 			pline("%s away! %s away!", run, run); 1316. 		   } else 1317. 			You("have an uncanny feeling..."); 1318. 		   break; 1319. 		case BEEHIVE: 1320. 		   You("enter a giant beehive!"); 1321. 		   break; 1322. 		case COCKNEST: 1323. 		   You("enter a disgusting nest!"); 1324. 		   break; 1325. 		case ANTHOLE: 1326. 		   You("enter an anthole!"); 1327. 		   break; 1328. 		case BARRACKS: 1329. 		   if(monstinroom(&mons[PM_SOLDIER], roomno) ||  1330. 			monstinroom(&mons[PM_SERGEANT], roomno) ||  1331. 			monstinroom(&mons[PM_LIEUTENANT], roomno) ||  1332. 			monstinroom(&mons[PM_CAPTAIN], roomno)) 1333. 			You("enter a military barracks!"); 1334. 		   else 1335. 			You("enter an abandoned barracks."); 1336. 		   break; 1337. 		case DELPHI: 1338. 		   if(monstinroom(&mons[PM_ORACLE], roomno)) 1339. 			verbalize("%s, %s, welcome to Delphi!", Hello, plname); 1340. 		   break; 1341. 		case TEMPLE: 1342. 		   intemple(roomno + ROOMOFFSET); 1343. 		   /* fall through */ 1344. 		default: 1345. 		   rt = 0; 1346. 	   }  1347.  1348. 	    if (rt != 0) { 1349. 		rooms[roomno].rtype = OROOM; 1350. 		if (!search_special(rt)) { 1351. 			/* No more room of that type */ 1352. 			switch(rt) { 1353. 			   case COURT: 1354. 				level.flags.has_court = 0; 1355. 				break; 1356. 			   case SWAMP: 1357. 				level.flags.has_swamp = 0; 1358. 				break; 1359. 			   case MORGUE: 1360. 				level.flags.has_morgue = 0; 1361. 				break; 1362. 			   case ZOO: 1363. 				level.flags.has_zoo = 0; 1364. 				break; 1365. 			   case BARRACKS: 1366. 				level.flags.has_barracks = 0; 1367. 				break; 1368. 			   case TEMPLE: 1369. 				level.flags.has_temple = 0; 1370. 				break; 1371. 			   case BEEHIVE: 1372. 				level.flags.has_beehive = 0; 1373. 				break; 1374. 			} 1375. 		}  1376. 		if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO) 1377. 		   for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 1378. 			if (!Stealth && !rn2(3)) mtmp->msleeping = 0; 1379. 	   }  1380. 	}  1381.  1382. 	return; 1383. } 1384.  1385. #endif /* OVL2 */ 1386. #ifdef OVLB 1387. 1388. int 1389. dopickup 1390. { 1391. 	int count; 1392. 	/* awful kludge to work around parse's pre-decrement */ 1393. 	count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0; 1394. 	multi = 0;	/* always reset */ 1395. 	/* uswallow case added by GAN 01/29/87 */ 1396. 	if(u.uswallow) { 1397. 		if (is_animal(u.ustuck->data)) { 1398. 		   You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck))); 1399. 		   pline("But it's kind of slimy, so you drop it."); 1400. 		} else 1401. 		   You("don't %s anything in here to pick up.",  1402. 			  Blind ? "feel" : "see"); 1403. 		return(1); 1404. 	} 1405. 	if(is_pool(u.ux, u.uy)) { 1406. 	   if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)  1407. 			|| (Flying && !Breathless)) { 1408. 		You("cannot dive into the water to pick things up."); 1409. 		return(1); 1410. 	   } else if (!Underwater) { 1411. 		You_cant("even see the bottom, let alone pick up %s.", 1412. 				something); 1413. 		return(1); 1414. 	   }  1415. 	}  1416. 	if(!OBJ_AT(u.ux, u.uy)) { 1417. 		pline("There is nothing here to pick up."); 1418. 		return(0); 1419. 	} 1420. 	if (!can_reach_floor) { 1421. #ifdef STEED 1422. 		if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) 1423. 			You("aren't skilled enough to reach from %s.", 1424. 					mon_nam(u.usteed)); 1425. 		else 1426. #endif 1427. 		You("cannot reach the %s.", surface(u.ux,u.uy)); 1428. 		return(1); 1429. 	} 1430. 	pickup(-count); 1431. 	return(1); 1432. } 1433.  1434. #endif /* OVLB */ 1435. #ifdef OVL2 1436. 1437. /* stop running if we see something interesting */ 1438. /* turn around a corner if that is the only way we can proceed */ 1439. /* do not turn left or right twice */ 1440. void 1441. lookaround 1442. { 1443.     register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9; 1444.    register int corrct = 0, noturn = 0; 1445.    register struct monst *mtmp; 1446.    register struct trap *trap; 1447. 1448. 	/* Grid bugs stop if trying to move diagonal, even if blind. Maybe */ 1449. 	/* they polymorphed while in the middle of a long move. */ 1450. 	if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) { 1451. 		nomul(0); 1452. 		return; 1453. 	} 1454.  1455. 	if(Blind || flags.run == 0) return; 1456. 	for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) { 1457. 		if(!isok(x,y)) continue; 1458. 1459. 	if(u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy) continue; 1460. 1461. 	if(x == u.ux && y == u.uy) continue; 1462. 1463. 	if((mtmp = m_at(x,y)) &&  1464. 		    mtmp->m_ap_type != M_AP_FURNITURE &&  1465. 		    mtmp->m_ap_type != M_AP_OBJECT &&  1466. 		    (!mtmp->minvis || See_invisible) && !mtmp->mundetected) { 1467. 	   if((flags.run != 1 && !mtmp->mtame)  1468. 					|| (x == u.ux+u.dx && y == u.uy+u.dy)) 1469. 		goto stop; 1470. 	} 1471.  1472. 	if (levl[x][y].typ == STONE) continue; 1473. 	if (x == u.ux-u.dx && y == u.uy-u.dy) continue; 1474. 1475. 	if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) ||  1476. 	    IS_AIR(levl[x][y].typ)) 1477. 	   continue; 1478. 	else if (closed_door(x,y)) { 1479. 	   if(x != u.ux && y != u.uy) continue; 1480. 	   if(flags.run != 1) goto stop; 1481. 	   goto bcorr; 1482. 	} else if (levl[x][y].typ == CORR) { 1483. bcorr: 1484. 	   if(levl[u.ux][u.uy].typ != ROOM) { 1485. 		if(flags.run == 1 || flags.run == 3) { 1486. 		   i = dist2(x,y,u.ux+u.dx,u.uy+u.dy); 1487. 		   if(i > 2) continue; 1488. 		   if(corrct == 1 && dist2(x,y,x0,y0) != 1) 1489. 			noturn = 1; 1490. 		   if(i < i0) { 1491. 			i0 = i; 1492. x0 = x; 1493. y0 = y; 1494. m0 = mtmp ? 1 : 0; 1495. 		    }  1496. 		}  1497. 		corrct++; 1498. 	   }  1499. 	    continue; 1500. 	} else if ((trap = t_at(x,y)) && trap->tseen) { 1501. 	   if(flags.run == 1) goto bcorr;	/* if you must */ 1502. 	   if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop; 1503. 	   continue; 1504. 	} else if (is_pool(x,y) || is_lava(x,y)) { 1505. 	   /* water and lava only stop you if directly in front, and stop 1506. 	    * you even if you are running 1507. 	    */  1508. 	    if(!Levitation && !Flying && !is_clinger(youmonst.data) &&  1509. 				x == u.ux+u.dx && y == u.uy+u.dy) 1510. 			/* No Wwalking check; otherwise they'd be able 1511. 			 * to test boots by trying to SHIFT-direction 1512. 			 * into a pool and seeing if the game allowed it 1513. */ 1514. 			goto stop; 1515. 	   continue; 1516. 	} else {		/* e.g. objects or trap or stairs */ 1517. 	   if(flags.run == 1) goto bcorr; 1518. 	   if(mtmp) continue;		/* d */ 1519. 	   if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) ||  1520. 	       ((y == u.uy - u.dy) && (x != u.ux + u.dx))) 1521. 	      continue; 1522. 	} 1523. stop: 1524. 	nomul(0); 1525. 	return; 1526.    } /* end for loops */ 1527. 1528.     if(corrct > 1 && flags.run == 2) goto stop; 1529.    if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&  1530. 				(corrct == 1 || (corrct == 2 && i0 == 1))) { 1531. 	/* make sure that we do not turn too far */ 1532. 	if(i0 == 2) { 1533. 	   if(u.dx == y0-u.uy && u.dy == u.ux-x0) 1534. 		i = 2;		/* straight turn right */ 1535. 	   else 1536. 		i = -2;		/* straight turn left */ 1537. 	} else if(u.dx && u.dy) { 1538. 	   if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy)) 1539. 		i = -1;		/* half turn left */ 1540. 	   else 1541. 		i = 1;		/* half turn right */ 1542. 	} else { 1543. 	   if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy)) 1544. 		i = 1;		/* half turn right */ 1545. 	   else 1546. 		i = -1;		/* half turn left */ 1547. 	} 1548.  1549. 	i += u.last_str_turn; 1550. 	if(i <= 2 && i >= -2) { 1551. 	   u.last_str_turn = i;  1552. u.dx = x0-u.ux; 1553. 	   u.dy = y0-u.uy; 1554. 	} 1555.     }  1556. }  1557.  1558. /* something like lookaround, but we are not running */ 1559. /* react only to monsters that might hit us */ 1560. int 1561. monster_nearby 1562. { 1563. 	register int x,y; 1564. 	register struct monst *mtmp; 1565. 1566. 	/* Also see the similar check in dochugw in monmove.c */ 1567. 	for(x = u.ux-1; x <= u.ux+1; x++) 1568. 	   for(y = u.uy-1; y <= u.uy+1; y++) { 1569. 		if(!isok(x,y)) continue; 1570. 		if(x == u.ux && y == u.uy) continue; 1571. 		if((mtmp = m_at(x,y)) && 1572. 		   mtmp->m_ap_type != M_AP_FURNITURE &&  1573. 		   mtmp->m_ap_type != M_AP_OBJECT &&  1574. 		   (!mtmp->mpeaceful || Hallucination) &&  1575. 		   (!is_hider(mtmp->data) || !mtmp->mundetected) &&  1576. 		   !noattacks(mtmp->data) &&  1577. 		   mtmp->mcanmove && !mtmp->msleeping &&  /* aplvax!jcn */  1578. 		   !onscary(u.ux, u.uy, mtmp) &&  1579. 		   canspotmon(mtmp)) 1580. 			return(1); 1581. 	} 1582. 	return(0); 1583. } 1584.  1585. void 1586. nomul(nval) 1587. 	register int nval; 1588. { 1589. 	if(multi < nval) return;	/* This is a bug fix by ab@unido */ 1590. 	u.uinvulnerable = FALSE;	/* Kludge to avoid ctrl-C bug -dlc */ 1591. 	u.usleep = 0; 1592. 	multi = nval; 1593. 	flags.mv = flags.run = 0; 1594. } 1595.  1596. /* called when a non-movement, multi-turn action has completed */ 1597. void unmul(msg_override) 1598. const char *msg_override; 1599. { 1600. 	multi = 0;	/* caller will usually have done this already */ 1601. 	if (msg_override) nomovemsg = msg_override; 1602. 	else if (!nomovemsg) nomovemsg = You_can_move_again; 1603. 	if (*nomovemsg) pline(nomovemsg); 1604. 	nomovemsg = 0; 1605. 	u.usleep = 0; 1606. 	if (afternmv) (*afternmv); 1607. 	afternmv = 0; 1608. } 1609.  1610. #endif /* OVL2 */ 1611. #ifdef OVL1 1612. 1613. void 1614. losehp(n, knam, k_format) 1615. register int n; 1616. register const char *knam; 1617. boolean k_format; 1618. { 1619. 	if (Upolyd) { 1620. 		u.mh -= n; 1621. if (u.mhmax < u.mh) u.mhmax = u.mh; 1622. 		flags.botl = 1; 1623. 		if (u.mh < 1) rehumanize; 1624. 		return; 1625. 	} 1626.  1627. 	u.uhp -= n;  1628. if(u.uhp > u.uhpmax) 1629. 		u.uhpmax = u.uhp;	/* perhaps n was negative */ 1630. 	flags.botl = 1; 1631. 	if(u.uhp < 1) { 1632. 		killer_format = k_format; 1633. 		killer = knam;		/* the thing that killed you */ 1634. 		You("die..."); 1635. 		done(DIED); 1636. 	} else if (u.uhp*10 < u.uhpmax && moves-wailmsg > 50 && n > 0) { 1637. 		wailmsg = moves; 1638. 		if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) { 1639. 			if (u.uhp == 1) 1640. 				pline("%s is about to die.", 1641. 			    		(Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ?  1642. 			    		urole.name.m : "Elf"); 1643. 			else if (4 <= (!!(HTeleportation & INTRINSIC)) + 1644. 				    (!!(HSee_invisible & INTRINSIC)) +  1645. 				    (!!(HPoison_resistance & INTRINSIC)) +  1646. 				    (!!(HCold_resistance & INTRINSIC)) +  1647. 				    (!!(HShock_resistance & INTRINSIC)) +  1648. 				    (!!(HFire_resistance & INTRINSIC)) +  1649. 				    (!!(HSleep_resistance & INTRINSIC)) +  1650. 				    (!!(HDisint_resistance & INTRINSIC)) +  1651. 				    (!!(HTeleport_control & INTRINSIC)) +  1652. 				    (!!(HStealth & INTRINSIC)) +  1653. 				    (!!(HFast & INTRINSIC)) +  1654. 				    (!!(HInvis & INTRINSIC))) 1655. 				pline("%s, all your powers will be lost...", 1656. 			    		(Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ?  1657. 			    		urole.name.m : "Elf"); 1658. 			else 1659. 				pline("%s, your life force is running out.", 1660. 			    		(Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ?  1661. 			    		urole.name.m : "Elf"); 1662. 		} else { 1663. 			if(u.uhp == 1) 1664. 				You_hear("the wailing of the Banshee..."); 1665. 			else 1666. 				You_hear("the howling of the CwnAnnwn..."); 1667. 		} 1668. 	}  1669. }  1670.  1671. int 1672. weight_cap 1673. { 1674. 	register long carrcap; 1675. 1676. 	carrcap = (((ACURRSTR + ACURR(A_CON))/2)+1)*50; 1677. 	if (Upolyd) { 1678. 		/* consistent with can_carry in mon.c */ 1679. 		if (youmonst.data->mlet == S_NYMPH) 1680. 			carrcap = MAX_CARR_CAP; 1681. 		else if (!youmonst.data->cwt) 1682. 			carrcap = (carrcap * (long)youmonst.data->msize) / MZ_HUMAN; 1683. 		else if (!strongmonst(youmonst.data) 1684. 			|| (strongmonst(youmonst.data) && (youmonst.data->cwt > WT_HUMAN))) 1685. 			carrcap = (carrcap * (long)youmonst.data->cwt / WT_HUMAN); 1686. 	} 1687.  1688. 	if (Levitation || Is_airlevel(&u.uz)    /* pugh@cornell */  1689. #ifdef STEED  1690. 			|| (u.usteed && strongmonst(u.usteed->data))  1691. #endif  1692. 	) 1693. 		carrcap = MAX_CARR_CAP; 1694. 	else { 1695. 		if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP; 1696. 		if (!Flying) { 1697. 			if(EWounded_legs & LEFT_SIDE) carrcap -= 100; 1698. 			if(EWounded_legs & RIGHT_SIDE) carrcap -= 100; 1699. 		} 1700. 		if (carrcap < 0) carrcap = 0; 1701. 	} 1702. 	return((int) carrcap); 1703. } 1704.  1705. static int wc;	/* current weight_cap; valid after call to inv_weight */ 1706. 1707. /* returns how far beyond the normal capacity the player is currently. */ 1708. /* inv_weight is negative if the player is below normal capacity. */ 1709. int 1710. inv_weight 1711. { 1712. 	register struct obj *otmp = invent; 1713. 	register int wt; 1714. 1715. 	/* when putting stuff into containers, gold is inserted at the head 1716. 	  of invent for easier manipulation by askchain & co, but it's also 1717. 	  retained in u.ugold in order to keep the status line accurate; we  1718. mustn't add its weight in twice under that circumstance */ 1719. 	wt = (otmp && otmp->oclass == GOLD_CLASS) ? 0 : 1720. 		(int)((u.ugold + 50L) / 100L); 1721. 1722. 	while (otmp) { 1723. 		if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data)) 1724. 			wt += otmp->owt; 1725. 		otmp = otmp->nobj; 1726. 	} 1727. 	wc = weight_cap; 1728. 	return (wt - wc); 1729. } 1730.  1731. /*  1732.  * Returns 0 if below normal capacity, or the number of "capacity units" 1733. * over the normal capacity the player is loaded. Max is 5. 1734. */  1735. int 1736. calc_capacity(xtra_wt) 1737. int xtra_wt; 1738. { 1739.     int cap, wt = inv_weight + xtra_wt; 1740. 1741.     if (wt <= 0) return UNENCUMBERED; 1742.    if (wc <= 1) return OVERLOADED; 1743.    cap = (wt*2 / wc) + 1; 1744.    return min(cap, OVERLOADED); 1745. } 1746.  1747. int 1748. near_capacity 1749. { 1750.     return calc_capacity(0); 1751. } 1752.  1753. int 1754. max_capacity 1755. { 1756.     int wt = inv_weight; 1757. 1758.     return (wt - (2 * wc)); 1759. } 1760.  1761. boolean 1762. check_capacity(str) 1763. const char *str; 1764. { 1765.     if(near_capacity >= EXT_ENCUMBER) { 1766. 	if(str) 1767. 	   pline(str); 1768. 	else 1769. 	   You_cant("do that while carrying so much stuff."); 1770. 	return 1; 1771.    }  1772.     return 0; 1773. } 1774.  1775. #endif /* OVL1 */ 1776. #ifdef OVLB 1777. 1778. int 1779. inv_cnt 1780. { 1781. 	register struct obj *otmp = invent; 1782. 	register int ct = 0; 1783. 1784. 	while(otmp){ 1785. 		ct++; 1786. 		otmp = otmp->nobj; 1787. 	} 1788. 	return(ct); 1789. } 1790.  1791. #endif /* OVLB */ 1792. 1793. /*hack.c*/