OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / src / invent.c
1 /* NetHack 3.6  invent.c        $NHDT-Date: 1447576348 2015/11/15 08:32:28 $  $NHDT-Branch: master $:$NHDT-Revision: 1.179 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6
7 #define NOINVSYM '#'
8 #define CONTAINED_SYM '>' /* designator for inside a container */
9
10 STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (struct obj *, struct obj *));
11 STATIC_DCL void NDECL(reorder_invent);
12 STATIC_DCL boolean FDECL(mergable, (struct obj *, struct obj *));
13 STATIC_DCL void FDECL(noarmor, (BOOLEAN_P));
14 STATIC_DCL void FDECL(invdisp_nothing, (const char *, const char *));
15 STATIC_DCL boolean FDECL(worn_wield_only, (struct obj *));
16 STATIC_DCL boolean FDECL(only_here, (struct obj *));
17 STATIC_DCL void FDECL(compactify, (char *));
18 STATIC_DCL boolean FDECL(splittable, (struct obj *));
19 STATIC_DCL boolean FDECL(taking_off, (const char *));
20 STATIC_DCL boolean FDECL(putting_on, (const char *));
21 STATIC_PTR int FDECL(ckunpaid, (struct obj *));
22 STATIC_PTR int FDECL(ckvalidcat, (struct obj *));
23 STATIC_PTR char *FDECL(safeq_xprname, (struct obj *));
24 STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
25 STATIC_DCL char FDECL(display_pickinv, (const char *, BOOLEAN_P, long *));
26 STATIC_DCL char FDECL(display_used_invlets, (CHAR_P));
27 STATIC_DCL void FDECL(tally_BUCX,
28                       (struct obj *, int *, int *, int *, int *, int *));
29 STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
30 STATIC_DCL void NDECL(dounpaid);
31 STATIC_DCL struct obj *FDECL(find_unpaid, (struct obj *, struct obj **));
32 STATIC_DCL void FDECL(menu_identify, (int));
33 STATIC_DCL boolean FDECL(tool_in_use, (struct obj *));
34 STATIC_DCL char FDECL(obj_to_let, (struct obj *));
35
36 static int lastinvnr = 51; /* 0 ... 51 (never saved&restored) */
37
38 /* wizards can wish for venom, which will become an invisible inventory
39  * item without this.  putting it in inv_order would mean venom would
40  * suddenly become a choice for all the inventory-class commands, which
41  * would probably cause mass confusion.  the test for inventory venom
42  * is only WIZARD and not wizard because the wizard can leave venom lying
43  * around on a bones level for normal players to find.  [Note to the
44  * confused:  'WIZARD' used to be a compile-time conditional so this was
45  * guarded by #ifdef WIZARD/.../#endif.]
46  */
47 static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */
48
49 STATIC_OVL int CFDECLSPEC
50 sortloot_cmp(obj1, obj2)
51 struct obj *obj1;
52 struct obj *obj2;
53 {
54     int val1 = 0;
55     int val2 = 0;
56
57     /* Sort object names in lexicographical order, ignoring quantity. */
58     int name_cmp = strcmpi(cxname_singular(obj1), cxname_singular(obj2));
59
60     if (name_cmp != 0) {
61         return name_cmp;
62     }
63
64     /* Sort by BUC. Map blessed to 4, uncursed to 2, cursed to 1, and unknown
65      * to 0. */
66     val1 = obj1->bknown
67                ? (obj1->blessed << 2)
68                      + ((!obj1->blessed && !obj1->cursed) << 1) + obj1->cursed
69                : 0;
70     val2 = obj2->bknown
71                ? (obj2->blessed << 2)
72                      + ((!obj2->blessed && !obj2->cursed) << 1) + obj2->cursed
73                : 0;
74     if (val1 != val2) {
75         return val2 - val1; /* Because bigger is better. */
76     }
77
78     /* Sort by greasing. This will put the objects in degreasing order. */
79     val1 = obj1->greased;
80     val2 = obj2->greased;
81     if (val1 != val2) {
82         return val2 - val1; /* Because bigger is better. */
83     }
84
85     /* Sort by erosion. The effective amount is what matters. */
86     val1 = greatest_erosion(obj1);
87     val2 = greatest_erosion(obj2);
88     if (val1 != val2) {
89         return val1 - val2; /* Because bigger is WORSE. */
90     }
91
92     /* Sort by erodeproofing. Map known-invulnerable to 1, and both
93      * known-vulnerable and unknown-vulnerability to 0, because that's how
94      * they're displayed. */
95     val1 = obj1->rknown && obj1->oerodeproof;
96     val2 = obj2->rknown && obj2->oerodeproof;
97     if (val1 != val2) {
98         return val2 - val1; /* Because bigger is better. */
99     }
100
101     /* Sort by enchantment. Map unknown to -1000, which is comfortably below
102      * the range of ->spe. */
103     val1 = obj1->known ? obj1->spe : -1000;
104     val2 = obj2->known ? obj2->spe : -1000;
105     if (val1 != val2) {
106         return val2 - val1; /* Because bigger is better. */
107     }
108
109     /* They're identical, as far as we're concerned,
110        but we want to force a determistic order between them. */
111     return (obj1->o_id > obj2->o_id) ? 1 : -1;
112 }
113
114 struct obj **
115 objarr_init(n)
116 int n;
117 {
118     return (struct obj **) alloc(n * sizeof(struct obj *));
119 }
120
121 void
122 objarr_set(otmp, idx, oarray, dosort)
123 struct obj *otmp;
124 int idx;
125 struct obj **oarray;
126 boolean dosort;
127 {
128     if (dosort) {
129         int j;
130         for (j = idx; j; j--) {
131             if (sortloot_cmp(otmp, oarray[j - 1]) > 0)
132                 break;
133             oarray[j] = oarray[j - 1];
134         }
135         oarray[j] = otmp;
136     } else {
137         oarray[idx] = otmp;
138     }
139 }
140
141 void
142 assigninvlet(otmp)
143 register struct obj *otmp;
144 {
145     boolean inuse[52];
146     register int i;
147     register struct obj *obj;
148
149     /* there should be at most one of these in inventory... */
150     if (otmp->oclass == COIN_CLASS) {
151         otmp->invlet = GOLD_SYM;
152         return;
153     }
154
155     for (i = 0; i < 52; i++)
156         inuse[i] = FALSE;
157     for (obj = invent; obj; obj = obj->nobj)
158         if (obj != otmp) {
159             i = obj->invlet;
160             if ('a' <= i && i <= 'z')
161                 inuse[i - 'a'] = TRUE;
162             else if ('A' <= i && i <= 'Z')
163                 inuse[i - 'A' + 26] = TRUE;
164             if (i == otmp->invlet)
165                 otmp->invlet = 0;
166         }
167     if ((i = otmp->invlet)
168         && (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
169         return;
170     for (i = lastinvnr + 1; i != lastinvnr; i++) {
171         if (i == 52) {
172             i = -1;
173             continue;
174         }
175         if (!inuse[i])
176             break;
177     }
178     otmp->invlet =
179         (inuse[i] ? NOINVSYM : (i < 26) ? ('a' + i) : ('A' + i - 26));
180     lastinvnr = i;
181 }
182
183 /* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */
184 #define inv_rank(o) ((o)->invlet ^ 040)
185
186 /* sort the inventory; used by addinv() and doorganize() */
187 STATIC_OVL void
188 reorder_invent()
189 {
190     struct obj *otmp, *prev, *next;
191     boolean need_more_sorting;
192
193     do {
194         /*
195          * We expect at most one item to be out of order, so this
196          * isn't nearly as inefficient as it may first appear.
197          */
198         need_more_sorting = FALSE;
199         for (otmp = invent, prev = 0; otmp;) {
200             next = otmp->nobj;
201             if (next && inv_rank(next) < inv_rank(otmp)) {
202                 need_more_sorting = TRUE;
203                 if (prev)
204                     prev->nobj = next;
205                 else
206                     invent = next;
207                 otmp->nobj = next->nobj;
208                 next->nobj = otmp;
209                 prev = next;
210             } else {
211                 prev = otmp;
212                 otmp = next;
213             }
214         }
215     } while (need_more_sorting);
216 }
217
218 #undef inv_rank
219
220 /* scan a list of objects to see whether another object will merge with
221    one of them; used in pickup.c when all 52 inventory slots are in use,
222    to figure out whether another object could still be picked up */
223 struct obj *
224 merge_choice(objlist, obj)
225 struct obj *objlist, *obj;
226 {
227     struct monst *shkp;
228     int save_nocharge;
229
230     if (obj->otyp == SCR_SCARE_MONSTER) /* punt on these */
231         return (struct obj *) 0;
232     /* if this is an item on the shop floor, the attributes it will
233        have when carried are different from what they are now; prevent
234        that from eliciting an incorrect result from mergable() */
235     save_nocharge = obj->no_charge;
236     if (objlist == invent && obj->where == OBJ_FLOOR
237         && (shkp = shop_keeper(inside_shop(obj->ox, obj->oy))) != 0) {
238         if (obj->no_charge)
239             obj->no_charge = 0;
240         /* A billable object won't have its `unpaid' bit set, so would
241            erroneously seem to be a candidate to merge with a similar
242            ordinary object.  That's no good, because once it's really
243            picked up, it won't merge after all.  It might merge with
244            another unpaid object, but we can't check that here (depends
245            too much upon shk's bill) and if it doesn't merge it would
246            end up in the '#' overflow inventory slot, so reject it now. */
247         else if (inhishop(shkp))
248             return (struct obj *) 0;
249     }
250     while (objlist) {
251         if (mergable(objlist, obj))
252             break;
253         objlist = objlist->nobj;
254     }
255     obj->no_charge = save_nocharge;
256     return objlist;
257 }
258
259 /* merge obj with otmp and delete obj if types agree */
260 int
261 merged(potmp, pobj)
262 struct obj **potmp, **pobj;
263 {
264     register struct obj *otmp = *potmp, *obj = *pobj;
265
266     if (mergable(otmp, obj)) {
267         /* Approximate age: we do it this way because if we were to
268          * do it "accurately" (merge only when ages are identical)
269          * we'd wind up never merging any corpses.
270          * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
271          *
272          * Don't do the age manipulation if lit.  We would need
273          * to stop the burn on both items, then merge the age,
274          * then restart the burn.
275          */
276         if (!obj->lamplit)
277             otmp->age = ((otmp->age * otmp->quan) + (obj->age * obj->quan))
278                         / (otmp->quan + obj->quan);
279
280         otmp->quan += obj->quan;
281         /* temporary special case for gold objects!!!! */
282         if (otmp->oclass == COIN_CLASS)
283             otmp->owt = weight(otmp);
284         /* and puddings!!!1!!one! */
285         else if (!Is_pudding(otmp))
286             otmp->owt += obj->owt;
287         if (!has_oname(otmp) && has_oname(obj))
288             otmp = *potmp = oname(otmp, ONAME(obj));
289         obj_extract_self(obj);
290
291         /* really should merge the timeouts */
292         if (obj->lamplit)
293             obj_merge_light_sources(obj, otmp);
294         if (obj->timed)
295             obj_stop_timers(obj); /* follows lights */
296
297         /* fixup for `#adjust' merging wielded darts, daggers, &c */
298         if (obj->owornmask && carried(otmp)) {
299             long wmask = otmp->owornmask | obj->owornmask;
300
301             /* Both the items might be worn in competing slots;
302                merger preference (regardless of which is which):
303              primary weapon + alternate weapon -> primary weapon;
304              primary weapon + quiver -> primary weapon;
305              alternate weapon + quiver -> alternate weapon.
306                (Prior to 3.3.0, it was not possible for the two
307                stacks to be worn in different slots and `obj'
308                didn't need to be unworn when merging.) */
309             if (wmask & W_WEP)
310                 wmask = W_WEP;
311             else if (wmask & W_SWAPWEP)
312                 wmask = W_SWAPWEP;
313             else if (wmask & W_QUIVER)
314                 wmask = W_QUIVER;
315             else {
316                 impossible("merging strangely worn items (%lx)", wmask);
317                 wmask = otmp->owornmask;
318             }
319             if ((otmp->owornmask & ~wmask) != 0L)
320                 setnotworn(otmp);
321             setworn(otmp, wmask);
322             setnotworn(obj);
323 #if 0
324         /* (this should not be necessary, since items
325             already in a monster's inventory don't ever get
326             merged into other objects [only vice versa]) */
327         } else if (obj->owornmask && mcarried(otmp)) {
328             if (obj == MON_WEP(otmp->ocarry)) {
329                 MON_WEP(otmp->ocarry) = otmp;
330                 otmp->owornmask = W_WEP;
331             }
332 #endif /*0*/
333         }
334
335         /* handle puddings a bit differently; absorption will
336          * free the other object automatically so we can just
337          * return out from here.  */
338         if (Is_pudding(obj)) {
339             pudding_merge_message(otmp, obj);
340             obj_absorb(potmp, pobj);
341             return 1;
342         }
343
344         obfree(obj, otmp); /* free(obj), bill->otmp */
345         return 1;
346     }
347     return 0;
348 }
349
350 /*
351  * Adjust hero intrinsics as if this object was being added to the hero's
352  * inventory.  Called _before_ the object has been added to the hero's
353  * inventory.
354  *
355  * This is called when adding objects to the hero's inventory normally (via
356  * addinv) or when an object in the hero's inventory has been polymorphed
357  * in-place.
358  *
359  * It may be valid to merge this code with with addinv_core2().
360  */
361 void
362 addinv_core1(obj)
363 struct obj *obj;
364 {
365     if (obj->oclass == COIN_CLASS) {
366         context.botl = 1;
367     } else if (obj->otyp == AMULET_OF_YENDOR) {
368         if (u.uhave.amulet)
369             impossible("already have amulet?");
370         u.uhave.amulet = 1;
371         u.uachieve.amulet = 1;
372     } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
373         if (u.uhave.menorah)
374             impossible("already have candelabrum?");
375         u.uhave.menorah = 1;
376         u.uachieve.menorah = 1;
377     } else if (obj->otyp == BELL_OF_OPENING) {
378         if (u.uhave.bell)
379             impossible("already have silver bell?");
380         u.uhave.bell = 1;
381         u.uachieve.bell = 1;
382     } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
383         if (u.uhave.book)
384             impossible("already have the book?");
385         u.uhave.book = 1;
386         u.uachieve.book = 1;
387     } else if (obj->oartifact) {
388         if (is_quest_artifact(obj)) {
389             if (u.uhave.questart)
390                 impossible("already have quest artifact?");
391             u.uhave.questart = 1;
392             artitouch(obj);
393         }
394         set_artifact_intrinsic(obj, 1, W_ART);
395     }
396     if (obj->otyp == LUCKSTONE && obj->record_achieve_special) {
397         u.uachieve.mines_luckstone = 1;
398         obj->record_achieve_special = 0;
399     } else if ((obj->otyp == AMULET_OF_REFLECTION
400                 || obj->otyp == BAG_OF_HOLDING)
401                && obj->record_achieve_special) {
402         u.uachieve.finish_sokoban = 1;
403         obj->record_achieve_special = 0;
404     }
405 }
406
407 /*
408  * Adjust hero intrinsics as if this object was being added to the hero's
409  * inventory.  Called _after_ the object has been added to the hero's
410  * inventory.
411  *
412  * This is called when adding objects to the hero's inventory normally (via
413  * addinv) or when an object in the hero's inventory has been polymorphed
414  * in-place.
415  */
416 void
417 addinv_core2(obj)
418 struct obj *obj;
419 {
420     if (confers_luck(obj)) {
421         /* new luckstone must be in inventory by this point
422          * for correct calculation */
423         set_moreluck();
424     }
425 }
426
427 /*
428  * Add obj to the hero's inventory.  Make sure the object is "free".
429  * Adjust hero attributes as necessary.
430  */
431 struct obj *
432 addinv(obj)
433 struct obj *obj;
434 {
435     struct obj *otmp, *prev;
436     int saved_otyp = (int) obj->otyp; /* for panic */
437
438     if (obj->where != OBJ_FREE)
439         panic("addinv: obj not free");
440     /* normally addtobill() clears no_charge when items in a shop are
441        picked up, but won't do so if the shop has become untended */
442     obj->no_charge = 0; /* should not be set in hero's invent */
443     if (Has_contents(obj))
444         picked_container(obj); /* clear no_charge */
445     obj->was_thrown = 0;       /* not meaningful for invent */
446
447     addinv_core1(obj);
448
449     /* merge with quiver in preference to any other inventory slot
450        in case quiver and wielded weapon are both eligible; adding
451        extra to quivered stack is more useful than to wielded one */
452     if (uquiver && merged(&uquiver, &obj)) {
453         obj = uquiver;
454         if (!obj)
455             panic("addinv: null obj after quiver merge otyp=%d", saved_otyp);
456         goto added;
457     }
458     /* merge if possible; find end of chain in the process */
459     for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj)
460         if (merged(&otmp, &obj)) {
461             obj = otmp;
462             if (!obj)
463                 panic("addinv: null obj after merge otyp=%d", saved_otyp);
464             goto added;
465         }
466     /* didn't merge, so insert into chain */
467     assigninvlet(obj);
468     if (flags.invlet_constant || !prev) {
469         obj->nobj = invent; /* insert at beginning */
470         invent = obj;
471         if (flags.invlet_constant)
472             reorder_invent();
473     } else {
474         prev->nobj = obj; /* insert at end */
475         obj->nobj = 0;
476     }
477     obj->where = OBJ_INVENT;
478
479 added:
480     addinv_core2(obj);
481     carry_obj_effects(obj); /* carrying affects the obj */
482     update_inventory();
483     return obj;
484 }
485
486 /*
487  * Some objects are affected by being carried.
488  * Make those adjustments here. Called _after_ the object
489  * has been added to the hero's or monster's inventory,
490  * and after hero's intrinsics have been updated.
491  */
492 void
493 carry_obj_effects(obj)
494 struct obj *obj;
495 {
496     /* Cursed figurines can spontaneously transform
497        when carried. */
498     if (obj->otyp == FIGURINE) {
499         if (obj->cursed && obj->corpsenm != NON_PM
500             && !dead_species(obj->corpsenm, TRUE)) {
501             attach_fig_transform_timeout(obj);
502         }
503     }
504 }
505
506 /* Add an item to the inventory unless we're fumbling or it refuses to be
507  * held (via touch_artifact), and give a message.
508  * If there aren't any free inventory slots, we'll drop it instead.
509  * If both success and failure messages are NULL, then we're just doing the
510  * fumbling/slot-limit checking for a silent grab.  In any case,
511  * touch_artifact will print its own messages if they are warranted.
512  */
513 struct obj *
514 hold_another_object(obj, drop_fmt, drop_arg, hold_msg)
515 struct obj *obj;
516 const char *drop_fmt, *drop_arg, *hold_msg;
517 {
518     char buf[BUFSZ];
519
520     if (!Blind)
521         obj->dknown = 1; /* maximize mergibility */
522     if (obj->oartifact) {
523         /* place_object may change these */
524         boolean crysknife = (obj->otyp == CRYSKNIFE);
525         int oerode = obj->oerodeproof;
526         boolean wasUpolyd = Upolyd;
527
528         /* in case touching this object turns out to be fatal */
529         place_object(obj, u.ux, u.uy);
530
531         if (!touch_artifact(obj, &youmonst)) {
532             obj_extract_self(obj); /* remove it from the floor */
533             dropy(obj);            /* now put it back again :-) */
534             return obj;
535         } else if (wasUpolyd && !Upolyd) {
536             /* loose your grip if you revert your form */
537             if (drop_fmt)
538                 pline(drop_fmt, drop_arg);
539             obj_extract_self(obj);
540             dropy(obj);
541             return obj;
542         }
543         obj_extract_self(obj);
544         if (crysknife) {
545             obj->otyp = CRYSKNIFE;
546             obj->oerodeproof = oerode;
547         }
548     }
549     if (Fumbling) {
550         if (drop_fmt)
551             pline(drop_fmt, drop_arg);
552         dropy(obj);
553     } else {
554         long oquan = obj->quan;
555         int prev_encumbr = near_capacity(); /* before addinv() */
556
557         /* encumbrance only matters if it would now become worse
558            than max( current_value, stressed ) */
559         if (prev_encumbr < MOD_ENCUMBER)
560             prev_encumbr = MOD_ENCUMBER;
561         /* addinv() may redraw the entire inventory, overwriting
562            drop_arg when it comes from something like doname() */
563         if (drop_arg)
564             drop_arg = strcpy(buf, drop_arg);
565
566         obj = addinv(obj);
567         if (inv_cnt(FALSE) > 52 || ((obj->otyp != LOADSTONE || !obj->cursed)
568                                     && near_capacity() > prev_encumbr)) {
569             if (drop_fmt)
570                 pline(drop_fmt, drop_arg);
571             /* undo any merge which took place */
572             if (obj->quan > oquan)
573                 obj = splitobj(obj, oquan);
574             dropx(obj);
575         } else {
576             if (flags.autoquiver && !uquiver && !obj->owornmask
577                 && (is_missile(obj) || ammo_and_launcher(obj, uwep)
578                     || ammo_and_launcher(obj, uswapwep)))
579                 setuqwep(obj);
580             if (hold_msg || drop_fmt)
581                 prinv(hold_msg, obj, oquan);
582         }
583     }
584     return obj;
585 }
586
587 /* useup() all of an item regardless of its quantity */
588 void
589 useupall(obj)
590 struct obj *obj;
591 {
592     setnotworn(obj);
593     freeinv(obj);
594     obfree(obj, (struct obj *) 0); /* deletes contents also */
595 }
596
597 void
598 useup(obj)
599 register struct obj *obj;
600 {
601     /* Note:  This works correctly for containers because they (containers)
602        don't merge. */
603     if (obj->quan > 1L) {
604         obj->in_use = FALSE; /* no longer in use */
605         obj->quan--;
606         obj->owt = weight(obj);
607         update_inventory();
608     } else {
609         useupall(obj);
610     }
611 }
612
613 /* use one charge from an item and possibly incur shop debt for it */
614 void
615 consume_obj_charge(obj, maybe_unpaid)
616 struct obj *obj;
617 boolean maybe_unpaid; /* false if caller handles shop billing */
618 {
619     if (maybe_unpaid)
620         check_unpaid(obj);
621     obj->spe -= 1;
622     if (obj->known)
623         update_inventory();
624 }
625
626 /*
627  * Adjust hero's attributes as if this object was being removed from the
628  * hero's inventory.  This should only be called from freeinv() and
629  * where we are polymorphing an object already in the hero's inventory.
630  *
631  * Should think of a better name...
632  */
633 void
634 freeinv_core(obj)
635 struct obj *obj;
636 {
637     if (obj->oclass == COIN_CLASS) {
638         context.botl = 1;
639         return;
640     } else if (obj->otyp == AMULET_OF_YENDOR) {
641         if (!u.uhave.amulet)
642             impossible("don't have amulet?");
643         u.uhave.amulet = 0;
644     } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
645         if (!u.uhave.menorah)
646             impossible("don't have candelabrum?");
647         u.uhave.menorah = 0;
648     } else if (obj->otyp == BELL_OF_OPENING) {
649         if (!u.uhave.bell)
650             impossible("don't have silver bell?");
651         u.uhave.bell = 0;
652     } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
653         if (!u.uhave.book)
654             impossible("don't have the book?");
655         u.uhave.book = 0;
656     } else if (obj->oartifact) {
657         if (is_quest_artifact(obj)) {
658             if (!u.uhave.questart)
659                 impossible("don't have quest artifact?");
660             u.uhave.questart = 0;
661         }
662         set_artifact_intrinsic(obj, 0, W_ART);
663     }
664
665     if (obj->otyp == LOADSTONE) {
666         curse(obj);
667     } else if (confers_luck(obj)) {
668         set_moreluck();
669         context.botl = 1;
670     } else if (obj->otyp == FIGURINE && obj->timed) {
671         (void) stop_timer(FIG_TRANSFORM, obj_to_any(obj));
672     }
673 }
674
675 /* remove an object from the hero's inventory */
676 void
677 freeinv(obj)
678 register struct obj *obj;
679 {
680     extract_nobj(obj, &invent);
681     freeinv_core(obj);
682     update_inventory();
683 }
684
685 void
686 delallobj(x, y)
687 int x, y;
688 {
689     struct obj *otmp, *otmp2;
690
691     for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
692         if (otmp == uball)
693             unpunish();
694         /* after unpunish(), or might get deallocated chain */
695         otmp2 = otmp->nexthere;
696         if (otmp == uchain)
697             continue;
698         delobj(otmp);
699     }
700 }
701
702 /* destroy object in fobj chain (if unpaid, it remains on the bill) */
703 void
704 delobj(obj)
705 register struct obj *obj;
706 {
707     boolean update_map;
708
709     if (obj->otyp == AMULET_OF_YENDOR
710         || obj->otyp == CANDELABRUM_OF_INVOCATION
711         || obj->otyp == BELL_OF_OPENING
712         || obj->otyp == SPE_BOOK_OF_THE_DEAD) {
713         /* player might be doing something stupid, but we
714          * can't guarantee that.  assume special artifacts
715          * are indestructible via drawbridges, and exploding
716          * chests, and golem creation, and ...
717          */
718         return;
719     }
720     update_map = (obj->where == OBJ_FLOOR);
721     obj_extract_self(obj);
722     if (update_map)
723         newsym(obj->ox, obj->oy);
724     obfree(obj, (struct obj *) 0); /* frees contents also */
725 }
726
727 /* try to find a particular type of object at designated map location */
728 struct obj *
729 sobj_at(otyp, x, y)
730 int otyp;
731 int x, y;
732 {
733     register struct obj *otmp;
734
735     for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
736         if (otmp->otyp == otyp)
737             break;
738
739     return otmp;
740 }
741
742 /* sobj_at(&c) traversal -- find next object of specified type */
743 struct obj *
744 nxtobj(obj, type, by_nexthere)
745 struct obj *obj;
746 int type;
747 boolean by_nexthere;
748 {
749     register struct obj *otmp;
750
751     otmp = obj; /* start with the object after this one */
752     do {
753         otmp = !by_nexthere ? otmp->nobj : otmp->nexthere;
754         if (!otmp)
755             break;
756     } while (otmp->otyp != type);
757
758     return otmp;
759 }
760
761 struct obj *
762 carrying(type)
763 register int type;
764 {
765     register struct obj *otmp;
766
767     for (otmp = invent; otmp; otmp = otmp->nobj)
768         if (otmp->otyp == type)
769             return  otmp;
770     return (struct obj *) 0;
771 }
772
773 /* Fictional and not-so-fictional currencies.
774  * http://concord.wikia.com/wiki/List_of_Fictional_Currencies
775  */
776 static const char *const currencies[] = {
777     "Altarian Dollar",       /* The Hitchhiker's Guide to the Galaxy */
778     "Ankh-Morpork Dollar",   /* Discworld */
779     "auric",                 /* The Domination of Draka */
780     "buckazoid",             /* Space Quest */
781     "cirbozoid",             /* Starslip */
782     "credit chit",           /* Deus Ex */
783     "cubit",                 /* Battlestar Galactica */
784     "Flanian Pobble Bead",   /* The Hitchhiker's Guide to the Galaxy */
785     "fretzer",               /* Jules Verne */
786     "imperial credit",       /* Star Wars */
787     "Hong Kong Luna Dollar", /* The Moon is a Harsh Mistress */
788     "kongbuck",              /* Snow Crash */
789     "nanite",                /* System Shock 2 */
790     "quatloo",               /* Star Trek, Sim City */
791     "simoleon",              /* Sim City */
792     "solari",                /* Spaceballs */
793     "spacebuck",             /* Spaceballs */
794     "sporebuck",             /* Spore */
795     "Triganic Pu",           /* The Hitchhiker's Guide to the Galaxy */
796     "woolong",               /* Cowboy Bebop */
797     "zorkmid",               /* Zork, NetHack */
798 };
799
800 const char *
801 currency(amount)
802 long amount;
803 {
804     const char *res;
805
806     res = Hallucination ? currencies[rn2(SIZE(currencies))] : "zorkmid";
807     if (amount != 1L)
808         res = makeplural(res);
809     return res;
810 }
811
812 boolean
813 have_lizard()
814 {
815     register struct obj *otmp;
816
817     for (otmp = invent; otmp; otmp = otmp->nobj)
818         if (otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
819             return  TRUE;
820     return FALSE;
821 }
822
823 /* 3.6.0 tribute */
824 struct obj *
825 u_have_novel()
826 {
827     register struct obj *otmp;
828
829     for (otmp = invent; otmp; otmp = otmp->nobj)
830         if (otmp->otyp == SPE_NOVEL)
831             return otmp;
832     return (struct obj *) 0;
833 }
834
835 struct obj *
836 o_on(id, objchn)
837 unsigned int id;
838 register struct obj *objchn;
839 {
840     struct obj *temp;
841
842     while (objchn) {
843         if (objchn->o_id == id)
844             return objchn;
845         if (Has_contents(objchn) && (temp = o_on(id, objchn->cobj)))
846             return temp;
847         objchn = objchn->nobj;
848     }
849     return (struct obj *) 0;
850 }
851
852 boolean
853 obj_here(obj, x, y)
854 register struct obj *obj;
855 int x, y;
856 {
857     register struct obj *otmp;
858
859     for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
860         if (obj == otmp)
861             return TRUE;
862     return FALSE;
863 }
864
865 struct obj *
866 g_at(x, y)
867 register int x, y;
868 {
869     register struct obj *obj = level.objects[x][y];
870
871     while (obj) {
872         if (obj->oclass == COIN_CLASS)
873             return obj;
874         obj = obj->nexthere;
875     }
876     return (struct obj *) 0;
877 }
878
879 /* compact a string of inventory letters by dashing runs of letters */
880 STATIC_OVL void
881 compactify(buf)
882 register char *buf;
883 {
884     register int i1 = 1, i2 = 1;
885     register char ilet, ilet1, ilet2;
886
887     ilet2 = buf[0];
888     ilet1 = buf[1];
889     buf[++i2] = buf[++i1];
890     ilet = buf[i1];
891     while (ilet) {
892         if (ilet == ilet1 + 1) {
893             if (ilet1 == ilet2 + 1)
894                 buf[i2 - 1] = ilet1 = '-';
895             else if (ilet2 == '-') {
896                 buf[i2 - 1] = ++ilet1;
897                 buf[i2] = buf[++i1];
898                 ilet = buf[i1];
899                 continue;
900             }
901         } else if (ilet == NOINVSYM) {
902             /* compact three or more consecutive '#'
903                characters into "#-#" */
904             if (i2 >= 2 && buf[i2 - 2] == NOINVSYM && buf[i2 - 1] == NOINVSYM)
905                 buf[i2 - 1] = '-';
906             else if (i2 >= 3 && buf[i2 - 3] == NOINVSYM && buf[i2 - 2] == '-'
907                      && buf[i2 - 1] == NOINVSYM)
908                 --i2;
909         }
910         ilet2 = ilet1;
911         ilet1 = ilet;
912         buf[++i2] = buf[++i1];
913         ilet = buf[i1];
914     }
915 }
916
917 /* some objects shouldn't be split when count given to getobj or askchain */
918 STATIC_OVL boolean
919 splittable(obj)
920 struct obj *obj;
921 {
922     return !((obj->otyp == LOADSTONE && obj->cursed)
923              || (obj == uwep && welded(uwep)));
924 }
925
926 /* match the prompt for either 'T' or 'R' command */
927 STATIC_OVL boolean
928 taking_off(action)
929 const char *action;
930 {
931     return !strcmp(action, "take off") || !strcmp(action, "remove");
932 }
933
934 /* match the prompt for either 'W' or 'P' command */
935 STATIC_OVL boolean
936 putting_on(action)
937 const char *action;
938 {
939     return !strcmp(action, "wear") || !strcmp(action, "put on");
940 }
941
942 /*
943  * getobj returns:
944  *      struct obj *xxx:        object to do something with.
945  *      (struct obj *) 0        error return: no object.
946  *      &zeroobj                explicitly no object (as in w-).
947 !!!! test if gold can be used in unusual ways (eaten etc.)
948 !!!! may be able to remove "usegold"
949  */
950 struct obj *
951 getobj(let, word)
952 register const char *let, *word;
953 {
954     register struct obj *otmp;
955     register char ilet;
956     char buf[BUFSZ], qbuf[QBUFSZ];
957     char lets[BUFSZ], altlets[BUFSZ], *ap;
958     register int foo = 0;
959     register char *bp = buf;
960     xchar allowcnt = 0; /* 0, 1 or 2 */
961     struct obj *firstobj = invent;
962     boolean usegold = FALSE; /* can't use gold because its illegal */
963     boolean allowall = FALSE;
964     boolean allownone = FALSE;
965     boolean useboulder = FALSE;
966     xchar foox = 0;
967     long cnt, prevcnt;
968     boolean prezero;
969     long dummymask;
970
971     if (*let == ALLOW_COUNT)
972         let++, allowcnt = 1;
973     if (*let == COIN_CLASS)
974         let++, usegold = TRUE;
975
976     /* Equivalent of an "ugly check" for gold */
977     if (usegold && !strcmp(word, "eat")
978         && (!metallivorous(youmonst.data)
979             || youmonst.data == &mons[PM_RUST_MONSTER]))
980         usegold = FALSE;
981
982     if (*let == ALL_CLASSES)
983         let++, allowall = TRUE;
984     if (*let == ALLOW_NONE)
985         let++, allownone = TRUE;
986     /* "ugly check" for reading fortune cookies, part 1.
987      * The normal 'ugly check' keeps the object on the inventory list.
988      * We don't want to do that for shirts/cookies, so the check for
989      * them is handled a bit differently (and also requires that we set
990      * allowall in the caller).
991      */
992     if (allowall && !strcmp(word, "read"))
993         allowall = FALSE;
994
995     /* another ugly check: show boulders (not statues) */
996     if (*let == WEAPON_CLASS && !strcmp(word, "throw")
997         && throws_rocks(youmonst.data))
998         useboulder = TRUE;
999
1000     if (allownone)
1001         *bp++ = '-';
1002     if (bp > buf && bp[-1] == '-')
1003         *bp++ = ' ';
1004     ap = altlets;
1005
1006     if (!flags.invlet_constant)
1007         reassign();
1008
1009     for (otmp = firstobj; otmp; otmp = otmp->nobj) {
1010         if (&bp[foo] == &buf[sizeof buf - 1]
1011             || ap == &altlets[sizeof altlets - 1]) {
1012             /* we must have a huge number of NOINVSYM items somehow */
1013             impossible("getobj: inventory overflow");
1014             break;
1015         }
1016
1017         if (!*let || index(let, otmp->oclass)
1018             || (usegold && otmp->invlet == GOLD_SYM)
1019             || (useboulder && otmp->otyp == BOULDER)) {
1020             register int otyp = otmp->otyp;
1021             bp[foo++] = otmp->invlet;
1022
1023 /* clang-format off */
1024 /* *INDENT-OFF* */
1025             /* ugly check: remove inappropriate things */
1026             if (
1027                 (taking_off(word) /* exclude if not worn */
1028                  && !(otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
1029              || (putting_on(word) /* exclude if already worn */
1030                  && (otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
1031 #if 0 /* 3.4.1 -- include currently wielded weapon among 'wield' choices */
1032              || (!strcmp(word, "wield")
1033                  && (otmp->owornmask & W_WEP))
1034 #endif
1035              || (!strcmp(word, "ready") /* exclude if wielded */
1036                  && (otmp == uwep || (otmp == uswapwep && u.twoweap)))
1037              || ((!strcmp(word, "dip") || !strcmp(word, "grease"))
1038                  && inaccessible_equipment(otmp, (const char *) 0, FALSE))
1039              ) {
1040                 foo--;
1041                 foox++;
1042             }
1043             /* Second ugly check; unlike the first it won't trigger an
1044              * "else" in "you don't have anything else to ___".
1045              */
1046             else if (
1047                 (putting_on(word)
1048                  && ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING)
1049                      || (otmp->oclass == TOOL_CLASS && otyp != BLINDFOLD
1050                          && otyp != TOWEL && otyp != LENSES)))
1051              || (!strcmp(word, "wield")
1052                  && (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
1053              || (!strcmp(word, "eat") && !is_edible(otmp))
1054              || (!strcmp(word, "sacrifice")
1055                  && (otyp != CORPSE && otyp != AMULET_OF_YENDOR
1056                      && otyp != FAKE_AMULET_OF_YENDOR))
1057              || (!strcmp(word, "write with")
1058                  && (otmp->oclass == TOOL_CLASS
1059                      && otyp != MAGIC_MARKER && otyp != TOWEL))
1060              || (!strcmp(word, "tin")
1061                  && (otyp != CORPSE || !tinnable(otmp)))
1062              || (!strcmp(word, "rub")
1063                  && ((otmp->oclass == TOOL_CLASS && otyp != OIL_LAMP
1064                       && otyp != MAGIC_LAMP && otyp != BRASS_LANTERN)
1065                      || (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
1066              || (!strcmp(word, "use or apply")
1067                  /* Picks, axes, pole-weapons, bullwhips */
1068                  && ((otmp->oclass == WEAPON_CLASS
1069                       && !is_pick(otmp) && !is_axe(otmp)
1070                       && !is_pole(otmp) && otyp != BULLWHIP)
1071                      || (otmp->oclass == POTION_CLASS
1072                          /* only applicable potion is oil, and it will only
1073                             be offered as a choice when already discovered */
1074                          && (otyp != POT_OIL || !otmp->dknown
1075                              || !objects[POT_OIL].oc_name_known))
1076                      || (otmp->oclass == FOOD_CLASS
1077                          && otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF)
1078                      || (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
1079              || (!strcmp(word, "invoke")
1080                  && !otmp->oartifact
1081                  && !objects[otyp].oc_unique
1082                  && (otyp != FAKE_AMULET_OF_YENDOR || otmp->known)
1083                  && otyp != CRYSTAL_BALL /* synonym for apply */
1084                  /* note: presenting the possibility of invoking non-artifact
1085                     mirrors and/or lamps is simply a cruel deception... */
1086                  && otyp != MIRROR
1087                  && otyp != MAGIC_LAMP
1088                  && (otyp != OIL_LAMP /* don't list known oil lamp */
1089                      || (otmp->dknown && objects[OIL_LAMP].oc_name_known)))
1090              || (!strcmp(word, "untrap with")
1091                  && ((otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE)
1092                      || (otmp->oclass == POTION_CLASS
1093                          /* only applicable potion is oil, and it will only
1094                             be offered as a choice when already discovered */
1095                          && (otyp != POT_OIL || !otmp->dknown
1096                              || !objects[POT_OIL].oc_name_known))))
1097              || (!strcmp(word, "tip") && !Is_container(otmp)
1098                  /* include horn of plenty if sufficiently discovered */
1099                  && (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown
1100                      || !objects[HORN_OF_PLENTY].oc_name_known))
1101              || (!strcmp(word, "charge") && !is_chargeable(otmp))
1102              || (!strcmp(word, "call") && !objtyp_is_callable(otyp))
1103              ) {
1104                 foo--;
1105             }
1106             /* Third ugly check:  acceptable but not listed as likely
1107              * candidates in the prompt or in the inventory subset if
1108              * player responds with '?'.
1109              */
1110             else if (
1111              /* ugly check for unworn armor that can't be worn */
1112                 (putting_on(word) && *let == ARMOR_CLASS
1113                  && !canwearobj(otmp, &dummymask, FALSE))
1114              /* or armor with 'P' or 'R' or accessory with 'W' or 'T' */
1115              || ((putting_on(word) || taking_off(word))
1116                  && ((*let == ARMOR_CLASS) ^ (otmp->oclass == ARMOR_CLASS)))
1117              /* or unsuitable items rubbed on known touchstone */
1118              || (!strncmp(word, "rub on the stone", 16)
1119                  && *let == GEM_CLASS && otmp->dknown
1120                  && objects[otyp].oc_name_known)
1121              /* suppress corpses on astral, amulets elsewhere */
1122              || (!strcmp(word, "sacrifice")
1123                  /* (!astral && amulet) || (astral && !amulet) */
1124                  && (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
1125              /* suppress container being stashed into */
1126              || (!strcmp(word, "stash") && !ck_bag(otmp))
1127              /* worn armor or accessory covered by cursed worn armor */
1128              || (taking_off(word)
1129                  && inaccessible_equipment(otmp, (const char *) 0, TRUE))
1130              ) {
1131                 /* acceptable but not listed as likely candidate */
1132                 foo--;
1133                 allowall = TRUE;
1134                 *ap++ = otmp->invlet;
1135             }
1136 /* *INDENT-ON* */
1137 /* clang-format on */
1138         } else {
1139             /* "ugly check" for reading fortune cookies, part 2 */
1140             if ((!strcmp(word, "read") && is_readable(otmp)))
1141                 allowall = usegold = TRUE;
1142         }
1143     }
1144
1145     bp[foo] = 0;
1146     if (foo == 0 && bp > buf && bp[-1] == ' ')
1147         *--bp = 0;
1148     Strcpy(lets, bp); /* necessary since we destroy buf */
1149     if (foo > 5)      /* compactify string */
1150         compactify(bp);
1151     *ap = '\0';
1152
1153     if (!foo && !allowall && !allownone) {
1154         You("don't have anything %sto %s.", foox ? "else " : "", word);
1155         return (struct obj *) 0;
1156     }
1157     for (;;) {
1158         cnt = 0;
1159         if (allowcnt == 2)
1160             allowcnt = 1; /* abort previous count */
1161         prezero = FALSE;
1162         if (!buf[0]) {
1163             Sprintf(qbuf, "What do you want to %s? [*]", word);
1164         } else {
1165             Sprintf(qbuf, "What do you want to %s? [%s or ?*]", word, buf);
1166         }
1167         if (in_doagain)
1168             ilet = readchar();
1169         else
1170             ilet = yn_function(qbuf, (char *) 0, '\0');
1171         if (digit(ilet) && !allowcnt) {
1172             pline("No count allowed with this command.");
1173             continue;
1174         }
1175         if (ilet == '0')
1176             prezero = TRUE;
1177         while (digit(ilet)) {
1178             if (ilet != '?' && ilet != '*')
1179                 savech(ilet);
1180             /* accumulate unless cnt has overflowed */
1181             if (allowcnt < 3) {
1182                 prevcnt = cnt;
1183                 cnt = 10L * cnt + (long) (ilet - '0');
1184                 /* signal presence of cnt */
1185                 allowcnt = (cnt >= prevcnt) ? 2 : 3;
1186             }
1187             ilet = readchar();
1188         }
1189         if (allowcnt == 3) {
1190             /* overflow detected; force cnt to be invalid */
1191             cnt = -1L;
1192             allowcnt = 2;
1193         }
1194         if (index(quitchars, ilet)) {
1195             if (flags.verbose)
1196                 pline1(Never_mind);
1197             return (struct obj *) 0;
1198         }
1199         if (ilet == '-') {
1200             if (!allownone) {
1201                 char *suf = (char *) 0;
1202
1203                 strcpy(buf, word);
1204                 if ((bp = strstr(buf, " on the ")) != 0) {
1205                     /* rub on the stone[s] */
1206                     *bp = '\0';
1207                     suf = (bp + 1);
1208                 }
1209                 if ((bp = strstr(buf, " or ")) != 0) {
1210                     *bp = '\0';
1211                     bp = (rn2(2) ? buf : (bp + 4));
1212                 } else
1213                     bp = buf;
1214                 You("mime %s something%s%s.", ing_suffix(bp), suf ? " " : "",
1215                     suf ? suf : "");
1216             }
1217             return (allownone ? &zeroobj : (struct obj *) 0);
1218         }
1219         /* since gold is now kept in inventory, we need to do processing for
1220            select-from-invent before checking whether gold has been picked */
1221         if (ilet == '?' || ilet == '*') {
1222             char *allowed_choices = (ilet == '?') ? lets : (char *) 0;
1223             long ctmp = 0;
1224
1225             if (ilet == '?' && !*lets && *altlets)
1226                 allowed_choices = altlets;
1227             ilet = display_pickinv(allowed_choices, TRUE,
1228                                    allowcnt ? &ctmp : (long *) 0);
1229             if (!ilet)
1230                 continue;
1231             if (allowcnt && ctmp >= 0) {
1232                 cnt = ctmp;
1233                 if (!cnt)
1234                     prezero = TRUE;
1235                 allowcnt = 2;
1236             }
1237             if (ilet == '\033') {
1238                 if (flags.verbose)
1239                     pline1(Never_mind);
1240                 return (struct obj *) 0;
1241             }
1242             /* they typed a letter (not a space) at the prompt */
1243         }
1244         /* find the item which was picked */
1245         for (otmp = invent; otmp; otmp = otmp->nobj)
1246             if (otmp->invlet == ilet)
1247                 break;
1248         /* some items have restrictions */
1249         if (ilet == def_oc_syms[COIN_CLASS].sym
1250             /* guard against the [hypothetical] chace of having more
1251                than one invent slot of gold and picking the non-'$' one */
1252             || (otmp && otmp->oclass == COIN_CLASS)) {
1253             if (!usegold) {
1254                 You("cannot %s gold.", word);
1255                 return (struct obj *) 0;
1256             }
1257             /* Historic note: early Nethack had a bug which was
1258              * first reported for Larn, where trying to drop 2^32-n
1259              * gold pieces was allowed, and did interesting things
1260              * to your money supply.  The LRS is the tax bureau
1261              * from Larn.
1262              */
1263             if (allowcnt == 2 && cnt <= 0) {
1264                 if (cnt < 0 || !prezero)
1265                     pline_The(
1266                   "LRS would be very interested to know you have that much.");
1267                 return (struct obj *) 0;
1268             }
1269         }
1270         if (allowcnt == 2 && !strcmp(word, "throw")) {
1271             /* permit counts for throwing gold, but don't accept
1272              * counts for other things since the throw code will
1273              * split off a single item anyway */
1274             if (ilet != def_oc_syms[COIN_CLASS].sym
1275                 && !(otmp && otmp->oclass == COIN_CLASS))
1276                 allowcnt = 1;
1277             if (cnt == 0 && prezero)
1278                 return (struct obj *) 0;
1279             if (cnt > 1) {
1280                 You("can only throw one item at a time.");
1281                 continue;
1282             }
1283         }
1284         context.botl = 1; /* May have changed the amount of money */
1285         savech(ilet);
1286         /* [we used to set otmp (by finding ilet in invent) here, but
1287            that's been moved above so that otmp can be checked earlier] */
1288         /* verify the chosen object */
1289         if (!otmp) {
1290             You("don't have that object.");
1291             if (in_doagain)
1292                 return (struct obj *) 0;
1293             continue;
1294         } else if (cnt < 0 || otmp->quan < cnt) {
1295             You("don't have that many!  You have only %ld.", otmp->quan);
1296             if (in_doagain)
1297                 return (struct obj *) 0;
1298             continue;
1299         }
1300         break;
1301     }
1302     if (!allowall && let && !index(let, otmp->oclass)
1303         && !(usegold && otmp->oclass == COIN_CLASS)) {
1304         silly_thing(word, otmp);
1305         return (struct obj *) 0;
1306     }
1307     if (allowcnt == 2) { /* cnt given */
1308         if (cnt == 0)
1309             return (struct obj *) 0;
1310         if (cnt != otmp->quan) {
1311             /* don't split a stack of cursed loadstones */
1312             if (splittable(otmp))
1313                 otmp = splitobj(otmp, cnt);
1314             else if (otmp->otyp == LOADSTONE && otmp->cursed)
1315                 /* kludge for canletgo()'s can't-drop-this message */
1316                 otmp->corpsenm = (int) cnt;
1317         }
1318     }
1319     return otmp;
1320 }
1321
1322 void
1323 silly_thing(word, otmp)
1324 const char *word;
1325 struct obj *otmp;
1326 {
1327 #if 1 /* 'P','R' vs 'W','T' handling is obsolete */
1328     nhUse(otmp);
1329 #else
1330     const char *s1, *s2, *s3, *what;
1331     int ocls = otmp->oclass, otyp = otmp->otyp;
1332
1333     s1 = s2 = s3 = 0;
1334     /* check for attempted use of accessory commands ('P','R') on armor
1335        and for corresponding armor commands ('W','T') on accessories */
1336     if (ocls == ARMOR_CLASS) {
1337         if (!strcmp(word, "put on"))
1338             s1 = "W", s2 = "wear", s3 = "";
1339         else if (!strcmp(word, "remove"))
1340             s1 = "T", s2 = "take", s3 = " off";
1341     } else if ((ocls == RING_CLASS || otyp == MEAT_RING)
1342                || ocls == AMULET_CLASS
1343                || (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
1344         if (!strcmp(word, "wear"))
1345             s1 = "P", s2 = "put", s3 = " on";
1346         else if (!strcmp(word, "take off"))
1347             s1 = "R", s2 = "remove", s3 = "";
1348     }
1349     if (s1) {
1350         what = "that";
1351         /* quantity for armor and accessory objects is always 1,
1352            but some things should be referred to as plural */
1353         if (otyp == LENSES || is_gloves(otmp) || is_boots(otmp))
1354             what = "those";
1355         pline("Use the '%s' command to %s %s%s.", s1, s2, what, s3);
1356     } else
1357 #endif
1358         pline(silly_thing_to, word);
1359 }
1360
1361 STATIC_PTR int
1362 ckvalidcat(otmp)
1363 struct obj *otmp;
1364 {
1365     /* use allow_category() from pickup.c */
1366     return (int) allow_category(otmp);
1367 }
1368
1369 STATIC_PTR int
1370 ckunpaid(otmp)
1371 struct obj *otmp;
1372 {
1373     return (otmp->unpaid || (Has_contents(otmp) && count_unpaid(otmp->cobj)));
1374 }
1375
1376 boolean
1377 wearing_armor()
1378 {
1379     return (boolean) (uarm || uarmc || uarmf || uarmg
1380                       || uarmh || uarms || uarmu);
1381 }
1382
1383 boolean
1384 is_worn(otmp)
1385 struct obj *otmp;
1386 {
1387     return (otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_SADDLE | W_WEAPON))
1388             ? TRUE
1389             : FALSE;
1390 }
1391
1392 /* extra xprname() input that askchain() can't pass through safe_qbuf() */
1393 STATIC_VAR struct xprnctx {
1394     char let;
1395     boolean dot;
1396 } safeq_xprn_ctx;
1397
1398 /* safe_qbuf() -> short_oname() callback */
1399 STATIC_PTR char *
1400 safeq_xprname(obj)
1401 struct obj *obj;
1402 {
1403     return xprname(obj, (char *) 0, safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
1404                    0L, 0L);
1405 }
1406
1407 /* alternate safe_qbuf() -> short_oname() callback */
1408 STATIC_PTR char *
1409 safeq_shortxprname(obj)
1410 struct obj *obj;
1411 {
1412     return xprname(obj, ansimpleoname(obj), safeq_xprn_ctx.let,
1413                    safeq_xprn_ctx.dot, 0L, 0L);
1414 }
1415
1416 static NEARDATA const char removeables[] = { ARMOR_CLASS, WEAPON_CLASS,
1417                                              RING_CLASS,  AMULET_CLASS,
1418                                              TOOL_CLASS,  0 };
1419
1420 /* interactive version of getobj - used for Drop, Identify and */
1421 /* Takeoff (A). Return the number of times fn was called successfully */
1422 /* If combo is TRUE, we just use this to get a category list */
1423 int
1424 ggetobj(word, fn, mx, combo, resultflags)
1425 const char *word;
1426 int FDECL((*fn), (OBJ_P)), mx;
1427 boolean combo; /* combination menu flag */
1428 unsigned *resultflags;
1429 {
1430     int FDECL((*ckfn), (OBJ_P)) = (int FDECL((*), (OBJ_P))) 0;
1431     boolean FDECL((*filter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
1432     boolean takeoff, ident, allflag, m_seen;
1433     int itemcount;
1434     int oletct, iletct, unpaid, oc_of_sym;
1435     char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 5];
1436     char extra_removeables[3 + 1]; /* uwep,uswapwep,uquiver */
1437     char buf[BUFSZ], qbuf[QBUFSZ];
1438
1439     if (resultflags)
1440         *resultflags = 0;
1441     takeoff = ident = allflag = m_seen = FALSE;
1442     if (!invent) {
1443         You("have nothing to %s.", word);
1444         return 0;
1445     }
1446     add_valid_menu_class(0); /* reset */
1447     if (taking_off(word)) {
1448         takeoff = TRUE;
1449         filter = is_worn;
1450     } else if (!strcmp(word, "identify")) {
1451         ident = TRUE;
1452         filter = not_fully_identified;
1453     }
1454
1455     iletct = collect_obj_classes(ilets, invent, FALSE, filter, &itemcount);
1456     unpaid = count_unpaid(invent);
1457
1458     if (ident && !iletct) {
1459         return -1; /* no further identifications */
1460     } else if (!takeoff && (unpaid || invent)) {
1461         ilets[iletct++] = ' ';
1462         if (unpaid)
1463             ilets[iletct++] = 'u';
1464         if (count_buc(invent, BUC_BLESSED))
1465             ilets[iletct++] = 'B';
1466         if (count_buc(invent, BUC_UNCURSED))
1467             ilets[iletct++] = 'U';
1468         if (count_buc(invent, BUC_CURSED))
1469             ilets[iletct++] = 'C';
1470         if (count_buc(invent, BUC_UNKNOWN))
1471             ilets[iletct++] = 'X';
1472         if (invent)
1473             ilets[iletct++] = 'a';
1474     } else if (takeoff && invent) {
1475         ilets[iletct++] = ' ';
1476     }
1477     ilets[iletct++] = 'i';
1478     if (!combo)
1479         ilets[iletct++] = 'm'; /* allow menu presentation on request */
1480     ilets[iletct] = '\0';
1481
1482     for (;;) {
1483         Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]", word,
1484                 ilets);
1485         getlin(qbuf, buf);
1486         if (buf[0] == '\033')
1487             return 0;
1488         if (index(buf, 'i')) {
1489             if (display_inventory((char *) 0, TRUE) == '\033')
1490                 return 0;
1491         } else
1492             break;
1493     }
1494
1495     extra_removeables[0] = '\0';
1496     if (takeoff) {
1497         /* arbitrary types of items can be placed in the weapon slots
1498            [any duplicate entries in extra_removeables[] won't matter] */
1499         if (uwep)
1500             (void) strkitten(extra_removeables, uwep->oclass);
1501         if (uswapwep)
1502             (void) strkitten(extra_removeables, uswapwep->oclass);
1503         if (uquiver)
1504             (void) strkitten(extra_removeables, uquiver->oclass);
1505     }
1506
1507     ip = buf;
1508     olets[oletct = 0] = '\0';
1509     while ((sym = *ip++) != '\0') {
1510         if (sym == ' ')
1511             continue;
1512         oc_of_sym = def_char_to_objclass(sym);
1513         if (takeoff && oc_of_sym != MAXOCLASSES) {
1514             if (index(extra_removeables, oc_of_sym)) {
1515                 ; /* skip rest of takeoff checks */
1516             } else if (!index(removeables, oc_of_sym)) {
1517                 pline("Not applicable.");
1518                 return 0;
1519             } else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
1520                 noarmor(FALSE);
1521                 return 0;
1522             } else if (oc_of_sym == WEAPON_CLASS && !uwep && !uswapwep
1523                        && !uquiver) {
1524                 You("are not wielding anything.");
1525                 return 0;
1526             } else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
1527                 You("are not wearing rings.");
1528                 return 0;
1529             } else if (oc_of_sym == AMULET_CLASS && !uamul) {
1530                 You("are not wearing an amulet.");
1531                 return 0;
1532             } else if (oc_of_sym == TOOL_CLASS && !ublindf) {
1533                 You("are not wearing a blindfold.");
1534                 return 0;
1535             }
1536         }
1537
1538         if (oc_of_sym == COIN_CLASS && !combo) {
1539             context.botl = 1;
1540         } else if (sym == 'a') {
1541             allflag = TRUE;
1542         } else if (sym == 'A') {
1543             /* same as the default */;
1544         } else if (sym == 'u') {
1545             add_valid_menu_class('u');
1546             ckfn = ckunpaid;
1547         } else if (sym == 'B') {
1548             add_valid_menu_class('B');
1549             ckfn = ckvalidcat;
1550         } else if (sym == 'U') {
1551             add_valid_menu_class('U');
1552             ckfn = ckvalidcat;
1553         } else if (sym == 'C') {
1554             add_valid_menu_class('C');
1555             ckfn = ckvalidcat;
1556         } else if (sym == 'X') {
1557             add_valid_menu_class('X');
1558             ckfn = ckvalidcat;
1559         } else if (sym == 'm') {
1560             m_seen = TRUE;
1561         } else if (oc_of_sym == MAXOCLASSES) {
1562             You("don't have any %c's.", sym);
1563         } else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */
1564             if (!index(olets, oc_of_sym)) {
1565                 add_valid_menu_class(oc_of_sym);
1566                 olets[oletct++] = oc_of_sym;
1567                 olets[oletct] = 0;
1568             }
1569         }
1570     }
1571
1572     if (m_seen) {
1573         return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3;
1574     } else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) {
1575         return 0;
1576 #if 0
1577     /* !!!! test gold dropping */
1578     } else if (allowgold == 2 && !oletct) {
1579         return 1; /* you dropped gold (or at least tried to)  */
1580 #endif
1581     } else {
1582         int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
1583         /*
1584          * askchain() has already finished the job in this case
1585          * so set a special flag to convey that back to the caller
1586          * so that it won't continue processing.
1587          * Fix for bug C331-1 reported by Irina Rempt-Drijfhout.
1588          */
1589         if (combo && allflag && resultflags)
1590             *resultflags |= ALL_FINISHED;
1591         return cnt;
1592     }
1593 }
1594
1595 /*
1596  * Walk through the chain starting at objchn and ask for all objects
1597  * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
1598  * whether the action in question (i.e., fn) has to be performed.
1599  * If allflag then no questions are asked. Max gives the max nr of
1600  * objects to be treated. Return the number of objects treated.
1601  */
1602 int
1603 askchain(objchn, olets, allflag, fn, ckfn, mx, word)
1604 struct obj **objchn;
1605 register int allflag, mx;
1606 register const char *olets, *word; /* olets is an Obj Class char array */
1607 register int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
1608 {
1609     struct obj *otmp, *otmpo;
1610     register char sym, ilet;
1611     register int cnt = 0, dud = 0, tmp;
1612     boolean takeoff, nodot, ident, take_out, put_in, first, ininv;
1613     char qbuf[QBUFSZ], qpfx[QBUFSZ];
1614
1615     takeoff = taking_off(word);
1616     ident = !strcmp(word, "identify");
1617     take_out = !strcmp(word, "take out");
1618     put_in = !strcmp(word, "put in");
1619     nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
1620              || takeoff || take_out || put_in);
1621     ininv = (*objchn == invent);
1622     first = TRUE;
1623 /* Changed so the askchain is interrogated in the order specified.
1624  * For example, if a person specifies =/ then first all rings will be
1625  * asked about followed by all wands -dgk
1626  */
1627 nextclass:
1628     ilet = 'a' - 1;
1629     if (*objchn && (*objchn)->oclass == COIN_CLASS)
1630         ilet--;                     /* extra iteration */
1631     /*
1632      * Multiple Drop can change the invent chain while it operates
1633      * (dropping a burning potion of oil while levitating creates
1634      * an explosion which can destroy inventory items), so simple
1635      * list traversal
1636      *  for (otmp = *objchn; otmp; otmp = otmp2) {
1637      *      otmp2 = otmp->nobj;
1638      *      ...
1639      *  }
1640      * is inadequate here.  Use each object's bypass bit to keep
1641      * track of which list elements have already been processed.
1642      */
1643     bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */
1644     while ((otmp = nxt_unbypassed_obj(*objchn)) != 0) {
1645         if (ilet == 'z')
1646             ilet = 'A';
1647         else
1648             ilet++;
1649         if (olets && *olets && otmp->oclass != *olets)
1650             continue;
1651         if (takeoff && !is_worn(otmp))
1652             continue;
1653         if (ident && !not_fully_identified(otmp))
1654             continue;
1655         if (ckfn && !(*ckfn)(otmp))
1656             continue;
1657         if (!allflag) {
1658             safeq_xprn_ctx.let = ilet;
1659             safeq_xprn_ctx.dot = !nodot;
1660             *qpfx = '\0';
1661             if (first) {
1662                 /* traditional_loot() skips prompting when only one
1663                    class of objects is involved, so prefix the first
1664                    object being queried here with an explanation why */
1665                 if (take_out || put_in)
1666                     Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
1667                 first = FALSE;
1668             }
1669             (void) safe_qbuf(
1670                 qbuf, qpfx, "?", otmp, ininv ? safeq_xprname : doname,
1671                 ininv ? safeq_shortxprname : ansimpleoname, "item");
1672             sym = (takeoff || ident || otmp->quan < 2L) ? nyaq(qbuf)
1673                                                         : nyNaq(qbuf);
1674         } else
1675             sym = 'y';
1676
1677         otmpo = otmp;
1678         if (sym == '#') {
1679             /* Number was entered; split the object unless it corresponds
1680                to 'none' or 'all'.  2 special cases: cursed loadstones and
1681                welded weapons (eg, multiple daggers) will remain as merged
1682                unit; done to avoid splitting an object that won't be
1683                droppable (even if we're picking up rather than dropping).
1684              */
1685             if (!yn_number)
1686                 sym = 'n';
1687             else {
1688                 sym = 'y';
1689                 if (yn_number < otmp->quan && splittable(otmp))
1690                     otmp = splitobj(otmp, yn_number);
1691             }
1692         }
1693         switch (sym) {
1694         case 'a':
1695             allflag = 1;
1696         case 'y':
1697             tmp = (*fn)(otmp);
1698             if (tmp < 0) {
1699                 if (container_gone(fn)) {
1700                     /* otmp caused magic bag to explode;
1701                        both are now gone */
1702                     otmp = 0; /* and return */
1703                 } else if (otmp && otmp != otmpo) {
1704                     /* split occurred, merge again */
1705                     (void) merged(&otmpo, &otmp);
1706                 }
1707                 goto ret;
1708             }
1709             cnt += tmp;
1710             if (--mx == 0)
1711                 goto ret;
1712         case 'n':
1713             if (nodot)
1714                 dud++;
1715         default:
1716             break;
1717         case 'q':
1718             /* special case for seffects() */
1719             if (ident)
1720                 cnt = -1;
1721             goto ret;
1722         }
1723     }
1724     if (olets && *olets && *++olets)
1725         goto nextclass;
1726     if (!takeoff && (dud || cnt))
1727         pline("That was all.");
1728     else if (!dud && !cnt)
1729         pline("No applicable objects.");
1730 ret:
1731     bypass_objlist(*objchn, FALSE);
1732     return cnt;
1733 }
1734
1735 /*
1736  *      Object identification routines:
1737  */
1738
1739 /* make an object actually be identified; no display updating */
1740 void
1741 fully_identify_obj(otmp)
1742 struct obj *otmp;
1743 {
1744     makeknown(otmp->otyp);
1745     if (otmp->oartifact)
1746         discover_artifact((xchar) otmp->oartifact);
1747     otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
1748     if (Is_container(otmp) || otmp->otyp == STATUE)
1749         otmp->cknown = otmp->lknown = 1;
1750     if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
1751         learn_egg_type(otmp->corpsenm);
1752 }
1753
1754 /* ggetobj callback routine; identify an object and give immediate feedback */
1755 int
1756 identify(otmp)
1757 struct obj *otmp;
1758 {
1759     fully_identify_obj(otmp);
1760     prinv((char *) 0, otmp, 0L);
1761     return 1;
1762 }
1763
1764 /* menu of unidentified objects; select and identify up to id_limit of them */
1765 STATIC_OVL void
1766 menu_identify(id_limit)
1767 int id_limit;
1768 {
1769     menu_item *pick_list;
1770     int n, i, first = 1, tryct = 5;
1771     char buf[BUFSZ];
1772     /* assumptions:  id_limit > 0 and at least one unID'd item is present */
1773
1774     while (id_limit) {
1775         Sprintf(buf, "What would you like to identify %s?",
1776                 first ? "first" : "next");
1777         n = query_objlist(buf, invent, SIGNAL_NOMENU | SIGNAL_ESCAPE
1778                                            | USE_INVLET | INVORDER_SORT,
1779                           &pick_list, PICK_ANY, not_fully_identified);
1780
1781         if (n > 0) {
1782             if (n > id_limit)
1783                 n = id_limit;
1784             for (i = 0; i < n; i++, id_limit--)
1785                 (void) identify(pick_list[i].item.a_obj);
1786             free((genericptr_t) pick_list);
1787             mark_synch(); /* Before we loop to pop open another menu */
1788             first = 0;
1789         } else if (n == -2) { /* player used ESC to quit menu */
1790             break;
1791         } else if (n == -1) { /* no eligible items found */
1792             pline("That was all.");
1793             break;
1794         } else if (!--tryct) { /* stop re-prompting */
1795             pline1(thats_enough_tries);
1796             break;
1797         } else { /* try again */
1798             pline("Choose an item; use ESC to decline.");
1799         }
1800     }
1801 }
1802
1803 /* dialog with user to identify a given number of items; 0 means all */
1804 void
1805 identify_pack(id_limit, learning_id)
1806 int id_limit;
1807 boolean learning_id; /* true if we just read unknown identify scroll */
1808 {
1809     struct obj *obj, *the_obj;
1810     int n, unid_cnt;
1811
1812     unid_cnt = 0;
1813     the_obj = 0; /* if unid_cnt ends up 1, this will be it */
1814     for (obj = invent; obj; obj = obj->nobj)
1815         if (not_fully_identified(obj))
1816             ++unid_cnt, the_obj = obj;
1817
1818     if (!unid_cnt) {
1819         You("have already identified all %sof your possessions.",
1820             learning_id ? "the rest " : "");
1821     } else if (!id_limit || id_limit >= unid_cnt) {
1822         /* identify everything */
1823         if (unid_cnt == 1) {
1824             (void) identify(the_obj);
1825         } else {
1826             /* TODO:  use fully_identify_obj and cornline/menu/whatever here
1827              */
1828             for (obj = invent; obj; obj = obj->nobj)
1829                 if (not_fully_identified(obj))
1830                     (void) identify(obj);
1831         }
1832     } else {
1833         /* identify up to `id_limit' items */
1834         n = 0;
1835         if (flags.menu_style == MENU_TRADITIONAL)
1836             do {
1837                 n = ggetobj("identify", identify, id_limit, FALSE,
1838                             (unsigned *) 0);
1839                 if (n < 0)
1840                     break; /* quit or no eligible items */
1841             } while ((id_limit -= n) > 0);
1842         if (n == 0 || n < -1)
1843             menu_identify(id_limit);
1844     }
1845     update_inventory();
1846 }
1847
1848 /* called when regaining sight; mark inventory objects which were picked
1849    up while blind as now having been seen */
1850 void
1851 learn_unseen_invent()
1852 {
1853     struct obj *otmp;
1854
1855     if (Blind)
1856         return; /* sanity check */
1857
1858     for (otmp = invent; otmp; otmp = otmp->nobj) {
1859         if (otmp->dknown)
1860             continue; /* already seen */
1861         /* set dknown, perhaps bknown (for priest[ess]) */
1862         (void) xname(otmp);
1863         /*
1864          * If object->eknown gets implemented (see learnwand(zap.c)),
1865          * handle deferred discovery here.
1866          */
1867     }
1868     update_inventory();
1869 }
1870
1871 /* should of course only be called for things in invent */
1872 STATIC_OVL char
1873 obj_to_let(obj)
1874 struct obj *obj;
1875 {
1876     if (!flags.invlet_constant) {
1877         obj->invlet = NOINVSYM;
1878         reassign();
1879     }
1880     return obj->invlet;
1881 }
1882
1883 /*
1884  * Print the indicated quantity of the given object.  If quan == 0L then use
1885  * the current quantity.
1886  */
1887 void
1888 prinv(prefix, obj, quan)
1889 const char *prefix;
1890 struct obj *obj;
1891 long quan;
1892 {
1893     if (!prefix)
1894         prefix = "";
1895     pline("%s%s%s", prefix, *prefix ? " " : "",
1896           xprname(obj, (char *) 0, obj_to_let(obj), TRUE, 0L, quan));
1897 }
1898
1899 char *
1900 xprname(obj, txt, let, dot, cost, quan)
1901 struct obj *obj;
1902 const char *txt; /* text to print instead of obj */
1903 char let;        /* inventory letter */
1904 boolean dot;     /* append period; (dot && cost => Iu) */
1905 long cost;       /* cost (for inventory of unpaid or expended items) */
1906 long quan;       /* if non-0, print this quantity, not obj->quan */
1907 {
1908 #ifdef LINT /* handle static char li[BUFSZ]; */
1909     char li[BUFSZ];
1910 #else
1911     static char li[BUFSZ];
1912 #endif
1913     boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM;
1914     long savequan = 0;
1915
1916     if (quan && obj) {
1917         savequan = obj->quan;
1918         obj->quan = quan;
1919     }
1920
1921     /*
1922      * If let is:
1923      *  *  Then obj == null and we are printing a total amount.
1924      *  >  Then the object is contained and doesn't have an inventory letter.
1925      */
1926     if (cost != 0 || let == '*') {
1927         /* if dot is true, we're doing Iu, otherwise Ix */
1928         Sprintf(li, "%c - %-45s %6ld %s",
1929                 (dot && use_invlet ? obj->invlet : let),
1930                 (txt ? txt : doname(obj)), cost, currency(cost));
1931     } else {
1932         /* ordinary inventory display or pickup message */
1933         Sprintf(li, "%c - %s%s", (use_invlet ? obj->invlet : let),
1934                 (txt ? txt : doname(obj)), (dot ? "." : ""));
1935     }
1936     if (savequan)
1937         obj->quan = savequan;
1938
1939     return li;
1940 }
1941
1942 /* the 'i' command */
1943 int
1944 ddoinv()
1945 {
1946     (void) display_inventory((char *) 0, FALSE);
1947     return 0;
1948 }
1949
1950 /*
1951  * find_unpaid()
1952  *
1953  * Scan the given list of objects.  If last_found is NULL, return the first
1954  * unpaid object found.  If last_found is not NULL, then skip over unpaid
1955  * objects until last_found is reached, then set last_found to NULL so the
1956  * next unpaid object is returned.  This routine recursively follows
1957  * containers.
1958  */
1959 STATIC_OVL struct obj *
1960 find_unpaid(list, last_found)
1961 struct obj *list, **last_found;
1962 {
1963     struct obj *obj;
1964
1965     while (list) {
1966         if (list->unpaid) {
1967             if (*last_found) {
1968                 /* still looking for previous unpaid object */
1969                 if (list == *last_found)
1970                     *last_found = (struct obj *) 0;
1971             } else
1972                 return ((*last_found = list));
1973         }
1974         if (Has_contents(list)) {
1975             if ((obj = find_unpaid(list->cobj, last_found)) != 0)
1976                 return obj;
1977         }
1978         list = list->nobj;
1979     }
1980     return (struct obj *) 0;
1981 }
1982
1983 /* for perm_invent when operating on a partial inventory display, so that
1984    the persistent one doesn't get shrunk during filtering for item selection
1985    then regrown to full inventory, possibly being resized in the process */
1986 static winid cached_pickinv_win = WIN_ERR;
1987
1988 void
1989 free_pickinv_cache()
1990 {
1991     if (cached_pickinv_win != WIN_ERR) {
1992         destroy_nhwindow(cached_pickinv_win);
1993         cached_pickinv_win = WIN_ERR;
1994     }
1995 }
1996
1997 /*
1998  * Internal function used by display_inventory and getobj that can display
1999  * inventory and return a count as well as a letter. If out_cnt is not null,
2000  * any count returned from the menu selection is placed here.
2001  */
2002 STATIC_OVL char
2003 display_pickinv(lets, want_reply, out_cnt)
2004 register const char *lets;
2005 boolean want_reply;
2006 long *out_cnt;
2007 {
2008     struct obj *otmp;
2009     char ilet, ret;
2010     char *invlet = flags.inv_order;
2011     int i, n, classcount;
2012     winid win;                        /* windows being used */
2013     anything any;
2014     menu_item *selected;
2015     struct obj **oarray;
2016
2017     if (flags.perm_invent && lets && *lets) {
2018         /* partial inventory in perm_invent setting; don't operate on
2019            full inventory window, use an alternate one instead; create
2020            the first time needed and keep it for re-use as needed later */
2021         if (cached_pickinv_win == WIN_ERR)
2022             cached_pickinv_win = create_nhwindow(NHW_MENU);
2023         win = cached_pickinv_win;
2024     } else
2025         win = WIN_INVEN;
2026
2027     /*
2028      * Exit early if no inventory -- but keep going if we are doing
2029      * a permanent inventory update.  We need to keep going so the
2030      * permanent inventory window updates itself to remove the last
2031      * item(s) dropped.  One down side:  the addition of the exception
2032      * for permanent inventory window updates _can_ pop the window
2033      * up when it's not displayed -- even if it's empty -- because we
2034      * don't know at this level if its up or not.  This may not be
2035      * an issue if empty checks are done before hand and the call
2036      * to here is short circuited away.
2037      */
2038     if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
2039         pline("Not carrying anything.");
2040         return 0;
2041     }
2042
2043     /* oxymoron? temporarily assign permanent inventory letters */
2044     if (!flags.invlet_constant)
2045         reassign();
2046
2047     if (lets && strlen(lets) == 1 && !iflags.override_ID) {
2048         /* when only one item of interest, use pline instead of menus;
2049            we actually use a fake message-line menu in order to allow
2050            the user to perform selection at the --More-- prompt for tty */
2051         ret = '\0';
2052         for (otmp = invent; otmp; otmp = otmp->nobj) {
2053             if (otmp->invlet == lets[0]) {
2054                 ret = message_menu(
2055                     lets[0], want_reply ? PICK_ONE : PICK_NONE,
2056                     xprname(otmp, (char *) 0, lets[0], TRUE, 0L, 0L));
2057                 if (out_cnt)
2058                     *out_cnt = -1L; /* select all */
2059                 break;
2060             }
2061         }
2062         return ret;
2063     }
2064
2065     /* count the number of items */
2066     for (n = 0, otmp = invent; otmp; otmp = otmp->nobj)
2067         if (!lets || !*lets || index(lets, otmp->invlet))
2068             n++;
2069
2070     oarray = objarr_init(n);
2071
2072     /* Add objects to the array */
2073     i = 0;
2074     for (otmp = invent; otmp; otmp = otmp->nobj)
2075         if (!lets || !*lets || index(lets, otmp->invlet)) {
2076             objarr_set(otmp, i++, oarray, (flags.sortloot == 'f'));
2077         }
2078
2079     start_menu(win);
2080     any = zeroany;
2081     if (wizard && iflags.override_ID) {
2082         char prompt[BUFSZ];
2083         any.a_char = -1;
2084         /* wiz_identify stuffed the wiz_identify cmd character
2085            into iflags.override_ID */
2086         Sprintf(prompt, "Debug Identify (%s to permanently identify)",
2087                 visctrl(iflags.override_ID));
2088         add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
2089                  prompt, MENU_UNSELECTED);
2090     }
2091 nextclass:
2092     classcount = 0;
2093     any = zeroany; /* set all bits to zero */
2094     for (i = 0; i < n; i++) {
2095         otmp = oarray[i];
2096         ilet = otmp->invlet;
2097         any = zeroany; /* zero */
2098         if (!flags.sortpack || otmp->oclass == *invlet) {
2099             if (flags.sortpack && !classcount) {
2100                 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2101                          let_to_name(*invlet, FALSE,
2102                                      (want_reply && iflags.menu_head_objsym)),
2103                          MENU_UNSELECTED);
2104                 classcount++;
2105             }
2106             any.a_char = ilet;
2107             add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE,
2108                      doname(otmp), MENU_UNSELECTED);
2109         }
2110     }
2111     if (flags.sortpack) {
2112         if (*++invlet)
2113             goto nextclass;
2114         if (--invlet != venom_inv) {
2115             invlet = venom_inv;
2116             goto nextclass;
2117         }
2118     }
2119     free(oarray);
2120     end_menu(win, (char *) 0);
2121
2122     n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
2123     if (n > 0) {
2124         ret = selected[0].item.a_char;
2125         if (out_cnt)
2126             *out_cnt = selected[0].count;
2127         free((genericptr_t) selected);
2128     } else
2129         ret = !n ? '\0' : '\033'; /* cancelled */
2130
2131     return ret;
2132 }
2133
2134 /*
2135  * If lets == NULL or "", list all objects in the inventory.  Otherwise,
2136  * list all objects with object classes that match the order in lets.
2137  *
2138  * Returns the letter identifier of a selected item, or 0 if nothing
2139  * was selected.
2140  */
2141 char
2142 display_inventory(lets, want_reply)
2143 const char *lets;
2144 boolean want_reply;
2145 {
2146     return display_pickinv(lets, want_reply, (long *) 0);
2147 }
2148
2149 /*
2150  * Show what is current using inventory letters.
2151  *
2152  */
2153 STATIC_OVL char
2154 display_used_invlets(avoidlet)
2155 char avoidlet;
2156 {
2157     struct obj *otmp;
2158     char ilet, ret = 0;
2159     char *invlet = flags.inv_order;
2160     int n, classcount, invdone = 0;
2161     winid win;
2162     anything any;
2163     menu_item *selected;
2164
2165     if (invent) {
2166         win = create_nhwindow(NHW_MENU);
2167         start_menu(win);
2168         while (!invdone) {
2169             any = zeroany; /* set all bits to zero */
2170             classcount = 0;
2171             for (otmp = invent; otmp; otmp = otmp->nobj) {
2172                 ilet = otmp->invlet;
2173                 if (ilet == avoidlet)
2174                     continue;
2175                 if (!flags.sortpack || otmp->oclass == *invlet) {
2176                     if (flags.sortpack && !classcount) {
2177                         any = zeroany; /* zero */
2178                         add_menu(win, NO_GLYPH, &any, 0, 0,
2179                                  iflags.menu_headings,
2180                                  let_to_name(*invlet, FALSE, FALSE),
2181                                  MENU_UNSELECTED);
2182                         classcount++;
2183                     }
2184                     any.a_char = ilet;
2185                     add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE,
2186                              doname(otmp), MENU_UNSELECTED);
2187                 }
2188             }
2189             if (flags.sortpack && *++invlet)
2190                 continue;
2191             invdone = 1;
2192         }
2193         end_menu(win, "Inventory letters used:");
2194
2195         n = select_menu(win, PICK_NONE, &selected);
2196         if (n > 0) {
2197             ret = selected[0].item.a_char;
2198             free((genericptr_t) selected);
2199         } else
2200             ret = !n ? '\0' : '\033'; /* cancelled */
2201         destroy_nhwindow(win);
2202     }
2203     return ret;
2204 }
2205
2206 /*
2207  * Returns the number of unpaid items within the given list.  This includes
2208  * contained objects.
2209  */
2210 int
2211 count_unpaid(list)
2212 struct obj *list;
2213 {
2214     int count = 0;
2215
2216     while (list) {
2217         if (list->unpaid)
2218             count++;
2219         if (Has_contents(list))
2220             count += count_unpaid(list->cobj);
2221         list = list->nobj;
2222     }
2223     return count;
2224 }
2225
2226 /*
2227  * Returns the number of items with b/u/c/unknown within the given list.
2228  * This does NOT include contained objects.
2229  *
2230  * Assumes that the hero sees or touches or otherwise senses the objects
2231  * at some point:  bknown is forced for priest[ess], like in xname().
2232  */
2233 int
2234 count_buc(list, type)
2235 struct obj *list;
2236 int type;
2237 {
2238     int count = 0;
2239
2240     for (; list; list = list->nobj) {
2241         /* coins are "none of the above" as far as BUCX filtering goes */
2242         if (list->oclass == COIN_CLASS)
2243             continue;
2244         /* priests always know bless/curse state */
2245         if (Role_if(PM_PRIEST))
2246             list->bknown = 1;
2247
2248         /* check whether this object matches the requested type */
2249         if (!list->bknown
2250                 ? (type == BUC_UNKNOWN)
2251                 : list->blessed ? (type == BUC_BLESSED)
2252                                 : list->cursed ? (type == BUC_CURSED)
2253                                                : (type == BUC_UNCURSED))
2254             ++count;
2255     }
2256     return count;
2257 }
2258
2259 /* similar to count_buc(), but tallies all states at once
2260    rather than looking for a specific type */
2261 STATIC_OVL void
2262 tally_BUCX(list, bcp, ucp, ccp, xcp, ocp)
2263 struct obj *list;
2264 int *bcp, *ucp, *ccp, *xcp, *ocp;
2265 {
2266     *bcp = *ucp = *ccp = *xcp = *ocp = 0;
2267     for (; list; list = list->nobj) {
2268         if (list->oclass == COIN_CLASS) {
2269             ++(*ocp); /* "other" */
2270             continue;
2271         }
2272         /* priests always know bless/curse state */
2273         if (Role_if(PM_PRIEST))
2274             list->bknown = 1;
2275
2276         if (!list->bknown)
2277             ++(*xcp);
2278         else if (list->blessed)
2279             ++(*bcp);
2280         else if (list->cursed)
2281             ++(*ccp);
2282         else /* neither blessed nor cursed => uncursed */
2283             ++(*ucp);
2284     }
2285 }
2286
2287 long
2288 count_contents(container, nested, quantity, everything)
2289 struct obj *container;
2290 boolean nested, /* include contents of any nested containers */
2291     quantity,   /* count all vs count separate stacks */
2292     everything; /* all objects vs only unpaid objects */
2293 {
2294     struct obj *otmp;
2295     long count = 0L;
2296
2297     for (otmp = container->cobj; otmp; otmp = otmp->nobj) {
2298         if (nested && Has_contents(otmp))
2299             count += count_contents(otmp, nested, quantity, everything);
2300         if (everything || otmp->unpaid)
2301             count += quantity ? otmp->quan : 1L;
2302     }
2303     return count;
2304 }
2305
2306 STATIC_OVL void
2307 dounpaid()
2308 {
2309     winid win;
2310     struct obj *otmp, *marker;
2311     register char ilet;
2312     char *invlet = flags.inv_order;
2313     int classcount, count, num_so_far;
2314     long cost, totcost;
2315
2316     count = count_unpaid(invent);
2317
2318     if (count == 1) {
2319         marker = (struct obj *) 0;
2320         otmp = find_unpaid(invent, &marker);
2321         cost = unpaid_cost(otmp, FALSE);
2322         iflags.suppress_price++; /* suppress "(unpaid)" suffix */
2323         pline1(xprname(otmp, distant_name(otmp, doname),
2324                        carried(otmp) ? otmp->invlet : CONTAINED_SYM, TRUE,
2325                        cost, 0L));
2326         iflags.suppress_price--;
2327         return;
2328     }
2329
2330     win = create_nhwindow(NHW_MENU);
2331     cost = totcost = 0;
2332     num_so_far = 0; /* count of # printed so far */
2333     if (!flags.invlet_constant)
2334         reassign();
2335
2336     do {
2337         classcount = 0;
2338         for (otmp = invent; otmp; otmp = otmp->nobj) {
2339             ilet = otmp->invlet;
2340             if (otmp->unpaid) {
2341                 if (!flags.sortpack || otmp->oclass == *invlet) {
2342                     if (flags.sortpack && !classcount) {
2343                         putstr(win, 0, let_to_name(*invlet, TRUE, FALSE));
2344                         classcount++;
2345                     }
2346
2347                     totcost += cost = unpaid_cost(otmp, FALSE);
2348                     iflags.suppress_price++; /* suppress "(unpaid)" suffix */
2349                     putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
2350                                            ilet, TRUE, cost, 0L));
2351                     iflags.suppress_price--;
2352                     num_so_far++;
2353                 }
2354             }
2355         }
2356     } while (flags.sortpack && (*++invlet));
2357
2358     if (count > num_so_far) {
2359         /* something unpaid is contained */
2360         if (flags.sortpack)
2361             putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE, FALSE));
2362         /*
2363          * Search through the container objects in the inventory for
2364          * unpaid items.  The top level inventory items have already
2365          * been listed.
2366          */
2367         for (otmp = invent; otmp; otmp = otmp->nobj) {
2368             if (Has_contents(otmp)) {
2369                 long contcost = 0L;
2370
2371                 marker = (struct obj *) 0; /* haven't found any */
2372                 while (find_unpaid(otmp->cobj, &marker)) {
2373                     totcost += cost = unpaid_cost(marker, FALSE);
2374                     contcost += cost;
2375                     if (otmp->cknown) {
2376                         iflags.suppress_price++; /* suppress "(unpaid)" sfx */
2377                         putstr(win, 0,
2378                                xprname(marker, distant_name(marker, doname),
2379                                        CONTAINED_SYM, TRUE, cost, 0L));
2380                         iflags.suppress_price--;
2381                     }
2382                 }
2383                 if (!otmp->cknown) {
2384                     char contbuf[BUFSZ];
2385
2386                     /* Shopkeeper knows what to charge for contents */
2387                     Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
2388                     putstr(win, 0,
2389                            xprname((struct obj *) 0, contbuf, CONTAINED_SYM,
2390                                    TRUE, contcost, 0L));
2391                 }
2392             }
2393         }
2394     }
2395
2396     putstr(win, 0, "");
2397     putstr(win, 0,
2398            xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
2399     display_nhwindow(win, FALSE);
2400     destroy_nhwindow(win);
2401 }
2402
2403 /* query objlist callback: return TRUE if obj type matches "this_type" */
2404 static int this_type;
2405
2406 STATIC_OVL boolean
2407 this_type_only(obj)
2408 struct obj *obj;
2409 {
2410     boolean res = (obj->oclass == this_type);
2411
2412     if (obj->oclass != COIN_CLASS) {
2413         switch (this_type) {
2414         case 'B':
2415             res = (obj->bknown && obj->blessed);
2416             break;
2417         case 'U':
2418             res = (obj->bknown && !(obj->blessed || obj->cursed));
2419             break;
2420         case 'C':
2421             res = (obj->bknown && obj->cursed);
2422             break;
2423         case 'X':
2424             res = !obj->bknown;
2425             break;
2426         default:
2427             break; /* use 'res' as-is */
2428         }
2429     }
2430     return res;
2431 }
2432
2433 /* the 'I' command */
2434 int
2435 dotypeinv()
2436 {
2437     char c = '\0';
2438     int n, i = 0;
2439     char *extra_types, types[BUFSZ];
2440     int class_count, oclass, unpaid_count, itemcount;
2441     int bcnt, ccnt, ucnt, xcnt, ocnt;
2442     boolean billx = *u.ushops && doinvbill(0);
2443     menu_item *pick_list;
2444     boolean traditional = TRUE;
2445     const char *prompt = "What type of object do you want an inventory of?";
2446
2447     if (!invent && !billx) {
2448         You("aren't carrying anything.");
2449         return 0;
2450     }
2451     unpaid_count = count_unpaid(invent);
2452     tally_BUCX(invent, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
2453
2454     if (flags.menu_style != MENU_TRADITIONAL) {
2455         if (flags.menu_style == MENU_FULL
2456             || flags.menu_style == MENU_PARTIAL) {
2457             traditional = FALSE;
2458             i = UNPAID_TYPES;
2459             if (billx)
2460                 i |= BILLED_TYPES;
2461             if (bcnt)
2462                 i |= BUC_BLESSED;
2463             if (ucnt)
2464                 i |= BUC_UNCURSED;
2465             if (ccnt)
2466                 i |= BUC_CURSED;
2467             if (xcnt)
2468                 i |= BUC_UNKNOWN;
2469             n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
2470             if (!n)
2471                 return 0;
2472             this_type = c = pick_list[0].item.a_int;
2473             free((genericptr_t) pick_list);
2474         }
2475     }
2476     if (traditional) {
2477         /* collect a list of classes of objects carried, for use as a prompt
2478          */
2479         types[0] = 0;
2480         class_count =
2481             collect_obj_classes(types, invent, FALSE,
2482                                 (boolean FDECL((*), (OBJ_P))) 0, &itemcount);
2483         if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
2484             types[class_count++] = ' ';
2485         if (unpaid_count)
2486             types[class_count++] = 'u';
2487         if (billx)
2488             types[class_count++] = 'x';
2489         if (bcnt)
2490             types[class_count++] = 'B';
2491         if (ucnt)
2492             types[class_count++] = 'U';
2493         if (ccnt)
2494             types[class_count++] = 'C';
2495         if (xcnt)
2496             types[class_count++] = 'X';
2497         types[class_count] = '\0';
2498         /* add everything not already included; user won't see these */
2499         extra_types = eos(types);
2500         *extra_types++ = '\033';
2501         if (!unpaid_count)
2502             *extra_types++ = 'u';
2503         if (!billx)
2504             *extra_types++ = 'x';
2505         if (!bcnt)
2506             *extra_types++ = 'B';
2507         if (!ucnt)
2508             *extra_types++ = 'U';
2509         if (!ccnt)
2510             *extra_types++ = 'C';
2511         if (!xcnt)
2512             *extra_types++ = 'X';
2513         *extra_types = '\0'; /* for index() */
2514         for (i = 0; i < MAXOCLASSES; i++)
2515             if (!index(types, def_oc_syms[i].sym)) {
2516                 *extra_types++ = def_oc_syms[i].sym;
2517                 *extra_types = '\0';
2518             }
2519
2520         if (class_count > 1) {
2521             c = yn_function(prompt, types, '\0');
2522             savech(c);
2523             if (c == '\0') {
2524                 clear_nhwindow(WIN_MESSAGE);
2525                 return 0;
2526             }
2527         } else {
2528             /* only one thing to itemize */
2529             if (unpaid_count)
2530                 c = 'u';
2531             else if (billx)
2532                 c = 'x';
2533             else
2534                 c = types[0];
2535         }
2536     }
2537     if (c == 'x' || (c == 'X' && billx && !xcnt)) {
2538         if (billx)
2539             (void) doinvbill(1);
2540         else
2541             pline("No used-up objects%s.",
2542                   unpaid_count ? " on your shopping bill" : "");
2543         return 0;
2544     }
2545     if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
2546         if (unpaid_count)
2547             dounpaid();
2548         else
2549             You("are not carrying any unpaid objects.");
2550         return 0;
2551     }
2552     if (traditional) {
2553         if (index("BUCX", c))
2554             oclass = c; /* not a class but understood by this_type_only() */
2555         else
2556             oclass = def_char_to_objclass(c); /* change to object class */
2557
2558         if (oclass == COIN_CLASS)
2559             return doprgold();
2560         if (index(types, c) > index(types, '\033')) {
2561             /* '> ESC' => hidden choice, something known not to be carried */
2562             const char *which = 0;
2563
2564             switch (c) {
2565             case 'B':
2566                 which = "known to be blessed";
2567                 break;
2568             case 'U':
2569                 which = "known to be uncursed";
2570                 break;
2571             case 'C':
2572                 which = "known to be cursed";
2573                 break;
2574             case 'X':
2575                 You(
2576           "have no objects whose blessed/uncursed/cursed status is unknown.");
2577                 break; /* better phrasing is desirable */
2578             default:
2579                 which = "such";
2580                 break;
2581             }
2582             if (which)
2583                 You("have no %s objects.", which);
2584             return 0;
2585         }
2586         this_type = oclass;
2587     }
2588     if (query_objlist((char *) 0, invent,
2589                       (flags.invlet_constant ? USE_INVLET : 0)
2590                           | INVORDER_SORT,
2591                       &pick_list, PICK_NONE, this_type_only) > 0)
2592         free((genericptr_t) pick_list);
2593     return 0;
2594 }
2595
2596 /* return a string describing the dungeon feature at <x,y> if there
2597    is one worth mentioning at that location; otherwise null */
2598 const char *
2599 dfeature_at(x, y, buf)
2600 int x, y;
2601 char *buf;
2602 {
2603     struct rm *lev = &levl[x][y];
2604     int ltyp = lev->typ, cmap = -1;
2605     const char *dfeature = 0;
2606     static char altbuf[BUFSZ];
2607
2608     if (IS_DOOR(ltyp)) {
2609         switch (lev->doormask) {
2610         case D_NODOOR:
2611             cmap = S_ndoor;
2612             break; /* "doorway" */
2613         case D_ISOPEN:
2614             cmap = S_vodoor;
2615             break; /* "open door" */
2616         case D_BROKEN:
2617             dfeature = "broken door";
2618             break;
2619         default:
2620             cmap = S_vcdoor;
2621             break; /* "closed door" */
2622         }
2623         /* override door description for open drawbridge */
2624         if (is_drawbridge_wall(x, y) >= 0)
2625             dfeature = "open drawbridge portcullis", cmap = -1;
2626     } else if (IS_FOUNTAIN(ltyp))
2627         cmap = S_fountain; /* "fountain" */
2628     else if (IS_THRONE(ltyp))
2629         cmap = S_throne; /* "opulent throne" */
2630     else if (is_lava(x, y))
2631         cmap = S_lava; /* "molten lava" */
2632     else if (is_ice(x, y))
2633         cmap = S_ice; /* "ice" */
2634     else if (is_pool(x, y))
2635         dfeature = "pool of water";
2636     else if (IS_SINK(ltyp))
2637         cmap = S_sink; /* "sink" */
2638     else if (IS_ALTAR(ltyp)) {
2639         Sprintf(altbuf, "%saltar to %s (%s)",
2640                 ((lev->altarmask & AM_SHRINE)
2641                  && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
2642                     ? "high "
2643                     : "",
2644                 a_gname(),
2645                 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
2646         dfeature = altbuf;
2647     } else if ((x == xupstair && y == yupstair)
2648                || (x == sstairs.sx && y == sstairs.sy && sstairs.up))
2649         cmap = S_upstair; /* "staircase up" */
2650     else if ((x == xdnstair && y == ydnstair)
2651              || (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
2652         cmap = S_dnstair; /* "staircase down" */
2653     else if (x == xupladder && y == yupladder)
2654         cmap = S_upladder; /* "ladder up" */
2655     else if (x == xdnladder && y == ydnladder)
2656         cmap = S_dnladder; /* "ladder down" */
2657     else if (ltyp == DRAWBRIDGE_DOWN)
2658         cmap = S_vodbridge; /* "lowered drawbridge" */
2659     else if (ltyp == DBWALL)
2660         cmap = S_vcdbridge; /* "raised drawbridge" */
2661     else if (IS_GRAVE(ltyp))
2662         cmap = S_grave; /* "grave" */
2663     else if (ltyp == TREE)
2664         cmap = S_tree; /* "tree" */
2665     else if (ltyp == IRONBARS)
2666         dfeature = "set of iron bars";
2667
2668     if (cmap >= 0)
2669         dfeature = defsyms[cmap].explanation;
2670     if (dfeature)
2671         Strcpy(buf, dfeature);
2672     return dfeature;
2673 }
2674
2675 /* look at what is here; if there are many objects (pile_limit or more),
2676    don't show them unless obj_cnt is 0 */
2677 int
2678 look_here(obj_cnt, picked_some)
2679 int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progress */
2680 boolean picked_some;
2681 {
2682     struct obj *otmp;
2683     struct trap *trap;
2684     const char *verb = Blind ? "feel" : "see";
2685     const char *dfeature = (char *) 0;
2686     char fbuf[BUFSZ], fbuf2[BUFSZ];
2687     winid tmpwin;
2688     boolean skip_objects, felt_cockatrice = FALSE;
2689
2690     /* default pile_limit is 5; a value of 0 means "never skip"
2691        (and 1 effectively forces "always skip") */
2692     skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
2693     if (u.uswallow && u.ustuck) {
2694         struct monst *mtmp = u.ustuck;
2695         Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
2696                 mbodypart(mtmp, STOMACH));
2697         /* Skip "Contents of " by using fbuf index 12 */
2698         You("%s to %s what is lying in %s.", Blind ? "try" : "look around",
2699             verb, &fbuf[12]);
2700         otmp = mtmp->minvent;
2701         if (otmp) {
2702             for (; otmp; otmp = otmp->nobj) {
2703                 /* If swallower is an animal, it should have become stone
2704                  * but... */
2705                 if (otmp->otyp == CORPSE)
2706                     feel_cockatrice(otmp, FALSE);
2707             }
2708             if (Blind)
2709                 Strcpy(fbuf, "You feel");
2710             Strcat(fbuf, ":");
2711             (void) display_minventory(mtmp, MINV_ALL, fbuf);
2712         } else {
2713             You("%s no objects here.", verb);
2714         }
2715         return !!Blind;
2716     }
2717     if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen)
2718         There("is %s here.",
2719               an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
2720
2721     otmp = level.objects[u.ux][u.uy];
2722     dfeature = dfeature_at(u.ux, u.uy, fbuf2);
2723     if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
2724         dfeature = 0;
2725
2726     if (Blind) {
2727         boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
2728
2729         if (dfeature && !strncmp(dfeature, "altar ", 6)) {
2730             /* don't say "altar" twice, dfeature has more info */
2731             You("try to feel what is here.");
2732         } else {
2733             const char *where = (Blind && !can_reach_floor(TRUE))
2734                                     ? "lying beneath you"
2735                                     : "lying here on the ",
2736                        *onwhat = (Blind && !can_reach_floor(TRUE))
2737                                      ? ""
2738                                      : surface(u.ux, u.uy);
2739
2740             You("try to feel what is %s%s.", drift ? "floating here" : where,
2741                 drift ? "" : onwhat);
2742         }
2743         if (dfeature && !drift && !strcmp(dfeature, surface(u.ux, u.uy)))
2744             dfeature = 0; /* ice already identified */
2745         if (!can_reach_floor(TRUE)) {
2746             pline("But you can't reach it!");
2747             return 0;
2748         }
2749     }
2750
2751     if (dfeature)
2752         Sprintf(fbuf, "There is %s here.", an(dfeature));
2753
2754     if (!otmp || is_lava(u.ux, u.uy)
2755         || (is_pool(u.ux, u.uy) && !Underwater)) {
2756         if (dfeature)
2757             pline1(fbuf);
2758         read_engr_at(u.ux, u.uy); /* Eric Backus */
2759         if (!skip_objects && (Blind || !dfeature))
2760             You("%s no objects here.", verb);
2761         return !!Blind;
2762     }
2763     /* we know there is something here */
2764
2765     if (skip_objects) {
2766         if (dfeature)
2767             pline1(fbuf);
2768         read_engr_at(u.ux, u.uy); /* Eric Backus */
2769         if (obj_cnt == 1 && otmp->quan == 1L)
2770             There("is %s object here.", picked_some ? "another" : "an");
2771         else
2772             There("are %s%s objects here.",
2773                   (obj_cnt < 5)
2774                       ? "a few"
2775                       : (obj_cnt < 10)
2776                           ? "several"
2777                           : "many",
2778                   picked_some ? " more" : "");
2779         for (; otmp; otmp = otmp->nexthere)
2780             if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
2781                 pline("%s %s%s.",
2782                       (obj_cnt > 1)
2783                           ? "Including"
2784                           : (otmp->quan > 1L)
2785                               ? "They're"
2786                               : "It's",
2787                       corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
2788                       poly_when_stoned(youmonst.data)
2789                           ? ""
2790                           : ", unfortunately");
2791                 feel_cockatrice(otmp, FALSE);
2792                 break;
2793             }
2794     } else if (!otmp->nexthere) {
2795         /* only one object */
2796         if (dfeature)
2797             pline1(fbuf);
2798         read_engr_at(u.ux, u.uy); /* Eric Backus */
2799         You("%s here %s.", verb, doname_with_price(otmp));
2800         iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
2801         if (otmp->otyp == CORPSE)
2802             feel_cockatrice(otmp, FALSE);
2803     } else {
2804         char buf[BUFSZ];
2805
2806         display_nhwindow(WIN_MESSAGE, FALSE);
2807         tmpwin = create_nhwindow(NHW_MENU);
2808         if (dfeature) {
2809             putstr(tmpwin, 0, fbuf);
2810             putstr(tmpwin, 0, "");
2811         }
2812         Sprintf(buf, "%s that %s here:",
2813                 picked_some ? "Other things" : "Things",
2814                 Blind ? "you feel" : "are");
2815         putstr(tmpwin, 0, buf);
2816         for (; otmp; otmp = otmp->nexthere) {
2817             if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
2818                 felt_cockatrice = TRUE;
2819                 Sprintf(buf, "%s...", doname(otmp));
2820                 putstr(tmpwin, 0, buf);
2821                 break;
2822             }
2823             putstr(tmpwin, 0, doname_with_price(otmp));
2824         }
2825         display_nhwindow(tmpwin, TRUE);
2826         destroy_nhwindow(tmpwin);
2827         if (felt_cockatrice)
2828             feel_cockatrice(otmp, FALSE);
2829         read_engr_at(u.ux, u.uy); /* Eric Backus */
2830     }
2831     return !!Blind;
2832 }
2833
2834 /* the ':' command - explicitly look at what is here, including all objects */
2835 int
2836 dolook()
2837 {
2838     return look_here(0, FALSE);
2839 }
2840
2841 boolean
2842 will_feel_cockatrice(otmp, force_touch)
2843 struct obj *otmp;
2844 boolean force_touch;
2845 {
2846     if ((Blind || force_touch) && !uarmg && !Stone_resistance
2847         && (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
2848         return TRUE;
2849     return FALSE;
2850 }
2851
2852 void
2853 feel_cockatrice(otmp, force_touch)
2854 struct obj *otmp;
2855 boolean force_touch;
2856 {
2857     char kbuf[BUFSZ];
2858
2859     if (will_feel_cockatrice(otmp, force_touch)) {
2860         /* "the <cockatrice> corpse" */
2861         Strcpy(kbuf, corpse_xname(otmp, (const char *) 0, CXN_PFX_THE));
2862
2863         if (poly_when_stoned(youmonst.data))
2864             You("touched %s with your bare %s.", kbuf,
2865                 makeplural(body_part(HAND)));
2866         else
2867             pline("Touching %s is a fatal mistake...", kbuf);
2868         /* normalize body shape here; hand, not body_part(HAND) */
2869         Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
2870         /* will call polymon() for the poly_when_stoned() case */
2871         instapetrify(kbuf);
2872     }
2873 }
2874
2875 void
2876 stackobj(obj)
2877 struct obj *obj;
2878 {
2879     struct obj *otmp;
2880
2881     for (otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
2882         if (otmp != obj && merged(&obj, &otmp))
2883             break;
2884     return;
2885 }
2886
2887 /* returns TRUE if obj  & otmp can be merged */
2888 STATIC_OVL boolean
2889 mergable(otmp, obj)
2890 register struct obj *otmp, *obj;
2891 {
2892     int objnamelth = 0, otmpnamelth = 0;
2893     if (obj == otmp)
2894         return FALSE; /* already the same object */
2895     if (obj->otyp != otmp->otyp)
2896         return FALSE;
2897     /* coins of the same kind will always merge */
2898     if (obj->oclass == COIN_CLASS)
2899         return TRUE;
2900     if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
2901         || obj->dknown != otmp->dknown
2902         || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
2903         || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed
2904         || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
2905         || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
2906         || obj->greased != otmp->greased || obj->oeroded != otmp->oeroded
2907         || obj->oeroded2 != otmp->oeroded2 || obj->bypass != otmp->bypass)
2908         return FALSE;
2909
2910     if (obj->nomerge) /* explicitly marked to prevent merge */
2911         return FALSE;
2912
2913     if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
2914         && (obj->oerodeproof != otmp->oerodeproof
2915             || obj->rknown != otmp->rknown))
2916         return FALSE;
2917
2918     if (obj->oclass == FOOD_CLASS
2919         && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
2920         return FALSE;
2921
2922     if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
2923         if (obj->corpsenm != otmp->corpsenm)
2924             return FALSE;
2925     }
2926
2927     /* hatching eggs don't merge; ditto for revivable corpses */
2928     if ((obj->otyp == EGG && (obj->timed || otmp->timed))
2929         || (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM
2930             && is_reviver(&mons[otmp->corpsenm])))
2931         return FALSE;
2932
2933     /* allow candle merging only if their ages are close */
2934     /* see begin_burn() for a reference for the magic "25" */
2935     if (Is_candle(obj) && obj->age / 25 != otmp->age / 25)
2936         return FALSE;
2937
2938     /* burning potions of oil never merge */
2939     if (obj->otyp == POT_OIL && obj->lamplit)
2940         return FALSE;
2941
2942     /* don't merge surcharged item with base-cost item */
2943     if (obj->unpaid && !same_price(obj, otmp))
2944         return FALSE;
2945
2946     /* if they have names, make sure they're the same */
2947     objnamelth = strlen(safe_oname(obj));
2948     otmpnamelth = strlen(safe_oname(otmp));
2949     if ((objnamelth != otmpnamelth
2950          && ((objnamelth && otmpnamelth) || obj->otyp == CORPSE))
2951         || (objnamelth && otmpnamelth
2952             && strncmp(ONAME(obj), ONAME(otmp), objnamelth)))
2953         return FALSE;
2954
2955     /* for the moment, any additional information is incompatible */
2956     if (has_omonst(obj) || has_omid(obj) || has_olong(obj) || has_omonst(otmp)
2957         || has_omid(otmp) || has_olong(otmp))
2958         return FALSE;
2959
2960     if (obj->oartifact != otmp->oartifact)
2961         return FALSE;
2962
2963     if (obj->known == otmp->known || !objects[otmp->otyp].oc_uses_known) {
2964         return (boolean) objects[obj->otyp].oc_merge;
2965     } else
2966         return FALSE;
2967 }
2968
2969 /* the '$' command */
2970 int
2971 doprgold()
2972 {
2973     /* the messages used to refer to "carrying gold", but that didn't
2974        take containers into account */
2975     long umoney = money_cnt(invent);
2976     if (!umoney)
2977         Your("wallet is empty.");
2978     else
2979         Your("wallet contains %ld %s.", umoney, currency(umoney));
2980     shopper_financial_report();
2981     return 0;
2982 }
2983
2984 /* the ')' command */
2985 int
2986 doprwep()
2987 {
2988     if (!uwep) {
2989         You("are empty %s.", body_part(HANDED));
2990     } else {
2991         prinv((char *) 0, uwep, 0L);
2992         if (u.twoweap)
2993             prinv((char *) 0, uswapwep, 0L);
2994     }
2995     return 0;
2996 }
2997
2998 /* caller is responsible for checking !wearing_armor() */
2999 STATIC_OVL void
3000 noarmor(report_uskin)
3001 boolean report_uskin;
3002 {
3003     if (!uskin || !report_uskin) {
3004         You("are not wearing any armor.");
3005     } else {
3006         char *p, *uskinname, buf[BUFSZ];
3007
3008         uskinname = strcpy(buf, simpleonames(uskin));
3009         /* shorten "set of <color> dragon scales" to "<color> scales"
3010            and "<color> dragon scale mail" to "<color> scale mail" */
3011         if (!strncmpi(uskinname, "set of ", 7))
3012             uskinname += 7;
3013         if ((p = strstri(uskinname, " dragon ")) != 0)
3014             while ((p[1] = p[8]) != '\0')
3015                 ++p;
3016
3017         You("are not wearing armor but have %s embedded in your skin.",
3018             uskinname);
3019     }
3020 }
3021
3022 /* the '[' command */
3023 int
3024 doprarm()
3025 {
3026     char lets[8];
3027     register int ct = 0;
3028     /*
3029      * Note:  players sometimes get here by pressing a function key which
3030      * transmits ''ESC [ <something>'' rather than by pressing '[';
3031      * there's nothing we can--or should-do about that here.
3032      */
3033
3034     if (!wearing_armor()) {
3035         noarmor(TRUE);
3036     } else {
3037         if (uarmu)
3038             lets[ct++] = obj_to_let(uarmu);
3039         if (uarm)
3040             lets[ct++] = obj_to_let(uarm);
3041         if (uarmc)
3042             lets[ct++] = obj_to_let(uarmc);
3043         if (uarmh)
3044             lets[ct++] = obj_to_let(uarmh);
3045         if (uarms)
3046             lets[ct++] = obj_to_let(uarms);
3047         if (uarmg)
3048             lets[ct++] = obj_to_let(uarmg);
3049         if (uarmf)
3050             lets[ct++] = obj_to_let(uarmf);
3051         lets[ct] = 0;
3052         (void) display_inventory(lets, FALSE);
3053     }
3054     return 0;
3055 }
3056
3057 /* the '=' command */
3058 int
3059 doprring()
3060 {
3061     if (!uleft && !uright)
3062         You("are not wearing any rings.");
3063     else {
3064         char lets[3];
3065         register int ct = 0;
3066
3067         if (uleft)
3068             lets[ct++] = obj_to_let(uleft);
3069         if (uright)
3070             lets[ct++] = obj_to_let(uright);
3071         lets[ct] = 0;
3072         (void) display_inventory(lets, FALSE);
3073     }
3074     return 0;
3075 }
3076
3077 /* the '"' command */
3078 int
3079 dopramulet()
3080 {
3081     if (!uamul)
3082         You("are not wearing an amulet.");
3083     else
3084         prinv((char *) 0, uamul, 0L);
3085     return 0;
3086 }
3087
3088 STATIC_OVL boolean
3089 tool_in_use(obj)
3090 struct obj *obj;
3091 {
3092     if ((obj->owornmask & (W_TOOL | W_SADDLE)) != 0L)
3093         return TRUE;
3094     if (obj->oclass != TOOL_CLASS)
3095         return FALSE;
3096     return (boolean) (obj == uwep || obj->lamplit
3097                       || (obj->otyp == LEASH && obj->leashmon));
3098 }
3099
3100 /* the '(' command */
3101 int
3102 doprtool()
3103 {
3104     struct obj *otmp;
3105     int ct = 0;
3106     char lets[52 + 1];
3107
3108     for (otmp = invent; otmp; otmp = otmp->nobj)
3109         if (tool_in_use(otmp))
3110             lets[ct++] = obj_to_let(otmp);
3111     lets[ct] = '\0';
3112     if (!ct)
3113         You("are not using any tools.");
3114     else
3115         (void) display_inventory(lets, FALSE);
3116     return 0;
3117 }
3118
3119 /* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
3120    show inventory of all currently wielded, worn, or used objects */
3121 int
3122 doprinuse()
3123 {
3124     struct obj *otmp;
3125     int ct = 0;
3126     char lets[52 + 1];
3127
3128     for (otmp = invent; otmp; otmp = otmp->nobj)
3129         if (is_worn(otmp) || tool_in_use(otmp))
3130             lets[ct++] = obj_to_let(otmp);
3131     lets[ct] = '\0';
3132     if (!ct)
3133         You("are not wearing or wielding anything.");
3134     else
3135         (void) display_inventory(lets, FALSE);
3136     return 0;
3137 }
3138
3139 /*
3140  * uses up an object that's on the floor, charging for it as necessary
3141  */
3142 void
3143 useupf(obj, numused)
3144 register struct obj *obj;
3145 long numused;
3146 {
3147     register struct obj *otmp;
3148     boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
3149
3150     /* burn_floor_objects() keeps an object pointer that it tries to
3151      * useupf() multiple times, so obj must survive if plural */
3152     if (obj->quan > numused)
3153         otmp = splitobj(obj, numused);
3154     else
3155         otmp = obj;
3156     if (costly_spot(otmp->ox, otmp->oy)) {
3157         if (index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
3158             addtobill(otmp, FALSE, FALSE, FALSE);
3159         else
3160             (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
3161     }
3162     delobj(otmp);
3163     if (at_u && u.uundetected && hides_under(youmonst.data))
3164         (void) hideunder(&youmonst);
3165 }
3166
3167 /*
3168  * Conversion from a class to a string for printing.
3169  * This must match the object class order.
3170  */
3171 STATIC_VAR NEARDATA const char *names[] = {
3172     0, "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", "Tools",
3173     "Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
3174     "Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
3175 };
3176
3177 static NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
3178
3179 static NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
3180
3181 static NEARDATA char *invbuf = (char *) 0;
3182 static NEARDATA unsigned invbufsiz = 0;
3183
3184 char *
3185 let_to_name(let, unpaid, showsym)
3186 char let;
3187 boolean unpaid, showsym;
3188 {
3189     const char *ocsymfmt = "  ('%c')";
3190     const int invbuf_sympadding = 8; /* arbitrary */
3191     const char *class_name;
3192     const char *pos;
3193     int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
3194     unsigned len;
3195
3196     if (oclass)
3197         class_name = names[oclass];
3198     else if ((pos = index(oth_symbols, let)) != 0)
3199         class_name = oth_names[pos - oth_symbols];
3200     else
3201         class_name = names[0];
3202
3203     len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "")
3204           + (oclass ? (strlen(ocsymfmt) + invbuf_sympadding) : 0);
3205     if (len > invbufsiz) {
3206         if (invbuf)
3207             free((genericptr_t) invbuf);
3208         invbufsiz = len + 10; /* add slop to reduce incremental realloc */
3209         invbuf = (char *) alloc(invbufsiz);
3210     }
3211     if (unpaid)
3212         Strcat(strcpy(invbuf, "Unpaid "), class_name);
3213     else
3214         Strcpy(invbuf, class_name);
3215     if ((oclass != 0) && showsym) {
3216         char *bp = eos(invbuf);
3217         int mlen = invbuf_sympadding - strlen(class_name);
3218         while (--mlen > 0) {
3219             *bp = ' ';
3220             bp++;
3221         }
3222         *bp = '\0';
3223         Sprintf(eos(invbuf), ocsymfmt, def_oc_syms[oclass].sym);
3224     }
3225     return invbuf;
3226 }
3227
3228 /* release the static buffer used by let_to_name() */
3229 void
3230 free_invbuf()
3231 {
3232     if (invbuf)
3233         free((genericptr_t) invbuf), invbuf = (char *) 0;
3234     invbufsiz = 0;
3235 }
3236
3237 /* give consecutive letters to every item in inventory (for !fixinv mode);
3238    gold is always forced to '$' slot at head of list */
3239 void
3240 reassign()
3241 {
3242     int i;
3243     struct obj *obj, *prevobj, *goldobj;
3244
3245     /* first, remove [first instance of] gold from invent, if present */
3246     prevobj = goldobj = 0;
3247     for (obj = invent; obj; prevobj = obj, obj = obj->nobj)
3248         if (obj->oclass == COIN_CLASS) {
3249             goldobj = obj;
3250             if (prevobj)
3251                 prevobj->nobj = goldobj->nobj;
3252             else
3253                 invent = goldobj->nobj;
3254             break;
3255         }
3256     /* second, re-letter the rest of the list */
3257     for (obj = invent, i = 0; obj; obj = obj->nobj, i++)
3258         obj->invlet =
3259             (i < 26) ? ('a' + i) : (i < 52) ? ('A' + i - 26) : NOINVSYM;
3260     /* third, assign gold the "letter" '$' and re-insert it at head */
3261     if (goldobj) {
3262         goldobj->invlet = GOLD_SYM;
3263         goldobj->nobj = invent;
3264         invent = goldobj;
3265     }
3266     if (i >= 52)
3267         i = 52 - 1;
3268     lastinvnr = i;
3269 }
3270
3271 /* #adjust command
3272  *
3273  *      User specifies a 'from' slot for inventory stack to move,
3274  *      then a 'to' slot for its destination.  Open slots and those
3275  *      filled by compatible stacks are listed as likely candidates
3276  *      but user can pick any inventory letter (including 'from').
3277  *      All compatible items found are gathered into the 'from'
3278  *      stack as it is moved.  If the 'to' slot isn't empty and
3279  *      doesn't merge, then its stack is swapped to the 'from' slot.
3280  *
3281  *      If the user specifies a count when choosing the 'from' slot,
3282  *      and that count is less than the full size of the stack,
3283  *      then the stack will be split.  The 'count' portion is moved
3284  *      to the destination, and the only candidate for merging with
3285  *      it is the stack already at the 'to' slot, if any.  When the
3286  *      destination is non-empty but won't merge, whatever is there
3287  *      will be moved to an open slot; if there isn't any open slot
3288  *      available, the adjustment attempt fails.
3289  *
3290  *      Splitting has one special case:  if 'to' slot is non-empty
3291  *      and is compatible with 'from' in all respects except for
3292  *      user-assigned names, the 'count' portion being moved is
3293  *      effectively renamed so that it will merge with 'to' stack.
3294  */
3295 int
3296 doorganize() /* inventory organizer by Del Lamb */
3297 {
3298     struct obj *obj, *otmp, *splitting, *bumped;
3299     int ix, cur, trycnt;
3300     char let;
3301     char alphabet[52 + 1], buf[52 + 1];
3302     char qbuf[QBUFSZ];
3303     char allowall[3]; /* { ALLOW_COUNT, ALL_CLASSES, 0 } */
3304     const char *adj_type;
3305
3306     if (!invent) {
3307         You("aren't carrying anything to adjust.");
3308         return 0;
3309     }
3310
3311     if (!flags.invlet_constant)
3312         reassign();
3313     /* get object the user wants to organize (the 'from' slot) */
3314     allowall[0] = ALLOW_COUNT;
3315     allowall[1] = ALL_CLASSES;
3316     allowall[2] = '\0';
3317     if (!(obj = getobj(allowall, "adjust")))
3318         return 0;
3319
3320     /* figure out whether user gave a split count to getobj() */
3321     splitting = bumped = 0;
3322     for (otmp = invent; otmp; otmp = otmp->nobj)
3323         if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
3324             if (otmp->invlet == obj->invlet)
3325                 splitting = otmp;
3326             break;
3327         }
3328
3329     /* initialize the list with all lower and upper case letters */
3330     for (ix = 0, let = 'a'; let <= 'z';)
3331         alphabet[ix++] = let++;
3332     for (let = 'A'; let <= 'Z';)
3333         alphabet[ix++] = let++;
3334     alphabet[ix] = '\0';
3335     /* for floating inv letters, truncate list after the first open slot */
3336     if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
3337         alphabet[ix + (splitting ? 0 : 1)] = '\0';
3338
3339     /* blank out all the letters currently in use in the inventory */
3340     /* except those that will be merged with the selected object   */
3341     for (otmp = invent; otmp; otmp = otmp->nobj)
3342         if (otmp != obj && !mergable(otmp, obj)) {
3343             let = otmp->invlet;
3344             if (let >= 'a' && let <= 'z')
3345                 alphabet[let - 'a'] = ' ';
3346             else if (let >= 'A' && let <= 'Z')
3347                 alphabet[let - 'A' + 26] = ' ';
3348         }
3349
3350     /* compact the list by removing all the blanks */
3351     for (ix = cur = 0; alphabet[ix]; ix++)
3352         if (alphabet[ix] != ' ')
3353             buf[cur++] = alphabet[ix];
3354     if (!cur && obj->invlet == NOINVSYM)
3355         buf[cur++] = NOINVSYM;
3356     buf[cur] = '\0';
3357     /* and by dashing runs of letters */
3358     if (cur > 5)
3359         compactify(buf);
3360
3361     /* get 'to' slot to use as destination */
3362     Sprintf(qbuf, "Adjust letter to what [%s]%s?", buf,
3363             invent ? " (? see used letters)" : "");
3364     for (trycnt = 1; ; ++trycnt) {
3365         let = yn_function(qbuf, (char *) 0, '\0');
3366         if (let == '?' || let == '*') {
3367             let = display_used_invlets(splitting ? obj->invlet : 0);
3368             if (!let)
3369                 continue;
3370             if (let == '\033')
3371                 goto noadjust;
3372         }
3373         if (index(quitchars, let)
3374             /* adjusting to same slot is meaningful since all
3375                compatible stacks get collected along the way,
3376                but splitting to same slot is not */
3377             || (splitting && let == obj->invlet)) {
3378         noadjust:
3379             if (splitting)
3380                 (void) merged(&splitting, &obj);
3381             pline1(Never_mind);
3382             return 0;
3383         }
3384         if ((letter(let) && let != '@') || index(buf, let))
3385             break; /* got one */
3386         if (trycnt == 5)
3387             goto noadjust;
3388         pline("Select an inventory slot letter."); /* else try again */
3389     }
3390
3391     /* change the inventory and print the resulting item */
3392     adj_type = !splitting ? "Moving:" : "Splitting:";
3393
3394     /*
3395      * don't use freeinv/addinv to avoid double-touching artifacts,
3396      * dousing lamps, losing luck, cursing loadstone, etc.
3397      */
3398     extract_nobj(obj, &invent);
3399
3400     for (otmp = invent; otmp;) {
3401         if (!splitting) {
3402             if (merged(&otmp, &obj)) {
3403                 adj_type = "Merging:";
3404                 obj = otmp;
3405                 otmp = otmp->nobj;
3406                 extract_nobj(obj, &invent);
3407                 continue; /* otmp has already been updated */
3408             } else if (otmp->invlet == let) {
3409                 adj_type = "Swapping:";
3410                 otmp->invlet = obj->invlet;
3411             }
3412         } else {
3413             /* splitting: don't merge extra compatible stacks;
3414                if destination is compatible, do merge with it,
3415                otherwise bump whatever is there to an open slot */
3416             if (otmp->invlet == let) {
3417                 int olth = 0;
3418
3419                 if (has_oname(obj))
3420                     olth = strlen(ONAME(obj));
3421                 /* ugly hack:  if these objects aren't going to merge
3422                    solely because they have conflicting user-assigned
3423                    names, strip off the name of the one being moved */
3424                 if (olth && !obj->oartifact && !mergable(otmp, obj)) {
3425                     char *holdname = ONAME(obj);
3426                     ONAME(obj) = (char *) 0;
3427                     /* restore name iff merging is still not possible */
3428                     if (!mergable(otmp, obj)) {
3429                         ONAME(obj) = holdname;
3430                         holdname = (char *) 0;
3431                     } else
3432                         free((genericptr_t) holdname);
3433                 }
3434
3435                 if (merged(&otmp, &obj)) {
3436                     obj = otmp;
3437                     extract_nobj(obj, &invent);
3438                 } else if (inv_cnt(FALSE) >= 52) {
3439                     (void) merged(&splitting, &obj); /* undo split */
3440                     /* "knapsack cannot accommodate any more items" */
3441                     Your("pack is too full.");
3442                     return 0;
3443                 } else {
3444                     bumped = otmp;
3445                     extract_nobj(bumped, &invent);
3446                 }
3447                 break;
3448             } /* found 'to' slot */
3449         }     /* splitting */
3450         otmp = otmp->nobj;
3451     }
3452
3453     /* inline addinv; insert loose object at beginning of inventory */
3454     obj->invlet = let;
3455     obj->nobj = invent;
3456     obj->where = OBJ_INVENT;
3457     invent = obj;
3458     reorder_invent();
3459     if (bumped) {
3460         /* splitting the 'from' stack is causing an incompatible
3461            stack in the 'to' slot to be moved into an open one;
3462            we need to do another inline insertion to inventory */
3463         assigninvlet(bumped);
3464         bumped->nobj = invent;
3465         bumped->where = OBJ_INVENT;
3466         invent = bumped;
3467         reorder_invent();
3468     }
3469
3470     /* messages deferred until inventory has been fully reestablished */
3471     prinv(adj_type, obj, 0L);
3472     if (bumped)
3473         prinv("Moving:", bumped, 0L);
3474     if (splitting)
3475         clear_splitobjs(); /* reset splitobj context */
3476     update_inventory();
3477     return 0;
3478 }
3479
3480 /* common to display_minventory and display_cinventory */
3481 STATIC_OVL void
3482 invdisp_nothing(hdr, txt)
3483 const char *hdr, *txt;
3484 {
3485     winid win;
3486     anything any;
3487     menu_item *selected;
3488
3489     any = zeroany;
3490     win = create_nhwindow(NHW_MENU);
3491     start_menu(win);
3492     add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr,
3493              MENU_UNSELECTED);
3494     add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
3495     add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
3496     end_menu(win, (char *) 0);
3497     if (select_menu(win, PICK_NONE, &selected) > 0)
3498         free((genericptr_t) selected);
3499     destroy_nhwindow(win);
3500     return;
3501 }
3502
3503 /* query_objlist callback: return things that are worn or wielded */
3504 STATIC_OVL boolean
3505 worn_wield_only(obj)
3506 struct obj *obj;
3507 {
3508 #if 1
3509     /* check for things that *are* worn or wielded (only used for monsters,
3510        so we don't worry about excluding W_CHAIN, W_ARTI and the like) */
3511     return (boolean) (obj->owornmask != 0L);
3512 #else
3513     /* this used to check for things that *might* be worn or wielded,
3514        but that's not particularly interesting */
3515     if (is_weptool(obj) || is_wet_towel(obj) || obj->otyp == MEAT_RING)
3516         return TRUE;
3517     return (boolean) (obj->oclass == WEAPON_CLASS
3518                       || obj->oclass == ARMOR_CLASS
3519                       || obj->oclass == AMULET_CLASS
3520                       || obj->oclass == RING_CLASS);
3521 #endif
3522 }
3523
3524 /*
3525  * Display a monster's inventory.
3526  * Returns a pointer to the object from the monster's inventory selected
3527  * or NULL if nothing was selected.
3528  *
3529  * By default, only worn and wielded items are displayed.  The caller
3530  * can pick one.  Modifier flags are:
3531  *
3532  *      MINV_NOLET      - nothing selectable
3533  *      MINV_ALL        - display all inventory
3534  */
3535 struct obj *
3536 display_minventory(mon, dflags, title)
3537 register struct monst *mon;
3538 int dflags;
3539 char *title;
3540 {
3541     struct obj *ret;
3542     char tmp[QBUFSZ];
3543     int n;
3544     menu_item *selected = 0;
3545     int do_all = (dflags & MINV_ALL) != 0,
3546         incl_hero = (do_all && u.uswallow && mon == u.ustuck),
3547         have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero);
3548
3549     Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
3550             do_all ? "possessions" : "armament");
3551
3552     if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
3553         /* Fool the 'weapon in hand' routine into
3554          * displaying 'weapon in claw', etc. properly.
3555          */
3556         youmonst.data = mon->data;
3557
3558         n = query_objlist(title ? title : tmp, mon->minvent,
3559                           INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0),
3560                           &selected,
3561                           (dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE,
3562                           do_all ? allow_all : worn_wield_only);
3563
3564         set_uasmon();
3565     } else {
3566         invdisp_nothing(title ? title : tmp, "(none)");
3567         n = 0;
3568     }
3569
3570     if (n > 0) {
3571         ret = selected[0].item.a_obj;
3572         free((genericptr_t) selected);
3573     } else
3574         ret = (struct obj *) 0;
3575     return ret;
3576 }
3577
3578 /*
3579  * Display the contents of a container in inventory style.
3580  * Currently, this is only used for statues, via wand of probing.
3581  */
3582 struct obj *
3583 display_cinventory(obj)
3584 register struct obj *obj;
3585 {
3586     struct obj *ret;
3587     char qbuf[QBUFSZ];
3588     int n;
3589     menu_item *selected = 0;
3590
3591     (void) safe_qbuf(qbuf, "Contents of ", ":", obj, doname, ansimpleoname,
3592                      "that");
3593
3594     if (obj->cobj) {
3595         n = query_objlist(qbuf, obj->cobj, INVORDER_SORT, &selected,
3596                           PICK_NONE, allow_all);
3597     } else {
3598         invdisp_nothing(qbuf, "(empty)");
3599         n = 0;
3600     }
3601     if (n > 0) {
3602         ret = selected[0].item.a_obj;
3603         free((genericptr_t) selected);
3604     } else
3605         ret = (struct obj *) 0;
3606     obj->cknown = 1;
3607     return ret;
3608 }
3609
3610 /* query objlist callback: return TRUE if obj is at given location */
3611 static coord only;
3612
3613 STATIC_OVL boolean
3614 only_here(obj)
3615 struct obj *obj;
3616 {
3617     return (obj->ox == only.x && obj->oy == only.y);
3618 }
3619
3620 /*
3621  * Display a list of buried items in inventory style.  Return a non-zero
3622  * value if there were items at that spot.
3623  *
3624  * Currently, this is only used with a wand of probing zapped downwards.
3625  */
3626 int
3627 display_binventory(x, y, as_if_seen)
3628 int x, y;
3629 boolean as_if_seen;
3630 {
3631     struct obj *obj;
3632     menu_item *selected = 0;
3633     int n;
3634
3635     /* count # of objects here */
3636     for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
3637         if (obj->ox == x && obj->oy == y) {
3638             if (as_if_seen)
3639                 obj->dknown = 1;
3640             n++;
3641         }
3642
3643     if (n) {
3644         only.x = x;
3645         only.y = y;
3646         if (query_objlist("Things that are buried here:", level.buriedobjlist,
3647                           INVORDER_SORT, &selected, PICK_NONE, only_here) > 0)
3648             free((genericptr_t) selected);
3649         only.x = only.y = 0;
3650     }
3651     return n;
3652 }
3653
3654 /*invent.c*/