Difference between revisions of "Source:NetHack 1.4f/invent.c"

From NetHackWiki
Jump to navigation Jump to search
m (Semi-redirect to 1.3d versions)
Line 1: Line 1:
The source code file '''invent.c''' in [[NetHack 1.4f source code|NetHack 1.4f]] is unchanged from [[NetHack 1.3d/invent.c]].
+
Below is the full text to '''invent.c''' from the [[NetHack 1.4f source code|source code]] of [[NetHack 1.4f]]. To link to a particular line, write [[NetHack 1.4f/invent.c#line123|[[NetHack 1.4f/invent.c#line123]]]], for example.
[[Category:NetHack 1.4f source code]]
+
 
 +
'''Warning!''' This is the source code from an old release. For the latest release, see [[Source code]]
 +
 
 +
The [http://www.juiblex.co.uk/nethack/source/nethack-1.4f.tar.gz Harlow distribution] of NetHack 1.4f does not contain this file; it contains one identical to its [[NetHack 1.3d/invent.c|counterpart]] in [[NetHack 1.3d]].  This is probably due to difficulties in applying the original patch as distributed on Usenet.  See [[How to apply the NetHack 1.4f patch]] for instructions to obtain this file.
 +
 
 +
{{CWI}}
 +
<span id="line1">1.    /* SCCS Id: @(#)invent.c 1.4 87/08/08</span>
 +
<span id="line2">2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */</span>
 +
<span id="line3">3.    /* invent.c - version 1.0.3 */</span>
 +
<span id="line4">4.    </span>
 +
<span id="line5">5.    #include <stdio.h></span>
 +
<span id="line6">6.    #include "hack.h"</span>
 +
<span id="line7">7.    extern struct obj *splitobj();</span>
 +
<span id="line8">8.    extern struct obj zeroobj;</span>
 +
<span id="line9">9.    extern char morc;</span>
 +
<span id="line10">10.  extern char quitchars[];</span>
 +
<span id="line11">11.  static char *xprname();</span>
 +
<span id="line12">12.  </span>
 +
<span id="line13">13.  #ifndef NOWORM</span>
 +
<span id="line14">14.  #include "wseg.h"</span>
 +
<span id="line15">15.  extern struct wseg *wsegs[32];</span>
 +
<span id="line16">16.  #endif</span>
 +
<span id="line17">17.  </span>
 +
<span id="line18">18.  #define NOINVSYM '#'</span>
 +
<span id="line19">19.  </span>
 +
<span id="line20">20.  int lastinvnr = 51; /* 0 ... 51 */</span>
 +
<span id="line21">21.  </span>
 +
<span id="line22">22.  static</span>
 +
<span id="line23">23.  assigninvlet(otmp)</span>
 +
<span id="line24">24.  register struct obj *otmp;</span>
 +
<span id="line25">25.  {</span>
 +
<span id="line26">26.  boolean inuse[52];</span>
 +
<span id="line27">27.  register int i;</span>
 +
<span id="line28">28.  register struct obj *obj;</span>
 +
<span id="line29">29.  </span>
 +
<span id="line30">30.  for(i = 0; i < 52; i++) inuse[i] = FALSE;</span>
 +
<span id="line31">31.  for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {</span>
 +
<span id="line32">32.  i = obj->invlet;</span>
 +
<span id="line33">33.  if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else</span>
 +
<span id="line34">34.  if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;</span>
 +
<span id="line35">35.  if(i == otmp->invlet) otmp->invlet = 0;</span>
 +
<span id="line36">36.  }</span>
 +
<span id="line37">37.  if((i = otmp->invlet) &&</span>
 +
<span id="line38">38.      (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))</span>
 +
<span id="line39">39.  return;</span>
 +
<span id="line40">40.  for(i = lastinvnr+1; i != lastinvnr; i++) {</span>
 +
<span id="line41">41.  if(i == 52) { i = -1; continue; }</span>
 +
<span id="line42">42.  if(!inuse[i]) break;</span>
 +
<span id="line43">43.  }</span>
 +
<span id="line44">44.  otmp->invlet = (inuse[i] ? NOINVSYM :</span>
 +
<span id="line45">45.  (i < 26) ? ('a'+i) : ('A'+i-26));</span>
 +
<span id="line46">46.  lastinvnr = i;</span>
 +
<span id="line47">47.  }</span>
 +
<span id="line48">48.  </span>
 +
<span id="line49">49.  struct obj *</span>
 +
<span id="line50">50.  addinv(obj)</span>
 +
<span id="line51">51.  register struct obj *obj;</span>
 +
<span id="line52">52.  {</span>
 +
<span id="line53">53.  register struct obj *otmp;</span>
 +
<span id="line54">54.  </span>
 +
<span id="line55">55.  /* merge or attach to end of chain */</span>
 +
<span id="line56">56.  if(!invent) {</span>
 +
<span id="line57">57.  invent = obj;</span>
 +
<span id="line58">58.  otmp = 0;</span>
 +
<span id="line59">59.  } else</span>
 +
<span id="line60">60.  for(otmp = invent; /* otmp */; otmp = otmp->nobj) {</span>
 +
<span id="line61">61.  if(merged(otmp, obj, 0))</span>
 +
<span id="line62">62.  return(otmp);</span>
 +
<span id="line63">63.  if(!otmp->nobj) {</span>
 +
<span id="line64">64.  otmp->nobj = obj;</span>
 +
<span id="line65">65.  break;</span>
 +
<span id="line66">66.  }</span>
 +
<span id="line67">67.  }</span>
 +
<span id="line68">68.  obj->nobj = 0;</span>
 +
<span id="line69">69.  </span>
 +
<span id="line70">70.  if(flags.invlet_constant) {</span>
 +
<span id="line71">71.  assigninvlet(obj);</span>
 +
<span id="line72">72.  /*</span>
 +
<span id="line73">73.  * The ordering of the chain is nowhere significant</span>
 +
<span id="line74">74.  * so in case you prefer some other order than the</span>
 +
<span id="line75">75.  * historical one, change the code below.</span>
 +
<span id="line76">76.  */</span>
 +
<span id="line77">77.  if(otmp) { /* find proper place in chain */</span>
 +
<span id="line78">78.  otmp->nobj = 0;</span>
 +
<span id="line79">79.  if((invent->invlet ^ 040) > (obj->invlet ^ 040)) {</span>
 +
<span id="line80">80.  obj->nobj = invent;</span>
 +
<span id="line81">81.  invent = obj;</span>
 +
<span id="line82">82.  } else</span>
 +
<span id="line83">83.  for(otmp = invent; ; otmp = otmp->nobj) {</span>
 +
<span id="line84">84.      if(!otmp->nobj ||</span>
 +
<span id="line85">85.  (otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){</span>
 +
<span id="line86">86.  obj->nobj = otmp->nobj;</span>
 +
<span id="line87">87.  otmp->nobj = obj;</span>
 +
<span id="line88">88.  break;</span>
 +
<span id="line89">89.      }</span>
 +
<span id="line90">90.  }</span>
 +
<span id="line91">91.  }</span>
 +
<span id="line92">92.  }</span>
 +
<span id="line93">93.  </span>
 +
<span id="line94">94.  return(obj);</span>
 +
<span id="line95">95.  }</span>
 +
<span id="line96">96.  </span>
 +
<span id="line97">97.  useup(obj)</span>
 +
<span id="line98">98.  register struct obj *obj;</span>
 +
<span id="line99">99.  {</span>
 +
<span id="line100">100.  if(obj->quan > 1){</span>
 +
<span id="line101">101.  obj->quan--;</span>
 +
<span id="line102">102.  obj->owt = weight(obj);</span>
 +
<span id="line103">103.  } else {</span>
 +
<span id="line104">104.  setnotworn(obj);</span>
 +
<span id="line105">105.  freeinv(obj);</span>
 +
<span id="line106">106.  obfree(obj, (struct obj *) 0);</span>
 +
<span id="line107">107.  }</span>
 +
<span id="line108">108.  }</span>
 +
<span id="line109">109.  </span>
 +
<span id="line110">110.  freeinv(obj)</span>
 +
<span id="line111">111.  register struct obj *obj;</span>
 +
<span id="line112">112.  {</span>
 +
<span id="line113">113.  register struct obj *otmp;</span>
 +
<span id="line114">114.  </span>
 +
<span id="line115">115.  if(obj == invent)</span>
 +
<span id="line116">116.  invent = invent->nobj;</span>
 +
<span id="line117">117.  else {</span>
 +
<span id="line118">118.  for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj)</span>
 +
<span id="line119">119.  if(!otmp->nobj) panic("freeinv");</span>
 +
<span id="line120">120.  otmp->nobj = obj->nobj;</span>
 +
<span id="line121">121.  }</span>
 +
<span id="line122">122.  }</span>
 +
<span id="line123">123.  </span>
 +
<span id="line124">124.  /* destroy object in fobj chain (if unpaid, it remains on the bill) */</span>
 +
<span id="line125">125.  delobj(obj) register struct obj *obj; {</span>
 +
<span id="line126">126.  freeobj(obj);</span>
 +
<span id="line127">127.  unpobj(obj);</span>
 +
<span id="line128">128.  obfree(obj, (struct obj *) 0);</span>
 +
<span id="line129">129.  }</span>
 +
<span id="line130">130.  </span>
 +
<span id="line131">131.  /* unlink obj from chain starting with fobj */</span>
 +
<span id="line132">132.  freeobj(obj) register struct obj *obj; {</span>
 +
<span id="line133">133.  register struct obj *otmp;</span>
 +
<span id="line134">134.  </span>
 +
<span id="line135">135.  if(obj == fobj) fobj = fobj->nobj;</span>
 +
<span id="line136">136.  else {</span>
 +
<span id="line137">137.  for(otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj)</span>
 +
<span id="line138">138.  if(!otmp) panic("error in freeobj");</span>
 +
<span id="line139">139.  otmp->nobj = obj->nobj;</span>
 +
<span id="line140">140.  }</span>
 +
<span id="line141">141.  }</span>
 +
<span id="line142">142.  </span>
 +
<span id="line143">143.  /* Note: freegold throws away its argument! */</span>
 +
<span id="line144">144.  freegold(gold) register struct gold *gold; {</span>
 +
<span id="line145">145.  register struct gold *gtmp;</span>
 +
<span id="line146">146.  </span>
 +
<span id="line147">147.  if(gold == fgold) fgold = gold->ngold;</span>
 +
<span id="line148">148.  else {</span>
 +
<span id="line149">149.  for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold)</span>
 +
<span id="line150">150.  if(!gtmp) panic("error in freegold");</span>
 +
<span id="line151">151.  gtmp->ngold = gold->ngold;</span>
 +
<span id="line152">152.  }</span>
 +
<span id="line153">153.  free((char *) gold);</span>
 +
<span id="line154">154.  }</span>
 +
<span id="line155">155.  </span>
 +
<span id="line156">156.  deltrap(trap)</span>
 +
<span id="line157">157.  register struct trap *trap;</span>
 +
<span id="line158">158.  {</span>
 +
<span id="line159">159.  register struct trap *ttmp;</span>
 +
<span id="line160">160.  </span>
 +
<span id="line161">161.  if(trap == ftrap)</span>
 +
<span id="line162">162.  ftrap = ftrap->ntrap;</span>
 +
<span id="line163">163.  else {</span>
 +
<span id="line164">164.  for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;</span>
 +
<span id="line165">165.  ttmp->ntrap = trap->ntrap;</span>
 +
<span id="line166">166.  }</span>
 +
<span id="line167">167.  free((char *) trap);</span>
 +
<span id="line168">168.  }</span>
 +
<span id="line169">169.  </span>
 +
<span id="line170">170.  struct wseg *m_atseg;</span>
 +
<span id="line171">171.  </span>
 +
<span id="line172">172.  struct monst *</span>
 +
<span id="line173">173.  m_at(x,y)</span>
 +
<span id="line174">174.  register x,y;</span>
 +
<span id="line175">175.  {</span>
 +
<span id="line176">176.  register struct monst *mtmp;</span>
 +
<span id="line177">177.  #ifndef NOWORM</span>
 +
<span id="line178">178.  register struct wseg *wtmp;</span>
 +
<span id="line179">179.  #endif</span>
 +
<span id="line180">180.  </span>
 +
<span id="line181">181.  m_atseg = 0;</span>
 +
<span id="line182">182.  for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){</span>
 +
<span id="line183">183.  if(mtmp->mx == x && mtmp->my == y)</span>
 +
<span id="line184">184.  return(mtmp);</span>
 +
<span id="line185">185.  #ifndef NOWORM</span>
 +
<span id="line186">186.  if(mtmp->wormno){</span>
 +
<span id="line187">187.      for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg)</span>
 +
<span id="line188">188.      if(wtmp->wx == x && wtmp->wy == y){</span>
 +
<span id="line189">189.  m_atseg = wtmp;</span>
 +
<span id="line190">190.  return(mtmp);</span>
 +
<span id="line191">191.      }</span>
 +
<span id="line192">192.  }</span>
 +
<span id="line193">193.  #endif</span>
 +
<span id="line194">194.  }</span>
 +
<span id="line195">195.  return(0);</span>
 +
<span id="line196">196.  }</span>
 +
<span id="line197">197.  </span>
 +
<span id="line198">198.  struct obj *</span>
 +
<span id="line199">199.  o_at(x,y)</span>
 +
<span id="line200">200.  register x,y;</span>
 +
<span id="line201">201.  {</span>
 +
<span id="line202">202.  register struct obj *otmp;</span>
 +
<span id="line203">203.  </span>
 +
<span id="line204">204.  for(otmp = fobj; otmp; otmp = otmp->nobj)</span>
 +
<span id="line205">205.  if(otmp->ox == x && otmp->oy == y) return(otmp);</span>
 +
<span id="line206">206.  return(0);</span>
 +
<span id="line207">207.  }</span>
 +
<span id="line208">208.  </span>
 +
<span id="line209">209.  struct obj *</span>
 +
<span id="line210">210.  sobj_at(n,x,y)</span>
 +
<span id="line211">211.  register n,x,y;</span>
 +
<span id="line212">212.  {</span>
 +
<span id="line213">213.  register struct obj *otmp;</span>
 +
<span id="line214">214.  </span>
 +
<span id="line215">215.  for(otmp = fobj; otmp; otmp = otmp->nobj)</span>
 +
<span id="line216">216.  if(otmp->ox == x && otmp->oy == y && otmp->otyp == n)</span>
 +
<span id="line217">217.  return(otmp);</span>
 +
<span id="line218">218.  return(0);</span>
 +
<span id="line219">219.  }</span>
 +
<span id="line220">220.  </span>
 +
<span id="line221">221.  carried(obj) register struct obj *obj; {</span>
 +
<span id="line222">222.  register struct obj *otmp;</span>
 +
<span id="line223">223.  for(otmp = invent; otmp; otmp = otmp->nobj)</span>
 +
<span id="line224">224.  if(otmp == obj) return(1);</span>
 +
<span id="line225">225.  return(0);</span>
 +
<span id="line226">226.  }</span>
 +
<span id="line227">227.  </span>
 +
<span id="line228">228.  struct obj *</span>
 +
<span id="line229">229.  carrying(type)</span>
 +
<span id="line230">230.  register int type;</span>
 +
<span id="line231">231.  {</span>
 +
<span id="line232">232.  register struct obj *otmp;</span>
 +
<span id="line233">233.  </span>
 +
<span id="line234">234.  for(otmp = invent; otmp; otmp = otmp->nobj)</span>
 +
<span id="line235">235.  if(otmp->otyp == type)</span>
 +
<span id="line236">236.  return(otmp);</span>
 +
<span id="line237">237.  return((struct obj *) 0);</span>
 +
<span id="line238">238.  }</span>
 +
<span id="line239">239.  </span>
 +
<span id="line240">240.  struct obj *</span>
 +
<span id="line241">241.  o_on(id, objchn) unsigned int id; register struct obj *objchn; {</span>
 +
<span id="line242">242.  while(objchn) {</span>
 +
<span id="line243">243.  if(objchn->o_id == id) return(objchn);</span>
 +
<span id="line244">244.  objchn = objchn->nobj;</span>
 +
<span id="line245">245.  }</span>
 +
<span id="line246">246.  return((struct obj *) 0);</span>
 +
<span id="line247">247.  }</span>
 +
<span id="line248">248.  </span>
 +
<span id="line249">249.  struct trap *</span>
 +
<span id="line250">250.  t_at(x,y)</span>
 +
<span id="line251">251.  register x,y;</span>
 +
<span id="line252">252.  {</span>
 +
<span id="line253">253.  register struct trap *trap = ftrap;</span>
 +
<span id="line254">254.  while(trap) {</span>
 +
<span id="line255">255.  if(trap->tx == x && trap->ty == y) return(trap);</span>
 +
<span id="line256">256.  trap = trap->ntrap;</span>
 +
<span id="line257">257.  }</span>
 +
<span id="line258">258.  return(0);</span>
 +
<span id="line259">259.  }</span>
 +
<span id="line260">260.  </span>
 +
<span id="line261">261.  struct gold *</span>
 +
<span id="line262">262.  g_at(x,y)</span>
 +
<span id="line263">263.  register x,y;</span>
 +
<span id="line264">264.  {</span>
 +
<span id="line265">265.  register struct gold *gold = fgold;</span>
 +
<span id="line266">266.  while(gold) {</span>
 +
<span id="line267">267.  if(gold->gx == x && gold->gy == y) return(gold);</span>
 +
<span id="line268">268.  gold = gold->ngold;</span>
 +
<span id="line269">269.  }</span>
 +
<span id="line270">270.  return(0);</span>
 +
<span id="line271">271.  }</span>
 +
<span id="line272">272.  </span>
 +
<span id="line273">273.  /* make dummy object structure containing gold - for temporary use only */</span>
 +
<span id="line274">274.  struct obj *</span>
 +
<span id="line275">275.  mkgoldobj(q)</span>
 +
<span id="line276">276.  register long q;</span>
 +
<span id="line277">277.  {</span>
 +
<span id="line278">278.  register struct obj *otmp;</span>
 +
<span id="line279">279.  </span>
 +
<span id="line280">280.  otmp = newobj(0);</span>
 +
<span id="line281">281.  /* should set o_id etc. but otmp will be freed soon */</span>
 +
<span id="line282">282.  otmp->olet = GOLD_SYM;</span>
 +
<span id="line283">283.  u.ugold -= q;</span>
 +
<span id="line284">284.  OGOLD(otmp) = q;</span>
 +
<span id="line285">285.  flags.botl = 1;</span>
 +
<span id="line286">286.  return(otmp);</span>
 +
<span id="line287">287.  }</span>
 +
<span id="line288">288.  </span>
 +
<span id="line289">289.  /*</span>
 +
<span id="line290">290.  * getobj returns:</span>
 +
<span id="line291">291.  * struct obj *xxx: object to do something with.</span>
 +
<span id="line292">292.  * (struct obj *) 0 error return: no object.</span>
 +
<span id="line293">293.  * &zeroobj explicitly no object (as in w-).</span>
 +
<span id="line294">294.  */</span>
 +
<span id="line295">295.  struct obj *</span>
 +
<span id="line296">296.  getobj(let,word)</span>
 +
<span id="line297">297.  register char *let,*word;</span>
 +
<span id="line298">298.  {</span>
 +
<span id="line299">299.  register struct obj *otmp;</span>
 +
<span id="line300">300.  register char ilet,ilet1,ilet2;</span>
 +
<span id="line301">301.  char buf[BUFSZ];</span>
 +
<span id="line302">302.  char lets[BUFSZ];</span>
 +
<span id="line303">303.  register int foo = 0, foo2;</span>
 +
<span id="line304">304.  register char *bp = buf;</span>
 +
<span id="line305">305.  xchar allowcnt = 0; /* 0, 1 or 2 */</span>
 +
<span id="line306">306.  boolean allowgold = FALSE;</span>
 +
<span id="line307">307.  boolean allowall = FALSE;</span>
 +
<span id="line308">308.  boolean allownone = FALSE;</span>
 +
<span id="line309">309.  xchar foox = 0;</span>
 +
<span id="line310">310.  long cnt;</span>
 +
<span id="line311">311.  </span>
 +
<span id="line312">312.  if(*let == '0') let++, allowcnt = 1;</span>
 +
<span id="line313">313.  if(*let == GOLD_SYM) let++, allowgold = TRUE;</span>
 +
<span id="line314">314.  if(*let == '#') let++, allowall = TRUE;</span>
 +
<span id="line315">315.  if(*let == '-') let++, allownone = TRUE;</span>
 +
<span id="line316">316.  if(allownone) *bp++ = '-';</span>
 +
<span id="line317">317.  if(allowgold) *bp++ = GOLD_SYM;</span>
 +
<span id="line318">318.  if(bp > buf && bp[-1] == '-') *bp++ = ' ';</span>
 +
<span id="line319">319.  </span>
 +
<span id="line320">320.  ilet = 'a';</span>
 +
<span id="line321">321.  for(otmp = invent; otmp; otmp = otmp->nobj){</span>
 +
<span id="line322">322.      if(!*let || index(let, otmp->olet)) {</span>
 +
<span id="line323">323.  bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet;</span>
 +
<span id="line324">324.  </span>
 +
<span id="line325">325.  /* ugly check: remove inappropriate things */</span>
 +
<span id="line326">326.  if((!strcmp(word, "take off") &&</span>
 +
<span id="line327">327.      !(otmp->owornmask & (W_ARMOR - W_ARM2)))</span>
 +
<span id="line328">328.  || (!strcmp(word, "wear") &&</span>
 +
<span id="line329">329.      (otmp->owornmask & (W_ARMOR | W_RING)))</span>
 +
<span id="line330">330.  || (!strcmp(word, "wield") &&</span>
 +
<span id="line331">331.      (otmp->owornmask & W_WEP))</span>
 +
<span id="line332">332.  #ifdef MARKER</span>
 +
<span id="line333">333.  || (!strcmp(word, "write with") &&</span>
 +
<span id="line334">334.      (otmp->olet == TOOL_SYM && otmp->otyp != MAGIC_MARKER))</span>
 +
<span id="line335">335.  #endif</span>
 +
<span id="line336">336.      ) {</span>
 +
<span id="line337">337.  foo--;</span>
 +
<span id="line338">338.  foox++;</span>
 +
<span id="line339">339.  }</span>
 +
<span id="line340">340.      }</span>
 +
<span id="line341">341.      if(ilet == 'z') ilet = 'A'; else ilet++;</span>
 +
<span id="line342">342.  }</span>
 +
<span id="line343">343.  bp[foo] = 0;</span>
 +
<span id="line344">344.  if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;</span>
 +
<span id="line345">345.  (void) strcpy(lets, bp); /* necessary since we destroy buf */</span>
 +
<span id="line346">346.  if(foo > 5) { /* compactify string */</span>
 +
<span id="line347">347.  foo = foo2 = 1;</span>
 +
<span id="line348">348.  ilet2 = bp[0];</span>
 +
<span id="line349">349.  ilet1 = bp[1];</span>
 +
<span id="line350">350.  while(ilet = bp[++foo2] = bp[++foo]){</span>
 +
<span id="line351">351.  if(ilet == ilet1+1){</span>
 +
<span id="line352">352.  if(ilet1 == ilet2+1)</span>
 +
<span id="line353">353.  bp[foo2 - 1] = ilet1 = '-';</span>
 +
<span id="line354">354.  else if(ilet2 == '-') {</span>
 +
<span id="line355">355.  bp[--foo2] = ++ilet1;</span>
 +
<span id="line356">356.  continue;</span>
 +
<span id="line357">357.  }</span>
 +
<span id="line358">358.  }</span>
 +
<span id="line359">359.  ilet2 = ilet1;</span>
 +
<span id="line360">360.  ilet1 = ilet;</span>
 +
<span id="line361">361.  }</span>
 +
<span id="line362">362.  }</span>
 +
<span id="line363">363.  if(!foo && !allowall && !allowgold && !allownone) {</span>
 +
<span id="line364">364.  pline("You don't have anything %sto %s.",</span>
 +
<span id="line365">365.  foox ? "else " : "", word);</span>
 +
<span id="line366">366.  return(0);</span>
 +
<span id="line367">367.  }</span>
 +
<span id="line368">368.  for(;;) {</span>
 +
<span id="line369">369.  if(!buf[0]) {</span>
 +
<span id="line370">370.  #ifdef REDO</span>
 +
<span id="line371">371.      if(!in_doagain)</span>
 +
<span id="line372">372.  #endif</span>
 +
<span id="line373">373.  pline("What do you want to %s [*]? ", word);</span>
 +
<span id="line374">374.  } else {</span>
 +
<span id="line375">375.  #ifdef REDO</span>
 +
<span id="line376">376.      if(!in_doagain)</span>
 +
<span id="line377">377.  #endif</span>
 +
<span id="line378">378.  pline("What do you want to %s [%s or ?*]? ",</span>
 +
<span id="line379">379.  word, buf);</span>
 +
<span id="line380">380.  }</span>
 +
<span id="line381">381.  cnt = 0;</span>
 +
<span id="line382">382.  ilet = readchar();</span>
 +
<span id="line383">383.  while(digit(ilet) && allowcnt) {</span>
 +
<span id="line384">384.  #ifdef REDO</span>
 +
<span id="line385">385.  if (ilet != '?' && ilet != '*') savech(ilet);</span>
 +
<span id="line386">386.  #endif</span>
 +
<span id="line387">387.  cnt = 10*cnt + (ilet - '0');</span>
 +
<span id="line388">388.  allowcnt = 2; /* signal presence of cnt */</span>
 +
<span id="line389">389.  ilet = readchar();</span>
 +
<span id="line390">390.  }</span>
 +
<span id="line391">391.  if(digit(ilet)) {</span>
 +
<span id="line392">392.  pline("No count allowed with this command.");</span>
 +
<span id="line393">393.  continue;</span>
 +
<span id="line394">394.  }</span>
 +
<span id="line395">395.  if(index(quitchars,ilet)) {</span>
 +
<span id="line396">396.  pline("Never mind.");</span>
 +
<span id="line397">397.  return((struct obj *)0);</span>
 +
<span id="line398">398.  }</span>
 +
<span id="line399">399.  if(ilet == '-') {</span>
 +
<span id="line400">400.  return(allownone ? &zeroobj : (struct obj *) 0);</span>
 +
<span id="line401">401.  }</span>
 +
<span id="line402">402.  if(ilet == GOLD_SYM) {</span>
 +
<span id="line403">403.  if(!allowgold){</span>
 +
<span id="line404">404.  pline("You cannot %s gold.", word);</span>
 +
<span id="line405">405.  continue;</span>
 +
<span id="line406">406.  }</span>
 +
<span id="line407">407.  if(!(allowcnt == 2 && cnt < u.ugold))</span>
 +
<span id="line408">408.  cnt = u.ugold;</span>
 +
<span id="line409">409.  return(mkgoldobj(cnt));</span>
 +
<span id="line410">410.  }</span>
 +
<span id="line411">411.  if(ilet == '?') {</span>
 +
<span id="line412">412.  doinv(lets);</span>
 +
<span id="line413">413.  if(!(ilet = morc)) continue;</span>
 +
<span id="line414">414.  /* he typed a letter (not a space) to more() */</span>
 +
<span id="line415">415.  } else if(ilet == '*') {</span>
 +
<span id="line416">416.  doinv((char *) 0);</span>
 +
<span id="line417">417.  if(!(ilet = morc)) continue;</span>
 +
<span id="line418">418.  /* ... */</span>
 +
<span id="line419">419.  }</span>
 +
<span id="line420">420.  #ifdef REDO</span>
 +
<span id="line421">421.  if (ilet != '?' && ilet != '*') savech(ilet);</span>
 +
<span id="line422">422.  #endif</span>
 +
<span id="line423">423.  if(flags.invlet_constant) {</span>
 +
<span id="line424">424.  for(otmp = invent; otmp; otmp = otmp->nobj)</span>
 +
<span id="line425">425.  if(otmp->invlet == ilet) break;</span>
 +
<span id="line426">426.  } else {</span>
 +
<span id="line427">427.  if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1;</span>
 +
<span id="line428">428.  ilet -= 'a';</span>
 +
<span id="line429">429.  for(otmp = invent; otmp && ilet;</span>
 +
<span id="line430">430.  ilet--, otmp = otmp->nobj) ;</span>
 +
<span id="line431">431.  }</span>
 +
<span id="line432">432.  if(!otmp) {</span>
 +
<span id="line433">433.  pline("You don't have that object.");</span>
 +
<span id="line434">434.  continue;</span>
 +
<span id="line435">435.  }</span>
 +
<span id="line436">436.  if(cnt < 0 || otmp->quan < cnt) {</span>
 +
<span id="line437">437.  pline("You don't have that many! [You have %u]"</span>
 +
<span id="line438">438.  , otmp->quan);</span>
 +
<span id="line439">439.  continue;</span>
 +
<span id="line440">440.  }</span>
 +
<span id="line441">441.  break;</span>
 +
<span id="line442">442.  }</span>
 +
<span id="line443">443.  if(!allowall && let && !index(let,otmp->olet)) {</span>
 +
<span id="line444">444.  pline("That is a silly thing to %s.",word);</span>
 +
<span id="line445">445.  return(0);</span>
 +
<span id="line446">446.  }</span>
 +
<span id="line447">447.  if(allowcnt == 2) { /* cnt given */</span>
 +
<span id="line448">448.  if(cnt == 0) return(0);</span>
 +
<span id="line449">449.  if(cnt != otmp->quan) {</span>
 +
<span id="line450">450.  register struct obj *obj;</span>
 +
<span id="line451">451.  obj = splitobj(otmp, (int) cnt);</span>
 +
<span id="line452">452.  if(otmp == uwep) setuwep(obj);</span>
 +
<span id="line453">453.  }</span>
 +
<span id="line454">454.  }</span>
 +
<span id="line455">455.  return(otmp);</span>
 +
<span id="line456">456.  }</span>
 +
<span id="line457">457.  </span>
 +
<span id="line458">458.  ckunpaid(otmp) register struct obj *otmp; {</span>
 +
<span id="line459">459.  return( otmp->unpaid );</span>
 +
<span id="line460">460.  }</span>
 +
<span id="line461">461.  </span>
 +
<span id="line462">462.  /* interactive version of getobj - used for Drop and Identify */</span>
 +
<span id="line463">463.  /* return the number of times fn was called successfully */</span>
 +
<span id="line464">464.  ggetobj(word, fn, max)</span>
 +
<span id="line465">465.  char *word;</span>
 +
<span id="line466">466.  int (*fn)(),  max;</span>
 +
<span id="line467">467.  {</span>
 +
<span id="line468">468.  char buf[BUFSZ];</span>
 +
<span id="line469">469.  register char *ip;</span>
 +
<span id="line470">470.  register char sym;</span>
 +
<span id="line471">471.  register int oletct = 0, iletct = 0;</span>
 +
<span id="line472">472.  register boolean allflag = FALSE;</span>
 +
<span id="line473">473.  char olets[20], ilets[20];</span>
 +
<span id="line474">474.  int (*ckfn)() = (int (*)()) 0;</span>
 +
<span id="line475">475.  xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; /* BAH */</span>
 +
<span id="line476">476.  if(!invent && !allowgold){</span>
 +
<span id="line477">477.  pline("You have nothing to %s.", word);</span>
 +
<span id="line478">478.  return(0);</span>
 +
<span id="line479">479.  } else {</span>
 +
<span id="line480">480.  register struct obj *otmp = invent;</span>
 +
<span id="line481">481.  register int uflg = 0;</span>
 +
<span id="line482">482.  </span>
 +
<span id="line483">483.  if(allowgold) ilets[iletct++] = GOLD_SYM;</span>
 +
<span id="line484">484.  ilets[iletct] = 0;</span>
 +
<span id="line485">485.  while(otmp) {</span>
 +
<span id="line486">486.  if(!index(ilets, otmp->olet)){</span>
 +
<span id="line487">487.  ilets[iletct++] = otmp->olet;</span>
 +
<span id="line488">488.  ilets[iletct] = 0;</span>
 +
<span id="line489">489.  }</span>
 +
<span id="line490">490.  if(otmp->unpaid) uflg = 1;</span>
 +
<span id="line491">491.  otmp = otmp->nobj;</span>
 +
<span id="line492">492.  }</span>
 +
<span id="line493">493.  ilets[iletct++] = ' ';</span>
 +
<span id="line494">494.  if(uflg) ilets[iletct++] = 'u';</span>
 +
<span id="line495">495.  if(invent) ilets[iletct++] = 'a';</span>
 +
<span id="line496">496.  ilets[iletct] = 0;</span>
 +
<span id="line497">497.  }</span>
 +
<span id="line498">498.  pline("What kinds of thing do you want to %s? [%s] ",</span>
 +
<span id="line499">499.  word, ilets);</span>
 +
<span id="line500">500.  getlin(buf);</span>
 +
<span id="line501">501.  if(buf[0] == '\033') {</span>
 +
<span id="line502">502.  clrlin();</span>
 +
<span id="line503">503.  return(0);</span>
 +
<span id="line504">504.  }</span>
 +
<span id="line505">505.  ip = buf;</span>
 +
<span id="line506">506.  olets[0] = 0;</span>
 +
<span id="line507">507.  while(sym = *ip++){</span>
 +
<span id="line508">508.  if(sym == ' ') continue;</span>
 +
<span id="line509">509.  if(sym == GOLD_SYM) {</span>
 +
<span id="line510">510.  if(allowgold == 1)</span>
 +
<span id="line511">511.  (*fn)(mkgoldobj(u.ugold));</span>
 +
<span id="line512">512.  else if(!u.ugold)</span>
 +
<span id="line513">513.  pline("You have no gold.");</span>
 +
<span id="line514">514.  allowgold = 2;</span>
 +
<span id="line515">515.  } else</span>
 +
<span id="line516">516.  if(sym == 'a' || sym == 'A') allflag = TRUE; else</span>
 +
<span id="line517">517.  if(sym == 'u' || sym == 'U') ckfn = ckunpaid; else</span>
 +
<span id="line518">518.  #ifdef SPELLS</span>
 +
<span id="line519">519.  if(index("!%?[()=*/+\"0", sym)){</span>
 +
<span id="line520">520.  #else</span>
 +
<span id="line521">521.  if(index("!%?[()=*/\"0", sym)){</span>
 +
<span id="line522">522.  #endif</span>
 +
<span id="line523">523.  if(!index(olets, sym)){</span>
 +
<span id="line524">524.  olets[oletct++] = sym;</span>
 +
<span id="line525">525.  olets[oletct] = 0;</span>
 +
<span id="line526">526.  }</span>
 +
<span id="line527">527.  }</span>
 +
<span id="line528">528.  else pline("You don't have any %c's.", sym);</span>
 +
<span id="line529">529.  }</span>
 +
<span id="line530">530.  if(allowgold == 2 && !oletct)</span>
 +
<span id="line531">531.  return(1); /* he dropped gold (or at least tried to) */</span>
 +
<span id="line532">532.  else</span>
 +
<span id="line533">533.  return(askchain(invent, olets, allflag, fn, ckfn, max));</span>
 +
<span id="line534">534.  }</span>
 +
<span id="line535">535.  </span>
 +
<span id="line536">536.  /*</span>
 +
<span id="line537">537.  * Walk through the chain starting at objchn and ask for all objects</span>
 +
<span id="line538">538.  * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL)</span>
 +
<span id="line539">539.  * whether the action in question (i.e., fn) has to be performed.</span>
 +
<span id="line540">540.  * If allflag then no questions are asked. Max gives the max nr of</span>
 +
<span id="line541">541.  * objects to be treated. Return the number of objects treated.</span>
 +
<span id="line542">542.  */</span>
 +
<span id="line543">543.  askchain(objchn, olets, allflag, fn, ckfn, max)</span>
 +
<span id="line544">544.  struct obj *objchn;</span>
 +
<span id="line545">545.  register char *olets;</span>
 +
<span id="line546">546.  int allflag;</span>
 +
<span id="line547">547.  int (*fn)(), (*ckfn)();</span>
 +
<span id="line548">548.  int max;</span>
 +
<span id="line549">549.  {</span>
 +
<span id="line550">550.  register struct obj *otmp, *otmp2;</span>
 +
<span id="line551">551.  register char sym, ilet;</span>
 +
<span id="line552">552.  register int cnt = 0;</span>
 +
<span id="line553">553.  #ifdef SORTING</span>
 +
<span id="line554">554.  /* changes so the askchain is interrogated in the order specified.</span>
 +
<span id="line555">555.  * For example, if a person specifies =/ then first all rings will be</span>
 +
<span id="line556">556.  * asked about followed by all wands -dgk</span>
 +
<span id="line557">557.  */</span>
 +
<span id="line558">558.  nextclass:</span>
 +
<span id="line559">559.  #endif</span>
 +
<span id="line560">560.  ilet = 'a'-1;</span>
 +
<span id="line561">561.  for(otmp = objchn; otmp; otmp = otmp2){</span>
 +
<span id="line562">562.  if(ilet == 'z') ilet = 'A'; else ilet++;</span>
 +
<span id="line563">563.  otmp2 = otmp->nobj;</span>
 +
<span id="line564">564.  #ifdef SORTING</span>
 +
<span id="line565">565.  if (olets && *olets && otmp->olet != *olets) continue;</span>
 +
<span id="line566">566.  #else</span>
 +
<span id="line567">567.  if(olets && *olets && !index(olets, otmp->olet)) continue;</span>
 +
<span id="line568">568.  #endif</span>
 +
<span id="line569">569.  if(ckfn && !(*ckfn)(otmp)) continue;</span>
 +
<span id="line570">570.  if(!allflag) {</span>
 +
<span id="line571">571.  pline(xprname(otmp, ilet));</span>
 +
<span id="line572">572.  addtopl(" [nyaq]? ");</span>
 +
<span id="line573">573.  sym = readchar();</span>
 +
<span id="line574">574.  }</span>
 +
<span id="line575">575.  else sym = 'y';</span>
 +
<span id="line576">576.  </span>
 +
<span id="line577">577.  switch(sym){</span>
 +
<span id="line578">578.  case 'a':</span>
 +
<span id="line579">579.  allflag = 1;</span>
 +
<span id="line580">580.  case 'y':</span>
 +
<span id="line581">581.  cnt += (*fn)(otmp);</span>
 +
<span id="line582">582.  if(--max == 0) goto ret;</span>
 +
<span id="line583">583.  case 'n':</span>
 +
<span id="line584">584.  default:</span>
 +
<span id="line585">585.  break;</span>
 +
<span id="line586">586.  case 'q':</span>
 +
<span id="line587">587.  goto ret;</span>
 +
<span id="line588">588.  }</span>
 +
<span id="line589">589.  }</span>
 +
<span id="line590">590.  #ifdef SORTING</span>
 +
<span id="line591">591.  if (olets && *olets && *++olets)</span>
 +
<span id="line592">592.  goto nextclass;</span>
 +
<span id="line593">593.  #endif</span>
 +
<span id="line594">594.  pline(cnt ? "That was all." : "No applicable objects.");</span>
 +
<span id="line595">595.  ret:</span>
 +
<span id="line596">596.  return(cnt);</span>
 +
<span id="line597">597.  }</span>
 +
<span id="line598">598.  </span>
 +
<span id="line599">599.  obj_to_let(obj) /* should of course only be called for things in invent */</span>
 +
<span id="line600">600.  register struct obj *obj;</span>
 +
<span id="line601">601.  {</span>
 +
<span id="line602">602.  register struct obj *otmp;</span>
 +
<span id="line603">603.  register char ilet;</span>
 +
<span id="line604">604.  </span>
 +
<span id="line605">605.  if(flags.invlet_constant)</span>
 +
<span id="line606">606.  return(obj->invlet);</span>
 +
<span id="line607">607.  ilet = 'a';</span>
 +
<span id="line608">608.  for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj)</span>
 +
<span id="line609">609.  if(++ilet > 'z') ilet = 'A';</span>
 +
<span id="line610">610.  return(otmp ? ilet : NOINVSYM);</span>
 +
<span id="line611">611.  }</span>
 +
<span id="line612">612.  </span>
 +
<span id="line613">613.  prinv(obj)</span>
 +
<span id="line614">614.  register struct obj *obj;</span>
 +
<span id="line615">615.  {</span>
 +
<span id="line616">616.  pline(xprname(obj, obj_to_let(obj)));</span>
 +
<span id="line617">617.  }</span>
 +
<span id="line618">618.  </span>
 +
<span id="line619">619.  static char *</span>
 +
<span id="line620">620.  xprname(obj,let)</span>
 +
<span id="line621">621.  register struct obj *obj;</span>
 +
<span id="line622">622.  register char let;</span>
 +
<span id="line623">623.  {</span>
 +
<span id="line624">624.  static char li[BUFSZ];</span>
 +
<span id="line625">625.  </span>
 +
<span id="line626">626.  (void) sprintf(li, "%c - %s.",</span>
 +
<span id="line627">627.  flags.invlet_constant ? obj->invlet : let,</span>
 +
<span id="line628">628.  doname(obj));</span>
 +
<span id="line629">629.  return(li);</span>
 +
<span id="line630">630.  }</span>
 +
<span id="line631">631.  </span>
 +
<span id="line632">632.  ddoinv()</span>
 +
<span id="line633">633.  {</span>
 +
<span id="line634">634.  doinv((char *) 0);</span>
 +
<span id="line635">635.  return(0);</span>
 +
<span id="line636">636.  }</span>
 +
<span id="line637">637.  </span>
 +
<span id="line638">638.  #ifdef SORTING</span>
 +
<span id="line639">639.  # ifdef SPELLS</span>
 +
<span id="line640">640.  char inv_order[] = "\")[%?+/=!(*0_`"; /* to be safe, include _ and ` */</span>
 +
<span id="line641">641.  # else</span>
 +
<span id="line642">642.  char inv_order[] = "\")[%?/=!(*0_`";</span>
 +
<span id="line643">643.  # endif</span>
 +
<span id="line644">644.  extern char *let_to_name();</span>
 +
<span id="line645">645.  #endif</span>
 +
<span id="line646">646.  </span>
 +
<span id="line647">647.  /* called with 0 or "": all objects in inventory */</span>
 +
<span id="line648">648.  /* otherwise: all objects with (serial) letter in lets */</span>
 +
<span id="line649">649.  doinv(lets)</span>
 +
<span id="line650">650.  register char *lets;</span>
 +
<span id="line651">651.  {</span>
 +
<span id="line652">652.  register struct obj *otmp;</span>
 +
<span id="line653">653.  register char ilet;</span>
 +
<span id="line654">654.  int ct = 0;</span>
 +
<span id="line655">655.  char any[BUFSZ];</span>
 +
<span id="line656">656.  #ifdef SORTING</span>
 +
<span id="line657">657.  char *invlet = inv_order;</span>
 +
<span id="line658">658.  int classcount = 0;</span>
 +
<span id="line659">659.  #endif /* SORTING /**/</span>
 +
<span id="line660">660.  </span>
 +
<span id="line661">661.  morc = 0; /* just to be sure */</span>
 +
<span id="line662">662.  </span>
 +
<span id="line663">663.  if(!invent){</span>
 +
<span id="line664">664.  pline("Not carrying anything.");</span>
 +
<span id="line665">665.  return;</span>
 +
<span id="line666">666.  }</span>
 +
<span id="line667">667.  </span>
 +
<span id="line668">668.  cornline(0, (char *) 0);</span>
 +
<span id="line669">669.  #ifdef SORTING</span>
 +
<span id="line670">670.  nextclass:</span>
 +
<span id="line671">671.  classcount = 0;</span>
 +
<span id="line672">672.  ilet = 'a';</span>
 +
<span id="line673">673.  for(otmp = invent; otmp; otmp = otmp->nobj) {</span>
 +
<span id="line674">674.  if(flags.invlet_constant) ilet = otmp->invlet;</span>
 +
<span id="line675">675.  if(!lets || !*lets || index(lets, ilet)) {</span>
 +
<span id="line676">676.  if (!flags.sortpack || otmp->olet == *invlet) {</span>
 +
<span id="line677">677.  if (flags.sortpack && !classcount) {</span>
 +
<span id="line678">678.  cornline(1, let_to_name(*invlet));</span>
 +
<span id="line679">679.  classcount++;</span>
 +
<span id="line680">680.  }</span>
 +
<span id="line681">681.  cornline(1, xprname(otmp, ilet));</span>
 +
<span id="line682">682.  any[ct++] = ilet;</span>
 +
<span id="line683">683.  }</span>
 +
<span id="line684">684.  }</span>
 +
<span id="line685">685.  if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';</span>
 +
<span id="line686">686.  }</span>
 +
<span id="line687">687.  if (flags.sortpack && *++invlet) goto nextclass;</span>
 +
<span id="line688">688.  #else</span>
 +
<span id="line689">689.  ilet = 'a';</span>
 +
<span id="line690">690.  for(otmp = invent; otmp; otmp = otmp->nobj) {</span>
 +
<span id="line691">691.      if(flags.invlet_constant) ilet = otmp->invlet;</span>
 +
<span id="line692">692.      if(!lets || !*lets || index(lets, ilet)) {</span>
 +
<span id="line693">693.      cornline(1, xprname(otmp, ilet));</span>
 +
<span id="line694">694.      any[ct++] = ilet;</span>
 +
<span id="line695">695.      }</span>
 +
<span id="line696">696.      if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';</span>
 +
<span id="line697">697.  }</span>
 +
<span id="line698">698.  #endif /* SORTING /**/</span>
 +
<span id="line699">699.  any[ct] = 0;</span>
 +
<span id="line700">700.  cornline(2, any);</span>
 +
<span id="line701">701.  }</span>
 +
<span id="line702">702.  </span>
 +
<span id="line703">703.  dotypeinv () /* free after Robert Viduya */</span>
 +
<span id="line704">704.  /* Changed to one type only, so he doesnt have to type cr */</span>
 +
<span id="line705">705.  {</span>
 +
<span id="line706">706.      char c, ilet;</span>
 +
<span id="line707">707.      char stuff[BUFSZ];</span>
 +
<span id="line708">708.      register int stct;</span>
 +
<span id="line709">709.      register struct obj *otmp;</span>
 +
<span id="line710">710.      boolean billx = inshop() && doinvbill(0);</span>
 +
<span id="line711">711.      boolean unpd = FALSE;</span>
 +
<span id="line712">712.  </span>
 +
<span id="line713">713.  if (!invent && !u.ugold && !billx) {</span>
 +
<span id="line714">714.      pline ("You aren't carrying anything.");</span>
 +
<span id="line715">715.      return(0);</span>
 +
<span id="line716">716.  }</span>
 +
<span id="line717">717.  </span>
 +
<span id="line718">718.  stct = 0;</span>
 +
<span id="line719">719.  if(u.ugold) stuff[stct++] = GOLD_SYM;</span>
 +
<span id="line720">720.  stuff[stct] = 0;</span>
 +
<span id="line721">721.  for(otmp = invent; otmp; otmp = otmp->nobj) {</span>
 +
<span id="line722">722.      if (!index (stuff, otmp->olet)) {</span>
 +
<span id="line723">723.  stuff[stct++] = otmp->olet;</span>
 +
<span id="line724">724.  stuff[stct] = 0;</span>
 +
<span id="line725">725.      }</span>
 +
<span id="line726">726.      if(otmp->unpaid)</span>
 +
<span id="line727">727.  unpd = TRUE;</span>
 +
<span id="line728">728.  }</span>
 +
<span id="line729">729.  if(unpd) stuff[stct++] = 'u';</span>
 +
<span id="line730">730.  if(billx) stuff[stct++] = 'x';</span>
 +
<span id="line731">731.  stuff[stct] = 0;</span>
 +
<span id="line732">732.  </span>
 +
<span id="line733">733.  if(stct > 1) {</span>
 +
<span id="line734">734.  #ifdef REDO</span>
 +
<span id="line735">735.    if (!in_doagain)</span>
 +
<span id="line736">736.  #endif</span>
 +
<span id="line737">737.      pline ("What type of object [%s] do you want an inventory of? ",</span>
 +
<span id="line738">738.  stuff);</span>
 +
<span id="line739">739.      c = readchar();</span>
 +
<span id="line740">740.  #ifdef REDO</span>
 +
<span id="line741">741.      savech(c);</span>
 +
<span id="line742">742.  #endif</span>
 +
<span id="line743">743.      if(index(quitchars,c)) return(0);</span>
 +
<span id="line744">744.  } else</span>
 +
<span id="line745">745.      c = stuff[0];</span>
 +
<span id="line746">746.  </span>
 +
<span id="line747">747.  if(c == GOLD_SYM)</span>
 +
<span id="line748">748.      return(doprgold());</span>
 +
<span id="line749">749.  </span>
 +
<span id="line750">750.  if(c == 'x' || c == 'X') {</span>
 +
<span id="line751">751.      if(billx)</span>
 +
<span id="line752">752.  (void) doinvbill(1);</span>
 +
<span id="line753">753.      else</span>
 +
<span id="line754">754.  pline("No used-up objects on the shopping bill.");</span>
 +
<span id="line755">755.      return(0);</span>
 +
<span id="line756">756.  }</span>
 +
<span id="line757">757.  </span>
 +
<span id="line758">758.  if((c == 'u' || c == 'U') && !unpd) {</span>
 +
<span id="line759">759.  pline("You are not carrying any unpaid objects.");</span>
 +
<span id="line760">760.  return(0);</span>
 +
<span id="line761">761.  }</span>
 +
<span id="line762">762.  </span>
 +
<span id="line763">763.  stct = 0;</span>
 +
<span id="line764">764.  ilet = 'a';</span>
 +
<span id="line765">765.  for (otmp = invent; otmp; otmp = otmp -> nobj) {</span>
 +
<span id="line766">766.      if(flags.invlet_constant) ilet = otmp->invlet;</span>
 +
<span id="line767">767.      if (c == otmp -> olet || (c == 'u' && otmp -> unpaid))</span>
 +
<span id="line768">768.  stuff[stct++] = ilet;</span>
 +
<span id="line769">769.      if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';</span>
 +
<span id="line770">770.  }</span>
 +
<span id="line771">771.  stuff[stct] = '\0';</span>
 +
<span id="line772">772.  if(stct == 0)</span>
 +
<span id="line773">773.  pline("You have no such objects.");</span>
 +
<span id="line774">774.  else</span>
 +
<span id="line775">775.  doinv (stuff);</span>
 +
<span id="line776">776.  </span>
 +
<span id="line777">777.  return(0);</span>
 +
<span id="line778">778.  }</span>
 +
<span id="line779">779.  </span>
 +
<span id="line780">780.  /* look at what is here */</span>
 +
<span id="line781">781.  dolook() {</span>
 +
<span id="line782">782.      register struct obj *otmp, *otmp0;</span>
 +
<span id="line783">783.      register struct gold *gold;</span>
 +
<span id="line784">784.      char *verb = Blind ? "feel" : "see";</span>
 +
<span id="line785">785.      int ct = 0;</span>
 +
<span id="line786">786.      int fd = 0;</span>
 +
<span id="line787">787.  </span>
 +
<span id="line788">788.  #ifdef KAA</span>
 +
<span id="line789">789.      read_engr_at(u.ux, u.uy); /* Eric Backus */</span>
 +
<span id="line790">790.  #endif</span>
 +
<span id="line791">791.      if(!u.uswallow) {</span>
 +
<span id="line792">792.  otmp0 = o_at(u.ux, u.uy);</span>
 +
<span id="line793">793.  gold = g_at(u.ux, u.uy);</span>
 +
<span id="line794">794.      }  else  {</span>
 +
<span id="line795">795.  pline("You %s no objects here.", verb);</span>
 +
<span id="line796">796.  return(!!Blind);</span>
 +
<span id="line797">797.      }</span>
 +
<span id="line798">798.  </span>
 +
<span id="line799">799.      /* added by GAN 10/30/86 */</span>
 +
<span id="line800">800.  #ifdef FOUNTAINS</span>
 +
<span id="line801">801.      if(IS_FOUNTAIN(levl[u.ux][u.uy].typ))  {</span>
 +
<span id="line802">802.  fd++;</span>
 +
<span id="line803">803.  pline("There is a fountain here.");</span>
 +
<span id="line804">804.      }</span>
 +
<span id="line805">805.  #endif</span>
 +
<span id="line806">806.  #ifdef NEWCLASS</span>
 +
<span id="line807">807.      if(IS_THRONE(levl[u.ux][u.uy].typ))  {</span>
 +
<span id="line808">808.  fd++;</span>
 +
<span id="line809">809.  pline("There is an opulent throne here.");</span>
 +
<span id="line810">810.      }    </span>
 +
<span id="line811">811.  #endif</span>
 +
<span id="line812">812.      if(u.ux == xupstair && u.uy == yupstair)  {</span>
 +
<span id="line813">813.  fd++;</span>
 +
<span id="line814">814.  pline("There is a stairway up here.");</span>
 +
<span id="line815">815.      }</span>
 +
<span id="line816">816.      if(u.ux == xdnstair && u.uy == ydnstair)  {</span>
 +
<span id="line817">817.  fd++;</span>
 +
<span id="line818">818.  cornline(1, "There is a stairway down here.");</span>
 +
<span id="line819">819.      }</span>
 +
<span id="line820">820.      if(Blind)  {</span>
 +
<span id="line821">821.  pline("You try to feel what is lying here on the floor.");</span>
 +
<span id="line822">822.  if(Levitation)  {</span>
 +
<span id="line823">823.  pline("But you can't reach it!");</span>
 +
<span id="line824">824.  return(0);</span>
 +
<span id="line825">825.  }</span>
 +
<span id="line826">826.      }</span>
 +
<span id="line827">827.  </span>
 +
<span id="line828">828.      if(!otmp0 && !gold) {</span>
 +
<span id="line829">829.  if(Blind || !fd)</span>
 +
<span id="line830">830.  pline("You %s no objects here.", verb);</span>
 +
<span id="line831">831.  return(!!Blind);</span>
 +
<span id="line832">832.      }</span>
 +
<span id="line833">833.  </span>
 +
<span id="line834">834.      cornline(0, "Things that are here:");</span>
 +
<span id="line835">835.      for(otmp = otmp0; otmp; otmp = otmp->nobj) {</span>
 +
<span id="line836">836.  if(otmp->ox == u.ux && otmp->oy == u.uy) {</span>
 +
<span id="line837">837.      ct++;</span>
 +
<span id="line838">838.      cornline(1, doname(otmp));</span>
 +
<span id="line839">839.      if(Blind && otmp->otyp == DEAD_COCKATRICE && !uarmg) {</span>
 +
<span id="line840">840.  pline("Touching the dead cockatrice is a fatal mistake ...");</span>
 +
<span id="line841">841.  pline("You die ...");</span>
 +
<span id="line842">842.  killer = "dead cockatrice";</span>
 +
<span id="line843">843.  done("died");</span>
 +
<span id="line844">844.      }</span>
 +
<span id="line845">845.  }</span>
 +
<span id="line846">846.      }</span>
 +
<span id="line847">847.  </span>
 +
<span id="line848">848.      if(gold) {</span>
 +
<span id="line849">849.  char gbuf[30];</span>
 +
<span id="line850">850.  </span>
 +
<span id="line851">851.  (void) sprintf(gbuf, "%ld gold piece%s",</span>
 +
<span id="line852">852.  gold->amount, plur(gold->amount));</span>
 +
<span id="line853">853.  if(!ct++)</span>
 +
<span id="line854">854.      pline("You %s here %s.", verb, gbuf);</span>
 +
<span id="line855">855.  else</span>
 +
<span id="line856">856.      cornline(1, gbuf);</span>
 +
<span id="line857">857.      }</span>
 +
<span id="line858">858.  </span>
 +
<span id="line859">859.      if(ct == 1 && !gold) {</span>
 +
<span id="line860">860.  pline("You %s here %s.", verb, doname(otmp0));</span>
 +
<span id="line861">861.  cornline(3, (char *) 0);</span>
 +
<span id="line862">862.      }</span>
 +
<span id="line863">863.      if(ct > 1)</span>
 +
<span id="line864">864.  cornline(2, (char *) 0);</span>
 +
<span id="line865">865.      return(!!Blind);</span>
 +
<span id="line866">866.  }</span>
 +
<span id="line867">867.  </span>
 +
<span id="line868">868.  stackobj(obj) register struct obj *obj; {</span>
 +
<span id="line869">869.  register struct obj *otmp = fobj;</span>
 +
<span id="line870">870.  for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj)</span>
 +
<span id="line871">871.  if(otmp->ox == obj->ox && otmp->oy == obj->oy &&</span>
 +
<span id="line872">872.  merged(obj,otmp,1))</span>
 +
<span id="line873">873.  return;</span>
 +
<span id="line874">874.  }</span>
 +
<span id="line875">875.  </span>
 +
<span id="line876">876.  /* merge obj with otmp and delete obj if types agree */</span>
 +
<span id="line877">877.  merged(otmp,obj,lose) register struct obj *otmp, *obj; {</span>
 +
<span id="line878">878.  if(obj->otyp == otmp->otyp &&</span>
 +
<span id="line879">879.    obj->unpaid == otmp->unpaid &&</span>
 +
<span id="line880">880.    obj->spe == otmp->spe &&</span>
 +
<span id="line881">881.    obj->dknown == otmp->dknown &&</span>
 +
<span id="line882">882.    obj->cursed == otmp->cursed &&</span>
 +
<span id="line883">883.  #ifdef SPELLS</span>
 +
<span id="line884">884.    (index("%*?!+", obj->olet) ||</span>
 +
<span id="line885">885.  #else</span>
 +
<span id="line886">886.    (index("%*?!", obj->olet) ||</span>
 +
<span id="line887">887.  #endif</span>
 +
<span id="line888">888.      (obj->known == otmp->known &&</span>
 +
<span id="line889">889.  (obj->olet == WEAPON_SYM && obj->otyp < BOOMERANG)))) {</span>
 +
<span id="line890">890.  otmp->quan += obj->quan;</span>
 +
<span id="line891">891.  otmp->owt += obj->owt;</span>
 +
<span id="line892">892.  if(lose) freeobj(obj);</span>
 +
<span id="line893">893.  obfree(obj,otmp); /* free(obj), bill->otmp */</span>
 +
<span id="line894">894.  return(1);</span>
 +
<span id="line895">895.  } else return(0);</span>
 +
<span id="line896">896.  }</span>
 +
<span id="line897">897.  </span>
 +
<span id="line898">898.  /*</span>
 +
<span id="line899">899.  * Gold is no longer displayed; in fact, when you have a lot of money,</span>
 +
<span id="line900">900.  * it may take a while before you have counted it all.</span>
 +
<span id="line901">901.  * [Bug: d$ and pickup still tell you how much it was.]</span>
 +
<span id="line902">902.  */</span>
 +
<span id="line903">903.  extern int (*occupation)();</span>
 +
<span id="line904">904.  extern char *occtxt;</span>
 +
<span id="line905">905.  static long goldcounted;</span>
 +
<span id="line906">906.  </span>
 +
<span id="line907">907.  countgold(){</span>
 +
<span id="line908">908.  if((goldcounted += 100*(u.ulevel + 1)) >= u.ugold) {</span>
 +
<span id="line909">909.  long eps = 0;</span>
 +
<span id="line910">910.  if(!rn2(2)) eps = rnd((int) (u.ugold/100 + 1));</span>
 +
<span id="line911">911.  pline("You probably have about %ld gold pieces.",</span>
 +
<span id="line912">912.  u.ugold + eps);</span>
 +
<span id="line913">913.  return(0); /* done */</span>
 +
<span id="line914">914.  }</span>
 +
<span id="line915">915.  return(1); /* continue */</span>
 +
<span id="line916">916.  }</span>
 +
<span id="line917">917.  </span>
 +
<span id="line918">918.  doprgold(){</span>
 +
<span id="line919">919.  if(!u.ugold)</span>
 +
<span id="line920">920.  pline("You do not carry any gold.");</span>
 +
<span id="line921">921.  else if(u.ugold <= 500)</span>
 +
<span id="line922">922.  pline("You are carrying %ld gold piece%s.", u.ugold, plur(u.ugold));</span>
 +
<span id="line923">923.  else {</span>
 +
<span id="line924">924.  pline("You sit down in order to count your gold pieces.");</span>
 +
<span id="line925">925.  goldcounted = 500;</span>
 +
<span id="line926">926.  occupation = countgold;</span>
 +
<span id="line927">927.  occtxt = "counting your gold";</span>
 +
<span id="line928">928.  }</span>
 +
<span id="line929">929.  return(1);</span>
 +
<span id="line930">930.  }</span>
 +
<span id="line931">931.  </span>
 +
<span id="line932">932.  /* --- end of gold counting section --- */</span>
 +
<span id="line933">933.  </span>
 +
<span id="line934">934.  doprwep(){</span>
 +
<span id="line935">935.  if(!uwep) pline("You are empty handed.");</span>
 +
<span id="line936">936.  else prinv(uwep);</span>
 +
<span id="line937">937.  return(0);</span>
 +
<span id="line938">938.  }</span>
 +
<span id="line939">939.  </span>
 +
<span id="line940">940.  doprarm(){</span>
 +
<span id="line941">941.  if(!uarm && !uarmg && !uarms && !uarmh)</span>
 +
<span id="line942">942.  pline("You are not wearing any armor.");</span>
 +
<span id="line943">943.  else {</span>
 +
<span id="line944">944.  char lets[6];</span>
 +
<span id="line945">945.  register int ct = 0;</span>
 +
<span id="line946">946.  </span>
 +
<span id="line947">947.  if(uarm) lets[ct++] = obj_to_let(uarm);</span>
 +
<span id="line948">948.  if(uarm2) lets[ct++] = obj_to_let(uarm2);</span>
 +
<span id="line949">949.  if(uarmh) lets[ct++] = obj_to_let(uarmh);</span>
 +
<span id="line950">950.  if(uarms) lets[ct++] = obj_to_let(uarms);</span>
 +
<span id="line951">951.  if(uarmg) lets[ct++] = obj_to_let(uarmg);</span>
 +
<span id="line952">952.  lets[ct] = 0;</span>
 +
<span id="line953">953.  doinv(lets);</span>
 +
<span id="line954">954.  }</span>
 +
<span id="line955">955.  return(0);</span>
 +
<span id="line956">956.  }</span>
 +
<span id="line957">957.  </span>
 +
<span id="line958">958.  doprring(){</span>
 +
<span id="line959">959.  if(!uleft && !uright)</span>
 +
<span id="line960">960.  pline("You are not wearing any rings.");</span>
 +
<span id="line961">961.  else {</span>
 +
<span id="line962">962.  char lets[3];</span>
 +
<span id="line963">963.  register int ct = 0;</span>
 +
<span id="line964">964.  </span>
 +
<span id="line965">965.  if(uleft) lets[ct++] = obj_to_let(uleft);</span>
 +
<span id="line966">966.  if(uright) lets[ct++] = obj_to_let(uright);</span>
 +
<span id="line967">967.  lets[ct] = 0;</span>
 +
<span id="line968">968.  doinv(lets);</span>
 +
<span id="line969">969.  }</span>
 +
<span id="line970">970.  return(0);</span>
 +
<span id="line971">971.  }</span>
 +
<span id="line972">972.  </span>
 +
<span id="line973">973. digit(c) char c; {</span>
 +
<span id="line974">974.  return(c >= '0' && c <= '9');</span>
 +
<span id="line975">975.  }</span>
 +
<span id="line976">976.  </span>
 +
<span id="line977">977.  /*</span>
 +
<span id="line978">978.  * useupf(obj)</span>
 +
<span id="line979">979.  * uses up an object that's on the floor</span>
 +
<span id="line980">980.  */</span>
 +
<span id="line981">981.  useupf(obj)</span>
 +
<span id="line982">982.  register struct obj *obj;</span>
 +
<span id="line983">983.  {</span>
 +
<span id="line984">984.  if(obj->quan > 1)  {</span>
 +
<span id="line985">985.  obj->quan--;</span>
 +
<span id="line986">986.  obj->owt = weight(obj);</span>
 +
<span id="line987">987.  }  else delobj(obj);</span>
 +
<span id="line988">988.  }</span>
 +
<span id="line989">989.  </span>
 +
<span id="line990">990.  #ifdef SORTING</span>
 +
<span id="line991">991.  /*</span>
 +
<span id="line992">992.  * Convert from a symbol to a string for printing object classes</span>
 +
<span id="line993">993.  *</span>
 +
<span id="line994">994.  * Names from objects.h</span>
 +
<span id="line995">995.  * char obj_symbols[] = {</span>
 +
<span id="line996">996.  * ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM,</span>
 +
<span id="line997">997.  * BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM,</span>
 +
<span id="line998">998.  * WAND_SYM, [SPBOOK_SYM], RING_SYM, GEM_SYM, 0 };</span>
 +
<span id="line999">999.   */</span>
 +
<span id="line1000">1000. #define Sprintf (void) sprintf</span>
 +
<span id="line1001">1001. </span>
 +
<span id="line1002">1002. extern char obj_symbols[];</span>
 +
<span id="line1003">1003. static char *names[] = {"Illegal objects", "Amulets", "Comestibles", "Weapons",</span>
 +
<span id="line1004">1004. "Tools", "Iron balls", "Chains", "Rocks", "Armor",</span>
 +
<span id="line1005">1005. "Potions", "Scrolls", "Wands",</span>
 +
<span id="line1006">1006. #ifdef SPELLS</span>
 +
<span id="line1007">1007. "Spellbooks",</span>
 +
<span id="line1008">1008. #endif</span>
 +
<span id="line1009">1009. "Rings", "Gems"};</span>
 +
<span id="line1010">1010. char *</span>
 +
<span id="line1011">1011. let_to_name(let)</span>
 +
<span id="line1012">1012. char let;</span>
 +
<span id="line1013">1013. {</span>
 +
<span id="line1014">1014. char *pos = index(obj_symbols, let);</span>
 +
<span id="line1015">1015. extern char *HI, *HE;</span>
 +
<span id="line1016">1016. /* buffer size is len(HI) + len(HE) + max(len(names[])) + 1 */</span>
 +
<span id="line1017">1017. static char buf[4 + 4 + 15 + 1];</span>
 +
<span id="line1018">1018. </span>
 +
<span id="line1019">1019. if (pos == NULL) pos = obj_symbols;</span>
 +
<span id="line1020">1020. if (HI && HE)</span>
 +
<span id="line1021">1021.     Sprintf(buf, "%s%s%s", HI, names[pos - obj_symbols], HE);</span>
 +
<span id="line1022">1022. else</span>
 +
<span id="line1023">1023.     Sprintf(buf, "%s", names[pos - obj_symbols]);</span>
 +
<span id="line1024">1024. return (buf);</span>
 +
<span id="line1025">1025. }</span>
 +
<span id="line1026">1026. #endif /* SORTING /**/</span>
 +
[[Category:NetHack 1.4f source code|invent.c]]

Revision as of 21:31, 10 September 2006

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

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

The Harlow distribution of NetHack 1.4f does not contain this file; it contains one identical to its counterpart in NetHack 1.3d. This is probably due to difficulties in applying the original patch as distributed on Usenet. See How to apply the NetHack 1.4f patch for instructions to obtain this file.

Screenshots and source code from Hack are used under the CWI license.

1.    /*	SCCS Id: @(#)invent.c	1.4	87/08/08
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* invent.c - version 1.0.3 */
4.    
5.    #include	<stdio.h>
6.    #include	"hack.h"
7.    extern struct obj *splitobj();
8.    extern struct obj zeroobj;
9.    extern char morc;
10.   extern char quitchars[];
11.   static char *xprname();
12.   
13.   #ifndef NOWORM
14.   #include	"wseg.h"
15.   extern struct wseg *wsegs[32];
16.   #endif
17.   
18.   #define	NOINVSYM	'#'
19.   
20.   int lastinvnr = 51;	/* 0 ... 51 */
21.   
22.   static
23.   assigninvlet(otmp)
24.   register struct obj *otmp;
25.   {
26.   	boolean inuse[52];
27.   	register int i;
28.   	register struct obj *obj;
29.   
30.   	for(i = 0; i < 52; i++) inuse[i] = FALSE;
31.   	for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
32.   		i = obj->invlet;
33.   		if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
34.   		if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
35.   		if(i == otmp->invlet) otmp->invlet = 0;
36.   	}
37.   	if((i = otmp->invlet) &&
38.   	    (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
39.   		return;
40.   	for(i = lastinvnr+1; i != lastinvnr; i++) {
41.   		if(i == 52) { i = -1; continue; }
42.   		if(!inuse[i]) break;
43.   	}
44.   	otmp->invlet = (inuse[i] ? NOINVSYM :
45.   			(i < 26) ? ('a'+i) : ('A'+i-26));
46.   	lastinvnr = i;
47.   }
48.   
49.   struct obj *
50.   addinv(obj)
51.   register struct obj *obj;
52.   {
53.   	register struct obj *otmp;
54.   
55.   	/* merge or attach to end of chain */
56.   	if(!invent) {
57.   		invent = obj;
58.   		otmp = 0;
59.   	} else
60.   	for(otmp = invent; /* otmp */; otmp = otmp->nobj) {
61.   		if(merged(otmp, obj, 0))
62.   			return(otmp);
63.   		if(!otmp->nobj) {
64.   			otmp->nobj = obj;
65.   			break;
66.   		}
67.   	}
68.   	obj->nobj = 0;
69.   
70.   	if(flags.invlet_constant) {
71.   		assigninvlet(obj);
72.   		/*
73.   		 * The ordering of the chain is nowhere significant
74.   		 * so in case you prefer some other order than the
75.   		 * historical one, change the code below.
76.   		 */
77.   		if(otmp) {	/* find proper place in chain */
78.   			otmp->nobj = 0;
79.   			if((invent->invlet ^ 040) > (obj->invlet ^ 040)) {
80.   				obj->nobj = invent;
81.   				invent = obj;
82.   			} else
83.   			for(otmp = invent; ; otmp = otmp->nobj) {
84.   			    if(!otmp->nobj ||
85.   				(otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){
86.   				obj->nobj = otmp->nobj;
87.   				otmp->nobj = obj;
88.   				break;
89.   			    }
90.   			}
91.   		}
92.   	}
93.   
94.   	return(obj);
95.   }
96.   
97.   useup(obj)
98.   register struct obj *obj;
99.   {
100.  	if(obj->quan > 1){
101.  		obj->quan--;
102.  		obj->owt = weight(obj);
103.  	} else {
104.  		setnotworn(obj);
105.  		freeinv(obj);
106.  		obfree(obj, (struct obj *) 0);
107.  	}
108.  }
109.  
110.  freeinv(obj)
111.  register struct obj *obj;
112.  {
113.  	register struct obj *otmp;
114.  
115.  	if(obj == invent)
116.  		invent = invent->nobj;
117.  	else {
118.  		for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj)
119.  			if(!otmp->nobj) panic("freeinv");
120.  		otmp->nobj = obj->nobj;
121.  	}
122.  }
123.  
124.  /* destroy object in fobj chain (if unpaid, it remains on the bill) */
125.  delobj(obj) register struct obj *obj; {
126.  	freeobj(obj);
127.  	unpobj(obj);
128.  	obfree(obj, (struct obj *) 0);
129.  }
130.  
131.  /* unlink obj from chain starting with fobj */
132.  freeobj(obj) register struct obj *obj; {
133.  	register struct obj *otmp;
134.  
135.  	if(obj == fobj) fobj = fobj->nobj;
136.  	else {
137.  		for(otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj)
138.  			if(!otmp) panic("error in freeobj");
139.  		otmp->nobj = obj->nobj;
140.  	}
141.  }
142.  
143.  /* Note: freegold throws away its argument! */
144.  freegold(gold) register struct gold *gold; {
145.  	register struct gold *gtmp;
146.  
147.  	if(gold == fgold) fgold = gold->ngold;
148.  	else {
149.  		for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold)
150.  			if(!gtmp) panic("error in freegold");
151.  		gtmp->ngold = gold->ngold;
152.  	}
153.  	free((char *) gold);
154.  }
155.  
156.  deltrap(trap)
157.  register struct trap *trap;
158.  {
159.  	register struct trap *ttmp;
160.  
161.  	if(trap == ftrap)
162.  		ftrap = ftrap->ntrap;
163.  	else {
164.  		for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
165.  		ttmp->ntrap = trap->ntrap;
166.  	}
167.  	free((char *) trap);
168.  }
169.  
170.  struct wseg *m_atseg;
171.  
172.  struct monst *
173.  m_at(x,y)
174.  register x,y;
175.  {
176.  	register struct monst *mtmp;
177.  #ifndef NOWORM
178.  	register struct wseg *wtmp;
179.  #endif
180.  
181.  	m_atseg = 0;
182.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
183.  		if(mtmp->mx == x && mtmp->my == y)
184.  			return(mtmp);
185.  #ifndef NOWORM
186.  		if(mtmp->wormno){
187.  		    for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg)
188.  		    if(wtmp->wx == x && wtmp->wy == y){
189.  			m_atseg = wtmp;
190.  			return(mtmp);
191.  		    }
192.  		}
193.  #endif
194.  	}
195.  	return(0);
196.  }
197.  
198.  struct obj *
199.  o_at(x,y)
200.  register x,y;
201.  {
202.  	register struct obj *otmp;
203.  
204.  	for(otmp = fobj; otmp; otmp = otmp->nobj)
205.  		if(otmp->ox == x && otmp->oy == y) return(otmp);
206.  	return(0);
207.  }
208.  
209.  struct obj *
210.  sobj_at(n,x,y)
211.  register n,x,y;
212.  {
213.  	register struct obj *otmp;
214.  
215.  	for(otmp = fobj; otmp; otmp = otmp->nobj)
216.  		if(otmp->ox == x && otmp->oy == y && otmp->otyp == n)
217.  			return(otmp);
218.  	return(0);
219.  }
220.  
221.  carried(obj) register struct obj *obj; {
222.  register struct obj *otmp;
223.  	for(otmp = invent; otmp; otmp = otmp->nobj)
224.  		if(otmp == obj) return(1);
225.  	return(0);
226.  }
227.  
228.  struct obj *
229.  carrying(type)
230.  register int type;
231.  {
232.  	register struct obj *otmp;
233.  
234.  	for(otmp = invent; otmp; otmp = otmp->nobj)
235.  		if(otmp->otyp == type)
236.  			return(otmp);
237.  	return((struct obj *) 0);
238.  }
239.  
240.  struct obj *
241.  o_on(id, objchn) unsigned int id; register struct obj *objchn; {
242.  	while(objchn) {
243.  		if(objchn->o_id == id) return(objchn);
244.  		objchn = objchn->nobj;
245.  	}
246.  	return((struct obj *) 0);
247.  }
248.  
249.  struct trap *
250.  t_at(x,y)
251.  register x,y;
252.  {
253.  	register struct trap *trap = ftrap;
254.  	while(trap) {
255.  		if(trap->tx == x && trap->ty == y) return(trap);
256.  		trap = trap->ntrap;
257.  	}
258.  	return(0);
259.  }
260.  
261.  struct gold *
262.  g_at(x,y)
263.  register x,y;
264.  {
265.  	register struct gold *gold = fgold;
266.  	while(gold) {
267.  		if(gold->gx == x && gold->gy == y) return(gold);
268.  		gold = gold->ngold;
269.  	}
270.  	return(0);
271.  }
272.  
273.  /* make dummy object structure containing gold - for temporary use only */
274.  struct obj *
275.  mkgoldobj(q)
276.  register long q;
277.  {
278.  	register struct obj *otmp;
279.  
280.  	otmp = newobj(0);
281.  	/* should set o_id etc. but otmp will be freed soon */
282.  	otmp->olet = GOLD_SYM;
283.  	u.ugold -= q;
284.  	OGOLD(otmp) = q;
285.  	flags.botl = 1;
286.  	return(otmp);
287.  }
288.  
289.  /*
290.   * getobj returns:
291.   *	struct obj *xxx:	object to do something with.
292.   *	(struct obj *) 0	error return: no object.
293.   *	&zeroobj		explicitly no object (as in w-).
294.   */
295.  struct obj *
296.  getobj(let,word)
297.  register char *let,*word;
298.  {
299.  	register struct obj *otmp;
300.  	register char ilet,ilet1,ilet2;
301.  	char buf[BUFSZ];
302.  	char lets[BUFSZ];
303.  	register int foo = 0, foo2;
304.  	register char *bp = buf;
305.  	xchar allowcnt = 0;	/* 0, 1 or 2 */
306.  	boolean allowgold = FALSE;
307.  	boolean allowall = FALSE;
308.  	boolean allownone = FALSE;
309.  	xchar foox = 0;
310.  	long cnt;
311.  
312.  	if(*let == '0') let++, allowcnt = 1;
313.  	if(*let == GOLD_SYM) let++, allowgold = TRUE;
314.  	if(*let == '#') let++, allowall = TRUE;
315.  	if(*let == '-') let++, allownone = TRUE;
316.  	if(allownone) *bp++ = '-';
317.  	if(allowgold) *bp++ = GOLD_SYM;
318.  	if(bp > buf && bp[-1] == '-') *bp++ = ' ';
319.  
320.  	ilet = 'a';
321.  	for(otmp = invent; otmp; otmp = otmp->nobj){
322.  	    if(!*let || index(let, otmp->olet)) {
323.  		bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet;
324.  
325.  		/* ugly check: remove inappropriate things */
326.  		if((!strcmp(word, "take off") &&
327.  		    !(otmp->owornmask & (W_ARMOR - W_ARM2)))
328.  		|| (!strcmp(word, "wear") &&
329.  		    (otmp->owornmask & (W_ARMOR | W_RING)))
330.  		|| (!strcmp(word, "wield") &&
331.  		    (otmp->owornmask & W_WEP))
332.  #ifdef MARKER
333.  		|| (!strcmp(word, "write with") &&
334.  		    (otmp->olet == TOOL_SYM && otmp->otyp != MAGIC_MARKER))
335.  #endif
336.  		    ) {
337.  			foo--;
338.  			foox++;
339.  		}
340.  	    }
341.  	    if(ilet == 'z') ilet = 'A'; else ilet++;
342.  	}
343.  	bp[foo] = 0;
344.  	if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
345.  	(void) strcpy(lets, bp);	/* necessary since we destroy buf */
346.  	if(foo > 5) {			/* compactify string */
347.  		foo = foo2 = 1;
348.  		ilet2 = bp[0];
349.  		ilet1 = bp[1];
350.  		while(ilet = bp[++foo2] = bp[++foo]){
351.  			if(ilet == ilet1+1){
352.  				if(ilet1 == ilet2+1)
353.  					bp[foo2 - 1] = ilet1 = '-';
354.  				else if(ilet2 == '-') {
355.  					bp[--foo2] = ++ilet1;
356.  					continue;
357.  				}
358.  			}
359.  			ilet2 = ilet1;
360.  			ilet1 = ilet;
361.  		}
362.  	}
363.  	if(!foo && !allowall && !allowgold && !allownone) {
364.  		pline("You don't have anything %sto %s.",
365.  			foox ? "else " : "", word);
366.  		return(0);
367.  	}
368.  	for(;;) {
369.  		if(!buf[0]) {
370.  #ifdef REDO
371.  		    if(!in_doagain)
372.  #endif
373.  			pline("What do you want to %s [*]? ", word);
374.  		} else {
375.  #ifdef REDO
376.  		    if(!in_doagain)
377.  #endif
378.  			pline("What do you want to %s [%s or ?*]? ",
379.  				word, buf);
380.  		}
381.  		cnt = 0;
382.  		ilet = readchar();
383.  		while(digit(ilet) && allowcnt) {
384.  #ifdef REDO
385.  			if (ilet != '?' && ilet != '*')	savech(ilet);
386.  #endif
387.  			cnt = 10*cnt + (ilet - '0');
388.  			allowcnt = 2;	/* signal presence of cnt */
389.  			ilet = readchar();
390.  		}
391.  		if(digit(ilet)) {
392.  			pline("No count allowed with this command.");
393.  			continue;
394.  		}
395.  		if(index(quitchars,ilet)) {
396.  			pline("Never mind.");
397.  			return((struct obj *)0);
398.  		}
399.  		if(ilet == '-') {
400.  			return(allownone ? &zeroobj : (struct obj *) 0);
401.  		}
402.  		if(ilet == GOLD_SYM) {
403.  			if(!allowgold){
404.  				pline("You cannot %s gold.", word);
405.  				continue;
406.  			}
407.  			if(!(allowcnt == 2 && cnt < u.ugold))
408.  				cnt = u.ugold;
409.  			return(mkgoldobj(cnt));
410.  		}
411.  		if(ilet == '?') {
412.  			doinv(lets);
413.  			if(!(ilet = morc)) continue;
414.  			/* he typed a letter (not a space) to more() */
415.  		} else if(ilet == '*') {
416.  			doinv((char *) 0);
417.  			if(!(ilet = morc)) continue;
418.  			/* ... */
419.  		}
420.  #ifdef REDO
421.  		if (ilet != '?' && ilet != '*')	savech(ilet);
422.  #endif
423.  		if(flags.invlet_constant) {
424.  			for(otmp = invent; otmp; otmp = otmp->nobj)
425.  				if(otmp->invlet == ilet) break;
426.  		} else {
427.  			if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1;
428.  			ilet -= 'a';
429.  			for(otmp = invent; otmp && ilet;
430.  					ilet--, otmp = otmp->nobj) ;
431.  		}
432.  		if(!otmp) {
433.  			pline("You don't have that object.");
434.  			continue;
435.  		}
436.  		if(cnt < 0 || otmp->quan < cnt) {
437.  			pline("You don't have that many! [You have %u]"
438.  			, otmp->quan);
439.  			continue;
440.  		}
441.  		break;
442.  	}
443.  	if(!allowall && let && !index(let,otmp->olet)) {
444.  		pline("That is a silly thing to %s.",word);
445.  		return(0);
446.  	}
447.  	if(allowcnt == 2) {	/* cnt given */
448.  		if(cnt == 0) return(0);
449.  		if(cnt != otmp->quan) {
450.  			register struct obj *obj;
451.  			obj = splitobj(otmp, (int) cnt);
452.  			if(otmp == uwep) setuwep(obj);
453.  		}
454.  	}
455.  	return(otmp);
456.  }
457.  
458.  ckunpaid(otmp) register struct obj *otmp; {
459.  	return( otmp->unpaid );
460.  }
461.  
462.  /* interactive version of getobj - used for Drop and Identify */
463.  /* return the number of times fn was called successfully */
464.  ggetobj(word, fn, max)
465.  char *word;
466.  int (*fn)(),  max;
467.  {
468.  char buf[BUFSZ];
469.  register char *ip;
470.  register char sym;
471.  register int oletct = 0, iletct = 0;
472.  register boolean allflag = FALSE;
473.  char olets[20], ilets[20];
474.  int (*ckfn)() = (int (*)()) 0;
475.  xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0;	/* BAH */
476.  	if(!invent && !allowgold){
477.  		pline("You have nothing to %s.", word);
478.  		return(0);
479.  	} else {
480.  		register struct obj *otmp = invent;
481.  		register int uflg = 0;
482.  
483.  		if(allowgold) ilets[iletct++] = GOLD_SYM;
484.  		ilets[iletct] = 0;
485.  		while(otmp) {
486.  			if(!index(ilets, otmp->olet)){
487.  				ilets[iletct++] = otmp->olet;
488.  				ilets[iletct] = 0;
489.  			}
490.  			if(otmp->unpaid) uflg = 1;
491.  			otmp = otmp->nobj;
492.  		}
493.  		ilets[iletct++] = ' ';
494.  		if(uflg) ilets[iletct++] = 'u';
495.  		if(invent) ilets[iletct++] = 'a';
496.  		ilets[iletct] = 0;
497.  	}
498.  	pline("What kinds of thing do you want to %s? [%s] ",
499.  		word, ilets);
500.  	getlin(buf);
501.  	if(buf[0] == '\033') {
502.  		clrlin();
503.  		return(0);
504.  	}
505.  	ip = buf;
506.  	olets[0] = 0;
507.  	while(sym = *ip++){
508.  		if(sym == ' ') continue;
509.  		if(sym == GOLD_SYM) {
510.  			if(allowgold == 1)
511.  				(*fn)(mkgoldobj(u.ugold));
512.  			else if(!u.ugold)
513.  				pline("You have no gold.");
514.  			allowgold = 2;
515.  		} else
516.  		if(sym == 'a' || sym == 'A') allflag = TRUE; else
517.  		if(sym == 'u' || sym == 'U') ckfn = ckunpaid; else
518.  #ifdef SPELLS
519.  		if(index("!%?[()=*/+\"0", sym)){
520.  #else
521.  		if(index("!%?[()=*/\"0", sym)){
522.  #endif
523.  			if(!index(olets, sym)){
524.  				olets[oletct++] = sym;
525.  				olets[oletct] = 0;
526.  			}
527.  		}
528.  		else pline("You don't have any %c's.", sym);
529.  	}
530.  	if(allowgold == 2 && !oletct)
531.  		return(1);	/* he dropped gold (or at least tried to) */
532.  	else
533.  		return(askchain(invent, olets, allflag, fn, ckfn, max));
534.  }
535.  
536.  /*
537.   * Walk through the chain starting at objchn and ask for all objects
538.   * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL)
539.   * whether the action in question (i.e., fn) has to be performed.
540.   * If allflag then no questions are asked. Max gives the max nr of
541.   * objects to be treated. Return the number of objects treated.
542.   */
543.  askchain(objchn, olets, allflag, fn, ckfn, max)
544.  struct obj *objchn;
545.  register char *olets;
546.  int allflag;
547.  int (*fn)(), (*ckfn)();
548.  int max;
549.  {
550.  register struct obj *otmp, *otmp2;
551.  register char sym, ilet;
552.  register int cnt = 0;
553.  #ifdef SORTING
554.  	/* changes so the askchain is interrogated in the order specified.
555.  	 * For example, if a person specifies =/ then first all rings will be
556.  	 * asked about followed by all wands -dgk
557.  	 */
558.  nextclass:
559.  #endif
560.  	ilet = 'a'-1;
561.  	for(otmp = objchn; otmp; otmp = otmp2){
562.  		if(ilet == 'z') ilet = 'A'; else ilet++;
563.  		otmp2 = otmp->nobj;
564.  #ifdef SORTING
565.  		if (olets && *olets && otmp->olet != *olets) continue;
566.  #else
567.  		if(olets && *olets && !index(olets, otmp->olet)) continue;
568.  #endif
569.  		if(ckfn && !(*ckfn)(otmp)) continue;
570.  		if(!allflag) {
571.  			pline(xprname(otmp, ilet));
572.  			addtopl(" [nyaq]? ");
573.  			sym = readchar();
574.  		}
575.  		else	sym = 'y';
576.  
577.  		switch(sym){
578.  		case 'a':
579.  			allflag = 1;
580.  		case 'y':
581.  			cnt += (*fn)(otmp);
582.  			if(--max == 0) goto ret;
583.  		case 'n':
584.  		default:
585.  			break;
586.  		case 'q':
587.  			goto ret;
588.  		}
589.  	}
590.  #ifdef SORTING
591.  	if (olets && *olets && *++olets)
592.  		goto nextclass;
593.  #endif
594.  	pline(cnt ? "That was all." : "No applicable objects.");
595.  ret:
596.  	return(cnt);
597.  }
598.  
599.  obj_to_let(obj)	/* should of course only be called for things in invent */
600.  register struct obj *obj;
601.  {
602.  	register struct obj *otmp;
603.  	register char ilet;
604.  
605.  	if(flags.invlet_constant)
606.  		return(obj->invlet);
607.  	ilet = 'a';
608.  	for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj)
609.  		if(++ilet > 'z') ilet = 'A';
610.  	return(otmp ? ilet : NOINVSYM);
611.  }
612.  
613.  prinv(obj)
614.  register struct obj *obj;
615.  {
616.  	pline(xprname(obj, obj_to_let(obj)));
617.  }
618.  
619.  static char *
620.  xprname(obj,let)
621.  register struct obj *obj;
622.  register char let;
623.  {
624.  	static char li[BUFSZ];
625.  
626.  	(void) sprintf(li, "%c - %s.",
627.  		flags.invlet_constant ? obj->invlet : let,
628.  		doname(obj));
629.  	return(li);
630.  }
631.  
632.  ddoinv()
633.  {
634.  	doinv((char *) 0);
635.  	return(0);
636.  }
637.  
638.  #ifdef SORTING
639.  # ifdef SPELLS
640.  char inv_order[] = "\")[%?+/=!(*0_`";	/* to be safe, include _ and ` */
641.  # else
642.  char inv_order[] = "\")[%?/=!(*0_`";
643.  # endif
644.  extern char *let_to_name();
645.  #endif
646.  
647.  /* called with 0 or "": all objects in inventory */
648.  /* otherwise: all objects with (serial) letter in lets */
649.  doinv(lets)
650.  register char *lets;
651.  {
652.  	register struct obj *otmp;
653.  	register char ilet;
654.  	int ct = 0;
655.  	char any[BUFSZ];
656.  #ifdef SORTING
657.  	char *invlet = inv_order;
658.  	int classcount = 0;
659.  #endif /* SORTING /**/
660.  
661.  	morc = 0;		/* just to be sure */
662.  
663.  	if(!invent){
664.  		pline("Not carrying anything.");
665.  		return;
666.  	}
667.  
668.  	cornline(0, (char *) 0);
669.  #ifdef SORTING
670.  nextclass:
671.  	classcount = 0;
672.  	ilet = 'a';
673.  	for(otmp = invent; otmp; otmp = otmp->nobj) {
674.  		if(flags.invlet_constant) ilet = otmp->invlet;
675.  		if(!lets || !*lets || index(lets, ilet)) {
676.  			if (!flags.sortpack || otmp->olet == *invlet) {
677.  				if (flags.sortpack && !classcount) {
678.  					cornline(1, let_to_name(*invlet));
679.  					classcount++;
680.  				}
681.  				cornline(1, xprname(otmp, ilet));
682.  				any[ct++] = ilet;
683.  			}
684.  		}
685.  		if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
686.  	}
687.  	if (flags.sortpack && *++invlet) goto nextclass;
688.  #else
689.  	ilet = 'a';
690.  	for(otmp = invent; otmp; otmp = otmp->nobj) {
691.  	    if(flags.invlet_constant) ilet = otmp->invlet;
692.  	    if(!lets || !*lets || index(lets, ilet)) {
693.  		    cornline(1, xprname(otmp, ilet));
694.  		    any[ct++] = ilet;
695.  	    }
696.  	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
697.  	}
698.  #endif /* SORTING /**/
699.  	any[ct] = 0;
700.  	cornline(2, any);
701.  }
702.  
703.  dotypeinv ()				/* free after Robert Viduya */
704.  /* Changed to one type only, so he doesnt have to type cr */
705.  {
706.      char c, ilet;
707.      char stuff[BUFSZ];
708.      register int stct;
709.      register struct obj *otmp;
710.      boolean billx = inshop() && doinvbill(0);
711.      boolean unpd = FALSE;
712.  
713.  	if (!invent && !u.ugold && !billx) {
714.  	    pline ("You aren't carrying anything.");
715.  	    return(0);
716.  	}
717.  
718.  	stct = 0;
719.  	if(u.ugold) stuff[stct++] = GOLD_SYM;
720.  	stuff[stct] = 0;
721.  	for(otmp = invent; otmp; otmp = otmp->nobj) {
722.  	    if (!index (stuff, otmp->olet)) {
723.  		stuff[stct++] = otmp->olet;
724.  		stuff[stct] = 0;
725.  	    }
726.  	    if(otmp->unpaid)
727.  		unpd = TRUE;
728.  	}
729.  	if(unpd) stuff[stct++] = 'u';
730.  	if(billx) stuff[stct++] = 'x';
731.  	stuff[stct] = 0;
732.  
733.  	if(stct > 1) {
734.  #ifdef REDO
735.  	  if (!in_doagain)
736.  #endif
737.  	    pline ("What type of object [%s] do you want an inventory of? ",
738.  		stuff);
739.  	    c = readchar();
740.  #ifdef REDO
741.  	    savech(c);
742.  #endif
743.  	    if(index(quitchars,c)) return(0);
744.  	} else
745.  	    c = stuff[0];
746.  
747.  	if(c == GOLD_SYM)
748.  	    return(doprgold());
749.  
750.  	if(c == 'x' || c == 'X') {
751.  	    if(billx)
752.  		(void) doinvbill(1);
753.  	    else
754.  		pline("No used-up objects on the shopping bill.");
755.  	    return(0);
756.  	}
757.  
758.  	if((c == 'u' || c == 'U') && !unpd) {
759.  		pline("You are not carrying any unpaid objects.");
760.  		return(0);
761.  	}
762.  
763.  	stct = 0;
764.  	ilet = 'a';
765.  	for (otmp = invent; otmp; otmp = otmp -> nobj) {
766.  	    if(flags.invlet_constant) ilet = otmp->invlet;
767.  	    if (c == otmp -> olet || (c == 'u' && otmp -> unpaid))
768.  		stuff[stct++] = ilet;
769.  	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
770.  	}
771.  	stuff[stct] = '\0';
772.  	if(stct == 0)
773.  		pline("You have no such objects.");
774.  	else
775.  		doinv (stuff);
776.  
777.  	return(0);
778.  }
779.  
780.  /* look at what is here */
781.  dolook() {
782.      register struct obj *otmp, *otmp0;
783.      register struct gold *gold;
784.      char *verb = Blind ? "feel" : "see";
785.      int	ct = 0;
786.      int fd = 0;
787.  
788.  #ifdef KAA
789.      read_engr_at(u.ux, u.uy); /* Eric Backus */
790.  #endif
791.      if(!u.uswallow) {
792.  	otmp0 = o_at(u.ux, u.uy);
793.  	gold = g_at(u.ux, u.uy);
794.      }  else  {
795.  	pline("You %s no objects here.", verb);
796.  	return(!!Blind);
797.      }
798.  
799.      /* added by GAN 10/30/86 */
800.  #ifdef FOUNTAINS
801.      if(IS_FOUNTAIN(levl[u.ux][u.uy].typ))  {
802.  	fd++;
803.  	pline("There is a fountain here.");
804.      }
805.  #endif
806.  #ifdef NEWCLASS
807.      if(IS_THRONE(levl[u.ux][u.uy].typ))  {
808.  	fd++;
809.  	pline("There is an opulent throne here.");
810.      }    
811.  #endif
812.      if(u.ux == xupstair && u.uy == yupstair)  {
813.  	fd++;
814.  	pline("There is a stairway up here.");
815.      }
816.      if(u.ux == xdnstair && u.uy == ydnstair)  {
817.  	fd++;
818.  	cornline(1, "There is a stairway down here.");
819.      }
820.      if(Blind)  {
821.  	 pline("You try to feel what is lying here on the floor.");
822.  	 if(Levitation)  {
823.  		pline("But you can't reach it!");
824.  		return(0);
825.  	 }
826.      }
827.   
828.      if(!otmp0 && !gold) {
829.  	if(Blind || !fd)
830.  		pline("You %s no objects here.", verb);
831.  	return(!!Blind);
832.      }
833.  
834.      cornline(0, "Things that are here:");
835.      for(otmp = otmp0; otmp; otmp = otmp->nobj) {
836.  	if(otmp->ox == u.ux && otmp->oy == u.uy) {
837.  	    ct++;
838.  	    cornline(1, doname(otmp));
839.  	    if(Blind && otmp->otyp == DEAD_COCKATRICE && !uarmg) {
840.  		pline("Touching the dead cockatrice is a fatal mistake ...");
841.  		pline("You die ...");
842.  		killer = "dead cockatrice";
843.  		done("died");
844.  	    }
845.  	}
846.      }
847.  
848.      if(gold) {
849.  	char gbuf[30];
850.  
851.  	(void) sprintf(gbuf, "%ld gold piece%s",
852.  		gold->amount, plur(gold->amount));
853.  	if(!ct++)
854.  	    pline("You %s here %s.", verb, gbuf);
855.  	else
856.  	    cornline(1, gbuf);
857.      }
858.  
859.      if(ct == 1 && !gold) {
860.  	pline("You %s here %s.", verb, doname(otmp0));
861.  	cornline(3, (char *) 0);
862.      }
863.      if(ct > 1)
864.  	cornline(2, (char *) 0);
865.      return(!!Blind);
866.  }
867.  
868.  stackobj(obj) register struct obj *obj; {
869.  register struct obj *otmp = fobj;
870.  	for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj)
871.  	if(otmp->ox == obj->ox && otmp->oy == obj->oy &&
872.  		merged(obj,otmp,1))
873.  			return;
874.  }
875.  
876.  /* merge obj with otmp and delete obj if types agree */
877.  merged(otmp,obj,lose) register struct obj *otmp, *obj; {
878.  	if(obj->otyp == otmp->otyp &&
879.  	  obj->unpaid == otmp->unpaid &&
880.  	  obj->spe == otmp->spe &&
881.  	  obj->dknown == otmp->dknown &&
882.  	  obj->cursed == otmp->cursed &&
883.  #ifdef SPELLS
884.  	  (index("%*?!+", obj->olet) ||
885.  #else
886.  	  (index("%*?!", obj->olet) ||
887.  #endif
888.  	    (obj->known == otmp->known &&
889.  		(obj->olet == WEAPON_SYM && obj->otyp < BOOMERANG)))) {
890.  		otmp->quan += obj->quan;
891.  		otmp->owt += obj->owt;
892.  		if(lose) freeobj(obj);
893.  		obfree(obj,otmp);	/* free(obj), bill->otmp */
894.  		return(1);
895.  	} else	return(0);
896.  }
897.  
898.  /*
899.   * Gold is no longer displayed; in fact, when you have a lot of money,
900.   * it may take a while before you have counted it all.
901.   * [Bug: d$ and pickup still tell you how much it was.]
902.   */
903.  extern int (*occupation)();
904.  extern char *occtxt;
905.  static long goldcounted;
906.  
907.  countgold(){
908.  	if((goldcounted += 100*(u.ulevel + 1)) >= u.ugold) {
909.  		long eps = 0;
910.  		if(!rn2(2)) eps = rnd((int) (u.ugold/100 + 1));
911.  		pline("You probably have about %ld gold pieces.",
912.  			u.ugold + eps);
913.  		return(0);	/* done */
914.  	}
915.  	return(1);		/* continue */
916.  }
917.  
918.  doprgold(){
919.  	if(!u.ugold)
920.  		pline("You do not carry any gold.");
921.  	else if(u.ugold <= 500)
922.  		pline("You are carrying %ld gold piece%s.", u.ugold, plur(u.ugold));
923.  	else {
924.  		pline("You sit down in order to count your gold pieces.");
925.  		goldcounted = 500;
926.  		occupation = countgold;
927.  		occtxt = "counting your gold";
928.  	}
929.  	return(1);
930.  }
931.  
932.  /* --- end of gold counting section --- */
933.  
934.  doprwep(){
935.  	if(!uwep) pline("You are empty handed.");
936.  	else prinv(uwep);
937.  	return(0);
938.  }
939.  
940.  doprarm(){
941.  	if(!uarm && !uarmg && !uarms && !uarmh)
942.  		pline("You are not wearing any armor.");
943.  	else {
944.  		char lets[6];
945.  		register int ct = 0;
946.  
947.  		if(uarm) lets[ct++] = obj_to_let(uarm);
948.  		if(uarm2) lets[ct++] = obj_to_let(uarm2);
949.  		if(uarmh) lets[ct++] = obj_to_let(uarmh);
950.  		if(uarms) lets[ct++] = obj_to_let(uarms);
951.  		if(uarmg) lets[ct++] = obj_to_let(uarmg);
952.  		lets[ct] = 0;
953.  		doinv(lets);
954.  	}
955.  	return(0);
956.  }
957.  
958.  doprring(){
959.  	if(!uleft && !uright)
960.  		pline("You are not wearing any rings.");
961.  	else {
962.  		char lets[3];
963.  		register int ct = 0;
964.  
965.  		if(uleft) lets[ct++] = obj_to_let(uleft);
966.  		if(uright) lets[ct++] = obj_to_let(uright);
967.  		lets[ct] = 0;
968.  		doinv(lets);
969.  	}
970.  	return(0);
971.  }
972.  
973.  digit(c) char c; {
974.  	return(c >= '0' && c <= '9');
975.  }
976.  
977.  /*
978.   * useupf(obj)
979.   * uses up an object that's on the floor
980.   */
981.  useupf(obj)
982.  register struct obj *obj;
983.  {
984.  	if(obj->quan > 1)  {
985.  		obj->quan--;
986.  		obj->owt = weight(obj);
987.  	}  else delobj(obj);
988.  }
989.  
990.  #ifdef SORTING
991.  /*
992.   * Convert from a symbol to a string for printing object classes
993.   *
994.   * Names from objects.h
995.   * char obj_symbols[] = {
996.   *	ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM,
997.   *	BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM,
998.   *	WAND_SYM, [SPBOOK_SYM], RING_SYM, GEM_SYM, 0 };
999.   */
1000. #define Sprintf (void) sprintf
1001. 
1002. extern char obj_symbols[];
1003. static char *names[] = {"Illegal objects", "Amulets", "Comestibles", "Weapons",
1004. 			"Tools", "Iron balls", "Chains", "Rocks", "Armor",
1005. 			"Potions", "Scrolls", "Wands",
1006. #ifdef SPELLS
1007. 			"Spellbooks",
1008. #endif
1009. 			"Rings", "Gems"};
1010. char *
1011. let_to_name(let)
1012. char let;
1013. {
1014. 	char *pos = index(obj_symbols, let);
1015. 	extern char *HI, *HE;
1016. 	/* buffer size is len(HI) + len(HE) + max(len(names[])) + 1 */
1017. 	static char buf[4 + 4 + 15 + 1];
1018. 
1019. 	if (pos == NULL) pos = obj_symbols;
1020. 	if (HI && HE)
1021. 	    Sprintf(buf, "%s%s%s", HI, names[pos - obj_symbols], HE);
1022. 	else
1023. 	    Sprintf(buf, "%s", names[pos - obj_symbols]);
1024. 	return (buf);
1025. }
1026. #endif /* SORTING /**/