Difference between revisions of "Source:NetHack 3.6.0/src/ball.c"

From NetHackWiki
Jump to navigation Jump to search
m (Fix indents and break functions)
 
Line 6: Line 6:
 
== Top of file ==
 
== Top of file ==
  
  <span id="line1">1.  /* NetHack 3.6 ball.c $NHDT-Date: 1446808438 2015/11/06 11:13:58 $  $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */</span>
+
  <span id="line1">1. /* NetHack 3.6 ball.c $NHDT-Date: 1446808438 2015/11/06 11:13:58 $  $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */</span>
  <span id="line2">2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */</span>
+
  <span id="line2">2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */</span>
  <span id="line3">3.  /* NetHack may be freely redistributed.  See license for details. */</span>
+
  <span id="line3">3. /* NetHack may be freely redistributed.  See license for details. */</span>
  <span id="line4">4.  </span>
+
  <span id="line4">4. </span>
  <span id="line5">5.  /* Ball & Chain</span>
+
  <span id="line5">5. /* Ball & Chain</span>
  <span id="line6">6.  * =============================================================*/</span>
+
  <span id="line6">6.  * =============================================================*/</span>
  <span id="line7">7.  </span>
+
  <span id="line7">7. </span>
  <span id="line8">8.  #include "hack.h"</span>
+
  <span id="line8">8. #include "hack.h"</span>
  <span id="line9">9.  </span>
+
  <span id="line9">9. </span>
  <span id="line10">10.  STATIC_DCL int NDECL(bc_order);</span>
+
  <span id="line10">10. STATIC_DCL int NDECL(bc_order);</span>
  <span id="line11">11.  STATIC_DCL void NDECL(litter);</span>
+
  <span id="line11">11. STATIC_DCL void NDECL(litter);</span>
  <span id="line12">12.  </span>
+
  <span id="line12">12. </span>
  
 
== ballrelease ==
 
== ballrelease ==
 
      
 
      
  <span id="line13">13.  void</span>
+
  <span id="line13">13. void</span>
  <span id="line14">14.  ballrelease(showmsg)</span>
+
  <span id="line14">14. ballrelease(showmsg)</span>
  <span id="line15">15.  boolean showmsg;</span>
+
  <span id="line15">15. boolean showmsg;</span>
  <span id="line16">16.  {</span>
+
  <span id="line16">16. {</span>
  <span id="line17">17.      if (carried(uball)) {</span>
+
  <span id="line17">17.    if (carried(uball)) {</span>
  <span id="line18">18.          if (showmsg)</span>
+
  <span id="line18">18.        if (showmsg)</span>
  <span id="line19">19.              pline("Startled, you drop the iron ball.");</span>
+
  <span id="line19">19.            pline("Startled, you drop the iron ball.");</span>
  <span id="line20">20.          if (uwep == uball)</span>
+
  <span id="line20">20.        if (uwep == uball)</span>
  <span id="line21">21.              setuwep((struct obj *) 0);</span>
+
  <span id="line21">21.            setuwep((struct obj *) 0);</span>
  <span id="line22">22.          if (uswapwep == uball)</span>
+
  <span id="line22">22.        if (uswapwep == uball)</span>
  <span id="line23">23.              setuswapwep((struct obj *) 0);</span>
+
  <span id="line23">23.            setuswapwep((struct obj *) 0);</span>
  <span id="line24">24.          if (uquiver == uball)</span>
+
  <span id="line24">24.        if (uquiver == uball)</span>
  <span id="line25">25.              setuqwep((struct obj *) 0);</span>
+
  <span id="line25">25.            setuqwep((struct obj *) 0);</span>
  <span id="line26">26.          ;</span>
+
  <span id="line26">26.        ;</span>
  <span id="line27">27.          if (uwep != uball)</span>
+
  <span id="line27">27.        if (uwep != uball)</span>
  <span id="line28">28.              freeinv(uball);</span>
+
  <span id="line28">28.            freeinv(uball);</span>
  <span id="line29">29.      }</span>
+
  <span id="line29">29.    }</span>
  <span id="line30">30.  }</span>
+
  <span id="line30">30. }</span>
  <span id="line31">31.  </span>
+
  <span id="line31">31. </span>
  
 
== ballfall ==
 
== ballfall ==
 
      
 
      
  <span id="line32">32.  void</span>
+
  <span id="line32">32. void</span>
  <span id="line33">33.  ballfall()</span>
+
  <span id="line33">33. ballfall()</span>
  <span id="line34">34.  {</span>
+
  <span id="line34">34. {</span>
  <span id="line35">35.      boolean gets_hit;</span>
+
  <span id="line35">35.    boolean gets_hit;</span>
  <span id="line36">36.  </span>
+
  <span id="line36">36. </span>
  <span id="line37">37.      gets_hit = (((uball->ox != u.ux) || (uball->oy != u.uy))</span>
+
  <span id="line37">37.    gets_hit = (((uball->ox != u.ux) || (uball->oy != u.uy))</span>
  <span id="line38">38.                  && ((uwep == uball) ? FALSE : (boolean) rn2(5)));</span>
+
  <span id="line38">38.                && ((uwep == uball) ? FALSE : (boolean) rn2(5)));</span>
  <span id="line39">39.      ballrelease(TRUE);</span>
+
  <span id="line39">39.    ballrelease(TRUE);</span>
  <span id="line40">40.      if (gets_hit) {</span>
+
  <span id="line40">40.    if (gets_hit) {</span>
  <span id="line41">41.          int dmg = rn1(7, 25);</span>
+
  <span id="line41">41.        int dmg = rn1(7, 25);</span>
  <span id="line42">42.          pline_The("iron ball falls on your %s.", body_part(HEAD));</span>
+
  <span id="line42">42.        pline_The("iron ball falls on your %s.", body_part(HEAD));</span>
  <span id="line43">43.          if (uarmh) {</span>
+
  <span id="line43">43.        if (uarmh) {</span>
  <span id="line44">44.              if (is_metallic(uarmh)) {</span>
+
  <span id="line44">44.            if (is_metallic(uarmh)) {</span>
  <span id="line45">45.                  pline("Fortunately, you are wearing a hard helmet.");</span>
+
  <span id="line45">45.                pline("Fortunately, you are wearing a hard helmet.");</span>
  <span id="line46">46.                  dmg = 3;</span>
+
  <span id="line46">46.                dmg = 3;</span>
  <span id="line47">47.              } else if (flags.verbose)</span>
+
  <span id="line47">47.            } else if (flags.verbose)</span>
  <span id="line48">48.                  pline("%s does not protect you.", Yname2(uarmh));</span>
+
  <span id="line48">48.                pline("%s does not protect you.", Yname2(uarmh));</span>
  <span id="line49">49.          }</span>
+
  <span id="line49">49.        }</span>
  <span id="line50">50.          losehp(Maybe_Half_Phys(dmg), "crunched in the head by an iron ball",</span>
+
  <span id="line50">50.        losehp(Maybe_Half_Phys(dmg), "crunched in the head by an iron ball",</span>
  <span id="line51">51.                NO_KILLER_PREFIX);</span>
+
  <span id="line51">51.                NO_KILLER_PREFIX);</span>
  <span id="line52">52.      }</span>
+
  <span id="line52">52.    }</span>
  <span id="line53">53.  }</span>
+
  <span id="line53">53. }</span>
  <span id="line54">54.  </span>
+
  <span id="line54">54. </span>
  
 
== placebc ==
 
== placebc ==
 
      
 
      
  <span id="line55">55.  /*</span>
+
  <span id="line55">55. /*</span>
  <span id="line56">56.  *  To make this work, we have to mess with the hero's mind.  The rules for</span>
+
  <span id="line56">56.  *  To make this work, we have to mess with the hero's mind.  The rules for</span>
  <span id="line57">57.  *  ball&chain are:</span>
+
  <span id="line57">57.  *  ball&chain are:</span>
  <span id="line58">58.  *</span>
+
  <span id="line58">58.  *</span>
  <span id="line59">59.  *      1. If the hero can see them, fine.</span>
+
  <span id="line59">59.  *      1. If the hero can see them, fine.</span>
  <span id="line60">60.  *      2. If the hero can't see either, it isn't seen.</span>
+
  <span id="line60">60.  *      2. If the hero can't see either, it isn't seen.</span>
  <span id="line61">61.  *      3. If either is felt it is seen.</span>
+
  <span id="line61">61.  *      3. If either is felt it is seen.</span>
  <span id="line62">62.  *      4. If either is felt and moved, it disappears.</span>
+
  <span id="line62">62.  *      4. If either is felt and moved, it disappears.</span>
  <span id="line63">63.  *</span>
+
  <span id="line63">63.  *</span>
  <span id="line64">64.  *  If the hero can see, then when a move is done, the ball and chain are</span>
+
  <span id="line64">64.  *  If the hero can see, then when a move is done, the ball and chain are</span>
  <span id="line65">65.  *  first picked up, the positions under them are corrected, then they</span>
+
  <span id="line65">65.  *  first picked up, the positions under them are corrected, then they</span>
  <span id="line66">66.  *  are moved after the hero moves.  Not too bad.</span>
+
  <span id="line66">66.  *  are moved after the hero moves.  Not too bad.</span>
  <span id="line67">67.  *</span>
+
  <span id="line67">67.  *</span>
  <span id="line68">68.  *  If the hero is blind, then she can "feel" the ball and/or chain at any</span>
+
  <span id="line68">68.  *  If the hero is blind, then she can "feel" the ball and/or chain at any</span>
  <span id="line69">69.  *  time.  However, when the hero moves, the felt ball and/or chain become</span>
+
  <span id="line69">69.  *  time.  However, when the hero moves, the felt ball and/or chain become</span>
  <span id="line70">70.  *  unfelt and whatever was felt "under" the ball&chain appears.  Pretty</span>
+
  <span id="line70">70.  *  unfelt and whatever was felt "under" the ball&chain appears.  Pretty</span>
  <span id="line71">71.  *  nifty, but it requires that the ball&chain "remember" what was under</span>
+
  <span id="line71">71.  *  nifty, but it requires that the ball&chain "remember" what was under</span>
  <span id="line72">72.  *  them --- i.e. they pick-up glyphs when they are felt and drop them when</span>
+
  <span id="line72">72.  *  them --- i.e. they pick-up glyphs when they are felt and drop them when</span>
  <span id="line73">73.  *  moved (and felt).  When swallowed, the ball&chain are pulled completely</span>
+
  <span id="line73">73.  *  moved (and felt).  When swallowed, the ball&chain are pulled completely</span>
  <span id="line74">74.  *  off of the dungeon, but are still on the object chain.  They are placed</span>
+
  <span id="line74">74.  *  off of the dungeon, but are still on the object chain.  They are placed</span>
  <span id="line75">75.  *  under the hero when she is expelled.</span>
+
  <span id="line75">75.  *  under the hero when she is expelled.</span>
  <span id="line76">76.  */</span>
+
  <span id="line76">76.  */</span>
  <span id="line77">77.  </span>
+
  <span id="line77">77. </span>
  <span id="line78">78.  /*</span>
+
  <span id="line78">78. /*</span>
  <span id="line79">79.  * from you.h</span>
+
  <span id="line79">79.  * from you.h</span>
  <span id="line80">80.  *      int u.bglyph            glyph under the ball</span>
+
  <span id="line80">80.  *      int u.bglyph            glyph under the ball</span>
  <span id="line81">81.  *      int u.cglyph            glyph under the chain</span>
+
  <span id="line81">81.  *      int u.cglyph            glyph under the chain</span>
  <span id="line82">82.  *      int u.bc_felt          mask for ball/chain being felt</span>
+
  <span id="line82">82.  *      int u.bc_felt          mask for ball/chain being felt</span>
  <span id="line83">83.  *      #define BC_BALL  0x01  bit mask in u.bc_felt for ball</span>
+
  <span id="line83">83.  *      #define BC_BALL  0x01  bit mask in u.bc_felt for ball</span>
  <span id="line84">84.  *      #define BC_CHAIN 0x02  bit mask in u.bc_felt for chain</span>
+
  <span id="line84">84.  *      #define BC_CHAIN 0x02  bit mask in u.bc_felt for chain</span>
  <span id="line85">85.  *      int u.bc_order          ball & chain order</span>
+
  <span id="line85">85.  *      int u.bc_order          ball & chain order</span>
  <span id="line86">86.  *</span>
+
  <span id="line86">86.  *</span>
  <span id="line87">87.  * u.bc_felt is also manipulated in display.c and read.c, the others only</span>
+
  <span id="line87">87.  * u.bc_felt is also manipulated in display.c and read.c, the others only</span>
  <span id="line88">88.  * in this file.  None of these variables are valid unless the player is</span>
+
  <span id="line88">88.  * in this file.  None of these variables are valid unless the player is</span>
  <span id="line89">89.  * Blind.</span>
+
  <span id="line89">89.  * Blind.</span>
  <span id="line90">90.  */</span>
+
  <span id="line90">90.  */</span>
  <span id="line91">91.  </span>
+
  <span id="line91">91. </span>
  <span id="line92">92.  /* values for u.bc_order */</span>
+
  <span id="line92">92. /* values for u.bc_order */</span>
  <span id="line93">93.  #define BCPOS_DIFFER 0 /* ball & chain at different positions */</span>
+
  <span id="line93">93. #define BCPOS_DIFFER 0 /* ball & chain at different positions */</span>
  <span id="line94">94.  #define BCPOS_CHAIN 1  /* chain on top of ball */</span>
+
  <span id="line94">94. #define BCPOS_CHAIN 1  /* chain on top of ball */</span>
  <span id="line95">95.  #define BCPOS_BALL 2  /* ball on top of chain */</span>
+
  <span id="line95">95. #define BCPOS_BALL 2  /* ball on top of chain */</span>
  <span id="line96">96.  </span>
+
  <span id="line96">96. </span>
  <span id="line97">97.  /*</span>
+
  <span id="line97">97. /*</span>
  <span id="line98">98.  *  Place the ball & chain under the hero.  Make sure that the ball & chain</span>
+
  <span id="line98">98.  *  Place the ball & chain under the hero.  Make sure that the ball & chain</span>
  <span id="line99">99.  *  variables are set (actually only needed when blind, but what the heck).</span>
+
  <span id="line99">99.  *  variables are set (actually only needed when blind, but what the heck).</span>
  <span id="line100">100.  *  It is assumed that when this is called, the ball and chain are NOT</span>
+
  <span id="line100">100.  *  It is assumed that when this is called, the ball and chain are NOT</span>
  <span id="line101">101.  *  attached to the object list.</span>
+
  <span id="line101">101.  *  attached to the object list.</span>
  <span id="line102">102.  *</span>
+
  <span id="line102">102.  *</span>
  <span id="line103">103.  *  Should not be called while swallowed except on waterlevel.</span>
+
  <span id="line103">103.  *  Should not be called while swallowed except on waterlevel.</span>
  <span id="line104">104.  */</span>
+
  <span id="line104">104.  */</span>
  <span id="line105">105.  void</span>
+
  <span id="line105">105. void</span>
  <span id="line106">106.  placebc()</span>
+
  <span id="line106">106. placebc()</span>
  <span id="line107">107.  {</span>
+
  <span id="line107">107. {</span>
  <span id="line108">108.      if (!uchain || !uball) {</span>
+
  <span id="line108">108.    if (!uchain || !uball) {</span>
  <span id="line109">109.          impossible("Where are your ball and chain?");</span>
+
  <span id="line109">109.        impossible("Where are your ball and chain?");</span>
  <span id="line110">110.          return;</span>
+
  <span id="line110">110.        return;</span>
  <span id="line111">111.      }</span>
+
  <span id="line111">111.    }</span>
  <span id="line112">112.  </span>
+
  <span id="line112">112. </span>
  <span id="line113">113.      (void) flooreffects(uchain, u.ux, u.uy, ""); /* chain might rust */</span>
+
  <span id="line113">113.    (void) flooreffects(uchain, u.ux, u.uy, ""); /* chain might rust */</span>
  <span id="line114">114.  </span>
+
  <span id="line114">114. </span>
  <span id="line115">115.      if (carried(uball)) /* the ball is carried */</span>
+
  <span id="line115">115.    if (carried(uball)) /* the ball is carried */</span>
  <span id="line116">116.          u.bc_order = BCPOS_DIFFER;</span>
+
  <span id="line116">116.        u.bc_order = BCPOS_DIFFER;</span>
  <span id="line117">117.      else {</span>
+
  <span id="line117">117.    else {</span>
  <span id="line118">118.          /* ball might rust -- already checked when carried */</span>
+
  <span id="line118">118.        /* ball might rust -- already checked when carried */</span>
  <span id="line119">119.          (void) flooreffects(uball, u.ux, u.uy, "");</span>
+
  <span id="line119">119.        (void) flooreffects(uball, u.ux, u.uy, "");</span>
  <span id="line120">120.          place_object(uball, u.ux, u.uy);</span>
+
  <span id="line120">120.        place_object(uball, u.ux, u.uy);</span>
  <span id="line121">121.          u.bc_order = BCPOS_CHAIN;</span>
+
  <span id="line121">121.        u.bc_order = BCPOS_CHAIN;</span>
  <span id="line122">122.      }</span>
+
  <span id="line122">122.    }</span>
  <span id="line123">123.  </span>
+
  <span id="line123">123. </span>
  <span id="line124">124.      place_object(uchain, u.ux, u.uy);</span>
+
  <span id="line124">124.    place_object(uchain, u.ux, u.uy);</span>
  <span id="line125">125.  </span>
+
  <span id="line125">125. </span>
  <span id="line126">126.      u.bglyph = u.cglyph = levl[u.ux][u.uy].glyph; /* pick up glyph */</span>
+
  <span id="line126">126.    u.bglyph = u.cglyph = levl[u.ux][u.uy].glyph; /* pick up glyph */</span>
  <span id="line127">127.  </span>
+
  <span id="line127">127. </span>
  <span id="line128">128.      newsym(u.ux, u.uy);</span>
+
  <span id="line128">128.    newsym(u.ux, u.uy);</span>
  <span id="line129">129.  }</span>
+
  <span id="line129">129. }</span>
  <span id="line130">130.  </span>
+
  <span id="line130">130. </span>
  
 
== unplacebc ==
 
== unplacebc ==
 
      
 
      
  <span id="line131">131.  void</span>
+
  <span id="line131">131. void</span>
  <span id="line132">132.  unplacebc()</span>
+
  <span id="line132">132. unplacebc()</span>
  <span id="line133">133.  {</span>
+
  <span id="line133">133. {</span>
  <span id="line134">134.      if (u.uswallow) {</span>
+
  <span id="line134">134.    if (u.uswallow) {</span>
  <span id="line135">135.          if (Is_waterlevel(&u.uz)) {</span>
+
  <span id="line135">135.        if (Is_waterlevel(&u.uz)) {</span>
  <span id="line136">136.              /* we need to proceed with the removal from the floor</span>
+
  <span id="line136">136.            /* we need to proceed with the removal from the floor</span>
  <span id="line137">137.              * so that movebubbles() processing will disregard it as</span>
+
  <span id="line137">137.              * so that movebubbles() processing will disregard it as</span>
  <span id="line138">138.              * intended. Ignore all the vision stuff.</span>
+
  <span id="line138">138.              * intended. Ignore all the vision stuff.</span>
  <span id="line139">139.              */</span>
+
  <span id="line139">139.              */</span>
  <span id="line140">140.              if (!carried(uball))</span>
+
  <span id="line140">140.            if (!carried(uball))</span>
  <span id="line141">141.                  obj_extract_self(uball);</span>
+
  <span id="line141">141.                obj_extract_self(uball);</span>
  <span id="line142">142.              obj_extract_self(uchain);</span>
+
  <span id="line142">142.            obj_extract_self(uchain);</span>
  <span id="line143">143.          }</span>
+
  <span id="line143">143.        }</span>
  <span id="line144">144.          /* ball&chain not unplaced while swallowed */</span>
+
  <span id="line144">144.        /* ball&chain not unplaced while swallowed */</span>
  <span id="line145">145.          return;</span>
+
  <span id="line145">145.        return;</span>
  <span id="line146">146.      }</span>
+
  <span id="line146">146.    }</span>
  <span id="line147">147.  </span>
+
  <span id="line147">147. </span>
  <span id="line148">148.      if (!carried(uball)) {</span>
+
  <span id="line148">148.    if (!carried(uball)) {</span>
  <span id="line149">149.          obj_extract_self(uball);</span>
+
  <span id="line149">149.        obj_extract_self(uball);</span>
  <span id="line150">150.          if (Blind && (u.bc_felt & BC_BALL)) /* drop glyph */</span>
+
  <span id="line150">150.        if (Blind && (u.bc_felt & BC_BALL)) /* drop glyph */</span>
  <span id="line151">151.              levl[uball->ox][uball->oy].glyph = u.bglyph;</span>
+
  <span id="line151">151.            levl[uball->ox][uball->oy].glyph = u.bglyph;</span>
  <span id="line152">152.  </span>
+
  <span id="line152">152. </span>
  <span id="line153">153.          newsym(uball->ox, uball->oy);</span>
+
  <span id="line153">153.        newsym(uball->ox, uball->oy);</span>
  <span id="line154">154.      }</span>
+
  <span id="line154">154.    }</span>
  <span id="line155">155.      obj_extract_self(uchain);</span>
+
  <span id="line155">155.    obj_extract_self(uchain);</span>
  <span id="line156">156.      if (Blind && (u.bc_felt & BC_CHAIN)) /* drop glyph */</span>
+
  <span id="line156">156.    if (Blind && (u.bc_felt & BC_CHAIN)) /* drop glyph */</span>
  <span id="line157">157.          levl[uchain->ox][uchain->oy].glyph = u.cglyph;</span>
+
  <span id="line157">157.        levl[uchain->ox][uchain->oy].glyph = u.cglyph;</span>
  <span id="line158">158.  </span>
+
  <span id="line158">158. </span>
  <span id="line159">159.      newsym(uchain->ox, uchain->oy);</span>
+
  <span id="line159">159.    newsym(uchain->ox, uchain->oy);</span>
  <span id="line160">160.      u.bc_felt = 0; /* feel nothing */</span>
+
  <span id="line160">160.    u.bc_felt = 0; /* feel nothing */</span>
  <span id="line161">161.  }</span>
+
  <span id="line161">161. }</span>
  <span id="line162">162.  </span>
+
  <span id="line162">162. </span>
  
 
== bc_order ==
 
== bc_order ==
 
      
 
      
  <span id="line163">163.  /*</span>
+
  <span id="line163">163. /*</span>
  <span id="line164">164.  *  Return the stacking of the hero's ball & chain.  This assumes that the</span>
+
  <span id="line164">164.  *  Return the stacking of the hero's ball & chain.  This assumes that the</span>
  <span id="line165">165.  *  hero is being punished.</span>
+
  <span id="line165">165.  *  hero is being punished.</span>
  <span id="line166">166.  */</span>
+
  <span id="line166">166.  */</span>
  <span id="line167">167.  STATIC_OVL int</span>
+
  <span id="line167">167. STATIC_OVL int</span>
  <span id="line168">168.  bc_order()</span>
+
  <span id="line168">168. bc_order()</span>
  <span id="line169">169.  {</span>
+
  <span id="line169">169. {</span>
  <span id="line170">170.      struct obj *obj;</span>
+
  <span id="line170">170.    struct obj *obj;</span>
  <span id="line171">171.  </span>
+
  <span id="line171">171. </span>
  <span id="line172">172.      if (uchain->ox != uball->ox || uchain->oy != uball->oy || carried(uball)</span>
+
  <span id="line172">172.    if (uchain->ox != uball->ox || uchain->oy != uball->oy || carried(uball)</span>
  <span id="line173">173.          || u.uswallow)</span>
+
  <span id="line173">173.        || u.uswallow)</span>
  <span id="line174">174.          return BCPOS_DIFFER;</span>
+
  <span id="line174">174.        return BCPOS_DIFFER;</span>
  <span id="line175">175.  </span>
+
  <span id="line175">175. </span>
  <span id="line176">176.      for (obj = level.objects[uball->ox][uball->oy]; obj;</span>
+
  <span id="line176">176.    for (obj = level.objects[uball->ox][uball->oy]; obj;</span>
  <span id="line177">177.          obj = obj->nexthere) {</span>
+
  <span id="line177">177.          obj = obj->nexthere) {</span>
  <span id="line178">178.          if (obj == uchain)</span>
+
  <span id="line178">178.        if (obj == uchain)</span>
  <span id="line179">179.              return BCPOS_CHAIN;</span>
+
  <span id="line179">179.            return BCPOS_CHAIN;</span>
  <span id="line180">180.          if (obj == uball)</span>
+
  <span id="line180">180.        if (obj == uball)</span>
  <span id="line181">181.              return BCPOS_BALL;</span>
+
  <span id="line181">181.            return BCPOS_BALL;</span>
  <span id="line182">182.      }</span>
+
  <span id="line182">182.    }</span>
  <span id="line183">183.      impossible("bc_order:  ball&chain not in same location!");</span>
+
  <span id="line183">183.    impossible("bc_order:  ball&chain not in same location!");</span>
  <span id="line184">184.      return BCPOS_DIFFER;</span>
+
  <span id="line184">184.    return BCPOS_DIFFER;</span>
  <span id="line185">185.  }</span>
+
  <span id="line185">185. }</span>
  <span id="line186">186.  </span>
+
  <span id="line186">186. </span>
  
 
== set_bc ==
 
== set_bc ==
 
      
 
      
  <span id="line187">187.  /*</span>
+
  <span id="line187">187. /*</span>
  <span id="line188">188.  *  set_bc()</span>
+
  <span id="line188">188.  *  set_bc()</span>
  <span id="line189">189.  *</span>
+
  <span id="line189">189.  *</span>
  <span id="line190">190.  *  The hero is either about to go blind or already blind and just punished.</span>
+
  <span id="line190">190.  *  The hero is either about to go blind or already blind and just punished.</span>
  <span id="line191">191.  *  Set up the ball and chain variables so that the ball and chain are "felt".</span>
+
  <span id="line191">191.  *  Set up the ball and chain variables so that the ball and chain are "felt".</span>
  <span id="line192">192.  */</span>
+
  <span id="line192">192.  */</span>
  <span id="line193">193.  void</span>
+
  <span id="line193">193. void</span>
  <span id="line194">194.  set_bc(already_blind)</span>
+
  <span id="line194">194. set_bc(already_blind)</span>
  <span id="line195">195.  int already_blind;</span>
+
  <span id="line195">195. int already_blind;</span>
  <span id="line196">196.  {</span>
+
  <span id="line196">196. {</span>
  <span id="line197">197.      int ball_on_floor = !carried(uball);</span>
+
  <span id="line197">197.    int ball_on_floor = !carried(uball);</span>
  <span id="line198">198.  </span>
+
  <span id="line198">198. </span>
  <span id="line199">199.      u.bc_order = bc_order(); /* get the order */</span>
+
  <span id="line199">199.    u.bc_order = bc_order(); /* get the order */</span>
  <span id="line200">200.      u.bc_felt = ball_on_floor ? BC_BALL | BC_CHAIN : BC_CHAIN; /* felt */</span>
+
  <span id="line200">200.    u.bc_felt = ball_on_floor ? BC_BALL | BC_CHAIN : BC_CHAIN; /* felt */</span>
  <span id="line201">201.  </span>
+
  <span id="line201">201. </span>
  <span id="line202">202.      if (already_blind || u.uswallow) {</span>
+
  <span id="line202">202.    if (already_blind || u.uswallow) {</span>
  <span id="line203">203.          u.cglyph = u.bglyph = levl[u.ux][u.uy].glyph;</span>
+
  <span id="line203">203.        u.cglyph = u.bglyph = levl[u.ux][u.uy].glyph;</span>
  <span id="line204">204.          return;</span>
+
  <span id="line204">204.        return;</span>
  <span id="line205">205.      }</span>
+
  <span id="line205">205.    }</span>
  <span id="line206">206.  </span>
+
  <span id="line206">206. </span>
  <span id="line207">207.      /*</span>
+
  <span id="line207">207.    /*</span>
  <span id="line208">208.      *  Since we can still see, remove the ball&chain and get the glyph that</span>
+
  <span id="line208">208.      *  Since we can still see, remove the ball&chain and get the glyph that</span>
  <span id="line209">209.      *  would be beneath them.  Then put the ball&chain back.  This is pretty</span>
+
  <span id="line209">209.      *  would be beneath them.  Then put the ball&chain back.  This is pretty</span>
  <span id="line210">210.      *  disgusting, but it will work.</span>
+
  <span id="line210">210.      *  disgusting, but it will work.</span>
  <span id="line211">211.      */</span>
+
  <span id="line211">211.      */</span>
  <span id="line212">212.      remove_object(uchain);</span>
+
  <span id="line212">212.    remove_object(uchain);</span>
  <span id="line213">213.      if (ball_on_floor)</span>
+
  <span id="line213">213.    if (ball_on_floor)</span>
  <span id="line214">214.          remove_object(uball);</span>
+
  <span id="line214">214.        remove_object(uball);</span>
  <span id="line215">215.  </span>
+
  <span id="line215">215. </span>
  <span id="line216">216.      newsym(uchain->ox, uchain->oy);</span>
+
  <span id="line216">216.    newsym(uchain->ox, uchain->oy);</span>
  <span id="line217">217.      u.cglyph = levl[uchain->ox][uchain->oy].glyph;</span>
+
  <span id="line217">217.    u.cglyph = levl[uchain->ox][uchain->oy].glyph;</span>
  <span id="line218">218.  </span>
+
  <span id="line218">218. </span>
  <span id="line219">219.      if (u.bc_order == BCPOS_DIFFER) { /* different locations */</span>
+
  <span id="line219">219.    if (u.bc_order == BCPOS_DIFFER) { /* different locations */</span>
  <span id="line220">220.          place_object(uchain, uchain->ox, uchain->oy);</span>
+
  <span id="line220">220.        place_object(uchain, uchain->ox, uchain->oy);</span>
  <span id="line221">221.          newsym(uchain->ox, uchain->oy);</span>
+
  <span id="line221">221.        newsym(uchain->ox, uchain->oy);</span>
  <span id="line222">222.          if (ball_on_floor) {</span>
+
  <span id="line222">222.        if (ball_on_floor) {</span>
  <span id="line223">223.              newsym(uball->ox, uball->oy); /* see under ball */</span>
+
  <span id="line223">223.            newsym(uball->ox, uball->oy); /* see under ball */</span>
  <span id="line224">224.              u.bglyph = levl[uball->ox][uball->oy].glyph;</span>
+
  <span id="line224">224.            u.bglyph = levl[uball->ox][uball->oy].glyph;</span>
  <span id="line225">225.              place_object(uball, uball->ox, uball->oy);</span>
+
  <span id="line225">225.            place_object(uball, uball->ox, uball->oy);</span>
  <span id="line226">226.              newsym(uball->ox, uball->oy); /* restore ball */</span>
+
  <span id="line226">226.            newsym(uball->ox, uball->oy); /* restore ball */</span>
  <span id="line227">227.          }</span>
+
  <span id="line227">227.        }</span>
  <span id="line228">228.      } else {</span>
+
  <span id="line228">228.    } else {</span>
  <span id="line229">229.          u.bglyph = u.cglyph;</span>
+
  <span id="line229">229.        u.bglyph = u.cglyph;</span>
  <span id="line230">230.          if (u.bc_order == BCPOS_CHAIN) {</span>
+
  <span id="line230">230.        if (u.bc_order == BCPOS_CHAIN) {</span>
  <span id="line231">231.              place_object(uball, uball->ox, uball->oy);</span>
+
  <span id="line231">231.            place_object(uball, uball->ox, uball->oy);</span>
  <span id="line232">232.              place_object(uchain, uchain->ox, uchain->oy);</span>
+
  <span id="line232">232.            place_object(uchain, uchain->ox, uchain->oy);</span>
  <span id="line233">233.          } else {</span>
+
  <span id="line233">233.        } else {</span>
  <span id="line234">234.              place_object(uchain, uchain->ox, uchain->oy);</span>
+
  <span id="line234">234.            place_object(uchain, uchain->ox, uchain->oy);</span>
  <span id="line235">235.              place_object(uball, uball->ox, uball->oy);</span>
+
  <span id="line235">235.            place_object(uball, uball->ox, uball->oy);</span>
  <span id="line236">236.          }</span>
+
  <span id="line236">236.        }</span>
  <span id="line237">237.          newsym(uball->ox, uball->oy);</span>
+
  <span id="line237">237.        newsym(uball->ox, uball->oy);</span>
  <span id="line238">238.      }</span>
+
  <span id="line238">238.    }</span>
  <span id="line239">239.  }</span>
+
  <span id="line239">239. }</span>
  <span id="line240">240.  </span>
+
  <span id="line240">240. </span>
  
 
== move_bc ==
 
== move_bc ==
 
      
 
      
  <span id="line241">241.  /*</span>
+
  <span id="line241">241. /*</span>
  <span id="line242">242.  *  move_bc()</span>
+
  <span id="line242">242.  *  move_bc()</span>
  <span id="line243">243.  *</span>
+
  <span id="line243">243.  *</span>
  <span id="line244">244.  *  Move the ball and chain.  This is called twice for every move.  The first</span>
+
  <span id="line244">244.  *  Move the ball and chain.  This is called twice for every move.  The first</span>
  <span id="line245">245.  *  time to pick up the ball and chain before the move, the second time to</span>
+
  <span id="line245">245.  *  time to pick up the ball and chain before the move, the second time to</span>
  <span id="line246">246.  *  place the ball and chain after the move.  If the ball is carried, this</span>
+
  <span id="line246">246.  *  place the ball and chain after the move.  If the ball is carried, this</span>
  <span id="line247">247.  *  function should never have BC_BALL as part of its control.</span>
+
  <span id="line247">247.  *  function should never have BC_BALL as part of its control.</span>
  <span id="line248">248.  *</span>
+
  <span id="line248">248.  *</span>
  <span id="line249">249.  *  Should not be called while swallowed.</span>
+
  <span id="line249">249.  *  Should not be called while swallowed.</span>
  <span id="line250">250.  */</span>
+
  <span id="line250">250.  */</span>
  <span id="line251">251.  void</span>
+
  <span id="line251">251. void</span>
  <span id="line252">252.  move_bc(before, control, ballx, bally, chainx, chainy)</span>
+
  <span id="line252">252. move_bc(before, control, ballx, bally, chainx, chainy)</span>
  <span id="line253">253.  int before, control;</span>
+
  <span id="line253">253. int before, control;</span>
  <span id="line254">254.  xchar ballx, bally, chainx, chainy; /* only matter !before */</span>
+
  <span id="line254">254. xchar ballx, bally, chainx, chainy; /* only matter !before */</span>
  <span id="line255">255.  {</span>
+
  <span id="line255">255. {</span>
  <span id="line256">256.      if (Blind) {</span>
+
  <span id="line256">256.    if (Blind) {</span>
  <span id="line257">257.          /*</span>
+
  <span id="line257">257.        /*</span>
  <span id="line258">258.          *  The hero is blind.  Time to work hard.  The ball and chain that</span>
+
  <span id="line258">258.          *  The hero is blind.  Time to work hard.  The ball and chain that</span>
  <span id="line259">259.          *  are attached to the hero are very special.  The hero knows that</span>
+
  <span id="line259">259.          *  are attached to the hero are very special.  The hero knows that</span>
  <span id="line260">260.          *  they are attached, so when they move, the hero knows that they</span>
+
  <span id="line260">260.          *  they are attached, so when they move, the hero knows that they</span>
  <span id="line261">261.          *  aren't at the last position remembered.  This is complicated</span>
+
  <span id="line261">261.          *  aren't at the last position remembered.  This is complicated</span>
  <span id="line262">262.          *  by the fact that the hero can "feel" the surrounding locations</span>
+
  <span id="line262">262.          *  by the fact that the hero can "feel" the surrounding locations</span>
  <span id="line263">263.          *  at any time, hence, making one or both of them show up again.</span>
+
  <span id="line263">263.          *  at any time, hence, making one or both of them show up again.</span>
  <span id="line264">264.          *  So, we have to keep track of which is felt at any one time and</span>
+
  <span id="line264">264.          *  So, we have to keep track of which is felt at any one time and</span>
  <span id="line265">265.          *  act accordingly.</span>
+
  <span id="line265">265.          *  act accordingly.</span>
  <span id="line266">266.          */</span>
+
  <span id="line266">266.          */</span>
  <span id="line267">267.          if (!before) {</span>
+
  <span id="line267">267.        if (!before) {</span>
  <span id="line268">268.              if ((control & BC_CHAIN) && (control & BC_BALL)) {</span>
+
  <span id="line268">268.            if ((control & BC_CHAIN) && (control & BC_BALL)) {</span>
  <span id="line269">269.                  /*</span>
+
  <span id="line269">269.                /*</span>
  <span id="line270">270.                  *  Both ball and chain moved.  If felt, drop glyph.</span>
+
  <span id="line270">270.                  *  Both ball and chain moved.  If felt, drop glyph.</span>
  <span id="line271">271.                  */</span>
+
  <span id="line271">271.                  */</span>
  <span id="line272">272.                  if (u.bc_felt & BC_BALL)</span>
+
  <span id="line272">272.                if (u.bc_felt & BC_BALL)</span>
  <span id="line273">273.                      levl[uball->ox][uball->oy].glyph = u.bglyph;</span>
+
  <span id="line273">273.                    levl[uball->ox][uball->oy].glyph = u.bglyph;</span>
  <span id="line274">274.                  if (u.bc_felt & BC_CHAIN)</span>
+
  <span id="line274">274.                if (u.bc_felt & BC_CHAIN)</span>
  <span id="line275">275.                      levl[uchain->ox][uchain->oy].glyph = u.cglyph;</span>
+
  <span id="line275">275.                    levl[uchain->ox][uchain->oy].glyph = u.cglyph;</span>
  <span id="line276">276.                  u.bc_felt = 0;</span>
+
  <span id="line276">276.                u.bc_felt = 0;</span>
  <span id="line277">277.  </span>
+
  <span id="line277">277. </span>
  <span id="line278">278.                  /* Pick up glyph at new location. */</span>
+
  <span id="line278">278.                /* Pick up glyph at new location. */</span>
  <span id="line279">279.                  u.bglyph = levl[ballx][bally].glyph;</span>
+
  <span id="line279">279.                u.bglyph = levl[ballx][bally].glyph;</span>
  <span id="line280">280.                  u.cglyph = levl[chainx][chainy].glyph;</span>
+
  <span id="line280">280.                u.cglyph = levl[chainx][chainy].glyph;</span>
  <span id="line281">281.  </span>
+
  <span id="line281">281. </span>
  <span id="line282">282.                  movobj(uball, ballx, bally);</span>
+
  <span id="line282">282.                movobj(uball, ballx, bally);</span>
  <span id="line283">283.                  movobj(uchain, chainx, chainy);</span>
+
  <span id="line283">283.                movobj(uchain, chainx, chainy);</span>
  <span id="line284">284.              } else if (control & BC_BALL) {</span>
+
  <span id="line284">284.            } else if (control & BC_BALL) {</span>
  <span id="line285">285.                  if (u.bc_felt & BC_BALL) {</span>
+
  <span id="line285">285.                if (u.bc_felt & BC_BALL) {</span>
  <span id="line286">286.                      if (u.bc_order == BCPOS_DIFFER) { /* ball by itself */</span>
+
  <span id="line286">286.                    if (u.bc_order == BCPOS_DIFFER) { /* ball by itself */</span>
  <span id="line287">287.                          levl[uball->ox][uball->oy].glyph = u.bglyph;</span>
+
  <span id="line287">287.                        levl[uball->ox][uball->oy].glyph = u.bglyph;</span>
  <span id="line288">288.                      } else if (u.bc_order == BCPOS_BALL) {</span>
+
  <span id="line288">288.                    } else if (u.bc_order == BCPOS_BALL) {</span>
  <span id="line289">289.                          if (u.bc_felt & BC_CHAIN) { /* know chain is there */</span>
+
  <span id="line289">289.                        if (u.bc_felt & BC_CHAIN) { /* know chain is there */</span>
  <span id="line290">290.                              map_object(uchain, 0);</span>
+
  <span id="line290">290.                            map_object(uchain, 0);</span>
  <span id="line291">291.                          } else {</span>
+
  <span id="line291">291.                        } else {</span>
  <span id="line292">292.                              levl[uball->ox][uball->oy].glyph = u.bglyph;</span>
+
  <span id="line292">292.                            levl[uball->ox][uball->oy].glyph = u.bglyph;</span>
  <span id="line293">293.                          }</span>
+
  <span id="line293">293.                        }</span>
  <span id="line294">294.                      }</span>
+
  <span id="line294">294.                    }</span>
  <span id="line295">295.                      u.bc_felt &= ~BC_BALL; /* no longer feel the ball */</span>
+
  <span id="line295">295.                    u.bc_felt &= ~BC_BALL; /* no longer feel the ball */</span>
  <span id="line296">296.                  }</span>
+
  <span id="line296">296.                }</span>
  <span id="line297">297.  </span>
+
  <span id="line297">297. </span>
  <span id="line298">298.                  /* Pick up glyph at new position. */</span>
+
  <span id="line298">298.                /* Pick up glyph at new position. */</span>
  <span id="line299">299.                  u.bglyph = (ballx != chainx || bally != chainy)</span>
+
  <span id="line299">299.                u.bglyph = (ballx != chainx || bally != chainy)</span>
  <span id="line300">300.                                ? levl[ballx][bally].glyph</span>
+
  <span id="line300">300.                                ? levl[ballx][bally].glyph</span>
  <span id="line301">301.                                : u.cglyph;</span>
+
  <span id="line301">301.                                : u.cglyph;</span>
  <span id="line302">302.  </span>
+
  <span id="line302">302. </span>
  <span id="line303">303.                  movobj(uball, ballx, bally);</span>
+
  <span id="line303">303.                movobj(uball, ballx, bally);</span>
  <span id="line304">304.              } else if (control & BC_CHAIN) {</span>
+
  <span id="line304">304.            } else if (control & BC_CHAIN) {</span>
  <span id="line305">305.                  if (u.bc_felt & BC_CHAIN) {</span>
+
  <span id="line305">305.                if (u.bc_felt & BC_CHAIN) {</span>
  <span id="line306">306.                      if (u.bc_order == BCPOS_DIFFER) {</span>
+
  <span id="line306">306.                    if (u.bc_order == BCPOS_DIFFER) {</span>
  <span id="line307">307.                          levl[uchain->ox][uchain->oy].glyph = u.cglyph;</span>
+
  <span id="line307">307.                        levl[uchain->ox][uchain->oy].glyph = u.cglyph;</span>
  <span id="line308">308.                      } else if (u.bc_order == BCPOS_CHAIN) {</span>
+
  <span id="line308">308.                    } else if (u.bc_order == BCPOS_CHAIN) {</span>
  <span id="line309">309.                          if (u.bc_felt & BC_BALL) {</span>
+
  <span id="line309">309.                        if (u.bc_felt & BC_BALL) {</span>
  <span id="line310">310.                              map_object(uball, 0);</span>
+
  <span id="line310">310.                            map_object(uball, 0);</span>
  <span id="line311">311.                          } else {</span>
+
  <span id="line311">311.                        } else {</span>
  <span id="line312">312.                              levl[uchain->ox][uchain->oy].glyph = u.cglyph;</span>
+
  <span id="line312">312.                            levl[uchain->ox][uchain->oy].glyph = u.cglyph;</span>
  <span id="line313">313.                          }</span>
+
  <span id="line313">313.                        }</span>
  <span id="line314">314.                      }</span>
+
  <span id="line314">314.                    }</span>
  <span id="line315">315.                      u.bc_felt &= ~BC_CHAIN;</span>
+
  <span id="line315">315.                    u.bc_felt &= ~BC_CHAIN;</span>
  <span id="line316">316.                  }</span>
+
  <span id="line316">316.                }</span>
  <span id="line317">317.                  /* Pick up glyph at new position. */</span>
+
  <span id="line317">317.                /* Pick up glyph at new position. */</span>
  <span id="line318">318.                  u.cglyph = (ballx != chainx || bally != chainy)</span>
+
  <span id="line318">318.                u.cglyph = (ballx != chainx || bally != chainy)</span>
  <span id="line319">319.                                ? levl[chainx][chainy].glyph</span>
+
  <span id="line319">319.                                ? levl[chainx][chainy].glyph</span>
  <span id="line320">320.                                : u.bglyph;</span>
+
  <span id="line320">320.                                : u.bglyph;</span>
  <span id="line321">321.  </span>
+
  <span id="line321">321. </span>
  <span id="line322">322.                  movobj(uchain, chainx, chainy);</span>
+
  <span id="line322">322.                movobj(uchain, chainx, chainy);</span>
  <span id="line323">323.              }</span>
+
  <span id="line323">323.            }</span>
  <span id="line324">324.  </span>
+
  <span id="line324">324. </span>
  <span id="line325">325.              u.bc_order = bc_order(); /* reset the order */</span>
+
  <span id="line325">325.            u.bc_order = bc_order(); /* reset the order */</span>
  <span id="line326">326.          }</span>
+
  <span id="line326">326.        }</span>
  <span id="line327">327.  </span>
+
  <span id="line327">327. </span>
  <span id="line328">328.      } else {</span>
+
  <span id="line328">328.    } else {</span>
  <span id="line329">329.          /*</span>
+
  <span id="line329">329.        /*</span>
  <span id="line330">330.          *  The hero is not blind.  To make this work correctly, we need to</span>
+
  <span id="line330">330.          *  The hero is not blind.  To make this work correctly, we need to</span>
  <span id="line331">331.          *  pick up the ball and chain before the hero moves, then put them</span>
+
  <span id="line331">331.          *  pick up the ball and chain before the hero moves, then put them</span>
  <span id="line332">332.          *  in their new positions after the hero moves.</span>
+
  <span id="line332">332.          *  in their new positions after the hero moves.</span>
  <span id="line333">333.          */</span>
+
  <span id="line333">333.          */</span>
  <span id="line334">334.          if (before) {</span>
+
  <span id="line334">334.        if (before) {</span>
  <span id="line335">335.              if (!control) {</span>
+
  <span id="line335">335.            if (!control) {</span>
  <span id="line336">336.                  /*</span>
+
  <span id="line336">336.                /*</span>
  <span id="line337">337.                  * Neither ball nor chain is moving, so remember which was</span>
+
  <span id="line337">337.                  * Neither ball nor chain is moving, so remember which was</span>
  <span id="line338">338.                  * on top until !before.  Use the variable u.bc_order</span>
+
  <span id="line338">338.                  * on top until !before.  Use the variable u.bc_order</span>
  <span id="line339">339.                  * since it is only valid when blind.</span>
+
  <span id="line339">339.                  * since it is only valid when blind.</span>
  <span id="line340">340.                  */</span>
+
  <span id="line340">340.                  */</span>
  <span id="line341">341.                  u.bc_order = bc_order();</span>
+
  <span id="line341">341.                u.bc_order = bc_order();</span>
  <span id="line342">342.              }</span>
+
  <span id="line342">342.            }</span>
  <span id="line343">343.  </span>
+
  <span id="line343">343. </span>
  <span id="line344">344.              remove_object(uchain);</span>
+
  <span id="line344">344.            remove_object(uchain);</span>
  <span id="line345">345.              newsym(uchain->ox, uchain->oy);</span>
+
  <span id="line345">345.            newsym(uchain->ox, uchain->oy);</span>
  <span id="line346">346.              if (!carried(uball)) {</span>
+
  <span id="line346">346.            if (!carried(uball)) {</span>
  <span id="line347">347.                  remove_object(uball);</span>
+
  <span id="line347">347.                remove_object(uball);</span>
  <span id="line348">348.                  newsym(uball->ox, uball->oy);</span>
+
  <span id="line348">348.                newsym(uball->ox, uball->oy);</span>
  <span id="line349">349.              }</span>
+
  <span id="line349">349.            }</span>
  <span id="line350">350.          } else {</span>
+
  <span id="line350">350.        } else {</span>
  <span id="line351">351.              int on_floor = !carried(uball);</span>
+
  <span id="line351">351.            int on_floor = !carried(uball);</span>
  <span id="line352">352.  </span>
+
  <span id="line352">352. </span>
  <span id="line353">353.              if ((control & BC_CHAIN)</span>
+
  <span id="line353">353.            if ((control & BC_CHAIN)</span>
  <span id="line354">354.                  || (!control && u.bc_order == BCPOS_CHAIN)) {</span>
+
  <span id="line354">354.                || (!control && u.bc_order == BCPOS_CHAIN)) {</span>
  <span id="line355">355.                  /* If the chain moved or nothing moved & chain on top. */</span>
+
  <span id="line355">355.                /* If the chain moved or nothing moved & chain on top. */</span>
  <span id="line356">356.                  if (on_floor)</span>
+
  <span id="line356">356.                if (on_floor)</span>
  <span id="line357">357.                      place_object(uball, ballx, bally);</span>
+
  <span id="line357">357.                    place_object(uball, ballx, bally);</span>
  <span id="line358">358.                  place_object(uchain, chainx, chainy); /* chain on top */</span>
+
  <span id="line358">358.                place_object(uchain, chainx, chainy); /* chain on top */</span>
  <span id="line359">359.              } else {</span>
+
  <span id="line359">359.            } else {</span>
  <span id="line360">360.                  place_object(uchain, chainx, chainy);</span>
+
  <span id="line360">360.                place_object(uchain, chainx, chainy);</span>
  <span id="line361">361.                  if (on_floor)</span>
+
  <span id="line361">361.                if (on_floor)</span>
  <span id="line362">362.                      place_object(uball, ballx, bally);</span>
+
  <span id="line362">362.                    place_object(uball, ballx, bally);</span>
  <span id="line363">363.                  /* ball on top */</span>
+
  <span id="line363">363.                /* ball on top */</span>
  <span id="line364">364.              }</span>
+
  <span id="line364">364.            }</span>
  <span id="line365">365.              newsym(chainx, chainy);</span>
+
  <span id="line365">365.            newsym(chainx, chainy);</span>
  <span id="line366">366.              if (on_floor)</span>
+
  <span id="line366">366.            if (on_floor)</span>
  <span id="line367">367.                  newsym(ballx, bally);</span>
+
  <span id="line367">367.                newsym(ballx, bally);</span>
  <span id="line368">368.          }</span>
+
  <span id="line368">368.        }</span>
  <span id="line369">369.      }</span>
+
  <span id="line369">369.    }</span>
  <span id="line370">370.  }</span>
+
  <span id="line370">370. }</span>
  <span id="line371">371.  </span>
+
  <span id="line371">371. </span>
  
 
== drag_ball ==
 
== drag_ball ==
 
      
 
      
<span id="line372">372.  /* return TRUE if the caller needs to place the ball and chain down again</span>
+
<span id="line372">372. /* return TRUE if the caller needs to place the ball and chain down again</span>
<span id="line373">373.   *</span>
+
<span id="line373">373.  *</span>
<span id="line374">374.   *  Should not be called while swallowed.  Should be called before movement,</span>
+
<span id="line374">374.  *  Should not be called while swallowed.  Should be called before movement,</span>
<span id="line375">375.   *  because we might want to move the ball or chain to the hero's old</span>
+
<span id="line375">375.  *  because we might want to move the ball or chain to the hero's old</span>
<span id="line376">376.   * position.</span>
+
<span id="line376">376.  * position.</span>
<span id="line377">377.   *</span>
+
<span id="line377">377.  *</span>
<span id="line378">378.   * It is called if we are moving.  It is also called if we are teleporting</span>
+
<span id="line378">378.  * It is called if we are moving.  It is also called if we are teleporting</span>
<span id="line379">379.   * *if* the ball doesn't move and we thus must drag the chain.  It is not</span>
+
<span id="line379">379.  * *if* the ball doesn't move and we thus must drag the chain.  It is not</span>
<span id="line380">380.   * called for ordinary teleportation.</span>
+
<span id="line380">380.  * called for ordinary teleportation.</span>
<span id="line381">381.   *</span>
+
<span id="line381">381.  *</span>
<span id="line382">382.   * allow_drag is only used in the ugly special case where teleporting must</span>
+
<span id="line382">382.  * allow_drag is only used in the ugly special case where teleporting must</span>
 +
<span id="line383">
  
 
== drop_ball ==
 
== drop_ball ==
 
      
 
      
  <span id="line683">683.  /*</span>
+
  <span id="line683">683. /*</span>
  <span id="line684">684.  *  drop_ball()</span>
+
  <span id="line684">684.  *  drop_ball()</span>
  <span id="line685">685.  *</span>
+
  <span id="line685">685.  *</span>
  <span id="line686">686.  *  The punished hero drops or throws her iron ball.  If the hero is</span>
+
  <span id="line686">686.  *  The punished hero drops or throws her iron ball.  If the hero is</span>
  <span id="line687">687.  *  blind, we must reset the order and glyph.  Check for side effects.</span>
+
  <span id="line687">687.  *  blind, we must reset the order and glyph.  Check for side effects.</span>
  <span id="line688">688.  *  This routine expects the ball to be already placed.</span>
+
  <span id="line688">688.  *  This routine expects the ball to be already placed.</span>
  <span id="line689">689.  *</span>
+
  <span id="line689">689.  *</span>
  <span id="line690">690.  *  Should not be called while swallowed.</span>
+
  <span id="line690">690.  *  Should not be called while swallowed.</span>
  <span id="line691">691.  */</span>
+
  <span id="line691">691.  */</span>
  <span id="line692">692.  void</span>
+
  <span id="line692">692. void</span>
  <span id="line693">693.  drop_ball(x, y)</span>
+
  <span id="line693">693. drop_ball(x, y)</span>
  <span id="line694">694.  xchar x, y;</span>
+
  <span id="line694">694. xchar x, y;</span>
  <span id="line695">695.  {</span>
+
  <span id="line695">695. {</span>
  <span id="line696">696.      if (Blind) {</span>
+
  <span id="line696">696.    if (Blind) {</span>
  <span id="line697">697.          /* get the order */</span>
+
  <span id="line697">697.        /* get the order */</span>
  <span id="line698">698.          u.bc_order = bc_order();</span>
+
  <span id="line698">698.        u.bc_order = bc_order();</span>
  <span id="line699">699.          /* pick up glyph */</span>
+
  <span id="line699">699.        /* pick up glyph */</span>
  <span id="line700">700.          u.bglyph = (u.bc_order) ? u.cglyph : levl[x][y].glyph;</span>
+
  <span id="line700">700.        u.bglyph = (u.bc_order) ? u.cglyph : levl[x][y].glyph;</span>
  <span id="line701">701.      }</span>
+
  <span id="line701">701.    }</span>
  <span id="line702">702.  </span>
+
  <span id="line702">702. </span>
  <span id="line703">703.      if (x != u.ux || y != u.uy) {</span>
+
  <span id="line703">703.    if (x != u.ux || y != u.uy) {</span>
  <span id="line704">704.          struct trap *t;</span>
+
  <span id="line704">704.        struct trap *t;</span>
  <span id="line705">705.          const char *pullmsg = "The ball pulls you out of the %s!";</span>
+
  <span id="line705">705.        const char *pullmsg = "The ball pulls you out of the %s!";</span>
  <span id="line706">706.  </span>
+
  <span id="line706">706. </span>
  <span id="line707">707.          if (u.utrap && u.utraptype != TT_INFLOOR</span>
+
  <span id="line707">707.        if (u.utrap && u.utraptype != TT_INFLOOR</span>
  <span id="line708">708.              && u.utraptype != TT_BURIEDBALL) {</span>
+
  <span id="line708">708.            && u.utraptype != TT_BURIEDBALL) {</span>
  <span id="line709">709.              switch (u.utraptype) {</span>
+
  <span id="line709">709.            switch (u.utraptype) {</span>
  <span id="line710">710.              case TT_PIT:</span>
+
  <span id="line710">710.            case TT_PIT:</span>
  <span id="line711">711.                  pline(pullmsg, "pit");</span>
+
  <span id="line711">711.                pline(pullmsg, "pit");</span>
  <span id="line712">712.                  break;</span>
+
  <span id="line712">712.                break;</span>
  <span id="line713">713.              case TT_WEB:</span>
+
  <span id="line713">713.            case TT_WEB:</span>
  <span id="line714">714.                  pline(pullmsg, "web");</span>
+
  <span id="line714">714.                pline(pullmsg, "web");</span>
  <span id="line715">715.                  pline_The("web is destroyed!");</span>
+
  <span id="line715">715.                pline_The("web is destroyed!");</span>
  <span id="line716">716.                  deltrap(t_at(u.ux, u.uy));</span>
+
  <span id="line716">716.                deltrap(t_at(u.ux, u.uy));</span>
  <span id="line717">717.                  break;</span>
+
  <span id="line717">717.                break;</span>
  <span id="line718">718.              case TT_LAVA:</span>
+
  <span id="line718">718.            case TT_LAVA:</span>
  <span id="line719">719.                  pline(pullmsg, "lava");</span>
+
  <span id="line719">719.                pline(pullmsg, "lava");</span>
  <span id="line720">720.                  break;</span>
+
  <span id="line720">720.                break;</span>
  <span id="line721">721.              case TT_BEARTRAP: {</span>
+
  <span id="line721">721.            case TT_BEARTRAP: {</span>
  <span id="line722">722.                  register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;</span>
+
  <span id="line722">722.                register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;</span>
  <span id="line723">723.                  pline(pullmsg, "bear trap");</span>
+
  <span id="line723">723.                pline(pullmsg, "bear trap");</span>
  <span id="line724">724.                  set_wounded_legs(side, rn1(1000, 500));</span>
+
  <span id="line724">724.                set_wounded_legs(side, rn1(1000, 500));</span>
  <span id="line725">725.                  if (!u.usteed) {</span>
+
  <span id="line725">725.                if (!u.usteed) {</span>
  <span id="line726">726.                      Your("%s %s is severely damaged.",</span>
+
  <span id="line726">726.                    Your("%s %s is severely damaged.",</span>
  <span id="line727">727.                          (side == LEFT_SIDE) ? "left" : "right",</span>
+
  <span id="line727">727.                          (side == LEFT_SIDE) ? "left" : "right",</span>
  <span id="line728">728.                          body_part(LEG));</span>
+
  <span id="line728">728.                          body_part(LEG));</span>
  <span id="line729">729.                      losehp(Maybe_Half_Phys(2),</span>
+
  <span id="line729">729.                    losehp(Maybe_Half_Phys(2),</span>
  <span id="line730">730.                            "leg damage from being pulled out of a bear trap",</span>
+
  <span id="line730">730.                            "leg damage from being pulled out of a bear trap",</span>
  <span id="line731">731.                            KILLED_BY);</span>
+
  <span id="line731">731.                            KILLED_BY);</span>
  <span id="line732">732.                  }</span>
+
  <span id="line732">732.                }</span>
  <span id="line733">733.                  break;</span>
+
  <span id="line733">733.                break;</span>
  <span id="line734">734.              }</span>
+
  <span id="line734">734.            }</span>
  <span id="line735">735.              }</span>
+
  <span id="line735">735.            }</span>
  <span id="line736">736.              u.utrap = 0;</span>
+
  <span id="line736">736.            u.utrap = 0;</span>
  <span id="line737">737.              fill_pit(u.ux, u.uy);</span>
+
  <span id="line737">737.            fill_pit(u.ux, u.uy);</span>
  <span id="line738">738.          }</span>
+
  <span id="line738">738.        }</span>
  <span id="line739">739.  </span>
+
  <span id="line739">739. </span>
  <span id="line740">740.          u.ux0 = u.ux;</span>
+
  <span id="line740">740.        u.ux0 = u.ux;</span>
  <span id="line741">741.          u.uy0 = u.uy;</span>
+
  <span id="line741">741.        u.uy0 = u.uy;</span>
  <span id="line742">742.          if (!Levitation && !MON_AT(x, y) && !u.utrap</span>
+
  <span id="line742">742.        if (!Levitation && !MON_AT(x, y) && !u.utrap</span>
  <span id="line743">743.              && (is_pool(x, y)</span>
+
  <span id="line743">743.            && (is_pool(x, y)</span>
  <span id="line744">744.                  || ((t = t_at(x, y))</span>
+
  <span id="line744">744.                || ((t = t_at(x, y))</span>
  <span id="line745">745.                      && (t->ttyp == PIT || t->ttyp == SPIKED_PIT</span>
+
  <span id="line745">745.                    && (t->ttyp == PIT || t->ttyp == SPIKED_PIT</span>
  <span id="line746">746.                          || t->ttyp == TRAPDOOR || t->ttyp == HOLE)))) {</span>
+
  <span id="line746">746.                        || t->ttyp == TRAPDOOR || t->ttyp == HOLE)))) {</span>
  <span id="line747">747.              u.ux = x;</span>
+
  <span id="line747">747.            u.ux = x;</span>
  <span id="line748">748.              u.uy = y;</span>
+
  <span id="line748">748.            u.uy = y;</span>
  <span id="line749">749.          } else {</span>
+
  <span id="line749">749.        } else {</span>
  <span id="line750">750.              u.ux = x - u.dx;</span>
+
  <span id="line750">750.            u.ux = x - u.dx;</span>
  <span id="line751">751.              u.uy = y - u.dy;</span>
+
  <span id="line751">751.            u.uy = y - u.dy;</span>
  <span id="line752">752.          }</span>
+
  <span id="line752">752.        }</span>
  <span id="line753">753.          vision_full_recalc = 1; /* hero has moved, recalculate vision later */</span>
+
  <span id="line753">753.        vision_full_recalc = 1; /* hero has moved, recalculate vision later */</span>
  <span id="line754">754.  </span>
+
  <span id="line754">754. </span>
  <span id="line755">755.          if (Blind) {</span>
+
  <span id="line755">755.        if (Blind) {</span>
  <span id="line756">756.              /* drop glyph under the chain */</span>
+
  <span id="line756">756.            /* drop glyph under the chain */</span>
  <span id="line757">757.              if (u.bc_felt & BC_CHAIN)</span>
+
  <span id="line757">757.            if (u.bc_felt & BC_CHAIN)</span>
  <span id="line758">758.                  levl[uchain->ox][uchain->oy].glyph = u.cglyph;</span>
+
  <span id="line758">758.                levl[uchain->ox][uchain->oy].glyph = u.cglyph;</span>
  <span id="line759">759.              u.bc_felt = 0; /* feel nothing */</span>
+
  <span id="line759">759.            u.bc_felt = 0; /* feel nothing */</span>
  <span id="line760">760.              /* pick up new glyph */</span>
+
  <span id="line760">760.            /* pick up new glyph */</span>
  <span id="line761">761.              u.cglyph = (u.bc_order) ? u.bglyph : levl[u.ux][u.uy].glyph;</span>
+
  <span id="line761">761.            u.cglyph = (u.bc_order) ? u.bglyph : levl[u.ux][u.uy].glyph;</span>
  <span id="line762">762.          }</span>
+
  <span id="line762">762.        }</span>
  <span id="line763">763.          movobj(uchain, u.ux, u.uy); /* has a newsym */</span>
+
  <span id="line763">763.        movobj(uchain, u.ux, u.uy); /* has a newsym */</span>
  <span id="line764">764.          if (Blind) {</span>
+
  <span id="line764">764.        if (Blind) {</span>
  <span id="line765">765.              u.bc_order = bc_order();</span>
+
  <span id="line765">765.            u.bc_order = bc_order();</span>
  <span id="line766">766.          }</span>
+
  <span id="line766">766.        }</span>
  <span id="line767">767.          newsym(u.ux0, u.uy0); /* clean up old position */</span>
+
  <span id="line767">767.        newsym(u.ux0, u.uy0); /* clean up old position */</span>
  <span id="line768">768.          if (u.ux0 != u.ux || u.uy0 != u.uy) {</span>
+
  <span id="line768">768.        if (u.ux0 != u.ux || u.uy0 != u.uy) {</span>
  <span id="line769">769.              spoteffects(TRUE);</span>
+
  <span id="line769">769.            spoteffects(TRUE);</span>
  <span id="line770">770.              sokoban_guilt();</span>
+
  <span id="line770">770.            sokoban_guilt();</span>
  <span id="line771">771.          }</span>
+
  <span id="line771">771.        }</span>
  <span id="line772">772.      }</span>
+
  <span id="line772">772.    }</span>
  <span id="line773">773.  }</span>
+
  <span id="line773">773. }</span>
  <span id="line774">774.  </span>
+
  <span id="line774">774. </span>
  
 
== litter ==
 
== litter ==
 
      
 
      
  <span id="line775">775.  STATIC_OVL void</span>
+
  <span id="line775">775. STATIC_OVL void</span>
  <span id="line776">776.  litter()</span>
+
  <span id="line776">776. litter()</span>
  <span id="line777">777.  {</span>
+
  <span id="line777">777. {</span>
  <span id="line778">778.      struct obj *otmp = invent, *nextobj;</span>
+
  <span id="line778">778.    struct obj *otmp = invent, *nextobj;</span>
  <span id="line779">779.      int capacity = weight_cap();</span>
+
  <span id="line779">779.    int capacity = weight_cap();</span>
  <span id="line780">780.  </span>
+
  <span id="line780">780. </span>
  <span id="line781">781.      while (otmp) {</span>
+
  <span id="line781">781.    while (otmp) {</span>
  <span id="line782">782.          nextobj = otmp->nobj;</span>
+
  <span id="line782">782.        nextobj = otmp->nobj;</span>
  <span id="line783">783.          if ((otmp != uball) && (rnd(capacity) <= (int) otmp->owt)) {</span>
+
  <span id="line783">783.        if ((otmp != uball) && (rnd(capacity) <= (int) otmp->owt)) {</span>
  <span id="line784">784.              if (canletgo(otmp, "")) {</span>
+
  <span id="line784">784.            if (canletgo(otmp, "")) {</span>
  <span id="line785">785.                  pline("%s you down the stairs.", Yobjnam2(otmp, "follow"));</span>
+
  <span id="line785">785.                pline("%s you down the stairs.", Yobjnam2(otmp, "follow"));</span>
  <span id="line786">786.                  dropx(otmp);</span>
+
  <span id="line786">786.                dropx(otmp);</span>
  <span id="line787">787.              }</span>
+
  <span id="line787">787.            }</span>
  <span id="line788">788.          }</span>
+
  <span id="line788">788.        }</span>
  <span id="line789">789.          otmp = nextobj;</span>
+
  <span id="line789">789.        otmp = nextobj;</span>
  <span id="line790">790.      }</span>
+
  <span id="line790">790.    }</span>
  <span id="line791">791.  }</span>
+
  <span id="line791">791. }</span>
  <span id="line792">792.  </span>
+
  <span id="line792">792. </span>
  
 
== drag_down ==
 
== drag_down ==
 
      
 
      
  <span id="line793">793.  void</span>
+
  <span id="line793">793. void</span>
  <span id="line794">794.  drag_down()</span>
+
  <span id="line794">794. drag_down()</span>
  <span id="line795">795.  {</span>
+
  <span id="line795">795. {</span>
  <span id="line796">796.      boolean forward;</span>
+
  <span id="line796">796.    boolean forward;</span>
  <span id="line797">797.      uchar dragchance = 3;</span>
+
  <span id="line797">797.    uchar dragchance = 3;</span>
  <span id="line798">798.  </span>
+
  <span id="line798">798. </span>
  <span id="line799">799.      /*</span>
+
  <span id="line799">799.    /*</span>
  <span id="line800">800.      *  Assume that the ball falls forward if:</span>
+
  <span id="line800">800.      *  Assume that the ball falls forward if:</span>
  <span id="line801">801.      *</span>
+
  <span id="line801">801.      *</span>
  <span id="line802">802.      *  a) the character is wielding it, or</span>
+
  <span id="line802">802.      *  a) the character is wielding it, or</span>
  <span id="line803">803.      *  b) the character has both hands available to hold it (i.e. is</span>
+
  <span id="line803">803.      *  b) the character has both hands available to hold it (i.e. is</span>
  <span id="line804">804.      *    not wielding any weapon), or</span>
+
  <span id="line804">804.      *    not wielding any weapon), or</span>
  <span id="line805">805.      *  c) (perhaps) it falls forward out of his non-weapon hand</span>
+
  <span id="line805">805.      *  c) (perhaps) it falls forward out of his non-weapon hand</span>
  <span id="line806">806.      */</span>
+
  <span id="line806">806.      */</span>
  <span id="line807">807.      forward = carried(uball) && (uwep == uball || !uwep || !rn2(3));</span>
+
  <span id="line807">807.    forward = carried(uball) && (uwep == uball || !uwep || !rn2(3));</span>
  <span id="line808">808.  </span>
+
  <span id="line808">808. </span>
  <span id="line809">809.      if (carried(uball))</span>
+
  <span id="line809">809.    if (carried(uball))</span>
  <span id="line810">810.          You("lose your grip on the iron ball.");</span>
+
  <span id="line810">810.        You("lose your grip on the iron ball.");</span>
  <span id="line811">811.  </span>
+
  <span id="line811">811. </span>
  <span id="line812">812.      if (forward) {</span>
+
  <span id="line812">812.    if (forward) {</span>
  <span id="line813">813.          if (rn2(6)) {</span>
+
  <span id="line813">813.        if (rn2(6)) {</span>
  <span id="line814">814.              pline_The("iron ball drags you downstairs!");</span>
+
  <span id="line814">814.            pline_The("iron ball drags you downstairs!");</span>
  <span id="line815">815.              losehp(Maybe_Half_Phys(rnd(6)),</span>
+
  <span id="line815">815.            losehp(Maybe_Half_Phys(rnd(6)),</span>
  <span id="line816">816.                    "dragged downstairs by an iron ball", NO_KILLER_PREFIX);</span>
+
  <span id="line816">816.                    "dragged downstairs by an iron ball", NO_KILLER_PREFIX);</span>
  <span id="line817">817.              litter();</span>
+
  <span id="line817">817.            litter();</span>
  <span id="line818">818.          }</span>
+
  <span id="line818">818.        }</span>
  <span id="line819">819.      } else {</span>
+
  <span id="line819">819.    } else {</span>
  <span id="line820">820.          if (rn2(2)) {</span>
+
  <span id="line820">820.        if (rn2(2)) {</span>
  <span id="line821">821.              pline_The("iron ball smacks into you!");</span>
+
  <span id="line821">821.            pline_The("iron ball smacks into you!");</span>
  <span id="line822">822.              losehp(Maybe_Half_Phys(rnd(20)), "iron ball collision",</span>
+
  <span id="line822">822.            losehp(Maybe_Half_Phys(rnd(20)), "iron ball collision",</span>
  <span id="line823">823.                    KILLED_BY_AN);</span>
+
  <span id="line823">823.                    KILLED_BY_AN);</span>
  <span id="line824">824.              exercise(A_STR, FALSE);</span>
+
  <span id="line824">824.            exercise(A_STR, FALSE);</span>
  <span id="line825">825.              dragchance -= 2;</span>
+
  <span id="line825">825.            dragchance -= 2;</span>
  <span id="line826">826.          }</span>
+
  <span id="line826">826.        }</span>
  <span id="line827">827.          if ((int) dragchance >= rnd(6)) {</span>
+
  <span id="line827">827.        if ((int) dragchance >= rnd(6)) {</span>
  <span id="line828">828.              pline_The("iron ball drags you downstairs!");</span>
+
  <span id="line828">828.            pline_The("iron ball drags you downstairs!");</span>
  <span id="line829">829.              losehp(Maybe_Half_Phys(rnd(3)),</span>
+
  <span id="line829">829.            losehp(Maybe_Half_Phys(rnd(3)),</span>
  <span id="line830">830.                    "dragged downstairs by an iron ball", NO_KILLER_PREFIX);</span>
+
  <span id="line830">830.                    "dragged downstairs by an iron ball", NO_KILLER_PREFIX);</span>
  <span id="line831">831.              exercise(A_STR, FALSE);</span>
+
  <span id="line831">831.            exercise(A_STR, FALSE);</span>
  <span id="line832">832.              litter();</span>
+
  <span id="line832">832.            litter();</span>
  <span id="line833">833.          }</span>
+
  <span id="line833">833.        }</span>
  <span id="line834">834.      }</span>
+
  <span id="line834">834.    }</span>
  <span id="line835">835.  }</span>
+
  <span id="line835">835. }</span>
  <span id="line836">836.  </span>
+
  <span id="line836">836. </span>
  <span id="line837">837.  /*ball.c*/</span>
+
  <span id="line837">837. /*ball.c*/</span>
 
[[Category:NetHack 3.6.0 source code|src/ball.c]]
 
[[Category:NetHack 3.6.0 source code|src/ball.c]]

Latest revision as of 14:05, 15 December 2015

Below is the full text to ball.c from the source code of NetHack 3.6.0. To link to a particular line, write [[Source:NetHack 3.6.0/src/ball.c#line123]], for example.

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

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

Top of file

 /* NetHack 3.6	ball.c	$NHDT-Date: 1446808438 2015/11/06 11:13:58 $  $NHDT-Branch: master $:$NHDT-Revision: 1.28 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* Ball & Chain
  * =============================================================*/
 
 #include "hack.h"
 
 STATIC_DCL int NDECL(bc_order);
 STATIC_DCL void NDECL(litter);
 

ballrelease

 void
 ballrelease(showmsg)
 boolean showmsg;
 {
     if (carried(uball)) {
         if (showmsg)
             pline("Startled, you drop the iron ball.");
         if (uwep == uball)
             setuwep((struct obj *) 0);
         if (uswapwep == uball)
             setuswapwep((struct obj *) 0);
         if (uquiver == uball)
             setuqwep((struct obj *) 0);
         ;
         if (uwep != uball)
             freeinv(uball);
     }
 }
 

ballfall

 void
 ballfall()
 {
     boolean gets_hit;
 
     gets_hit = (((uball->ox != u.ux) || (uball->oy != u.uy))
                 && ((uwep == uball) ? FALSE : (boolean) rn2(5)));
     ballrelease(TRUE);
     if (gets_hit) {
         int dmg = rn1(7, 25);
         pline_The("iron ball falls on your %s.", body_part(HEAD));
         if (uarmh) {
             if (is_metallic(uarmh)) {
                 pline("Fortunately, you are wearing a hard helmet.");
                 dmg = 3;
             } else if (flags.verbose)
                 pline("%s does not protect you.", Yname2(uarmh));
         }
         losehp(Maybe_Half_Phys(dmg), "crunched in the head by an iron ball",
                NO_KILLER_PREFIX);
     }
 }
 

placebc

 /*
  *  To make this work, we have to mess with the hero's mind.  The rules for
  *  ball&chain are:
  *
  *      1. If the hero can see them, fine.
  *      2. If the hero can't see either, it isn't seen.
  *      3. If either is felt it is seen.
  *      4. If either is felt and moved, it disappears.
  *
  *  If the hero can see, then when a move is done, the ball and chain are
  *  first picked up, the positions under them are corrected, then they
  *  are moved after the hero moves.  Not too bad.
  *
  *  If the hero is blind, then she can "feel" the ball and/or chain at any
  *  time.  However, when the hero moves, the felt ball and/or chain become
  *  unfelt and whatever was felt "under" the ball&chain appears.  Pretty
  *  nifty, but it requires that the ball&chain "remember" what was under
  *  them --- i.e. they pick-up glyphs when they are felt and drop them when
  *  moved (and felt).  When swallowed, the ball&chain are pulled completely
  *  off of the dungeon, but are still on the object chain.  They are placed
  *  under the hero when she is expelled.
  */
 
 /*
  * from you.h
  *      int u.bglyph            glyph under the ball
  *      int u.cglyph            glyph under the chain
  *      int u.bc_felt           mask for ball/chain being felt
  *      #define BC_BALL  0x01   bit mask in u.bc_felt for ball
  *      #define BC_CHAIN 0x02   bit mask in u.bc_felt for chain
  *      int u.bc_order          ball & chain order
  *
  * u.bc_felt is also manipulated in display.c and read.c, the others only
  * in this file.  None of these variables are valid unless the player is
  * Blind.
  */
 
 /* values for u.bc_order */
 #define BCPOS_DIFFER 0 /* ball & chain at different positions */
 #define BCPOS_CHAIN 1  /* chain on top of ball */
 #define BCPOS_BALL 2   /* ball on top of chain */
 
 /*
  *  Place the ball & chain under the hero.  Make sure that the ball & chain
  *  variables are set (actually only needed when blind, but what the heck).
  *  It is assumed that when this is called, the ball and chain are NOT
  *  attached to the object list.
  *
  *  Should not be called while swallowed except on waterlevel.
  */
 void
 placebc()
 {
     if (!uchain || !uball) {
         impossible("Where are your ball and chain?");
         return;
     }
 
     (void) flooreffects(uchain, u.ux, u.uy, ""); /* chain might rust */
 
     if (carried(uball)) /* the ball is carried */
         u.bc_order = BCPOS_DIFFER;
     else {
         /* ball might rust -- already checked when carried */
         (void) flooreffects(uball, u.ux, u.uy, "");
         place_object(uball, u.ux, u.uy);
         u.bc_order = BCPOS_CHAIN;
     }
 
     place_object(uchain, u.ux, u.uy);
 
     u.bglyph = u.cglyph = levl[u.ux][u.uy].glyph; /* pick up glyph */
 
     newsym(u.ux, u.uy);
 }
 

unplacebc

 void
 unplacebc()
 {
     if (u.uswallow) {
         if (Is_waterlevel(&u.uz)) {
             /* we need to proceed with the removal from the floor
              * so that movebubbles() processing will disregard it as
              * intended. Ignore all the vision stuff.
              */
             if (!carried(uball))
                 obj_extract_self(uball);
             obj_extract_self(uchain);
         }
         /* ball&chain not unplaced while swallowed */
         return;
     }
 
     if (!carried(uball)) {
         obj_extract_self(uball);
         if (Blind && (u.bc_felt & BC_BALL)) /* drop glyph */
             levl[uball->ox][uball->oy].glyph = u.bglyph;
 
         newsym(uball->ox, uball->oy);
     }
     obj_extract_self(uchain);
     if (Blind && (u.bc_felt & BC_CHAIN)) /* drop glyph */
         levl[uchain->ox][uchain->oy].glyph = u.cglyph;
 
     newsym(uchain->ox, uchain->oy);
     u.bc_felt = 0; /* feel nothing */
 }
 

bc_order

 /*
  *  Return the stacking of the hero's ball & chain.  This assumes that the
  *  hero is being punished.
  */
 STATIC_OVL int
 bc_order()
 {
     struct obj *obj;
 
     if (uchain->ox != uball->ox || uchain->oy != uball->oy || carried(uball)
         || u.uswallow)
         return BCPOS_DIFFER;
 
     for (obj = level.objects[uball->ox][uball->oy]; obj;
          obj = obj->nexthere) {
         if (obj == uchain)
             return BCPOS_CHAIN;
         if (obj == uball)
             return BCPOS_BALL;
     }
     impossible("bc_order:  ball&chain not in same location!");
     return BCPOS_DIFFER;
 }
 

set_bc

 /*
  *  set_bc()
  *
  *  The hero is either about to go blind or already blind and just punished.
  *  Set up the ball and chain variables so that the ball and chain are "felt".
  */
 void
 set_bc(already_blind)
 int already_blind;
 {
     int ball_on_floor = !carried(uball);
 
     u.bc_order = bc_order(); /* get the order */
     u.bc_felt = ball_on_floor ? BC_BALL | BC_CHAIN : BC_CHAIN; /* felt */
 
     if (already_blind || u.uswallow) {
         u.cglyph = u.bglyph = levl[u.ux][u.uy].glyph;
         return;
     }
 
     /*
      *  Since we can still see, remove the ball&chain and get the glyph that
      *  would be beneath them.  Then put the ball&chain back.  This is pretty
      *  disgusting, but it will work.
      */
     remove_object(uchain);
     if (ball_on_floor)
         remove_object(uball);
 
     newsym(uchain->ox, uchain->oy);
     u.cglyph = levl[uchain->ox][uchain->oy].glyph;
 
     if (u.bc_order == BCPOS_DIFFER) { /* different locations */
         place_object(uchain, uchain->ox, uchain->oy);
         newsym(uchain->ox, uchain->oy);
         if (ball_on_floor) {
             newsym(uball->ox, uball->oy); /* see under ball */
             u.bglyph = levl[uball->ox][uball->oy].glyph;
             place_object(uball, uball->ox, uball->oy);
             newsym(uball->ox, uball->oy); /* restore ball */
         }
     } else {
         u.bglyph = u.cglyph;
         if (u.bc_order == BCPOS_CHAIN) {
             place_object(uball, uball->ox, uball->oy);
             place_object(uchain, uchain->ox, uchain->oy);
         } else {
             place_object(uchain, uchain->ox, uchain->oy);
             place_object(uball, uball->ox, uball->oy);
         }
         newsym(uball->ox, uball->oy);
     }
 }
 

move_bc

 /*
  *  move_bc()
  *
  *  Move the ball and chain.  This is called twice for every move.  The first
  *  time to pick up the ball and chain before the move, the second time to
  *  place the ball and chain after the move.  If the ball is carried, this
  *  function should never have BC_BALL as part of its control.
  *
  *  Should not be called while swallowed.
  */
 void
 move_bc(before, control, ballx, bally, chainx, chainy)
 int before, control;
 xchar ballx, bally, chainx, chainy; /* only matter !before */
 {
     if (Blind) {
         /*
          *  The hero is blind.  Time to work hard.  The ball and chain that
          *  are attached to the hero are very special.  The hero knows that
          *  they are attached, so when they move, the hero knows that they
          *  aren't at the last position remembered.  This is complicated
          *  by the fact that the hero can "feel" the surrounding locations
          *  at any time, hence, making one or both of them show up again.
          *  So, we have to keep track of which is felt at any one time and
          *  act accordingly.
          */
         if (!before) {
             if ((control & BC_CHAIN) && (control & BC_BALL)) {
                 /*
                  *  Both ball and chain moved.  If felt, drop glyph.
                  */
                 if (u.bc_felt & BC_BALL)
                     levl[uball->ox][uball->oy].glyph = u.bglyph;
                 if (u.bc_felt & BC_CHAIN)
                     levl[uchain->ox][uchain->oy].glyph = u.cglyph;
                 u.bc_felt = 0;
 
                 /* Pick up glyph at new location. */
                 u.bglyph = levl[ballx][bally].glyph;
                 u.cglyph = levl[chainx][chainy].glyph;
 
                 movobj(uball, ballx, bally);
                 movobj(uchain, chainx, chainy);
             } else if (control & BC_BALL) {
                 if (u.bc_felt & BC_BALL) {
                     if (u.bc_order == BCPOS_DIFFER) { /* ball by itself */
                         levl[uball->ox][uball->oy].glyph = u.bglyph;
                     } else if (u.bc_order == BCPOS_BALL) {
                         if (u.bc_felt & BC_CHAIN) { /* know chain is there */
                             map_object(uchain, 0);
                         } else {
                             levl[uball->ox][uball->oy].glyph = u.bglyph;
                         }
                     }
                     u.bc_felt &= ~BC_BALL; /* no longer feel the ball */
                 }
 
                 /* Pick up glyph at new position. */
                 u.bglyph = (ballx != chainx || bally != chainy)
                                ? levl[ballx][bally].glyph
                                : u.cglyph;
 
                 movobj(uball, ballx, bally);
             } else if (control & BC_CHAIN) {
                 if (u.bc_felt & BC_CHAIN) {
                     if (u.bc_order == BCPOS_DIFFER) {
                         levl[uchain->ox][uchain->oy].glyph = u.cglyph;
                     } else if (u.bc_order == BCPOS_CHAIN) {
                         if (u.bc_felt & BC_BALL) {
                             map_object(uball, 0);
                         } else {
                             levl[uchain->ox][uchain->oy].glyph = u.cglyph;
                         }
                     }
                     u.bc_felt &= ~BC_CHAIN;
                 }
                 /* Pick up glyph at new position. */
                 u.cglyph = (ballx != chainx || bally != chainy)
                                ? levl[chainx][chainy].glyph
                                : u.bglyph;
 
                 movobj(uchain, chainx, chainy);
             }
 
             u.bc_order = bc_order(); /* reset the order */
         }
 
     } else {
         /*
          *  The hero is not blind.  To make this work correctly, we need to
          *  pick up the ball and chain before the hero moves, then put them
          *  in their new positions after the hero moves.
          */
         if (before) {
             if (!control) {
                 /*
                  * Neither ball nor chain is moving, so remember which was
                  * on top until !before.  Use the variable u.bc_order
                  * since it is only valid when blind.
                  */
                 u.bc_order = bc_order();
             }
 
             remove_object(uchain);
             newsym(uchain->ox, uchain->oy);
             if (!carried(uball)) {
                 remove_object(uball);
                 newsym(uball->ox, uball->oy);
             }
         } else {
             int on_floor = !carried(uball);
 
             if ((control & BC_CHAIN)
                 || (!control && u.bc_order == BCPOS_CHAIN)) {
                 /* If the chain moved or nothing moved & chain on top. */
                 if (on_floor)
                     place_object(uball, ballx, bally);
                 place_object(uchain, chainx, chainy); /* chain on top */
             } else {
                 place_object(uchain, chainx, chainy);
                 if (on_floor)
                     place_object(uball, ballx, bally);
                 /* ball on top */
             }
             newsym(chainx, chainy);
             if (on_floor)
                 newsym(ballx, bally);
         }
     }
 }
 

drag_ball

 /* return TRUE if the caller needs to place the ball and chain down again
  *
  *  Should not be called while swallowed.  Should be called before movement,
  *  because we might want to move the ball or chain to the hero's old
  * position.
  *
  * It is called if we are moving.  It is also called if we are teleporting
  * *if* the ball doesn't move and we thus must drag the chain.  It is not
  * called for ordinary teleportation.
  *
  * allow_drag is only used in the ugly special case where teleporting must
  * drag the chain, while an identical-looking movement must drag both the ball
  * and chain.
  */
 boolean
 drag_ball(x, y, bc_control, ballx, bally, chainx, chainy, cause_delay,
           allow_drag)
 xchar x, y;
 int *bc_control;
 xchar *ballx, *bally, *chainx, *chainy;
 boolean *cause_delay;
 boolean allow_drag;
 {
     struct trap *t = (struct trap *) 0;
     boolean already_in_rock;
 
     *ballx = uball->ox;
     *bally = uball->oy;
     *chainx = uchain->ox;
     *chainy = uchain->oy;
     *bc_control = 0;
     *cause_delay = FALSE;
 
     if (dist2(x, y, uchain->ox, uchain->oy) <= 2) { /* nothing moved */
         move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
         return TRUE;
     }
 
     /* only need to move the chain? */
     if (carried(uball) || distmin(x, y, uball->ox, uball->oy) <= 2) {
         xchar oldchainx = uchain->ox, oldchainy = uchain->oy;
         *bc_control = BC_CHAIN;
         move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
         if (carried(uball)) {
             /* move chain only if necessary */
             if (distmin(x, y, uchain->ox, uchain->oy) > 1) {
                 *chainx = u.ux;
                 *chainy = u.uy;
             }
             return TRUE;
         }
 #define CHAIN_IN_MIDDLE(chx, chy) \
     (distmin(x, y, chx, chy) <= 1 \
      && distmin(chx, chy, uball->ox, uball->oy) <= 1)
 #define IS_CHAIN_ROCK(x, y)      \
     (IS_ROCK(levl[x][y].typ)     \
      || (IS_DOOR(levl[x][y].typ) \
          && (levl[x][y].doormask & (D_CLOSED | D_LOCKED))))
 /* Don't ever move the chain into solid rock.  If we have to, then instead
  * undo the move_bc() and jump to the drag ball code.  Note that this also
  * means the "cannot carry and drag" message will not appear, since unless we
  * moved at least two squares there is no possibility of the chain position
  * being in solid rock.
  */
 #define SKIP_TO_DRAG                                               \
     {                                                              \
         *chainx = oldchainx;                                       \
         *chainy = oldchainy;                                       \
         move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy); \
         goto drag;                                                 \
     }
         if (IS_CHAIN_ROCK(u.ux, u.uy) || IS_CHAIN_ROCK(*chainx, *chainy)
             || IS_CHAIN_ROCK(uball->ox, uball->oy))
             already_in_rock = TRUE;
         else
             already_in_rock = FALSE;
 
         switch (dist2(x, y, uball->ox, uball->oy)) {
         /* two spaces diagonal from ball, move chain inbetween */
         case 8:
             *chainx = (uball->ox + x) / 2;
             *chainy = (uball->oy + y) / 2;
             if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock)
                 SKIP_TO_DRAG;
             break;
 
         /* player is distance 2/1 from ball; move chain to one of the
          * two spaces between
          *   @
          *   __
          *    0
          */
         case 5: {
             xchar tempx, tempy, tempx2, tempy2;
 
             /* find position closest to current position of chain */
             /* no effect if current position is already OK */
             if (abs(x - uball->ox) == 1) {
                 tempx = x;
                 tempx2 = uball->ox;
                 tempy = tempy2 = (uball->oy + y) / 2;
             } else {
                 tempx = tempx2 = (uball->ox + x) / 2;
                 tempy = y;
                 tempy2 = uball->oy;
             }
             if (IS_CHAIN_ROCK(tempx, tempy) && !IS_CHAIN_ROCK(tempx2, tempy2)
                 && !already_in_rock) {
                 if (allow_drag) {
                     /* Avoid pathological case *if* not teleporting:
                      *   0                          0_
                      *   _X  move northeast  ----->  X@
                      *    @
                      */
                     if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 5
                         && dist2(x, y, tempx, tempy) == 1)
                         SKIP_TO_DRAG;
                     /* Avoid pathological case *if* not teleporting:
                      *    0                          0
                      *   _X  move east       ----->  X_
                      *    @                           @
                      */
                     if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 4
                         && dist2(x, y, tempx, tempy) == 2)
                         SKIP_TO_DRAG;
                 }
                 *chainx = tempx2;
                 *chainy = tempy2;
             } else if (!IS_CHAIN_ROCK(tempx, tempy)
                        && IS_CHAIN_ROCK(tempx2, tempy2) && !already_in_rock) {
                 if (allow_drag) {
                     if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 5
                         && dist2(x, y, tempx2, tempy2) == 1)
                         SKIP_TO_DRAG;
                     if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 4
                         && dist2(x, y, tempx2, tempy2) == 2)
                         SKIP_TO_DRAG;
                 }
                 *chainx = tempx;
                 *chainy = tempy;
             } else if (IS_CHAIN_ROCK(tempx, tempy)
                        && IS_CHAIN_ROCK(tempx2, tempy2) && !already_in_rock) {
                 SKIP_TO_DRAG;
             } else if (dist2(tempx, tempy, uchain->ox, uchain->oy)
                            < dist2(tempx2, tempy2, uchain->ox, uchain->oy)
                        || ((dist2(tempx, tempy, uchain->ox, uchain->oy)
                             == dist2(tempx2, tempy2, uchain->ox, uchain->oy))
                            && rn2(2))) {
                 *chainx = tempx;
                 *chainy = tempy;
             } else {
                 *chainx = tempx2;
                 *chainy = tempy2;
             }
             break;
         }
 
         /* ball is two spaces horizontal or vertical from player; move*/
         /* chain inbetween *unless* current chain position is OK */
         case 4:
             if (CHAIN_IN_MIDDLE(uchain->ox, uchain->oy))
                 break;
             *chainx = (x + uball->ox) / 2;
             *chainy = (y + uball->oy) / 2;
             if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock)
                 SKIP_TO_DRAG;
             break;
 
         /* ball is one space diagonal from player.  Check for the
          * following special case:
          *   @
          *    _    moving southwest becomes  @_
          *   0                                0
          * (This will also catch teleporting that happens to resemble
          * this case, but oh well.)  Otherwise fall through.
          */
         case 2:
             if (dist2(x, y, uball->ox, uball->oy) == 2
                 && dist2(x, y, uchain->ox, uchain->oy) == 4) {
                 if (uchain->oy == y)
                     *chainx = uball->ox;
                 else
                     *chainy = uball->oy;
                 if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock)
                     SKIP_TO_DRAG;
                 break;
             }
         /* fall through */
         case 1:
         case 0:
             /* do nothing if possible */
             if (CHAIN_IN_MIDDLE(uchain->ox, uchain->oy))
                 break;
             /* otherwise try to drag chain to player's old position */
             if (CHAIN_IN_MIDDLE(u.ux, u.uy)) {
                 *chainx = u.ux;
                 *chainy = u.uy;
                 break;
             }
             /* otherwise use player's new position (they must have
                teleported, for this to happen) */
             *chainx = x;
             *chainy = y;
             break;
 
         default:
             impossible("bad chain movement");
             break;
         }
 #undef SKIP_TO_DRAG
 #undef CHAIN_IN_MIDDLE
         return TRUE;
     }
 
 drag:
 
     if (near_capacity() > SLT_ENCUMBER && dist2(x, y, u.ux, u.uy) <= 2) {
         You("cannot %sdrag the heavy iron ball.",
             invent ? "carry all that and also " : "");
         nomul(0);
         return FALSE;
     }
 
     if ((is_pool(uchain->ox, uchain->oy)
          /* water not mere continuation of previous water */
          && (levl[uchain->ox][uchain->oy].typ == POOL
              || !is_pool(uball->ox, uball->oy)
              || levl[uball->ox][uball->oy].typ == POOL))
         || ((t = t_at(uchain->ox, uchain->oy))
             && (t->ttyp == PIT || t->ttyp == SPIKED_PIT || t->ttyp == HOLE
                 || t->ttyp == TRAPDOOR))) {
         if (Levitation) {
             You_feel("a tug from the iron ball.");
             if (t)
                 t->tseen = 1;
         } else {
             struct monst *victim;
 
             You("are jerked back by the iron ball!");
             if ((victim = m_at(uchain->ox, uchain->oy)) != 0) {
                 int tmp;
 
                 tmp = -2 + Luck + find_mac(victim);
                 tmp += omon_adj(victim, uball, TRUE);
                 if (tmp >= rnd(20))
                     (void) hmon(victim, uball, HMON_DRAGGED);
                 else
                     miss(xname(uball), victim);
 
             } /* now check again in case mon died */
             if (!m_at(uchain->ox, uchain->oy)) {
                 u.ux = uchain->ox;
                 u.uy = uchain->oy;
                 newsym(u.ux0, u.uy0);
             }
             nomul(0);
 
             *bc_control = BC_BALL;
             move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
             *ballx = uchain->ox;
             *bally = uchain->oy;
             move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy);
             spoteffects(TRUE);
             return FALSE;
         }
     }
 
     *bc_control = BC_BALL | BC_CHAIN;
 
     move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
     if (dist2(x, y, u.ux, u.uy) > 2) {
         /* Awful case: we're still in range of the ball, so we thought we
          * could only move the chain, but it turned out that the target
          * square for the chain was rock, so we had to drag it instead.
          * But we can't drag it either, because we teleported and are more
          * than one square from our old position.  Revert to the teleport
          * behavior.
          */
         *ballx = *chainx = x;
         *bally = *chainy = y;
     } else {
         xchar newchainx = u.ux, newchainy = u.uy;
 
         /*
          * Generally, chain moves to hero's previous location and ball
          * moves to chain's previous location, except that we try to
          * keep the chain directly between the hero and the ball.  But,
          * take the simple approach if the hero's previous location or
          * the potential between location is inaccessible.
          */
         if (dist2(x, y, uchain->ox, uchain->oy) == 4
             && !IS_CHAIN_ROCK(newchainx, newchainy)) {
             newchainx = (x + uchain->ox) / 2;
             newchainy = (y + uchain->oy) / 2;
             if (IS_CHAIN_ROCK(newchainx, newchainy)) {
                 /* don't let chain move to inaccessible location */
                 newchainx = u.ux;
                 newchainy = u.uy;
             }
         }
 
         *ballx = uchain->ox;
         *bally = uchain->oy;
         *chainx = newchainx;
         *chainy = newchainy;
     }
 #undef IS_CHAIN_ROCK
     *cause_delay = TRUE;
     return TRUE;
 }
 

drop_ball

 /*
  *  drop_ball()
  *
  *  The punished hero drops or throws her iron ball.  If the hero is
  *  blind, we must reset the order and glyph.  Check for side effects.
  *  This routine expects the ball to be already placed.
  *
  *  Should not be called while swallowed.
  */
 void
 drop_ball(x, y)
 xchar x, y;
 {
     if (Blind) {
         /* get the order */
         u.bc_order = bc_order();
         /* pick up glyph */
         u.bglyph = (u.bc_order) ? u.cglyph : levl[x][y].glyph;
     }
 
     if (x != u.ux || y != u.uy) {
         struct trap *t;
         const char *pullmsg = "The ball pulls you out of the %s!";
 
         if (u.utrap && u.utraptype != TT_INFLOOR
             && u.utraptype != TT_BURIEDBALL) {
             switch (u.utraptype) {
             case TT_PIT:
                 pline(pullmsg, "pit");
                 break;
             case TT_WEB:
                 pline(pullmsg, "web");
                 pline_The("web is destroyed!");
                 deltrap(t_at(u.ux, u.uy));
                 break;
             case TT_LAVA:
                 pline(pullmsg, "lava");
                 break;
             case TT_BEARTRAP: {
                 register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
                 pline(pullmsg, "bear trap");
                 set_wounded_legs(side, rn1(1000, 500));
                 if (!u.usteed) {
                     Your("%s %s is severely damaged.",
                          (side == LEFT_SIDE) ? "left" : "right",
                          body_part(LEG));
                     losehp(Maybe_Half_Phys(2),
                            "leg damage from being pulled out of a bear trap",
                            KILLED_BY);
                 }
                 break;
             }
             }
             u.utrap = 0;
             fill_pit(u.ux, u.uy);
         }
 
         u.ux0 = u.ux;
         u.uy0 = u.uy;
         if (!Levitation && !MON_AT(x, y) && !u.utrap
             && (is_pool(x, y)
                 || ((t = t_at(x, y))
                     && (t->ttyp == PIT || t->ttyp == SPIKED_PIT
                         || t->ttyp == TRAPDOOR || t->ttyp == HOLE)))) {
             u.ux = x;
             u.uy = y;
         } else {
             u.ux = x - u.dx;
             u.uy = y - u.dy;
         }
         vision_full_recalc = 1; /* hero has moved, recalculate vision later */
 
         if (Blind) {
             /* drop glyph under the chain */
             if (u.bc_felt & BC_CHAIN)
                 levl[uchain->ox][uchain->oy].glyph = u.cglyph;
             u.bc_felt = 0; /* feel nothing */
             /* pick up new glyph */
             u.cglyph = (u.bc_order) ? u.bglyph : levl[u.ux][u.uy].glyph;
         }
         movobj(uchain, u.ux, u.uy); /* has a newsym */
         if (Blind) {
             u.bc_order = bc_order();
         }
         newsym(u.ux0, u.uy0); /* clean up old position */
         if (u.ux0 != u.ux || u.uy0 != u.uy) {
             spoteffects(TRUE);
             sokoban_guilt();
         }
     }
 }
 

litter

 STATIC_OVL void
 litter()
 {
     struct obj *otmp = invent, *nextobj;
     int capacity = weight_cap();
 
     while (otmp) {
         nextobj = otmp->nobj;
         if ((otmp != uball) && (rnd(capacity) <= (int) otmp->owt)) {
             if (canletgo(otmp, "")) {
                 pline("%s you down the stairs.", Yobjnam2(otmp, "follow"));
                 dropx(otmp);
             }
         }
         otmp = nextobj;
     }
 }
 

drag_down

 void
 drag_down()
 {
     boolean forward;
     uchar dragchance = 3;
 
     /*
      *  Assume that the ball falls forward if:
      *
      *  a) the character is wielding it, or
      *  b) the character has both hands available to hold it (i.e. is
      *     not wielding any weapon), or
      *  c) (perhaps) it falls forward out of his non-weapon hand
      */
     forward = carried(uball) && (uwep == uball || !uwep || !rn2(3));
 
     if (carried(uball))
         You("lose your grip on the iron ball.");
 
     if (forward) {
         if (rn2(6)) {
             pline_The("iron ball drags you downstairs!");
             losehp(Maybe_Half_Phys(rnd(6)),
                    "dragged downstairs by an iron ball", NO_KILLER_PREFIX);
             litter();
         }
     } else {
         if (rn2(2)) {
             pline_The("iron ball smacks into you!");
             losehp(Maybe_Half_Phys(rnd(20)), "iron ball collision",
                    KILLED_BY_AN);
             exercise(A_STR, FALSE);
             dragchance -= 2;
         }
         if ((int) dragchance >= rnd(6)) {
             pline_The("iron ball drags you downstairs!");
             losehp(Maybe_Half_Phys(rnd(3)),
                    "dragged downstairs by an iron ball", NO_KILLER_PREFIX);
             exercise(A_STR, FALSE);
             litter();
         }
     }
 }
 
 /*ball.c*/