Fandom

Wikihack

Source:NetHack 3.2.0/hack.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

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

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

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

Also on Fandom

Random Wiki