Wikia

Wikihack

Source:SLASH'EM 0.0.7E7F2/hack.c

2,032pages on
this wiki
Talk0

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

Around Wikia's network

Random Wiki