Source:SLASH'EM 0.0.7E7F2/hack.c

Below is the full text to hack.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/hack.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

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