Fandom

Wikihack

Source: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 src/hack.c from NetHack 3.4.3. To link to a particular line, write [[hack.c#line123]], for example.

Top of file Edit

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.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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.   

revive_nasty Edit

22.   #ifdef OVL2
23.   
24.   boolean
25.   revive_nasty(x, y, msg)
26.   int x,y;
27.   const char *msg;
28.   {
29.       register struct obj *otmp, *otmp2;
30.       struct monst *mtmp;
31.       coord cc;
32.       boolean revived = FALSE;
33.   
34.       for(otmp = level.objects[x][y]; otmp; otmp = otmp2) {
35.   	otmp2 = otmp->nexthere;
36.   	if (otmp->otyp == CORPSE &&
37.   	    (is_rider(&mons[otmp->corpsenm]) ||
38.   	     otmp->corpsenm == PM_WIZARD_OF_YENDOR)) {
39.   	    /* move any living monster already at that location */
40.   	    if((mtmp = m_at(x,y)) && enexto(&cc, x, y, mtmp->data))
41.   		rloc_to(mtmp, cc.x, cc.y);
42.   	    if(msg) Norep("%s", msg);
43.   	    revived = revive_corpse(otmp);
44.   	}
45.       }
46.   
47.       /* this location might not be safe, if not, move revived monster */
48.       if (revived) {
49.   	mtmp = m_at(x,y);
50.   	if (mtmp && !goodpos(x, y, mtmp, 0) &&
51.   	    enexto(&cc, x, y, mtmp->data)) {
52.   	    rloc_to(mtmp, cc.x, cc.y);
53.   	}
54.   	/* else impossible? */
55.       }
56.   
57.       return (revived);
58.   }
59.   

moverock Edit

Called when the player attempts to move into a space occupied by a boulder. The player may push the boulder, fail to move the boulder, or squeeze into the same space as the boulder.

60.   STATIC_OVL int
61.   moverock()
62.   {
63.       register xchar rx, ry, sx, sy;
64.       register struct obj *otmp;
65.       register struct trap *ttmp;
66.       register struct monst *mtmp;
67.   
68.       sx = u.ux + u.dx,  sy = u.uy + u.dy;	/* boulder starting position */
69.       while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) {
70.   	/* make sure that this boulder is visible as the top object */
71.   	if (otmp != level.objects[sx][sy]) movobj(otmp, sx, sy);
72.   
73.   	rx = u.ux + 2 * u.dx;	/* boulder destination position */
74.   	ry = u.uy + 2 * u.dy;
75.   	nomul(0);
76.   	if (Levitation || Is_airlevel(&u.uz)) {
77.   	    if (Blind) feel_location(sx, sy);
78.   	    You("don't have enough leverage to push %s.", the(xname(otmp)));
79.   	    /* Give them a chance to climb over it? */
80.   	    return -1;
81.   	}

You can't push boulders while levitating or on the Plane of Air.

82.   	if (verysmall(youmonst.data)
83.   #ifdef STEED
84.   		 && !u.usteed
85.   #endif
86.   				    ) {
87.   	    if (Blind) feel_location(sx, sy);
88.   	    pline("You're too small to push that %s.", xname(otmp));
89.   	    goto cannot_push;
90.   	}

If you are polymorphed into a very small monster and are not riding a steed, you cannot push boulders.

91.   	if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
92.   	    levl[rx][ry].typ != IRONBARS &&
93.   	    (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) || (
94.   #ifdef REINCARNATION
95.   		!Is_rogue_level(&u.uz) &&
96.   #endif
97.   		(levl[rx][ry].doormask & ~D_BROKEN) == D_NODOOR)) &&
98.   	    !sobj_at(BOULDER, rx, ry)) {
99.   	    ttmp = t_at(rx, ry);
100.  	    mtmp = m_at(rx, ry);
101.  

Pushing the boulder may be successful if you are in Sokoban, not trying to push into rock or iron bars, not trying to push diagonally through a door or Rogue level doorway, and not trying to push into a space already containing a boulder. If you may be successful, we store the trap and the monster at the destination, for the following sections of code.

102.  		/* KMH -- Sokoban doesn't let you push boulders diagonally */
103.  	    if (In_sokoban(&u.uz) && u.dx && u.dy) {
104.  	    	if (Blind) feel_location(sx,sy);
105.  	    	pline("%s won't roll diagonally on this %s.",
106.  	        		The(xname(otmp)), surface(sx, sy));
107.  	    	goto cannot_push;
108.  	    }
109.  

You can't push boulders diagonally in Sokoban.

110.  	    if (revive_nasty(rx, ry, "You sense movement on the other side."))
111.  		return (-1);
112.  

Try to revive a nasty corpse, such as a Rider on the other side. If so, the corpse comes back to life and you can't push the boulder.

113.  	    if (mtmp && !noncorporeal(mtmp->data) &&
114.  		    (!mtmp->mtrapped ||
115.  			 !(ttmp && ((ttmp->ttyp == PIT) ||
116.  				    (ttmp->ttyp == SPIKED_PIT))))) {
117.  		if (Blind) feel_location(sx, sy);
118.  		if (canspotmon(mtmp))
119.  		    pline("There's %s on the other side.", a_monnam(mtmp));
120.  		else {
121.  		    You_hear("a monster behind %s.", the(xname(otmp)));
122.  		    map_invisible(rx, ry);
123.  		}
124.  		if (flags.verbose)
125.  		    pline("Perhaps that's why %s cannot move it.",
126.  #ifdef STEED
127.  				u.usteed ? y_monnam(u.usteed) :
128.  #endif
129.  				"you");
130.  		goto cannot_push;
131.  	    }
132.  

If there is a monster with a body that is not trapped in a pit or spiked pit at the destination square, you can't push the boulder.

133.  	    if (ttmp)
134.  		switch(ttmp->ttyp) {

The following code handles any traps on the destination square.

135.  		case LANDMINE:
136.  		    if (rn2(10)) {
137.  			obj_extract_self(otmp);
138.  			place_object(otmp, rx, ry);
139.  			unblock_point(sx, sy);
140.  			newsym(sx, sy);
141.  			pline("KAABLAMM!!!  %s %s land mine.",
142.  			      Tobjnam(otmp, "trigger"),
143.  			      ttmp->madeby_u ? "your" : "a");
144.  			blow_up_landmine(ttmp);
145.  			/* if the boulder remains, it should fill the pit */
146.  			fill_pit(u.ux, u.uy);
147.  			if (cansee(rx,ry)) newsym(rx,ry);
148.  			continue;
149.  		    }
150.  		    break;

If you push into a landmine, it will trigger the landmine with 90% probability. If the boulder is not broken or destroyed by the resulting explosion, it will fill the resulting pit.

151.  		case SPIKED_PIT:
152.  		case PIT:
153.  		    obj_extract_self(otmp);
154.  		    /* vision kludge to get messages right;
155.  		       the pit will temporarily be seen even
156.  		       if this is one among multiple boulders */
157.  		    if (!Blind) viz_array[ry][rx] |= IN_SIGHT;
158.  		    if (!flooreffects(otmp, rx, ry, "fall")) {
159.  			place_object(otmp, rx, ry);
160.  		    }
161.  		    if (mtmp && !Blind) newsym(rx, ry);
162.  		    continue;

Pushing a boulder into a pit or spiked pit will cause damage to a trapped monster. If the monster dies, the boulder will fill the pit, removing the trap.

163.  		case HOLE:
164.  		case TRAPDOOR:
165.  		    if (Blind)
166.  			pline("Kerplunk!  You no longer feel %s.",
167.  				the(xname(otmp)));
168.  		    else
169.  			pline("%s%s and %s a %s in the %s!",
170.  			  Tobjnam(otmp,
171.  			   (ttmp->ttyp == TRAPDOOR) ? "trigger" : "fall"),
172.  			  (ttmp->ttyp == TRAPDOOR) ? nul : " into",
173.  			  otense(otmp, "plug"),
174.  			  (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",
175.  			  surface(rx, ry));
176.  		    deltrap(ttmp);
177.  		    delobj(otmp);
178.  		    bury_objs(rx, ry);
179.  		    if (cansee(rx,ry)) newsym(rx,ry);
180.  		    continue;

Pushing a boulder into a hole or trapdoor will remove the trap and the boulder.

181.  		case LEVEL_TELEP:
182.  		case TELEP_TRAP:
183.  #ifdef STEED
184.  		    if (u.usteed)
185.  			pline("%s pushes %s and suddenly it disappears!",
186.  			      upstart(y_monnam(u.usteed)), the(xname(otmp)));
187.  		    else
188.  #endif
189.  		    You("push %s and suddenly it disappears!",
190.  			the(xname(otmp)));
191.  		    if (ttmp->ttyp == TELEP_TRAP)
192.  			rloco(otmp);
193.  		    else {
194.  			int newlev = random_teleport_level();
195.  			d_level dest;
196.  
197.  			if (newlev == depth(&u.uz) || In_endgame(&u.uz))
198.  			    continue;
199.  			obj_extract_self(otmp);
200.  			add_to_migration(otmp);
201.  			get_level(&dest, newlev);
202.  			otmp->ox = dest.dnum;
203.  			otmp->oy = dest.dlevel;
204.  			otmp->owornmask = (long)MIGR_RANDOM;
205.  		    }
206.  		    seetrap(ttmp);
207.  		    continue;

If you push the boulder into a teleportation or level teleportation trap, the boulder will teleport.

208.  		}
209.  	    if (closed_door(rx, ry))
210.  		goto nopushmsg;

You can't push a boulder into a closed door.

211.  	    if (boulder_hits_pool(otmp, rx, ry, TRUE))
212.  		continue;

If the boulder is being pushed into water or lava, it will be consumed and may or may not fill the space.

213.  	    /*
214.  	     * Re-link at top of fobj chain so that pile order is preserved
215.  	     * when level is restored.
216.  	     */
217.  	    if (otmp != fobj) {
218.  		remove_object(otmp);
219.  		place_object(otmp, otmp->ox, otmp->oy);
220.  	    }
221.  
222.  	    {
223.  #ifdef LINT /* static long lastmovetime; */
224.  		long lastmovetime;
225.  		lastmovetime = 0;
226.  #else
227.  		/* note: reset to zero after save/restore cycle */
228.  		static NEARDATA long lastmovetime;
229.  #endif

Designed to prevent consecutive "With great effort you move the boulder" messages from appearing.

230.  #ifdef STEED
231.  		if (!u.usteed) {
232.  #endif
233.  		  if (moves > lastmovetime+2 || moves < lastmovetime)
234.  		    pline("With %s effort you move %s.",
235.  			  throws_rocks(youmonst.data) ? "little" : "great",
236.  			  the(xname(otmp)));

The message will only appear if you haven't pushed a boulder within the past three turns.

237.  		  exercise(A_STR, TRUE);

Pushing boulders exercises strength.

238.  #ifdef STEED
239.  		} else 
240.  		    pline("%s moves %s.",
241.  			  upstart(y_monnam(u.usteed)), the(xname(otmp)));
242.  #endif
243.  		lastmovetime = moves;
244.  	    }
245.  
246.  	    /* Move the boulder *after* the message. */
247.  	    if (glyph_is_invisible(levl[rx][ry].glyph))
248.  		unmap_object(rx, ry);
249.  	    movobj(otmp, rx, ry);	/* does newsym(rx,ry) */
250.  	    if (Blind) {
251.  		feel_location(rx,ry);
252.  		feel_location(sx, sy);
253.  	    } else {
254.  		newsym(sx, sy);
255.  	    }
256.  	} else {

This code moves the boulder, then updates the map and has you feel the square the boulder was originally on (if you were blind).

257.  	nopushmsg:
258.  #ifdef STEED
259.  	  if (u.usteed)
260.  	    pline("%s tries to move %s, but cannot.",
261.  		  upstart(y_monnam(u.usteed)), the(xname(otmp)));
262.  	  else
263.  #endif
264.  	    You("try to move %s, but in vain.", the(xname(otmp)));
265.  	    if (Blind) feel_location(sx, sy);
266.  	cannot_push:

If you were not able to push the boulder for some reason, the following code happens.

267.  	    if (throws_rocks(youmonst.data)) {
268.  #ifdef STEED
269.  		if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
270.  		    You("aren't skilled enough to %s %s from %s.",
271.  			(flags.pickup && !In_sokoban(&u.uz))
272.  			    ? "pick up" : "push aside",
273.  			the(xname(otmp)), y_monnam(u.usteed));
274.  		} else
275.  #endif
276.  		{
277.  		    pline("However, you can easily %s.",
278.  			(flags.pickup && !In_sokoban(&u.uz))
279.  			    ? "pick it up" : "push it aside");
280.  		    if (In_sokoban(&u.uz))
281.  			change_luck(-1);	/* Sokoban guilt */
282.  		    break;
283.  		}

If you can throw rocks are are not riding a steed unskilled, you can pick up the boulder or move into its space. If you do that in Sokoban, there is a luck penalty.

284.  		break;
285.  	    }
286.  
287.  	    if (
288.  #ifdef STEED
289.  		!u.usteed &&
290.  #endif	    
291.  		(((!invent || inv_weight() <= -850) &&
292.  		 (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][sy].typ)
293.  				     && IS_ROCK(levl[sx][u.uy].typ))))
294.  		|| verysmall(youmonst.data))) {
295.  		pline("However, you can squeeze yourself into a small opening.");
296.  		if (In_sokoban(&u.uz))
297.  		    change_luck(-1);	/* Sokoban guilt */
298.  		break;
299.  	    } else
300.  		return (-1);

If you are not on a steed and either are very small, carrying nothing or your inventory is 850 or more units below your carrying capacity, you can occupy the same space as the boulder. Again, this incurs a luck penalty in Sokoban.

301.  	}
302.      }
303.      return (0);
304.  }
305.  

still_chewing Edit

306.  /*
307.   *  still_chewing()
308.   *
309.   *  Chew on a wall, door, or boulder.  Returns TRUE if still eating, FALSE
310.   *  when done.
311.   */
312.  STATIC_OVL int
313.  still_chewing(x,y)
314.      xchar x, y;
315.  {
316.      struct rm *lev = &levl[x][y];
317.      struct obj *boulder = sobj_at(BOULDER,x,y);
318.      const char *digtxt = (char *)0, *dmgtxt = (char *)0;
319.  
320.      if (digging.down)		/* not continuing previous dig (w/ pick-axe) */
321.  	(void) memset((genericptr_t)&digging, 0, sizeof digging);
322.  
323.      if (!boulder && IS_ROCK(lev->typ) && !may_dig(x,y)) {
324.  	You("hurt your teeth on the %s.",
325.  	    IS_TREE(lev->typ) ? "tree" : "hard stone");
326.  	nomul(0);
327.  	return 1;
328.      } else if (digging.pos.x != x || digging.pos.y != y ||
329.  		!on_level(&digging.level, &u.uz)) {
330.  	digging.down = FALSE;
331.  	digging.chew = TRUE;
332.  	digging.warned = FALSE;
333.  	digging.pos.x = x;
334.  	digging.pos.y = y;
335.  	assign_level(&digging.level, &u.uz);
336.  	/* solid rock takes more work & time to dig through */
337.  	digging.effort =
338.  	    (IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + u.udaminc;
339.  	You("start chewing %s %s.",
340.  	    (boulder || IS_TREE(lev->typ)) ? "on a" : "a hole in the",
341.  	    boulder ? "boulder" :
342.  	    IS_TREE(lev->typ) ? "tree" : IS_ROCK(lev->typ) ? "rock" : "door");
343.  	watch_dig((struct monst *)0, x, y, FALSE);
344.  	return 1;
345.      } else if ((digging.effort += (30 + u.udaminc)) <= 100)  {
346.  	if (flags.verbose)
347.  	    You("%s chewing on the %s.",
348.  		digging.chew ? "continue" : "begin",
349.  		boulder ? "boulder" :
350.  		IS_TREE(lev->typ) ? "tree" :
351.  		IS_ROCK(lev->typ) ? "rock" : "door");
352.  	digging.chew = TRUE;
353.  	watch_dig((struct monst *)0, x, y, FALSE);
354.  	return 1;
355.      }
356.  
357.      /* Okay, you've chewed through something */
358.      u.uconduct.food++;
359.      u.uhunger += rnd(20);
360.  
361.      if (boulder) {
362.  	delobj(boulder);		/* boulder goes bye-bye */
363.  	You("eat the boulder.");	/* yum */
364.  
365.  	/*
366.  	 *  The location could still block because of
367.  	 *	1. More than one boulder
368.  	 *	2. Boulder stuck in a wall/stone/door.
369.  	 *
370.  	 *  [perhaps use does_block() below (from vision.c)]
371.  	 */
372.  	if (IS_ROCK(lev->typ) || closed_door(x,y) || sobj_at(BOULDER,x,y)) {
373.  	    block_point(x,y);	/* delobj will unblock the point */
374.  	    /* reset dig state */
375.  	    (void) memset((genericptr_t)&digging, 0, sizeof digging);
376.  	    return 1;
377.  	}
378.  
379.      } else if (IS_WALL(lev->typ)) {
380.  	if (*in_rooms(x, y, SHOPBASE)) {
381.  	    add_damage(x, y, 10L * ACURRSTR);
382.  	    dmgtxt = "damage";
383.  	}
384.  	digtxt = "chew a hole in the wall.";
385.  	if (level.flags.is_maze_lev) {
386.  	    lev->typ = ROOM;
387.  	} else if (level.flags.is_cavernous_lev && !in_town(x, y)) {
388.  	    lev->typ = CORR;
389.  	} else {
390.  	    lev->typ = DOOR;
391.  	    lev->doormask = D_NODOOR;
392.  	}
393.      } else if (IS_TREE(lev->typ)) {
394.  	digtxt = "chew through the tree.";
395.  	lev->typ = ROOM;
396.      } else if (lev->typ == SDOOR) {
397.  	if (lev->doormask & D_TRAPPED) {
398.  	    lev->doormask = D_NODOOR;
399.  	    b_trapped("secret door", 0);
400.  	} else {
401.  	    digtxt = "chew through the secret door.";
402.  	    lev->doormask = D_BROKEN;
403.  	}
404.  	lev->typ = DOOR;
405.  
406.      } else if (IS_DOOR(lev->typ)) {
407.  	if (*in_rooms(x, y, SHOPBASE)) {
408.  	    add_damage(x, y, 400L);
409.  	    dmgtxt = "break";
410.  	}
411.  	if (lev->doormask & D_TRAPPED) {
412.  	    lev->doormask = D_NODOOR;
413.  	    b_trapped("door", 0);
414.  	} else {
415.  	    digtxt = "chew through the door.";
416.  	    lev->doormask = D_BROKEN;
417.  	}
418.  
419.      } else { /* STONE or SCORR */
420.  	digtxt = "chew a passage through the rock.";
421.  	lev->typ = CORR;
422.      }
423.  
424.      unblock_point(x, y);	/* vision */
425.      newsym(x, y);
426.      if (digtxt) You(digtxt);	/* after newsym */
427.      if (dmgtxt) pay_for_damage(dmgtxt, FALSE);
428.      (void) memset((genericptr_t)&digging, 0, sizeof digging);
429.      return 0;
430.  }
431.  
432.  #endif /* OVL2 */

movobj Edit

433.  #ifdef OVLB
434.  
435.  void
436.  movobj(obj, ox, oy)
437.  register struct obj *obj;
438.  register xchar ox, oy;
439.  {
440.  	/* optimize by leaving on the fobj chain? */
441.  	remove_object(obj);
442.  	newsym(obj->ox, obj->oy);
443.  	place_object(obj, ox, oy);
444.  	newsym(ox, oy);
445.  }
446.  

dosinkfall Edit

447.  #ifdef SINKS
448.  static NEARDATA const char fell_on_sink[] = "fell onto a sink";
449.  
450.  STATIC_OVL void
451.  dosinkfall()
452.  {
453.  	register struct obj *obj;
454.  
455.  	if (is_floater(youmonst.data) || (HLevitation & FROMOUTSIDE)) {
456.  	    You("wobble unsteadily for a moment.");
457.  	} else {
458.  	    long save_ELev = ELevitation, save_HLev = HLevitation;
459.  
460.  	    /* fake removal of levitation in advance so that final
461.  	       disclosure will be right in case this turns out to
462.  	       be fatal; fortunately the fact that rings and boots
463.  	       are really still worn has no effect on bones data */
464.  	    ELevitation = HLevitation = 0L;
465.  	    You("crash to the floor!");
466.  	    losehp(rn1(8, 25 - (int)ACURR(A_CON)),
467.  		   fell_on_sink, NO_KILLER_PREFIX);
468.  	    exercise(A_DEX, FALSE);
469.  	    selftouch("Falling, you");
470.  	    for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
471.  		if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) {
472.  		    You("fell on %s.", doname(obj));
473.  		    losehp(rnd(3), fell_on_sink, NO_KILLER_PREFIX);
474.  		    exercise(A_CON, FALSE);
475.  		}
476.  	    ELevitation = save_ELev;
477.  	    HLevitation = save_HLev;
478.  	}
479.  
480.  	ELevitation &= ~W_ARTI;
481.  	HLevitation &= ~(I_SPECIAL|TIMEOUT);
482.  	HLevitation++;
483.  	if(uleft && uleft->otyp == RIN_LEVITATION) {
484.  	    obj = uleft;
485.  	    Ring_off(obj);
486.  	    off_msg(obj);
487.  	}
488.  	if(uright && uright->otyp == RIN_LEVITATION) {
489.  	    obj = uright;
490.  	    Ring_off(obj);
491.  	    off_msg(obj);
492.  	}
493.  	if(uarmf && uarmf->otyp == LEVITATION_BOOTS) {
494.  	    obj = uarmf;
495.  	    (void)Boots_off();
496.  	    off_msg(obj);
497.  	}
498.  	HLevitation--;
499.  }
500.  #endif
501.  

may_dig Edit

502.  boolean
503.  may_dig(x,y)
504.  register xchar x,y;
505.  /* intended to be called only on ROCKs */
506.  {
507.      return (boolean)(!(IS_STWALL(levl[x][y].typ) &&
508.  			(levl[x][y].wall_info & W_NONDIGGABLE)));
509.  }
510.  

may_passwall Edit

511.  boolean
512.  may_passwall(x,y)
513.  register xchar x,y;
514.  {
515.     return (boolean)(!(IS_STWALL(levl[x][y].typ) &&
516.  			(levl[x][y].wall_info & W_NONPASSWALL)));
517.  }
518.  
519.  #endif /* OVLB */

bad_rock Edit

520.  #ifdef OVL1
521.  
522.  boolean
523.  bad_rock(mdat,x,y)
524.  struct permonst *mdat;
525.  register xchar x,y;
526.  {
527.  	return((boolean) ((In_sokoban(&u.uz) && sobj_at(BOULDER,x,y)) ||
528.  	       (IS_ROCK(levl[x][y].typ)
529.  		    && (!tunnels(mdat) || needspick(mdat) || !may_dig(x,y))
530.  		    && !(passes_walls(mdat) && may_passwall(x,y)))));
531.  }
532.  

invocation_pos Edit

533.  boolean
534.  invocation_pos(x, y)
535.  xchar x, y;
536.  {
537.  	return((boolean)(Invocation_lev(&u.uz) && x == inv_pos.x && y == inv_pos.y));
538.  }
539.  
540.  #endif /* OVL1 */

test_move Edit

541.  #ifdef OVL3
542.  
543.  /* return TRUE if (dx,dy) is an OK place to move
544.   * mode is one of DO_MOVE, TEST_MOVE or TEST_TRAV
545.   */
546.  boolean 
547.  test_move(ux, uy, dx, dy, mode)
548.  int ux, uy, dx, dy;
549.  int mode;
550.  {
551.      int x = ux+dx;
552.      int y = uy+dy;
553.      register struct rm *tmpr = &levl[x][y];
554.      register struct rm *ust;
555.  
556.      /*
557.       *  Check for physical obstacles.  First, the place we are going.
558.       */
559.      if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) {
560.  	if (Blind && mode == DO_MOVE) feel_location(x,y);
561.  	if (Passes_walls && may_passwall(x,y)) {
562.  	    ;	/* do nothing */
563.  	} else if (tmpr->typ == IRONBARS) {
564.  	    if (!(Passes_walls || passes_bars(youmonst.data)))
565.  		return FALSE;
566.  	} else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
567.  	    /* Eat the rock. */
568.  	    if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
569.  	} else if (flags.autodig && !flags.run && !flags.nopick &&
570.  		   uwep && is_pick(uwep)) {
571.  	/* MRKR: Automatic digging when wielding the appropriate tool */
572.  	    if (mode == DO_MOVE)
573.  		(void) use_pick_axe2(uwep);
574.  	    return FALSE;
575.  	} else {
576.  	    if (mode == DO_MOVE) {
577.  		if (Is_stronghold(&u.uz) && is_db_wall(x,y))
578.  		    pline_The("drawbridge is up!");
579.  		if (Passes_walls && !may_passwall(x,y) && In_sokoban(&u.uz))
580.  		    pline_The("Sokoban walls resist your ability.");
581.  	    }
582.  	    return FALSE;
583.  	}
584.      } else if (IS_DOOR(tmpr->typ)) {
585.  	if (closed_door(x,y)) {
586.  	    if (Blind && mode == DO_MOVE) feel_location(x,y);
587.  	    if (Passes_walls)
588.  		;	/* do nothing */
589.  	    else if (can_ooze(&youmonst)) {
590.  		if (mode == DO_MOVE) You("ooze under the door.");
591.  	    } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
592.  		/* Eat the door. */
593.  		if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
594.  	    } else {
595.  		if (mode == DO_MOVE) {
596.  		    if (amorphous(youmonst.data))
597.  			You("try to ooze under the door, but can't squeeze your possessions through.");
598.  		    else if (x == ux || y == uy) {
599.  			if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) {
600.  #ifdef STEED
601.  			    if (u.usteed) {
602.  				You_cant("lead %s through that closed door.",
603.  				         y_monnam(u.usteed));
604.  			    } else
605.  #endif
606.  			    {
607.  			        pline("Ouch!  You bump into a door.");
608.  			        exercise(A_DEX, FALSE);
609.  			    }
610.  			} else pline("That door is closed.");
611.  		    }
612.  		} else if (mode == TEST_TRAV) goto testdiag;
613.  		return FALSE;
614.  	    }
615.  	} else {
616.  	testdiag:
617.  	    if (dx && dy && !Passes_walls
618.  		&& ((tmpr->doormask & ~D_BROKEN)
619.  #ifdef REINCARNATION
620.  		    || Is_rogue_level(&u.uz)
621.  #endif
622.  		    || block_door(x,y))) {
623.  		/* Diagonal moves into a door are not allowed. */
624.  		if (Blind && mode == DO_MOVE)
625.  		    feel_location(x,y);
626.  		return FALSE;
627.  	    }
628.  	}
629.      }
630.      if (dx && dy
631.  	    && bad_rock(youmonst.data,ux,y) && bad_rock(youmonst.data,x,uy)) {
632.  	/* Move at a diagonal. */
633.  	if (In_sokoban(&u.uz)) {
634.  	    if (mode == DO_MOVE)
635.  		You("cannot pass that way.");
636.  	    return FALSE;
637.  	}
638.  	if (bigmonst(youmonst.data)) {
639.  	    if (mode == DO_MOVE)
640.  		Your("body is too large to fit through.");
641.  	    return FALSE;
642.  	}
643.  	if (invent && (inv_weight() + weight_cap() > 600)) {
644.  	    if (mode == DO_MOVE)
645.  		You("are carrying too much to get through.");
646.  	    return FALSE;
647.  	}
648.      }
649.      /* Pick travel path that does not require crossing a trap.
650.       * Avoid water and lava using the usual running rules.
651.       * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
652.      if (flags.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) {
653.  	struct trap* t = t_at(x, y);
654.  
655.  	if ((t && t->tseen) ||
656.  	    (!Levitation && !Flying &&
657.  	     !is_clinger(youmonst.data) &&
658.  	     (is_pool(x, y) || is_lava(x, y)) && levl[x][y].seenv))
659.  	    return FALSE;
660.      }
661.  
662.      ust = &levl[ux][uy];
663.  
664.      /* Now see if other things block our way . . */
665.      if (dx && dy && !Passes_walls
666.  		     && (IS_DOOR(ust->typ) && ((ust->doormask & ~D_BROKEN)
667.  #ifdef REINCARNATION
668.  			     || Is_rogue_level(&u.uz)
669.  #endif
670.  			     || block_entry(x, y))
671.  			 )) {
672.  	/* Can't move at a diagonal out of a doorway with door. */
673.  	return FALSE;
674.      }
675.  
676.      if (sobj_at(BOULDER,x,y) && (In_sokoban(&u.uz) || !Passes_walls)) {
677.  	if (!(Blind || Hallucination) && (flags.run >= 2) && mode != TEST_TRAV)
678.  	    return FALSE;
679.  	if (mode == DO_MOVE) {
680.  	    /* tunneling monsters will chew before pushing */
681.  	    if (tunnels(youmonst.data) && !needspick(youmonst.data) &&
682.  		!In_sokoban(&u.uz)) {
683.  		if (still_chewing(x,y)) return FALSE;
684.  	    } else
685.  		if (moverock() < 0) return FALSE;
686.  	} else if (mode == TEST_TRAV) {
687.  	    struct obj* obj;
688.  
689.  	    /* don't pick two boulders in a row, unless there's a way thru */
690.  	    if (sobj_at(BOULDER,ux,uy) && !In_sokoban(&u.uz)) {
691.  		if (!Passes_walls &&
692.  		    !(tunnels(youmonst.data) && !needspick(youmonst.data)) &&
693.  		    !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK) &&
694.  		    !((obj = carrying(WAN_DIGGING)) &&
695.  		      !objects[obj->otyp].oc_name_known))
696.  		    return FALSE;
697.  	    }
698.  	}
699.  	/* assume you'll be able to push it when you get there... */
700.      }
701.  
702.      /* OK, it is a legal place to move. */
703.      return TRUE;
704.  }
705.  

findtravelpath Edit

706.  /*
707.   * Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy).
708.   * A shortest path is returned.  If guess is TRUE, consider various
709.   * inaccessible locations as valid intermediate path points.
710.   * Returns TRUE if a path was found.
711.   */
712.  static boolean
713.  findtravelpath(guess)
714.  boolean guess;
715.  {
716.      /* if travel to adjacent, reachable location, use normal movement rules */
717.      if (!guess && iflags.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1) {
718.  	flags.run = 0;
719.  	if (test_move(u.ux, u.uy, u.tx-u.ux, u.ty-u.uy, TEST_MOVE)) {
720.  	    u.dx = u.tx-u.ux;
721.  	    u.dy = u.ty-u.uy;
722.  	    nomul(0);
723.  	    iflags.travelcc.x = iflags.travelcc.y = -1;
724.  	    return TRUE;
725.  	}
726.  	flags.run = 8;
727.      }
728.      if (u.tx != u.ux || u.ty != u.uy) {
729.  	xchar travel[COLNO][ROWNO];
730.  	xchar travelstepx[2][COLNO*ROWNO];
731.  	xchar travelstepy[2][COLNO*ROWNO];
732.  	xchar tx, ty, ux, uy;
733.  	int n = 1;			/* max offset in travelsteps */
734.  	int set = 0;			/* two sets current and previous */
735.  	int radius = 1;			/* search radius */
736.  	int i;
737.  
738.  	/* If guessing, first find an "obvious" goal location.  The obvious
739.  	 * goal is the position the player knows of, or might figure out
740.  	 * (couldsee) that is closest to the target on a straight path.
741.  	 */
742.  	if (guess) {
743.  	    tx = u.ux; ty = u.uy; ux = u.tx; uy = u.ty;
744.  	} else {
745.  	    tx = u.tx; ty = u.ty; ux = u.ux; uy = u.uy;
746.  	}
747.  
748.      noguess:
749.  	(void) memset((genericptr_t)travel, 0, sizeof(travel));
750.  	travelstepx[0][0] = tx;
751.  	travelstepy[0][0] = ty;
752.  
753.  	while (n != 0) {
754.  	    int nn = 0;
755.  
756.  	    for (i = 0; i < n; i++) {
757.  		int dir;
758.  		int x = travelstepx[set][i];
759.  		int y = travelstepy[set][i];
760.  		static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
761.  		/* no diagonal movement for grid bugs */
762.  		int dirmax = u.umonnum == PM_GRID_BUG ? 4 : 8;
763.  
764.  		for (dir = 0; dir < dirmax; ++dir) {
765.  		    int nx = x+xdir[ordered[dir]];
766.  		    int ny = y+ydir[ordered[dir]];
767.  
768.  		    if (!isok(nx, ny)) continue;
769.  		    if ((!Passes_walls && !can_ooze(&youmonst) &&
770.  			closed_door(x, y)) || sobj_at(BOULDER, x, y)) {
771.  			/* closed doors and boulders usually
772.  			 * cause a delay, so prefer another path */
773.  			if (travel[x][y] > radius-3) {
774.  			    travelstepx[1-set][nn] = x;
775.  			    travelstepy[1-set][nn] = y;
776.  			    /* don't change travel matrix! */
777.  			    nn++;
778.  			    continue;
779.  			}
780.  		    }
781.  		    if (test_move(x, y, nx-x, ny-y, TEST_TRAV) &&
782.  			(levl[nx][ny].seenv || (!Blind && couldsee(nx, ny)))) {
783.  			if (nx == ux && ny == uy) {
784.  			    if (!guess) {
785.  				u.dx = x-ux;
786.  				u.dy = y-uy;
787.  				if (x == u.tx && y == u.ty) {
788.  				    nomul(0);
789.  				    /* reset run so domove run checks work */
790.  				    flags.run = 8;
791.  				    iflags.travelcc.x = iflags.travelcc.y = -1;
792.  				}
793.  				return TRUE;
794.  			    }
795.  			} else if (!travel[nx][ny]) {
796.  			    travelstepx[1-set][nn] = nx;
797.  			    travelstepy[1-set][nn] = ny;
798.  			    travel[nx][ny] = radius;
799.  			    nn++;
800.  			}
801.  		    }
802.  		}
803.  	    }
804.  	    
805.  	    n = nn;
806.  	    set = 1-set;
807.  	    radius++;
808.  	}
809.  
810.  	/* if guessing, find best location in travel matrix and go there */
811.  	if (guess) {
812.  	    int px = tx, py = ty;	/* pick location */
813.  	    int dist, nxtdist, d2, nd2;
814.  
815.  	    dist = distmin(ux, uy, tx, ty);
816.  	    d2 = dist2(ux, uy, tx, ty);
817.  	    for (tx = 1; tx < COLNO; ++tx)
818.  		for (ty = 0; ty < ROWNO; ++ty)
819.  		    if (travel[tx][ty]) {
820.  			nxtdist = distmin(ux, uy, tx, ty);
821.  			if (nxtdist == dist && couldsee(tx, ty)) {
822.  			    nd2 = dist2(ux, uy, tx, ty);
823.  			    if (nd2 < d2) {
824.  				/* prefer non-zigzag path */
825.  				px = tx; py = ty;
826.  				d2 = nd2;
827.  			    }
828.  			} else if (nxtdist < dist && couldsee(tx, ty)) {
829.  			    px = tx; py = ty;
830.  			    dist = nxtdist;
831.  			    d2 = dist2(ux, uy, tx, ty);
832.  			}
833.  		    }
834.  
835.  	    if (px == u.ux && py == u.uy) {
836.  		/* no guesses, just go in the general direction */
837.  		u.dx = sgn(u.tx - u.ux);
838.  		u.dy = sgn(u.ty - u.uy);
839.  		if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE))
840.  		    return TRUE;
841.  		goto found;
842.  	    }
843.  	    tx = px;
844.  	    ty = py;
845.  	    ux = u.ux;
846.  	    uy = u.uy;
847.  	    set = 0;
848.  	    n = radius = 1;
849.  	    guess = FALSE;
850.  	    goto noguess;
851.  	}
852.  	return FALSE;
853.      }
854.  
855.  found:
856.      u.dx = 0;
857.      u.dy = 0;
858.      nomul(0);
859.      return FALSE;
860.  }
861.  

domove Edit

862.  void
863.  domove()
864.  {
865.  	register struct monst *mtmp;
866.  	register struct rm *tmpr;
867.  	register xchar x,y;
868.  	struct trap *trap;
869.  	int wtcap;
870.  	boolean on_ice;
871.  	xchar chainx, chainy, ballx, bally;	/* ball&chain new positions */
872.  	int bc_control;				/* control for ball&chain */
873.  	boolean cause_delay = FALSE;	/* dragging ball will skip a move */
874.  	const char *predicament;
875.  
876.  	u_wipe_engr(rnd(5));
877.  
878.  	if (flags.travel) {
879.  	    if (!findtravelpath(FALSE))
880.  		(void) findtravelpath(TRUE);
881.  	    iflags.travel1 = 0;
882.  	}
883.  
884.  	if(((wtcap = near_capacity()) >= OVERLOADED
885.  	    || (wtcap > SLT_ENCUMBER &&
886.  		(Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
887.  			: (u.uhp < 10 && u.uhp != u.uhpmax))))
888.  	   && !Is_airlevel(&u.uz)) {
889.  	    if(wtcap < OVERLOADED) {
890.  		You("don't have enough stamina to move.");
891.  		exercise(A_CON, FALSE);
892.  	    } else
893.  		You("collapse under your load.");
894.  	    nomul(0);
895.  	    return;
896.  	}
897.  	if(u.uswallow) {
898.  		u.dx = u.dy = 0;
899.  		u.ux = x = u.ustuck->mx;
900.  		u.uy = y = u.ustuck->my;
901.  		mtmp = u.ustuck;
902.  	} else {
903.  		if (Is_airlevel(&u.uz) && rn2(4) &&
904.  			!Levitation && !Flying) {
905.  		    switch(rn2(3)) {
906.  		    case 0:
907.  			You("tumble in place.");
908.  			exercise(A_DEX, FALSE);
909.  			break;
910.  		    case 1:
911.  			You_cant("control your movements very well."); break;
912.  		    case 2:
913.  			pline("It's hard to walk in thin air.");
914.  			exercise(A_DEX, TRUE);
915.  			break;
916.  		    }
917.  		    return;
918.  		}
919.  
920.  		/* check slippery ice */
921.  		on_ice = !Levitation && is_ice(u.ux, u.uy);
922.  		if (on_ice) {
923.  		    static int skates = 0;
924.  		    if (!skates) skates = find_skates();
925.  		    if ((uarmf && uarmf->otyp == skates)
926.  			    || resists_cold(&youmonst) || Flying
927.  			    || is_floater(youmonst.data) || is_clinger(youmonst.data)
928.  			    || is_whirly(youmonst.data))
929.  			on_ice = FALSE;
930.  		    else if (!rn2(Cold_resistance ? 3 : 2)) {
931.  			HFumbling |= FROMOUTSIDE;
932.  			HFumbling &= ~TIMEOUT;
933.  			HFumbling += 1;  /* slip on next move */
934.  		    }
935.  		}
936.  		if (!on_ice && (HFumbling & FROMOUTSIDE))
937.  		    HFumbling &= ~FROMOUTSIDE;
938.  
939.  		x = u.ux + u.dx;
940.  		y = u.uy + u.dy;
941.  		if(Stunned || (Confusion && !rn2(5))) {
942.  			register int tries = 0;
943.  
944.  			do {
945.  				if(tries++ > 50) {
946.  					nomul(0);
947.  					return;
948.  				}
949.  				confdir();
950.  				x = u.ux + u.dx;
951.  				y = u.uy + u.dy;
952.  			} while(!isok(x, y) || bad_rock(youmonst.data, x, y));
953.  		}
954.  		/* turbulence might alter your actual destination */
955.  		if (u.uinwater) {
956.  			water_friction();
957.  			if (!u.dx && !u.dy) {
958.  				nomul(0);
959.  				return;
960.  			}
961.  			x = u.ux + u.dx;
962.  			y = u.uy + u.dy;
963.  		}
964.  		if(!isok(x, y)) {
965.  			nomul(0);
966.  			return;
967.  		}
968.  		if (((trap = t_at(x, y)) && trap->tseen) ||
969.  		    (Blind && !Levitation && !Flying &&
970.  		     !is_clinger(youmonst.data) &&
971.  		     (is_pool(x, y) || is_lava(x, y)) && levl[x][y].seenv)) {
972.  			if(flags.run >= 2) {
973.  				nomul(0);
974.  				flags.move = 0;
975.  				return;
976.  			} else
977.  				nomul(0);
978.  		}
979.  
980.  		if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
981.  		    if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
982.  			/* perhaps it fled (or was teleported or ... ) */
983.  			u.ustuck = 0;
984.  		    } else if (sticks(youmonst.data)) {
985.  			/* When polymorphed into a sticking monster,
986.  			 * u.ustuck means it's stuck to you, not you to it.
987.  			 */
988.  			You("release %s.", mon_nam(u.ustuck));
989.  			u.ustuck = 0;
990.  		    } else {
991.  			/* If holder is asleep or paralyzed:
992.  			 *	37.5% chance of getting away,
993.  			 *	12.5% chance of waking/releasing it;
994.  			 * otherwise:
995.  			 *	 7.5% chance of getting away.
996.  			 * [strength ought to be a factor]
997.  			 * If holder is tame and there is no conflict,
998.  			 * guaranteed escape.
999.  			 */
1000. 			switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
1001. 			case 0: case 1: case 2:
1002. 			pull_free:
1003. 			    You("pull free from %s.", mon_nam(u.ustuck));
1004. 			    u.ustuck = 0;
1005. 			    break;
1006. 			case 3:
1007. 			    if (!u.ustuck->mcanmove) {
1008. 				/* it's free to move on next turn */
1009. 				u.ustuck->mfrozen = 1;
1010. 				u.ustuck->msleeping = 0;
1011. 			    }
1012. 			    /*FALLTHRU*/
1013. 			default:
1014. 			    if (u.ustuck->mtame &&
1015. 				!Conflict && !u.ustuck->mconf)
1016. 				goto pull_free;
1017. 			    You("cannot escape from %s!", mon_nam(u.ustuck));
1018. 			    nomul(0);
1019. 			    return;
1020. 			}
1021. 		    }
1022. 		}
1023. 
1024. 		mtmp = m_at(x,y);
1025. 		if (mtmp) {
1026. 			/* Don't attack if you're running, and can see it */
1027. 			/* We should never get here if forcefight */
1028. 			if (flags.run &&
1029. 			    ((!Blind && mon_visible(mtmp) &&
1030. 			      ((mtmp->m_ap_type != M_AP_FURNITURE &&
1031. 				mtmp->m_ap_type != M_AP_OBJECT) ||
1032. 			       Protection_from_shape_changers)) ||
1033. 			     sensemon(mtmp))) {
1034. 				nomul(0);
1035. 				flags.move = 0;
1036. 				return;
1037. 			}
1038. 		}
1039. 	}
1040. 
1041. 	u.ux0 = u.ux;
1042. 	u.uy0 = u.uy;
1043. 	bhitpos.x = x;
1044. 	bhitpos.y = y;
1045. 	tmpr = &levl[x][y];
1046. 
1047. 	/* attack monster */
1048. 	if(mtmp) {
1049. 	    nomul(0);
1050. 	    /* only attack if we know it's there */
1051. 	    /* or if we used the 'F' command to fight blindly */
1052. 	    /* or if it hides_under, in which case we call attack() to print
1053. 	     * the Wait! message.
1054. 	     * This is different from ceiling hiders, who aren't handled in
1055. 	     * attack().
1056. 	     */
1057. 
1058. 	    /* If they used a 'm' command, trying to move onto a monster
1059. 	     * prints the below message and wastes a turn.  The exception is
1060. 	     * if the monster is unseen and the player doesn't remember an
1061. 	     * invisible monster--then, we fall through to attack() and
1062. 	     * attack_check(), which still wastes a turn, but prints a
1063. 	     * different message and makes the player remember the monster.		     */
1064. 	    if(flags.nopick &&
1065. 		  (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))){
1066. 		if(mtmp->m_ap_type && !Protection_from_shape_changers
1067. 						    && !sensemon(mtmp))
1068. 		    stumble_onto_mimic(mtmp);
1069. 		else if (mtmp->mpeaceful && !Hallucination)
1070. 		    pline("Pardon me, %s.", m_monnam(mtmp));
1071. 		else
1072. 		    You("move right into %s.", mon_nam(mtmp));
1073. 		return;
1074. 	    }
1075. 	    if(flags.forcefight || !mtmp->mundetected || sensemon(mtmp) ||
1076. 		    ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL) &&
1077. 			!is_safepet(mtmp))){
1078. 		gethungry();
1079. 		if(wtcap >= HVY_ENCUMBER && moves%3) {
1080. 		    if (Upolyd && u.mh > 1) {
1081. 			u.mh--;
1082. 		    } else if (!Upolyd && u.uhp > 1) {
1083. 			u.uhp--;
1084. 		    } else {
1085. 			You("pass out from exertion!");
1086. 			exercise(A_CON, FALSE);
1087. 			fall_asleep(-10, FALSE);
1088. 		    }
1089. 		}
1090. 		if(multi < 0) return;	/* we just fainted */
1091. 
1092. 		/* try to attack; note that it might evade */
1093. 		/* also, we don't attack tame when _safepet_ */
1094. 		if(attack(mtmp)) return;
1095. 	    }
1096. 	}
1097. 
1098. 	/* specifying 'F' with no monster wastes a turn */
1099. 	if (flags.forcefight ||
1100. 	    /* remembered an 'I' && didn't use a move command */
1101. 	    (glyph_is_invisible(levl[x][y].glyph) && !flags.nopick)) {
1102. 		boolean expl = (Upolyd && attacktype(youmonst.data, AT_EXPL));
1103. 	    	char buf[BUFSZ];
1104. 		Sprintf(buf,"a vacant spot on the %s", surface(x,y));
1105. 		You("%s %s.",
1106. 		    expl ? "explode at" : "attack",
1107. 		    !Underwater ? "thin air" :
1108. 		    is_pool(x,y) ? "empty water" : buf);
1109. 		unmap_object(x, y); /* known empty -- remove 'I' if present */
1110. 		newsym(x, y);
1111. 		nomul(0);
1112. 		if (expl) {
1113. 		    u.mh = -1;		/* dead in the current form */
1114. 		    rehumanize();
1115. 		}
1116. 		return;
1117. 	}
1118. 	if (glyph_is_invisible(levl[x][y].glyph)) {
1119. 	    unmap_object(x, y);
1120. 	    newsym(x, y);
1121. 	}
1122. 	/* not attacking an animal, so we try to move */
1123. #ifdef STEED
1124. 	if (u.usteed && !u.usteed->mcanmove && (u.dx || u.dy)) {
1125. 		pline("%s won't move!", upstart(y_monnam(u.usteed)));
1126. 		nomul(0);
1127. 		return;
1128. 	} else
1129. #endif
1130. 	if(!youmonst.data->mmove) {
1131. 		You("are rooted %s.",
1132. 		    Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
1133. 		    "in place" : "to the ground");
1134. 		nomul(0);
1135. 		return;
1136. 	}
1137. 	if(u.utrap) {
1138. 		if(u.utraptype == TT_PIT) {
1139. 		    if (!rn2(2) && sobj_at(BOULDER, u.ux, u.uy)) {
1140. 			Your("%s gets stuck in a crevice.", body_part(LEG));
1141. 			display_nhwindow(WIN_MESSAGE, FALSE);
1142. 			clear_nhwindow(WIN_MESSAGE);
1143. 			You("free your %s.", body_part(LEG));
1144. 		    } else if (!(--u.utrap)) {
1145. 			You("%s to the edge of the pit.",
1146. 				(In_sokoban(&u.uz) && Levitation) ?
1147. 				"struggle against the air currents and float" :
1148. #ifdef STEED
1149. 				u.usteed ? "ride" :
1150. #endif
1151. 				"crawl");
1152. 			fill_pit(u.ux, u.uy);
1153. 			vision_full_recalc = 1;	/* vision limits change */
1154. 		    } else if (flags.verbose) {
1155. #ifdef STEED
1156. 			if (u.usteed)
1157. 			    Norep("%s is still in a pit.",
1158. 				  upstart(y_monnam(u.usteed)));
1159. 			else
1160. #endif
1161. 			Norep( (Hallucination && !rn2(5)) ?
1162. 				"You've fallen, and you can't get up." :
1163. 				"You are still in a pit." );
1164. 		    }
1165. 		} else if (u.utraptype == TT_LAVA) {
1166. 		    if(flags.verbose) {
1167. 			predicament = "stuck in the lava";
1168. #ifdef STEED
1169. 			if (u.usteed)
1170. 			    Norep("%s is %s.", upstart(y_monnam(u.usteed)),
1171. 				  predicament);
1172. 			else
1173. #endif
1174. 			Norep("You are %s.", predicament);
1175. 		    }
1176. 		    if(!is_lava(x,y)) {
1177. 			u.utrap--;
1178. 			if((u.utrap & 0xff) == 0) {
1179. #ifdef STEED
1180. 			    if (u.usteed)
1181. 				You("lead %s to the edge of the lava.",
1182. 				    y_monnam(u.usteed));
1183. 			    else
1184. #endif
1185. 			     You("pull yourself to the edge of the lava.");
1186. 			    u.utrap = 0;
1187. 			}
1188. 		    }
1189. 		    u.umoved = TRUE;
1190. 		} else if (u.utraptype == TT_WEB) {
1191. 		    if(uwep && uwep->oartifact == ART_STING) {
1192. 			u.utrap = 0;
1193. 			pline("Sting cuts through the web!");
1194. 			return;
1195. 		    }
1196. 		    if(--u.utrap) {
1197. 			if(flags.verbose) {
1198. 			    predicament = "stuck to the web";
1199. #ifdef STEED
1200. 			    if (u.usteed)
1201. 				Norep("%s is %s.", upstart(y_monnam(u.usteed)),
1202. 				      predicament);
1203. 			    else
1204. #endif
1205. 			    Norep("You are %s.", predicament);
1206. 			}
1207. 		    } else {
1208. #ifdef STEED
1209. 			if (u.usteed)
1210. 			    pline("%s breaks out of the web.",
1211. 				  upstart(y_monnam(u.usteed)));
1212. 			else
1213. #endif
1214. 			You("disentangle yourself.");
1215. 		    }
1216. 		} else if (u.utraptype == TT_INFLOOR) {
1217. 		    if(--u.utrap) {
1218. 			if(flags.verbose) {
1219. 			    predicament = "stuck in the";
1220. #ifdef STEED
1221. 			    if (u.usteed)
1222. 				Norep("%s is %s %s.",
1223. 				      upstart(y_monnam(u.usteed)),
1224. 				      predicament, surface(u.ux, u.uy));
1225. 			    else
1226. #endif
1227. 			    Norep("You are %s %s.", predicament,
1228. 				  surface(u.ux, u.uy));
1229. 			}
1230. 		    } else {
1231. #ifdef STEED
1232. 			if (u.usteed)
1233. 			    pline("%s finally wiggles free.",
1234. 				  upstart(y_monnam(u.usteed)));
1235. 			else
1236. #endif
1237. 			You("finally wiggle free.");
1238. 		    }
1239. 		} else {
1240. 		    if(flags.verbose) {
1241. 			predicament = "caught in a bear trap";
1242. #ifdef STEED
1243. 			if (u.usteed)
1244. 			    Norep("%s is %s.", upstart(y_monnam(u.usteed)),
1245. 				  predicament);
1246. 			else
1247. #endif
1248. 			Norep("You are %s.", predicament);
1249. 		    }
1250. 		    if((u.dx && u.dy) || !rn2(5)) u.utrap--;
1251. 		}
1252. 		return;
1253. 	}
1254. 
1255. 	if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, DO_MOVE)) {
1256. 	    flags.move = 0;
1257. 	    nomul(0);
1258. 	    return;
1259. 	}
1260. 
1261. 	/* Move ball and chain.  */
1262. 	if (Punished)
1263. 	    if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy,
1264. 			&cause_delay, TRUE))
1265. 		return;
1266. 
1267. 	/* Check regions entering/leaving */
1268. 	if (!in_out_region(x,y))
1269. 	    return;
1270. 
1271.  	/* now move the hero */
1272. 	mtmp = m_at(x, y);
1273. 	u.ux += u.dx;
1274. 	u.uy += u.dy;
1275. #ifdef STEED
1276. 	/* Move your steed, too */
1277. 	if (u.usteed) {
1278. 		u.usteed->mx = u.ux;
1279. 		u.usteed->my = u.uy;
1280. 		exercise_steed();
1281. 	}
1282. #endif
1283. 
1284. 	/*
1285. 	 * If safepet at destination then move the pet to the hero's
1286. 	 * previous location using the same conditions as in attack().
1287. 	 * there are special extenuating circumstances:
1288. 	 * (1) if the pet dies then your god angers,
1289. 	 * (2) if the pet gets trapped then your god may disapprove,
1290. 	 * (3) if the pet was already trapped and you attempt to free it
1291. 	 * not only do you encounter the trap but you may frighten your
1292. 	 * pet causing it to go wild!  moral: don't abuse this privilege.
1293. 	 *
1294. 	 * Ceiling-hiding pets are skipped by this section of code, to
1295. 	 * be caught by the normal falling-monster code.
1296. 	 */
1297. 	if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
1298. 	    /* if trapped, there's a chance the pet goes wild */
1299. 	    if (mtmp->mtrapped) {
1300. 		if (!rn2(mtmp->mtame)) {
1301. 		    mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
1302. 		    if (mtmp->mleashed) m_unleash(mtmp, TRUE);
1303. 		    growl(mtmp);
1304. 		} else {
1305. 		    yelp(mtmp);
1306. 		}
1307. 	    }
1308. 	    mtmp->mundetected = 0;
1309. 	    if (mtmp->m_ap_type) seemimic(mtmp);
1310. 	    else if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my);
1311. 
1312. 	    if (mtmp->mtrapped &&
1313. 		    (trap = t_at(mtmp->mx, mtmp->my)) != 0 &&
1314. 		    (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) &&
1315. 		    sobj_at(BOULDER, trap->tx, trap->ty)) {
1316. 		/* can't swap places with pet pinned in a pit by a boulder */
1317. 		u.ux = u.ux0,  u.uy = u.uy0;	/* didn't move after all */
1318. 	    } else if (u.ux0 != x && u.uy0 != y &&
1319. 		       bad_rock(mtmp->data, x, u.uy0) &&
1320. 		       bad_rock(mtmp->data, u.ux0, y) &&
1321. 		       (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
1322. 		/* can't swap places when pet won't fit thru the opening */
1323. 		u.ux = u.ux0,  u.uy = u.uy0;	/* didn't move after all */
1324. 		You("stop.  %s won't fit through.", upstart(y_monnam(mtmp)));
1325. 	    } else {
1326. 		char pnambuf[BUFSZ];
1327. 
1328. 		/* save its current description in case of polymorph */
1329. 		Strcpy(pnambuf, y_monnam(mtmp));
1330. 		mtmp->mtrapped = 0;
1331. 		remove_monster(x, y);
1332. 		place_monster(mtmp, u.ux0, u.uy0);
1333. 
1334. 		/* check for displacing it into pools and traps */
1335. 		switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
1336. 		case 0:
1337. 		    You("%s %s.", mtmp->mtame ? "displaced" : "frightened",
1338. 			pnambuf);
1339. 		    break;
1340. 		case 1:		/* trapped */
1341. 		case 3:		/* changed levels */
1342. 		    /* there's already been a trap message, reinforce it */
1343. 		    abuse_dog(mtmp);
1344. 		    adjalign(-3);
1345. 		    break;
1346. 		case 2:
1347. 		    /* it may have drowned or died.  that's no way to
1348. 		     * treat a pet!  your god gets angry.
1349. 		     */
1350. 		    if (rn2(4)) {
1351. 			You_feel("guilty about losing your pet like this.");
1352. 			u.ugangr++;
1353. 			adjalign(-15);
1354. 		    }
1355. 
1356. 		    /* you killed your pet by direct action.
1357. 		     * minliquid and mintrap don't know to do this
1358. 		     */
1359. 		    u.uconduct.killer++;
1360. 		    break;
1361. 		default:
1362. 		    pline("that's strange, unknown mintrap result!");
1363. 		    break;
1364. 		}
1365. 	    }
1366. 	}
1367. 
1368. 	reset_occupations();
1369. 	if (flags.run) {
1370. 	    if ( flags.run < 8 )
1371. 		if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) ||
1372. 			IS_FURNITURE(tmpr->typ))
1373. 		    nomul(0);
1374. 	}
1375. 
1376. 	if (hides_under(youmonst.data))
1377. 	    u.uundetected = OBJ_AT(u.ux, u.uy);
1378. 	else if (youmonst.data->mlet == S_EEL)
1379. 	    u.uundetected = is_pool(u.ux, u.uy) && !Is_waterlevel(&u.uz);
1380. 	else if (u.dx || u.dy)
1381. 	    u.uundetected = 0;
1382. 
1383. 	/*
1384. 	 * Mimics (or whatever) become noticeable if they move and are
1385. 	 * imitating something that doesn't move.  We could extend this
1386. 	 * to non-moving monsters...
1387. 	 */
1388. 	if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
1389. 				|| youmonst.m_ap_type == M_AP_FURNITURE))
1390. 	    youmonst.m_ap_type = M_AP_NOTHING;
1391. 
1392. 	check_leash(u.ux0,u.uy0);
1393. 
1394. 	if(u.ux0 != u.ux || u.uy0 != u.uy) {
1395. 	    u.umoved = TRUE;
1396. 	    /* Clean old position -- vision_recalc() will print our new one. */
1397. 	    newsym(u.ux0,u.uy0);
1398. 	    /* Since the hero has moved, adjust what can be seen/unseen. */
1399. 	    vision_recalc(1);	/* Do the work now in the recover time. */
1400. 	    invocation_message();
1401. 	}
1402. 
1403. 	if (Punished)				/* put back ball and chain */
1404. 	    move_bc(0,bc_control,ballx,bally,chainx,chainy);
1405. 
1406. 	spoteffects(TRUE);
1407. 
1408. 	/* delay next move because of ball dragging */
1409. 	/* must come after we finished picking up, in spoteffects() */
1410. 	if (cause_delay) {
1411. 	    nomul(-2);
1412. 	    nomovemsg = "";
1413. 	}
1414. 
1415. 	if (flags.run && iflags.runmode != RUN_TPORT) {
1416. 	    /* display every step or every 7th step depending upon mode */
1417. 	    if (iflags.runmode != RUN_LEAP || !(moves % 7L)) {
1418. 		if (flags.time) flags.botl = 1;
1419. 		curs_on_u();
1420. 		delay_output();
1421. 		if (iflags.runmode == RUN_CRAWL) {
1422. 		    delay_output();
1423. 		    delay_output();
1424. 		    delay_output();
1425. 		    delay_output();
1426. 		}
1427. 	    }
1428. 	}
1429. }
1430. 

invocation_message Edit

1431. void
1432. invocation_message()
1433. {
1434. 	/* a special clue-msg when on the Invocation position */
1435. 	if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
1436. 	    char buf[BUFSZ];
1437. 	    struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
1438. 
1439. 	    nomul(0);		/* stop running or travelling */
1440. #ifdef STEED
1441. 	    if (u.usteed) Sprintf(buf, "beneath %s", y_monnam(u.usteed));
1442. 	    else
1443. #endif
1444. 	    if (Levitation || Flying) Strcpy(buf, "beneath you");
1445. 	    else Sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
1446. 
1447. 	    You_feel("a strange vibration %s.", buf);
1448. 	    if (otmp && otmp->spe == 7 && otmp->lamplit)
1449. 		pline("%s %s!", The(xname(otmp)),
1450. 		    Blind ? "throbs palpably" : "glows with a strange light");
1451. 	}
1452. }
1453. 
1454. #endif /* OVL3 */

spoteffects Edit

1455. #ifdef OVL2
1456. 
1457. void
1458. spoteffects(pick)
1459. boolean pick;
1460. {
1461. 	register struct monst *mtmp;
1462. 
1463. 	if(u.uinwater) {
1464. 		int was_underwater;
1465. 
1466. 		if (!is_pool(u.ux,u.uy)) {
1467. 			if (Is_waterlevel(&u.uz))
1468. 				You("pop into an air bubble.");
1469. 			else if (is_lava(u.ux, u.uy))
1470. 				You("leave the water...");	/* oops! */
1471. 			else
1472. 				You("are on solid %s again.",
1473. 				    is_ice(u.ux, u.uy) ? "ice" : "land");
1474. 		}
1475. 		else if (Is_waterlevel(&u.uz))
1476. 			goto stillinwater;
1477. 		else if (Levitation)
1478. 			You("pop out of the water like a cork!");
1479. 		else if (Flying)
1480. 			You("fly out of the water.");
1481. 		else if (Wwalking)
1482. 			You("slowly rise above the surface.");
1483. 		else
1484. 			goto stillinwater;
1485. 		was_underwater = Underwater && !Is_waterlevel(&u.uz);
1486. 		u.uinwater = 0;		/* leave the water */
1487. 		if (was_underwater) {	/* restore vision */
1488. 			docrt();
1489. 			vision_full_recalc = 1;
1490. 		}
1491. 	}
1492. stillinwater:;
1493. 	if (!Levitation && !u.ustuck && !Flying) {
1494. 	    /* limit recursive calls through teleds() */
1495. 	    if (is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) {
1496. #ifdef STEED
1497. 		if (u.usteed && !is_flyer(u.usteed->data) &&
1498. 			!is_floater(u.usteed->data) &&
1499. 			!is_clinger(u.usteed->data)) {
1500. 		    dismount_steed(Underwater ?
1501. 			    DISMOUNT_FELL : DISMOUNT_GENERIC);
1502. 		    /* dismount_steed() -> float_down() -> pickup() */
1503. 		    if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz))
1504. 			pick = FALSE;
1505. 		} else
1506. #endif
1507. 		if (is_lava(u.ux, u.uy)) {
1508. 		    if (lava_effects()) return;
1509. 		} else if (!Wwalking && drown())
1510. 		    return;
1511. 	    }
1512. 	}
1513. 	check_special_room(FALSE);
1514. #ifdef SINKS
1515. 	if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
1516. 		dosinkfall();
1517. #endif
1518. 	if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
1519. 		struct trap *trap = t_at(u.ux, u.uy);
1520. 		boolean pit;
1521. 		pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
1522. 		if (trap && pit)
1523. 			dotrap(trap, 0);	/* fall into pit */
1524. 		if (pick) (void) pickup(1);
1525. 		if (trap && !pit)
1526. 			dotrap(trap, 0);	/* fall into arrow trap, etc. */
1527. 	}
1528. 	if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
1529. 		mtmp->mundetected = mtmp->msleeping = 0;
1530. 		switch(mtmp->data->mlet) {
1531. 		    case S_PIERCER:
1532. 			pline("%s suddenly drops from the %s!",
1533. 			      Amonnam(mtmp), ceiling(u.ux,u.uy));
1534. 			if(mtmp->mtame) /* jumps to greet you, not attack */
1535. 			    ;
1536. 			else if(uarmh && is_metallic(uarmh))
1537. 			    pline("Its blow glances off your helmet.");
1538. 			else if (u.uac + 3 <= rnd(20))
1539. 			    You("are almost hit by %s!",
1540. 				x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
1541. 			else {
1542. 			    int dmg;
1543. 			    You("are hit by %s!",
1544. 				x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
1545. 			    dmg = d(4,6);
1546. 			    if(Half_physical_damage) dmg = (dmg+1) / 2;
1547. 			    mdamageu(mtmp, dmg);
1548. 			}
1549. 			break;
1550. 		    default:	/* monster surprises you. */
1551. 			if(mtmp->mtame)
1552. 			    pline("%s jumps near you from the %s.",
1553. 					Amonnam(mtmp), ceiling(u.ux,u.uy));
1554. 			else if(mtmp->mpeaceful) {
1555. 				You("surprise %s!",
1556. 				    Blind && !sensemon(mtmp) ?
1557. 				    something : a_monnam(mtmp));
1558. 				mtmp->mpeaceful = 0;
1559. 			} else
1560. 			    pline("%s attacks you by surprise!",
1561. 					Amonnam(mtmp));
1562. 			break;
1563. 		}
1564. 		mnexto(mtmp); /* have to move the monster */
1565. 	}
1566. }
1567. 

monstinroom Edit

1568. STATIC_OVL boolean
1569. monstinroom(mdat,roomno)
1570. struct permonst *mdat;
1571. int roomno;
1572. {
1573. 	register struct monst *mtmp;
1574. 
1575. 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
1576. 		if(!DEADMONSTER(mtmp) && mtmp->data == mdat &&
1577. 		   index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
1578. 			return(TRUE);
1579. 	return(FALSE);
1580. }
1581. 

in_rooms Edit

in_rooms() takes three parameters, an x,y coordinate and a room type, and returns a string of chars, which will contain indexes to rooms-array (adjusted by ROOMOFFSET). The x,y location is in the rooms pointed to by those characters. If the location is not in any room, a zero-length string is returned.

For example, the following code tells the player the size of one of the shops he is in:

char roomlst = *in_rooms(u.ux, u.uy, SHOPBASE);
if (roomlst && roomlst[0] >= ROOMOFFSET) {
  int rmno = roomlst[0] - ROOMOFFSET;
  pline("Shop size: %i,%i", rooms[rmno].hx - rooms[rmno].lx + 1, rooms[rmno].hy - rooms[rmno].ly + 1);
}
1582. char *
1583. in_rooms(x, y, typewanted)
1584. register xchar x, y;
1585. register int typewanted;
1586. {
1587. 	static char buf[5];
1588. 	char rno, *ptr = &buf[4];
1589. 	int typefound, min_x, min_y, max_x, max_y_offset, step;
1590. 	register struct rm *lev;
1591. 
1592. #define goodtype(rno) (!typewanted || \
1593. 	     ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) || \
1594. 	     ((typewanted == SHOPBASE) && (typefound > SHOPBASE))) \
1595. 
1596. 	switch (rno = levl[x][y].roomno) {
1597. 		case NO_ROOM:
1598. 			return(ptr);
1599. 		case SHARED:
1600. 			step = 2;
1601. 			break;
1602. 		case SHARED_PLUS:
1603. 			step = 1;
1604. 			break;
1605. 		default:			/* i.e. a regular room # */
1606. 			if (goodtype(rno))
1607. 				*(--ptr) = rno;
1608. 			return(ptr);
1609. 	}
1610. 
1611. 	min_x = x - 1;
1612. 	max_x = x + 1;
1613. 	if (x < 1)
1614. 		min_x += step;
1615. 	else
1616. 	if (x >= COLNO)
1617. 		max_x -= step;
1618. 
1619. 	min_y = y - 1;
1620. 	max_y_offset = 2;
1621. 	if (min_y < 0) {
1622. 		min_y += step;
1623. 		max_y_offset -= step;
1624. 	} else
1625. 	if ((min_y + max_y_offset) >= ROWNO)
1626. 		max_y_offset -= step;
1627. 
1628. 	for (x = min_x; x <= max_x; x += step) {
1629. 		lev = &levl[x][min_y];
1630. 		y = 0;
1631. 		if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
1632. 		    !index(ptr, rno) && goodtype(rno))
1633. 			*(--ptr) = rno;
1634. 		y += step;
1635. 		if (y > max_y_offset)
1636. 			continue;
1637. 		if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
1638. 		    !index(ptr, rno) && goodtype(rno))
1639. 			*(--ptr) = rno;
1640. 		y += step;
1641. 		if (y > max_y_offset)
1642. 			continue;
1643. 		if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
1644. 		    !index(ptr, rno) && goodtype(rno))
1645. 			*(--ptr) = rno;
1646. 	}
1647. 	return(ptr);
1648. }
1649. 

in_town Edit

1650. /* is (x,y) in a town? */
1651. boolean
1652. in_town(x, y)
1653. register int x, y;
1654. {
1655. 	s_level *slev = Is_special(&u.uz);
1656. 	register struct mkroom *sroom;
1657. 	boolean has_subrooms = FALSE;
1658. 
1659. 	if (!slev || !slev->flags.town) return FALSE;
1660. 
1661. 	/*
1662. 	 * See if (x,y) is in a room with subrooms, if so, assume it's the
1663. 	 * town.  If there are no subrooms, the whole level is in town.
1664. 	 */
1665. 	for (sroom = &rooms[0]; sroom->hx > 0; sroom++) {
1666. 	    if (sroom->nsubrooms > 0) {
1667. 		has_subrooms = TRUE;
1668. 		if (inside_room(sroom, x, y)) return TRUE;
1669. 	    }
1670. 	}
1671. 
1672. 	return !has_subrooms;
1673. }
1674. 

move_update Edit

1675. STATIC_OVL void
1676. move_update(newlev)
1677. register boolean newlev;
1678. {
1679. 	char *ptr1, *ptr2, *ptr3, *ptr4;
1680. 
1681. 	Strcpy(u.urooms0, u.urooms);
1682. 	Strcpy(u.ushops0, u.ushops);
1683. 	if (newlev) {
1684. 		u.urooms[0] = '\0';
1685. 		u.uentered[0] = '\0';
1686. 		u.ushops[0] = '\0';
1687. 		u.ushops_entered[0] = '\0';
1688. 		Strcpy(u.ushops_left, u.ushops0);
1689. 		return;
1690. 	}
1691. 	Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
1692. 
1693. 	for (ptr1 = &u.urooms[0],
1694. 	     ptr2 = &u.uentered[0],
1695. 	     ptr3 = &u.ushops[0],
1696. 	     ptr4 = &u.ushops_entered[0];
1697. 	     *ptr1; ptr1++) {
1698. 		if (!index(u.urooms0, *ptr1))
1699. 			*(ptr2++) = *ptr1;
1700. 		if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
1701. 			*(ptr3++) = *ptr1;
1702. 			if (!index(u.ushops0, *ptr1))
1703. 				*(ptr4++) = *ptr1;
1704. 		}
1705. 	}
1706. 	*ptr2 = '\0';
1707. 	*ptr3 = '\0';
1708. 	*ptr4 = '\0';
1709. 
1710. 	/* filter u.ushops0 -> u.ushops_left */
1711. 	for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
1712. 		if (!index(u.ushops, *ptr1))
1713. 			*(ptr2++) = *ptr1;
1714. 	*ptr2 = '\0';
1715. }
1716. 

check_special_room Edit

1717. void
1718. check_special_room(newlev)
1719. register boolean newlev;
1720. {
1721. 	register struct monst *mtmp;
1722. 	char *ptr;
1723. 
1724. 	move_update(newlev);
1725. 
1726. 	if (*u.ushops0)
1727. 	    u_left_shop(u.ushops_left, newlev);
1728. 
1729. 	if (!*u.uentered && !*u.ushops_entered)		/* implied by newlev */
1730. 	    return;		/* no entrance messages necessary */
1731. 
1732. 	/* Did we just enter a shop? */
1733. 	if (*u.ushops_entered)
1734. 	    u_entered_shop(u.ushops_entered);
1735. 
1736. 	for (ptr = &u.uentered[0]; *ptr; ptr++) {
1737. 	    register int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
1738. 
1739. 	    /* Did we just enter some other special room? */
1740. 	    /* vault.c insists that a vault remain a VAULT,
1741. 	     * and temples should remain TEMPLEs,
1742. 	     * but everything else gives a message only the first time */
1743. 	    switch (rt) {
1744. 		case ZOO:
1745. 		    pline("Welcome to David's treasure zoo!");
1746. 		    break;
1747. 		case SWAMP:
1748. 		    pline("It %s rather %s down here.",
1749. 			  Blind ? "feels" : "looks",
1750. 			  Blind ? "humid" : "muddy");
1751. 		    break;
1752. 		case COURT:
1753. 		    You("enter an opulent throne room!");
1754. 		    break;
1755. 		case LEPREHALL:
1756. 		    You("enter a leprechaun hall!");
1757. 		    break;
1758. 		case MORGUE:
1759. 		    if(midnight()) {
1760. 			const char *run = locomotion(youmonst.data, "Run");
1761. 			pline("%s away!  %s away!", run, run);
1762. 		    } else
1763. 			You("have an uncanny feeling...");
1764. 		    break;
1765. 		case BEEHIVE:
1766. 		    You("enter a giant beehive!");
1767. 		    break;
1768. 		case COCKNEST:
1769. 		    You("enter a disgusting nest!");
1770. 		    break;
1771. 		case ANTHOLE:
1772. 		    You("enter an anthole!");
1773. 		    break;
1774. 		case BARRACKS:
1775. 		    if(monstinroom(&mons[PM_SOLDIER], roomno) ||
1776. 			monstinroom(&mons[PM_SERGEANT], roomno) ||
1777. 			monstinroom(&mons[PM_LIEUTENANT], roomno) ||
1778. 			monstinroom(&mons[PM_CAPTAIN], roomno))
1779. 			You("enter a military barracks!");
1780. 		    else
1781. 			You("enter an abandoned barracks.");
1782. 		    break;
1783. 		case DELPHI:
1784. 		    if(monstinroom(&mons[PM_ORACLE], roomno))
1785. 			verbalize("%s, %s, welcome to Delphi!",
1786. 					Hello((struct monst *) 0), plname);
1787. 		    break;
1788. 		case TEMPLE:
1789. 		    intemple(roomno + ROOMOFFSET);
1790. 		    /* fall through */
1791. 		default:
1792. 		    rt = 0;
1793. 	    }
1794. 
1795. 	    if (rt != 0) {
1796. 		rooms[roomno].rtype = OROOM;
1797. 		if (!search_special(rt)) {
1798. 			/* No more room of that type */
1799. 			switch(rt) {
1800. 			    case COURT:
1801. 				level.flags.has_court = 0;
1802. 				break;
1803. 			    case SWAMP:
1804. 				level.flags.has_swamp = 0;
1805. 				break;
1806. 			    case MORGUE:
1807. 				level.flags.has_morgue = 0;
1808. 				break;
1809. 			    case ZOO:
1810. 				level.flags.has_zoo = 0;
1811. 				break;
1812. 			    case BARRACKS:
1813. 				level.flags.has_barracks = 0;
1814. 				break;
1815. 			    case TEMPLE:
1816. 				level.flags.has_temple = 0;
1817. 				break;
1818. 			    case BEEHIVE:
1819. 				level.flags.has_beehive = 0;
1820. 				break;
1821. 			}
1822. 		}
1823. 		if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO)
1824. 		    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
1825. 			if (!DEADMONSTER(mtmp) && !Stealth && !rn2(3)) mtmp->msleeping = 0;
1826. 	    }
1827. 	}
1828. 
1829. 	return;
1830. }
1831. 
1832. #endif /* OVL2 */

dopickup Edit

1833. #ifdef OVLB
1834. 
1835. int
1836. dopickup()
1837. {
1838. 	int count;
1839. 	struct trap *traphere = t_at(u.ux, u.uy);
1840.  	/* awful kludge to work around parse()'s pre-decrement */
1841. 	count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
1842. 	multi = 0;	/* always reset */
1843. 	/* uswallow case added by GAN 01/29/87 */
1844. 	if(u.uswallow) {
1845. 	    if (!u.ustuck->minvent) {
1846. 		if (is_animal(u.ustuck->data)) {
1847. 		    You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck)));
1848. 		    pline("But it's kind of slimy, so you drop it.");
1849. 		} else
1850. 		    You("don't %s anything in here to pick up.",
1851. 			  Blind ? "feel" : "see");
1852. 		return(1);
1853. 	    } else {
1854. 	    	int tmpcount = -count;
1855. 		return loot_mon(u.ustuck, &tmpcount, (boolean *)0);
1856. 	    }
1857. 	}
1858. 	if(is_pool(u.ux, u.uy)) {
1859. 	    if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
1860. 			|| (Flying && !Breathless)) {
1861. 		You("cannot dive into the water to pick things up.");
1862. 		return(0);
1863. 	    } else if (!Underwater) {
1864. 		You_cant("even see the bottom, let alone pick up %s.",
1865. 				something);
1866. 		return(0);
1867. 	    }
1868. 	}
1869. 	if (is_lava(u.ux, u.uy)) {
1870. 	    if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
1871. 			|| (Flying && !Breathless)) {
1872. 		You_cant("reach the bottom to pick things up.");
1873. 		return(0);
1874. 	    } else if (!likes_lava(youmonst.data)) {
1875. 		You("would burn to a crisp trying to pick things up.");
1876. 		return(0);
1877. 	    }
1878. 	}
1879. 	if(!OBJ_AT(u.ux, u.uy)) {
1880. 		There("is nothing here to pick up.");
1881. 		return(0);
1882. 	}
1883. 	if (!can_reach_floor()) {
1884. #ifdef STEED
1885. 		if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
1886. 		    You("aren't skilled enough to reach from %s.",
1887. 			y_monnam(u.usteed));
1888. 		else
1889. #endif
1890. 		You("cannot reach the %s.", surface(u.ux,u.uy));
1891. 		return(0);
1892. 	}
1893. 
1894.  	if (traphere && traphere->tseen) {
1895. 		/* Allow pickup from holes and trap doors that you escaped from
1896. 		 * because that stuff is teetering on the edge just like you, but
1897. 		 * not pits, because there is an elevation discrepancy with stuff
1898. 		 * in pits.
1899. 		 */
1900. 		if ((traphere->ttyp == PIT || traphere->ttyp == SPIKED_PIT) &&
1901. 		     (!u.utrap || (u.utrap && u.utraptype != TT_PIT))) {
1902. 			You("cannot reach the bottom of the pit.");
1903. 			return(0);
1904. 		}
1905. 	}
1906. 
1907. 	return (pickup(-count));
1908. }
1909. 
1910. #endif /* OVLB */

lookaround Edit

1911. #ifdef OVL2
1912. 
1913. /* stop running if we see something interesting */
1914. /* turn around a corner if that is the only way we can proceed */
1915. /* do not turn left or right twice */
1916. void
1917. lookaround()
1918. {
1919.     register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
1920.     register int corrct = 0, noturn = 0;
1921.     register struct monst *mtmp;
1922.     register struct trap *trap;
1923. 
1924.     /* Grid bugs stop if trying to move diagonal, even if blind.  Maybe */
1925.     /* they polymorphed while in the middle of a long move. */
1926.     if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) {
1927. 	nomul(0);
1928. 	return;
1929.     }
1930. 
1931.     if(Blind || flags.run == 0) return;
1932.     for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) {
1933. 	if(!isok(x,y)) continue;
1934. 
1935. 	if(u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy) continue;
1936. 
1937. 	if(x == u.ux && y == u.uy) continue;
1938. 
1939. 	if((mtmp = m_at(x,y)) &&
1940. 		    mtmp->m_ap_type != M_AP_FURNITURE &&
1941. 		    mtmp->m_ap_type != M_AP_OBJECT &&
1942. 		    (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
1943. 	    if((flags.run != 1 && !mtmp->mtame)
1944. 					|| (x == u.ux+u.dx && y == u.uy+u.dy))
1945. 		goto stop;
1946. 	}
1947. 
1948. 	if (levl[x][y].typ == STONE) continue;
1949. 	if (x == u.ux-u.dx && y == u.uy-u.dy) continue;
1950. 
1951. 	if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) ||
1952. 	    IS_AIR(levl[x][y].typ))
1953. 	    continue;
1954. 	else if (closed_door(x,y) ||
1955. 		 (mtmp && mtmp->m_ap_type == M_AP_FURNITURE &&
1956. 		  (mtmp->mappearance == S_hcdoor ||
1957. 		   mtmp->mappearance == S_vcdoor))) {
1958. 	    if(x != u.ux && y != u.uy) continue;
1959. 	    if(flags.run != 1) goto stop;
1960. 	    goto bcorr;
1961. 	} else if (levl[x][y].typ == CORR) {
1962. bcorr:
1963. 	    if(levl[u.ux][u.uy].typ != ROOM) {
1964. 		if(flags.run == 1 || flags.run == 3 || flags.run == 8) {
1965. 		    i = dist2(x,y,u.ux+u.dx,u.uy+u.dy);
1966. 		    if(i > 2) continue;
1967. 		    if(corrct == 1 && dist2(x,y,x0,y0) != 1)
1968. 			noturn = 1;
1969. 		    if(i < i0) {
1970. 			i0 = i;
1971. 			x0 = x;
1972. 			y0 = y;
1973. 			m0 = mtmp ? 1 : 0;
1974. 		    }
1975. 		}
1976. 		corrct++;
1977. 	    }
1978. 	    continue;
1979. 	} else if ((trap = t_at(x,y)) && trap->tseen) {
1980. 	    if(flags.run == 1) goto bcorr;	/* if you must */
1981. 	    if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
1982. 	    continue;
1983. 	} else if (is_pool(x,y) || is_lava(x,y)) {
1984. 	    /* water and lava only stop you if directly in front, and stop
1985. 	     * you even if you are running
1986. 	     */
1987. 	    if(!Levitation && !Flying && !is_clinger(youmonst.data) &&
1988. 				x == u.ux+u.dx && y == u.uy+u.dy)
1989. 			/* No Wwalking check; otherwise they'd be able
1990. 			 * to test boots by trying to SHIFT-direction
1991. 			 * into a pool and seeing if the game allowed it
1992. 			 */
1993. 			goto stop;
1994. 	    continue;
1995. 	} else {		/* e.g. objects or trap or stairs */
1996. 	    if(flags.run == 1) goto bcorr;
1997. 	    if(flags.run == 8) continue;
1998. 	    if(mtmp) continue;		/* d */
1999. 	    if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) ||
2000. 	       ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
2001. 	       continue;
2002. 	}
2003. stop:
2004. 	nomul(0);
2005. 	return;
2006.     } /* end for loops */
2007. 
2008.     if(corrct > 1 && flags.run == 2) goto stop;
2009.     if((flags.run == 1 || flags.run == 3 || flags.run == 8) &&
2010. 	!noturn && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1)))
2011.     {
2012. 	/* make sure that we do not turn too far */
2013. 	if(i0 == 2) {
2014. 	    if(u.dx == y0-u.uy && u.dy == u.ux-x0)
2015. 		i = 2;		/* straight turn right */
2016. 	    else
2017. 		i = -2;		/* straight turn left */
2018. 	} else if(u.dx && u.dy) {
2019. 	    if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
2020. 		i = -1;		/* half turn left */
2021. 	    else
2022. 		i = 1;		/* half turn right */
2023. 	} else {
2024. 	    if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy))
2025. 		i = 1;		/* half turn right */
2026. 	    else
2027. 		i = -1;		/* half turn left */
2028. 	}
2029. 
2030. 	i += u.last_str_turn;
2031. 	if(i <= 2 && i >= -2) {
2032. 	    u.last_str_turn = i;
2033. 	    u.dx = x0-u.ux;
2034. 	    u.dy = y0-u.uy;
2035. 	}
2036.     }
2037. }
2038. 

monster_nearby Edit

2039. /* something like lookaround, but we are not running */
2040. /* react only to monsters that might hit us */
2041. int
2042. monster_nearby()
2043. {
2044. 	register int x,y;
2045. 	register struct monst *mtmp;
2046. 
2047. 	/* Also see the similar check in dochugw() in monmove.c */
2048. 	for(x = u.ux-1; x <= u.ux+1; x++)
2049. 	    for(y = u.uy-1; y <= u.uy+1; y++) {
2050. 		if(!isok(x,y)) continue;
2051. 		if(x == u.ux && y == u.uy) continue;
2052. 		if((mtmp = m_at(x,y)) &&
2053. 		   mtmp->m_ap_type != M_AP_FURNITURE &&
2054. 		   mtmp->m_ap_type != M_AP_OBJECT &&
2055. 		   (!mtmp->mpeaceful || Hallucination) &&
2056. 		   (!is_hider(mtmp->data) || !mtmp->mundetected) &&
2057. 		   !noattacks(mtmp->data) &&
2058. 		   mtmp->mcanmove && !mtmp->msleeping &&  /* aplvax!jcn */
2059. 		   !onscary(u.ux, u.uy, mtmp) &&
2060. 		   canspotmon(mtmp))
2061. 			return(1);
2062. 	}
2063. 	return(0);
2064. }
2065. 

nomul Edit

nomul() takes one parameter, a negative value, a number of turns to wait. This is used when the hero does some action that takes multiple turns to complete. For example, to wait 3 turns: nomul(-3);

If the parameter is 0, then the currently active multiturn action is "cancelled" and player will be able to act on the next turn.

2066. void
2067. nomul(nval)
2068. 	register int nval;
2069. {
2070. 	if(multi < nval) return;	/* This is a bug fix by ab@unido */
2071. 	u.uinvulnerable = FALSE;	/* Kludge to avoid ctrl-C bug -dlc */
2072. 	u.usleep = 0;
2073. 	multi = nval;
2074. 	flags.travel = iflags.travel1 = flags.mv = flags.run = 0;
2075. }
2076. 

unmul Edit

2077. /* called when a non-movement, multi-turn action has completed */
2078. void
2079. unmul(msg_override)
2080. const char *msg_override;
2081. {
2082. 	multi = 0;	/* caller will usually have done this already */
2083. 	if (msg_override) nomovemsg = msg_override;
2084. 	else if (!nomovemsg) nomovemsg = You_can_move_again;
2085. 	if (*nomovemsg) pline(nomovemsg);
2086. 	nomovemsg = 0;
2087. 	u.usleep = 0;
2088. 	if (afternmv) (*afternmv)();
2089. 	afternmv = 0;
2090. }
2091. 
2092. #endif /* OVL2 */

maybe_wail Edit

2093. #ifdef OVL1
2094. 
2095. STATIC_OVL void
2096. maybe_wail()
2097. {
2098.     static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES,
2099. 			      SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES,
2100. 			      TELEPORT_CONTROL, STEALTH, FAST, INVIS };
2101. 
2102.     if (moves <= wailmsg + 50) return;
2103. 
2104.     wailmsg = moves;
2105.     if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) {
2106. 	const char *who;
2107. 	int i, powercnt;
2108. 
2109. 	who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ?
2110. 		urole.name.m : "Elf";
2111. 	if (u.uhp == 1) {
2112. 	    pline("%s is about to die.", who);
2113. 	} else {
2114. 	    for (i = 0, powercnt = 0; i < SIZE(powers); ++i)
2115. 		if (u.uprops[powers[i]].intrinsic & INTRINSIC) ++powercnt;
2116. 
2117. 	    pline(powercnt >= 4 ? "%s, all your powers will be lost..."
2118. 				: "%s, your life force is running out.", who);
2119. 	}
2120.     } else {
2121. 	You_hear(u.uhp == 1 ? "the wailing of the Banshee..."
2122. 			    : "the howling of the CwnAnnwn...");
2123.     }
2124. }
2125. 

losehp Edit

losehp() takes 3 parameters, damage, killer string and killer format. damage is an integer value, and hero will be dealt that much damage. If this kills the hero, then the killer string will be used as the death reason, and killer format will define how the killer string is used. Killer string is one of KILLED_BY_AN, KILLED_BY or NO_KILLER_PREFIX. For example:

losehp(rnd(30), "system shock", KILLED_BY_AN);
2126. void
2127. losehp(n, knam, k_format)
2128. register int n;
2129. register const char *knam;
2130. boolean k_format;
2131. {
2132. 	if (Upolyd) {
2133. 		u.mh -= n;
2134. 		if (u.mhmax < u.mh) u.mhmax = u.mh;
2135. 		flags.botl = 1;
2136. 		if (u.mh < 1)
2137. 		    rehumanize();
2138. 		else if (n > 0 && u.mh*10 < u.mhmax && Unchanging)
2139. 		    maybe_wail();
2140. 		return;
2141. 	}
2142. 
2143. 	u.uhp -= n;
2144. 	if(u.uhp > u.uhpmax)
2145. 		u.uhpmax = u.uhp;	/* perhaps n was negative */
2146. 	flags.botl = 1;
2147. 	if(u.uhp < 1) {
2148. 		killer_format = k_format;
2149. 		killer = knam;		/* the thing that killed you */
2150. 		You("die...");
2151. 		done(DIED);
2152. 	} else if (n > 0 && u.uhp*10 < u.uhpmax) {
2153. 		maybe_wail();
2154. 	}
2155. }
2156. 

weight_cap Edit

2157. int
2158. weight_cap()
2159. {
2160. 	register long carrcap;
2161. 
2162. 	carrcap = 25*(ACURRSTR + ACURR(A_CON)) + 50;
2163. 	if (Upolyd) {
2164. 		/* consistent with can_carry() in mon.c */
2165. 		if (youmonst.data->mlet == S_NYMPH)
2166. 			carrcap = MAX_CARR_CAP;
2167. 		else if (!youmonst.data->cwt)
2168. 			carrcap = (carrcap * (long)youmonst.data->msize) / MZ_HUMAN;
2169. 		else if (!strongmonst(youmonst.data)
2170. 			|| (strongmonst(youmonst.data) && (youmonst.data->cwt > WT_HUMAN)))
2171. 			carrcap = (carrcap * (long)youmonst.data->cwt / WT_HUMAN);
2172. 	}
2173. 
2174. 	if (Levitation || Is_airlevel(&u.uz)    /* pugh@cornell */
2175. #ifdef STEED
2176. 			|| (u.usteed && strongmonst(u.usteed->data))
2177. #endif
2178. 	)
2179. 		carrcap = MAX_CARR_CAP;
2180. 	else {
2181. 		if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
2182. 		if (!Flying) {
2183. 			if(EWounded_legs & LEFT_SIDE) carrcap -= 100;
2184. 			if(EWounded_legs & RIGHT_SIDE) carrcap -= 100;
2185. 		}
2186. 		if (carrcap < 0) carrcap = 0;
2187. 	}
2188. 	return((int) carrcap);
2189. }
2190. 

inv_weight Edit

2191. static int wc;	/* current weight_cap(); valid after call to inv_weight() */
2192. 
2193. /* returns how far beyond the normal capacity the player is currently. */
2194. /* inv_weight() is negative if the player is below normal capacity. */
2195. int
2196. inv_weight()
2197. {
2198. 	register struct obj *otmp = invent;
2199. 	register int wt = 0;
2200. 
2201. #ifndef GOLDOBJ
2202. 	/* when putting stuff into containers, gold is inserted at the head
2203. 	   of invent for easier manipulation by askchain & co, but it's also
2204. 	   retained in u.ugold in order to keep the status line accurate; we
2205. 	   mustn't add its weight in twice under that circumstance */
2206. 	wt = (otmp && otmp->oclass == COIN_CLASS) ? 0 :
2207. 		(int)((u.ugold + 50L) / 100L);
2208. #endif
2209. 	while (otmp) {
2210. #ifndef GOLDOBJ
2211. 		if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data))
2212. #else
2213. 		if (otmp->oclass == COIN_CLASS)
2214. 			wt += (int)(((long)otmp->quan + 50L) / 100L);
2215. 		else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data))
2216. #endif
2217. 			wt += otmp->owt;
2218. 		otmp = otmp->nobj;
2219. 	}
2220. 	wc = weight_cap();
2221. 	return (wt - wc);
2222. }
2223. 

calc_capacity Edit

2224. /*
2225.  * Returns 0 if below normal capacity, or the number of "capacity units"
2226.  * over the normal capacity the player is loaded.  Max is 5.
2227.  */
2228. int
2229. calc_capacity(xtra_wt)
2230. int xtra_wt;
2231. {
2232.     int cap, wt = inv_weight() + xtra_wt;
2233. 
2234.     if (wt <= 0) return UNENCUMBERED;
2235.     if (wc <= 1) return OVERLOADED;
2236.     cap = (wt*2 / wc) + 1;
2237.     return min(cap, OVERLOADED);
2238. }
2239. 

near_capacity Edit

2240. int
2241. near_capacity()
2242. {
2243.     return calc_capacity(0);
2244. }
2245. 

max_capacity Edit

2246. int
2247. max_capacity()
2248. {
2249.     int wt = inv_weight();
2250. 
2251.     return (wt - (2 * wc));
2252. }
2253. 

check_capacity Edit

2254. boolean
2255. check_capacity(str)
2256. const char *str;
2257. {
2258.     if(near_capacity() >= EXT_ENCUMBER) {
2259. 	if(str)
2260. 	    pline(str);
2261. 	else
2262. 	    You_cant("do that while carrying so much stuff.");
2263. 	return 1;
2264.     }
2265.     return 0;
2266. }
2267. 
2268. #endif /* OVL1 */

inv_cnt Edit

2269. #ifdef OVLB
2270. 
2271. int
2272. inv_cnt()
2273. {
2274. 	register struct obj *otmp = invent;
2275. 	register int ct = 0;
2276. 
2277. 	while(otmp){
2278. 		ct++;
2279. 		otmp = otmp->nobj;
2280. 	}
2281. 	return(ct);
2282. }
2283. 

money_cnt Edit

2284. #ifdef GOLDOBJ
2285. /* Counts the money in an object chain. */
2286. /* Intended use is for your or some monsters inventory, */
2287. /* now that u.gold/m.gold is gone.*/
2288. /* Counting money in a container might be possible too. */
2289. long
2290. money_cnt(otmp)
2291. struct obj *otmp;
2292. {
2293.         while(otmp) {
2294. 	        /* Must change when silver & copper is implemented: */
2295.  	        if (otmp->oclass == COIN_CLASS) return otmp->quan;
2296.   	        otmp = otmp->nobj;
2297. 	}
2298. 	return 0;
2299. }
2300. #endif
2301. #endif /* OVLB */
2302. 
2303. /*hack.c*/

Also on Fandom

Random Wiki