Source:SLASH'EM 0.0.7E7F2/hack.c

From NetHackWiki
Revision as of 19:08, 7 March 2008 by Kernigh bot (talk | contribs) (SLASH'EM 0.0.7E7F2/hack.c moved to Source:SLASH'EM 0.0.7E7F2/hack.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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*/