Fandom

Wikihack

Source:NetHack 3.3.0/ball.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 ball.c from the source code of NetHack 3.3.0. To link to a particular line, write [[NetHack 3.3.0/ball.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: @(#)ball.c	3.3	97/04/23	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    /* Ball & Chain =============================================================*/
6.    
7.    #include "hack.h"
8.    
9.    STATIC_DCL int NDECL(bc_order);
10.   STATIC_DCL void NDECL(litter);
11.   
12.   void
13.   ballfall()
14.   {
15.   	boolean gets_hit;
16.   
17.   	gets_hit = (((uball->ox != u.ux) || (uball->oy != u.uy)) &&
18.   		    ((uwep == uball)? FALSE : (boolean)rn2(5)));
19.   	if (carried(uball)) {
20.   		pline("Startled, you drop the iron ball.");
21.   		if (uwep == uball)
22.   			setuwep((struct obj *)0);
23.   		if (uswapwep == uball)
24.   			setuswapwep((struct obj *)0);
25.   		if (uquiver == uball)
26.   			setuqwep((struct obj *)0);;
27.   		if (uwep != uball)
28.   			freeinv(uball);
29.   	}
30.   	if(gets_hit){
31.   		int dmg = rn1(7,25);
32.   		pline_The("iron ball falls on your %s.",
33.   			body_part(HEAD));
34.   		if (uarmh)
35.   		    if(is_metallic(uarmh)) {
36.   			pline("Fortunately, you are wearing a hard helmet.");
37.   			dmg = 3;
38.   		    } else if (flags.verbose)
39.   			Your("%s does not protect you.", xname(uarmh));
40.   		losehp(dmg, "Crunched in the head by an iron ball",
41.   			NO_KILLER_PREFIX);
42.   	}
43.   }
44.   
45.   /*
46.    *  To make this work, we have to mess with the hero's mind.  The rules for
47.    *  ball&chain are:
48.    *
49.    *	1. If the hero can see them, fine.
50.    *	2. If the hero can't see either, it isn't seen.
51.    *	3. If either is felt it is seen.
52.    *	4. If either is felt and moved, it disappears.
53.    *
54.    *  If the hero can see, then when a move is done, the ball and chain are
55.    *  first picked up, the positions under them are corrected, then they
56.    *  are moved after the hero moves.  Not too bad.
57.    *
58.    *  If the hero is blind, then she can "feel" the ball and/or chain at any
59.    *  time.  However, when the hero moves, the felt ball and/or chain become
60.    *  unfelt and whatever was felt "under" the ball&chain appears.  Pretty
61.    *  nifty, but it requires that the ball&chain "remember" what was under
62.    *  them --- i.e. they pick-up glyphs when they are felt and drop them when
63.    *  moved (and felt).  When swallowed, the ball&chain are pulled completely
64.    *  off of the dungeon, but are still on the object chain.  They are placed
65.    *  under the hero when she is expelled.
66.    */
67.   
68.   /*
69.    * from you.h
70.    *	int u.bglyph		glyph under the ball
71.    *	int u.cglyph		glyph under the chain
72.    *	int u.bc_felt		mask for ball/chain being felt
73.    *	#define BC_BALL  0x01	bit mask in u.bc_felt for ball
74.    *	#define BC_CHAIN 0x02	bit mask in u.bc_felt for chain
75.    *	int u.bc_order		ball & chain order
76.    *
77.    * u.bc_felt is also manipulated in display.c and read.c, the others only
78.    * in this file.  None of these variables are valid unless the player is
79.    * Blind.
80.    */
81.   
82.   /* values for u.bc_order */
83.   #define BCPOS_DIFFER	0	/* ball & chain at different positions */
84.   #define BCPOS_CHAIN	1	/* chain on top of ball */
85.   #define BCPOS_BALL	2	/* ball on top of chain */
86.   
87.   
88.   
89.   /*
90.    *  Place the ball & chain under the hero.  Make sure that the ball & chain
91.    *  variables are set (actually only needed when blind, but what the heck).
92.    *  It is assumed that when this is called, the ball and chain are NOT
93.    *  attached to the object list.
94.    *
95.    *  Should not be called while swallowed.
96.    */
97.   void
98.   placebc()
99.   {
100.      if (!uchain || !uball) {
101.  	impossible("Where are your ball and chain?");
102.  	return;
103.      }
104.  
105.      (void) flooreffects(uchain, u.ux, u.uy, "");	/* chain might rust */
106.  
107.      if (carried(uball))		/* the ball is carried */
108.  	u.bc_order = BCPOS_DIFFER;
109.      else {
110.  	/* ball might rust -- already checked when carried */
111.  	(void) flooreffects(uball, u.ux, u.uy, "");
112.  	place_object(uball, u.ux, u.uy);
113.  	u.bc_order = BCPOS_CHAIN;
114.      }
115.  
116.      place_object(uchain, u.ux, u.uy);
117.  
118.      u.bglyph = u.cglyph = levl[u.ux][u.uy].glyph;   /* pick up glyph */
119.  
120.      newsym(u.ux,u.uy);
121.  }
122.  
123.  void
124.  unplacebc()
125.  {
126.      if (u.uswallow) return;	/* ball&chain not placed while swallowed */
127.  
128.      if (!carried(uball)) {
129.  	obj_extract_self(uball);
130.  	if (Blind && (u.bc_felt & BC_BALL))		/* drop glyph */
131.  	    levl[uball->ox][uball->oy].glyph = u.bglyph;
132.  
133.  	newsym(uball->ox,uball->oy);
134.      }
135.      obj_extract_self(uchain);
136.      if (Blind && (u.bc_felt & BC_CHAIN))		/* drop glyph */
137.  	levl[uchain->ox][uchain->oy].glyph = u.cglyph;
138.  
139.      newsym(uchain->ox,uchain->oy);
140.      u.bc_felt = 0;					/* feel nothing */
141.  }
142.  
143.  
144.  /*
145.   *  Return the stacking of the hero's ball & chain.  This assumes that the
146.   *  hero is being punished.
147.   */
148.  STATIC_OVL int
149.  bc_order()
150.  {
151.      struct obj *obj;
152.  
153.      if (uchain->ox != uball->ox || uchain->oy != uball->oy || carried(uball)
154.  		|| u.uswallow)
155.  	return BCPOS_DIFFER;
156.  
157.      for (obj = level.objects[uball->ox][uball->oy]; obj; obj = obj->nexthere) {
158.  	if (obj == uchain) return BCPOS_CHAIN;
159.  	if (obj == uball) return BCPOS_BALL;
160.      }
161.      impossible("bc_order:  ball&chain not in same location!");
162.      return BCPOS_DIFFER;
163.  }
164.  
165.  /*
166.   *  set_bc()
167.   *
168.   *  The hero is either about to go blind or already blind and just punished.
169.   *  Set up the ball and chain variables so that the ball and chain are "felt".
170.   */
171.  void
172.  set_bc(already_blind)
173.  int already_blind;
174.  {
175.      int ball_on_floor = !carried(uball);
176.  
177.      u.bc_order = bc_order();				/* get the order */
178.      u.bc_felt = ball_on_floor ? BC_BALL|BC_CHAIN : BC_CHAIN;	/* felt */
179.  
180.      if (already_blind || u.uswallow) {
181.  	u.cglyph = u.bglyph = levl[u.ux][u.uy].glyph;
182.  	return;
183.      }
184.  
185.      /*
186.       *  Since we can still see, remove the ball&chain and get the glyph that
187.       *  would be beneath them.  Then put the ball&chain back.  This is pretty
188.       *  disgusting, but it will work.
189.       */
190.      remove_object(uchain);
191.      if (ball_on_floor) remove_object(uball);
192.  
193.      newsym(uchain->ox, uchain->oy);
194.      u.cglyph = levl[uchain->ox][uchain->oy].glyph;
195.  
196.      if (u.bc_order == BCPOS_DIFFER) {		/* different locations */
197.  	place_object(uchain, uchain->ox, uchain->oy);
198.  	newsym(uchain->ox, uchain->oy);
199.  	if (ball_on_floor) {
200.  	    newsym(uball->ox, uball->oy);		/* see under ball */
201.  	    u.bglyph = levl[uball->ox][uball->oy].glyph;
202.  	    place_object(uball,  uball->ox, uball->oy);
203.  	    newsym(uball->ox, uball->oy);		/* restore ball */
204.  	}
205.      } else {
206.  	u.bglyph = u.cglyph;
207.  	if (u.bc_order == BCPOS_CHAIN) {
208.  	    place_object(uball,  uball->ox, uball->oy);
209.  	    place_object(uchain, uchain->ox, uchain->oy);
210.  	} else {
211.  	    place_object(uchain, uchain->ox, uchain->oy);
212.  	    place_object(uball,  uball->ox, uball->oy);
213.  	}
214.  	newsym(uball->ox, uball->oy);
215.      }
216.  }
217.  
218.  
219.  /*
220.   *  move_bc()
221.   *
222.   *  Move the ball and chain.  This is called twice for every move.  The first
223.   *  time to pick up the ball and chain before the move, the second time to
224.   *  place the ball and chain after the move.  If the ball is carried, this
225.   *  function should never have BC_BALL as part of its control.
226.   *
227.   *  Should not be called while swallowed.
228.   */
229.  void
230.  move_bc(before, control, ballx, bally, chainx, chainy)
231.  int   before, control;
232.  xchar ballx, bally, chainx, chainy;	/* only matter !before */
233.  {
234.      if (Blind) {
235.  	/*
236.  	 *  The hero is blind.  Time to work hard.  The ball and chain that
237.  	 *  are attached to the hero are very special.  The hero knows that
238.  	 *  they are attached, so when they move, the hero knows that they
239.  	 *  aren't at the last position remembered.  This is complicated
240.  	 *  by the fact that the hero can "feel" the surrounding locations
241.  	 *  at any time, hence, making one or both of them show up again.
242.  	 *  So, we have to keep track of which is felt at any one time and
243.  	 *  act accordingly.
244.  	 */
245.  	if (!before) {
246.  	    if ((control & BC_CHAIN) && (control & BC_BALL)) {
247.  		/*
248.  		 *  Both ball and chain moved.  If felt, drop glyph.
249.  		 */
250.  		if (u.bc_felt & BC_BALL)
251.  		    levl[uball->ox][uball->oy].glyph = u.bglyph;
252.  		if (u.bc_felt & BC_CHAIN)
253.  		    levl[uchain->ox][uchain->oy].glyph = u.cglyph;
254.  		u.bc_felt = 0;
255.  
256.  		/* Pick up glyph at new location. */
257.  		u.bglyph = levl[ballx][bally].glyph;
258.  		u.cglyph = levl[chainx][chainy].glyph;
259.  
260.  		movobj(uball,ballx,bally);
261.  		movobj(uchain,chainx,chainy);
262.  	    } else if (control & BC_BALL) {
263.  		if (u.bc_felt & BC_BALL) {
264.  		    if (u.bc_order == BCPOS_DIFFER) {	/* ball by itself */
265.  			levl[uball->ox][uball->oy].glyph = u.bglyph;
266.  		    } else if (u.bc_order == BCPOS_BALL) {
267.  			if (u.bc_felt & BC_CHAIN) {   /* know chain is there */
268.  			    map_object(uchain, 0);
269.  			} else {
270.  			    levl[uball->ox][uball->oy].glyph = u.bglyph;
271.  			}
272.  		    }
273.  		    u.bc_felt &= ~BC_BALL;	/* no longer feel the ball */
274.  		}
275.  
276.  		/* Pick up glyph at new position. */
277.  		u.bglyph = (ballx != chainx || bally != chainy) ?
278.  					levl[ballx][bally].glyph : u.cglyph;
279.  
280.  		movobj(uball,ballx,bally);
281.  	    } else if (control & BC_CHAIN) {
282.  		if (u.bc_felt & BC_CHAIN) {
283.  		    if (u.bc_order == BCPOS_DIFFER) {
284.  			levl[uchain->ox][uchain->oy].glyph = u.cglyph;
285.  		    } else if (u.bc_order == BCPOS_CHAIN) {
286.  			if (u.bc_felt & BC_BALL) {
287.  			    map_object(uball, 0);
288.  			} else {
289.  			    levl[uchain->ox][uchain->oy].glyph = u.cglyph;
290.  			}
291.  		    }
292.  		    u.bc_felt &= ~BC_CHAIN;
293.  		}
294.  		/* Pick up glyph at new position. */
295.  		u.cglyph = (ballx != chainx || bally != chainy) ?
296.  					levl[chainx][chainy].glyph : u.bglyph;
297.  
298.  		movobj(uchain,chainx,chainy);
299.  	    }
300.  
301.  	    u.bc_order = bc_order();	/* reset the order */
302.  	}
303.  
304.      } else {
305.  	/*
306.  	 *  The hero is not blind.  To make this work correctly, we need to
307.  	 *  pick up the ball and chain before the hero moves, then put them
308.  	 *  in their new positions after the hero moves.
309.  	 */
310.  	if (before) {
311.  	    if (!control) {
312.  		/*
313.  		 * Neither ball nor chain is moving, so remember which was
314.  		 * on top until !before.  Use the variable u.bc_order
315.  		 * since it is only valid when blind.
316.  		 */
317.  		u.bc_order = bc_order();
318.  	    }
319.  
320.  	    remove_object(uchain);
321.  	    newsym(uchain->ox, uchain->oy);
322.  	    if (!carried(uball)) {
323.  		remove_object(uball);
324.  		newsym(uball->ox,  uball->oy);
325.  	    }
326.  	} else {
327.  	    int on_floor = !carried(uball);
328.  
329.  	    if ((control & BC_CHAIN) ||
330.  				(!control && u.bc_order == BCPOS_CHAIN)) {
331.  		/* If the chain moved or nothing moved & chain on top. */
332.  		if (on_floor) place_object(uball,  ballx, bally);
333.  		place_object(uchain, chainx, chainy);	/* chain on top */
334.  	    } else {
335.  		place_object(uchain, chainx, chainy);
336.  		if (on_floor) place_object(uball,  ballx, bally);
337.  							    /* ball on top */
338.  	    }
339.  	    newsym(chainx, chainy);
340.  	    if (on_floor) newsym(ballx, bally);
341.  	}
342.      }
343.  }
344.  
345.  /* return TRUE if ball could be dragged
346.   *
347.   *  Should not be called while swallowed.
348.   */
349.  boolean
350.  drag_ball(x, y, bc_control, ballx, bally, chainx, chainy, cause_delay)
351.  xchar x, y;
352.  int *bc_control;
353.  xchar *ballx, *bally, *chainx, *chainy;
354.  boolean *cause_delay;
355.  {
356.  	struct trap *t = (struct trap *)0;
357.  
358.  	*ballx  = uball->ox;
359.  	*bally  = uball->oy;
360.  	*chainx = uchain->ox;
361.  	*chainy = uchain->oy;
362.  	*bc_control = 0;
363.  	*cause_delay = FALSE;
364.  
365.  	if (dist2(x, y, uchain->ox, uchain->oy) <= 2) {	/* nothing moved */
366.  	    move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
367.  	    return TRUE;
368.  	}
369.  
370.  	if (carried(uball) || dist2(x, y, uball->ox, uball->oy) < 3 ||
371.  		(uball->ox == uchain->ox && uball->oy == uchain->oy)) {
372.  	    /*
373.  	     * Case where the ball doesn't move but the chain can't just move
374.  	     * to the player's position:
375.  	     *   @                                             _
376.  	     *    _    moving southwest becomes  @_  and not  @
377.  	     *   0                                0            0
378.  	     */
379.  	    *bc_control = BC_CHAIN;
380.  	    move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
381.  	    if (dist2(x, y, uball->ox, uball->oy) == 2 &&
382.  		    dist2(x, y, uchain->ox, uchain->oy) == 4) {
383.  		if (uchain->oy == y)
384.  		    *chainx = uball->ox;
385.  		else
386.  		    *chainy = uball->oy;
387.  	    } else {
388.  		*chainx = u.ux;
389.  		*chainy = u.uy;
390.  	    }
391.  	    return TRUE;
392.  	}
393.  
394.  	if (near_capacity() > SLT_ENCUMBER) {
395.  	    You("cannot %sdrag the heavy iron ball.",
396.  			    invent ? "carry all that and also " : "");
397.  	    nomul(0);
398.  	    return FALSE;
399.  	}
400.  
401.  	if ((is_pool(uchain->ox, uchain->oy) &&
402.  			/* water not mere continuation of previous water */
403.  			(levl[uchain->ox][uchain->oy].typ == POOL ||
404.  			 !is_pool(uball->ox, uball->oy) ||
405.  			 levl[uball->ox][uball->oy].typ == POOL))
406.  	    || ((t = t_at(uchain->ox, uchain->oy)) &&
407.  			(t->ttyp == PIT ||
408.  			 t->ttyp == SPIKED_PIT ||
409.  			 t->ttyp == HOLE ||
410.  			 t->ttyp == TRAPDOOR)) ) {
411.  
412.  	    if (Levitation) {
413.  		You_feel("a tug from the iron ball.");
414.  		if (t) t->tseen = 1;
415.  	    } else {
416.  		struct monst *victim;
417.  
418.  		You("are jerked back by the iron ball!");
419.  		if ((victim = m_at(uchain->ox, uchain->oy)) != 0) {
420.  		    int tmp;
421.  
422.  		    tmp = -2 + Luck + find_mac(victim);
423.  		    tmp += omon_adj(victim, uball, TRUE);
424.  		    if (tmp >= rnd(20))
425.  			(void) hmon(victim,uball,1);
426.  		    else
427.  			miss(xname(uball), victim);
428.  
429.  		}		/* now check again in case mon died */
430.  		if (!m_at(uchain->ox, uchain->oy)) {
431.  		    u.ux = uchain->ox;
432.  		    u.uy = uchain->oy;
433.  		    newsym(u.ux0, u.uy0);
434.  		}
435.  		nomul(0);
436.  
437.  		*bc_control = BC_BALL;
438.  		move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
439.  		*ballx = uchain->ox;
440.  		*bally = uchain->oy;
441.  		move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy);
442.  		spoteffects();
443.  		return FALSE;
444.  	    }
445.  	}
446.  
447.  	*bc_control = BC_BALL|BC_CHAIN;;
448.  
449.  	move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
450.  	*ballx  = uchain->ox;
451.  	*bally  = uchain->oy;
452.  	*chainx = u.ux;
453.  	*chainy = u.uy;
454.  	*cause_delay = TRUE;
455.  	return TRUE;
456.  }
457.  
458.  /*
459.   *  drop_ball()
460.   *
461.   *  The punished hero drops or throws her iron ball.  If the hero is
462.   *  blind, we must reset the order and glyph.  Check for side effects.
463.   *  This routine expects the ball to be already placed.
464.   *
465.   *  Should not be called while swallowed.
466.   */
467.  void
468.  drop_ball(x, y)
469.  xchar x, y;
470.  {
471.      if (Blind) {
472.  	u.bc_order = bc_order();			/* get the order */
473.  							/* pick up glyph */
474.  	u.bglyph = (u.bc_order) ? u.cglyph : levl[x][y].glyph;
475.      }
476.  
477.      if (x != u.ux || y != u.uy) {
478.  	struct trap *t;
479.  	const char *pullmsg = "The ball pulls you out of the %s!";
480.  
481.  	if (u.utrap && u.utraptype != TT_INFLOOR) {
482.  	    switch(u.utraptype) {
483.  	    case TT_PIT:
484.  		pline(pullmsg, "pit");
485.  		break;
486.  	    case TT_WEB:
487.  		pline(pullmsg, "web");
488.  		pline_The("web is destroyed!");
489.  		deltrap(t_at(u.ux,u.uy));
490.  		break;
491.  	    case TT_LAVA:
492.  		pline(pullmsg, "lava");
493.  		break;
494.  	    case TT_BEARTRAP: {
495.  		register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
496.  		pline(pullmsg, "bear trap");
497.  		set_wounded_legs(side, rn1(1000, 500));
498.  #ifdef STEED
499.  		if (!u.usteed)
500.  #endif
501.  		{
502.  		    Your("%s %s is severely damaged.",
503.  					(side == LEFT_SIDE) ? "left" : "right",
504.  					body_part(LEG));
505.  		    losehp(2, "leg damage from being pulled out of a bear trap",
506.  					KILLED_BY);
507.  		}
508.  		break;
509.  	      }
510.  	    }
511.  	    u.utrap = 0;
512.  	    fill_pit(u.ux, u.uy);
513.  	}
514.  
515.  	u.ux0 = u.ux;
516.  	u.uy0 = u.uy;
517.  	if (!Levitation && !MON_AT(x, y) && !u.utrap &&
518.  			    (is_pool(x, y) ||
519.  			     ((t = t_at(x, y)) &&
520.  			      (t->ttyp == PIT || t->ttyp == SPIKED_PIT ||
521.  			       t->ttyp == TRAPDOOR || t->ttyp == HOLE)))) {
522.  	    u.ux = x;
523.  	    u.uy = y;
524.  	} else {
525.  	    u.ux = x - u.dx;
526.  	    u.uy = y - u.dy;
527.  	}
528.  	vision_full_recalc = 1;	/* hero has moved, recalculate vision later */
529.  
530.  	if (Blind) {
531.  	    /* drop glyph under the chain */
532.  	    if (u.bc_felt & BC_CHAIN)
533.  		levl[uchain->ox][uchain->oy].glyph = u.cglyph;
534.  	    u.bc_felt  = 0;		/* feel nothing */
535.  	    /* pick up new glyph */
536.  	    u.cglyph = (u.bc_order) ? u.bglyph : levl[u.ux][u.uy].glyph;
537.  	}
538.  	movobj(uchain,u.ux,u.uy);	/* has a newsym */
539.  	if (Blind) {
540.  	    u.bc_order = bc_order();
541.  	}
542.  	newsym(u.ux0,u.uy0);		/* clean up old position */
543.  	if (u.ux0 != u.ux || u.uy0 != u.uy)
544.  	    spoteffects();
545.      }
546.  }
547.  
548.  
549.  STATIC_OVL void
550.  litter()
551.  {
552.  	struct obj *otmp = invent, *nextobj;
553.  	int capacity = weight_cap();
554.  
555.  	while (otmp) {
556.  		nextobj = otmp->nobj;
557.  		if ((otmp != uball) && (rnd(capacity) <= (int)otmp->owt)) {
558.  			if (otmp == uwep)
559.  				setuwep((struct obj *)0);
560.  			if ((otmp != uwep) && (canletgo(otmp, ""))) {
561.  				Your("%s you down the stairs.",
562.  				     aobjnam(otmp, "follow"));
563.  				dropx(otmp);
564.  			}
565.  		}
566.  		otmp = nextobj;
567.  	}
568.  }
569.  
570.  void
571.  drag_down()
572.  {
573.  	boolean forward;
574.  	uchar dragchance = 3;
575.  
576.  	/*
577.  	 *	Assume that the ball falls forward if:
578.  	 *
579.  	 *	a) the character is wielding it, or
580.  	 *	b) the character has both hands available to hold it (i.e. is
581.  	 *	   not wielding any weapon), or
582.  	 *	c) (perhaps) it falls forward out of his non-weapon hand
583.  	 */
584.  
585.  	forward = carried(uball) && (uwep == uball || !uwep || !rn2(3));
586.  
587.  	if (carried(uball))
588.  		You("lose your grip on the iron ball.");
589.  
590.  	if (forward) {
591.  		if(rn2(6)) {
592.  			pline_The("iron ball drags you downstairs!");
593.  			losehp(rnd(6), "dragged downstairs by an iron ball",
594.  				NO_KILLER_PREFIX);
595.  			litter();
596.  		}
597.  	} else {
598.  		if(rn2(2)) {
599.  			pline_The("iron ball smacks into you!");
600.  			losehp(rnd(20), "iron ball collision", KILLED_BY_AN);
601.  			exercise(A_STR, FALSE);
602.  			dragchance -= 2;
603.  		}
604.  		if( (int) dragchance >= rnd(6)) {
605.  			pline_The("iron ball drags you downstairs!");
606.  			losehp(rnd(3), "dragged downstairs by an iron ball",
607.  				NO_KILLER_PREFIX);
608.  			exercise(A_STR, FALSE);
609.  			litter();
610.  		}
611.  	}
612.  }
613.  
614.  /*ball.c*/

Also on Fandom

Random Wiki