1 /* SCCS Id: @(#)invent.c 3.4 2003/12/02 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
8 #define CONTAINED_SYM '>' /* designator for inside a container */
11 STATIC_DCL void NDECL(reorder_invent);
12 STATIC_DCL boolean FDECL(mergable,(struct obj *,struct obj *));
13 STATIC_DCL void FDECL(invdisp_nothing, (const char *,const char *));
14 STATIC_DCL boolean FDECL(worn_wield_only, (struct obj *));
15 STATIC_DCL boolean FDECL(only_here, (struct obj *));
17 STATIC_DCL void FDECL(compactify,(char *));
18 STATIC_DCL boolean FDECL(taking_off, (const char *));
19 STATIC_DCL boolean FDECL(putting_on, (const char *));
20 STATIC_PTR int FDECL(ckunpaid,(struct obj *));
21 STATIC_PTR int FDECL(ckvalidcat,(struct obj *));
22 static char FDECL(display_pickinv, (const char *,BOOLEAN_P, long *));
24 STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
25 STATIC_DCL void NDECL(dounpaid);
26 STATIC_DCL struct obj *FDECL(find_unpaid,(struct obj *,struct obj **));
27 STATIC_DCL void FDECL(menu_identify, (int));
28 STATIC_DCL boolean FDECL(tool_in_use, (struct obj *));
30 STATIC_DCL char FDECL(obj_to_let,(struct obj *));
34 static int lastinvnr = 51; /* 0 ... 51 (never saved&restored) */
37 /* wizards can wish for venom, which will become an invisible inventory
38 * item without this. putting it in inv_order would mean venom would
39 * suddenly become a choice for all the inventory-class commands, which
40 * would probably cause mass confusion. the test for inventory venom
41 * is only WIZARD and not wizard because the wizard can leave venom lying
42 * around on a bones level for normal players to find.
44 static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */
49 register struct obj *otmp;
53 register struct obj *obj;
56 /* There is only one of these in inventory... */
57 if (otmp->oclass == COIN_CLASS) {
58 otmp->invlet = GOLD_SYM;
63 for(i = 0; i < 52; i++) inuse[i] = FALSE;
64 for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
66 if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
67 if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
68 if(i == otmp->invlet) otmp->invlet = 0;
70 if((i = otmp->invlet) &&
71 (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
73 for(i = lastinvnr+1; i != lastinvnr; i++) {
74 if(i == 52) { i = -1; continue; }
77 otmp->invlet = (inuse[i] ? NOINVSYM :
78 (i < 26) ? ('a'+i) : ('A'+i-26));
85 /* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */
86 #define inv_rank(o) ((o)->invlet ^ 040)
88 /* sort the inventory; used by addinv() and doorganize() */
92 struct obj *otmp, *prev, *next;
93 boolean need_more_sorting;
97 * We expect at most one item to be out of order, so this
98 * isn't nearly as inefficient as it may first appear.
100 need_more_sorting = FALSE;
101 for (otmp = invent, prev = 0; otmp; ) {
103 if (next && inv_rank(next) < inv_rank(otmp)) {
104 need_more_sorting = TRUE;
105 if (prev) prev->nobj = next;
107 otmp->nobj = next->nobj;
115 } while (need_more_sorting);
120 /* scan a list of objects to see whether another object will merge with
121 one of them; used in pickup.c when all 52 inventory slots are in use,
122 to figure out whether another object could still be picked up */
124 merge_choice(objlist, obj)
125 struct obj *objlist, *obj;
130 if (obj->otyp == SCR_SCARE_MONSTER) /* punt on these */
131 return (struct obj *)0;
132 /* if this is an item on the shop floor, the attributes it will
133 have when carried are different from what they are now; prevent
134 that from eliciting an incorrect result from mergable() */
135 save_nocharge = obj->no_charge;
136 if (objlist == invent && obj->where == OBJ_FLOOR &&
137 (shkp = shop_keeper(inside_shop(obj->ox, obj->oy))) != 0) {
138 if (obj->no_charge) obj->no_charge = 0;
139 /* A billable object won't have its `unpaid' bit set, so would
140 erroneously seem to be a candidate to merge with a similar
141 ordinary object. That's no good, because once it's really
142 picked up, it won't merge after all. It might merge with
143 another unpaid object, but we can't check that here (depends
144 too much upon shk's bill) and if it doesn't merge it would
145 end up in the '#' overflow inventory slot, so reject it now. */
146 else if (inhishop(shkp)) return (struct obj *)0;
149 if (mergable(objlist, obj)) break;
150 objlist = objlist->nobj;
152 obj->no_charge = save_nocharge;
156 /* merge obj with otmp and delete obj if types agree */
159 struct obj **potmp, **pobj;
161 register struct obj *otmp = *potmp, *obj = *pobj;
163 if(mergable(otmp, obj)) {
164 /* Approximate age: we do it this way because if we were to
165 * do it "accurately" (merge only when ages are identical)
166 * we'd wind up never merging any corpses.
167 * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
169 * Don't do the age manipulation if lit. We would need
170 * to stop the burn on both items, then merge the age,
171 * then restart the burn.
174 otmp->age = ((otmp->age*otmp->quan) + (obj->age*obj->quan))
175 / (otmp->quan + obj->quan);
177 otmp->quan += obj->quan;
179 /* temporary special case for gold objects!!!! */
181 if (otmp->oclass == COIN_CLASS) otmp->owt = weight(otmp);
182 else otmp->owt += obj->owt;
183 if(!otmp->onamelth && obj->onamelth)
184 otmp = *potmp = oname(otmp, ONAME(obj));
185 obj_extract_self(obj);
187 /* really should merge the timeouts */
188 if (obj->lamplit) obj_merge_light_sources(obj, otmp);
189 if (obj->timed) obj_stop_timers(obj); /* follows lights */
191 /* fixup for `#adjust' merging wielded darts, daggers, &c */
192 if (obj->owornmask && carried(otmp)) {
193 long wmask = otmp->owornmask | obj->owornmask;
195 /* Both the items might be worn in competing slots;
196 merger preference (regardless of which is which):
197 primary weapon + alternate weapon -> primary weapon;
198 primary weapon + quiver -> primary weapon;
199 alternate weapon + quiver -> alternate weapon.
200 (Prior to 3.3.0, it was not possible for the two
201 stacks to be worn in different slots and `obj'
202 didn't need to be unworn when merging.) */
203 if (wmask & W_WEP) wmask = W_WEP;
204 else if (wmask & W_SWAPWEP) wmask = W_SWAPWEP;
205 else if (wmask & W_QUIVER) wmask = W_QUIVER;
207 impossible("merging strangely worn items (%lx)", wmask);
208 wmask = otmp->owornmask;
210 if ((otmp->owornmask & ~wmask) != 0L) setnotworn(otmp);
211 setworn(otmp, wmask);
215 /* (this should not be necessary, since items
216 already in a monster's inventory don't ever get
217 merged into other objects [only vice versa]) */
218 else if (obj->owornmask && mcarried(otmp)) {
219 if (obj == MON_WEP(otmp->ocarry)) {
220 MON_WEP(otmp->ocarry) = otmp;
221 otmp->owornmask = W_WEP;
226 obfree(obj,otmp); /* free(obj), bill->otmp */
233 Adjust hero intrinsics as if this object was being added to the hero's
234 inventory. Called _before_ the object has been added to the hero's
237 This is called when adding objects to the hero's inventory normally (via
238 addinv) or when an object in the hero's inventory has been polymorphed
241 It may be valid to merge this code with with addinv_core2().
247 if (obj->oclass == COIN_CLASS) {
249 u.ugold += obj->quan;
253 } else if (obj->otyp == AMULET_OF_YENDOR) {
254 if (u.uhave.amulet) impossible("already have amulet?");
256 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
257 if (u.uhave.menorah) impossible("already have candelabrum?");
259 } else if (obj->otyp == BELL_OF_OPENING) {
260 if (u.uhave.bell) impossible("already have silver bell?");
262 } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
263 if (u.uhave.book) impossible("already have the book?");
265 } else if (obj->oartifact) {
266 if (is_quest_artifact(obj)) {
267 if (u.uhave.questart)
268 impossible("already have quest artifact?");
269 u.uhave.questart = 1;
272 set_artifact_intrinsic(obj, 1, W_ART);
277 Adjust hero intrinsics as if this object was being added to the hero's
278 inventory. Called _after_ the object has been added to the hero's
281 This is called when adding objects to the hero's inventory normally (via
282 addinv) or when an object in the hero's inventory has been polymorphed
289 if (confers_luck(obj)) {
290 /* new luckstone must be in inventory by this point
291 * for correct calculation */
297 Add obj to the hero's inventory. Make sure the object is "free".
298 Adjust hero attributes as necessary.
304 struct obj *otmp, *prev;
306 if (obj->where != OBJ_FREE)
307 panic("addinv: obj not free");
308 obj->no_charge = 0; /* not meaningful for invent */
312 /* if handed gold, we're done */
313 if (obj->oclass == COIN_CLASS)
317 /* merge if possible; find end of chain in the process */
318 for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj)
319 if (merged(&otmp, &obj)) {
323 /* didn't merge, so insert into chain */
324 if (flags.invlet_constant || !prev) {
325 if (flags.invlet_constant) assigninvlet(obj);
326 obj->nobj = invent; /* insert at beginning */
328 if (flags.invlet_constant) reorder_invent();
330 prev->nobj = obj; /* insert at end */
333 obj->where = OBJ_INVENT;
337 carry_obj_effects(obj); /* carrying affects the obj */
343 * Some objects are affected by being carried.
344 * Make those adjustments here. Called _after_ the object
345 * has been added to the hero's or monster's inventory,
346 * and after hero's intrinsics have been updated.
349 carry_obj_effects(obj)
352 /* Cursed figurines can spontaneously transform
354 if (obj->otyp == FIGURINE) {
356 && obj->corpsenm != NON_PM
357 && !dead_species(obj->corpsenm,TRUE)) {
358 attach_fig_transform_timeout(obj);
366 /* Add an item to the inventory unless we're fumbling or it refuses to be
367 * held (via touch_artifact), and give a message.
368 * If there aren't any free inventory slots, we'll drop it instead.
369 * If both success and failure messages are NULL, then we're just doing the
370 * fumbling/slot-limit checking for a silent grab. In any case,
371 * touch_artifact will print its own messages if they are warranted.
374 hold_another_object(obj, drop_fmt, drop_arg, hold_msg)
376 const char *drop_fmt, *drop_arg, *hold_msg;
380 if (!Blind) obj->dknown = 1; /* maximize mergibility */
381 if (obj->oartifact) {
382 /* place_object may change these */
383 boolean crysknife = (obj->otyp == CRYSKNIFE);
384 int oerode = obj->oerodeproof;
385 boolean wasUpolyd = Upolyd;
387 /* in case touching this object turns out to be fatal */
388 place_object(obj, u.ux, u.uy);
390 if (!touch_artifact(obj, &youmonst)) {
391 obj_extract_self(obj); /* remove it from the floor */
392 dropy(obj); /* now put it back again :-) */
394 } else if (wasUpolyd && !Upolyd) {
395 /* loose your grip if you revert your form */
396 if (drop_fmt) pline(drop_fmt, drop_arg);
397 obj_extract_self(obj);
401 obj_extract_self(obj);
403 obj->otyp = CRYSKNIFE;
404 obj->oerodeproof = oerode;
408 if (drop_fmt) pline(drop_fmt, drop_arg);
411 long oquan = obj->quan;
412 int prev_encumbr = near_capacity(); /* before addinv() */
414 /* encumbrance only matters if it would now become worse
415 than max( current_value, stressed ) */
416 if (prev_encumbr < MOD_ENCUMBER) prev_encumbr = MOD_ENCUMBER;
417 /* addinv() may redraw the entire inventory, overwriting
418 drop_arg when it comes from something like doname() */
419 if (drop_arg) drop_arg = strcpy(buf, drop_arg);
423 || ((obj->otyp != LOADSTONE || !obj->cursed)
424 && near_capacity() > prev_encumbr)) {
425 if (drop_fmt) pline(drop_fmt, drop_arg);
426 /* undo any merge which took place */
427 if (obj->quan > oquan) obj = splitobj(obj, oquan);
430 if (flags.autoquiver && !uquiver && !obj->owornmask &&
432 ammo_and_launcher(obj, uwep) ||
433 ammo_and_launcher(obj, uswapwep)))
435 if (hold_msg || drop_fmt) prinv(hold_msg, obj, oquan);
441 /* useup() all of an item regardless of its quantity */
448 obfree(obj, (struct obj *)0); /* deletes contents also */
453 register struct obj *obj;
455 /* Note: This works correctly for containers because they */
456 /* (containers) don't merge. */
457 if (obj->quan > 1L) {
458 obj->in_use = FALSE; /* no longer in use */
460 obj->owt = weight(obj);
467 /* use one charge from an item and possibly incur shop debt for it */
469 consume_obj_charge(obj, maybe_unpaid)
471 boolean maybe_unpaid; /* false if caller handles shop billing */
473 if (maybe_unpaid) check_unpaid(obj);
475 if (obj->known) update_inventory();
482 Adjust hero's attributes as if this object was being removed from the
483 hero's inventory. This should only be called from freeinv() and
484 where we are polymorphing an object already in the hero's inventory.
486 Should think of a better name...
492 if (obj->oclass == COIN_CLASS) {
494 u.ugold -= obj->quan;
499 } else if (obj->otyp == AMULET_OF_YENDOR) {
500 if (!u.uhave.amulet) impossible("don't have amulet?");
502 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
503 if (!u.uhave.menorah) impossible("don't have candelabrum?");
505 } else if (obj->otyp == BELL_OF_OPENING) {
506 if (!u.uhave.bell) impossible("don't have silver bell?");
508 } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
509 if (!u.uhave.book) impossible("don't have the book?");
511 } else if (obj->oartifact) {
512 if (is_quest_artifact(obj)) {
513 if (!u.uhave.questart)
514 impossible("don't have quest artifact?");
515 u.uhave.questart = 0;
517 set_artifact_intrinsic(obj, 0, W_ART);
520 if (obj->otyp == LOADSTONE) {
522 } else if (confers_luck(obj)) {
525 } else if (obj->otyp == FIGURINE && obj->timed) {
526 (void) stop_timer(FIG_TRANSFORM, (genericptr_t) obj);
530 /* remove an object from the hero's inventory */
533 register struct obj *obj;
535 extract_nobj(obj, &invent);
544 struct obj *otmp, *otmp2;
546 for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
549 /* after unpunish(), or might get deallocated chain */
550 otmp2 = otmp->nexthere;
560 /* destroy object in fobj chain (if unpaid, it remains on the bill) */
563 register struct obj *obj;
567 if (obj->otyp == AMULET_OF_YENDOR ||
568 obj->otyp == CANDELABRUM_OF_INVOCATION ||
569 obj->otyp == BELL_OF_OPENING ||
570 obj->otyp == SPE_BOOK_OF_THE_DEAD) {
571 /* player might be doing something stupid, but we
572 * can't guarantee that. assume special artifacts
573 * are indestructible via drawbridges, and exploding
574 * chests, and golem creation, and ...
578 update_map = (obj->where == OBJ_FLOOR);
579 obj_extract_self(obj);
580 if (update_map) newsym(obj->ox, obj->oy);
581 obfree(obj, (struct obj *) 0); /* frees contents also */
589 register int n, x, y;
591 register struct obj *otmp;
593 for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
596 return((struct obj *)0);
606 register struct obj *otmp;
608 for(otmp = invent; otmp; otmp = otmp->nobj)
609 if(otmp->otyp == type)
611 return((struct obj *) 0);
618 if (amount == 1L) return "zorkmid";
619 else return "zorkmids";
625 register struct obj *otmp;
627 for(otmp = invent; otmp; otmp = otmp->nobj)
628 if(otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
636 register struct obj *objchn;
641 if(objchn->o_id == id) return(objchn);
642 if (Has_contents(objchn) && (temp = o_on(id,objchn->cobj)))
644 objchn = objchn->nobj;
646 return((struct obj *) 0);
651 register struct obj *obj;
654 register struct obj *otmp;
656 for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
657 if(obj == otmp) return(TRUE);
668 register struct obj *obj = level.objects[x][y];
670 if (obj->oclass == COIN_CLASS) return obj;
673 return((struct obj *)0);
679 /* Make a gold object from the hero's gold. */
684 register struct obj *otmp;
686 otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
689 otmp->owt = weight(otmp);
700 /* compact a string of inventory letters by dashing runs of letters */
702 register int i1 = 1, i2 = 1;
703 register char ilet, ilet1, ilet2;
707 buf[++i2] = buf[++i1];
710 if(ilet == ilet1+1) {
712 buf[i2 - 1] = ilet1 = '-';
713 else if(ilet2 == '-') {
714 buf[i2 - 1] = ++ilet1;
722 buf[++i2] = buf[++i1];
727 /* match the prompt for either 'T' or 'R' command */
732 return !strcmp(action, "take off") || !strcmp(action, "remove");
735 /* match the prompt for either 'W' or 'P' command */
740 return !strcmp(action, "wear") || !strcmp(action, "put on");
745 * struct obj *xxx: object to do something with.
746 * (struct obj *) 0 error return: no object.
747 * &zeroobj explicitly no object (as in w-).
749 !!!! test if gold can be used in unusual ways (eaten etc.)
750 !!!! may be able to remove "usegold"
755 register const char *let,*word;
757 register struct obj *otmp;
759 char buf[BUFSZ], qbuf[QBUFSZ];
760 char lets[BUFSZ], altlets[BUFSZ], *ap;
761 register int foo = 0;
762 register char *bp = buf;
763 xchar allowcnt = 0; /* 0, 1 or 2 */
765 boolean allowgold = FALSE; /* can't use gold because they don't have any */
767 boolean usegold = FALSE; /* can't use gold because its illegal */
768 boolean allowall = FALSE;
769 boolean allownone = FALSE;
770 boolean useboulder = FALSE;
773 boolean prezero = FALSE;
776 if(*let == ALLOW_COUNT) let++, allowcnt = 1;
778 if(*let == COIN_CLASS) let++,
779 usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE);
781 if(*let == COIN_CLASS) let++, usegold = TRUE;
784 /* Equivalent of an "ugly check" for gold */
785 if (usegold && !strcmp(word, "eat") &&
786 (!metallivorous(youmonst.data)
787 || youmonst.data == &mons[PM_RUST_MONSTER]))
789 usegold = allowgold = FALSE;
794 if(*let == ALL_CLASSES) let++, allowall = TRUE;
795 if(*let == ALLOW_NONE) let++, allownone = TRUE;
796 /* "ugly check" for reading fortune cookies, part 1 */
797 /* The normal 'ugly check' keeps the object on the inventory list.
798 * We don't want to do that for shirts/cookies, so the check for
799 * them is handled a bit differently (and also requires that we set
800 * allowall in the caller)
802 if(allowall && !strcmp(word, "read")) allowall = FALSE;
804 /* another ugly check: show boulders (not statues) */
805 if(*let == WEAPON_CLASS &&
806 !strcmp(word, "throw") && throws_rocks(youmonst.data))
809 if(allownone) *bp++ = '-';
811 if(allowgold) *bp++ = def_oc_syms[COIN_CLASS];
813 if(bp > buf && bp[-1] == '-') *bp++ = ' ';
817 for (otmp = invent; otmp; otmp = otmp->nobj) {
818 if (!flags.invlet_constant)
820 if (otmp->invlet != GOLD_SYM) /* don't reassign this */
822 otmp->invlet = ilet; /* reassign() */
823 if (!*let || index(let, otmp->oclass)
825 || (usegold && otmp->invlet == GOLD_SYM)
827 || (useboulder && otmp->otyp == BOULDER)
829 register int otyp = otmp->otyp;
830 bp[foo++] = otmp->invlet;
832 /* ugly check: remove inappropriate things */
833 if ((taking_off(word) &&
834 (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))
835 || (otmp==uarm && uarmc)
837 || (otmp==uarmu && (uarm || uarmc))
840 || (putting_on(word) &&
841 (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
843 #if 0 /* 3.4.1 -- include currently wielded weapon among the choices */
844 || (!strcmp(word, "wield") &&
845 (otmp->owornmask & W_WEP))
847 || (!strcmp(word, "ready") &&
848 (otmp == uwep || (otmp == uswapwep && u.twoweap)))
854 /* Second ugly check; unlike the first it won't trigger an
855 * "else" in "you don't have anything else to ___".
857 else if ((putting_on(word) &&
858 ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING) ||
859 (otmp->oclass == TOOL_CLASS &&
860 otyp != BLINDFOLD && otyp != TOWEL && otyp != LENSES)))
861 || (!strcmp(word, "wield") &&
862 (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
863 || (!strcmp(word, "eat") && !is_edible(otmp))
864 || (!strcmp(word, "sacrifice") &&
866 otyp != AMULET_OF_YENDOR && otyp != FAKE_AMULET_OF_YENDOR))
867 || (!strcmp(word, "write with") &&
868 (otmp->oclass == TOOL_CLASS &&
869 otyp != MAGIC_MARKER && otyp != TOWEL))
870 || (!strcmp(word, "tin") &&
871 (otyp != CORPSE || !tinnable(otmp)))
872 || (!strcmp(word, "rub") &&
873 ((otmp->oclass == TOOL_CLASS &&
874 otyp != OIL_LAMP && otyp != MAGIC_LAMP &&
875 otyp != BRASS_LANTERN) ||
876 (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
877 || (!strncmp(word, "rub on the stone", 16) &&
878 *let == GEM_CLASS && /* using known touchstone */
879 otmp->dknown && objects[otyp].oc_name_known)
880 || ((!strcmp(word, "use or apply") ||
881 !strcmp(word, "untrap with")) &&
882 /* Picks, axes, pole-weapons, bullwhips */
883 ((otmp->oclass == WEAPON_CLASS && !is_pick(otmp) &&
884 !is_axe(otmp) && !is_pole(otmp) && otyp != BULLWHIP) ||
885 (otmp->oclass == POTION_CLASS &&
886 /* only applicable potion is oil, and it will only
887 be offered as a choice when already discovered */
888 (otyp != POT_OIL || !otmp->dknown ||
889 !objects[POT_OIL].oc_name_known)) ||
890 (otmp->oclass == FOOD_CLASS &&
891 otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF) ||
892 (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
893 || (!strcmp(word, "invoke") &&
894 (!otmp->oartifact && !objects[otyp].oc_unique &&
895 (otyp != FAKE_AMULET_OF_YENDOR || otmp->known) &&
896 otyp != CRYSTAL_BALL && /* #invoke synonym for apply */
897 /* note: presenting the possibility of invoking non-artifact
898 mirrors and/or lamps is a simply a cruel deception... */
899 otyp != MIRROR && otyp != MAGIC_LAMP &&
900 (otyp != OIL_LAMP || /* don't list known oil lamp */
901 (otmp->dknown && objects[OIL_LAMP].oc_name_known))))
902 || (!strcmp(word, "untrap with") &&
903 (otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE))
904 || (!strcmp(word, "charge") && !is_chargeable(otmp))
907 /* ugly check for unworn armor that can't be worn */
908 else if (putting_on(word) && *let == ARMOR_CLASS &&
909 !canwearobj(otmp, &dummymask, FALSE)) {
912 *ap++ = otmp->invlet;
916 /* "ugly check" for reading fortune cookies, part 2 */
917 if ((!strcmp(word, "read") &&
918 (otmp->otyp == FORTUNE_COOKIE
920 || otmp->otyp == T_SHIRT
926 if(ilet == 'z') ilet = 'A'; else ilet++;
929 if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
930 Strcpy(lets, bp); /* necessary since we destroy buf */
931 if(foo > 5) /* compactify string */
936 if(!foo && !allowall && !allowgold && !allownone) {
938 if(!foo && !allowall && !allownone) {
940 You("don't have anything %sto %s.",
941 foox ? "else " : "", word);
942 return((struct obj *)0);
946 if (allowcnt == 2) allowcnt = 1; /* abort previous count */
948 Sprintf(qbuf, "What do you want to %s? [*]", word);
950 Sprintf(qbuf, "What do you want to %s? [%s or ?*]",
958 ilet = yn_function(qbuf, (char *)0, '\0');
959 if(ilet == '0') prezero = TRUE;
960 while(digit(ilet) && allowcnt) {
962 if (ilet != '?' && ilet != '*') savech(ilet);
964 cnt = 10*cnt + (ilet - '0');
965 allowcnt = 2; /* signal presence of cnt */
969 pline("No count allowed with this command.");
972 if(index(quitchars,ilet)) {
975 return((struct obj *)0);
978 return(allownone ? &zeroobj : (struct obj *) 0);
980 if(ilet == def_oc_syms[COIN_CLASS]) {
982 if (!strncmp(word, "rub on ", 7)) {
983 /* the dangers of building sentences... */
984 You("cannot rub gold%s.", word + 3);
986 You("cannot %s gold.", word);
988 return(struct obj *)0;
990 } else if (!allowgold) {
991 You("are not carrying any gold.");
992 return(struct obj *)0;
995 if(cnt == 0 && prezero) return((struct obj *)0);
996 /* Historic note: early Nethack had a bug which was
997 * first reported for Larn, where trying to drop 2^32-n
998 * gold pieces was allowed, and did interesting things
999 * to your money supply. The LRS is the tax bureau
1003 pline_The("LRS would be very interested to know you have that much.");
1004 return(struct obj *)0;
1008 if(!(allowcnt == 2 && cnt < u.ugold))
1010 return(mkgoldobj(cnt));
1013 if(ilet == '?' || ilet == '*') {
1014 char *allowed_choices = (ilet == '?') ? lets : (char *)0;
1017 if (ilet == '?' && !*lets && *altlets)
1018 allowed_choices = altlets;
1019 ilet = display_pickinv(allowed_choices, TRUE,
1020 allowcnt ? &ctmp : (long *)0);
1022 if (allowcnt && ctmp >= 0) {
1024 if (!cnt) prezero = TRUE;
1027 if(ilet == '\033') {
1030 return((struct obj *)0);
1032 /* they typed a letter (not a space) at the prompt */
1034 if(allowcnt == 2 && !strcmp(word,"throw")) {
1035 /* permit counts for throwing gold, but don't accept
1036 * counts for other things since the throw code will
1037 * split off a single item anyway */
1039 if (ilet != def_oc_syms[COIN_CLASS])
1042 if(cnt == 0 && prezero) return((struct obj *)0);
1044 You("can only throw one item at a time.");
1049 flags.botl = 1; /* May have changed the amount of money */
1054 for (otmp = invent; otmp; otmp = otmp->nobj)
1055 if (otmp->invlet == ilet) break;
1057 You("don't have that object.");
1059 if (in_doagain) return((struct obj *) 0);
1062 } else if (cnt < 0 || otmp->quan < cnt) {
1063 You("don't have that many! You have only %ld.",
1066 if (in_doagain) return((struct obj *) 0);
1072 if(!allowall && let && !index(let,otmp->oclass)
1074 && !(usegold && otmp->oclass == COIN_CLASS)
1077 silly_thing(word, otmp);
1078 return((struct obj *)0);
1080 if(allowcnt == 2) { /* cnt given */
1081 if(cnt == 0) return (struct obj *)0;
1082 if(cnt != otmp->quan) {
1083 /* don't split a stack of cursed loadstones */
1084 if (otmp->otyp == LOADSTONE && otmp->cursed)
1085 /* kludge for canletgo()'s can't-drop-this message */
1086 otmp->corpsenm = (int) cnt;
1088 otmp = splitobj(otmp, cnt);
1095 silly_thing(word, otmp)
1099 const char *s1, *s2, *s3, *what;
1100 int ocls = otmp->oclass, otyp = otmp->otyp;
1103 /* check for attempted use of accessory commands ('P','R') on armor
1104 and for corresponding armor commands ('W','T') on accessories */
1105 if (ocls == ARMOR_CLASS) {
1106 if (!strcmp(word, "put on"))
1107 s1 = "W", s2 = "wear", s3 = "";
1108 else if (!strcmp(word, "remove"))
1109 s1 = "T", s2 = "take", s3 = " off";
1110 } else if ((ocls == RING_CLASS || otyp == MEAT_RING) ||
1111 ocls == AMULET_CLASS ||
1112 (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
1113 if (!strcmp(word, "wear"))
1114 s1 = "P", s2 = "put", s3 = " on";
1115 else if (!strcmp(word, "take off"))
1116 s1 = "R", s2 = "remove", s3 = "";
1120 /* quantity for armor and accessory objects is always 1,
1121 but some things should be referred to as plural */
1122 if (otyp == LENSES || is_gloves(otmp) || is_boots(otmp))
1124 pline("Use the '%s' command to %s %s%s.", s1, s2, what, s3);
1126 pline(silly_thing_to, word);
1135 register struct obj *otmp;
1137 /* use allow_category() from pickup.c */
1138 return((int)allow_category(otmp));
1143 register struct obj *otmp;
1145 return((int)(otmp->unpaid));
1151 return((boolean)(uarm || uarmc || uarmf || uarmg || uarmh || uarms
1160 register struct obj *otmp;
1162 return((boolean)(!!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
1166 W_WEP | W_SWAPWEP | W_QUIVER))));
1169 static NEARDATA const char removeables[] =
1170 { ARMOR_CLASS, WEAPON_CLASS, RING_CLASS, AMULET_CLASS, TOOL_CLASS, 0 };
1172 /* interactive version of getobj - used for Drop, Identify and */
1173 /* Takeoff (A). Return the number of times fn was called successfully */
1174 /* If combo is TRUE, we just use this to get a category list */
1176 ggetobj(word, fn, mx, combo, resultflags)
1178 int FDECL((*fn),(OBJ_P)), mx;
1179 boolean combo; /* combination menu flag */
1180 unsigned *resultflags;
1182 int FDECL((*ckfn),(OBJ_P)) = (int FDECL((*),(OBJ_P))) 0;
1183 boolean FDECL((*filter),(OBJ_P)) = (boolean FDECL((*),(OBJ_P))) 0;
1184 boolean takeoff, ident, allflag, m_seen;
1187 int oletct, iletct, allowgold, unpaid, oc_of_sym;
1189 int oletct, iletct, unpaid, oc_of_sym;
1191 char sym, *ip, olets[MAXOCLASSES+5], ilets[MAXOCLASSES+5];
1192 char extra_removeables[3+1]; /* uwep,uswapwep,uquiver */
1193 char buf[BUFSZ], qbuf[QBUFSZ];
1195 if (resultflags) *resultflags = 0;
1197 allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0;
1199 takeoff = ident = allflag = m_seen = FALSE;
1201 if(!invent && !allowgold){
1205 You("have nothing to %s.", word);
1208 add_valid_menu_class(0); /* reset */
1209 if (taking_off(word)) {
1212 } else if (!strcmp(word, "identify")) {
1214 filter = not_fully_identified;
1217 iletct = collect_obj_classes(ilets, invent,
1222 filter, &itemcount);
1223 unpaid = count_unpaid(invent);
1225 if (ident && !iletct) {
1226 return -1; /* no further identifications */
1227 } else if (!takeoff && (unpaid || invent)) {
1228 ilets[iletct++] = ' ';
1229 if (unpaid) ilets[iletct++] = 'u';
1230 if (count_buc(invent, BUC_BLESSED)) ilets[iletct++] = 'B';
1231 if (count_buc(invent, BUC_UNCURSED)) ilets[iletct++] = 'U';
1232 if (count_buc(invent, BUC_CURSED)) ilets[iletct++] = 'C';
1233 if (count_buc(invent, BUC_UNKNOWN)) ilets[iletct++] = 'X';
1234 if (invent) ilets[iletct++] = 'a';
1235 } else if (takeoff && invent) {
1236 ilets[iletct++] = ' ';
1238 ilets[iletct++] = 'i';
1240 ilets[iletct++] = 'm'; /* allow menu presentation on request */
1241 ilets[iletct] = '\0';
1244 Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]",
1247 if (buf[0] == '\033') return(0);
1248 if (index(buf, 'i')) {
1249 if (display_inventory((char *)0, TRUE) == '\033') return 0;
1254 extra_removeables[0] = '\0';
1256 /* arbitrary types of items can be placed in the weapon slots
1257 [any duplicate entries in extra_removeables[] won't matter] */
1258 if (uwep) (void)strkitten(extra_removeables, uwep->oclass);
1259 if (uswapwep) (void)strkitten(extra_removeables, uswapwep->oclass);
1260 if (uquiver) (void)strkitten(extra_removeables, uquiver->oclass);
1264 olets[oletct = 0] = '\0';
1265 while ((sym = *ip++) != '\0') {
1266 if (sym == ' ') continue;
1267 oc_of_sym = def_char_to_objclass(sym);
1268 if (takeoff && oc_of_sym != MAXOCLASSES) {
1269 if (index(extra_removeables, oc_of_sym)) {
1270 ; /* skip rest of takeoff checks */
1271 } else if (!index(removeables, oc_of_sym)) {
1272 pline("Not applicable.");
1274 } else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
1275 You("are not wearing any armor.");
1277 } else if (oc_of_sym == WEAPON_CLASS &&
1278 !uwep && !uswapwep && !uquiver) {
1279 You("are not wielding anything.");
1281 } else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
1282 You("are not wearing rings.");
1284 } else if (oc_of_sym == AMULET_CLASS && !uamul) {
1285 You("are not wearing an amulet.");
1287 } else if (oc_of_sym == TOOL_CLASS && !ublindf) {
1288 You("are not wearing a blindfold.");
1293 if (oc_of_sym == COIN_CLASS && !combo) {
1296 (*fn)(mkgoldobj(u.ugold));
1298 You("have no gold.");
1303 } else if (sym == 'a') {
1305 } else if (sym == 'A') {
1306 /* same as the default */ ;
1307 } else if (sym == 'u') {
1308 add_valid_menu_class('u');
1310 } else if (sym == 'B') {
1311 add_valid_menu_class('B');
1313 } else if (sym == 'U') {
1314 add_valid_menu_class('U');
1316 } else if (sym == 'C') {
1317 add_valid_menu_class('C');
1319 } else if (sym == 'X') {
1320 add_valid_menu_class('X');
1322 } else if (sym == 'm') {
1324 } else if (oc_of_sym == MAXOCLASSES) {
1325 You("don't have any %c's.", sym);
1326 } else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */
1327 if (!index(olets, oc_of_sym)) {
1328 add_valid_menu_class(oc_of_sym);
1329 olets[oletct++] = oc_of_sym;
1336 return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3;
1337 else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag)
1340 else if (allowgold == 2 && !oletct)
1341 return 1; /* you dropped gold (or at least tried to) */
1344 else /*!!!! if (allowgold == 2 && !oletct)
1345 !!!! return 1; you dropped gold (or at least tried to)
1346 !!!! test gold dropping
1349 int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
1351 * askchain() has already finished the job in this case
1352 * so set a special flag to convey that back to the caller
1353 * so that it won't continue processing.
1354 * Fix for bug C331-1 reported by Irina Rempt-Drijfhout.
1356 if (combo && allflag && resultflags)
1357 *resultflags |= ALL_FINISHED;
1363 * Walk through the chain starting at objchn and ask for all objects
1364 * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
1365 * whether the action in question (i.e., fn) has to be performed.
1366 * If allflag then no questions are asked. Max gives the max nr of
1367 * objects to be treated. Return the number of objects treated.
1370 askchain(objchn, olets, allflag, fn, ckfn, mx, word)
1371 struct obj **objchn;
1372 register int allflag, mx;
1373 register const char *olets, *word; /* olets is an Obj Class char array */
1374 register int FDECL((*fn),(OBJ_P)), FDECL((*ckfn),(OBJ_P));
1376 struct obj *otmp, *otmp2, *otmpo;
1377 register char sym, ilet;
1378 register int cnt = 0, dud = 0, tmp;
1379 boolean takeoff, nodot, ident, ininv;
1382 takeoff = taking_off(word);
1383 ident = !strcmp(word, "identify");
1384 nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") ||
1386 ininv = (*objchn == invent);
1387 /* Changed so the askchain is interrogated in the order specified.
1388 * For example, if a person specifies =/ then first all rings will be
1389 * asked about followed by all wands -dgk
1393 if (*objchn && (*objchn)->oclass == COIN_CLASS)
1394 ilet--; /* extra iteration */
1395 for (otmp = *objchn; otmp; otmp = otmp2) {
1396 if(ilet == 'z') ilet = 'A'; else ilet++;
1398 if (olets && *olets && otmp->oclass != *olets) continue;
1399 if (takeoff && !is_worn(otmp)) continue;
1400 if (ident && !not_fully_identified(otmp)) continue;
1401 if (ckfn && !(*ckfn)(otmp)) continue;
1403 Strcpy(qbuf, !ininv ? doname(otmp) :
1404 xprname(otmp, (char *)0, ilet, !nodot, 0L, 0L));
1406 sym = (takeoff || ident || otmp->quan < 2L) ?
1407 nyaq(qbuf) : nyNaq(qbuf);
1413 /* Number was entered; split the object unless it corresponds
1414 to 'none' or 'all'. 2 special cases: cursed loadstones and
1415 welded weapons (eg, multiple daggers) will remain as merged
1416 unit; done to avoid splitting an object that won't be
1417 droppable (even if we're picking up rather than dropping).
1423 if (yn_number < otmp->quan && !welded(otmp) &&
1424 (!otmp->cursed || otmp->otyp != LOADSTONE)) {
1425 otmp = splitobj(otmp, yn_number);
1435 if (otmp != otmpo) {
1436 /* split occurred, merge again */
1437 (void) merged(&otmpo, &otmp);
1442 if(--mx == 0) goto ret;
1448 /* special case for seffects() */
1449 if (ident) cnt = -1;
1453 if (olets && *olets && *++olets)
1455 if(!takeoff && (dud || cnt)) pline("That was all.");
1456 else if(!dud && !cnt) pline("No applicable objects.");
1463 * Object identification routines:
1466 /* make an object actually be identified; no display updating */
1468 fully_identify_obj(otmp)
1471 makeknown(otmp->otyp);
1472 if (otmp->oartifact) discover_artifact((xchar)otmp->oartifact);
1473 otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
1474 if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
1475 learn_egg_type(otmp->corpsenm);
1478 /* ggetobj callback routine; identify an object and give immediate feedback */
1483 fully_identify_obj(otmp);
1484 prinv((char *)0, otmp, 0L);
1488 /* menu of unidentified objects; select and identify up to id_limit of them */
1490 menu_identify(id_limit)
1493 menu_item *pick_list;
1494 int n, i, first = 1;
1496 /* assumptions: id_limit > 0 and at least one unID'd item is present */
1499 Sprintf(buf, "What would you like to identify %s?",
1500 first ? "first" : "next");
1501 n = query_objlist(buf, invent, SIGNAL_NOMENU|USE_INVLET|INVORDER_SORT,
1502 &pick_list, PICK_ANY, not_fully_identified);
1505 if (n > id_limit) n = id_limit;
1506 for (i = 0; i < n; i++, id_limit--)
1507 (void) identify(pick_list[i].item.a_obj);
1508 free((genericptr_t) pick_list);
1509 mark_synch(); /* Before we loop to pop open another menu */
1511 if (n < 0) pline("That was all.");
1512 id_limit = 0; /* Stop now */
1518 /* dialog with user to identify a given number of items; 0 means all */
1520 identify_pack(id_limit)
1523 struct obj *obj, *the_obj;
1527 the_obj = 0; /* if unid_cnt ends up 1, this will be it */
1528 for (obj = invent; obj; obj = obj->nobj)
1529 if (not_fully_identified(obj)) ++unid_cnt, the_obj = obj;
1532 You("have already identified all of your possessions.");
1533 } else if (!id_limit) {
1534 /* identify everything */
1535 if (unid_cnt == 1) {
1536 (void) identify(the_obj);
1539 /* TODO: use fully_identify_obj and cornline/menu/whatever here */
1540 for (obj = invent; obj; obj = obj->nobj)
1541 if (not_fully_identified(obj)) (void) identify(obj);
1545 /* identify up to `id_limit' items */
1547 if (flags.menu_style == MENU_TRADITIONAL)
1549 n = ggetobj("identify", identify, id_limit, FALSE, (unsigned *)0);
1550 if (n < 0) break; /* quit or no eligible items */
1551 } while ((id_limit -= n) > 0);
1552 if (n == 0 || n < -1)
1553 menu_identify(id_limit);
1562 obj_to_let(obj) /* should of course only be called for things in invent */
1563 register struct obj *obj;
1566 if (obj->oclass == COIN_CLASS)
1569 if (!flags.invlet_constant) {
1570 obj->invlet = NOINVSYM;
1577 * Print the indicated quantity of the given object. If quan == 0L then use
1578 * the current quantity.
1581 prinv(prefix, obj, quan)
1583 register struct obj *obj;
1586 if (!prefix) prefix = "";
1588 prefix, *prefix ? " " : "",
1589 xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L, quan));
1596 xprname(obj, txt, let, dot, cost, quan)
1598 const char *txt; /* text to print instead of obj */
1599 char let; /* inventory letter */
1600 boolean dot; /* append period; (dot && cost => Iu) */
1601 long cost; /* cost (for inventory of unpaid or expended items) */
1602 long quan; /* if non-0, print this quantity, not obj->quan */
1604 #ifdef LINT /* handle static char li[BUFSZ]; */
1607 static char li[BUFSZ];
1609 boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM;
1613 savequan = obj->quan;
1619 * * Then obj == null and we are printing a total amount.
1620 * > Then the object is contained and doesn't have an inventory letter.
1622 if (cost != 0 || let == '*') {
1623 /* if dot is true, we're doing Iu, otherwise Ix */
1624 Sprintf(li, "%c - %-45s %6ld %s",
1625 (dot && use_invlet ? obj->invlet : let),
1626 (txt ? txt : doname(obj)), cost, currency(cost));
1628 } else if (obj && obj->oclass == COIN_CLASS) {
1629 Sprintf(li, "%ld gold piece%s%s", obj->quan, plur(obj->quan),
1633 /* ordinary inventory display or pickup message */
1634 Sprintf(li, "%c - %s%s",
1635 (use_invlet ? obj->invlet : let),
1636 (txt ? txt : doname(obj)), (dot ? "." : ""));
1638 if (savequan) obj->quan = savequan;
1646 /* the 'i' command */
1650 (void) display_inventory((char *)0, FALSE);
1657 * Scan the given list of objects. If last_found is NULL, return the first
1658 * unpaid object found. If last_found is not NULL, then skip over unpaid
1659 * objects until last_found is reached, then set last_found to NULL so the
1660 * next unpaid object is returned. This routine recursively follows
1663 STATIC_OVL struct obj *
1664 find_unpaid(list, last_found)
1665 struct obj *list, **last_found;
1672 /* still looking for previous unpaid object */
1673 if (list == *last_found)
1674 *last_found = (struct obj *) 0;
1676 return (*last_found = list);
1678 if (Has_contents(list)) {
1679 if ((obj = find_unpaid(list->cobj, last_found)) != 0)
1684 return (struct obj *) 0;
1688 * Internal function used by display_inventory and getobj that can display
1689 * inventory and return a count as well as a letter. If out_cnt is not null,
1690 * any count returned from the menu selection is placed here.
1693 display_pickinv(lets, want_reply, out_cnt)
1694 register const char *lets;
1700 char *invlet = flags.inv_order;
1702 winid win; /* windows being used */
1703 static winid local_win = WIN_ERR; /* window for partial menus */
1705 menu_item *selected;
1707 /* overriden by global flag */
1708 if (flags.perm_invent) {
1709 win = (lets && *lets) ? local_win : WIN_INVEN;
1710 /* create the first time used */
1712 win = local_win = create_nhwindow(NHW_MENU);
1717 Exit early if no inventory -- but keep going if we are doing
1718 a permanent inventory update. We need to keep going so the
1719 permanent inventory window updates itself to remove the last
1720 item(s) dropped. One down side: the addition of the exception
1721 for permanent inventory window updates _can_ pop the window
1722 up when it's not displayed -- even if it's empty -- because we
1723 don't know at this level if its up or not. This may not be
1724 an issue if empty checks are done before hand and the call
1725 to here is short circuited away.
1727 if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
1729 pline("Not carrying anything%s.", u.ugold ? " except gold" : "");
1731 pline("Not carrying anything.");
1736 /* oxymoron? temporarily assign permanent inventory letters */
1737 if (!flags.invlet_constant) reassign();
1739 if (lets && strlen(lets) == 1) {
1740 /* when only one item of interest, use pline instead of menus;
1741 we actually use a fake message-line menu in order to allow
1742 the user to perform selection at the --More-- prompt for tty */
1744 for (otmp = invent; otmp; otmp = otmp->nobj) {
1745 if (otmp->invlet == lets[0]) {
1746 ret = message_menu(lets[0],
1747 want_reply ? PICK_ONE : PICK_NONE,
1748 xprname(otmp, (char *)0, lets[0], TRUE, 0L, 0L));
1749 if (out_cnt) *out_cnt = -1L; /* select all */
1759 any.a_void = 0; /* set all bits to zero */
1760 for(otmp = invent; otmp; otmp = otmp->nobj) {
1761 ilet = otmp->invlet;
1762 if(!lets || !*lets || index(lets, ilet)) {
1763 if (!flags.sortpack || otmp->oclass == *invlet) {
1764 if (flags.sortpack && !classcount) {
1765 any.a_void = 0; /* zero */
1766 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
1767 let_to_name(*invlet, FALSE), MENU_UNSELECTED);
1771 add_menu(win, obj_to_glyph(otmp),
1772 &any, ilet, 0, ATR_NONE, doname(otmp),
1777 if (flags.sortpack) {
1778 if (*++invlet) goto nextclass;
1780 if (--invlet != venom_inv) {
1786 end_menu(win, (char *) 0);
1788 n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
1790 ret = selected[0].item.a_char;
1791 if (out_cnt) *out_cnt = selected[0].count;
1792 free((genericptr_t)selected);
1794 ret = !n ? '\0' : '\033'; /* cancelled */
1800 * If lets == NULL or "", list all objects in the inventory. Otherwise,
1801 * list all objects with object classes that match the order in lets.
1803 * Returns the letter identifier of a selected item, or 0 if nothing
1807 display_inventory(lets, want_reply)
1808 register const char *lets;
1811 return display_pickinv(lets, want_reply, (long *)0);
1815 * Returns the number of unpaid items within the given list. This includes
1816 * contained objects.
1825 if (list->unpaid) count++;
1826 if (Has_contents(list))
1827 count += count_unpaid(list->cobj);
1834 * Returns the number of items with b/u/c/unknown within the given list.
1835 * This does NOT include contained objects.
1838 count_buc(list, type)
1845 if (Role_if(PM_PRIEST)) list->bknown = TRUE;
1848 if (list->oclass != COIN_CLASS && list->bknown && list->blessed)
1852 if (list->oclass != COIN_CLASS && list->bknown && list->cursed)
1856 if (list->oclass != COIN_CLASS &&
1857 list->bknown && !list->blessed && !list->cursed)
1861 if (list->oclass != COIN_CLASS && !list->bknown)
1865 impossible("need count of curse status %d?", type);
1877 struct obj *otmp, *marker;
1879 char *invlet = flags.inv_order;
1880 int classcount, count, num_so_far;
1881 int save_unpaid = 0; /* lint init */
1884 count = count_unpaid(invent);
1887 marker = (struct obj *) 0;
1888 otmp = find_unpaid(invent, &marker);
1890 /* see if the unpaid item is in the top level inventory */
1891 for (marker = invent; marker; marker = marker->nobj)
1892 if (marker == otmp) break;
1894 pline("%s", xprname(otmp, distant_name(otmp, doname),
1895 marker ? otmp->invlet : CONTAINED_SYM,
1896 TRUE, unpaid_cost(otmp), 0L));
1900 win = create_nhwindow(NHW_MENU);
1902 num_so_far = 0; /* count of # printed so far */
1903 if (!flags.invlet_constant) reassign();
1907 for (otmp = invent; otmp; otmp = otmp->nobj) {
1908 ilet = otmp->invlet;
1910 if (!flags.sortpack || otmp->oclass == *invlet) {
1911 if (flags.sortpack && !classcount) {
1912 putstr(win, 0, let_to_name(*invlet, TRUE));
1916 totcost += cost = unpaid_cost(otmp);
1917 /* suppress "(unpaid)" suffix */
1918 save_unpaid = otmp->unpaid;
1920 putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
1921 ilet, TRUE, cost, 0L));
1922 otmp->unpaid = save_unpaid;
1927 } while (flags.sortpack && (*++invlet));
1929 if (count > num_so_far) {
1930 /* something unpaid is contained */
1932 putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE));
1934 * Search through the container objects in the inventory for
1935 * unpaid items. The top level inventory items have already
1938 for (otmp = invent; otmp; otmp = otmp->nobj) {
1939 if (Has_contents(otmp)) {
1940 marker = (struct obj *) 0; /* haven't found any */
1941 while (find_unpaid(otmp->cobj, &marker)) {
1942 totcost += cost = unpaid_cost(marker);
1943 save_unpaid = marker->unpaid;
1944 marker->unpaid = 0; /* suppress "(unpaid)" suffix */
1946 xprname(marker, distant_name(marker, doname),
1947 CONTAINED_SYM, TRUE, cost, 0L));
1948 marker->unpaid = save_unpaid;
1955 putstr(win, 0, xprname((struct obj *)0, "Total:", '*', FALSE, totcost, 0L));
1956 display_nhwindow(win, FALSE);
1957 destroy_nhwindow(win);
1961 /* query objlist callback: return TRUE if obj type matches "this_type" */
1962 static int this_type;
1968 return (obj->oclass == this_type);
1971 /* the 'I' command */
1977 char *extra_types, types[BUFSZ];
1978 int class_count, oclass, unpaid_count, itemcount;
1979 boolean billx = *u.ushops && doinvbill(0);
1980 menu_item *pick_list;
1981 boolean traditional = TRUE;
1982 const char *prompt = "What type of object do you want an inventory of?";
1985 if (!invent && !u.ugold && !billx) {
1987 if (!invent && !billx) {
1989 You("aren't carrying anything.");
1992 unpaid_count = count_unpaid(invent);
1993 if (flags.menu_style != MENU_TRADITIONAL) {
1994 if (flags.menu_style == MENU_FULL ||
1995 flags.menu_style == MENU_PARTIAL) {
1996 traditional = FALSE;
1998 if (billx) i |= BILLED_TYPES;
1999 n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
2001 this_type = c = pick_list[0].item.a_int;
2002 free((genericptr_t) pick_list);
2006 /* collect a list of classes of objects carried, for use as a prompt */
2008 class_count = collect_obj_classes(types, invent,
2013 (boolean FDECL((*),(OBJ_P))) 0, &itemcount);
2022 /* add everything not already included; user won't see these */
2023 extra_types = eos(types);
2024 *extra_types++ = '\033';
2025 if (!unpaid_count) *extra_types++ = 'u';
2026 if (!billx) *extra_types++ = 'x';
2027 *extra_types = '\0'; /* for index() */
2028 for (i = 0; i < MAXOCLASSES; i++)
2029 if (!index(types, def_oc_syms[i])) {
2030 *extra_types++ = def_oc_syms[i];
2031 *extra_types = '\0';
2034 if(class_count > 1) {
2035 c = yn_function(prompt, types, '\0');
2040 clear_nhwindow(WIN_MESSAGE);
2044 /* only one thing to itemize */
2055 (void) doinvbill(1);
2057 pline("No used-up objects on your shopping bill.");
2064 You("are not carrying any unpaid objects.");
2068 oclass = def_char_to_objclass(c); /* change to object class */
2069 if (oclass == COIN_CLASS) {
2071 } else if (index(types, c) > index(types, '\033')) {
2072 You("have no such objects.");
2077 if (query_objlist((char *) 0, invent,
2078 (flags.invlet_constant ? USE_INVLET : 0)|INVORDER_SORT,
2079 &pick_list, PICK_NONE, this_type_only) > 0)
2080 free((genericptr_t)pick_list);
2084 /* return a string describing the dungeon feature at <x,y> if there
2085 is one worth mentioning at that location; otherwise null */
2087 dfeature_at(x, y, buf)
2091 struct rm *lev = &levl[x][y];
2092 int ltyp = lev->typ, cmap = -1;
2093 const char *dfeature = 0;
2094 static char altbuf[BUFSZ];
2096 if (IS_DOOR(ltyp)) {
2097 switch (lev->doormask) {
2098 case D_NODOOR: cmap = S_ndoor; break; /* "doorway" */
2099 case D_ISOPEN: cmap = S_vodoor; break; /* "open door" */
2100 case D_BROKEN: dfeature = "broken door"; break;
2101 default: cmap = S_vcdoor; break; /* "closed door" */
2103 /* override door description for open drawbridge */
2104 if (is_drawbridge_wall(x, y) >= 0)
2105 dfeature = "open drawbridge portcullis", cmap = -1;
2106 } else if (IS_FOUNTAIN(ltyp))
2107 cmap = S_fountain; /* "fountain" */
2108 else if (IS_THRONE(ltyp))
2109 cmap = S_throne; /* "opulent throne" */
2110 else if (is_lava(x,y))
2111 cmap = S_lava; /* "molten lava" */
2112 else if (is_ice(x,y))
2113 cmap = S_ice; /* "ice" */
2114 else if (is_pool(x,y))
2115 dfeature = "pool of water";
2117 else if (IS_SINK(ltyp))
2118 cmap = S_sink; /* "sink" */
2120 else if (IS_ALTAR(ltyp)) {
2121 Sprintf(altbuf, "altar to %s (%s)", a_gname(),
2122 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
2124 } else if ((x == xupstair && y == yupstair) ||
2125 (x == sstairs.sx && y == sstairs.sy && sstairs.up))
2126 cmap = S_upstair; /* "staircase up" */
2127 else if ((x == xdnstair && y == ydnstair) ||
2128 (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
2129 cmap = S_dnstair; /* "staircase down" */
2130 else if (x == xupladder && y == yupladder)
2131 cmap = S_upladder; /* "ladder up" */
2132 else if (x == xdnladder && y == ydnladder)
2133 cmap = S_dnladder; /* "ladder down" */
2134 else if (ltyp == DRAWBRIDGE_DOWN)
2135 cmap = S_vodbridge; /* "lowered drawbridge" */
2136 else if (ltyp == DBWALL)
2137 cmap = S_vcdbridge; /* "raised drawbridge" */
2138 else if (IS_GRAVE(ltyp))
2139 cmap = S_grave; /* "grave" */
2140 else if (ltyp == TREE)
2141 cmap = S_tree; /* "tree" */
2142 else if (ltyp == IRONBARS)
2143 dfeature = "set of iron bars";
2145 if (cmap >= 0) dfeature = defsyms[cmap].explanation;
2146 if (dfeature) Strcpy(buf, dfeature);
2150 /* look at what is here; if there are many objects (5 or more),
2151 don't show them unless obj_cnt is 0 */
2153 look_here(obj_cnt, picked_some)
2154 int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progess */
2155 boolean picked_some;
2159 const char *verb = Blind ? "feel" : "see";
2160 const char *dfeature = (char *)0;
2161 char fbuf[BUFSZ], fbuf2[BUFSZ];
2163 boolean skip_objects = (obj_cnt >= 5), felt_cockatrice = FALSE;
2165 if (u.uswallow && u.ustuck) {
2166 struct monst *mtmp = u.ustuck;
2167 Sprintf(fbuf, "Contents of %s %s",
2168 s_suffix(mon_nam(mtmp)), mbodypart(mtmp, STOMACH));
2169 /* Skip "Contents of " by using fbuf index 12 */
2170 You("%s to %s what is lying in %s.",
2171 Blind ? "try" : "look around", verb, &fbuf[12]);
2172 otmp = mtmp->minvent;
2174 for ( ; otmp; otmp = otmp->nobj) {
2175 /* If swallower is an animal, it should have become stone but... */
2176 if (otmp->otyp == CORPSE) feel_cockatrice(otmp, FALSE);
2178 if (Blind) Strcpy(fbuf, "You feel");
2180 (void) display_minventory(mtmp, MINV_ALL, fbuf);
2182 You("%s no objects here.", verb);
2186 if (!skip_objects && (trap = t_at(u.ux,u.uy)) && trap->tseen)
2187 There("is %s here.",
2188 an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
2190 otmp = level.objects[u.ux][u.uy];
2191 dfeature = dfeature_at(u.ux, u.uy, fbuf2);
2192 if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
2196 boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
2197 if (dfeature && !strncmp(dfeature, "altar ", 6)) {
2198 /* don't say "altar" twice, dfeature has more info */
2199 You("try to feel what is here.");
2201 You("try to feel what is %s%s.",
2202 drift ? "floating here" : "lying here on the ",
2203 drift ? "" : surface(u.ux, u.uy));
2205 if (dfeature && !drift && !strcmp(dfeature, surface(u.ux,u.uy)))
2206 dfeature = 0; /* ice already identifed */
2207 if (!can_reach_floor()) {
2208 pline("But you can't reach it!");
2214 Sprintf(fbuf, "There is %s here.", an(dfeature));
2216 if (!otmp || is_lava(u.ux,u.uy) || (is_pool(u.ux,u.uy) && !Underwater)) {
2217 if (dfeature) pline(fbuf);
2218 read_engr_at(u.ux, u.uy); /* Eric Backus */
2219 if (!skip_objects && (Blind || !dfeature))
2220 You("%s no objects here.", verb);
2223 /* we know there is something here */
2226 if (dfeature) pline(fbuf);
2227 read_engr_at(u.ux, u.uy); /* Eric Backus */
2228 There("are %s%s objects here.",
2229 (obj_cnt <= 10) ? "several" : "many",
2230 picked_some ? " more" : "");
2231 } else if (!otmp->nexthere) {
2232 /* only one object */
2233 if (dfeature) pline(fbuf);
2234 read_engr_at(u.ux, u.uy); /* Eric Backus */
2235 #ifdef INVISIBLE_OBJECTS
2236 if (otmp->oinvis && !See_invisible) verb = "feel";
2238 You("%s here %s.", verb, doname(otmp));
2239 if (otmp->otyp == CORPSE) feel_cockatrice(otmp, FALSE);
2241 display_nhwindow(WIN_MESSAGE, FALSE);
2242 tmpwin = create_nhwindow(NHW_MENU);
2244 putstr(tmpwin, 0, fbuf);
2245 putstr(tmpwin, 0, "");
2247 putstr(tmpwin, 0, Blind ? "Things that you feel here:" :
2248 "Things that are here:");
2249 for ( ; otmp; otmp = otmp->nexthere) {
2250 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
2252 felt_cockatrice = TRUE;
2253 Strcpy(buf, doname(otmp));
2255 putstr(tmpwin, 0, buf);
2258 putstr(tmpwin, 0, doname(otmp));
2260 display_nhwindow(tmpwin, TRUE);
2261 destroy_nhwindow(tmpwin);
2262 if (felt_cockatrice) feel_cockatrice(otmp, FALSE);
2263 read_engr_at(u.ux, u.uy); /* Eric Backus */
2268 /* explicilty look at what is here, including all objects */
2272 return look_here(0, FALSE);
2276 will_feel_cockatrice(otmp, force_touch)
2278 boolean force_touch;
2280 if ((Blind || force_touch) && !uarmg && !Stone_resistance &&
2281 (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
2287 feel_cockatrice(otmp, force_touch)
2289 boolean force_touch;
2293 if (will_feel_cockatrice(otmp, force_touch)) {
2294 if(poly_when_stoned(youmonst.data))
2295 You("touched the %s corpse with your bare %s.",
2296 mons[otmp->corpsenm].mname, makeplural(body_part(HAND)));
2298 pline("Touching the %s corpse is a fatal mistake...",
2299 mons[otmp->corpsenm].mname);
2300 Sprintf(kbuf, "%s corpse", an(mons[otmp->corpsenm].mname));
2314 for(otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
2315 if(otmp != obj && merged(&obj,&otmp))
2321 mergable(otmp, obj) /* returns TRUE if obj & otmp can be merged */
2322 register struct obj *otmp, *obj;
2324 if (obj->otyp != otmp->otyp) return FALSE;
2326 /* coins of the same kind will always merge */
2327 if (obj->oclass == COIN_CLASS) return TRUE;
2329 if (obj->unpaid != otmp->unpaid ||
2330 obj->spe != otmp->spe || obj->dknown != otmp->dknown ||
2331 (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST)) ||
2332 obj->cursed != otmp->cursed || obj->blessed != otmp->blessed ||
2333 obj->no_charge != otmp->no_charge ||
2334 obj->obroken != otmp->obroken ||
2335 obj->otrapped != otmp->otrapped ||
2336 obj->lamplit != otmp->lamplit ||
2337 #ifdef INVISIBLE_OBJECTS
2338 obj->oinvis != otmp->oinvis ||
2340 obj->greased != otmp->greased ||
2341 obj->oeroded != otmp->oeroded ||
2342 obj->oeroded2 != otmp->oeroded2 ||
2343 obj->bypass != otmp->bypass)
2346 if ((obj->oclass==WEAPON_CLASS || obj->oclass==ARMOR_CLASS) &&
2347 (obj->oerodeproof!=otmp->oerodeproof || obj->rknown!=otmp->rknown))
2350 if (obj->oclass == FOOD_CLASS && (obj->oeaten != otmp->oeaten ||
2351 obj->orotten != otmp->orotten))
2354 if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
2355 if (obj->corpsenm != otmp->corpsenm)
2359 /* hatching eggs don't merge; ditto for revivable corpses */
2360 if ((obj->otyp == EGG && (obj->timed || otmp->timed)) ||
2361 (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM &&
2362 is_reviver(&mons[otmp->corpsenm])))
2365 /* allow candle merging only if their ages are close */
2366 /* see begin_burn() for a reference for the magic "25" */
2367 if (Is_candle(obj) && obj->age/25 != otmp->age/25)
2370 /* burning potions of oil never merge */
2371 if (obj->otyp == POT_OIL && obj->lamplit)
2374 /* don't merge surcharged item with base-cost item */
2375 if (obj->unpaid && !same_price(obj, otmp))
2378 /* if they have names, make sure they're the same */
2379 if ( (obj->onamelth != otmp->onamelth &&
2380 ((obj->onamelth && otmp->onamelth) || obj->otyp == CORPSE)
2382 (obj->onamelth && otmp->onamelth &&
2383 strncmp(ONAME(obj), ONAME(otmp), (int)obj->onamelth)))
2386 /* for the moment, any additional information is incompatible */
2387 if (obj->oxlth || otmp->oxlth) return FALSE;
2389 if(obj->oartifact != otmp->oartifact) return FALSE;
2391 if(obj->known == otmp->known ||
2392 !objects[otmp->otyp].oc_uses_known) {
2393 return((boolean)(objects[obj->otyp].oc_merge));
2394 } else return(FALSE);
2400 /* the messages used to refer to "carrying gold", but that didn't
2401 take containers into account */
2404 Your("wallet is empty.");
2406 Your("wallet contains %ld gold piece%s.", u.ugold, plur(u.ugold));
2408 long umoney = money_cnt(invent);
2410 Your("wallet is empty.");
2412 Your("wallet contains %ld %s.", umoney, currency(umoney));
2414 shopper_financial_report();
2425 You("are empty %s.", body_part(HANDED));
2427 prinv((char *)0, uwep, 0L);
2428 if (u.twoweap) prinv((char *)0, uswapwep, 0L);
2436 if(!wearing_armor())
2437 You("are not wearing any armor.");
2444 register int ct = 0;
2447 if(uarmu) lets[ct++] = obj_to_let(uarmu);
2449 if(uarm) lets[ct++] = obj_to_let(uarm);
2450 if(uarmc) lets[ct++] = obj_to_let(uarmc);
2451 if(uarmh) lets[ct++] = obj_to_let(uarmh);
2452 if(uarms) lets[ct++] = obj_to_let(uarms);
2453 if(uarmg) lets[ct++] = obj_to_let(uarmg);
2454 if(uarmf) lets[ct++] = obj_to_let(uarmf);
2456 (void) display_inventory(lets, FALSE);
2464 if(!uleft && !uright)
2465 You("are not wearing any rings.");
2468 register int ct = 0;
2470 if(uleft) lets[ct++] = obj_to_let(uleft);
2471 if(uright) lets[ct++] = obj_to_let(uright);
2473 (void) display_inventory(lets, FALSE);
2482 You("are not wearing an amulet.");
2484 prinv((char *)0, uamul, 0L);
2492 if ((obj->owornmask & (W_TOOL
2496 )) != 0L) return TRUE;
2497 if (obj->oclass != TOOL_CLASS) return FALSE;
2498 return (boolean)(obj == uwep || obj->lamplit ||
2499 (obj->otyp == LEASH && obj->leashmon));
2509 for (otmp = invent; otmp; otmp = otmp->nobj)
2510 if (tool_in_use(otmp))
2511 lets[ct++] = obj_to_let(otmp);
2513 if (!ct) You("are not using any tools.");
2514 else (void) display_inventory(lets, FALSE);
2518 /* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
2519 show inventory of all currently wielded, worn, or used objects */
2527 for (otmp = invent; otmp; otmp = otmp->nobj)
2528 if (is_worn(otmp) || tool_in_use(otmp))
2529 lets[ct++] = obj_to_let(otmp);
2531 if (!ct) You("are not wearing or wielding anything.");
2532 else (void) display_inventory(lets, FALSE);
2537 * uses up an object that's on the floor, charging for it as necessary
2540 useupf(obj, numused)
2541 register struct obj *obj;
2544 register struct obj *otmp;
2545 boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
2547 /* burn_floor_paper() keeps an object pointer that it tries to
2548 * useupf() multiple times, so obj must survive if plural */
2549 if (obj->quan > numused)
2550 otmp = splitobj(obj, numused);
2553 if(costly_spot(otmp->ox, otmp->oy)) {
2554 if(index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
2555 addtobill(otmp, FALSE, FALSE, FALSE);
2556 else (void)stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
2559 if (at_u && u.uundetected && hides_under(youmonst.data))
2560 u.uundetected = OBJ_AT(u.ux, u.uy);
2569 * Conversion from a class to a string for printing.
2570 * This must match the object class order.
2572 STATIC_VAR NEARDATA const char *names[] = { 0,
2573 "Illegal objects", "Weapons", "Armor", "Rings", "Amulets",
2574 "Tools", "Comestibles", "Potions", "Scrolls", "Spellbooks",
2575 "Wands", "Coins", "Gems", "Boulders/Statues", "Iron balls",
2579 static NEARDATA const char oth_symbols[] = {
2584 static NEARDATA const char *oth_names[] = {
2585 "Bagged/Boxed items"
2588 static NEARDATA char *invbuf = (char *)0;
2589 static NEARDATA unsigned invbufsiz = 0;
2592 let_to_name(let,unpaid)
2596 const char *class_name;
2598 int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
2602 class_name = names[oclass];
2603 else if ((pos = index(oth_symbols, let)) != 0)
2604 class_name = oth_names[pos - oth_symbols];
2606 class_name = names[0];
2608 len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "");
2609 if (len > invbufsiz) {
2610 if (invbuf) free((genericptr_t)invbuf);
2611 invbufsiz = len + 10; /* add slop to reduce incremental realloc */
2612 invbuf = (char *) alloc(invbufsiz);
2615 Strcat(strcpy(invbuf, "Unpaid "), class_name);
2617 Strcpy(invbuf, class_name);
2624 if (invbuf) free((genericptr_t)invbuf), invbuf = (char *)0;
2635 register struct obj *obj;
2637 for(obj = invent, i = 0; obj; obj = obj->nobj, i++)
2638 obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26);
2646 doorganize() /* inventory organizer by Del Lamb */
2648 struct obj *obj, *otmp;
2649 register int ix, cur;
2651 char alphabet[52+1], buf[52+1];
2654 const char *adj_type;
2656 if (!flags.invlet_constant) reassign();
2657 /* get a pointer to the object the user wants to organize */
2658 allowall[0] = ALL_CLASSES; allowall[1] = '\0';
2659 if (!(obj = getobj(allowall,"adjust"))) return(0);
2661 /* initialize the list with all upper and lower case letters */
2662 for (let = 'a', ix = 0; let <= 'z';) alphabet[ix++] = let++;
2663 for (let = 'A', ix = 26; let <= 'Z';) alphabet[ix++] = let++;
2666 /* blank out all the letters currently in use in the inventory */
2667 /* except those that will be merged with the selected object */
2668 for (otmp = invent; otmp; otmp = otmp->nobj)
2669 if (otmp != obj && !mergable(otmp,obj)) {
2670 if (otmp->invlet <= 'Z')
2671 alphabet[(otmp->invlet) - 'A' + 26] = ' ';
2672 else alphabet[(otmp->invlet) - 'a'] = ' ';
2675 /* compact the list by removing all the blanks */
2676 for (ix = cur = 0; ix <= 52; ix++)
2677 if (alphabet[ix] != ' ') buf[cur++] = alphabet[ix];
2679 /* and by dashing runs of letters */
2680 if(cur > 5) compactify(buf);
2682 /* get new letter to use as inventory letter */
2684 Sprintf(qbuf, "Adjust letter to what [%s]?",buf);
2685 let = yn_function(qbuf, (char *)0, '\0');
2686 if(index(quitchars,let)) {
2690 if (let == '@' || !letter(let))
2691 pline("Select an inventory slot letter.");
2696 /* change the inventory and print the resulting item */
2697 adj_type = "Moving:";
2700 * don't use freeinv/addinv to avoid double-touching artifacts,
2701 * dousing lamps, losing luck, cursing loadstone, etc.
2703 extract_nobj(obj, &invent);
2705 for (otmp = invent; otmp;)
2706 if (merged(&otmp,&obj)) {
2707 adj_type = "Merging:";
2710 extract_nobj(obj, &invent);
2712 if (otmp->invlet == let) {
2713 adj_type = "Swapping:";
2714 otmp->invlet = obj->invlet;
2719 /* inline addinv (assuming flags.invlet_constant and !merged) */
2721 obj->nobj = invent; /* insert at beginning */
2722 obj->where = OBJ_INVENT;
2726 prinv(adj_type, obj, 0L);
2731 /* common to display_minventory and display_cinventory */
2733 invdisp_nothing(hdr, txt)
2734 const char *hdr, *txt;
2738 menu_item *selected;
2741 win = create_nhwindow(NHW_MENU);
2743 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr, MENU_UNSELECTED);
2744 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
2745 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
2746 end_menu(win, (char *)0);
2747 if (select_menu(win, PICK_NONE, &selected) > 0)
2748 free((genericptr_t)selected);
2749 destroy_nhwindow(win);
2753 /* query_objlist callback: return things that could possibly be worn/wielded */
2755 worn_wield_only(obj)
2758 return (obj->oclass == WEAPON_CLASS
2759 || obj->oclass == ARMOR_CLASS
2760 || obj->oclass == AMULET_CLASS
2761 || obj->oclass == RING_CLASS
2762 || obj->oclass == TOOL_CLASS);
2766 * Display a monster's inventory.
2767 * Returns a pointer to the object from the monster's inventory selected
2768 * or NULL if nothing was selected.
2770 * By default, only worn and wielded items are displayed. The caller
2771 * can pick one. Modifier flags are:
2773 * MINV_NOLET - nothing selectable
2774 * MINV_ALL - display all inventory
2777 display_minventory(mon, dflags, title)
2778 register struct monst *mon;
2788 menu_item *selected = 0;
2790 int do_all = (dflags & MINV_ALL) != 0,
2791 do_gold = (do_all && mon->mgold);
2793 int do_all = (dflags & MINV_ALL) != 0;
2796 Sprintf(tmp,"%s %s:", s_suffix(noit_Monnam(mon)),
2797 do_all ? "possessions" : "armament");
2800 if (do_all ? (mon->minvent || mon->mgold)
2802 if (do_all ? (mon->minvent != 0)
2804 : (mon->misc_worn_check || MON_WEP(mon))) {
2805 /* Fool the 'weapon in hand' routine into
2806 * displaying 'weapon in claw', etc. properly.
2808 youmonst.data = mon->data;
2813 * Make temporary gold object and insert at the head of
2814 * the mon's inventory. We can get away with using a
2815 * stack variable object because monsters don't carry
2816 * gold in their inventory, so it won't merge.
2819 m_gold.otyp = GOLD_PIECE; m_gold.oclass = COIN_CLASS;
2820 m_gold.quan = mon->mgold; m_gold.dknown = 1;
2821 m_gold.where = OBJ_FREE;
2822 /* we had better not merge and free this object... */
2823 if (add_to_minv(mon, &m_gold))
2824 panic("display_minventory: static object freed.");
2828 n = query_objlist(title ? title : tmp, mon->minvent, INVORDER_SORT, &selected,
2829 (dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE,
2830 do_all ? allow_all : worn_wield_only);
2833 if (do_gold) obj_extract_self(&m_gold);
2838 invdisp_nothing(title ? title : tmp, "(none)");
2843 ret = selected[0].item.a_obj;
2844 free((genericptr_t)selected);
2847 * Unfortunately, we can't return a pointer to our temporary
2848 * gold object. We'll have to work out a scheme where this
2849 * can happen. Maybe even put gold in the inventory list...
2851 if (ret == &m_gold) ret = (struct obj *) 0;
2854 ret = (struct obj *) 0;
2859 * Display the contents of a container in inventory style.
2860 * Currently, this is only used for statues, via wand of probing.
2863 display_cinventory(obj)
2864 register struct obj *obj;
2869 menu_item *selected = 0;
2871 Sprintf(tmp,"Contents of %s:", doname(obj));
2874 n = query_objlist(tmp, obj->cobj, INVORDER_SORT, &selected,
2875 PICK_NONE, allow_all);
2877 invdisp_nothing(tmp, "(empty)");
2881 ret = selected[0].item.a_obj;
2882 free((genericptr_t)selected);
2884 ret = (struct obj *) 0;
2888 /* query objlist callback: return TRUE if obj is at given location */
2895 return (obj->ox == only.x && obj->oy == only.y);
2899 * Display a list of buried items in inventory style. Return a non-zero
2900 * value if there were items at that spot.
2902 * Currently, this is only used with a wand of probing zapped downwards.
2905 display_binventory(x, y, as_if_seen)
2910 menu_item *selected = 0;
2913 /* count # of objects here */
2914 for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
2915 if (obj->ox == x && obj->oy == y) {
2916 if (as_if_seen) obj->dknown = 1;
2923 if (query_objlist("Things that are buried here:",
2924 level.buriedobjlist, INVORDER_SORT,
2925 &selected, PICK_NONE, only_here) > 0)
2926 free((genericptr_t)selected);
2927 only.x = only.y = 0;