Difference between revisions of "Source:NetHack 3.0.0/shk.c"

From NetHackWiki
Jump to navigation Jump to search
(Replaced content with ' '''Bold text''' THIS PAGE SUCK'S')
m (Undo revision 49431 by 69.31.241.242 (talk))
 
Line 1: Line 1:
 +
Below is the full text to '''shk.c''' from the [[NetHack 3.0.0 source code|source code]] of [[NetHack 3.0.0]]. To link to a particular line, write [[NetHack 3.0.0/shk.c#line123|<nowiki>[[NetHack 3.0.0/shk.c#line123]]</nowiki>]], for example.
  
'''Bold text''' THIS PAGE SUCK'S
+
'''Warning!''' This is the source code from an old release. For the latest release, see [[Source code]]
 +
 
 +
{{NGPL}}
 +
<span id="line1">1.    /* SCCS Id: @(#)shk.c 3.0 89/02/10</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="line4">4.    </span>
 +
<span id="line5">5.    /* block some unused #defines to avoid overloading some cpp's */</span>
 +
<span id="line6">6.    #define MONATTK_H</span>
 +
<span id="line7">7.    #include "hack.h"</span>
 +
<span id="line8">8.    </span>
 +
<span id="line9">9.    #include "eshk.h"</span>
 +
<span id="line10">10.  </span>
 +
<span id="line11">11.  #ifdef KOPS</span>
 +
<span id="line12">12.  static int makekops();</span>
 +
<span id="line13">13.  static void kops_gone();</span>
 +
<span id="line14">14.  #endif /* KOPS */</span>
 +
<span id="line15">15.  </span>
 +
<span id="line16">16.  #define NOTANGRY(mon) mon->mpeaceful</span>
 +
<span id="line17">17.  #define ANGRY(mon) !NOTANGRY(mon)</span>
 +
<span id="line18">18.  </span>
 +
<span id="line19">19.  /* Descriptor of current shopkeeper. Note that the bill need not be</span>
 +
<span id="line20">20.      per-shopkeeper, since it is valid only when in a shop. */</span>
 +
<span id="line21">21.  static struct monst *shopkeeper = 0;</span>
 +
<span id="line22">22.  static struct bill_x *bill;</span>
 +
<span id="line23">23.  static int shlevel = 0; /* level of this shopkeeper */</span>
 +
<span id="line24">24.  /* struct obj *billobjs; /* objects on bill with bp->useup */</span>
 +
<span id="line25">25.  /* only accessed here and by save & restore */</span>
 +
<span id="line26">26.  static long int total; /* filled by addupbill() */</span>
 +
<span id="line27">27.  static long int followmsg; /* last time of follow message */</span>
 +
<span id="line28">28.  static void setpaid(), findshk P((int));</span>
 +
<span id="line29">29.  static int dopayobj P((struct bill_x *)), getprice P((struct obj *));</span>
 +
<span id="line30">30.  static struct obj *bp_to_obj P((struct bill_x *));</span>
 +
<span id="line31">31.  </span>
 +
<span id="line32">32.  /*</span>
 +
<span id="line33">33.  invariants: obj->unpaid iff onbill(obj) [unless bp->useup]</span>
 +
<span id="line34">34.  obj->quan <= bp->bquan</span>
 +
<span id="line35">35.    */</span>
 +
<span id="line36">36.  </span>
 +
<span id="line37">37.  char *</span>
 +
<span id="line38">38.  shkname(mtmp) /* called in do_name.c */</span>
 +
<span id="line39">39.  register struct monst *mtmp;</span>
 +
<span id="line40">40.  {</span>
 +
<span id="line41">41.  return(ESHK(mtmp)->shknam);</span>
 +
<span id="line42">42.  }</span>
 +
<span id="line43">43.  </span>
 +
<span id="line44">44.  void</span>
 +
<span id="line45">45.  shkdead(mtmp) /* called in mon.c */</span>
 +
<span id="line46">46.  register struct monst *mtmp;</span>
 +
<span id="line47">47.  {</span>
 +
<span id="line48">48.  register struct eshk *eshk = ESHK(mtmp);</span>
 +
<span id="line49">49.  </span>
 +
<span id="line50">50.  if(eshk->shoplevel == dlevel)</span>
 +
<span id="line51">51.  rooms[eshk->shoproom].rtype = OROOM;</span>
 +
<span id="line52">52.  if(mtmp == shopkeeper) {</span>
 +
<span id="line53">53.  setpaid();</span>
 +
<span id="line54">54.  shopkeeper = 0;</span>
 +
<span id="line55">55.  bill = (struct bill_x *) -1000; /* dump core when referenced */</span>
 +
<span id="line56">56.  }</span>
 +
<span id="line57">57.  }</span>
 +
<span id="line58">58.  </span>
 +
<span id="line59">59.  void</span>
 +
<span id="line60">60.  replshk(mtmp,mtmp2)</span>
 +
<span id="line61">61.  register struct monst *mtmp, *mtmp2;</span>
 +
<span id="line62">62.  {</span>
 +
<span id="line63">63.  if(mtmp == shopkeeper) {</span>
 +
<span id="line64">64.  shopkeeper = mtmp2;</span>
 +
<span id="line65">65.  bill = &(ESHK(shopkeeper)->bill[0]);</span>
 +
<span id="line66">66.  }</span>
 +
<span id="line67">67.  }</span>
 +
<span id="line68">68.  </span>
 +
<span id="line69">69.  static void</span>
 +
<span id="line70">70.  setpaid(){ /* caller has checked that shopkeeper exists */</span>
 +
<span id="line71">71.  /* either we paid or left the shop or he just died */</span>
 +
<span id="line72">72.  register struct obj *obj;</span>
 +
<span id="line73">73.  register struct monst *mtmp;</span>
 +
<span id="line74">74.  for(obj = invent; obj; obj = obj->nobj)</span>
 +
<span id="line75">75.  obj->unpaid = 0;</span>
 +
<span id="line76">76.  for(obj = fobj; obj; obj = obj->nobj)</span>
 +
<span id="line77">77.  obj->unpaid = 0;</span>
 +
<span id="line78">78.  for(obj = fcobj; obj; obj = obj->nobj)</span>
 +
<span id="line79">79.  obj->unpaid = 0;</span>
 +
<span id="line80">80.  for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)</span>
 +
<span id="line81">81.  for(obj = mtmp->minvent; obj; obj = obj->nobj)</span>
 +
<span id="line82">82.  obj->unpaid = 0;</span>
 +
<span id="line83">83.  for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)</span>
 +
<span id="line84">84.  for(obj = mtmp->minvent; obj; obj = obj->nobj)</span>
 +
<span id="line85">85.  obj->unpaid = 0;</span>
 +
<span id="line86">86.  while(obj = billobjs){</span>
 +
<span id="line87">87.  billobjs = obj->nobj;</span>
 +
<span id="line88">88.  free((genericptr_t) obj);</span>
 +
<span id="line89">89.  }</span>
 +
<span id="line90">90.  if(shopkeeper) {</span>
 +
<span id="line91">91.  ESHK(shopkeeper)->billct = 0;</span>
 +
<span id="line92">92.  ESHK(shopkeeper)->credit = 0L;</span>
 +
<span id="line93">93.  ESHK(shopkeeper)->debit = 0L;</span>
 +
<span id="line94">94.  }</span>
 +
<span id="line95">95.  }</span>
 +
<span id="line96">96.  </span>
 +
<span id="line97">97.  static void</span>
 +
<span id="line98">98.  addupbill(){ /* delivers result in total */</span>
 +
<span id="line99">99.  /* caller has checked that shopkeeper exists */</span>
 +
<span id="line100">100.  register int ct = ESHK(shopkeeper)->billct;</span>
 +
<span id="line101">101.  register struct bill_x *bp = bill;</span>
 +
<span id="line102">102.  total = 0;</span>
 +
<span id="line103">103.  while(ct--){</span>
 +
<span id="line104">104.  total += bp->price * bp->bquan;</span>
 +
<span id="line105">105.  bp++;</span>
 +
<span id="line106">106.  }</span>
 +
<span id="line107">107.  }</span>
 +
<span id="line108">108.  </span>
 +
<span id="line109">109.  int</span>
 +
<span id="line110">110.  inshop() {</span>
 +
<span id="line111">111.  register int roomno = inroom(u.ux,u.uy);</span>
 +
<span id="line112">112.  </span>
 +
<span id="line113">113.  /* Did we just leave a shop? */</span>
 +
<span id="line114">114.  if(u.uinshop &&</span>
 +
<span id="line115">115.      (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {</span>
 +
<span id="line116">116.  </span>
 +
<span id="line117">117.  /* This is part of the bugfix for shopkeepers not having their</span>
 +
<span id="line118">118.  * bill paid.  As reported by ab@unido -dgk</span>
 +
<span id="line119">119.  * I made this standard due to the KOPS code below. -mrs</span>
 +
<span id="line120">120.  */</span>
 +
<span id="line121">121.  if(shopkeeper) {</span>
 +
<span id="line122">122.      if(ESHK(shopkeeper)->billct || ESHK(shopkeeper)->debit) {</span>
 +
<span id="line123">123.  if(inroom(shopkeeper->mx, shopkeeper->my)</span>
 +
<span id="line124">124.      == u.uinshop - 1) /* ab@unido */</span>
 +
<span id="line125">125.      You("escaped the shop without paying!");</span>
 +
<span id="line126">126.  addupbill();</span>
 +
<span id="line127">127.  total += ESHK(shopkeeper)->debit;</span>
 +
<span id="line128">128.  You("stole %ld zorkmids worth of merchandise.",</span>
 +
<span id="line129">129.  total);</span>
 +
<span id="line130">130.  ESHK(shopkeeper)->robbed += total;</span>
 +
<span id="line131">131.  ESHK(shopkeeper)->credit = 0L;</span>
 +
<span id="line132">132.  ESHK(shopkeeper)->debit = 0L;</span>
 +
<span id="line133">133.  if (pl_character[0] != 'R') /* stealing is unlawful */</span>
 +
<span id="line134">134.  adjalign(-sgn(u.ualigntyp));</span>
 +
<span id="line135">135.  setpaid();</span>
 +
<span id="line136">136.  if((rooms[ESHK(shopkeeper)->shoproom].rtype == SHOPBASE)</span>
 +
<span id="line137">137.      == (rn2(3) == 0))</span>
 +
<span id="line138">138.      ESHK(shopkeeper)->following = 1;</span>
 +
<span id="line139">139.  #ifdef KOPS</span>
 +
<span id="line140">140.      {  /* Keystone Kops srt@ucla */</span>
 +
<span id="line141">141.  coord mm;</span>
 +
<span id="line142">142.  </span>
 +
<span id="line143">143.  if (flags.soundok)</span>
 +
<span id="line144">144.      pline("An alarm sounds throughout the dungeon!");</span>
 +
<span id="line145">145.  if(flags.verbose) {</span>
 +
<span id="line146">146.      if((mons[PM_KEYSTONE_KOP].geno & G_GENOD) &&</span>
 +
<span id="line147">147.        (mons[PM_KOP_SERGEANT].geno & G_GENOD) &&</span>
 +
<span id="line148">148.        (mons[PM_KOP_LIEUTENANT].geno & G_GENOD) &&</span>
 +
<span id="line149">149.        (mons[PM_KOP_KAPTAIN].geno & G_GENOD)) {</span>
 +
<span id="line150">150.  if (flags.soundok)</span>
 +
<span id="line151">151.      pline("But no one seems to respond to it.");</span>
 +
<span id="line152">152.      } else</span>
 +
<span id="line153">153.  pline("The Keystone Kops are after you!");</span>
 +
<span id="line154">154.  }</span>
 +
<span id="line155">155.  /* Create a swarm near the staircase */</span>
 +
<span id="line156">156.  mm.x = xdnstair;</span>
 +
<span id="line157">157.  mm.y = ydnstair;</span>
 +
<span id="line158">158.  (void) makekops(&mm);</span>
 +
<span id="line159">159.  /* Create a swarm near the shopkeeper */</span>
 +
<span id="line160">160.  mm.x = shopkeeper->mx;</span>
 +
<span id="line161">161.  mm.y = shopkeeper->my;</span>
 +
<span id="line162">162.  (void) makekops(&mm);</span>
 +
<span id="line163">163.      }</span>
 +
<span id="line164">164.  #endif</span>
 +
<span id="line165">165.      }</span>
 +
<span id="line166">166.      shopkeeper = 0;</span>
 +
<span id="line167">167.      shlevel = 0;</span>
 +
<span id="line168">168.  }</span>
 +
<span id="line169">169.  u.uinshop = 0;</span>
 +
<span id="line170">170.  }</span>
 +
<span id="line171">171.  </span>
 +
<span id="line172">172.  /* Did we just enter a zoo of some kind? */</span>
 +
<span id="line173">173.  /* This counts everything except shops and vaults</span>
 +
<span id="line174">174.    -- vault.c insists that a vault remain a VAULT */</span>
 +
<span id="line175">175.  if(roomno >= 0) {</span>
 +
<span id="line176">176.  register int rt = rooms[roomno].rtype;</span>
 +
<span id="line177">177.  register struct monst *mtmp;</span>
 +
<span id="line178">178.  </span>
 +
<span id="line179">179.  switch (rt) {</span>
 +
<span id="line180">180.  case ZOO:</span>
 +
<span id="line181">181.      pline("Welcome to David's treasure zoo!");</span>
 +
<span id="line182">182.      break;</span>
 +
<span id="line183">183.  case SWAMP:</span>
 +
<span id="line184">184.      pline("It looks rather muddy down here.");</span>
 +
<span id="line185">185.      break;</span>
 +
<span id="line186">186.  #ifdef THRONES</span>
 +
<span id="line187">187.  case COURT:</span>
 +
<span id="line188">188.      You("enter an opulent throne room!");</span>
 +
<span id="line189">189.      break;</span>
 +
<span id="line190">190.  #endif</span>
 +
<span id="line191">191.  case MORGUE:</span>
 +
<span id="line192">192.      if(midnight())</span>
 +
<span id="line193">193.  pline("Run away!  Run away!");</span>
 +
<span id="line194">194.      else</span>
 +
<span id="line195">195.  You("have an uncanny feeling...");</span>
 +
<span id="line196">196.      break;</span>
 +
<span id="line197">197.  case BEEHIVE:</span>
 +
<span id="line198">198.      You("enter a giant beehive!");</span>
 +
<span id="line199">199.      break;</span>
 +
<span id="line200">200.  #ifdef ARMY</span>
 +
<span id="line201">201.  case BARRACKS:</span>
 +
<span id="line202">202.      if(!((mons[PM_SOLDIER].geno & G_GENOD) &&</span>
 +
<span id="line203">203.          (mons[PM_SERGEANT].geno & G_GENOD) &&</span>
 +
<span id="line204">204.          (mons[PM_LIEUTENANT].geno & G_GENOD) &&</span>
 +
<span id="line205">205.          (mons[PM_CAPTAIN].geno & G_GENOD)))</span>
 +
<span id="line206">206.      You("enter a military barracks!");</span>
 +
<span id="line207">207.      else You("enter an abandoned barracks.");</span>
 +
<span id="line208">208.      break;</span>
 +
<span id="line209">209.  #endif</span>
 +
<span id="line210">210.  #ifdef ORACLE</span>
 +
<span id="line211">211.  case DELPHI:</span>
 +
<span id="line212">212.      if(!(mons[PM_ORACLE].geno & G_GENOD))</span>
 +
<span id="line213">213.          pline("\"Hello, %s, welcome to Delphi!\"", plname);</span>
 +
<span id="line214">214.      break;</span>
 +
<span id="line215">215.  #endif</span>
 +
<span id="line216">216.  default:</span>
 +
<span id="line217">217.      rt = 0;</span>
 +
<span id="line218">218.  }</span>
 +
<span id="line219">219.  </span>
 +
<span id="line220">220.  if(rt != 0) {</span>
 +
<span id="line221">221.      rooms[roomno].rtype = OROOM;</span>
 +
<span id="line222">222.      if(rt==COURT || rt==SWAMP || rt==MORGUE || rt==ZOO)</span>
 +
<span id="line223">223.  for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)</span>
 +
<span id="line224">224.      /* was if(rt != ZOO || !rn2(3)) -- why should ZOO</span>
 +
<span id="line225">225.        be different from COURT or MORGUE? */</span>
 +
<span id="line226">226.      if(!Stealth && !rn2(3))</span>
 +
<span id="line227">227.  mtmp->msleep = 0;</span>
 +
<span id="line228">228.  }</span>
 +
<span id="line229">229.  }</span>
 +
<span id="line230">230.  #if defined(ALTARS) && defined(THEOLOGY)</span>
 +
<span id="line231">231.  if(roomno >= 0 && rooms[roomno].rtype == TEMPLE) {</span>
 +
<span id="line232">232.      intemple();</span>
 +
<span id="line233">233.  }</span>
 +
<span id="line234">234.  #endif</span>
 +
<span id="line235">235.  /* Did we just enter a shop? */</span>
 +
<span id="line236">236.  if(roomno >= 0 && rooms[roomno].rtype >= SHOPBASE) {</span>
 +
<span id="line237">237.      register int rt = rooms[roomno].rtype;</span>
 +
<span id="line238">238.  </span>
 +
<span id="line239">239.      if(shlevel != dlevel || !shopkeeper</span>
 +
<span id="line240">240.  || ESHK(shopkeeper)->shoproom != roomno)</span>
 +
<span id="line241">241.  findshk(roomno);</span>
 +
<span id="line242">242.      if(!shopkeeper) {</span>
 +
<span id="line243">243.  rooms[roomno].rtype = OROOM;</span>
 +
<span id="line244">244.  u.uinshop = 0;</span>
 +
<span id="line245">245.      } else if(!u.uinshop){</span>
 +
<span id="line246">246.  if(!ESHK(shopkeeper)->visitct ||</span>
 +
<span id="line247">247.    strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)) {</span>
 +
<span id="line248">248.      /* He seems to be new here */</span>
 +
<span id="line249">249.      ESHK(shopkeeper)->visitct = 0;</span>
 +
<span id="line250">250.      ESHK(shopkeeper)->following = 0;</span>
 +
<span id="line251">251.      (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);</span>
 +
<span id="line252">252.      NOTANGRY(shopkeeper) = 1;</span>
 +
<span id="line253">253.  }</span>
 +
<span id="line254">254.  if(!ESHK(shopkeeper)->following && inhishop(shopkeeper)) {</span>
 +
<span id="line255">255.      if(ANGRY(shopkeeper))</span>
 +
<span id="line256">256.  pline("\"So, %s, you dare return to %s's %s?!\"",</span>
 +
<span id="line257">257.      plname,</span>
 +
<span id="line258">258.      shkname(shopkeeper),</span>
 +
<span id="line259">259.      shtypes[rt - SHOPBASE].name);</span>
 +
<span id="line260">260.      else</span>
 +
<span id="line261">261.      if(ESHK(shopkeeper)->robbed)</span>
 +
<span id="line262">262.  pline("\"Beware, %s!  I am upset about missing stock!\"",</span>
 +
<span id="line263">263.      plname);</span>
 +
<span id="line264">264.      else</span>
 +
<span id="line265">265.  pline("\"Hello, %s!  Welcome%s to %s's %s!\"",</span>
 +
<span id="line266">266.      plname,</span>
 +
<span id="line267">267.      ESHK(shopkeeper)->visitct++ ? " again" : "",</span>
 +
<span id="line268">268.      shkname(shopkeeper),</span>
 +
<span id="line269">269.      shtypes[rt - SHOPBASE].name);</span>
 +
<span id="line270">270.      if(carrying(PICK_AXE) != (struct obj *)0) {</span>
 +
<span id="line271">271.  pline(NOTANGRY(shopkeeper) ?</span>
 +
<span id="line272">272.    "\"Will you please leave your pick-axe outside?\"" :</span>
 +
<span id="line273">273.    "\"Leave the pick-axe outside.\"");</span>
 +
<span id="line274">274.  if(dochug(shopkeeper)) {</span>
 +
<span id="line275">275.      u.uinshop = 0; /* he died moving */</span>
 +
<span id="line276">276.      return(0);</span>
 +
<span id="line277">277.  }</span>
 +
<span id="line278">278.      }</span>
 +
<span id="line279">279.  }</span>
 +
<span id="line280">280.  u.uinshop = (unsigned int)(roomno + 1);</span>
 +
<span id="line281">281.      }</span>
 +
<span id="line282">282.  }</span>
 +
<span id="line283">283.  return (int)u.uinshop;</span>
 +
<span id="line284">284.  }</span>
 +
<span id="line285">285.  </span>
 +
<span id="line286">286.  int</span>
 +
<span id="line287">287.  inhishop(mtmp)</span>
 +
<span id="line288">288.  register struct monst *mtmp;</span>
 +
<span id="line289">289.  {</span>
 +
<span id="line290">290.  return((ESHK(mtmp)->shoproom == inroom(mtmp->mx, mtmp->my) &&</span>
 +
<span id="line291">291.  ESHK(mtmp)->shoplevel == dlevel));</span>
 +
<span id="line292">292.  }</span>
 +
<span id="line293">293.  </span>
 +
<span id="line294">294.  static void</span>
 +
<span id="line295">295.  findshk(roomno)</span>
 +
<span id="line296">296.  register int roomno;</span>
 +
<span id="line297">297.  {</span>
 +
<span id="line298">298.  register struct monst *mtmp;</span>
 +
<span id="line299">299.  </span>
 +
<span id="line300">300.  for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)</span>
 +
<span id="line301">301.      if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno</span>
 +
<span id="line302">302.    && ESHK(mtmp)->shoplevel == dlevel) {</span>
 +
<span id="line303">303.  shopkeeper = mtmp;</span>
 +
<span id="line304">304.  bill = &(ESHK(shopkeeper)->bill[0]);</span>
 +
<span id="line305">305.  shlevel = dlevel;</span>
 +
<span id="line306">306.  if(ANGRY(shopkeeper) &&</span>
 +
<span id="line307">307.    strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ))</span>
 +
<span id="line308">308.  NOTANGRY(shopkeeper) = 1;</span>
 +
<span id="line309">309.  /* billobjs = 0; -- this is wrong if we save in a shop */</span>
 +
<span id="line310">310.  /* (and it is harmless to have too many things in billobjs) */</span>
 +
<span id="line311">311.  return;</span>
 +
<span id="line312">312.  }</span>
 +
<span id="line313">313.  shopkeeper = 0;</span>
 +
<span id="line314">314.  shlevel = 0;</span>
 +
<span id="line315">315.  bill = (struct bill_x *) -1000; /* dump core when referenced */</span>
 +
<span id="line316">316.  }</span>
 +
<span id="line317">317.  </span>
 +
<span id="line318">318.  static struct bill_x *</span>
 +
<span id="line319">319.  onbill(obj)</span>
 +
<span id="line320">320.  register struct obj *obj;</span>
 +
<span id="line321">321.  {</span>
 +
<span id="line322">322.  register struct bill_x *bp;</span>
 +
<span id="line323">323.  if(!shopkeeper) return (struct bill_x *)0;</span>
 +
<span id="line324">324.  for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)</span>
 +
<span id="line325">325.  if(bp->bo_id == obj->o_id) {</span>
 +
<span id="line326">326.  if(!obj->unpaid) pline("onbill: paid obj on bill?");</span>
 +
<span id="line327">327.  return(bp);</span>
 +
<span id="line328">328.  }</span>
 +
<span id="line329">329.  if(obj->unpaid) pline("onbill: unpaid obj not on bill?");</span>
 +
<span id="line330">330.  return (struct bill_x *)0;</span>
 +
<span id="line331">331.  }</span>
 +
<span id="line332">332.  </span>
 +
<span id="line333">333.  /* called with two args on merge */</span>
 +
<span id="line334">334.  void</span>
 +
<span id="line335">335.  obfree(obj, merge)</span>
 +
<span id="line336">336.  register struct obj *obj, *merge;</span>
 +
<span id="line337">337.  {</span>
 +
<span id="line338">338.  register struct bill_x *bp = onbill(obj);</span>
 +
<span id="line339">339.  register struct bill_x *bpm;</span>
 +
<span id="line340">340.  if(bp) {</span>
 +
<span id="line341">341.  if(!merge){</span>
 +
<span id="line342">342.  bp->useup = 1;</span>
 +
<span id="line343">343.  obj->unpaid = 0; /* only for doinvbill */</span>
 +
<span id="line344">344.  obj->nobj = billobjs;</span>
 +
<span id="line345">345.  billobjs = obj;</span>
 +
<span id="line346">346.  return;</span>
 +
<span id="line347">347.  }</span>
 +
<span id="line348">348.  bpm = onbill(merge);</span>
 +
<span id="line349">349.  if(!bpm){</span>
 +
<span id="line350">350.  /* this used to be a rename */</span>
 +
<span id="line351">351.  impossible("obfree: not on bill??");</span>
 +
<span id="line352">352.  return;</span>
 +
<span id="line353">353.  } else {</span>
 +
<span id="line354">354.  /* this was a merger */</span>
 +
<span id="line355">355.  bpm->bquan += bp->bquan;</span>
 +
<span id="line356">356.  ESHK(shopkeeper)->billct--;</span>
 +
<span id="line357">357.  *bp = bill[ESHK(shopkeeper)->billct];</span>
 +
<span id="line358">358.  }</span>
 +
<span id="line359">359.  }</span>
 +
<span id="line360">360.  free((genericptr_t) obj);</span>
 +
<span id="line361">361.  }</span>
 +
<span id="line362">362.  </span>
 +
<span id="line363">363.  static long</span>
 +
<span id="line364">364.  check_credit(tmp, shkp)</span>
 +
<span id="line365">365.  long tmp;</span>
 +
<span id="line366">366.  register struct monst *shkp;</span>
 +
<span id="line367">367.  {</span>
 +
<span id="line368">368.  long credit = ESHK(shkp)->credit;</span>
 +
<span id="line369">369.  </span>
 +
<span id="line370">370.  if(credit == 0L) return(tmp);</span>
 +
<span id="line371">371.  if(credit >= tmp) {</span>
 +
<span id="line372">372.  pline("The price is deducted from your credit.");</span>
 +
<span id="line373">373.  ESHK(shkp)->credit -=tmp;</span>
 +
<span id="line374">374.  tmp = 0L;</span>
 +
<span id="line375">375.  } else {</span>
 +
<span id="line376">376.  pline("The price is partially covered by your credit.");</span>
 +
<span id="line377">377.  ESHK(shkp)->credit = 0L;</span>
 +
<span id="line378">378.  tmp -= credit;</span>
 +
<span id="line379">379.  }</span>
 +
<span id="line380">380.  return(tmp);</span>
 +
<span id="line381">381.  }</span>
 +
<span id="line382">382.  </span>
 +
<span id="line383">383.  static void</span>
 +
<span id="line384">384.  pay(tmp,shkp)</span>
 +
<span id="line385">385.  long tmp;</span>
 +
<span id="line386">386.  register struct monst *shkp;</span>
 +
<span id="line387">387.  {</span>
 +
<span id="line388">388.  long robbed = ESHK(shkp)->robbed;</span>
 +
<span id="line389">389.  long balance = ((tmp <= 0) ? tmp : check_credit(tmp, shkp));</span>
 +
<span id="line390">390.  </span>
 +
<span id="line391">391.  u.ugold -= balance;</span>
 +
<span id="line392">392.  shkp->mgold += balance;</span>
 +
<span id="line393">393.  flags.botl = 1;</span>
 +
<span id="line394">394.  if(robbed) {</span>
 +
<span id="line395">395.  robbed -= tmp;</span>
 +
<span id="line396">396.  if(robbed < 0) robbed = 0;</span>
 +
<span id="line397">397.  ESHK(shkp)->robbed = robbed;</span>
 +
<span id="line398">398.  }</span>
 +
<span id="line399">399.  }</span>
 +
<span id="line400">400.  </span>
 +
<span id="line401">401.  /* return shkp to home position */</span>
 +
<span id="line402">402.  void</span>
 +
<span id="line403">403.  home_shk(shkp)</span>
 +
<span id="line404">404.  register struct monst *shkp;</span>
 +
<span id="line405">405.  {</span>
 +
<span id="line406">406.  register xchar x = ESHK(shkp)->shk.x, y = ESHK(shkp)->shk.y;</span>
 +
<span id="line407">407.  if(levl[x][y].mmask)</span>
 +
<span id="line408">408.  mnearto(m_at(x,y), x, y, FALSE);</span>
 +
<span id="line409">409.  levl[shkp->mx][shkp->my].mmask = 0;</span>
 +
<span id="line410">410.  shkp->mx = x;</span>
 +
<span id="line411">411.  shkp->my = y;</span>
 +
<span id="line412">412.  levl[shkp->mx][shkp->my].mmask = 1;</span>
 +
<span id="line413">413.  unpmon(shkp);</span>
 +
<span id="line414">414.  }</span>
 +
<span id="line415">415.  </span>
 +
<span id="line416">416.  void</span>
 +
<span id="line417">417.  make_happy_shk(shkp)</span>
 +
<span id="line418">418.  struct monst *shkp;</span>
 +
<span id="line419">419.  {</span>
 +
<span id="line420">420.  register boolean wasmad = ANGRY(shkp);</span>
 +
<span id="line421">421.  </span>
 +
<span id="line422">422.  NOTANGRY(shkp) = 1;</span>
 +
<span id="line423">423.  ESHK(shkp)->following = 0;</span>
 +
<span id="line424">424.  ESHK(shkp)->robbed = 0;</span>
 +
<span id="line425">425.  if (pl_character[0] != 'R')</span>
 +
<span id="line426">426.  adjalign(sgn(u.ualigntyp));</span>
 +
<span id="line427">427.  if(!inhishop(shkp)) {</span>
 +
<span id="line428">428.  pline("Satisfied, %s suddenly disappears!", mon_nam(shkp));</span>
 +
<span id="line429">429.  if(ESHK(shkp)->shoplevel == dlevel)</span>
 +
<span id="line430">430.  home_shk(shkp);</span>
 +
<span id="line431">431.  else</span>
 +
<span id="line432">432.  fall_down(shkp, ESHK(shkp)->shoplevel);</span>
 +
<span id="line433">433.  } else if(wasmad)</span>
 +
<span id="line434">434.  pline("%s calms down.", Monnam(shkp));</span>
 +
<span id="line435">435.  #ifdef KOPS</span>
 +
<span id="line436">436.  kops_gone();</span>
 +
<span id="line437">437.  #endif</span>
 +
<span id="line438">438.  }</span>
 +
<span id="line439">439.  </span>
 +
<span id="line440">440.  static const char no_money[] = "Moreover, you have no money.";</span>
 +
<span id="line441">441.  </span>
 +
<span id="line442">442.  int</span>
 +
<span id="line443">443.  dopay()</span>
 +
<span id="line444">444.  {</span>
 +
<span id="line445">445.  long ltmp;</span>
 +
<span id="line446">446.  register struct bill_x *bp;</span>
 +
<span id="line447">447.  register struct monst *shkp;</span>
 +
<span id="line448">448.  int pass, tmp;</span>
 +
<span id="line449">449.  </span>
 +
<span id="line450">450.  multi = 0;</span>
 +
<span id="line451">451.  (void) inshop();</span>
 +
<span id="line452">452.  for(shkp = fmon; shkp; shkp = shkp->nmon)</span>
 +
<span id="line453">453.  if(shkp->isshk && dist(shkp->mx,shkp->my) < 3)</span>
 +
<span id="line454">454.  break;</span>
 +
<span id="line455">455.  if(!shkp && u.uinshop && inhishop(shopkeeper))</span>
 +
<span id="line456">456.  shkp = shopkeeper;</span>
 +
<span id="line457">457.  </span>
 +
<span id="line458">458.  if(!shkp) {</span>
 +
<span id="line459">459.  pline("There is nobody here to receive your payment.");</span>
 +
<span id="line460">460.  return(0);</span>
 +
<span id="line461">461.  }</span>
 +
<span id="line462">462.  ltmp = ESHK(shkp)->robbed;</span>
 +
<span id="line463">463.  if(shkp != shopkeeper && NOTANGRY(shkp)) {</span>
 +
<span id="line464">464.  if(!ltmp)</span>
 +
<span id="line465">465.      You("do not owe %s anything.", mon_nam(shkp));</span>
 +
<span id="line466">466.  else if(!u.ugold)</span>
 +
<span id="line467">467.      You("have no money.");</span>
 +
<span id="line468">468.  else {</span>
 +
<span id="line469">469.      long ugold = u.ugold;</span>
 +
<span id="line470">470.  </span>
 +
<span id="line471">471.      if(ugold  > ltmp) {</span>
 +
<span id="line472">472.  You("give %s the %ld gold pieces %s asked for.",</span>
 +
<span id="line473">473.      mon_nam(shkp), ltmp,</span>
 +
<span id="line474">474.      ESHK(shkp)->ismale ? "he" : "she");</span>
 +
<span id="line475">475.  pay(ltmp, shkp);</span>
 +
<span id="line476">476.      } else {</span>
 +
<span id="line477">477.  You("give %s all your gold.", mon_nam(shkp));</span>
 +
<span id="line478">478.  pay(u.ugold, shkp);</span>
 +
<span id="line479">479.      }</span>
 +
<span id="line480">480.      if(ugold < ltmp/2)</span>
 +
<span id="line481">481.  pline("Unfortunately, %s doesn't look satisfied.",</span>
 +
<span id="line482">482.      ESHK(shkp)->ismale ? "he" : "she");</span>
 +
<span id="line483">483.      else</span>
 +
<span id="line484">484.  make_happy_shk(shkp);</span>
 +
<span id="line485">485.  }</span>
 +
<span id="line486">486.  return(1);</span>
 +
<span id="line487">487.  }</span>
 +
<span id="line488">488.  </span>
 +
<span id="line489">489.  /* ltmp is still ESHK(shkp)->robbed here */</span>
 +
<span id="line490">490.  if(!ESHK(shkp)->billct) {</span>
 +
<span id="line491">491.  if(!ltmp && NOTANGRY(shkp)) {</span>
 +
<span id="line492">492.      You("do not owe %s anything.", mon_nam(shkp));</span>
 +
<span id="line493">493.      if(!u.ugold) pline(no_money);</span>
 +
<span id="line494">494.  } else if(ltmp) {</span>
 +
<span id="line495">495.      pline("%s is after blood, not money!", mon_nam(shkp));</span>
 +
<span id="line496">496.      if(u.ugold < ltmp/2) {</span>
 +
<span id="line497">497.  if(!u.ugold) pline(no_money);</span>
 +
<span id="line498">498.  else pline("Besides, you don't have enough to interest %s.",</span>
 +
<span id="line499">499.  ESHK(shkp)->ismale ? "him" : "her");</span>
 +
<span id="line500">500.  return(1);</span>
 +
<span id="line501">501.      }</span>
 +
<span id="line502">502.      pline("But since %s shop has been robbed recently,",</span>
 +
<span id="line503">503.  ESHK(shkp)->ismale ? "his" : "her");</span>
 +
<span id="line504">504.      pline("you %scompensate %s for %s losses.",</span>
 +
<span id="line505">505.  (u.ugold < ltmp) ? "partially " : "",</span>
 +
<span id="line506">506.  mon_nam(shkp),</span>
 +
<span id="line507">507.  ESHK(shkp)->ismale ? "his" : "her");</span>
 +
<span id="line508">508.      pay(u.ugold < ltmp ? u.ugold : ltmp, shkp);</span>
 +
<span id="line509">509.      make_happy_shk(shkp);</span>
 +
<span id="line510">510.  } else {</span>
 +
<span id="line511">511.      /* shopkeeper is angry, but has not been robbed --</span>
 +
<span id="line512">512.      * door broken, attacked, etc. */</span>
 +
<span id="line513">513.      pline("%s is after your hide, not your money!",</span>
 +
<span id="line514">514.  mon_nam(shkp));</span>
 +
<span id="line515">515.      if(u.ugold < 1000) {</span>
 +
<span id="line516">516.  if(!u.ugold) pline(no_money);</span>
 +
<span id="line517">517.  else</span>
 +
<span id="line518">518.  pline("Besides, you don't have enough to interest %s.",</span>
 +
<span id="line519">519.  ESHK(shkp)->ismale ? "him" : "her");</span>
 +
<span id="line520">520.  return(1);</span>
 +
<span id="line521">521.      }</span>
 +
<span id="line522">522.      You("try to appease %s by giving %s 1000 gold pieces.",</span>
 +
<span id="line523">523.  a_monnam(shkp, "angry"),</span>
 +
<span id="line524">524.  ESHK(shkp)->ismale ? "him" : "her");</span>
 +
<span id="line525">525.      pay(1000L,shkp);</span>
 +
<span id="line526">526.      if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)</span>
 +
<span id="line527">527.      || rn2(3))</span>
 +
<span id="line528">528.  make_happy_shk(shkp);</span>
 +
<span id="line529">529.      else</span>
 +
<span id="line530">530.  pline("But %s is as angry as ever.", Monnam(shkp));</span>
 +
<span id="line531">531.  }</span>
 +
<span id="line532">532.  return(1);</span>
 +
<span id="line533">533.  }</span>
 +
<span id="line534">534.  if(shkp != shopkeeper) {</span>
 +
<span id="line535">535.  impossible("dopay: not to shopkeeper?");</span>
 +
<span id="line536">536.  if(shopkeeper) setpaid();</span>
 +
<span id="line537">537.  return(0);</span>
 +
<span id="line538">538.  }</span>
 +
<span id="line539">539.  /* pay debt, if any, first */</span>
 +
<span id="line540">540.  if(ESHK(shopkeeper)->debit) {</span>
 +
<span id="line541">541.          You("owe %s %ld zorkmids for the use of merchandise.",</span>
 +
<span id="line542">542.  shkname(shopkeeper), ESHK(shopkeeper)->debit);</span>
 +
<span id="line543">543.          if(u.ugold + ESHK(shopkeeper)->credit < </span>
 +
<span id="line544">544.  ESHK(shopkeeper)->debit) {</span>
 +
<span id="line545">545.      pline("But you don't have enough gold%s.",</span>
 +
<span id="line546">546.  ESHK(shopkeeper)->credit ? " or credit" : "");</span>
 +
<span id="line547">547.      return(1);</span>
 +
<span id="line548">548.          } else {</span>
 +
<span id="line549">549.      long dtmp = ESHK(shopkeeper)->debit;</span>
 +
<span id="line550">550.  </span>
 +
<span id="line551">551.      if(ESHK(shopkeeper)->credit >= dtmp) {</span>
 +
<span id="line552">552.  ESHK(shopkeeper)->credit -= dtmp;</span>
 +
<span id="line553">553.  ESHK(shopkeeper)->debit = 0L;</span>
 +
<span id="line554">554.                  Your("debt is covered by your credit.");</span>
 +
<span id="line555">555.      } else if(!ESHK(shopkeeper)->credit) {</span>
 +
<span id="line556">556.  u.ugold -= dtmp;</span>
 +
<span id="line557">557.  shopkeeper->mgold += dtmp;</span>
 +
<span id="line558">558.  ESHK(shopkeeper)->debit = 0L;</span>
 +
<span id="line559">559.  You("pay that debt.");</span>
 +
<span id="line560">560.  flags.botl = 1;</span>
 +
<span id="line561">561.      } else {</span>
 +
<span id="line562">562.  dtmp -= ESHK(shopkeeper)->credit;</span>
 +
<span id="line563">563.  ESHK(shopkeeper)->credit = 0L;</span>
 +
<span id="line564">564.  u.ugold -= dtmp;</span>
 +
<span id="line565">565.  shopkeeper->mgold += dtmp;</span>
 +
<span id="line566">566.  ESHK(shopkeeper)->debit = 0L;</span>
 +
<span id="line567">567.  pline("That debt is partially offset by your credit.");</span>
 +
<span id="line568">568.  You("pay the remainder.");</span>
 +
<span id="line569">569.  flags.botl = 1;</span>
 +
<span id="line570">570.      }</span>
 +
<span id="line571">571.  }</span>
 +
<span id="line572">572.  }</span>
 +
<span id="line573">573.  for(pass = 0; pass <= 1; pass++) {</span>
 +
<span id="line574">574.  tmp = 0;</span>
 +
<span id="line575">575.  while(tmp < ESHK(shopkeeper)->billct) {</span>
 +
<span id="line576">576.      bp = &bill[tmp];</span>
 +
<span id="line577">577.      if(!pass && !bp->useup) {</span>
 +
<span id="line578">578.  tmp++;</span>
 +
<span id="line579">579.  continue;</span>
 +
<span id="line580">580.      }</span>
 +
<span id="line581">581.      if(!dopayobj(bp)) return(1);</span>
 +
<span id="line582">582.  #ifdef MSDOS</span>
 +
<span id="line583">583.      *bp = bill[--ESHK(shopkeeper)->billct];</span>
 +
<span id="line584">584.  #else</span>
 +
<span id="line585">585.      bill[tmp] = bill[--ESHK(shopkeeper)->billct];</span>
 +
<span id="line586">586.  #endif /* MSDOS /**/</span>
 +
<span id="line587">587.  }</span>
 +
<span id="line588">588.  }</span>
 +
<span id="line589">589.  pline("\"Thank you for shopping in %s's %s!\"",</span>
 +
<span id="line590">590.  shkname(shopkeeper),</span>
 +
<span id="line591">591.  shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype - SHOPBASE].name);</span>
 +
<span id="line592">592.  NOTANGRY(shopkeeper) = 1;</span>
 +
<span id="line593">593.  return(1);</span>
 +
<span id="line594">594.  }</span>
 +
<span id="line595">595.  </span>
 +
<span id="line596">596.  /* return 1 if paid successfully */</span>
 +
<span id="line597">597.  /*        0 if not enough money */</span>
 +
<span id="line598">598.  /*      -1 if object could not be found (but was paid) */</span>
 +
<span id="line599">599.  static int</span>
 +
<span id="line600">600.  dopayobj(bp)</span>
 +
<span id="line601">601.  register struct bill_x *bp;</span>
 +
<span id="line602">602.  {</span>
 +
<span id="line603">603.  register struct obj *obj;</span>
 +
<span id="line604">604.  long ltmp;</span>
 +
<span id="line605">605.  </span>
 +
<span id="line606">606.  /* find the object on one of the lists */</span>
 +
<span id="line607">607.  obj = bp_to_obj(bp);</span>
 +
<span id="line608">608.  </span>
 +
<span id="line609">609.  if(!obj) {</span>
 +
<span id="line610">610.  impossible("Shopkeeper administration out of order.");</span>
 +
<span id="line611">611.  setpaid(); /* be nice to the player */</span>
 +
<span id="line612">612.  return(0);</span>
 +
<span id="line613">613.  }</span>
 +
<span id="line614">614.  </span>
 +
<span id="line615">615.  if(!obj->unpaid && !bp->useup){</span>
 +
<span id="line616">616.  impossible("Paid object on bill??");</span>
 +
<span id="line617">617.  return(1);</span>
 +
<span id="line618">618.  }</span>
 +
<span id="line619">619.  obj->unpaid = 0;</span>
 +
<span id="line620">620.  ltmp = bp->price * bp->bquan;</span>
 +
<span id="line621">621.  if(ANGRY(shopkeeper)) ltmp += ltmp/3;</span>
 +
<span id="line622">622.  if(u.ugold + ESHK(shopkeeper)->credit < ltmp){</span>
 +
<span id="line623">623.  You("don't have gold%s enough to pay for %s.",</span>
 +
<span id="line624">624.  (ESHK(shopkeeper)->credit > 0L) ? " or credit" : "",</span>
 +
<span id="line625">625.  doname(obj));</span>
 +
<span id="line626">626.  obj->unpaid = 1;</span>
 +
<span id="line627">627.  return(0);</span>
 +
<span id="line628">628.  }</span>
 +
<span id="line629">629.  pay(ltmp, shopkeeper);</span>
 +
<span id="line630">630.  You("bought %s for %ld gold piece%s.",</span>
 +
<span id="line631">631.  doname(obj), ltmp, plur(ltmp));</span>
 +
<span id="line632">632.  if(bp->useup) {</span>
 +
<span id="line633">633.  register struct obj *otmp = billobjs;</span>
 +
<span id="line634">634.  if(obj == billobjs)</span>
 +
<span id="line635">635.  billobjs = obj->nobj;</span>
 +
<span id="line636">636.  else {</span>
 +
<span id="line637">637.  while(otmp && otmp->nobj != obj) otmp = otmp->nobj;</span>
 +
<span id="line638">638.  if(otmp) otmp->nobj = obj->nobj;</span>
 +
<span id="line639">639.  else pline("Error in shopkeeper administration.");</span>
 +
<span id="line640">640.  }</span>
 +
<span id="line641">641.  free((genericptr_t) obj);</span>
 +
<span id="line642">642.  }</span>
 +
<span id="line643">643.  return(1);</span>
 +
<span id="line644">644.  }</span>
 +
<span id="line645">645.  </span>
 +
<span id="line646">646.  /* routine called after dying (or quitting) with nonempty bill or upset shk */</span>
 +
<span id="line647">647.  boolean</span>
 +
<span id="line648">648.  paybill(){</span>
 +
<span id="line649">649.  register struct monst *mtmp;</span>
 +
<span id="line650">650.  register int loss = 0;</span>
 +
<span id="line651">651.  register struct obj *otmp;</span>
 +
<span id="line652">652.  register xchar ox, oy;</span>
 +
<span id="line653">653.  register boolean take = FALSE;</span>
 +
<span id="line654">654.  register boolean taken = FALSE;</span>
 +
<span id="line655">655.  </span>
 +
<span id="line656">656.  for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)</span>
 +
<span id="line657">657.      if(mtmp->isshk) {</span>
 +
<span id="line658">658.  /* for bones: we don't want a shopless shk around */</span>
 +
<span id="line659">659.  if(ESHK(mtmp)->shoplevel != dlevel) mongone(mtmp);</span>
 +
<span id="line660">660.  else shopkeeper = mtmp;</span>
 +
<span id="line661">661.      }</span>
 +
<span id="line662">662.  </span>
 +
<span id="line663">663.  if(!shopkeeper) return(FALSE);</span>
 +
<span id="line664">664.  </span>
 +
<span id="line665">665.  /* get one case out of the way: you die in the shop, the */</span>
 +
<span id="line666">666.  /* shopkeeper is peaceful, nothing stolen, nothing owed. */</span>
 +
<span id="line667">667.  if(in_shop(u.ux,u.uy) && !IS_DOOR(levl[u.ux][u.uy].typ) &&</span>
 +
<span id="line668">668.      !ESHK(shopkeeper)->billct && !ESHK(shopkeeper)->robbed &&</span>
 +
<span id="line669">669.      inhishop(shopkeeper) && NOTANGRY(shopkeeper) &&</span>
 +
<span id="line670">670.      !ESHK(shopkeeper)->following) {</span>
 +
<span id="line671">671.  pline("%s gratefully inherits all your possessions.",</span>
 +
<span id="line672">672.  Monnam(shopkeeper));</span>
 +
<span id="line673">673.  goto clear;</span>
 +
<span id="line674">674.  }</span>
 +
<span id="line675">675.  </span>
 +
<span id="line676">676.  if(ESHK(shopkeeper)->billct || ESHK(shopkeeper)->robbed) {</span>
 +
<span id="line677">677.  addupbill();</span>
 +
<span id="line678">678.  loss = ((total >= ESHK(shopkeeper)->robbed) ? total :</span>
 +
<span id="line679">679.  ESHK(shopkeeper)->robbed);</span>
 +
<span id="line680">680.  take = TRUE;</span>
 +
<span id="line681">681.  }</span>
 +
<span id="line682">682.  </span>
 +
<span id="line683">683.  if(ESHK(shopkeeper)->following || ANGRY(shopkeeper) || take) {</span>
 +
<span id="line684">684.  if((loss > u.ugold) || !loss) {</span>
 +
<span id="line685">685.  pline("%s comes and takes all your possessions.",</span>
 +
<span id="line686">686.  Monnam(shopkeeper));</span>
 +
<span id="line687">687.  taken = TRUE;</span>
 +
<span id="line688">688.  shopkeeper->mgold += u.ugold;</span>
 +
<span id="line689">689.  u.ugold = 0;</span>
 +
<span id="line690">690.  /* in case bones: make it be for real... */</span>
 +
<span id="line691">691.  if(!in_shop(u.ux, u.uy) || IS_DOOR(levl[u.ux][u.uy].typ)) {</span>
 +
<span id="line692">692.      /* shk.x,shk.y is the position immediately in</span>
 +
<span id="line693">693.      * front of the door -- move in one more space</span>
 +
<span id="line694">694.      */</span>
 +
<span id="line695">695.      ox = ESHK(shopkeeper)->shk.x;</span>
 +
<span id="line696">696.      oy = ESHK(shopkeeper)->shk.y;</span>
 +
<span id="line697">697.      ox += sgn(ox - ESHK(shopkeeper)->shd.x);</span>
 +
<span id="line698">698.      oy += sgn(oy - ESHK(shopkeeper)->shd.y);</span>
 +
<span id="line699">699.  } else {</span>
 +
<span id="line700">700.      ox = u.ux;</span>
 +
<span id="line701">701.      oy = u.uy;</span>
 +
<span id="line702">702.  }</span>
 +
<span id="line703">703.  </span>
 +
<span id="line704">704.  if (invent) {</span>
 +
<span id="line705">705.      levl[ox][oy].omask = 1;</span>
 +
<span id="line706">706.      for(otmp = invent; otmp; otmp = otmp->nobj) {</span>
 +
<span id="line707">707.  otmp->ox = ox;</span>
 +
<span id="line708">708.  otmp->oy = oy;</span>
 +
<span id="line709">709.  otmp->age = 0;</span>
 +
<span id="line710">710.      }</span>
 +
<span id="line711">711.  </span>
 +
<span id="line712">712.      /* add to main object list at end so invent is</span>
 +
<span id="line713">713.        still good */</span>
 +
<span id="line714">714.      if (fobj) {</span>
 +
<span id="line715">715.  otmp = fobj;</span>
 +
<span id="line716">716.  while(otmp->nobj)</span>
 +
<span id="line717">717.      otmp = otmp->nobj;</span>
 +
<span id="line718">718.  otmp->nobj = invent;</span>
 +
<span id="line719">719.      } else</span>
 +
<span id="line720">720.  fobj = invent;</span>
 +
<span id="line721">721.  }</span>
 +
<span id="line722">722.  } else {</span>
 +
<span id="line723">723.  u.ugold -= loss;</span>
 +
<span id="line724">724.  shopkeeper->mgold += loss;</span>
 +
<span id="line725">725.  pline("%s comes and takes %ld zorkmids %sowed %s.",</span>
 +
<span id="line726">726.        Monnam(shopkeeper),</span>
 +
<span id="line727">727.        loss,</span>
 +
<span id="line728">728.        strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ) ? "" : "you ",</span>
 +
<span id="line729">729.        ESHK(shopkeeper)->ismale ? "him" : "her");</span>
 +
<span id="line730">730.  }</span>
 +
<span id="line731">731.  </span>
 +
<span id="line732">732.  /* in case we create bones */</span>
 +
<span id="line733">733.  if(!inhishop(shopkeeper))</span>
 +
<span id="line734">734.  home_shk(shopkeeper);</span>
 +
<span id="line735">735.  }</span>
 +
<span id="line736">736.  clear:</span>
 +
<span id="line737">737.  setpaid();</span>
 +
<span id="line738">738.  return(taken);</span>
 +
<span id="line739">739.  }</span>
 +
<span id="line740">740.  </span>
 +
<span id="line741">741.  /* find obj on one of the lists */</span>
 +
<span id="line742">742.  static struct obj *</span>
 +
<span id="line743">743.  bp_to_obj(bp)</span>
 +
<span id="line744">744.  register struct bill_x *bp;</span>
 +
<span id="line745">745.  {</span>
 +
<span id="line746">746.  register struct obj *obj;</span>
 +
<span id="line747">747.  register struct monst *mtmp;</span>
 +
<span id="line748">748.  register unsigned int id = bp->bo_id;</span>
 +
<span id="line749">749.  </span>
 +
<span id="line750">750.  if(bp->useup)</span>
 +
<span id="line751">751.  obj = o_on(id, billobjs);</span>
 +
<span id="line752">752.  else if(!(obj = o_on(id, invent)) &&</span>
 +
<span id="line753">753.  !(obj = o_on(id, fobj)) &&</span>
 +
<span id="line754">754.  !(obj = o_on(id, fcobj))) {</span>
 +
<span id="line755">755.      for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)</span>
 +
<span id="line756">756.  if(obj = o_on(id, mtmp->minvent))</span>
 +
<span id="line757">757.      break;</span>
 +
<span id="line758">758.      for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)</span>
 +
<span id="line759">759.  if(obj = o_on(id, mtmp->minvent))</span>
 +
<span id="line760">760.      break;</span>
 +
<span id="line761">761.  }</span>
 +
<span id="line762">762.  return(obj);</span>
 +
<span id="line763">763.  }</span>
 +
<span id="line764">764.  </span>
 +
<span id="line765">765.  static long</span>
 +
<span id="line766">766.  get_cost(obj)</span>
 +
<span id="line767">767.  register struct obj *obj;</span>
 +
<span id="line768">768.  {</span>
 +
<span id="line769">769.  register long tmp;</span>
 +
<span id="line770">770.  </span>
 +
<span id="line771">771.  tmp = getprice(obj);</span>
 +
<span id="line772">772.  if (!tmp) tmp = 5;</span>
 +
<span id="line773">773.  if (ANGRY(shopkeeper) || </span>
 +
<span id="line774">774.  (pl_character[0] == 'T' && u.ulevel < (MAXULEV/2))</span>
 +
<span id="line775">775.  #ifdef SHIRT</span>
 +
<span id="line776">776.      || (uarmu && !uarm) /* wearing just a Hawaiian shirt */</span>
 +
<span id="line777">777.  #endif</span>
 +
<span id="line778">778.    )</span>
 +
<span id="line779">779.  tmp += tmp/3;</span>
 +
<span id="line780">780.  if (ACURR(A_CHA) > 18) tmp /= 2;</span>
 +
<span id="line781">781.  else if (ACURR(A_CHA) > 17) tmp = (tmp * 2)/3;</span>
 +
<span id="line782">782.  else if (ACURR(A_CHA) > 15) tmp = (tmp * 3)/4;</span>
 +
<span id="line783">783.  else if (ACURR(A_CHA) < 11) tmp = (tmp * 4)/3;</span>
 +
<span id="line784">784.  else if (ACURR(A_CHA) < 8) tmp = (tmp * 3)/2;</span>
 +
<span id="line785">785.  else if (ACURR(A_CHA) < 6) tmp *= 2;</span>
 +
<span id="line786">786.  return(tmp);</span>
 +
<span id="line787">787.  }</span>
 +
<span id="line788">788.  </span>
 +
<span id="line789">789.  </span>
 +
<span id="line790">790.  /* called in hack.c when we pickup an object */</span>
 +
<span id="line791">791.  void</span>
 +
<span id="line792">792.  addtobill(obj, ininv)</span>
 +
<span id="line793">793.  register struct obj *obj;</span>
 +
<span id="line794">794.  register boolean ininv;</span>
 +
<span id="line795">795.  {</span>
 +
<span id="line796">796.  register struct bill_x *bp;</span>
 +
<span id="line797">797.  char buf[40];</span>
 +
<span id="line798">798.  if(!shopkeeper || !inhishop(shopkeeper)) return;</span>
 +
<span id="line799">799.  </span>
 +
<span id="line800">800.  if(!costly_spot(obj->ox,obj->oy) || /* either pickup or kick */</span>
 +
<span id="line801">801.  onbill(obj) /* perhaps we threw it away earlier */</span>
 +
<span id="line802">802.        ) return;</span>
 +
<span id="line803">803.  if(ESHK(shopkeeper)->billct == BILLSZ) {</span>
 +
<span id="line804">804.  You("got that for free!");</span>
 +
<span id="line805">805.  return;</span>
 +
<span id="line806">806.  }</span>
 +
<span id="line807">807.  /* To recognize objects the shopkeeper is not interested in. -dgk</span>
 +
<span id="line808">808.  */</span>
 +
<span id="line809">809.  if (obj->no_charge) {</span>
 +
<span id="line810">810.  obj->no_charge = 0;</span>
 +
<span id="line811">811.  return;</span>
 +
<span id="line812">812.  }</span>
 +
<span id="line813">813.  bp = &bill[ESHK(shopkeeper)->billct];</span>
 +
<span id="line814">814.  bp->bo_id = obj->o_id;</span>
 +
<span id="line815">815.  bp->bquan = obj->quan;</span>
 +
<span id="line816">816.  bp->useup = 0;</span>
 +
<span id="line817">817.  bp->price = get_cost(obj);</span>
 +
<span id="line818">818.  Strcpy(buf, "\"For you, ");</span>
 +
<span id="line819">819.  if (ANGRY(shopkeeper)) Strcat(buf, "scum ");</span>
 +
<span id="line820">820.  else {</span>
 +
<span id="line821">821.      switch(rnd(4)</span>
 +
<span id="line822">822.  #ifdef HARD</span>
 +
<span id="line823">823.    + u.udemigod</span>
 +
<span id="line824">824.  #endif</span>
 +
<span id="line825">825.  ) {</span>
 +
<span id="line826">826.  case 1: Strcat(buf, "good");</span>
 +
<span id="line827">827.  break;</span>
 +
<span id="line828">828.  case 2: Strcat(buf, "honored");</span>
 +
<span id="line829">829.  break;</span>
 +
<span id="line830">830.  case 3: Strcat(buf, "most gracious");</span>
 +
<span id="line831">831.  break;</span>
 +
<span id="line832">832.  case 4: Strcat(buf, "esteemed");</span>
 +
<span id="line833">833.  break;</span>
 +
<span id="line834">834.  case 5: if (u.ualigntyp == U_CHAOTIC) Strcat(buf, "un");</span>
 +
<span id="line835">835.  Strcat(buf, "holy");</span>
 +
<span id="line836">836.  break;</span>
 +
<span id="line837">837.      }</span>
 +
<span id="line838">838.  #ifdef POLYSELF</span>
 +
<span id="line839">839.      if(!is_human(uasmon)) Strcat(buf, " creature");</span>
 +
<span id="line840">840.      else</span>
 +
<span id="line841">841.  #endif</span>
 +
<span id="line842">842.  Strcat(buf, (flags.female) ? " lady" : " sir");</span>
 +
<span id="line843">843.  }</span>
 +
<span id="line844">844.  obj->dknown = 1; /* after all, the shk is telling you what it is */</span>
 +
<span id="line845">845.  if(ininv) {</span>
 +
<span id="line846">846.  obj->quan = 1; /* fool xname() into giving singular */</span>
 +
<span id="line847">847.  pline("%s; only %d %s %s.\"", buf, bp->price,</span>
 +
<span id="line848">848.  (bp->bquan > 1) ? "per" : "for this", xname(obj));</span>
 +
<span id="line849">849.  obj->quan = bp->bquan;</span>
 +
<span id="line850">850.  } else pline("The %s will cost you %d zorkmids%s.",</span>
 +
<span id="line851">851.  xname(obj), bp->price,</span>
 +
<span id="line852">852.  (bp->bquan > 1) ? " each" : "");</span>
 +
<span id="line853">853.  ESHK(shopkeeper)->billct++;</span>
 +
<span id="line854">854.  obj->unpaid = 1;</span>
 +
<span id="line855">855.  }</span>
 +
<span id="line856">856.  </span>
 +
<span id="line857">857.  void</span>
 +
<span id="line858">858.  splitbill(obj, otmp)</span>
 +
<span id="line859">859.  register struct obj *obj, *otmp;</span>
 +
<span id="line860">860.  {</span>
 +
<span id="line861">861.  /* otmp has been split off from obj */</span>
 +
<span id="line862">862.  register struct bill_x *bp;</span>
 +
<span id="line863">863.  register int tmp;</span>
 +
<span id="line864">864.  bp = onbill(obj);</span>
 +
<span id="line865">865.  if(!bp) {</span>
 +
<span id="line866">866.  impossible("splitbill: not on bill?");</span>
 +
<span id="line867">867.  return;</span>
 +
<span id="line868">868.  }</span>
 +
<span id="line869">869.  if(bp->bquan < otmp->quan) {</span>
 +
<span id="line870">870.  impossible("Negative quantity on bill??");</span>
 +
<span id="line871">871.  }</span>
 +
<span id="line872">872.  if(bp->bquan == otmp->quan) {</span>
 +
<span id="line873">873.  impossible("Zero quantity on bill??");</span>
 +
<span id="line874">874.  }</span>
 +
<span id="line875">875.  bp->bquan -= otmp->quan;</span>
 +
<span id="line876">876.  </span>
 +
<span id="line877">877.  if(ESHK(shopkeeper)->billct == BILLSZ) otmp->unpaid = 0;</span>
 +
<span id="line878">878.  else {</span>
 +
<span id="line879">879.  tmp = bp->price;</span>
 +
<span id="line880">880.  bp = &bill[ESHK(shopkeeper)->billct];</span>
 +
<span id="line881">881.  bp->bo_id = otmp->o_id;</span>
 +
<span id="line882">882.  bp->bquan = otmp->quan;</span>
 +
<span id="line883">883.  bp->useup = 0;</span>
 +
<span id="line884">884.  bp->price = tmp;</span>
 +
<span id="line885">885.  ESHK(shopkeeper)->billct++;</span>
 +
<span id="line886">886.  }</span>
 +
<span id="line887">887.  }</span>
 +
<span id="line888">888.  </span>
 +
<span id="line889">889.  void</span>
 +
<span id="line890">890.  subfrombill(obj)</span>
 +
<span id="line891">891.  register struct obj *obj;</span>
 +
<span id="line892">892.  {</span>
 +
<span id="line893">893.  long ltmp;</span>
 +
<span id="line894">894.  /* register int tmp; /* use of tmp commented out below */</span>
 +
<span id="line895">895.  register struct obj *otmp;</span>
 +
<span id="line896">896.  register struct bill_x *bp;</span>
 +
<span id="line897">897.  if(!costly_spot(u.ux,u.uy))</span>
 +
<span id="line898">898.  return;</span>
 +
<span id="line899">899.  if((bp = onbill(obj)) != 0) {</span>
 +
<span id="line900">900.  obj->unpaid = 0;</span>
 +
<span id="line901">901.  if(bp->bquan > obj->quan){</span>
 +
<span id="line902">902.  otmp = newobj(0);</span>
 +
<span id="line903">903.  *otmp = *obj;</span>
 +
<span id="line904">904.  bp->bo_id = otmp->o_id = flags.ident++;</span>
 +
<span id="line905">905.  otmp->quan = (bp->bquan -= obj->quan);</span>
 +
<span id="line906">906.  otmp->owt = 0; /* superfluous */</span>
 +
<span id="line907">907.  otmp->onamelth = 0;</span>
 +
<span id="line908">908.  bp->useup = 1;</span>
 +
<span id="line909">909.  otmp->nobj = billobjs;</span>
 +
<span id="line910">910.  billobjs = otmp;</span>
 +
<span id="line911">911.  return;</span>
 +
<span id="line912">912.  }</span>
 +
<span id="line913">913.  ESHK(shopkeeper)->billct--;</span>
 +
<span id="line914">914.  *bp = bill[ESHK(shopkeeper)->billct];</span>
 +
<span id="line915">915.  return;</span>
 +
<span id="line916">916.  }</span>
 +
<span id="line917">917.  if(obj->unpaid) {</span>
 +
<span id="line918">918.  if(inhishop(shopkeeper))</span>
 +
<span id="line919">919.      pline("%s didn't notice.", Monnam(shopkeeper));</span>
 +
<span id="line920">920.  obj->unpaid = 0;</span>
 +
<span id="line921">921.  return; /* %% */</span>
 +
<span id="line922">922.  }</span>
 +
<span id="line923">923.  /* he dropped something of his own - probably wants to sell it */</span>
 +
<span id="line924">924.  if(shopkeeper->msleep || shopkeeper->mfroz || !inhishop(shopkeeper))</span>
 +
<span id="line925">925.  return;</span>
 +
<span id="line926">926.  ltmp = getprice(obj) * obj->quan;</span>
 +
<span id="line927">927.  if(ESHK(shopkeeper)->billct == BILLSZ</span>
 +
<span id="line928">928.    || !saleable(rooms[ESHK(shopkeeper)->shoproom].rtype-SHOPBASE, obj)</span>
 +
<span id="line929">929.    || otmp->olet == BALL_SYM || ltmp == 0L) {</span>
 +
<span id="line930">930.  pline("%s seems not interested.", Monnam(shopkeeper));</span>
 +
<span id="line931">931.  obj->no_charge = 1;</span>
 +
<span id="line932">932.  return;</span>
 +
<span id="line933">933.  }</span>
 +
<span id="line934">934.  if (ANGRY(shopkeeper) || (pl_character[0] == 'T' && u.ulevel < (MAXULEV/2))</span>
 +
<span id="line935">935.  #ifdef SHIRT</span>
 +
<span id="line936">936.      || (uarmu && !uarm) /* wearing just a Hawaiian shirt */</span>
 +
<span id="line937">937.  #endif</span>
 +
<span id="line938">938.    ) {</span>
 +
<span id="line939">939.  ltmp /= 3;</span>
 +
<span id="line940">940.  NOTANGRY(shopkeeper) = 1;</span>
 +
<span id="line941">941.  } else ltmp /= 2;</span>
 +
<span id="line942">942.  if(ESHK(shopkeeper)->robbed) {</span>
 +
<span id="line943">943.  if((ESHK(shopkeeper)->robbed -= ltmp) < 0)</span>
 +
<span id="line944">944.  ESHK(shopkeeper)->robbed = 0;</span>
 +
<span id="line945">945.  pline("\"Thank you for your contribution to restock this recently plundered shop.\"");</span>
 +
<span id="line946">946.  return;</span>
 +
<span id="line947">947.  }</span>
 +
<span id="line948">948.  if(ltmp > shopkeeper->mgold)</span>
 +
<span id="line949">949.  ltmp = shopkeeper->mgold;</span>
 +
<span id="line950">950.  pay(-ltmp, shopkeeper);</span>
 +
<span id="line951">951.  if(!ltmp) {</span>
 +
<span id="line952">952.  pline("%s gladly accepts %s but cannot pay you at present.",</span>
 +
<span id="line953">953.  Monnam(shopkeeper), doname(obj));</span>
 +
<span id="line954">954.  obj->no_charge = 1;</span>
 +
<span id="line955">955.  } else</span>
 +
<span id="line956">956.  You("sold %s for %ld gold piece%s.", doname(obj), ltmp,</span>
 +
<span id="line957">957.  plur(ltmp));</span>
 +
<span id="line958">958.  }</span>
 +
<span id="line959">959.  </span>
 +
<span id="line960">960.  int</span>
 +
<span id="line961">961.  doinvbill(mode)</span>
 +
<span id="line962">962.  int mode; /* 0: deliver count 1: paged */</span>
 +
<span id="line963">963.  {</span>
 +
<span id="line964">964.  register struct bill_x *bp;</span>
 +
<span id="line965">965.  register struct obj *obj;</span>
 +
<span id="line966">966.  long totused, thisused;</span>
 +
<span id="line967">967.  char buf[BUFSZ];</span>
 +
<span id="line968">968.  </span>
 +
<span id="line969">969.  if(mode == 0) {</span>
 +
<span id="line970">970.      register int cnt = 0;</span>
 +
<span id="line971">971.  </span>
 +
<span id="line972">972.      if(shopkeeper)</span>
 +
<span id="line973">973.  for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++)</span>
 +
<span id="line974">974.      if(bp->useup ||</span>
 +
<span id="line975">975.        ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan))</span>
 +
<span id="line976">976.  cnt++;</span>
 +
<span id="line977">977.      return(cnt);</span>
 +
<span id="line978">978.  }</span>
 +
<span id="line979">979.  </span>
 +
<span id="line980">980.  if(!shopkeeper) {</span>
 +
<span id="line981">981.  impossible("doinvbill: no shopkeeper?");</span>
 +
<span id="line982">982.  return(0);</span>
 +
<span id="line983">983.  }</span>
 +
<span id="line984">984.  </span>
 +
<span id="line985">985.  set_pager(0);</span>
 +
<span id="line986">986.  if(page_line("Unpaid articles already used up:") || page_line(""))</span>
 +
<span id="line987">987.      goto quit;</span>
 +
<span id="line988">988.  </span>
 +
<span id="line989">989.  totused = 0;</span>
 +
<span id="line990">990.  for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) {</span>
 +
<span id="line991">991.      obj = bp_to_obj(bp);</span>
 +
<span id="line992">992.      if(!obj) {</span>
 +
<span id="line993">993.  impossible("Bad shopkeeper administration.");</span>
 +
<span id="line994">994.  goto quit;</span>
 +
<span id="line995">995.      }</span>
 +
<span id="line996">996.      if(bp->useup || bp->bquan > obj->quan) {</span>
 +
<span id="line997">997.  register int cnt, oquan, uquan;</span>
 +
<span id="line998">998.  </span>
 +
<span id="line999">999.  oquan = obj->quan;</span>
 +
<span id="line1000">1000. uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);</span>
 +
<span id="line1001">1001. thisused = bp->price * uquan;</span>
 +
<span id="line1002">1002. totused += thisused;</span>
 +
<span id="line1003">1003. obj->quan = uquan; /* cheat doname */</span>
 +
<span id="line1004">1004. Sprintf(buf, "x -  %s", doname(obj));</span>
 +
<span id="line1005">1005. obj->quan = oquan; /* restore value */</span>
 +
<span id="line1006">1006. for(cnt = 0; buf[cnt]; cnt++);</span>
 +
<span id="line1007">1007. while(cnt < 50)</span>
 +
<span id="line1008">1008. buf[cnt++] = ' ';</span>
 +
<span id="line1009">1009. Sprintf(&buf[cnt], " %5ld zorkmids", thisused);</span>
 +
<span id="line1010">1010. if(page_line(buf))</span>
 +
<span id="line1011">1011. goto quit;</span>
 +
<span id="line1012">1012.     }</span>
 +
<span id="line1013">1013. }</span>
 +
<span id="line1014">1014. Sprintf(buf, "Total:%50ld zorkmids", totused);</span>
 +
<span id="line1015">1015. if(page_line("") || page_line(buf))</span>
 +
<span id="line1016">1016. goto quit;</span>
 +
<span id="line1017">1017. set_pager(1);</span>
 +
<span id="line1018">1018. return(0);</span>
 +
<span id="line1019">1019. quit:</span>
 +
<span id="line1020">1020. set_pager(2);</span>
 +
<span id="line1021">1021. return(0);</span>
 +
<span id="line1022">1022. }</span>
 +
<span id="line1023">1023. </span>
 +
<span id="line1024">1024. #define HUNGRY 2</span>
 +
<span id="line1025">1025. static int</span>
 +
<span id="line1026">1026. getprice(obj)</span>
 +
<span id="line1027">1027. register struct obj *obj;</span>
 +
<span id="line1028">1028. {</span>
 +
<span id="line1029">1029. register int tmp = objects[obj->otyp].oc_cost;</span>
 +
<span id="line1030">1030. </span>
 +
<span id="line1031">1031. switch(obj->olet) {</span>
 +
<span id="line1032">1032. case AMULET_SYM:</span>
 +
<span id="line1033">1033. if(obj->otyp == AMULET_OF_YENDOR) {</span>
 +
<span id="line1034">1034. /* don't let the player get rich selling fakes */</span>
 +
<span id="line1035">1035. tmp = (obj->spe < 0 ? 0 : 3500);</span>
 +
<span id="line1036">1036. }</span>
 +
<span id="line1037">1037. break;</span>
 +
<span id="line1038">1038. case FOOD_SYM:</span>
 +
<span id="line1039">1039. /* simpler hunger check, (2-4)*cost */</span>
 +
<span id="line1040">1040. if (u.uhs >= HUNGRY) tmp *= u.uhs;</span>
 +
<span id="line1041">1041. break;</span>
 +
<span id="line1042">1042. case WAND_SYM:</span>
 +
<span id="line1043">1043. if (obj->spe == -1) tmp = 0;</span>
 +
<span id="line1044">1044. break;</span>
 +
<span id="line1045">1045. case POTION_SYM:</span>
 +
<span id="line1046">1046. if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed)</span>
 +
<span id="line1047">1047. tmp = 0;</span>
 +
<span id="line1048">1048. break;</span>
 +
<span id="line1049">1049. case ARMOR_SYM:</span>
 +
<span id="line1050">1050. if (u.uac > 0) tmp += u.uac * 2;</span>
 +
<span id="line1051">1051. case WEAPON_SYM:</span>
 +
<span id="line1052">1052. if (obj->spe > 0) tmp += 10 * obj->spe;</span>
 +
<span id="line1053">1053. break;</span>
 +
<span id="line1054">1054. case CHAIN_SYM:</span>
 +
<span id="line1055">1055. pline("Strange... carrying a chain?");</span>
 +
<span id="line1056">1056. break;</span>
 +
<span id="line1057">1057. }</span>
 +
<span id="line1058">1058. return(tmp);</span>
 +
<span id="line1059">1059. }</span>
 +
<span id="line1060">1060. </span>
 +
<span id="line1061">1061. int</span>
 +
<span id="line1062">1062. shkcatch(obj)</span>
 +
<span id="line1063">1063. register struct obj *obj;</span>
 +
<span id="line1064">1064. {</span>
 +
<span id="line1065">1065. register struct monst *shkp = shopkeeper;</span>
 +
<span id="line1066">1066. </span>
 +
<span id="line1067">1067. if(u.uinshop && shkp && !shkp->mfroz && !shkp->msleep &&</span>
 +
<span id="line1068">1068.     u.dx && u.dy &&</span>
 +
<span id="line1069">1069.     inroom(u.ux+u.dx, u.uy+u.dy) + 1 == u.uinshop &&</span>
 +
<span id="line1070">1070.     shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y &&</span>
 +
<span id="line1071">1071.     u.ux == ESHK(shkp)->shd.x && u.uy == ESHK(shkp)->shd.y) {</span>
 +
<span id="line1072">1072. pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj));</span>
 +
<span id="line1073">1073. obj->nobj = shkp->minvent;</span>
 +
<span id="line1074">1074. shkp->minvent = obj;</span>
 +
<span id="line1075">1075. return(1);</span>
 +
<span id="line1076">1076. }</span>
 +
<span id="line1077">1077. return(0);</span>
 +
<span id="line1078">1078. }</span>
 +
<span id="line1079">1079. </span>
 +
<span id="line1080">1080. /*</span>
 +
<span id="line1081">1081.  * shk_move: return 1: he moved  0: he didn't  -1: let m_move do it  -2: died</span>
 +
<span id="line1082">1082.  */</span>
 +
<span id="line1083">1083. int</span>
 +
<span id="line1084">1084. shk_move(shkp)</span>
 +
<span id="line1085">1085. register struct monst *shkp;</span>
 +
<span id="line1086">1086. {</span>
 +
<span id="line1087">1087. register xchar gx,gy,omx,omy;</span>
 +
<span id="line1088">1088. register int udist;</span>
 +
<span id="line1089">1089. register schar appr;</span>
 +
<span id="line1090">1090. int z;</span>
 +
<span id="line1091">1091. schar shkroom;</span>
 +
<span id="line1092">1092. boolean uondoor, satdoor, avoid, badinv;</span>
 +
<span id="line1093">1093. </span>
 +
<span id="line1094">1094. omx = shkp->mx;</span>
 +
<span id="line1095">1095. omy = shkp->my;</span>
 +
<span id="line1096">1096. </span>
 +
<span id="line1097">1097. if((udist = dist(omx,omy)) < 3) {</span>
 +
<span id="line1098">1098. if(ANGRY(shkp)) {</span>
 +
<span id="line1099">1099. if(Displaced)</span>
 +
<span id="line1100">1100.   Your("displaced image doesn't fool %s!",</span>
 +
<span id="line1101">1101. Monnam(shkp));</span>
 +
<span id="line1102">1102. (void) mattacku(shkp);</span>
 +
<span id="line1103">1103. return(0);</span>
 +
<span id="line1104">1104. }</span>
 +
<span id="line1105">1105. if(ESHK(shkp)->following) {</span>
 +
<span id="line1106">1106. if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)) {</span>
 +
<span id="line1107">1107.     pline("\"Hello, %s!  I was looking for %s.\"",</span>
 +
<span id="line1108">1108.     plname, ESHK(shkp)->customer);</span>
 +
<span id="line1109">1109.     ESHK(shkp)->following = 0;</span>
 +
<span id="line1110">1110.     return(0);</span>
 +
<span id="line1111">1111. }</span>
 +
<span id="line1112">1112. if(moves > followmsg+4) {</span>
 +
<span id="line1113">1113.     pline("\"Hello, %s!  Didn't you forget to pay?\"",</span>
 +
<span id="line1114">1114.     plname);</span>
 +
<span id="line1115">1115.     followmsg = moves;</span>
 +
<span id="line1116">1116. #ifdef HARD</span>
 +
<span id="line1117">1117.     if (!rn2(4)) {</span>
 +
<span id="line1118">1118.     pline ("%s doesn't like customers who don't pay.", Monnam(shkp));</span>
 +
<span id="line1119">1119. NOTANGRY(shkp) = 0;</span>
 +
<span id="line1120">1120.     }</span>
 +
<span id="line1121">1121. #endif</span>
 +
<span id="line1122">1122. }</span>
 +
<span id="line1123">1123. if(udist < 2)</span>
 +
<span id="line1124">1124.     return(0);</span>
 +
<span id="line1125">1125. }</span>
 +
<span id="line1126">1126. }</span>
 +
<span id="line1127">1127. </span>
 +
<span id="line1128">1128. shkroom = inroom(omx,omy);</span>
 +
<span id="line1129">1129. appr = 1;</span>
 +
<span id="line1130">1130. gx = ESHK(shkp)->shk.x;</span>
 +
<span id="line1131">1131. gy = ESHK(shkp)->shk.y;</span>
 +
<span id="line1132">1132. satdoor = (gx == omx && gy == omy);</span>
 +
<span id="line1133">1133. if(ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){</span>
 +
<span id="line1134">1134. gx = u.ux;</span>
 +
<span id="line1135">1135. gy = u.uy;</span>
 +
<span id="line1136">1136. if(shkroom < 0 || shkroom != inroom(u.ux,u.uy))</span>
 +
<span id="line1137">1137.     if(udist > 4)</span>
 +
<span id="line1138">1138. return(-1); /* leave it to m_move */</span>
 +
<span id="line1139">1139. } else if(ANGRY(shkp)) {</span>
 +
<span id="line1140">1140. long saveBlind = Blinded;</span>
 +
<span id="line1141">1141. struct obj *saveUblindf = ublindf;</span>
 +
<span id="line1142">1142. Blinded = 0;</span>
 +
<span id="line1143">1143. ublindf = (struct obj *)0;</span>
 +
<span id="line1144">1144. if(shkp->mcansee && !Invis && cansee(omx,omy)) {</span>
 +
<span id="line1145">1145. gx = u.ux;</span>
 +
<span id="line1146">1146. gy = u.uy;</span>
 +
<span id="line1147">1147. }</span>
 +
<span id="line1148">1148. Blinded = saveBlind;</span>
 +
<span id="line1149">1149. ublindf = saveUblindf;</span>
 +
<span id="line1150">1150. avoid = FALSE;</span>
 +
<span id="line1151">1151. } else {</span>
 +
<span id="line1152">1152. #define GDIST(x,y) (dist2(x,y,gx,gy))</span>
 +
<span id="line1153">1153. if(Invis)</span>
 +
<span id="line1154">1154.     avoid = FALSE;</span>
 +
<span id="line1155">1155. else {</span>
 +
<span id="line1156">1156.     uondoor = (u.ux == ESHK(shkp)->shd.x &&</span>
 +
<span id="line1157">1157. u.uy == ESHK(shkp)->shd.y);</span>
 +
<span id="line1158">1158.     if(uondoor) {</span>
 +
<span id="line1159">1159. if(ESHK(shkp)->billct && inhishop(shkp))</span>
 +
<span id="line1160">1160.     pline(NOTANGRY(shkp) ?</span>
 +
<span id="line1161">1161. "\"Hello, %s!  Will you please pay before leaving?\"" :</span>
 +
<span id="line1162">1162. "\"Hey, %s!  Don't leave without paying!\"",</span>
 +
<span id="line1163">1163. plname);</span>
 +
<span id="line1164">1164. badinv = (!!carrying(PICK_AXE));</span>
 +
<span id="line1165">1165. if(satdoor && badinv)</span>
 +
<span id="line1166">1166.     return(0);</span>
 +
<span id="line1167">1167. avoid = !badinv;</span>
 +
<span id="line1168">1168.     } else {</span>
 +
<span id="line1169">1169. avoid = (u.uinshop && dist(gx,gy) > 8);</span>
 +
<span id="line1170">1170. badinv = FALSE;</span>
 +
<span id="line1171">1171.     }</span>
 +
<span id="line1172">1172. </span>
 +
<span id="line1173">1173.     if(((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)</span>
 +
<span id="line1174">1174. && GDIST(omx,omy) < 3) {</span>
 +
<span id="line1175">1175. if(!badinv && !online(omx,omy))</span>
 +
<span id="line1176">1176.     return(0);</span>
 +
<span id="line1177">1177. if(satdoor)</span>
 +
<span id="line1178">1178.     appr = gx = gy = 0;</span>
 +
<span id="line1179">1179.     }</span>
 +
<span id="line1180">1180. }</span>
 +
<span id="line1181">1181. }</span>
 +
<span id="line1182">1182. </span>
 +
<span id="line1183">1183. return(move_special(shkp,shkroom,appr,uondoor,avoid,omx,omy,gx,gy));</span>
 +
<span id="line1184">1184. }</span>
 +
<span id="line1185">1185. </span>
 +
<span id="line1186">1186. int</span>
 +
<span id="line1187">1187. online(x,y) /* New version to speed things up.</span>
 +
<span id="line1188">1188. * Compiler dependant, may not always work.</span>
 +
<span id="line1189">1189. */</span>
 +
<span id="line1190">1190. register xchar x, y;</span>
 +
<span id="line1191">1191. {</span>
 +
<span id="line1192">1192. return((x-=u.ux) == 0 || (y-=u.uy) == 0 || x == y || (x+=y) == 0);</span>
 +
<span id="line1193">1193. }</span>
 +
<span id="line1194">1194. </span>
 +
<span id="line1195">1195. /* Original version, just in case...</span>
 +
<span id="line1196">1196.  *online(x,y) {</span>
 +
<span id="line1197">1197.  * return(x==u.ux || y==u.uy || (x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy));</span>
 +
<span id="line1198">1198.  *}</span>
 +
<span id="line1199">1199.  */</span>
 +
<span id="line1200">1200. </span>
 +
<span id="line1201">1201. /* for use in levl_follower (mondata.c) */</span>
 +
<span id="line1202">1202. boolean</span>
 +
<span id="line1203">1203. is_fshk(mtmp)</span>
 +
<span id="line1204">1204. register struct monst *mtmp;</span>
 +
<span id="line1205">1205. {</span>
 +
<span id="line1206">1206. return(mtmp->isshk && ESHK(mtmp)->following);</span>
 +
<span id="line1207">1207. }</span>
 +
<span id="line1208">1208. </span>
 +
<span id="line1209">1209. /* He is digging in the shop. */</span>
 +
<span id="line1210">1210. void</span>
 +
<span id="line1211">1211. shopdig(fall)</span>
 +
<span id="line1212">1212. register int fall;</span>
 +
<span id="line1213">1213. {</span>
 +
<span id="line1214">1214.    if(!shopkeeper) return;</span>
 +
<span id="line1215">1215.    if(!inhishop(shopkeeper)) {</span>
 +
<span id="line1216">1216. if (pl_character[0] == 'K') adjalign(-sgn(u.ualigntyp));</span>
 +
<span id="line1217">1217. return;</span>
 +
<span id="line1218">1218.    }</span>
 +
<span id="line1219">1219. </span>
 +
<span id="line1220">1220.    if(!fall) {</span>
 +
<span id="line1221">1221. if(u.utraptype == TT_PIT)</span>
 +
<span id="line1222">1222.     pline("\"Be careful, %s, or you might fall through the floor.\"",</span>
 +
<span id="line1223">1223. flags.female ? "madam" : "sir");</span>
 +
<span id="line1224">1224. else</span>
 +
<span id="line1225">1225.     pline("\"%s, do not damage the floor here!\"",</span>
 +
<span id="line1226">1226. flags.female ? "Madam" : "Sir");</span>
 +
<span id="line1227">1227. if (pl_character[0] == 'K') adjalign(-sgn(u.ualigntyp));</span>
 +
<span id="line1228">1228.    } else if(um_dist(shopkeeper->mx, shopkeeper->my, 2)) {</span>
 +
<span id="line1229">1229. register struct obj *obj, *obj2;</span>
 +
<span id="line1230">1230. </span>
 +
<span id="line1231">1231. if(dist(shopkeeper->mx, shopkeeper->my) > 2) {</span>
 +
<span id="line1232">1232. mnexto(shopkeeper);</span>
 +
<span id="line1233">1233. /* for some reason he can't come next to you */</span>
 +
<span id="line1234">1234. if(dist(shopkeeper->mx, shopkeeper->my) > 2) {</span>
 +
<span id="line1235">1235.     pline("%s curses you in anger and frustration!",</span>
 +
<span id="line1236">1236. shkname(shopkeeper));</span>
 +
<span id="line1237">1237.     NOTANGRY(shopkeeper) = 0;</span>
 +
<span id="line1238">1238.     return;</span>
 +
<span id="line1239">1239. } else pline("%s leaps, and grabs your backpack!",</span>
 +
<span id="line1240">1240. shkname(shopkeeper));</span>
 +
<span id="line1241">1241. } else pline("%s grabs your backpack!", shkname(shopkeeper));</span>
 +
<span id="line1242">1242. </span>
 +
<span id="line1243">1243. for(obj = invent; obj; obj = obj2) {</span>
 +
<span id="line1244">1244. obj2 = obj->nobj;</span>
 +
<span id="line1245">1245. if(obj->owornmask) continue;</span>
 +
<span id="line1246">1246. freeinv(obj);</span>
 +
<span id="line1247">1247. obj->nobj = shopkeeper->minvent;</span>
 +
<span id="line1248">1248. shopkeeper->minvent = obj;</span>
 +
<span id="line1249">1249. if(obj->unpaid)</span>
 +
<span id="line1250">1250. subfrombill(obj);</span>
 +
<span id="line1251">1251. }</span>
 +
<span id="line1252">1252.    }</span>
 +
<span id="line1253">1253. }</span>
 +
<span id="line1254">1254. </span>
 +
<span id="line1255">1255. #ifdef KOPS</span>
 +
<span id="line1256">1256. static int</span>
 +
<span id="line1257">1257. makekops(mm) /* returns the number of (all types of) Kops  made */</span>
 +
<span id="line1258">1258. coord *mm;</span>
 +
<span id="line1259">1259. {</span>
 +
<span id="line1260">1260. register int cnt = dlevel + rnd(5);</span>
 +
<span id="line1261">1261. register int scnt = (cnt / 3) + 1; /* at least one sarge */</span>
 +
<span id="line1262">1262. register int lcnt = (cnt / 6); /* maybe a lieutenant */</span>
 +
<span id="line1263">1263. register int kcnt = (cnt / 9); /* and maybe a kaptain */</span>
 +
<span id="line1264">1264. </span>
 +
<span id="line1265">1265. while(cnt--) {</span>
 +
<span id="line1266">1266.     enexto(mm, mm->x, mm->y);</span>
 +
<span id="line1267">1267.     (void) makemon(&mons[PM_KEYSTONE_KOP], mm->x, mm->y);</span>
 +
<span id="line1268">1268. }</span>
 +
<span id="line1269">1269. while(scnt--) {</span>
 +
<span id="line1270">1270.     enexto(mm, mm->x, mm->y);</span>
 +
<span id="line1271">1271.     (void) makemon(&mons[PM_KOP_SERGEANT], mm->x, mm->y);</span>
 +
<span id="line1272">1272. }</span>
 +
<span id="line1273">1273. while(lcnt--) {</span>
 +
<span id="line1274">1274.     enexto(mm, mm->x, mm->y);</span>
 +
<span id="line1275">1275.     (void) makemon(&mons[PM_KOP_LIEUTENANT], mm->x, mm->y);</span>
 +
<span id="line1276">1276. }</span>
 +
<span id="line1277">1277. while(kcnt--) {</span>
 +
<span id="line1278">1278.     enexto(mm, mm->x, mm->y);</span>
 +
<span id="line1279">1279.     (void) makemon(&mons[PM_KOP_KAPTAIN], mm->x, mm->y);</span>
 +
<span id="line1280">1280. }</span>
 +
<span id="line1281">1281. return(cnt + scnt + lcnt + kcnt);</span>
 +
<span id="line1282">1282. }</span>
 +
<span id="line1283">1283. #endif</span>
 +
<span id="line1284">1284. </span>
 +
<span id="line1285">1285. boolean</span>
 +
<span id="line1286">1286. in_shop(x,y)</span>
 +
<span id="line1287">1287. register int x, y;</span>
 +
<span id="line1288">1288. {</span>
 +
<span id="line1289">1289. register int roomno = inroom(x, y);</span>
 +
<span id="line1290">1290. </span>
 +
<span id="line1291">1291. if (roomno < 0) return(FALSE);</span>
 +
<span id="line1292">1292. return (IS_SHOP(rooms[roomno]));</span>
 +
<span id="line1293">1293. }</span>
 +
<span id="line1294">1294. </span>
 +
<span id="line1295">1295. void</span>
 +
<span id="line1296">1296. pay_for_door(x,y,dmgstr)</span>
 +
<span id="line1297">1297. register int x, y;</span>
 +
<span id="line1298">1298. register char *dmgstr;</span>
 +
<span id="line1299">1299. {</span>
 +
<span id="line1300">1300. register struct monst *mtmp;</span>
 +
<span id="line1301">1301. register int ox, oy;</span>
 +
<span id="line1302">1302. register int roomno = inroom(x, y);</span>
 +
<span id="line1303">1303. register int damage = (ACURR(A_STR) > 18) ? 400 : 20 * ACURR(A_STR);</span>
 +
<span id="line1304">1304. </span>
 +
<span id="line1305">1305. /* make sure this function is not used in the wrong place */</span>
 +
<span id="line1306">1306. if(!(IS_DOOR(levl[x][y].typ) && in_shop(x, y))) return;</span>
 +
<span id="line1307">1307. </span>
 +
<span id="line1308">1308. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)</span>
 +
<span id="line1309">1309.     if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno</span>
 +
<span id="line1310">1310.   && ESHK(mtmp)->shoplevel == dlevel) {</span>
 +
<span id="line1311">1311. shopkeeper = mtmp;</span>
 +
<span id="line1312">1312. }</span>
 +
<span id="line1313">1313. </span>
 +
<span id="line1314">1314. if(!shopkeeper) return;</span>
 +
<span id="line1315">1315. </span>
 +
<span id="line1316">1316. /* not the best introduction to the shk... */</span>
 +
<span id="line1317">1317. (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);</span>
 +
<span id="line1318">1318. </span>
 +
<span id="line1319">1319. /* if he is already on the war path, be sure it's all out */</span>
 +
<span id="line1320">1320. if(ANGRY(shopkeeper) || ESHK(shopkeeper)->following) {</span>
 +
<span id="line1321">1321. NOTANGRY(shopkeeper) = 0;</span>
 +
<span id="line1322">1322. ESHK(shopkeeper)->following = 1;</span>
 +
<span id="line1323">1323. return;</span>
 +
<span id="line1324">1324. }</span>
 +
<span id="line1325">1325. </span>
 +
<span id="line1326">1326. ox = shopkeeper->mx;</span>
 +
<span id="line1327">1327. oy = shopkeeper->my;</span>
 +
<span id="line1328">1328. </span>
 +
<span id="line1329">1329. /* if he's not in his shop.. */</span>
 +
<span id="line1330">1330. if(!in_shop(ox, oy)) return;</span>
 +
<span id="line1331">1331. </span>
 +
<span id="line1332">1332. /* if a !shopkeeper shows up at the door, move him */</span>
 +
<span id="line1333">1333. if(levl[x][y].mmask && (mtmp = m_at(x, y)) != shopkeeper) {</span>
 +
<span id="line1334">1334. if(flags.soundok) {</span>
 +
<span id="line1335">1335.     You("hear an angry voice: \"Out of my way, scum!\"");</span>
 +
<span id="line1336">1336.     (void) fflush(stdout);</span>
 +
<span id="line1337">1337. #if defined(SYSV) || defined(ULTRIX)</span>
 +
<span id="line1338">1338.     (void)</span>
 +
<span id="line1339">1339. #endif</span>
 +
<span id="line1340">1340. #ifdef UNIX</span>
 +
<span id="line1341">1341. sleep(1);</span>
 +
<span id="line1342">1342. #endif</span>
 +
<span id="line1343">1343. }</span>
 +
<span id="line1344">1344. mnearto(mtmp, x, y, FALSE);</span>
 +
<span id="line1345">1345. }</span>
 +
<span id="line1346">1346. </span>
 +
<span id="line1347">1347. /* make shk show up at the door */</span>
 +
<span id="line1348">1348. levl[shopkeeper->mx][shopkeeper->my].mmask = 0;</span>
 +
<span id="line1349">1349. levl[x][y].mmask = 1;</span>
 +
<span id="line1350">1350. shopkeeper->mx = x;</span>
 +
<span id="line1351">1351. shopkeeper->my = y;</span>
 +
<span id="line1352">1352. pmon(shopkeeper);</span>
 +
<span id="line1353">1353. </span>
 +
<span id="line1354">1354. if(um_dist(x, y, 1)) goto chase;</span>
 +
<span id="line1355">1355. </span>
 +
<span id="line1356">1356. if(u.ugold < damage || !rn2(50)) {</span>
 +
<span id="line1357">1357. chase:</span>
 +
<span id="line1358">1358. if(um_dist(x, y, 1))</span>
 +
<span id="line1359">1359.     pline("%s shouts: \"Who dared %s my door?\"",</span>
 +
<span id="line1360">1360. shkname(shopkeeper), dmgstr);</span>
 +
<span id="line1361">1361. else pline("\"How dare you %s my door?\"", dmgstr);</span>
 +
<span id="line1362">1362. NOTANGRY(shopkeeper) = 0;</span>
 +
<span id="line1363">1363. ESHK(shopkeeper)->following = 1;</span>
 +
<span id="line1364">1364. return;</span>
 +
<span id="line1365">1365. }</span>
 +
<span id="line1366">1366. </span>
 +
<span id="line1367">1367. pline("\"Cad!  You did %d zorkmids worth of damage!\"  Pay? ", damage);</span>
 +
<span id="line1368">1368. if(yn() != 'n') {</span>
 +
<span id="line1369">1369. u.ugold -= damage;</span>
 +
<span id="line1370">1370. shopkeeper->mgold += damage;</span>
 +
<span id="line1371">1371. flags.botl = 1;</span>
 +
<span id="line1372">1372. pline("Mollified, %s accepts your restitution.",</span>
 +
<span id="line1373">1373. shkname(shopkeeper));</span>
 +
<span id="line1374">1374. </span>
 +
<span id="line1375">1375. /* clear ox oy of another monster, if one got there somehow */</span>
 +
<span id="line1376">1376. if(levl[ox][oy].mmask) mnearto(m_at(ox,oy),ox,oy,FALSE);</span>
 +
<span id="line1377">1377. </span>
 +
<span id="line1378">1378. /* move shk back to his orig loc */</span>
 +
<span id="line1379">1379. levl[shopkeeper->mx][shopkeeper->my].mmask = 0;</span>
 +
<span id="line1380">1380. levl[ox][oy].mmask = 1;</span>
 +
<span id="line1381">1381. shopkeeper->mx = ox;</span>
 +
<span id="line1382">1382. shopkeeper->my = oy;</span>
 +
<span id="line1383">1383. unpmon(shopkeeper);</span>
 +
<span id="line1384">1384. NOTANGRY(shopkeeper) = 1;</span>
 +
<span id="line1385">1385. }</span>
 +
<span id="line1386">1386. else {</span>
 +
<span id="line1387">1387. pline("\"Oh, yes!  You'll pay!\"");</span>
 +
<span id="line1388">1388. ESHK(shopkeeper)->following = 1;</span>
 +
<span id="line1389">1389. NOTANGRY(shopkeeper) = 0;</span>
 +
<span id="line1390">1390. adjalign(-sgn(u.ualigntyp));</span>
 +
<span id="line1391">1391. }</span>
 +
<span id="line1392">1392. }</span>
 +
<span id="line1393">1393. </span>
 +
<span id="line1394">1394. /* called in dokick.c when we kick an object in a store */</span>
 +
<span id="line1395">1395. boolean</span>
 +
<span id="line1396">1396. costly_spot(x, y)</span>
 +
<span id="line1397">1397. register int x, y;</span>
 +
<span id="line1398">1398. {</span>
 +
<span id="line1399">1399. register struct monst *shkp = shopkeeper;</span>
 +
<span id="line1400">1400. </span>
 +
<span id="line1401">1401. if(!shkp) return(FALSE);</span>
 +
<span id="line1402">1402. </span>
 +
<span id="line1403">1403. return(in_shop(x, y) && levl[x][y].typ != DOOR &&</span>
 +
<span id="line1404">1404. !(x == ESHK(shkp)->shk.x && y == ESHK(shkp)->shk.y));</span>
 +
<span id="line1405">1405. }</span>
 +
<span id="line1406">1406. </span>
 +
<span id="line1407">1407. #ifdef KOPS</span>
 +
<span id="line1408">1408. static void</span>
 +
<span id="line1409">1409. kops_gone()</span>
 +
<span id="line1410">1410. {</span>
 +
<span id="line1411">1411. register int cnt = 0;</span>
 +
<span id="line1412">1412. register struct monst *mtmp, *mtmp2;</span>
 +
<span id="line1413">1413. </span>
 +
<span id="line1414">1414. /* turn off automatic resurrection of kops */</span>
 +
<span id="line1415">1415. allow_kops = FALSE;</span>
 +
<span id="line1416">1416. </span>
 +
<span id="line1417">1417. for(mtmp = fmon; mtmp; mtmp = mtmp2) {</span>
 +
<span id="line1418">1418. mtmp2 = mtmp->nmon;</span>
 +
<span id="line1419">1419. if(mtmp->data->mlet == S_KOP) {</span>
 +
<span id="line1420">1420. mongone(mtmp);</span>
 +
<span id="line1421">1421. cnt++;</span>
 +
<span id="line1422">1422. }</span>
 +
<span id="line1423">1423. }</span>
 +
<span id="line1424">1424. if(cnt) pline("The Kops (disappointed) disappear into thin air.");</span>
 +
<span id="line1425">1425. allow_kops = TRUE;</span>
 +
<span id="line1426">1426. }</span>
 +
<span id="line1427">1427. #endif</span>
 +
<span id="line1428">1428. </span>
 +
<span id="line1429">1429. static long</span>
 +
<span id="line1430">1430. cost_per_charge(otmp)</span>
 +
<span id="line1431">1431. register struct obj *otmp;</span>
 +
<span id="line1432">1432. {</span>
 +
<span id="line1433">1433. register long tmp = get_cost(otmp);</span>
 +
<span id="line1434">1434. </span>
 +
<span id="line1435">1435. /* The idea is to make the exhaustive use of */</span>
 +
<span id="line1436">1436. /* an unpaid item more expansive than buying */</span>
 +
<span id="line1437">1437. /* outright.     */</span>
 +
<span id="line1438">1438. if(otmp->otyp == MAGIC_LAMP) { /* 1 */</span>
 +
<span id="line1439">1439. tmp += (tmp/3L);</span>
 +
<span id="line1440">1440. } else if(otmp->otyp == MAGIC_MARKER) {  /* 70 - 100 */</span>
 +
<span id="line1441">1441. /* no way to determine in advance  */</span>
 +
<span id="line1442">1442. /* how many charges will be wasted. */</span>
 +
<span id="line1443">1443. /* so, arbitrarily, one half of the */</span>
 +
<span id="line1444">1444. /* price per use.     */</span>
 +
<span id="line1445">1445. tmp = (tmp/2L);</span>
 +
<span id="line1446">1446. } else if(otmp->otyp == BAG_OF_TRICKS) { /* 1 - 20 */</span>
 +
<span id="line1447">1447. tmp = (tmp/5L);</span>
 +
<span id="line1448">1448. } else if(otmp->otyp == CRYSTAL_BALL ||  /* 1 - 5 */</span>
 +
<span id="line1449">1449.   otmp->otyp == LAMP ||                 /* 1-10 */</span>
 +
<span id="line1450">1450. #ifdef MUSIC</span>
 +
<span id="line1451">1451. (otmp->otyp >= MAGIC_FLUTE &&</span>
 +
<span id="line1452">1452.   otmp->otyp <= DRUM_OF_EARTHQUAKE) || /* 5 - 9 */</span>
 +
<span id="line1453">1453. #endif</span>
 +
<span id="line1454">1454.     otmp->olet == WAND_SYM) { /* 3 - 11 */</span>
 +
<span id="line1455">1455. if(otmp->spe == 1) tmp += (tmp/3L);</span>
 +
<span id="line1456">1456. else tmp = (tmp/4L);</span>
 +
<span id="line1457">1457. }</span>
 +
<span id="line1458">1458. else return(0L);</span>
 +
<span id="line1459">1459. return(tmp);</span>
 +
<span id="line1460">1460. }</span>
 +
<span id="line1461">1461. </span>
 +
<span id="line1462">1462. /* for using charges of unpaid objects */</span>
 +
<span id="line1463">1463. void</span>
 +
<span id="line1464">1464. check_unpaid(otmp)</span>
 +
<span id="line1465">1465. register struct obj *otmp;</span>
 +
<span id="line1466">1466. {</span>
 +
<span id="line1467">1467. if(!in_shop(u.ux, u.uy)) return;</span>
 +
<span id="line1468">1468. </span>
 +
<span id="line1469">1469. if(otmp->spe <= 0) return;</span>
 +
<span id="line1470">1470. </span>
 +
<span id="line1471">1471. if(otmp->unpaid) {</span>
 +
<span id="line1472">1472. ESHK(shopkeeper)->debit += cost_per_charge(otmp);</span>
 +
<span id="line1473">1473. }</span>
 +
<span id="line1474">1474. }</span>
 +
[[Category:NetHack 3.0.0 source code|shk.c]]

Latest revision as of 15:29, 31 May 2010

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

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

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

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.

1.    /*	SCCS Id: @(#)shk.c	3.0	89/02/10
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    /* block some unused #defines to avoid overloading some cpp's */
6.    #define MONATTK_H
7.    #include "hack.h"
8.    
9.    #include "eshk.h"
10.   
11.   #ifdef KOPS
12.   static int makekops();
13.   static void kops_gone();
14.   #endif /* KOPS */
15.   
16.   #define	NOTANGRY(mon)	mon->mpeaceful
17.   #define	ANGRY(mon)	!NOTANGRY(mon)
18.   
19.   /* Descriptor of current shopkeeper. Note that the bill need not be
20.      per-shopkeeper, since it is valid only when in a shop. */
21.   static struct monst *shopkeeper = 0;
22.   static struct bill_x *bill;
23.   static int shlevel = 0;	/* level of this shopkeeper */
24.   /* struct obj *billobjs;	/* objects on bill with bp->useup */
25.   				/* only accessed here and by save & restore */
26.   static long int total;		/* filled by addupbill() */
27.   static long int followmsg;	/* last time of follow message */
28.   static void setpaid(), findshk P((int));
29.   static int dopayobj P((struct bill_x *)), getprice P((struct obj *));
30.   static struct obj *bp_to_obj P((struct bill_x *));
31.   
32.   /*
33.   	invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
34.   		obj->quan <= bp->bquan
35.    */
36.   
37.   char *
38.   shkname(mtmp)				/* called in do_name.c */
39.   register struct monst *mtmp;
40.   {
41.   	return(ESHK(mtmp)->shknam);
42.   }
43.   
44.   void
45.   shkdead(mtmp)				/* called in mon.c */
46.   register struct monst *mtmp;
47.   {
48.   	register struct eshk *eshk = ESHK(mtmp);
49.   
50.   	if(eshk->shoplevel == dlevel)
51.   		rooms[eshk->shoproom].rtype = OROOM;
52.   	if(mtmp == shopkeeper) {
53.   		setpaid();
54.   		shopkeeper = 0;
55.   		bill = (struct bill_x *) -1000;	/* dump core when referenced */
56.   	}
57.   }
58.   
59.   void
60.   replshk(mtmp,mtmp2)
61.   register struct monst *mtmp, *mtmp2;
62.   {
63.   	if(mtmp == shopkeeper) {
64.   		shopkeeper = mtmp2;
65.   		bill = &(ESHK(shopkeeper)->bill[0]);
66.   	}
67.   }
68.   
69.   static void
70.   setpaid(){	/* caller has checked that shopkeeper exists */
71.   		/* either we paid or left the shop or he just died */
72.   	register struct obj *obj;
73.   	register struct monst *mtmp;
74.   	for(obj = invent; obj; obj = obj->nobj)
75.   		obj->unpaid = 0;
76.   	for(obj = fobj; obj; obj = obj->nobj)
77.   		obj->unpaid = 0;
78.   	for(obj = fcobj; obj; obj = obj->nobj)
79.   		obj->unpaid = 0;
80.   	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
81.   		for(obj = mtmp->minvent; obj; obj = obj->nobj)
82.   			obj->unpaid = 0;
83.   	for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
84.   		for(obj = mtmp->minvent; obj; obj = obj->nobj)
85.   			obj->unpaid = 0;
86.   	while(obj = billobjs){
87.   		billobjs = obj->nobj;
88.   		free((genericptr_t) obj);
89.   	}
90.   	if(shopkeeper) {
91.   		ESHK(shopkeeper)->billct = 0;
92.   		ESHK(shopkeeper)->credit = 0L;
93.   		ESHK(shopkeeper)->debit = 0L;
94.   	}
95.   }
96.   
97.   static void
98.   addupbill(){	/* delivers result in total */
99.   		/* caller has checked that shopkeeper exists */
100.  	register int ct = ESHK(shopkeeper)->billct;
101.  	register struct bill_x *bp = bill;
102.  	total = 0;
103.  	while(ct--){
104.  		total += bp->price * bp->bquan;
105.  		bp++;
106.  	}
107.  }
108.  
109.  int
110.  inshop() {
111.  	register int roomno = inroom(u.ux,u.uy);
112.  
113.  	/* Did we just leave a shop? */
114.  	if(u.uinshop &&
115.  	    (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {
116.  
117.  	/* This is part of the bugfix for shopkeepers not having their
118.  	 * bill paid.  As reported by ab@unido -dgk
119.  	 * I made this standard due to the KOPS code below. -mrs
120.  	 */
121.  		if(shopkeeper) {
122.  		    if(ESHK(shopkeeper)->billct || ESHK(shopkeeper)->debit) {
123.  			if(inroom(shopkeeper->mx, shopkeeper->my)
124.  			    == u.uinshop - 1)	/* ab@unido */
125.  			    You("escaped the shop without paying!");
126.  			addupbill();
127.  			total += ESHK(shopkeeper)->debit;
128.  			You("stole %ld zorkmids worth of merchandise.",
129.  				total);
130.  			ESHK(shopkeeper)->robbed += total;
131.  			ESHK(shopkeeper)->credit = 0L;
132.  			ESHK(shopkeeper)->debit = 0L;
133.  			if (pl_character[0] != 'R') /* stealing is unlawful */
134.  				adjalign(-sgn(u.ualigntyp));
135.  			setpaid();
136.  			if((rooms[ESHK(shopkeeper)->shoproom].rtype == SHOPBASE)
137.  			    == (rn2(3) == 0))
138.  			    ESHK(shopkeeper)->following = 1;
139.  #ifdef KOPS
140.  		    {   /* Keystone Kops srt@ucla */
141.  			coord mm;
142.  
143.  			if (flags.soundok)
144.  			    pline("An alarm sounds throughout the dungeon!");
145.  			if(flags.verbose) {
146.  			    if((mons[PM_KEYSTONE_KOP].geno & G_GENOD) &&
147.   			       (mons[PM_KOP_SERGEANT].geno & G_GENOD) &&
148.   			       (mons[PM_KOP_LIEUTENANT].geno & G_GENOD) &&
149.  			       (mons[PM_KOP_KAPTAIN].geno & G_GENOD)) {
150.  				if (flags.soundok)
151.  				    pline("But no one seems to respond to it.");
152.  			    } else
153.  				pline("The Keystone Kops are after you!");
154.  			}
155.  			/* Create a swarm near the staircase */
156.  			mm.x = xdnstair;
157.  			mm.y = ydnstair;
158.  			(void) makekops(&mm);
159.  			/* Create a swarm near the shopkeeper */
160.  			mm.x = shopkeeper->mx;
161.  			mm.y = shopkeeper->my;
162.  			(void) makekops(&mm);
163.  		    }
164.  #endif
165.  		    }
166.  		    shopkeeper = 0;
167.  		    shlevel = 0;
168.  		}
169.  		u.uinshop = 0;
170.  	}
171.  
172.  	/* Did we just enter a zoo of some kind? */
173.  	/* This counts everything except shops and vaults
174.  	   -- vault.c insists that a vault remain a VAULT */
175.  	if(roomno >= 0) {
176.  		register int rt = rooms[roomno].rtype;
177.  		register struct monst *mtmp;
178.  
179.  		switch (rt) {
180.  		case ZOO:
181.  		    pline("Welcome to David's treasure zoo!");
182.  		    break;
183.  		case SWAMP:
184.  		    pline("It looks rather muddy down here.");
185.  		    break;
186.  #ifdef THRONES
187.  		case COURT:
188.  		    You("enter an opulent throne room!");
189.  		    break;
190.  #endif
191.  		case MORGUE:
192.  		    if(midnight())
193.  			pline("Run away!  Run away!");
194.  		    else
195.  			You("have an uncanny feeling...");
196.  		    break;
197.  		case BEEHIVE:
198.  		    You("enter a giant beehive!");
199.  		    break;
200.  #ifdef ARMY
201.  		case BARRACKS:
202.  		    if(!((mons[PM_SOLDIER].geno & G_GENOD) &&
203.  		         (mons[PM_SERGEANT].geno & G_GENOD) &&
204.  		         (mons[PM_LIEUTENANT].geno & G_GENOD) &&
205.  		         (mons[PM_CAPTAIN].geno & G_GENOD)))
206.  		    	You("enter a military barracks!");
207.  		    else You("enter an abandoned barracks.");
208.  		    break;
209.  #endif
210.  #ifdef ORACLE
211.  		case DELPHI:
212.  		    if(!(mons[PM_ORACLE].geno & G_GENOD))
213.  		        pline("\"Hello, %s, welcome to Delphi!\"", plname);
214.  		    break;
215.  #endif
216.  		default:
217.  		    rt = 0;
218.  		}
219.  
220.  		if(rt != 0) {
221.  		    rooms[roomno].rtype = OROOM;
222.  		    if(rt==COURT || rt==SWAMP || rt==MORGUE || rt==ZOO)
223.  			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
224.  			    /* was if(rt != ZOO || !rn2(3)) -- why should ZOO
225.  			       be different from COURT or MORGUE? */
226.  			    if(!Stealth && !rn2(3))
227.  				mtmp->msleep = 0;
228.  		}
229.  	}
230.  #if defined(ALTARS) && defined(THEOLOGY)
231.  	if(roomno >= 0 && rooms[roomno].rtype == TEMPLE) {
232.  	    intemple();
233.  	}
234.  #endif
235.  	/* Did we just enter a shop? */
236.  	if(roomno >= 0 && rooms[roomno].rtype >= SHOPBASE) {
237.  	    register int rt = rooms[roomno].rtype;
238.  
239.  	    if(shlevel != dlevel || !shopkeeper
240.  				 || ESHK(shopkeeper)->shoproom != roomno)
241.  		findshk(roomno);
242.  	    if(!shopkeeper) {
243.  		rooms[roomno].rtype = OROOM;
244.  		u.uinshop = 0;
245.  	    } else if(!u.uinshop){
246.  		if(!ESHK(shopkeeper)->visitct ||
247.  		   strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)) {
248.  		    /* He seems to be new here */
249.  		    ESHK(shopkeeper)->visitct = 0;
250.  		    ESHK(shopkeeper)->following = 0;
251.  		    (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
252.  		    NOTANGRY(shopkeeper) = 1;
253.  		}
254.  		if(!ESHK(shopkeeper)->following && inhishop(shopkeeper)) {
255.  		    if(ANGRY(shopkeeper))
256.  			pline("\"So, %s, you dare return to %s's %s?!\"",
257.  			    plname,
258.  			    shkname(shopkeeper),
259.  			    shtypes[rt - SHOPBASE].name);
260.  		    else
261.  		    if(ESHK(shopkeeper)->robbed)
262.  			pline("\"Beware, %s!  I am upset about missing stock!\"",
263.  			    plname);
264.  		    else
265.  			pline("\"Hello, %s!  Welcome%s to %s's %s!\"",
266.  			    plname,
267.  			    ESHK(shopkeeper)->visitct++ ? " again" : "",
268.  			    shkname(shopkeeper),
269.  			    shtypes[rt - SHOPBASE].name);
270.  		    if(carrying(PICK_AXE) != (struct obj *)0) {
271.  			pline(NOTANGRY(shopkeeper) ?
272.  			   "\"Will you please leave your pick-axe outside?\"" :
273.  			   "\"Leave the pick-axe outside.\"");
274.  			if(dochug(shopkeeper)) {
275.  			    u.uinshop = 0;	/* he died moving */
276.  			    return(0);
277.  			}
278.  		    }
279.  		}
280.  		u.uinshop = (unsigned int)(roomno + 1);
281.  	    }
282.  	}
283.  	return (int)u.uinshop;
284.  }
285.  
286.  int
287.  inhishop(mtmp)
288.  register struct monst *mtmp;
289.  {
290.  	return((ESHK(mtmp)->shoproom == inroom(mtmp->mx, mtmp->my) &&
291.  		ESHK(mtmp)->shoplevel == dlevel));
292.  }
293.  
294.  static void
295.  findshk(roomno)
296.  register int roomno;
297.  {
298.  	register struct monst *mtmp;
299.  
300.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
301.  	    if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
302.  			   && ESHK(mtmp)->shoplevel == dlevel) {
303.  		shopkeeper = mtmp;
304.  		bill = &(ESHK(shopkeeper)->bill[0]);
305.  		shlevel = dlevel;
306.  		if(ANGRY(shopkeeper) &&
307.  		   strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ))
308.  			NOTANGRY(shopkeeper) = 1;
309.  		/* billobjs = 0; -- this is wrong if we save in a shop */
310.  		/* (and it is harmless to have too many things in billobjs) */
311.  		return;
312.  	}
313.  	shopkeeper = 0;
314.  	shlevel = 0;
315.  	bill = (struct bill_x *) -1000;	/* dump core when referenced */
316.  }
317.  
318.  static struct bill_x *
319.  onbill(obj)
320.  register struct obj *obj;
321.  {
322.  	register struct bill_x *bp;
323.  	if(!shopkeeper) return (struct bill_x *)0;
324.  	for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)
325.  		if(bp->bo_id == obj->o_id) {
326.  			if(!obj->unpaid) pline("onbill: paid obj on bill?");
327.  			return(bp);
328.  		}
329.  	if(obj->unpaid) pline("onbill: unpaid obj not on bill?");
330.  	return (struct bill_x *)0;
331.  }
332.  
333.  /* called with two args on merge */
334.  void
335.  obfree(obj, merge)
336.  register struct obj *obj, *merge;
337.  {
338.  	register struct bill_x *bp = onbill(obj);
339.  	register struct bill_x *bpm;
340.  	if(bp) {
341.  		if(!merge){
342.  			bp->useup = 1;
343.  			obj->unpaid = 0;	/* only for doinvbill */
344.  			obj->nobj = billobjs;
345.  			billobjs = obj;
346.  			return;
347.  		}
348.  		bpm = onbill(merge);
349.  		if(!bpm){
350.  			/* this used to be a rename */
351.  			impossible("obfree: not on bill??");
352.  			return;
353.  		} else {
354.  			/* this was a merger */
355.  			bpm->bquan += bp->bquan;
356.  			ESHK(shopkeeper)->billct--;
357.  			*bp = bill[ESHK(shopkeeper)->billct];
358.  		}
359.  	}
360.  	free((genericptr_t) obj);
361.  }
362.  
363.  static long
364.  check_credit(tmp, shkp)
365.  long tmp;
366.  register struct monst *shkp;
367.  {
368.  	long credit = ESHK(shkp)->credit;
369.  
370.  	if(credit == 0L) return(tmp);
371.  	if(credit >= tmp) {
372.  		pline("The price is deducted from your credit.");
373.  		ESHK(shkp)->credit -=tmp;
374.  		tmp = 0L;
375.  	} else {
376.  		pline("The price is partially covered by your credit.");
377.  		ESHK(shkp)->credit = 0L;
378.  		tmp -= credit;
379.  	}
380.  	return(tmp);
381.  }
382.  
383.  static void
384.  pay(tmp,shkp)
385.  long tmp;
386.  register struct monst *shkp;
387.  {
388.  	long robbed = ESHK(shkp)->robbed;
389.  	long balance = ((tmp <= 0) ? tmp : check_credit(tmp, shkp));
390.  
391.  	u.ugold -= balance;
392.  	shkp->mgold += balance;
393.  	flags.botl = 1;
394.  	if(robbed) {
395.  		robbed -= tmp;
396.  		if(robbed < 0) robbed = 0;
397.  		ESHK(shkp)->robbed = robbed;
398.  	}
399.  }
400.  
401.  /* return shkp to home position */
402.  void
403.  home_shk(shkp)
404.  register struct monst *shkp;
405.  {
406.  	register xchar x = ESHK(shkp)->shk.x, y = ESHK(shkp)->shk.y;
407.  	if(levl[x][y].mmask)
408.  		mnearto(m_at(x,y), x, y, FALSE);
409.  	levl[shkp->mx][shkp->my].mmask = 0;
410.  	shkp->mx = x;
411.  	shkp->my = y;
412.  	levl[shkp->mx][shkp->my].mmask = 1;
413.  	unpmon(shkp);
414.  }
415.  
416.  void
417.  make_happy_shk(shkp)
418.  struct monst *shkp;
419.  {
420.  	register boolean wasmad = ANGRY(shkp);
421.  
422.  	NOTANGRY(shkp) = 1;
423.  	ESHK(shkp)->following = 0;
424.  	ESHK(shkp)->robbed = 0;
425.  	if (pl_character[0] != 'R')
426.  		adjalign(sgn(u.ualigntyp));
427.  	if(!inhishop(shkp)) {
428.  		pline("Satisfied, %s suddenly disappears!", mon_nam(shkp));
429.  		if(ESHK(shkp)->shoplevel == dlevel)
430.  			home_shk(shkp);
431.  		else
432.  			fall_down(shkp, ESHK(shkp)->shoplevel);
433.  	} else if(wasmad)
434.  		pline("%s calms down.", Monnam(shkp));
435.  #ifdef KOPS
436.  	kops_gone();
437.  #endif
438.  }
439.  
440.  static const char no_money[] = "Moreover, you have no money.";
441.  
442.  int
443.  dopay()
444.  {
445.  	long ltmp;
446.  	register struct bill_x *bp;
447.  	register struct monst *shkp;
448.  	int pass, tmp;
449.  
450.  	multi = 0;
451.  	(void) inshop();
452.  	for(shkp = fmon; shkp; shkp = shkp->nmon)
453.  		if(shkp->isshk && dist(shkp->mx,shkp->my) < 3)
454.  			break;
455.  	if(!shkp && u.uinshop && inhishop(shopkeeper))
456.  		shkp = shopkeeper;
457.  
458.  	if(!shkp) {
459.  		pline("There is nobody here to receive your payment.");
460.  		return(0);
461.  	}
462.  	ltmp = ESHK(shkp)->robbed;
463.  	if(shkp != shopkeeper && NOTANGRY(shkp)) {
464.  		if(!ltmp)
465.  		    You("do not owe %s anything.", mon_nam(shkp));
466.  		else if(!u.ugold)
467.  		    You("have no money.");
468.  		else {
469.  		    long ugold = u.ugold;
470.  
471.  		    if(ugold  > ltmp) {
472.  			You("give %s the %ld gold pieces %s asked for.",
473.  			    mon_nam(shkp), ltmp,
474.  			    ESHK(shkp)->ismale ? "he" : "she");
475.  			pay(ltmp, shkp);
476.  		    } else {
477.  			You("give %s all your gold.", mon_nam(shkp));
478.  			pay(u.ugold, shkp);
479.  		    }
480.  		    if(ugold < ltmp/2)
481.  			pline("Unfortunately, %s doesn't look satisfied.",
482.  			    ESHK(shkp)->ismale ? "he" : "she");
483.  		    else
484.  			make_happy_shk(shkp);
485.  		}
486.  		return(1);
487.  	}
488.  
489.  	/* ltmp is still ESHK(shkp)->robbed here */
490.  	if(!ESHK(shkp)->billct) {
491.  		if(!ltmp && NOTANGRY(shkp)) {
492.  		    You("do not owe %s anything.", mon_nam(shkp));
493.  		    if(!u.ugold) pline(no_money);
494.  		} else if(ltmp) {
495.  		    pline("%s is after blood, not money!", mon_nam(shkp));
496.  		    if(u.ugold < ltmp/2) {
497.  			if(!u.ugold) pline(no_money);
498.  			else pline("Besides, you don't have enough to interest %s.",
499.  				ESHK(shkp)->ismale ? "him" : "her");
500.  			return(1);
501.  		    }
502.  		    pline("But since %s shop has been robbed recently,",
503.  			ESHK(shkp)->ismale ? "his" : "her");
504.  		    pline("you %scompensate %s for %s losses.",
505.  			(u.ugold < ltmp) ? "partially " : "",
506.  			mon_nam(shkp),
507.  			ESHK(shkp)->ismale ? "his" : "her");
508.  		    pay(u.ugold < ltmp ? u.ugold : ltmp, shkp);
509.  		    make_happy_shk(shkp);
510.  		} else {
511.  		    /* shopkeeper is angry, but has not been robbed --
512.  		     * door broken, attacked, etc. */
513.  		    pline("%s is after your hide, not your money!",
514.  					mon_nam(shkp));
515.  		    if(u.ugold < 1000) {
516.  			if(!u.ugold) pline(no_money);
517.  			else
518.  		pline("Besides, you don't have enough to interest %s.",
519.  				ESHK(shkp)->ismale ? "him" : "her");
520.  			return(1);
521.  		    }
522.  		    You("try to appease %s by giving %s 1000 gold pieces.",
523.  				a_monnam(shkp, "angry"),
524.  				ESHK(shkp)->ismale ? "him" : "her");
525.  		    pay(1000L,shkp);
526.  		    if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)
527.  		    		|| rn2(3))
528.  			make_happy_shk(shkp);
529.  		    else
530.  			pline("But %s is as angry as ever.", Monnam(shkp));
531.  		}
532.  		return(1);
533.  	}
534.  	if(shkp != shopkeeper) {
535.  		impossible("dopay: not to shopkeeper?");
536.  		if(shopkeeper) setpaid();
537.  		return(0);
538.  	}
539.  	/* pay debt, if any, first */
540.  	if(ESHK(shopkeeper)->debit) {
541.  	        You("owe %s %ld zorkmids for the use of merchandise.",
542.  			shkname(shopkeeper), ESHK(shopkeeper)->debit);
543.  	        if(u.ugold + ESHK(shopkeeper)->credit < 
544.  					ESHK(shopkeeper)->debit) {
545.  		    pline("But you don't have enough gold%s.",
546.  			ESHK(shopkeeper)->credit ? " or credit" : "");
547.  		    return(1);
548.  	        } else {
549.  		    long dtmp = ESHK(shopkeeper)->debit;
550.  
551.  		    if(ESHK(shopkeeper)->credit >= dtmp) {
552.  			ESHK(shopkeeper)->credit -= dtmp;
553.  			ESHK(shopkeeper)->debit = 0L;
554.  	                Your("debt is covered by your credit.");
555.  		    } else if(!ESHK(shopkeeper)->credit) {
556.  			u.ugold -= dtmp;
557.  			shopkeeper->mgold += dtmp;
558.  			ESHK(shopkeeper)->debit = 0L;
559.  			You("pay that debt.");
560.  			flags.botl = 1;
561.  		    } else {
562.  			dtmp -= ESHK(shopkeeper)->credit;
563.  			ESHK(shopkeeper)->credit = 0L;
564.  			u.ugold -= dtmp;
565.  			shopkeeper->mgold += dtmp;
566.  			ESHK(shopkeeper)->debit = 0L;
567.  			pline("That debt is partially offset by your credit.");
568.  			You("pay the remainder.");
569.  			flags.botl = 1;
570.  		    }
571.  		}
572.  	}
573.  	for(pass = 0; pass <= 1; pass++) {
574.  		tmp = 0;
575.  		while(tmp < ESHK(shopkeeper)->billct) {
576.  		    bp = &bill[tmp];
577.  		    if(!pass && !bp->useup) {
578.  			tmp++;
579.  			continue;
580.  		    }
581.  		    if(!dopayobj(bp)) return(1);
582.  #ifdef MSDOS
583.  		    *bp = bill[--ESHK(shopkeeper)->billct];
584.  #else
585.  		    bill[tmp] = bill[--ESHK(shopkeeper)->billct];
586.  #endif /* MSDOS /**/
587.  		}
588.  	}
589.  	pline("\"Thank you for shopping in %s's %s!\"",
590.  		shkname(shopkeeper),
591.  		shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype - SHOPBASE].name);
592.  	NOTANGRY(shopkeeper) = 1;
593.  	return(1);
594.  }
595.  
596.  /* return 1 if paid successfully */
597.  /*        0 if not enough money */
598.  /*       -1 if object could not be found (but was paid) */
599.  static int
600.  dopayobj(bp)
601.  register struct bill_x *bp;
602.  {
603.  	register struct obj *obj;
604.  	long ltmp;
605.  
606.  	/* find the object on one of the lists */
607.  	obj = bp_to_obj(bp);
608.  
609.  	if(!obj) {
610.  		impossible("Shopkeeper administration out of order.");
611.  		setpaid();	/* be nice to the player */
612.  		return(0);
613.  	}
614.  
615.  	if(!obj->unpaid && !bp->useup){
616.  		impossible("Paid object on bill??");
617.  		return(1);
618.  	}
619.  	obj->unpaid = 0;
620.  	ltmp = bp->price * bp->bquan;
621.  	if(ANGRY(shopkeeper)) ltmp += ltmp/3;
622.  	if(u.ugold + ESHK(shopkeeper)->credit < ltmp){
623.  		You("don't have gold%s enough to pay for %s.",
624.  			(ESHK(shopkeeper)->credit > 0L) ? " or credit" : "",
625.  			doname(obj));
626.  		obj->unpaid = 1;
627.  		return(0);
628.  	}
629.  	pay(ltmp, shopkeeper);
630.  	You("bought %s for %ld gold piece%s.",
631.  		doname(obj), ltmp, plur(ltmp));
632.  	if(bp->useup) {
633.  		register struct obj *otmp = billobjs;
634.  		if(obj == billobjs)
635.  			billobjs = obj->nobj;
636.  		else {
637.  			while(otmp && otmp->nobj != obj) otmp = otmp->nobj;
638.  			if(otmp) otmp->nobj = obj->nobj;
639.  			else pline("Error in shopkeeper administration.");
640.  		}
641.  		free((genericptr_t) obj);
642.  	}
643.  	return(1);
644.  }
645.  
646.  /* routine called after dying (or quitting) with nonempty bill or upset shk */
647.  boolean
648.  paybill(){
649.  	register struct monst *mtmp;
650.  	register int loss = 0;
651.  	register struct obj *otmp;
652.  	register xchar ox, oy;
653.  	register boolean take = FALSE;
654.  	register boolean taken = FALSE;
655.  
656.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
657.  	    if(mtmp->isshk) {
658.  		/* for bones: we don't want a shopless shk around */
659.  		if(ESHK(mtmp)->shoplevel != dlevel) mongone(mtmp);
660.  		else shopkeeper = mtmp;
661.  	    }
662.  
663.  	if(!shopkeeper) return(FALSE);
664.  
665.  	/* get one case out of the way: you die in the shop, the */
666.  	/* shopkeeper is peaceful, nothing stolen, nothing owed. */
667.  	if(in_shop(u.ux,u.uy) && !IS_DOOR(levl[u.ux][u.uy].typ) &&
668.  	    !ESHK(shopkeeper)->billct && !ESHK(shopkeeper)->robbed &&
669.  	    inhishop(shopkeeper) && NOTANGRY(shopkeeper) &&
670.  	    !ESHK(shopkeeper)->following) {
671.  		pline("%s gratefully inherits all your possessions.",
672.  				Monnam(shopkeeper));
673.  		goto clear;
674.  	}
675.  
676.  	if(ESHK(shopkeeper)->billct || ESHK(shopkeeper)->robbed) {
677.  		addupbill();
678.  		loss = ((total >= ESHK(shopkeeper)->robbed) ? total :
679.  				ESHK(shopkeeper)->robbed);
680.  		take = TRUE;
681.  	}
682.  
683.  	if(ESHK(shopkeeper)->following || ANGRY(shopkeeper) || take) {
684.  		if((loss > u.ugold) || !loss) {
685.  			pline("%s comes and takes all your possessions.",
686.  					Monnam(shopkeeper));
687.  			taken = TRUE;
688.  			shopkeeper->mgold += u.ugold;
689.  			u.ugold = 0;
690.  			/* in case bones: make it be for real... */
691.  			if(!in_shop(u.ux, u.uy) || IS_DOOR(levl[u.ux][u.uy].typ)) {
692.  			    /* shk.x,shk.y is the position immediately in
693.  			     * front of the door -- move in one more space
694.  			     */
695.  			    ox = ESHK(shopkeeper)->shk.x;
696.  			    oy = ESHK(shopkeeper)->shk.y;
697.  			    ox += sgn(ox - ESHK(shopkeeper)->shd.x);
698.  			    oy += sgn(oy - ESHK(shopkeeper)->shd.y);
699.  			} else {
700.  			    ox = u.ux;
701.  			    oy = u.uy;
702.  			}
703.  
704.  			if (invent) {
705.  			    levl[ox][oy].omask = 1;
706.  			    for(otmp = invent; otmp; otmp = otmp->nobj) {
707.  				otmp->ox = ox;
708.  				otmp->oy = oy;
709.  				otmp->age = 0;
710.  			    }
711.  
712.  			    /* add to main object list at end so invent is
713.  			       still good */
714.  			    if (fobj) {
715.  				otmp = fobj;
716.  				while(otmp->nobj)
717.  				    otmp = otmp->nobj;
718.  				otmp->nobj = invent;
719.  			    } else
720.  				fobj = invent;
721.  			}
722.  		} else {
723.  			u.ugold -= loss;
724.  			shopkeeper->mgold += loss;
725.  			pline("%s comes and takes %ld zorkmids %sowed %s.",
726.  			       Monnam(shopkeeper),
727.  			       loss,
728.  			       strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ) ? "" : "you ",
729.  			       ESHK(shopkeeper)->ismale ? "him" : "her");
730.  		}
731.  
732.  		/* in case we create bones */
733.  		if(!inhishop(shopkeeper))
734.  			home_shk(shopkeeper);
735.  	}
736.  clear:
737.  	setpaid();
738.  	return(taken);
739.  }
740.  
741.  /* find obj on one of the lists */
742.  static struct obj *
743.  bp_to_obj(bp)
744.  register struct bill_x *bp;
745.  {
746.  	register struct obj *obj;
747.  	register struct monst *mtmp;
748.  	register unsigned int id = bp->bo_id;
749.  
750.  	if(bp->useup)
751.  		obj = o_on(id, billobjs);
752.  	else if(!(obj = o_on(id, invent)) &&
753.  		!(obj = o_on(id, fobj)) &&
754.  		!(obj = o_on(id, fcobj))) {
755.  		    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
756.  			if(obj = o_on(id, mtmp->minvent))
757.  			    break;
758.  		    for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
759.  			if(obj = o_on(id, mtmp->minvent))
760.  			    break;
761.  		}
762.  	return(obj);
763.  }
764.  
765.  static long
766.  get_cost(obj)
767.  register struct obj *obj;
768.  {
769.  	register long tmp;
770.  
771.  	tmp = getprice(obj);
772.  	if (!tmp) tmp = 5;
773.  	if (ANGRY(shopkeeper) || 
774.  		(pl_character[0] == 'T' && u.ulevel < (MAXULEV/2))
775.  #ifdef SHIRT
776.  	    || (uarmu && !uarm) /* wearing just a Hawaiian shirt */
777.  #endif
778.  	   )
779.  		tmp += tmp/3;
780.  	if (ACURR(A_CHA) > 18)		tmp /= 2;
781.  	else if (ACURR(A_CHA) > 17)	tmp = (tmp * 2)/3;
782.  	else if (ACURR(A_CHA) > 15)	tmp = (tmp * 3)/4;
783.  	else if (ACURR(A_CHA) < 11)	tmp = (tmp * 4)/3;
784.  	else if (ACURR(A_CHA) < 8)	tmp = (tmp * 3)/2;
785.  	else if (ACURR(A_CHA) < 6)	tmp *= 2;
786.  	return(tmp);
787.  }
788.  
789.  
790.  /* called in hack.c when we pickup an object */
791.  void
792.  addtobill(obj, ininv)
793.  register struct obj *obj;
794.  register boolean ininv;
795.  {
796.  	register struct bill_x *bp;
797.  	char	buf[40];
798.  	if(!shopkeeper || !inhishop(shopkeeper)) return;
799.  
800.  	if(!costly_spot(obj->ox,obj->oy) ||	/* either pickup or kick */
801.  		onbill(obj) /* perhaps we threw it away earlier */
802.  	      ) return;
803.  	if(ESHK(shopkeeper)->billct == BILLSZ) {
804.  		You("got that for free!");
805.  		return;
806.  	}
807.  	/* To recognize objects the shopkeeper is not interested in. -dgk
808.  	 */
809.  	if (obj->no_charge) {
810.  		obj->no_charge = 0;
811.  		return;
812.  	}
813.  	bp = &bill[ESHK(shopkeeper)->billct];
814.  	bp->bo_id = obj->o_id;
815.  	bp->bquan = obj->quan;
816.  	bp->useup = 0;
817.  	bp->price = get_cost(obj);
818.  	Strcpy(buf, "\"For you, ");
819.  	if (ANGRY(shopkeeper)) Strcat(buf, "scum ");
820.  	else {
821.  	    switch(rnd(4)
822.  #ifdef HARD
823.  		   + u.udemigod
824.  #endif
825.  				) {
826.  		case 1:	Strcat(buf, "good");
827.  			break;
828.  		case 2:	Strcat(buf, "honored");
829.  			break;
830.  		case 3:	Strcat(buf, "most gracious");
831.  			break;
832.  		case 4:	Strcat(buf, "esteemed");
833.  			break;
834.  		case 5: if (u.ualigntyp == U_CHAOTIC) Strcat(buf, "un");
835.  			Strcat(buf, "holy");
836.  			break;
837.  	    }
838.  #ifdef POLYSELF
839.  	    if(!is_human(uasmon)) Strcat(buf, " creature");
840.  	    else
841.  #endif
842.  		Strcat(buf, (flags.female) ? " lady" : " sir");
843.  	}
844.  	obj->dknown = 1; /* after all, the shk is telling you what it is */
845.  	if(ininv) {
846.  		obj->quan = 1; /* fool xname() into giving singular */
847.  		pline("%s; only %d %s %s.\"", buf, bp->price,
848.  			(bp->bquan > 1) ? "per" : "for this", xname(obj));
849.  		obj->quan = bp->bquan;
850.  	} else pline("The %s will cost you %d zorkmids%s.",
851.  			xname(obj), bp->price,
852.  			(bp->bquan > 1) ? " each" : "");
853.  	ESHK(shopkeeper)->billct++;
854.  	obj->unpaid = 1;
855.  }
856.  
857.  void
858.  splitbill(obj, otmp)
859.  register struct obj *obj, *otmp;
860.  {
861.  	/* otmp has been split off from obj */
862.  	register struct bill_x *bp;
863.  	register int tmp;
864.  	bp = onbill(obj);
865.  	if(!bp) {
866.  		impossible("splitbill: not on bill?");
867.  		return;
868.  	}
869.  	if(bp->bquan < otmp->quan) {
870.  		impossible("Negative quantity on bill??");
871.  	}
872.  	if(bp->bquan == otmp->quan) {
873.  		impossible("Zero quantity on bill??");
874.  	}
875.  	bp->bquan -= otmp->quan;
876.  
877.  	if(ESHK(shopkeeper)->billct == BILLSZ) otmp->unpaid = 0;
878.  	else {
879.  		tmp = bp->price;
880.  		bp = &bill[ESHK(shopkeeper)->billct];
881.  		bp->bo_id = otmp->o_id;
882.  		bp->bquan = otmp->quan;
883.  		bp->useup = 0;
884.  		bp->price = tmp;
885.  		ESHK(shopkeeper)->billct++;
886.  	}
887.  }
888.  
889.  void
890.  subfrombill(obj)
891.  register struct obj *obj;
892.  {
893.  	long ltmp;
894.  	/* register int tmp;	/* use of tmp commented out below */
895.  	register struct obj *otmp;
896.  	register struct bill_x *bp;
897.  	if(!costly_spot(u.ux,u.uy))
898.  		return;
899.  	if((bp = onbill(obj)) != 0) {
900.  		obj->unpaid = 0;
901.  		if(bp->bquan > obj->quan){
902.  			otmp = newobj(0);
903.  			*otmp = *obj;
904.  			bp->bo_id = otmp->o_id = flags.ident++;
905.  			otmp->quan = (bp->bquan -= obj->quan);
906.  			otmp->owt = 0;	/* superfluous */
907.  			otmp->onamelth = 0;
908.  			bp->useup = 1;
909.  			otmp->nobj = billobjs;
910.  			billobjs = otmp;
911.  			return;
912.  		}
913.  		ESHK(shopkeeper)->billct--;
914.  		*bp = bill[ESHK(shopkeeper)->billct];
915.  		return;
916.  	}
917.  	if(obj->unpaid) {
918.  		if(inhishop(shopkeeper))
919.  		    pline("%s didn't notice.", Monnam(shopkeeper));
920.  		obj->unpaid = 0;
921.  		return;		/* %% */
922.  	}
923.  	/* he dropped something of his own - probably wants to sell it */
924.  	if(shopkeeper->msleep || shopkeeper->mfroz || !inhishop(shopkeeper))
925.  		return;
926.  	ltmp = getprice(obj) * obj->quan;
927.  	if(ESHK(shopkeeper)->billct == BILLSZ
928.  	   || !saleable(rooms[ESHK(shopkeeper)->shoproom].rtype-SHOPBASE, obj)
929.  	   || otmp->olet == BALL_SYM || ltmp == 0L) {
930.  		pline("%s seems not interested.", Monnam(shopkeeper));
931.  		obj->no_charge = 1;
932.  		return;
933.  	}
934.  	if (ANGRY(shopkeeper) || (pl_character[0] == 'T' && u.ulevel < (MAXULEV/2))
935.  #ifdef SHIRT
936.  	    || (uarmu && !uarm) /* wearing just a Hawaiian shirt */
937.  #endif
938.  	   ) {
939.  		ltmp /= 3;
940.  		NOTANGRY(shopkeeper) = 1;
941.  	} else	ltmp /= 2;
942.  	if(ESHK(shopkeeper)->robbed) {
943.  		if((ESHK(shopkeeper)->robbed -= ltmp) < 0)
944.  			ESHK(shopkeeper)->robbed = 0;
945.  pline("\"Thank you for your contribution to restock this recently plundered shop.\"");
946.  		return;
947.  	}
948.  	if(ltmp > shopkeeper->mgold)
949.  		ltmp = shopkeeper->mgold;
950.  	pay(-ltmp, shopkeeper);
951.  	if(!ltmp) {
952.  		pline("%s gladly accepts %s but cannot pay you at present.",
953.  			Monnam(shopkeeper), doname(obj));
954.  			obj->no_charge = 1;
955.  	} else
956.  	You("sold %s for %ld gold piece%s.", doname(obj), ltmp,
957.  		plur(ltmp));
958.  }
959.  
960.  int
961.  doinvbill(mode)
962.  int mode;		/* 0: deliver count 1: paged */
963.  {
964.  	register struct bill_x *bp;
965.  	register struct obj *obj;
966.  	long totused, thisused;
967.  	char buf[BUFSZ];
968.  
969.  	if(mode == 0) {
970.  	    register int cnt = 0;
971.  
972.  	    if(shopkeeper)
973.  		for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++)
974.  		    if(bp->useup ||
975.  		      ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan))
976.  			cnt++;
977.  	    return(cnt);
978.  	}
979.  
980.  	if(!shopkeeper) {
981.  		impossible("doinvbill: no shopkeeper?");
982.  		return(0);
983.  	}
984.  
985.  	set_pager(0);
986.  	if(page_line("Unpaid articles already used up:") || page_line(""))
987.  	    goto quit;
988.  
989.  	totused = 0;
990.  	for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) {
991.  	    obj = bp_to_obj(bp);
992.  	    if(!obj) {
993.  		impossible("Bad shopkeeper administration.");
994.  		goto quit;
995.  	    }
996.  	    if(bp->useup || bp->bquan > obj->quan) {
997.  		register int cnt, oquan, uquan;
998.  
999.  		oquan = obj->quan;
1000. 		uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
1001. 		thisused = bp->price * uquan;
1002. 		totused += thisused;
1003. 		obj->quan = uquan;		/* cheat doname */
1004. 		Sprintf(buf, "x -  %s", doname(obj));
1005. 		obj->quan = oquan;		/* restore value */
1006. 		for(cnt = 0; buf[cnt]; cnt++);
1007. 		while(cnt < 50)
1008. 			buf[cnt++] = ' ';
1009. 		Sprintf(&buf[cnt], " %5ld zorkmids", thisused);
1010. 		if(page_line(buf))
1011. 			goto quit;
1012. 	    }
1013. 	}
1014. 	Sprintf(buf, "Total:%50ld zorkmids", totused);
1015. 	if(page_line("") || page_line(buf))
1016. 		goto quit;
1017. 	set_pager(1);
1018. 	return(0);
1019. quit:
1020. 	set_pager(2);
1021. 	return(0);
1022. }
1023. 
1024. #define HUNGRY	2
1025. static int
1026. getprice(obj)
1027. register struct obj *obj;
1028. {
1029. 	register int tmp = objects[obj->otyp].oc_cost;
1030. 
1031. 	switch(obj->olet) {
1032. 	case AMULET_SYM:
1033. 		if(obj->otyp == AMULET_OF_YENDOR) {
1034. 			/* don't let the player get rich selling fakes */
1035. 			tmp = (obj->spe < 0 ? 0 : 3500);
1036. 		}
1037. 		break;
1038. 	case FOOD_SYM:
1039. 		/* simpler hunger check, (2-4)*cost */
1040. 		if (u.uhs >= HUNGRY) tmp *= u.uhs;
1041. 		break;
1042. 	case WAND_SYM:
1043. 		if (obj->spe == -1) tmp = 0;
1044. 		break;
1045. 	case POTION_SYM:
1046. 		if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed)
1047. 			tmp = 0;
1048. 		break;
1049. 	case ARMOR_SYM:
1050. 		if (u.uac > 0) tmp += u.uac * 2;
1051. 	case WEAPON_SYM:
1052. 		if (obj->spe > 0) tmp += 10 * obj->spe;
1053. 		break;
1054. 	case CHAIN_SYM:
1055. 		pline("Strange... carrying a chain?");
1056. 		break;
1057. 	}
1058. 	return(tmp);
1059. }
1060. 
1061. int
1062. shkcatch(obj)
1063. register struct obj *obj;
1064. {
1065. 	register struct monst *shkp = shopkeeper;
1066. 
1067. 	if(u.uinshop && shkp && !shkp->mfroz && !shkp->msleep &&
1068. 	    u.dx && u.dy &&
1069. 	    inroom(u.ux+u.dx, u.uy+u.dy) + 1 == u.uinshop &&
1070. 	    shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y &&
1071. 	    u.ux == ESHK(shkp)->shd.x && u.uy == ESHK(shkp)->shd.y) {
1072. 		pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj));
1073. 		obj->nobj = shkp->minvent;
1074. 		shkp->minvent = obj;
1075. 		return(1);
1076. 	}
1077. 	return(0);
1078. }
1079. 
1080. /*
1081.  * shk_move: return 1: he moved  0: he didn't  -1: let m_move do it  -2: died
1082.  */
1083. int
1084. shk_move(shkp)
1085. register struct monst *shkp;
1086. {
1087. 	register xchar gx,gy,omx,omy;
1088. 	register int udist;
1089. 	register schar appr;
1090. 	int z;
1091. 	schar shkroom;
1092. 	boolean uondoor, satdoor, avoid, badinv;
1093. 
1094. 	omx = shkp->mx;
1095. 	omy = shkp->my;
1096. 
1097. 	if((udist = dist(omx,omy)) < 3) {
1098. 		if(ANGRY(shkp)) {
1099. 			if(Displaced)
1100. 			  Your("displaced image doesn't fool %s!",
1101. 				Monnam(shkp));
1102. 			(void) mattacku(shkp);
1103. 			return(0);
1104. 		}
1105. 		if(ESHK(shkp)->following) {
1106. 			if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)) {
1107. 			    pline("\"Hello, %s!  I was looking for %s.\"",
1108. 				    plname, ESHK(shkp)->customer);
1109. 				    ESHK(shkp)->following = 0;
1110. 			    return(0);
1111. 			}
1112. 			if(moves > followmsg+4) {
1113. 			    pline("\"Hello, %s!  Didn't you forget to pay?\"",
1114. 				    plname);
1115. 			    followmsg = moves;
1116. #ifdef HARD
1117. 			    if (!rn2(4)) {
1118. 	    pline ("%s doesn't like customers who don't pay.", Monnam(shkp));
1119. 				NOTANGRY(shkp) = 0;
1120. 			    }
1121. #endif
1122. 			}
1123. 			if(udist < 2)
1124. 			    return(0);
1125. 		}
1126. 	}
1127. 
1128. 	shkroom = inroom(omx,omy);
1129. 	appr = 1;
1130. 	gx = ESHK(shkp)->shk.x;
1131. 	gy = ESHK(shkp)->shk.y;
1132. 	satdoor = (gx == omx && gy == omy);
1133. 	if(ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){
1134. 		gx = u.ux;
1135. 		gy = u.uy;
1136. 		if(shkroom < 0 || shkroom != inroom(u.ux,u.uy))
1137. 		    if(udist > 4)
1138. 			return(-1);	/* leave it to m_move */
1139. 	} else if(ANGRY(shkp)) {
1140. 		long saveBlind = Blinded;
1141. 		struct obj *saveUblindf = ublindf;
1142. 		Blinded = 0;
1143. 		ublindf = (struct obj *)0;
1144. 		if(shkp->mcansee && !Invis && cansee(omx,omy)) {
1145. 			gx = u.ux;
1146. 			gy = u.uy;
1147. 		}
1148. 		Blinded = saveBlind;
1149. 		ublindf = saveUblindf;
1150. 		avoid = FALSE;
1151. 	} else {
1152. #define	GDIST(x,y)	(dist2(x,y,gx,gy))
1153. 		if(Invis)
1154. 		    avoid = FALSE;
1155. 		else {
1156. 		    uondoor = (u.ux == ESHK(shkp)->shd.x &&
1157. 				u.uy == ESHK(shkp)->shd.y);
1158. 		    if(uondoor) {
1159. 			if(ESHK(shkp)->billct && inhishop(shkp))
1160. 			    pline(NOTANGRY(shkp) ?
1161. 				"\"Hello, %s!  Will you please pay before leaving?\"" :
1162. 				"\"Hey, %s!  Don't leave without paying!\"",
1163. 				plname);
1164. 			badinv = (!!carrying(PICK_AXE));
1165. 			if(satdoor && badinv)
1166. 			    return(0);
1167. 			avoid = !badinv;
1168. 		    } else {
1169. 			avoid = (u.uinshop && dist(gx,gy) > 8);
1170. 			badinv = FALSE;
1171. 		    }
1172. 
1173. 		    if(((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
1174. 			&& GDIST(omx,omy) < 3) {
1175. 			if(!badinv && !online(omx,omy))
1176. 			    return(0);
1177. 			if(satdoor)
1178. 			    appr = gx = gy = 0;
1179. 		    }
1180. 		}
1181. 	}
1182. 	
1183. 	return(move_special(shkp,shkroom,appr,uondoor,avoid,omx,omy,gx,gy));
1184. }
1185. 
1186. int
1187. online(x,y)		/*	New version to speed things up.
1188. 			 *	Compiler dependant, may not always work.
1189. 			 */
1190. register xchar x, y;
1191. {
1192. 	return((x-=u.ux) == 0 || (y-=u.uy) == 0 || x == y || (x+=y) == 0);
1193. }
1194. 
1195. /*			Original version, just in case...
1196.  *online(x,y) {
1197.  *	return(x==u.ux || y==u.uy || (x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy));
1198.  *}
1199.  */
1200. 
1201. /* for use in levl_follower (mondata.c) */
1202. boolean
1203. is_fshk(mtmp)
1204. register struct monst *mtmp;
1205. {
1206. 	return(mtmp->isshk && ESHK(mtmp)->following);
1207. }
1208. 
1209. /* He is digging in the shop. */
1210. void
1211. shopdig(fall)
1212. register int fall;
1213. {
1214.     if(!shopkeeper) return;
1215.     if(!inhishop(shopkeeper)) {
1216. 	if (pl_character[0] == 'K') adjalign(-sgn(u.ualigntyp));
1217. 	return;
1218.     }
1219. 
1220.     if(!fall) {
1221. 	if(u.utraptype == TT_PIT)
1222. 	    pline("\"Be careful, %s, or you might fall through the floor.\"",
1223. 		flags.female ? "madam" : "sir");
1224. 	else
1225. 	    pline("\"%s, do not damage the floor here!\"",
1226. 			flags.female ? "Madam" : "Sir");
1227. 	if (pl_character[0] == 'K') adjalign(-sgn(u.ualigntyp));
1228.     } else if(um_dist(shopkeeper->mx, shopkeeper->my, 2)) {
1229. 	register struct obj *obj, *obj2;
1230. 
1231. 	if(dist(shopkeeper->mx, shopkeeper->my) > 2) {
1232. 		mnexto(shopkeeper);
1233. 		/* for some reason he can't come next to you */
1234. 		if(dist(shopkeeper->mx, shopkeeper->my) > 2) {
1235. 		    pline("%s curses you in anger and frustration!",
1236. 					shkname(shopkeeper));
1237. 		    NOTANGRY(shopkeeper) = 0;
1238. 		    return;
1239. 		} else pline("%s leaps, and grabs your backpack!",
1240. 					shkname(shopkeeper));
1241. 	} else pline("%s grabs your backpack!", shkname(shopkeeper));
1242. 
1243. 	for(obj = invent; obj; obj = obj2) {
1244. 		obj2 = obj->nobj;
1245. 		if(obj->owornmask) continue;
1246. 		freeinv(obj);
1247. 		obj->nobj = shopkeeper->minvent;
1248. 		shopkeeper->minvent = obj;
1249. 		if(obj->unpaid)
1250. 			subfrombill(obj);
1251. 	}
1252.     }
1253. }
1254. 
1255. #ifdef KOPS
1256. static int
1257. makekops(mm)		/* returns the number of (all types of) Kops  made */
1258. coord *mm;
1259. {
1260. 	register int cnt = dlevel + rnd(5);
1261. 	register int scnt = (cnt / 3) + 1;	/* at least one sarge */
1262. 	register int lcnt = (cnt / 6);		/* maybe a lieutenant */
1263. 	register int kcnt = (cnt / 9);		/* and maybe a kaptain */
1264. 
1265. 	while(cnt--) {
1266. 	    enexto(mm, mm->x, mm->y);
1267. 	    (void) makemon(&mons[PM_KEYSTONE_KOP], mm->x, mm->y);
1268. 	}
1269. 	while(scnt--) {
1270. 	    enexto(mm, mm->x, mm->y);
1271. 	    (void) makemon(&mons[PM_KOP_SERGEANT], mm->x, mm->y);
1272. 	}
1273. 	while(lcnt--) {
1274. 	    enexto(mm, mm->x, mm->y);
1275. 	    (void) makemon(&mons[PM_KOP_LIEUTENANT], mm->x, mm->y);
1276. 	}
1277. 	while(kcnt--) {
1278. 	    enexto(mm, mm->x, mm->y);
1279. 	    (void) makemon(&mons[PM_KOP_KAPTAIN], mm->x, mm->y);
1280. 	}
1281. 	return(cnt + scnt + lcnt + kcnt);
1282. }
1283. #endif
1284. 
1285. boolean
1286. in_shop(x,y)
1287. register int x, y;
1288. {
1289. 	register int roomno = inroom(x, y);
1290. 
1291. 	if (roomno < 0) return(FALSE);
1292. 	return (IS_SHOP(rooms[roomno]));
1293. }
1294. 
1295. void
1296. pay_for_door(x,y,dmgstr)
1297. register int x, y;
1298. register char *dmgstr;
1299. {
1300. 	register struct monst *mtmp;
1301. 	register int ox, oy;
1302. 	register int roomno = inroom(x, y);
1303. 	register int damage = (ACURR(A_STR) > 18) ? 400 : 20 * ACURR(A_STR);
1304. 
1305. 	/* make sure this function is not used in the wrong place */
1306. 	if(!(IS_DOOR(levl[x][y].typ) && in_shop(x, y))) return;
1307. 
1308. 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
1309. 	    if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
1310. 			   && ESHK(mtmp)->shoplevel == dlevel) {
1311. 		shopkeeper = mtmp;
1312. 	}
1313. 
1314. 	if(!shopkeeper) return;
1315. 
1316. 	/* not the best introduction to the shk... */
1317. 	(void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
1318. 
1319. 	/* if he is already on the war path, be sure it's all out */
1320. 	if(ANGRY(shopkeeper) || ESHK(shopkeeper)->following) {
1321. 		NOTANGRY(shopkeeper) = 0;
1322. 		ESHK(shopkeeper)->following = 1;
1323. 		return;
1324. 	}
1325. 
1326. 	ox = shopkeeper->mx;
1327. 	oy = shopkeeper->my;
1328. 
1329. 	/* if he's not in his shop.. */
1330. 	if(!in_shop(ox, oy)) return;
1331. 
1332. 	/* if a !shopkeeper shows up at the door, move him */
1333. 	if(levl[x][y].mmask && (mtmp = m_at(x, y)) != shopkeeper) {
1334. 		if(flags.soundok) {
1335. 		    You("hear an angry voice: \"Out of my way, scum!\"");
1336. 		    (void) fflush(stdout);
1337. #if defined(SYSV) || defined(ULTRIX)
1338. 		    (void)
1339. #endif
1340. #ifdef UNIX
1341. 			sleep(1);
1342. #endif
1343. 		}
1344. 		mnearto(mtmp, x, y, FALSE);
1345. 	}
1346. 
1347. 	/* make shk show up at the door */
1348. 	levl[shopkeeper->mx][shopkeeper->my].mmask = 0;
1349. 	levl[x][y].mmask = 1;
1350. 	shopkeeper->mx = x;
1351. 	shopkeeper->my = y;
1352. 	pmon(shopkeeper);
1353. 
1354. 	if(um_dist(x, y, 1)) goto chase;
1355. 
1356. 	if(u.ugold < damage || !rn2(50)) {
1357. chase:
1358. 		if(um_dist(x, y, 1))
1359. 		    pline("%s shouts: \"Who dared %s my door?\"",
1360. 				shkname(shopkeeper), dmgstr);
1361. 		else pline("\"How dare you %s my door?\"", dmgstr);
1362. 		NOTANGRY(shopkeeper) = 0;
1363. 		ESHK(shopkeeper)->following = 1;
1364. 		return;
1365. 	}
1366. 
1367. 	pline("\"Cad!  You did %d zorkmids worth of damage!\"  Pay? ", damage);
1368. 	if(yn() != 'n') {
1369. 		u.ugold -= damage;
1370. 		shopkeeper->mgold += damage;
1371. 		flags.botl = 1;
1372. 		pline("Mollified, %s accepts your restitution.",
1373. 			shkname(shopkeeper));
1374. 
1375. 		/* clear ox oy of another monster, if one got there somehow */
1376. 		if(levl[ox][oy].mmask) mnearto(m_at(ox,oy),ox,oy,FALSE);
1377. 
1378. 		/* move shk back to his orig loc */
1379. 		levl[shopkeeper->mx][shopkeeper->my].mmask = 0;
1380. 		levl[ox][oy].mmask = 1;
1381. 		shopkeeper->mx = ox;
1382. 		shopkeeper->my = oy;
1383. 		unpmon(shopkeeper);
1384. 		NOTANGRY(shopkeeper) = 1;
1385. 	}
1386. 	else {
1387. 		pline("\"Oh, yes!  You'll pay!\"");
1388. 		ESHK(shopkeeper)->following = 1;
1389. 		NOTANGRY(shopkeeper) = 0;
1390. 		adjalign(-sgn(u.ualigntyp));
1391. 	}
1392. }
1393. 
1394. /* called in dokick.c when we kick an object in a store */
1395. boolean
1396. costly_spot(x, y)
1397. register int x, y;
1398. {
1399. 	register struct monst *shkp = shopkeeper;
1400. 	
1401. 	if(!shkp) return(FALSE);
1402. 
1403. 	return(in_shop(x, y) && levl[x][y].typ != DOOR &&
1404. 		!(x == ESHK(shkp)->shk.x && y == ESHK(shkp)->shk.y));
1405. }
1406. 
1407. #ifdef KOPS
1408. static void
1409. kops_gone()
1410. {
1411. 	register int cnt = 0;
1412. 	register struct monst *mtmp, *mtmp2;
1413. 
1414. 	/* turn off automatic resurrection of kops */
1415. 	allow_kops = FALSE;
1416. 
1417. 	for(mtmp = fmon; mtmp; mtmp = mtmp2) {
1418. 		mtmp2 = mtmp->nmon;
1419. 		if(mtmp->data->mlet == S_KOP) {
1420. 			mongone(mtmp);
1421. 			cnt++;
1422. 		}
1423. 	}
1424. 	if(cnt) pline("The Kops (disappointed) disappear into thin air.");
1425. 	allow_kops = TRUE;
1426. }
1427. #endif
1428. 
1429. static long
1430. cost_per_charge(otmp)
1431. register struct obj *otmp;
1432. {
1433. 	register long tmp = get_cost(otmp);
1434. 
1435. 	/* The idea is to make the exhaustive use of */
1436. 	/* an unpaid item more expansive than buying */
1437. 	/* outright.				     */
1438. 	if(otmp->otyp == MAGIC_LAMP) {			 /* 1 */
1439. 		tmp += (tmp/3L);
1440. 	} else if(otmp->otyp == MAGIC_MARKER) {  	 /* 70 - 100 */
1441. 		/* no way to determine in advance   */
1442. 		/* how many charges will be wasted. */
1443. 		/* so, arbitrarily, one half of the */
1444. 		/* price per use.		    */
1445. 		tmp = (tmp/2L);
1446. 	} else if(otmp->otyp == BAG_OF_TRICKS) { 	 /* 1 - 20 */
1447. 		tmp = (tmp/5L);
1448. 	} else if(otmp->otyp == CRYSTAL_BALL ||  	 /* 1 - 5 */
1449. 		  otmp->otyp == LAMP ||	                 /* 1-10 */
1450. #ifdef MUSIC
1451. 		 (otmp->otyp >= MAGIC_FLUTE &&
1452. 		  otmp->otyp <= DRUM_OF_EARTHQUAKE) || 	 /* 5 - 9 */
1453. #endif
1454. 	  	  otmp->olet == WAND_SYM) {		 /* 3 - 11 */
1455. 		if(otmp->spe == 1) tmp += (tmp/3L);
1456. 		else tmp = (tmp/4L);
1457. 	}
1458. 	else return(0L);
1459. 	return(tmp);
1460. }
1461. 
1462. /* for using charges of unpaid objects */
1463. void
1464. check_unpaid(otmp)
1465. register struct obj *otmp;
1466. {
1467. 	if(!in_shop(u.ux, u.uy)) return;
1468. 	
1469. 	if(otmp->spe <= 0) return;
1470. 
1471. 	if(otmp->unpaid) {
1472. 		ESHK(shopkeeper)->debit += cost_per_charge(otmp);
1473. 	}
1474. }