1 /* NetHack 3.6 invent.c $NHDT-Date: 1674864733 2023/01/28 00:12:13 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.268 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Derek S. Ray, 2015. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2023 */
9 /* JNetHack may be freely redistributed. See license for details. */
13 #ifndef C /* same as cmd.c */
14 #define C(c) (0x1f & (c))
18 #define CONTAINED_SYM '>' /* designator for inside a container */
21 STATIC_DCL void FDECL(loot_classify, (Loot *, struct obj *));
22 STATIC_DCL char *FDECL(loot_xname, (struct obj *));
23 STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (const genericptr,
25 STATIC_DCL void NDECL(reorder_invent);
26 STATIC_DCL void FDECL(noarmor, (BOOLEAN_P));
27 STATIC_DCL void FDECL(invdisp_nothing, (const char *, const char *));
28 STATIC_DCL boolean FDECL(worn_wield_only, (struct obj *));
29 STATIC_DCL boolean FDECL(only_here, (struct obj *));
30 STATIC_DCL void FDECL(compactify, (char *));
31 STATIC_DCL boolean FDECL(taking_off, (const char *));
32 STATIC_DCL boolean FDECL(putting_on, (const char *));
33 STATIC_PTR int FDECL(ckvalidcat, (struct obj *));
34 STATIC_PTR int FDECL(ckunpaid, (struct obj *));
35 STATIC_PTR char *FDECL(safeq_xprname, (struct obj *));
36 STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
37 STATIC_DCL char FDECL(display_pickinv, (const char *, const char *,
38 const char *, BOOLEAN_P, long *));
39 STATIC_DCL char FDECL(display_used_invlets, (CHAR_P));
40 STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
41 STATIC_DCL void NDECL(dounpaid);
42 STATIC_DCL struct obj *FDECL(find_unpaid, (struct obj *, struct obj **));
43 STATIC_DCL void FDECL(menu_identify, (int));
44 STATIC_DCL boolean FDECL(tool_in_use, (struct obj *));
45 STATIC_DCL char FDECL(obj_to_let, (struct obj *));
47 static int lastinvnr = 51; /* 0 ... 51 (never saved&restored) */
49 /* wizards can wish for venom, which will become an invisible inventory
50 * item without this. putting it in inv_order would mean venom would
51 * suddenly become a choice for all the inventory-class commands, which
52 * would probably cause mass confusion. the test for inventory venom
53 * is only WIZARD and not wizard because the wizard can leave venom lying
54 * around on a bones level for normal players to find. [Note to the
55 * confused: 'WIZARD' used to be a compile-time conditional so this was
56 * guarded by #ifdef WIZARD/.../#endif.]
58 static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */
60 /* sortloot() classification; called at most once [per sort] for each object */
62 loot_classify(sort_item, obj)
66 /* we may eventually make this a settable option to always use
67 with sortloot instead of only when the 'sortpack' option isn't
68 set; it is similar to sortpack's inv_order but items most
69 likely to be picked up are moved to the front */
70 static char def_srt_order[MAXOCLASSES] = {
71 COIN_CLASS, AMULET_CLASS, RING_CLASS, WAND_CLASS, POTION_CLASS,
72 SCROLL_CLASS, SPBOOK_CLASS, GEM_CLASS, FOOD_CLASS, TOOL_CLASS,
73 WEAPON_CLASS, ARMOR_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0,
75 static char armcat[8];
76 const char *classorder;
78 int k, otyp = obj->otyp, oclass = obj->oclass;
79 boolean seen, discovered = objects[otyp].oc_name_known ? TRUE : FALSE;
82 * For the value types assigned by this classification, sortloot()
83 * will put lower valued ones before higher valued ones.
86 obj->dknown = 1; /* xname(obj) does this; we want it sooner */
87 seen = obj->dknown ? TRUE : FALSE,
89 classorder = flags.sortpack ? flags.inv_order : def_srt_order;
90 p = index(classorder, oclass);
92 k = 1 + (int) (p - classorder);
94 k = 1 + (int) strlen(classorder) + (oclass != VENOM_CLASS);
95 sort_item->orderclass = (xchar) k;
96 /* subclass designation; only a few classes have subclasses
97 and the non-armor ones we use are fairly arbitrary */
101 /* one-time init; we use a different order than the subclass
102 values defined by objclass.h */
103 armcat[ARM_HELM] = 1; /* [2] */
104 armcat[ARM_GLOVES] = 2; /* [3] */
105 armcat[ARM_BOOTS] = 3; /* [4] */
106 armcat[ARM_SHIELD] = 4; /* [1] */
107 armcat[ARM_CLOAK] = 5; /* [5] */
108 armcat[ARM_SHIRT] = 6; /* [6] */
109 armcat[ARM_SUIT] = 7; /* [0] */
110 armcat[7] = 8; /* sanity protection */
112 k = objects[otyp].oc_armcat;
113 /* oc_armcat overloads oc_subtyp which is an 'schar' so guard
114 against somebody assigning something unexpected to it */
120 /* for weapons, group by ammo (arrows, bolts), launcher (bows),
121 missile (darts, boomerangs), stackable (daggers, knives, spears),
122 'other' (swords, axes, &c), polearms */
123 k = objects[otyp].oc_skill;
124 k = (k < 0) ? ((k >= -P_CROSSBOW && k <= -P_BOW) ? 1 : 3)
125 : ((k >= P_BOW && k <= P_CROSSBOW) ? 2
126 : (k == P_SPEAR || k == P_DAGGER || k == P_KNIFE) ? 4
127 : !is_pole(obj) ? 5 : 6);
130 if (seen && discovered
131 && (otyp == BAG_OF_TRICKS || otyp == HORN_OF_PLENTY))
132 k = 2; /* known pseudo-container */
133 else if (Is_container(obj))
134 k = 1; /* regular container or unknown bag of tricks */
146 case DRUM_OF_EARTHQUAKE:
147 case HORN_OF_PLENTY: /* not a musical instrument */
148 k = 3; /* instrument or unknown horn of plenty */
151 k = 4; /* 'other' tool */
156 /* [what about separating "partly eaten" within each group?] */
162 /* [maybe separate one-bite foods from rations and such?] */
163 k = obj->globby ? 6 : 2;
178 * Normally subclass takes priority over discovery status, but
179 * that would give away information for gems (assuming we'll
180 * group them as valuable gems, next glass, then gray stones,
181 * and finally rocks once they're all fully identified).
184 * 1) unseen gems and glass ("gem")
185 * 2) seen but undiscovered gems and glass ("blue gem"),
186 * 3) discovered gems ("sapphire"),
187 * 4) discovered glass ("worthless pieced of blue glass"),
188 * 5) unseen gray stones and rocks ("stone"),
189 * 6) seen but undiscovered gray stones ("gray stone"),
190 * 7) discovered gray stones ("touchstone"),
191 * 8) seen rocks ("rock").
193 switch (objects[obj->otyp].oc_material) {
195 k = !seen ? 1 : !discovered ? 2 : 3;
198 k = !seen ? 1 : !discovered ? 2 : 4;
200 default: /* MINERAL */
201 k = !seen ? 5 : (obj->otyp != ROCK) ? (!discovered ? 6 : 7) : 8;
206 /* other classes don't have subclasses; we assign a nonzero
207 value because sortloot() uses 0 to mean 'not yet classified' */
208 k = 1; /* any non-zero would do */
211 sort_item->subclass = (xchar) k;
212 /* discovery status */
213 k = !seen ? 1 /* unseen */
214 : (discovered || !OBJ_DESCR(objects[otyp])) ? 4
215 : (objects[otyp].oc_uname) ? 3 /* named (partially discovered) */
216 : 2; /* undiscovered */
217 sort_item->disco = (xchar) k;
220 /* sortloot() formatting routine; for alphabetizing, not shown to user */
227 char *res, *save_oname;
230 * Deal with things that xname() includes as a prefix. We don't
231 * want such because they change alphabetical ordering. First,
232 * remember 'obj's current settings.
234 saveo.odiluted = obj->odiluted;
235 saveo.blessed = obj->blessed, saveo.cursed = obj->cursed;
236 saveo.spe = obj->spe;
237 saveo.owt = obj->owt;
238 save_oname = has_oname(obj) ? ONAME(obj) : 0;
239 save_debug = flags.debug;
240 /* suppress "diluted" for potions and "holy/unholy" for water;
241 sortloot() will deal with them using other criteria than name */
242 if (obj->oclass == POTION_CLASS) {
244 if (obj->otyp == POT_WATER)
245 obj->blessed = 0, obj->cursed = 0;
247 /* make "wet towel" and "moist towel" format as "towel" so that all
248 three group together */
249 if (obj->otyp == TOWEL)
251 /* group "<size> glob of <foo>" by <foo> rather than by <size> */
253 obj->owt = 200; /* 200: weight of combined glob from ten creatures
254 (five or fewer is "small", more than fifteen is
255 "large", in between has no prefix) */
256 /* suppress user-assigned name */
257 if (save_oname && !obj->oartifact)
259 /* avoid wizard mode formatting variations */
260 if (wizard) { /* flags.debug */
261 /* paranoia: before toggling off wizard mode, guard against a
262 panic in xname() producing a normal mode panic save file */
263 program_state.something_worth_saving = 0;
267 res = cxname_singular(obj);
271 program_state.something_worth_saving = 1;
273 /* restore the object */
274 if (obj->oclass == POTION_CLASS) {
275 obj->odiluted = saveo.odiluted;
276 if (obj->otyp == POT_WATER)
277 obj->blessed = saveo.blessed, obj->cursed = saveo.cursed;
279 if (obj->otyp == TOWEL) {
280 obj->spe = saveo.spe;
281 /* give "towel" a suffix that will force wet ones to come first,
282 moist ones next, and dry ones last regardless of whether
283 they've been flagged as having spe known */
284 Strcat(res, is_wet_towel(obj) ? ((obj->spe >= 3) ? "x" : "y") : "z");
287 obj->owt = saveo.owt;
288 /* we've suppressed the size prefix (above); there normally won't
289 be more than one of a given creature type because they coalesce,
290 but globs with different bless/curse state won't merge so it is
291 feasible to have multiple at the same location; add a suffix to
292 get such sorted by size (small first) */
293 Strcat(res, (obj->owt <= 100) ? "a"
294 : (obj->owt <= 300) ? "b"
295 : (obj->owt <= 500) ? "c"
298 if (save_oname && !obj->oartifact)
299 ONAME(obj) = save_oname;
304 /* set by sortloot() for use by sortloot_cmp(); reset by sortloot when done */
305 static unsigned sortlootmode = 0;
307 /* qsort comparison routine for sortloot() */
308 STATIC_OVL int CFDECLSPEC
309 sortloot_cmp(vptr1, vptr2)
310 const genericptr vptr1;
311 const genericptr vptr2;
313 struct sortloot_item *sli1 = (struct sortloot_item *) vptr1,
314 *sli2 = (struct sortloot_item *) vptr2;
315 struct obj *obj1 = sli1->obj,
318 int val1, val2, c, namcmp;
320 /* order by object class unless we're doing by-invlet without sortpack */
321 if ((sortlootmode & (SORTLOOT_PACK | SORTLOOT_INVLET))
322 != SORTLOOT_INVLET) {
323 /* Classify each object at most once no matter how many
324 comparisons it is involved in. */
325 if (!sli1->orderclass)
326 loot_classify(sli1, obj1);
327 if (!sli2->orderclass)
328 loot_classify(sli2, obj2);
331 val1 = sli1->orderclass;
332 val2 = sli2->orderclass;
334 return (int) (val1 - val2);
336 /* skip sub-classes when ordering by sortpack+invlet */
337 if ((sortlootmode & SORTLOOT_INVLET) == 0) {
338 /* Class matches; sort by subclass. */
339 val1 = sli1->subclass;
340 val2 = sli2->subclass;
344 /* Class and subclass match; sort by discovery status:
345 * first unseen, then seen but not named or discovered,
346 * then named, lastly discovered.
349 * 3) dark green potion called confusion
350 * 4) potion of healing
351 * Multiple entries within each group will be put into
352 * alphabetical order below.
361 /* order by assigned inventory letter */
362 if ((sortlootmode & SORTLOOT_INVLET) != 0) {
364 val1 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
365 : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
367 : (c == '#') ? 1 + 52 + 1
368 : 1 + 52 + 1 + 1; /* none of the above */
370 val2 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
371 : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
373 : (c == '#') ? 1 + 52 + 1
374 : 1 + 52 + 1 + 1; /* none of the above */
379 if ((sortlootmode & SORTLOOT_LOOT) == 0)
383 * Sort object names in lexicographical order, ignoring quantity.
385 * Each obj gets formatted at most once (per sort) no matter how many
386 * comparisons it gets subjected to.
390 nam1 = sli1->str = dupstr(loot_xname(obj1));
393 nam2 = sli2->str = dupstr(loot_xname(obj2));
394 if ((namcmp = strcmpi(nam1, nam2)) != 0)
398 val1 = obj1->bknown ? (obj1->blessed ? 3 : !obj1->cursed ? 2 : 1) : 0;
399 val2 = obj2->bknown ? (obj2->blessed ? 3 : !obj2->cursed ? 2 : 1) : 0;
401 return val2 - val1; /* bigger is better */
403 /* Sort by greasing. This will put the objects in degreasing order. */
404 val1 = obj1->greased;
405 val2 = obj2->greased;
407 return val2 - val1; /* bigger is better */
409 /* Sort by erosion. The effective amount is what matters. */
410 val1 = greatest_erosion(obj1);
411 val2 = greatest_erosion(obj2);
413 return val1 - val2; /* bigger is WORSE */
415 /* Sort by erodeproofing. Map known-invulnerable to 1, and both
416 known-vulnerable and unknown-vulnerability to 0, because that's
417 how they're displayed. */
418 val1 = obj1->rknown && obj1->oerodeproof;
419 val2 = obj2->rknown && obj2->oerodeproof;
421 return val2 - val1; /* bigger is better */
423 /* Sort by enchantment. Map unknown to -1000, which is comfortably
424 below the range of obj->spe. oc_uses_known means that obj->known
425 matters, which usually indirectly means that obj->spe is relevant.
426 Lots of objects use obj->spe for some other purpose (see obj.h). */
427 if (objects[obj1->otyp].oc_uses_known
428 /* exclude eggs (laid by you) and tins (homemade, pureed, &c) */
429 && obj1->oclass != FOOD_CLASS) {
430 val1 = obj1->known ? obj1->spe : -1000;
431 val2 = obj2->known ? obj2->spe : -1000;
433 return val2 - val1; /* bigger is better */
437 /* They're identical, as far as we're concerned. We want
438 to force a deterministic order, and do so by producing a
439 stable sort: maintain the original order of equal items. */
440 return (sli1->indx - sli2->indx);
444 * sortloot() - the story so far...
446 * The original implementation constructed and returned an array
447 * of pointers to objects in the requested order. Callers had to
448 * count the number of objects, allocate the array, pass one
449 * object at a time to the routine which populates it, traverse
450 * the objects via stepping through the array, then free the
451 * array. The ordering process used a basic insertion sort which
452 * is fine for short lists but inefficient for long ones.
454 * 3.6.0 (and continuing with 3.6.1) changed all that so that
455 * sortloot was self-contained as far as callers were concerned.
456 * It reordered the linked list into the requested order and then
457 * normal list traversal was used to process it. It also switched
458 * to qsort() on the assumption that the C library implementation
459 * put some effort into sorting efficiently. It also checked
460 * whether the list was already sorted as it got ready to do the
461 * sorting, so re-examining inventory or a pile of objects without
462 * having changed anything would gobble up less CPU than a full
463 * sort. But it had at least two problems (aside from the ordinary
464 * complement of bugs):
465 * 1) some players wanted to get the original order back when they
466 * changed the 'sortloot' option back to 'none', but the list
467 * reordering made that infeasible;
468 * 2) object identification giving the 'ID whole pack' result
469 * would call makeknown() on each newly ID'd object, that would
470 * call update_inventory() to update the persistent inventory
471 * window if one existed, the interface would call the inventory
472 * display routine which would call sortloot() which might change
473 * the order of the list being traversed by the identify code,
474 * possibly skipping the ID of some objects. That could have been
475 * avoided by suppressing 'perm_invent' during identification
476 * (fragile) or by avoiding sortloot() during inventory display
479 * As of 3.6.2: revert to the temporary array of ordered obj pointers
480 * but have sortloot() do the counting and allocation. Callers
481 * need to use array traversal instead of linked list traversal
482 * and need to free the temporary array when done. And the
483 * array contains 'struct sortloot_item' (aka 'Loot') entries
484 * instead of simple 'struct obj *' entries.
487 sortloot(olist, mode, by_nexthere, filterfunc)
488 struct obj **olist; /* previous version might have changed *olist, we don't */
489 unsigned mode; /* flags for sortloot_cmp() */
490 boolean by_nexthere; /* T: traverse via obj->nexthere, F: via obj->nobj */
491 boolean FDECL((*filterfunc), (OBJ_P));
496 boolean augment_filter;
498 for (n = 0, o = *olist; o; o = by_nexthere ? o->nexthere : o->nobj)
500 /* note: if there is a filter function, this might overallocate */
501 sliarray = (Loot *) alloc((n + 1) * sizeof *sliarray);
503 /* the 'keep cockatrice corpses' flag is overloaded with sort mode */
504 augment_filter = (mode & SORTLOOT_PETRIFY) ? TRUE : FALSE;
505 mode &= ~SORTLOOT_PETRIFY; /* remove flag, leaving mode */
506 /* populate aliarray[0..n-1] */
507 for (i = 0, o = *olist; o; o = by_nexthere ? o->nexthere : o->nobj) {
508 if (filterfunc && !(*filterfunc)(o)
509 /* caller may be asking us to override filterfunc (in order
510 to do a cockatrice corpse touch check during pickup even
511 if/when the filter rejects food class) */
512 && (!augment_filter || o->otyp != CORPSE
513 || !touch_petrifies(&mons[o->corpsenm])))
515 sliarray[i].obj = o, sliarray[i].indx = (int) i;
516 sliarray[i].str = (char *) 0;
517 sliarray[i].orderclass = sliarray[i].subclass = sliarray[i].disco = 0;
521 /* add a terminator so that we don't have to pass 'n' back to caller */
522 sliarray[n].obj = (struct obj *) 0, sliarray[n].indx = -1;
523 sliarray[n].str = (char *) 0;
524 sliarray[n].orderclass = sliarray[n].subclass = sliarray[n].disco = 0;
526 /* do the sort; if no sorting is requested, we'll just return
527 a sortloot_item array reflecting the current ordering */
529 sortlootmode = mode; /* extra input for sortloot_cmp() */
530 qsort((genericptr_t) sliarray, n, sizeof *sliarray, sortloot_cmp);
531 sortlootmode = 0; /* reset static mode flags */
532 /* if sortloot_cmp formatted any objects, discard their strings now */
533 for (i = 0; i < n; ++i)
535 free((genericptr_t) sliarray[i].str), sliarray[i].str = 0;
540 /* sortloot() callers should use this to free up memory it allocates */
542 unsortloot(loot_array_p)
546 free((genericptr_t) *loot_array_p), *loot_array_p = (Loot *) 0;
549 #if 0 /* 3.6.0 'revamp' */
551 sortloot(olist, mode, by_nexthere)
553 unsigned mode; /* flags for sortloot_cmp() */
554 boolean by_nexthere; /* T: traverse via obj->nexthere, F: via obj->nobj */
556 struct sortloot_item *sliarray, osli, nsli;
557 struct obj *o, **nxt_p;
559 boolean already_sorted = TRUE;
561 sortlootmode = mode; /* extra input for sortloot_cmp() */
562 for (n = osli.indx = 0, osli.obj = *olist; (o = osli.obj) != 0;
564 nsli.obj = by_nexthere ? o->nexthere : o->nobj;
565 nsli.indx = (int) ++n;
566 if (nsli.obj && already_sorted
567 && sortloot_cmp((genericptr_t) &osli, (genericptr_t) &nsli) > 0)
568 already_sorted = FALSE;
570 if (n > 1 && !already_sorted) {
571 sliarray = (struct sortloot_item *) alloc(n * sizeof *sliarray);
572 for (i = 0, o = *olist; o;
573 ++i, o = by_nexthere ? o->nexthere : o->nobj)
574 sliarray[i].obj = o, sliarray[i].indx = (int) i;
576 qsort((genericptr_t) sliarray, n, sizeof *sliarray, sortloot_cmp);
577 for (i = 0; i < n; ++i) {
579 nxt_p = by_nexthere ? &(o->nexthere) : &(o->nobj);
580 *nxt_p = (i < n - 1) ? sliarray[i + 1].obj : (struct obj *) 0;
582 *olist = sliarray[0].obj;
583 free((genericptr_t) sliarray);
591 register struct obj *otmp;
595 register struct obj *obj;
597 /* there should be at most one of these in inventory... */
598 if (otmp->oclass == COIN_CLASS) {
599 otmp->invlet = GOLD_SYM;
603 for (i = 0; i < 52; i++)
605 for (obj = invent; obj; obj = obj->nobj)
608 if ('a' <= i && i <= 'z')
609 inuse[i - 'a'] = TRUE;
610 else if ('A' <= i && i <= 'Z')
611 inuse[i - 'A' + 26] = TRUE;
612 if (i == otmp->invlet)
615 if ((i = otmp->invlet)
616 && (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
618 for (i = lastinvnr + 1; i != lastinvnr; i++) {
627 (inuse[i] ? NOINVSYM : (i < 26) ? ('a' + i) : ('A' + i - 26));
631 /* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */
632 #define inv_rank(o) ((o)->invlet ^ 040)
634 /* sort the inventory; used by addinv() and doorganize() */
638 struct obj *otmp, *prev, *next;
639 boolean need_more_sorting;
643 * We expect at most one item to be out of order, so this
644 * isn't nearly as inefficient as it may first appear.
646 need_more_sorting = FALSE;
647 for (otmp = invent, prev = 0; otmp;) {
649 if (next && inv_rank(next) < inv_rank(otmp)) {
650 need_more_sorting = TRUE;
655 otmp->nobj = next->nobj;
663 } while (need_more_sorting);
668 /* scan a list of objects to see whether another object will merge with
669 one of them; used in pickup.c when all 52 inventory slots are in use,
670 to figure out whether another object could still be picked up */
672 merge_choice(objlist, obj)
673 struct obj *objlist, *obj;
678 if (obj->otyp == SCR_SCARE_MONSTER) /* punt on these */
679 return (struct obj *) 0;
680 /* if this is an item on the shop floor, the attributes it will
681 have when carried are different from what they are now; prevent
682 that from eliciting an incorrect result from mergable() */
683 save_nocharge = obj->no_charge;
684 if (objlist == invent && obj->where == OBJ_FLOOR
685 && (shkp = shop_keeper(inside_shop(obj->ox, obj->oy))) != 0) {
688 /* A billable object won't have its `unpaid' bit set, so would
689 erroneously seem to be a candidate to merge with a similar
690 ordinary object. That's no good, because once it's really
691 picked up, it won't merge after all. It might merge with
692 another unpaid object, but we can't check that here (depends
693 too much upon shk's bill) and if it doesn't merge it would
694 end up in the '#' overflow inventory slot, so reject it now. */
695 else if (inhishop(shkp))
696 return (struct obj *) 0;
699 if (mergable(objlist, obj))
701 objlist = objlist->nobj;
703 obj->no_charge = save_nocharge;
707 /* merge obj with otmp and delete obj if types agree */
710 struct obj **potmp, **pobj;
712 register struct obj *otmp = *potmp, *obj = *pobj;
714 if (mergable(otmp, obj)) {
715 /* Approximate age: we do it this way because if we were to
716 * do it "accurately" (merge only when ages are identical)
717 * we'd wind up never merging any corpses.
718 * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
720 * Don't do the age manipulation if lit. We would need
721 * to stop the burn on both items, then merge the age,
722 * then restart the burn. Glob ages are averaged in the
723 * absorb routine, which uses weight rather than quantity
724 * to adjust for proportion (glob quantity is always 1).
726 if (!obj->lamplit && !obj->globby)
727 otmp->age = ((otmp->age * otmp->quan) + (obj->age * obj->quan))
728 / (otmp->quan + obj->quan);
731 otmp->quan += obj->quan;
732 /* temporary special case for gold objects!!!! */
733 if (otmp->oclass == COIN_CLASS)
734 otmp->owt = weight(otmp), otmp->bknown = 0;
735 /* and puddings!!!1!!one! */
736 else if (!Is_pudding(otmp))
737 otmp->owt += obj->owt;
738 if (!has_oname(otmp) && has_oname(obj))
739 otmp = *potmp = oname(otmp, ONAME(obj));
740 obj_extract_self(obj);
742 /* really should merge the timeouts */
744 obj_merge_light_sources(obj, otmp);
746 obj_stop_timers(obj); /* follows lights */
748 /* fixup for `#adjust' merging wielded darts, daggers, &c */
749 if (obj->owornmask && carried(otmp)) {
750 long wmask = otmp->owornmask | obj->owornmask;
752 /* Both the items might be worn in competing slots;
753 merger preference (regardless of which is which):
754 primary weapon + alternate weapon -> primary weapon;
755 primary weapon + quiver -> primary weapon;
756 alternate weapon + quiver -> alternate weapon.
757 (Prior to 3.3.0, it was not possible for the two
758 stacks to be worn in different slots and `obj'
759 didn't need to be unworn when merging.) */
762 else if (wmask & W_SWAPWEP)
764 else if (wmask & W_QUIVER)
767 impossible("merging strangely worn items (%lx)", wmask);
768 wmask = otmp->owornmask;
770 if ((otmp->owornmask & ~wmask) != 0L)
772 setworn(otmp, wmask);
775 /* (this should not be necessary, since items
776 already in a monster's inventory don't ever get
777 merged into other objects [only vice versa]) */
778 } else if (obj->owornmask && mcarried(otmp)) {
779 if (obj == MON_WEP(otmp->ocarry)) {
780 MON_WEP(otmp->ocarry) = otmp;
781 otmp->owornmask = W_WEP;
786 /* handle puddings a bit differently; absorption will free the
787 other object automatically so we can just return out from here */
789 pudding_merge_message(otmp, obj);
790 obj_absorb(potmp, pobj);
794 obfree(obj, otmp); /* free(obj), bill->otmp */
801 * Adjust hero intrinsics as if this object was being added to the hero's
802 * inventory. Called _before_ the object has been added to the hero's
805 * This is called when adding objects to the hero's inventory normally (via
806 * addinv) or when an object in the hero's inventory has been polymorphed
809 * It may be valid to merge this code with with addinv_core2().
815 if (obj->oclass == COIN_CLASS) {
817 } else if (obj->otyp == AMULET_OF_YENDOR) {
819 impossible("already have amulet?");
821 u.uachieve.amulet = 1;
822 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
824 impossible("already have candelabrum?");
826 u.uachieve.menorah = 1;
827 } else if (obj->otyp == BELL_OF_OPENING) {
829 impossible("already have silver bell?");
832 } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
834 impossible("already have the book?");
837 } else if (obj->oartifact) {
838 if (is_quest_artifact(obj)) {
839 if (u.uhave.questart)
840 impossible("already have quest artifact?");
841 u.uhave.questart = 1;
844 set_artifact_intrinsic(obj, 1, W_ART);
847 /* "special achievements" aren't discoverable during play, they
848 end up being recorded in XLOGFILE at end of game, nowhere else;
849 record_achieve_special overloads corpsenm which is ordinarily
850 initialized to NON_PM (-1) rather than to 0; any special prize
851 must never be a corpse, egg, tin, figurine, or statue because
852 their use of obj->corpsenm for monster type would conflict,
853 nor be a leash (corpsenm overloaded for m_id of leashed
854 monster) or a novel (corpsenm overloaded for novel index) */
855 if (is_mines_prize(obj)) {
856 u.uachieve.mines_luckstone = 1;
857 obj->record_achieve_special = NON_PM;
859 } else if (is_soko_prize(obj)) {
860 u.uachieve.finish_sokoban = 1;
861 obj->record_achieve_special = NON_PM;
867 * Adjust hero intrinsics as if this object was being added to the hero's
868 * inventory. Called _after_ the object has been added to the hero's
871 * This is called when adding objects to the hero's inventory normally (via
872 * addinv) or when an object in the hero's inventory has been polymorphed
879 if (confers_luck(obj)) {
880 /* new luckstone must be in inventory by this point
881 * for correct calculation */
887 * Add obj to the hero's inventory. Make sure the object is "free".
888 * Adjust hero attributes as necessary.
894 struct obj *otmp, *prev;
895 int saved_otyp = (int) obj->otyp; /* for panic */
896 boolean obj_was_thrown;
898 if (obj->where != OBJ_FREE)
899 panic("addinv: obj not free");
900 /* normally addtobill() clears no_charge when items in a shop are
901 picked up, but won't do so if the shop has become untended */
902 obj->no_charge = 0; /* should not be set in hero's invent */
903 if (Has_contents(obj))
904 picked_container(obj); /* clear no_charge */
905 obj_was_thrown = obj->was_thrown;
906 obj->was_thrown = 0; /* not meaningful for invent */
910 /* merge with quiver in preference to any other inventory slot
911 in case quiver and wielded weapon are both eligible; adding
912 extra to quivered stack is more useful than to wielded one */
913 if (uquiver && merged(&uquiver, &obj)) {
916 panic("addinv: null obj after quiver merge otyp=%d", saved_otyp);
919 /* merge if possible; find end of chain in the process */
920 for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj)
921 if (merged(&otmp, &obj)) {
924 panic("addinv: null obj after merge otyp=%d", saved_otyp);
927 /* didn't merge, so insert into chain */
929 if (flags.invlet_constant || !prev) {
930 obj->nobj = invent; /* insert at beginning */
932 if (flags.invlet_constant)
935 prev->nobj = obj; /* insert at end */
938 obj->where = OBJ_INVENT;
940 /* fill empty quiver if obj was thrown */
941 if (flags.pickup_thrown && !uquiver && obj_was_thrown
942 /* if Mjollnir is thrown and fails to return, we want to
943 auto-pick it when we move to its spot, but not into quiver;
944 aklyses behave like Mjollnir when thrown while wielded, but
945 we lack sufficient information here make them exceptions */
946 && obj->oartifact != ART_MJOLLNIR
947 && (throwing_weapon(obj) || is_ammo(obj)))
951 carry_obj_effects(obj); /* carrying affects the obj */
957 * Some objects are affected by being carried.
958 * Make those adjustments here. Called _after_ the object
959 * has been added to the hero's or monster's inventory,
960 * and after hero's intrinsics have been updated.
963 carry_obj_effects(obj)
966 /* Cursed figurines can spontaneously transform when carried. */
967 if (obj->otyp == FIGURINE) {
968 if (obj->cursed && obj->corpsenm != NON_PM
969 && !dead_species(obj->corpsenm, TRUE)) {
970 attach_fig_transform_timeout(obj);
975 /* Add an item to the inventory unless we're fumbling or it refuses to be
976 * held (via touch_artifact), and give a message.
977 * If there aren't any free inventory slots, we'll drop it instead.
978 * If both success and failure messages are NULL, then we're just doing the
979 * fumbling/slot-limit checking for a silent grab. In any case,
980 * touch_artifact will print its own messages if they are warranted.
983 hold_another_object(obj, drop_fmt, drop_arg, hold_msg)
985 const char *drop_fmt, *drop_arg, *hold_msg;
990 obj->dknown = 1; /* maximize mergibility */
991 if (obj->oartifact) {
992 /* place_object may change these */
993 boolean crysknife = (obj->otyp == CRYSKNIFE);
994 int oerode = obj->oerodeproof;
995 boolean wasUpolyd = Upolyd;
997 /* in case touching this object turns out to be fatal */
998 place_object(obj, u.ux, u.uy);
1000 if (!touch_artifact(obj, &youmonst)) {
1001 obj_extract_self(obj); /* remove it from the floor */
1002 dropy(obj); /* now put it back again :-) */
1004 } else if (wasUpolyd && !Upolyd) {
1005 /* loose your grip if you revert your form */
1007 pline(drop_fmt, drop_arg);
1008 obj_extract_self(obj);
1012 obj_extract_self(obj);
1014 obj->otyp = CRYSKNIFE;
1015 obj->oerodeproof = oerode;
1020 obj = addinv(obj); /* dropping expects obj to be in invent */
1023 long oquan = obj->quan;
1024 int prev_encumbr = near_capacity(); /* before addinv() */
1026 /* encumbrance only matters if it would now become worse
1027 than max( current_value, stressed ) */
1028 if (prev_encumbr < MOD_ENCUMBER)
1029 prev_encumbr = MOD_ENCUMBER;
1030 /* addinv() may redraw the entire inventory, overwriting
1031 drop_arg when it comes from something like doname() */
1033 drop_arg = strcpy(buf, drop_arg);
1036 if (inv_cnt(FALSE) > 52 || ((obj->otyp != LOADSTONE || !obj->cursed)
1037 && near_capacity() > prev_encumbr)) {
1038 /* undo any merge which took place */
1039 if (obj->quan > oquan)
1040 obj = splitobj(obj, oquan);
1043 if (flags.autoquiver && !uquiver && !obj->owornmask
1044 && (is_missile(obj) || ammo_and_launcher(obj, uwep)
1045 || ammo_and_launcher(obj, uswapwep)))
1047 if (hold_msg || drop_fmt)
1048 prinv(hold_msg, obj, oquan);
1055 pline(drop_fmt, drop_arg);
1057 if (can_reach_floor(TRUE)) {
1061 hitfloor(obj, FALSE);
1063 return (struct obj *) 0; /* might be gone */
1066 /* useup() all of an item regardless of its quantity */
1073 obfree(obj, (struct obj *) 0); /* deletes contents also */
1078 register struct obj *obj;
1080 /* Note: This works correctly for containers because they (containers)
1082 if (obj->quan > 1L) {
1083 obj->in_use = FALSE; /* no longer in use */
1085 obj->owt = weight(obj);
1092 /* use one charge from an item and possibly incur shop debt for it */
1094 consume_obj_charge(obj, maybe_unpaid)
1096 boolean maybe_unpaid; /* false if caller handles shop billing */
1106 * Adjust hero's attributes as if this object was being removed from the
1107 * hero's inventory. This should only be called from freeinv() and
1108 * where we are polymorphing an object already in the hero's inventory.
1110 * Should think of a better name...
1116 if (obj->oclass == COIN_CLASS) {
1119 } else if (obj->otyp == AMULET_OF_YENDOR) {
1120 if (!u.uhave.amulet)
1121 impossible("don't have amulet?");
1123 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
1124 if (!u.uhave.menorah)
1125 impossible("don't have candelabrum?");
1126 u.uhave.menorah = 0;
1127 } else if (obj->otyp == BELL_OF_OPENING) {
1129 impossible("don't have silver bell?");
1131 } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1133 impossible("don't have the book?");
1135 } else if (obj->oartifact) {
1136 if (is_quest_artifact(obj)) {
1137 if (!u.uhave.questart)
1138 impossible("don't have quest artifact?");
1139 u.uhave.questart = 0;
1141 set_artifact_intrinsic(obj, 0, W_ART);
1144 if (obj->otyp == LOADSTONE) {
1146 } else if (confers_luck(obj)) {
1149 } else if (obj->otyp == FIGURINE && obj->timed) {
1150 (void) stop_timer(FIG_TRANSFORM, obj_to_any(obj));
1154 /* remove an object from the hero's inventory */
1157 register struct obj *obj;
1159 extract_nobj(obj, &invent);
1168 struct obj *otmp, *otmp2;
1170 for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
1173 /* after unpunish(), or might get deallocated chain */
1174 otmp2 = otmp->nexthere;
1181 /* destroy object in fobj chain (if unpaid, it remains on the bill) */
1184 register struct obj *obj;
1188 if (obj->otyp == AMULET_OF_YENDOR
1189 || obj->otyp == CANDELABRUM_OF_INVOCATION
1190 || obj->otyp == BELL_OF_OPENING
1191 || obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1192 /* player might be doing something stupid, but we
1193 * can't guarantee that. assume special artifacts
1194 * are indestructible via drawbridges, and exploding
1195 * chests, and golem creation, and ...
1199 update_map = (obj->where == OBJ_FLOOR);
1200 obj_extract_self(obj);
1202 newsym(obj->ox, obj->oy);
1203 obfree(obj, (struct obj *) 0); /* frees contents also */
1206 /* try to find a particular type of object at designated map location */
1212 register struct obj *otmp;
1214 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
1215 if (otmp->otyp == otyp)
1221 /* sobj_at(&c) traversal -- find next object of specified type */
1223 nxtobj(obj, type, by_nexthere)
1226 boolean by_nexthere;
1228 register struct obj *otmp;
1230 otmp = obj; /* start with the object after this one */
1232 otmp = !by_nexthere ? otmp->nobj : otmp->nexthere;
1235 } while (otmp->otyp != type);
1244 register struct obj *otmp;
1246 for (otmp = invent; otmp; otmp = otmp->nobj)
1247 if (otmp->otyp == type)
1249 return (struct obj *) 0;
1252 /* Fictional and not-so-fictional currencies.
1253 * http://concord.wikia.com/wiki/List_of_Fictional_Currencies
1255 static const char *const currencies[] = {
1257 "Altarian Dollar", /* The Hitchhiker's Guide to the Galaxy */
1258 "Ankh-Morpork Dollar", /* Discworld */
1259 "auric", /* The Domination of Draka */
1260 "buckazoid", /* Space Quest */
1261 "cirbozoid", /* Starslip */
1262 "credit chit", /* Deus Ex */
1263 "cubit", /* Battlestar Galactica */
1264 "Flanian Pobble Bead", /* The Hitchhiker's Guide to the Galaxy */
1265 "fretzer", /* Jules Verne */
1266 "imperial credit", /* Star Wars */
1267 "Hong Kong Luna Dollar", /* The Moon is a Harsh Mistress */
1268 "kongbuck", /* Snow Crash */
1269 "nanite", /* System Shock 2 */
1270 "quatloo", /* Star Trek, Sim City */
1271 "simoleon", /* Sim City */
1272 "solari", /* Spaceballs */
1273 "spacebuck", /* Spaceballs */
1274 "sporebuck", /* Spore */
1275 "Triganic Pu", /* The Hitchhiker's Guide to the Galaxy */
1276 "woolong", /* Cowboy Bebop */
1277 "zorkmid", /* Zork, NetHack */
1279 "
\83A
\83\8b\83^
\83C
\83\8b\81E
\83h
\83\8b", /* The Hitchhiker's Guide to the Galaxy */
1280 "
\83A
\83\93\83N
\83\82\83\8b\83|
\81[
\83N
\81E
\83h
\83\8b", /* Discworld */
1281 "
\83\86\81[
\83\8a\83b
\83N", /* The Domination of Draka */
1282 "
\83o
\83b
\83J
\83]
\83C
\83h", /* Space Quest */
1283 "
\83T
\81[
\83{
\83]
\83C
\83h", /* Starslip */
1284 "
\83N
\83\8c\83W
\83b
\83g
\81E
\83`
\83b
\83g", /* Deus Ex */
1285 "
\83L
\83\85\81[
\83r
\83b
\83g", /* Battlestar Galactica */
1286 "
\83t
\83\8c\83j
\83A
\83\93\81E
\83s
\83b
\83u
\83\8b\81E
\83r
\81[
\83h", /* The Hitchhiker's Guide to the Galaxy */
1287 "
\83t
\83\8c\83b
\83c
\83@", /* Jules Verne */
1288 "
\92é
\8d\91\83N
\83\8c\83W
\83b
\83g", /* Star Wars */
1289 "
\8d\81\8d`
\8c\8e\83h
\83\8b", /* The Moon is a Harsh Mistress */
1290 "
\83R
\83\93\83o
\83b
\83N", /* Snow Crash */
1291 "
\83i
\81[
\83i
\83C
\83g", /* System Shock 2 */
1292 "
\83N
\83@
\83g
\83\8d", /* Star Trek, Sim City */
1293 "
\83V
\83\82\83\8c\83I
\83\93", /* Sim City */
1294 "
\83\
\83\89\83\8a", /* Spaceballs */
1295 "
\83X
\83y
\81[
\83X
\83o
\83b
\83N", /* Spaceballs */
1296 "
\83X
\83|
\83A
\83o
\83b
\83N", /* Spore */
1297 "
\83g
\83\89\83C
\83K
\83j
\83b
\83N
\81E
\83v
\81[", /* The Hitchhiker's Guide to the Galaxy */
1298 "
\83E
\81[
\83\8d\83\93", /* Cowboy Bebop */
1299 "
\83S
\81[
\83\8b\83h", /* Zork, NetHack */
1310 res = Hallucination ? currencies[rn2(SIZE(currencies))] : "zorkmid";
1312 res = makeplural(res);
1314 res = Hallucination ? currencies[rn2(SIZE(currencies))] : "
\83S
\81[
\83\8b\83h";
1322 register struct obj *otmp;
1324 for (otmp = invent; otmp; otmp = otmp->nobj)
1325 if (otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
1334 register struct obj *otmp;
1336 for (otmp = invent; otmp; otmp = otmp->nobj)
1337 if (otmp->otyp == SPE_NOVEL)
1339 return (struct obj *) 0;
1345 register struct obj *objchn;
1350 if (objchn->o_id == id)
1352 if (Has_contents(objchn) && (temp = o_on(id, objchn->cobj)))
1354 objchn = objchn->nobj;
1356 return (struct obj *) 0;
1361 register struct obj *obj;
1364 register struct obj *otmp;
1366 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
1376 register struct obj *obj = level.objects[x][y];
1379 if (obj->oclass == COIN_CLASS)
1381 obj = obj->nexthere;
1383 return (struct obj *) 0;
1386 /* compact a string of inventory letters by dashing runs of letters */
1391 register int i1 = 1, i2 = 1;
1392 register char ilet, ilet1, ilet2;
1396 buf[++i2] = buf[++i1];
1399 if (ilet == ilet1 + 1) {
1400 if (ilet1 == ilet2 + 1)
1401 buf[i2 - 1] = ilet1 = '-';
1402 else if (ilet2 == '-') {
1403 buf[i2 - 1] = ++ilet1;
1404 buf[i2] = buf[++i1];
1408 } else if (ilet == NOINVSYM) {
1409 /* compact three or more consecutive '#'
1410 characters into "#-#" */
1411 if (i2 >= 2 && buf[i2 - 2] == NOINVSYM && buf[i2 - 1] == NOINVSYM)
1413 else if (i2 >= 3 && buf[i2 - 3] == NOINVSYM && buf[i2 - 2] == '-'
1414 && buf[i2 - 1] == NOINVSYM)
1419 buf[++i2] = buf[++i1];
1424 /* some objects shouldn't be split when count given to getobj or askchain */
1429 return !((obj->otyp == LOADSTONE && obj->cursed)
1430 || (obj == uwep && welded(uwep)));
1433 /* match the prompt for either 'T' or 'R' command */
1438 return !strcmp(action, "take off") || !strcmp(action, "remove");
1441 /* match the prompt for either 'W' or 'P' command */
1446 return !strcmp(action, "wear") || !strcmp(action, "put on");
1451 * struct obj *xxx: object to do something with.
1452 * (struct obj *) 0 error return: no object.
1453 * &zeroobj explicitly no object (as in w-).
1454 !!!! test if gold can be used in unusual ways (eaten etc.)
1455 !!!! may be able to remove "usegold"
1458 ** word
\82É
\82Í
\89p
\8cê
\82Å
\93®
\8e\8c\82ª
\93ü
\82é
\81D
1460 **
\93ú
\96{
\8cê
\82Å
\82Í
\81C
\81u
\82Ç
\82ê
\82ð
\8f\91\82«
\82Ü
\82·
\82©
\81v
\82æ
\82è
\81u
\82Ç
\82ê
\82É
\8f\91\82«
\82Ü
\82·
\82©
\81v
\82Ì
\95û
\82ª
\8e©
\91R
\82È
\82Ì
\82Å
\81C
1461 **
\8dÅ
\8f\89\82Ì
\88ê
\95¶
\8e\9a\82É
\81u
\82É
\81v
\82â
\81u
\82Ì
\81v
\82ð
\8ew
\92è
\82µ
\82½
\8fê
\8d\87\82Í
\8f\95\8e\8c\82ð
\95Ï
\8dX
\82·
\82é
\81D
1466 register const char *let, *word;
1468 register struct obj *otmp;
1469 register char ilet = 0;
1470 char buf[BUFSZ], qbuf[QBUFSZ];
1471 char lets[BUFSZ], altlets[BUFSZ], *ap;
1472 register int foo = 0;
1473 register char *bp = buf;
1474 xchar allowcnt = 0; /* 0, 1 or 2 */
1475 boolean usegold = FALSE; /* can't use gold because its illegal */
1476 boolean allowall = FALSE;
1477 boolean allownone = FALSE;
1478 boolean useboulder = FALSE;
1481 boolean cntgiven = FALSE;
1482 boolean msggiven = FALSE;
1483 boolean oneloop = FALSE;
1485 Loot *sortedinvent, *srtinv;
1492 struct trans_verb *tv = trans_verb(word);
1496 joshi = tv->particle;
1498 if (*let == ALLOW_COUNT)
1499 let++, allowcnt = 1;
1500 if (*let == COIN_CLASS)
1501 let++, usegold = TRUE;
1503 /* Equivalent of an "ugly check" for gold */
1504 if (usegold && !strcmp(word, "eat")
1505 && (!metallivorous(youmonst.data)
1506 || youmonst.data == &mons[PM_RUST_MONSTER]))
1509 if (*let == ALL_CLASSES)
1510 let++, allowall = TRUE;
1511 if (*let == ALLOW_NONE)
1512 let++, allownone = TRUE;
1513 /* "ugly check" for reading fortune cookies, part 1.
1514 * The normal 'ugly check' keeps the object on the inventory list.
1515 * We don't want to do that for shirts/cookies, so the check for
1516 * them is handled a bit differently (and also requires that we set
1517 * allowall in the caller).
1519 if (allowall && !strcmp(word, "read"))
1522 /* another ugly check: show boulders (not statues) */
1523 if (*let == WEAPON_CLASS && !strcmp(word, "throw")
1524 && throws_rocks(youmonst.data))
1528 *bp++ = HANDS_SYM, *bp++ = ' '; /* '-' */
1531 if (!flags.invlet_constant)
1534 /* force invent to be in invlet order before collecting candidate
1535 inventory letters */
1536 sortedinvent = sortloot(&invent, SORTLOOT_INVLET, FALSE,
1537 (boolean FDECL((*), (OBJ_P))) 0);
1539 for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
1540 if (&bp[foo] == &buf[sizeof buf - 1]
1541 || ap == &altlets[sizeof altlets - 1]) {
1542 /* we must have a huge number of NOINVSYM items somehow */
1543 impossible("getobj: inventory overflow");
1547 if (!*let || index(let, otmp->oclass)
1548 || (usegold && otmp->invlet == GOLD_SYM)
1549 || (useboulder && otmp->otyp == BOULDER)) {
1550 register int otyp = otmp->otyp;
1552 bp[foo++] = otmp->invlet;
1553 /* clang-format off */
1555 /* ugly check: remove inappropriate things */
1557 (taking_off(word) /* exclude if not worn */
1558 && !(otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
1559 || (putting_on(word) /* exclude if already worn */
1560 && (otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
1561 #if 0 /* 3.4.1 -- include currently wielded weapon among 'wield' choices */
1562 || (!strcmp(word, "wield")
1563 && (otmp->owornmask & W_WEP))
1565 || (!strcmp(word, "ready") /* exclude when wielded... */
1566 && ((otmp == uwep || (otmp == uswapwep && u.twoweap))
1567 && otmp->quan == 1L)) /* ...unless more than one */
1568 || ((!strcmp(word, "dip") || !strcmp(word, "grease"))
1569 && inaccessible_equipment(otmp, (const char *) 0, FALSE))
1574 /* Second ugly check; unlike the first it won't trigger an
1575 * "else" in "you don't have anything else to ___".
1579 && ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING)
1580 || (otmp->oclass == TOOL_CLASS && otyp != BLINDFOLD
1581 && otyp != TOWEL && otyp != LENSES)))
1582 || (!strcmp(word, "wield")
1583 && (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
1584 || (!strcmp(word, "eat") && !is_edible(otmp))
1585 || (!strcmp(word, "sacrifice")
1586 && (otyp != CORPSE && otyp != AMULET_OF_YENDOR
1587 && otyp != FAKE_AMULET_OF_YENDOR))
1588 || (!strcmp(word, "write with")
1589 && (otmp->oclass == TOOL_CLASS
1590 && otyp != MAGIC_MARKER && otyp != TOWEL))
1591 || (!strcmp(word, "tin")
1592 && (otyp != CORPSE || !tinnable(otmp)))
1593 || (!strcmp(word, "rub")
1594 && ((otmp->oclass == TOOL_CLASS && otyp != OIL_LAMP
1595 && otyp != MAGIC_LAMP && otyp != BRASS_LANTERN)
1596 || (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
1597 || (!strcmp(word, "use or apply")
1598 /* Picks, axes, pole-weapons, bullwhips */
1599 && ((otmp->oclass == WEAPON_CLASS
1600 && !is_pick(otmp) && !is_axe(otmp)
1601 && !is_pole(otmp) && otyp != BULLWHIP)
1602 || (otmp->oclass == POTION_CLASS
1603 /* only applicable potion is oil, and it will only
1604 be offered as a choice when already discovered */
1605 && (otyp != POT_OIL || !otmp->dknown
1606 || !objects[POT_OIL].oc_name_known))
1607 || (otmp->oclass == FOOD_CLASS
1608 && otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF)
1609 || (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
1610 || (!strcmp(word, "invoke")
1612 && !objects[otyp].oc_unique
1613 && (otyp != FAKE_AMULET_OF_YENDOR || otmp->known)
1614 && otyp != CRYSTAL_BALL /* synonym for apply */
1615 /* note: presenting the possibility of invoking non-artifact
1616 mirrors and/or lamps is simply a cruel deception... */
1618 && otyp != MAGIC_LAMP
1619 && (otyp != OIL_LAMP /* don't list known oil lamp */
1620 || (otmp->dknown && objects[OIL_LAMP].oc_name_known)))
1621 || (!strcmp(word, "untrap with")
1622 && ((otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE)
1623 || (otmp->oclass == POTION_CLASS
1624 /* only applicable potion is oil, and it will only
1625 be offered as a choice when already discovered */
1626 && (otyp != POT_OIL || !otmp->dknown
1627 || !objects[POT_OIL].oc_name_known))))
1628 || (!strcmp(word, "tip") && !Is_container(otmp)
1629 /* include horn of plenty if sufficiently discovered */
1630 && (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown
1631 || !objects[HORN_OF_PLENTY].oc_name_known))
1632 || (!strcmp(word, "charge") && !is_chargeable(otmp))
1633 || (!strcmp(word, "open") && otyp != TIN)
1634 || (!strcmp(word, "call") && !objtyp_is_callable(otyp))
1635 || (!strcmp(word, "adjust") && otmp->oclass == COIN_CLASS
1640 /* Third ugly check: acceptable but not listed as likely
1641 * candidates in the prompt or in the inventory subset if
1642 * player responds with '?'.
1645 /* ugly check for unworn armor that can't be worn */
1646 (putting_on(word) && *let == ARMOR_CLASS
1647 && !canwearobj(otmp, &dummymask, FALSE))
1648 /* or armor with 'P' or 'R' or accessory with 'W' or 'T' */
1649 || ((putting_on(word) || taking_off(word))
1650 && ((*let == ARMOR_CLASS) ^ (otmp->oclass == ARMOR_CLASS)))
1651 /* or unsuitable items rubbed on known touchstone */
1652 || (!strncmp(word, "rub on the stone", 16)
1653 && *let == GEM_CLASS && otmp->dknown
1654 && objects[otyp].oc_name_known)
1655 /* suppress corpses on astral, amulets elsewhere */
1656 || (!strcmp(word, "sacrifice")
1657 /* (!astral && amulet) || (astral && !amulet) */
1658 && (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
1659 /* suppress container being stashed into */
1660 || (!strcmp(word, "stash") && !ck_bag(otmp))
1661 /* worn armor (shirt, suit) covered by worn armor (suit, cloak)
1662 or accessory (ring) covered by cursed worn armor (gloves) */
1663 || (taking_off(word)
1664 && inaccessible_equipment(otmp, (const char *) 0,
1665 (boolean) (otmp->oclass == RING_CLASS)))
1666 || (!strcmp(word, "write on")
1667 && (!(otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER)
1668 || !otmp->dknown || !objects[otyp].oc_name_known))
1670 /* acceptable but not listed as likely candidate */
1673 *ap++ = otmp->invlet;
1676 /* clang-format on */
1678 /* "ugly check" for reading fortune cookies, part 2 */
1679 if ((!strcmp(word, "read") && is_readable(otmp)))
1680 allowall = usegold = TRUE;
1683 unsortloot(&sortedinvent);
1686 if (foo == 0 && bp > buf && bp[-1] == ' ')
1688 Strcpy(lets, bp); /* necessary since we destroy buf */
1689 if (foo > 5) /* compactify string */
1693 if (!foo && !allowall && !allownone) {
1695 You("don't have anything %sto %s.", foox ? "else " : "", word);
1697 You("%s%s
\82à
\82Ì
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", foox ? "
\91¼
\82É" : "", jcan(jword));
1698 return (struct obj *) 0;
1699 } else if (!strcmp(word, "write on")) { /* ugly check for magic marker */
1700 /* we wanted all scrolls and books in altlets[], but that came with
1701 'allowall' which we don't want since it prevents "silly thing"
1702 result if anything other than scroll or spellbook is chosen */
1709 Sprintf(qbuf, "What do you want to %s?", word);
1711 Sprintf(qbuf, "%s%s%s
\82©
\81H", what, joshi, jpolite(jword));
1714 else if (iflags.force_invmenu) {
1715 /* don't overwrite a possible quitchars */
1717 ilet = *let ? '?' : '*';
1719 putmsghistory(qbuf, FALSE);
1724 Strcat(qbuf, " [*]");
1726 Sprintf(eos(qbuf), " [%s or ?*]", buf);
1727 ilet = yn_function(qbuf, (char *) 0, '\0');
1734 pline("No count allowed with this command.");
1736 pline("
\82±
\82Ì
\83R
\83}
\83\93\83h
\82É
\90\94\8e\9a\82Í
\82Â
\82©
\82¦
\82È
\82¢
\81D");
1739 ilet = get_count(NULL, ilet, LARGEST_INT, &tmpcnt, TRUE);
1745 if (index(quitchars, ilet)) {
1748 return (struct obj *) 0;
1750 if (ilet == HANDS_SYM) { /* '-' */
1753 char *suf = (char *) 0;
1756 if ((bp = strstr(buf, " on the ")) != 0) {
1757 /* rub on the stone[s] */
1761 if ((bp = strstr(buf, " or ")) != 0) {
1763 bp = (rn2(2) ? buf : (bp + 4));
1766 You("mime %s something%s%s.", ing_suffix(bp), suf ? " " : "",
1769 You("
\89½
\82©
\82ð%s
\82Ó
\82è
\82ð
\82µ
\82½
\81D", bp);
1772 return (allownone ? (struct obj *) &zeroobj : (struct obj *) 0);
1775 /* since gold is now kept in inventory, we need to do processing for
1776 select-from-invent before checking whether gold has been picked */
1777 if (ilet == '?' || ilet == '*') {
1778 char *allowed_choices = (ilet == '?') ? lets : (char *) 0;
1780 char menuquery[QBUFSZ];
1782 menuquery[0] = qbuf[0] = '\0';
1783 if (iflags.force_invmenu)
1785 Sprintf(menuquery, "What do you want to %s?", word);
1787 Sprintf(menuquery, "%s%s%s
\82©
\81H", what, joshi, jpolite(jword));
1788 if (!strcmp(word, "grease"))
1790 Sprintf(qbuf, "your %s", fingers_or_gloves(FALSE));
1792 Sprintf(qbuf, "
\82 \82È
\82½
\82Ì%s", fingers_or_gloves(FALSE));
1793 else if (!strcmp(word, "write with"))
1795 Sprintf(qbuf, "your %s", body_part(FINGERTIP));
1797 Sprintf(qbuf, "
\82 \82È
\82½
\82Ì%s", body_part(FINGERTIP));
1798 else if (!strcmp(word, "wield"))
1800 Sprintf(qbuf, "your %s %s%s", uarmg ? "gloved" : "bare",
1801 makeplural(body_part(HAND)),
1802 !uwep ? " (wielded)" : "");
1804 Sprintf(qbuf, "
\89½
\82à
\8eè
\82É
\82µ
\82È
\82¢%s",
1805 !uwep ? "(
\8c»
\8dÝ)" : "");
1807 else if (!strcmp(word, "ready"))
1809 Sprintf(qbuf, "empty quiver%s",
1810 !uquiver ? " (nothing readied)" : "");
1812 Sprintf(qbuf, "
\8bó
\82Ì
\96î
\93\9b%s",
1813 !uquiver ? " (
\89½
\82à
\8f\80\94õ
\82µ
\82Ä
\82¢
\82È
\82¢)" : "");
1816 if (ilet == '?' && !*lets && *altlets)
1817 allowed_choices = altlets;
1818 ilet = display_pickinv(allowed_choices, *qbuf ? qbuf : (char *) 0,
1820 TRUE, allowcnt ? &ctmp : (long *) 0);
1823 if (ilet == HANDS_SYM)
1824 return (struct obj *) &zeroobj; /* cast away 'const' */
1825 if (ilet == '\033') {
1828 return (struct obj *) 0;
1832 if (allowcnt && ctmp >= 0) {
1836 /* they typed a letter (not a space) at the prompt */
1838 /* find the item which was picked */
1839 for (otmp = invent; otmp; otmp = otmp->nobj)
1840 if (otmp->invlet == ilet)
1842 /* some items have restrictions */
1843 if (ilet == def_oc_syms[COIN_CLASS].sym
1844 /* guard against the [hypothetical] chace of having more
1845 than one invent slot of gold and picking the non-'$' one */
1846 || (otmp && otmp->oclass == COIN_CLASS)) {
1849 You("cannot %s gold.", word);
1851 You("
\8bà
\89Ý%s%s
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D", joshi, jword);
1852 return (struct obj *) 0;
1854 /* Historic note: early Nethack had a bug which was
1855 * first reported for Larn, where trying to drop 2^32-n
1856 * gold pieces was allowed, and did interesting things
1857 * to your money supply. The LRS is the tax bureau
1860 if (cntgiven && cnt <= 0) {
1864 "LRS would be very interested to know you have that much.");
1866 "
\82»
\82Ì
\8bZ
\82Í
\82Æ
\82 \82é
\83Q
\81[
\83\80\82Ì
\83J
\83W
\83m
\82Å
\8eg
\82¦
\82½
\82¯
\82Ç
\81C
\82à
\82Í
\82â
\8eg
\82¦
\82È
\82¢
\82æ
\81D");
1867 return (struct obj *) 0;
1870 if (cntgiven && !strcmp(word, "throw")) {
1871 /* permit counts for throwing gold, but don't accept
1872 * counts for other things since the throw code will
1873 * split off a single item anyway */
1875 return (struct obj *) 0;
1876 if (cnt > 1 && (ilet != def_oc_syms[COIN_CLASS].sym
1877 && !(otmp && otmp->oclass == COIN_CLASS))) {
1879 You("can only throw one item at a time.");
1881 You("
\93¯
\8e\9e\82É
\82½
\82
\82³
\82ñ
\82Ì
\82à
\82Ì
\82ð
\93\8a\82°
\82ç
\82ê
\82È
\82¢
\81D");
1885 context.botl = 1; /* May have changed the amount of money */
1887 /* [we used to set otmp (by finding ilet in invent) here, but
1888 that's been moved above so that otmp can be checked earlier] */
1889 /* verify the chosen object */
1892 You("don't have that object.");
1894 You("
\82»
\82ñ
\82È
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
1896 return (struct obj *) 0;
1898 } else if (cnt < 0 || otmp->quan < cnt) {
1900 You("don't have that many! You have only %ld.", otmp->quan);
1902 pline("
\82»
\82ñ
\82È
\82É
\82½
\82
\82³
\82ñ
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81I
\82¹
\82¢
\82º
\82¢%ld%s
\82Á
\82Ä
\82Æ
\82±
\82¾
\81D", otmp->quan, numeral(otmp));
1904 return (struct obj *) 0;
1909 if (!allowall && let && !index(let, otmp->oclass)
1910 && !(usegold && otmp->oclass == COIN_CLASS)) {
1912 silly_thing(word, otmp);
1914 silly_thing(jword, otmp);
1916 return (struct obj *) 0;
1920 return (struct obj *) 0;
1921 if (cnt != otmp->quan) {
1922 /* don't split a stack of cursed loadstones */
1923 if (splittable(otmp))
1924 otmp = splitobj(otmp, cnt);
1925 else if (otmp->otyp == LOADSTONE && otmp->cursed)
1926 /* kludge for canletgo()'s can't-drop-this message */
1927 otmp->corpsenm = (int) cnt;
1934 silly_thing(word, otmp)
1938 #if 1 /* 'P','R' vs 'W','T' handling is obsolete */
1941 const char *s1, *s2, *s3;
1942 int ocls = otmp->oclass, otyp = otmp->otyp;
1945 /* check for attempted use of accessory commands ('P','R') on armor
1946 and for corresponding armor commands ('W','T') on accessories */
1947 if (ocls == ARMOR_CLASS) {
1949 if (!strcmp(word, "put on"))
1950 s1 = "W", s2 = "wear", s3 = "";
1951 else if (!strcmp(word, "remove"))
1952 s1 = "T", s2 = "take", s3 = " off";
1954 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1955 s1 = "W", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1956 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1957 s1 = "T", s2 = "
\82Í
\82¸
\82·", s3 = "";
1959 } else if ((ocls == RING_CLASS || otyp == MEAT_RING)
1960 || ocls == AMULET_CLASS
1961 || (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
1963 if (!strcmp(word, "wear"))
1964 s1 = "P", s2 = "put", s3 = " on";
1965 else if (!strcmp(word, "take off"))
1966 s1 = "R", s2 = "remove", s3 = "";
1968 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1969 s1 = "P", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1970 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1971 s1 = "R", s2 = "
\82Í
\82¸
\82·", s3 = "";
1976 pline("Use the '%s' command to %s %s%s.", s1, s2,
1977 !(is_plural(otmp) || pair_of(otmp)) ? "that" : "those", s3);
1979 pline("
\82»
\82ê
\82ð%s
\82É
\82Í'%s'
\83R
\83}
\83\93\83h
\82ð
\8eg
\82¤
\82±
\82Æ
\81D", s2, s1);
1983 pline(silly_thing_to, word);
1990 /* use allow_category() from pickup.c */
1991 return (int) allow_category(otmp);
1998 return (otmp->unpaid || (Has_contents(otmp) && count_unpaid(otmp->cobj)));
2004 return (boolean) (uarm || uarmc || uarmf || uarmg
2005 || uarmh || uarms || uarmu);
2012 return (otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_SADDLE | W_WEAPONS))
2017 /* extra xprname() input that askchain() can't pass through safe_qbuf() */
2018 STATIC_VAR struct xprnctx {
2023 /* safe_qbuf() -> short_oname() callback */
2028 return xprname(obj, (char *) 0, safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
2032 /* alternate safe_qbuf() -> short_oname() callback */
2034 safeq_shortxprname(obj)
2037 return xprname(obj, ansimpleoname(obj), safeq_xprn_ctx.let,
2038 safeq_xprn_ctx.dot, 0L, 0L);
2041 static NEARDATA const char removeables[] = { ARMOR_CLASS, WEAPON_CLASS,
2042 RING_CLASS, AMULET_CLASS,
2045 /* Interactive version of getobj - used for Drop, Identify, and Takeoff (A).
2046 Return the number of times fn was called successfully.
2047 If combo is TRUE, we just use this to get a category list. */
2048 /*JP CHECK: 3.6.6
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
2049 do.c:1068: || (result = ggetobj("drop", drop, 0, FALSE, (unsigned *) 0)) < -1)
2050 do.c:1117: i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
2051 do_wear.c:3153: || (result = ggetobj("take off", select_off, 0, FALSE,
2052 do_wear.c:3207: i = ggetobj("take off", select_off, 0, TRUE, &ggofeedback);
2053 invent.c:2564: n = ggetobj("identify", identify, id_limit, FALSE,
2056 ggetobj(word, fn, mx, combo, resultflags)
2058 int FDECL((*fn), (OBJ_P)), mx;
2059 boolean combo; /* combination menu flag */
2060 unsigned *resultflags;
2062 int FDECL((*ckfn), (OBJ_P)) = (int FDECL((*), (OBJ_P))) 0;
2063 boolean FDECL((*ofilter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
2064 boolean takeoff, ident, allflag, m_seen;
2066 int oletct, iletct, unpaid, oc_of_sym;
2067 char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 10];
2068 char extra_removeables[3 + 1]; /* uwep,uswapwep,uquiver */
2069 char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
2071 const char *joshi = "
\82ð";
2074 const struct trans_verb *tv = trans_verb(word);
2076 joshi = tv->particle;
2081 You("have nothing to %s.", word);
2083 You("%s
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", jcan(jword));
2085 *resultflags = ALL_FINISHED;
2090 takeoff = ident = allflag = m_seen = FALSE;
2091 add_valid_menu_class(0); /* reset */
2092 if (taking_off(word)) {
2095 } else if (!strcmp(word, "identify")) {
2097 ofilter = not_fully_identified;
2100 iletct = collect_obj_classes(ilets, invent, FALSE, ofilter, &itemcount);
2101 unpaid = count_unpaid(invent);
2103 if (ident && !iletct) {
2104 return -1; /* no further identifications */
2105 } else if (invent) {
2106 ilets[iletct++] = ' ';
2108 ilets[iletct++] = 'u';
2109 if (count_buc(invent, BUC_BLESSED, ofilter))
2110 ilets[iletct++] = 'B';
2111 if (count_buc(invent, BUC_UNCURSED, ofilter))
2112 ilets[iletct++] = 'U';
2113 if (count_buc(invent, BUC_CURSED, ofilter))
2114 ilets[iletct++] = 'C';
2115 if (count_buc(invent, BUC_UNKNOWN, ofilter))
2116 ilets[iletct++] = 'X';
2117 ilets[iletct++] = 'a';
2119 ilets[iletct++] = 'i';
2121 ilets[iletct++] = 'm'; /* allow menu presentation on request */
2122 ilets[iletct] = '\0';
2126 Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]",
2129 Sprintf(qbuf,"
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\82à
\82Ì%s%s
\82©
\81H[%s]", joshi,
2130 jpolite(jword), ilets);
2133 if (buf[0] == '\033')
2135 if (index(buf, 'i')) {
2136 char ailets[1+26+26+1+5+1]; /* $ + a-z + A-Z + # + slop + \0 */
2139 /* applicable inventory letters; if empty, show entire invent */
2142 for (otmp = invent; otmp; otmp = otmp->nobj)
2143 /* index() check: limit overflow items to one '#' */
2144 if ((*ofilter)(otmp) && !index(ailets, otmp->invlet))
2145 (void) strkitten(ailets, otmp->invlet);
2146 if (display_inventory(ailets, TRUE) == '\033')
2152 extra_removeables[0] = '\0';
2154 /* arbitrary types of items can be placed in the weapon slots
2155 [any duplicate entries in extra_removeables[] won't matter] */
2157 (void) strkitten(extra_removeables, uwep->oclass);
2159 (void) strkitten(extra_removeables, uswapwep->oclass);
2161 (void) strkitten(extra_removeables, uquiver->oclass);
2165 olets[oletct = 0] = '\0';
2166 while ((sym = *ip++) != '\0') {
2169 oc_of_sym = def_char_to_objclass(sym);
2170 if (takeoff && oc_of_sym != MAXOCLASSES) {
2171 if (index(extra_removeables, oc_of_sym)) {
2172 ; /* skip rest of takeoff checks */
2173 } else if (!index(removeables, oc_of_sym)) {
2175 pline("Not applicable.");
2177 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2179 } else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
2182 } else if (oc_of_sym == WEAPON_CLASS && !uwep && !uswapwep
2185 You("are not wielding anything.");
2187 You("
\89½
\82à
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
2189 } else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
2191 You("are not wearing rings.");
2193 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
2195 } else if (oc_of_sym == AMULET_CLASS && !uamul) {
2197 You("are not wearing an amulet.");
2199 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
2201 } else if (oc_of_sym == TOOL_CLASS && !ublindf) {
2203 You("are not wearing a blindfold.");
2205 You("
\96Ú
\89B
\82µ
\82ð
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
2210 if (oc_of_sym == COIN_CLASS && !combo) {
2212 } else if (sym == 'a') {
2214 } else if (sym == 'A') {
2215 ; /* same as the default */
2216 } else if (sym == 'u') {
2217 add_valid_menu_class('u');
2219 } else if (index("BUCX", sym)) {
2220 add_valid_menu_class(sym); /* 'B','U','C',or 'X' */
2222 } else if (sym == 'm') {
2224 } else if (oc_of_sym == MAXOCLASSES) {
2226 You("don't have any %c's.", sym);
2228 You("%c
\82É
\91®
\82·
\82é
\95¨
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", sym);
2229 } else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */
2230 if (!index(olets, oc_of_sym)) {
2231 add_valid_menu_class(oc_of_sym);
2232 olets[oletct++] = oc_of_sym;
2240 || (!oletct && ckfn != ckunpaid && ckfn != ckvalidcat))
2242 } else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) {
2245 /* !!!! test gold dropping */
2246 } else if (allowgold == 2 && !oletct) {
2247 return 1; /* you dropped gold (or at least tried to) */
2250 int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
2252 * askchain() has already finished the job in this case
2253 * so set a special flag to convey that back to the caller
2254 * so that it won't continue processing.
2255 * Fix for bug C331-1 reported by Irina Rempt-Drijfhout.
2257 if (combo && allflag && resultflags)
2258 *resultflags |= ALL_FINISHED;
2264 * Walk through the chain starting at objchn and ask for all objects
2265 * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
2266 * whether the action in question (i.e., fn) has to be performed.
2267 * If allflag then no questions are asked. Mx gives the max number
2268 * of objects to be treated. Return the number of objects treated.
2270 /*JP CHECK: 3.6.2
\82Å
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
2271 invent.c:2228: int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
2272 pickup.c:3208: if (askchain(objlist, (one_by_one ? (char *) 0 : selection), allflag,
2273 word
\82É
\82Í
\93®
\8e\8c\82ª
\89p
\8cê
\82Å
\93ü
\82é
\81B
2276 askchain(objchn, olets, allflag, fn, ckfn, mx, word)
2277 struct obj **objchn; /* *objchn might change */
2279 const char *olets, *word; /* olets is an Obj Class char array */
2280 int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
2282 struct obj *otmp, *otmpo;
2283 register char sym, ilet;
2284 int cnt = 0, dud = 0, tmp;
2285 boolean takeoff, nodot, ident, take_out, put_in, first, ininv, bycat;
2286 char qbuf[QBUFSZ], qpfx[QBUFSZ];
2287 Loot *sortedchn = 0;
2289 takeoff = taking_off(word);
2290 ident = !strcmp(word, "identify");
2291 take_out = !strcmp(word, "take out");
2292 put_in = !strcmp(word, "put in");
2293 nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
2294 || takeoff || take_out || put_in);
2295 ininv = (*objchn == invent);
2296 bycat = (menu_class_present('u')
2297 || menu_class_present('B') || menu_class_present('U')
2298 || menu_class_present('C') || menu_class_present('X'));
2300 /* someday maybe we'll sort by 'olets' too (temporarily replace
2301 flags.packorder and pass SORTLOOT_PACK), but not yet... */
2302 sortedchn = sortloot(objchn, SORTLOOT_INVLET, FALSE,
2303 (boolean FDECL((*), (OBJ_P))) 0);
2307 * Interrogate in the object class order specified.
2308 * For example, if a person specifies =/ then first all rings
2309 * will be asked about followed by all wands. -dgk
2313 if (*objchn && (*objchn)->oclass == COIN_CLASS)
2314 ilet--; /* extra iteration */
2316 * Multiple Drop can change the invent chain while it operates
2317 * (dropping a burning potion of oil while levitating creates
2318 * an explosion which can destroy inventory items), so simple
2320 * for (otmp = *objchn; otmp; otmp = otmp2) {
2321 * otmp2 = otmp->nobj;
2324 * is inadequate here. Use each object's bypass bit to keep
2325 * track of which list elements have already been processed.
2327 bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */
2328 while ((otmp = nxt_unbypassed_loot(sortedchn, *objchn)) != 0) {
2331 else if (ilet == 'Z')
2332 ilet = NOINVSYM; /* '#' */
2335 if (olets && *olets && otmp->oclass != *olets)
2337 if (takeoff && !is_worn(otmp))
2339 if (ident && !not_fully_identified(otmp))
2341 if (ckfn && !(*ckfn)(otmp))
2343 if (bycat && !ckvalidcat(otmp))
2346 safeq_xprn_ctx.let = ilet;
2347 safeq_xprn_ctx.dot = !nodot;
2350 /* traditional_loot() skips prompting when only one
2351 class of objects is involved, so prefix the first
2352 object being queried here with an explanation why */
2353 if (take_out || put_in)
2354 Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
2358 (void) safe_qbuf(qbuf, qpfx, "?", otmp,
2359 ininv ? safeq_xprname : doname,
2360 ininv ? safeq_shortxprname : ansimpleoname,
2363 (void) safe_qbuf(qbuf, qpfx, "
\81H", otmp,
2364 ininv ? safeq_xprname : doname,
2365 ininv ? safeq_shortxprname : ansimpleoname,
2366 "
\83A
\83C
\83e
\83\80");
2368 sym = (takeoff || ident || otmp->quan < 2L) ? nyaq(qbuf)
2375 /* Number was entered; split the object unless it corresponds
2376 to 'none' or 'all'. 2 special cases: cursed loadstones and
2377 welded weapons (eg, multiple daggers) will remain as merged
2378 unit; done to avoid splitting an object that won't be
2379 droppable (even if we're picking up rather than dropping). */
2384 if (yn_number < otmp->quan && splittable(otmp))
2385 otmp = splitobj(otmp, yn_number);
2395 if (container_gone(fn)) {
2396 /* otmp caused magic bag to explode;
2397 both are now gone */
2398 otmp = 0; /* and return */
2399 } else if (otmp && otmp != otmpo) {
2400 /* split occurred, merge again */
2401 (void) merged(&otmpo, &otmp);
2415 /* special case for seffects() */
2421 if (olets && *olets && *++olets)
2424 if (!takeoff && (dud || cnt))
2426 pline("That was all.");
2428 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
2429 else if (!dud && !cnt)
2431 pline("No applicable objects.");
2433 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2435 unsortloot(&sortedchn);
2436 bypass_objlist(*objchn, FALSE);
2441 * Object identification routines:
2444 /* make an object actually be identified; no display updating */
2446 fully_identify_obj(otmp)
2449 makeknown(otmp->otyp);
2450 if (otmp->oartifact)
2451 discover_artifact((xchar) otmp->oartifact);
2452 otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
2453 if (Is_container(otmp) || otmp->otyp == STATUE)
2454 otmp->cknown = otmp->lknown = 1;
2455 if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
2456 learn_egg_type(otmp->corpsenm);
2459 /* ggetobj callback routine; identify an object and give immediate feedback */
2464 fully_identify_obj(otmp);
2465 prinv((char *) 0, otmp, 0L);
2469 /* menu of unidentified objects; select and identify up to id_limit of them */
2471 menu_identify(id_limit)
2474 menu_item *pick_list;
2475 int n, i, first = 1, tryct = 5;
2477 /* assumptions: id_limit > 0 and at least one unID'd item is present */
2481 Sprintf(buf, "What would you like to identify %s?",
2482 first ? "first" : "next");
2484 Sprintf(buf, "
\82Ç
\82ê
\82ð%s
\82É
\8e¯
\95Ê
\82µ
\82Ü
\82·
\82©
\81H",
2485 first ? "
\8dÅ
\8f\89" : "
\8e\9f");
2487 n = query_objlist(buf, &invent, (SIGNAL_NOMENU | SIGNAL_ESCAPE
2488 | USE_INVLET | INVORDER_SORT),
2489 &pick_list, PICK_ANY, not_fully_identified);
2494 for (i = 0; i < n; i++, id_limit--)
2495 (void) identify(pick_list[i].item.a_obj);
2496 free((genericptr_t) pick_list);
2497 mark_synch(); /* Before we loop to pop open another menu */
2499 } else if (n == -2) { /* player used ESC to quit menu */
2501 } else if (n == -1) { /* no eligible items found */
2503 pline("That was all.");
2505 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
2507 } else if (!--tryct) { /* stop re-prompting */
2508 pline1(thats_enough_tries);
2510 } else { /* try again */
2512 pline("Choose an item; use ESC to decline.");
2514 pline("
\83A
\83C
\83e
\83\80\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢;
\82â
\82ß
\82é
\82È
\82çESC
\81D");
2518 /* count the unidentified items */
2520 count_unidentified(objchn)
2526 for (obj = objchn; obj; obj = obj->nobj)
2527 if (not_fully_identified(obj))
2532 /* dialog with user to identify a given number of items; 0 means all */
2534 identify_pack(id_limit, learning_id)
2536 boolean learning_id; /* true if we just read unknown identify scroll */
2539 int n, unid_cnt = count_unidentified(invent);
2543 You("have already identified all %sof your possessions.",
2544 learning_id ? "the rest " : "");
2546 You("%s
\91S
\82Ä
\82Ì
\8f\8a\97L
\95¨
\82ð
\8e¯
\95Ê
\82µ
\82Ä
\82µ
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D",
2547 learning_id ? "
\8ec
\82è" : "");
2549 } else if (!id_limit || id_limit >= unid_cnt) {
2550 /* identify everything */
2551 /* TODO: use fully_identify_obj and cornline/menu/whatever here */
2552 for (obj = invent; obj; obj = obj->nobj) {
2553 if (not_fully_identified(obj)) {
2554 (void) identify(obj);
2560 /* identify up to `id_limit' items */
2562 if (flags.menu_style == MENU_TRADITIONAL)
2564 n = ggetobj("identify", identify, id_limit, FALSE,
2567 break; /* quit or no eligible items */
2568 } while ((id_limit -= n) > 0);
2569 if (n == 0 || n < -1)
2570 menu_identify(id_limit);
2575 /* called when regaining sight; mark inventory objects which were picked
2576 up while blind as now having been seen */
2578 learn_unseen_invent()
2583 return; /* sanity check */
2585 for (otmp = invent; otmp; otmp = otmp->nobj) {
2587 continue; /* already seen */
2588 /* set dknown, perhaps bknown (for priest[ess]) */
2591 * If object->eknown gets implemented (see learnwand(zap.c)),
2592 * handle deferred discovery here.
2598 /* persistent inventory window is maintained by interface code;
2599 'update_inventory' used to be a macro for
2600 (*windowprocs.win_update_inventory) but the restore hackery
2601 was getting out of hand; this is now a central call point */
2609 * Ought to check (windowprocs.wincap2 & WC2_PERM_INVENT) here....
2611 * We currently don't skip this call when iflags.perm_invent is False
2612 * because curses uses that to disable a previous perm_invent window
2613 * (after toggle via 'O'; perhaps the options code should handle that).
2615 (*windowprocs.win_update_inventory)();
2618 /* should of course only be called for things in invent */
2623 if (!flags.invlet_constant) {
2624 obj->invlet = NOINVSYM;
2631 * Print the indicated quantity of the given object. If quan == 0L then use
2632 * the current quantity.
2635 prinv(prefix, obj, quan)
2643 pline("%s%s%s", prefix, *prefix ? " " : "",
2644 xprname(obj, (char *) 0, obj_to_let(obj), TRUE, 0L, quan));
2647 xprname(obj, (char *)0, obj_to_let(obj), *prefix ? FALSE : TRUE, 0L, quan),
2653 xprname(obj, txt, let, dot, cost, quan)
2655 const char *txt; /* text to print instead of obj */
2656 char let; /* inventory letter */
2657 boolean dot; /* append period; (dot && cost => Iu) */
2658 long cost; /* cost (for inventory of unpaid or expended items) */
2659 long quan; /* if non-0, print this quantity, not obj->quan */
2661 #ifdef LINT /* handle static char li[BUFSZ]; */
2664 static char li[BUFSZ];
2666 char suffix[80]; /* plenty of room for count and hallucinatory currency */
2667 int sfxlen, txtlen; /* signed int for %*s formatting */
2669 boolean use_invlet = (flags.invlet_constant
2670 && let != CONTAINED_SYM && let != HANDS_SYM);
2674 savequan = obj->quan;
2679 * - Then obj == null and 'txt' refers to hands or fingers.
2680 * * Then obj == null and we are printing a total amount.
2681 * > Then the object is contained and doesn't have an inventory letter.
2683 fmt = "%c - %.*s%s";
2686 txtlen = (int) strlen(txt);
2688 if (cost != 0L || let == '*') {
2689 /* if dot is true, we're doing Iu, otherwise Ix */
2690 if (dot && use_invlet)
2693 Sprintf(suffix, "%c%6ld %.50s", iflags.menu_tab_sep ? '\t' : ' ',
2694 cost, currency(cost));
2696 Sprintf(suffix, "%c%6ld%.50s", iflags.menu_tab_sep ? '\t' : ' ',
2697 cost, currency(cost));
2699 if (!iflags.menu_tab_sep) {
2700 fmt = "%c - %-45.*s%s";
2705 /* ordinary inventory display or pickup message */
2709 Strcpy(suffix, dot ? "." : "");
2711 Strcpy(suffix, dot ? "
\81D" : "");
2713 sfxlen = (int) strlen(suffix);
2714 if (txtlen > BUFSZ - 1 - (4 + sfxlen)) /* 4: "c - " prefix */
2715 txtlen = BUFSZ - 1 - (4 + sfxlen);
2716 Sprintf(li, fmt, let, txtlen, txt, suffix);
2719 obj->quan = savequan;
2724 /* the 'i' command */
2728 (void) display_inventory((char *) 0, FALSE);
2735 * Scan the given list of objects. If last_found is NULL, return the first
2736 * unpaid object found. If last_found is not NULL, then skip over unpaid
2737 * objects until last_found is reached, then set last_found to NULL so the
2738 * next unpaid object is returned. This routine recursively follows
2741 STATIC_OVL struct obj *
2742 find_unpaid(list, last_found)
2743 struct obj *list, **last_found;
2750 /* still looking for previous unpaid object */
2751 if (list == *last_found)
2752 *last_found = (struct obj *) 0;
2754 return ((*last_found = list));
2756 if (Has_contents(list)) {
2757 if ((obj = find_unpaid(list->cobj, last_found)) != 0)
2762 return (struct obj *) 0;
2765 /* for perm_invent when operating on a partial inventory display, so that
2766 the persistent one doesn't get shrunk during filtering for item selection
2767 then regrown to full inventory, possibly being resized in the process */
2768 static winid cached_pickinv_win = WIN_ERR;
2771 free_pickinv_cache()
2773 if (cached_pickinv_win != WIN_ERR) {
2774 destroy_nhwindow(cached_pickinv_win);
2775 cached_pickinv_win = WIN_ERR;
2780 * Internal function used by display_inventory and getobj that can display
2781 * inventory and return a count as well as a letter. If out_cnt is not null,
2782 * any count returned from the menu selection is placed here.
2785 display_pickinv(lets, xtra_choice, query, want_reply, out_cnt)
2786 register const char *lets;
2787 const char *xtra_choice; /* "fingers", pick hands rather than an object */
2793 static const char not_carrying_anything[] = "Not carrying anything";
2795 static const char not_carrying_anything[] = "
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢";
2796 struct obj *otmp, wizid_fakeobj;
2798 char *invlet = flags.inv_order;
2800 winid win; /* windows being used */
2802 menu_item *selected;
2804 Loot *sortedinvent, *srtinv;
2805 boolean wizid = (wizard && iflags.override_ID), gotsomething = FALSE;
2808 lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
2810 if (iflags.perm_invent && (lets || xtra_choice || wizid)) {
2811 /* partial inventory in perm_invent setting; don't operate on
2812 full inventory window, use an alternate one instead; create
2813 the first time needed and keep it for re-use as needed later */
2814 if (cached_pickinv_win == WIN_ERR)
2815 cached_pickinv_win = create_nhwindow(NHW_MENU);
2816 win = cached_pickinv_win;
2821 * Exit early if no inventory -- but keep going if we are doing
2822 * a permanent inventory update. We need to keep going so the
2823 * permanent inventory window updates itself to remove the last
2824 * item(s) dropped. One down side: the addition of the exception
2825 * for permanent inventory window updates _can_ pop the window
2826 * up when it's not displayed -- even if it's empty -- because we
2827 * don't know at this level if its up or not. This may not be
2828 * an issue if empty checks are done before hand and the call
2829 * to here is short circuited away.
2831 * 2: our count here is only to distinguish between 0 and 1 and
2832 * more than 1; for the last one, we don't need a precise number.
2833 * For perm_invent update we force 'more than 1'.
2835 n = (iflags.perm_invent && !lets && !want_reply) ? 2
2836 : lets ? (int) strlen(lets)
2837 : !invent ? 0 : !invent->nobj ? 1 : 2;
2838 /* for xtra_choice, there's another 'item' not included in initial 'n';
2839 for !lets (full invent) and for override_ID (wizard mode identify),
2840 skip message_menu handling of single item even if item count was 1 */
2841 if (xtra_choice || (n == 1 && (!lets || iflags.override_ID)))
2846 pline("%s.", not_carrying_anything);
2848 pline("%s
\81D", not_carrying_anything);
2852 /* oxymoron? temporarily assign permanent inventory letters */
2853 if (!flags.invlet_constant)
2856 if (n == 1 && !iflags.force_invmenu) {
2857 /* when only one item of interest, use pline instead of menus;
2858 we actually use a fake message-line menu in order to allow
2859 the user to perform selection at the --More-- prompt for tty */
2862 /* xtra_choice is "bare hands" (wield), "fingertip" (Engrave),
2863 "nothing" (ready Quiver), or "fingers" (apply grease) */
2864 ret = message_menu(HANDS_SYM, PICK_ONE,
2865 xprname((struct obj *) 0, xtra_choice,
2866 HANDS_SYM, TRUE, 0L, 0L)); /* '-' */
2868 for (otmp = invent; otmp; otmp = otmp->nobj)
2869 if (!lets || otmp->invlet == lets[0])
2872 ret = message_menu(otmp->invlet,
2873 want_reply ? PICK_ONE : PICK_NONE,
2874 xprname(otmp, (char *) 0, lets[0],
2878 *out_cnt = -1L; /* select all */
2882 sortflags = (flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET;
2884 sortflags |= SORTLOOT_PACK;
2885 sortedinvent = sortloot(&invent, sortflags, FALSE,
2886 (boolean FDECL((*), (OBJ_P))) 0);
2890 if (wizard && iflags.override_ID) {
2892 char prompt[QBUFSZ];
2894 unid_cnt = count_unidentified(invent);
2895 Sprintf(prompt, "Debug Identify"); /* 'title' rather than 'prompt' */
2897 Sprintf(eos(prompt),
2898 " -- unidentified or partially identified item%s",
2900 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, prompt, MENU_UNSELECTED);
2902 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
2903 "(all items are permanently identified already)",
2905 gotsomething = TRUE;
2907 any.a_obj = &wizid_fakeobj;
2908 Sprintf(prompt, "select %s to permanently identify",
2909 (unid_cnt == 1) ? "it": "any or all of them");
2910 /* wiz_identify stuffed the wiz_identify command character (^I)
2911 into iflags.override_ID for our use as an accelerator;
2912 it could be ambiguous if player has assigned a letter to
2913 the #wizidentify command, so include it as a group accelator
2914 but use '_' as the primary selector */
2916 Sprintf(eos(prompt), " (%s for all)",
2917 visctrl(iflags.override_ID));
2918 add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
2919 prompt, MENU_UNSELECTED);
2920 gotsomething = TRUE;
2922 } else if (xtra_choice) {
2923 /* wizard override ID and xtra_choice are mutually exclusive */
2925 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2926 "Miscellaneous", MENU_UNSELECTED);
2927 any.a_char = HANDS_SYM; /* '-' */
2928 add_menu(win, NO_GLYPH, &any, HANDS_SYM, 0, ATR_NONE,
2929 xtra_choice, MENU_UNSELECTED);
2930 gotsomething = TRUE;
2934 for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
2935 if (lets && !index(lets, otmp->invlet))
2937 if (!flags.sortpack || otmp->oclass == *invlet) {
2938 if (wizid && !not_fully_identified(otmp))
2940 any = zeroany; /* all bits zero */
2941 ilet = otmp->invlet;
2942 if (flags.sortpack && !classcount) {
2943 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2944 let_to_name(*invlet, FALSE,
2945 (want_reply && iflags.menu_head_objsym)),
2953 add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng), &any, ilet,
2954 wizid ? def_oc_syms[(int) otmp->oclass].sym : 0,
2955 ATR_NONE, doname(otmp), MENU_UNSELECTED);
2956 gotsomething = TRUE;
2959 if (flags.sortpack) {
2962 if (--invlet != venom_inv) {
2967 if (iflags.force_invmenu && lets && want_reply) {
2970 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2971 "Special", MENU_UNSELECTED);
2973 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2974 "
\93Á
\8eê", MENU_UNSELECTED);
2978 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
2979 "(list everything)", MENU_UNSELECTED);
2981 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
2982 "(
\91S
\82Ä
\82Ì
\88ê
\97\97)", MENU_UNSELECTED);
2984 gotsomething = TRUE;
2986 unsortloot(&sortedinvent);
2987 /* for permanent inventory where we intend to show everything but
2988 nothing has been listed (because there isn't anyhing to list;
2989 the n==0 case above gets skipped for perm_invent), put something
2991 if (iflags.perm_invent && !lets && !gotsomething) {
2993 add_menu(win, NO_GLYPH, &any, 0, 0, 0,
2994 not_carrying_anything, MENU_UNSELECTED);
2997 end_menu(win, query && *query ? query : (char *) 0);
2999 n = select_menu(win,
3000 wizid ? PICK_ANY : want_reply ? PICK_ONE : PICK_NONE,
3006 /* identifying items will update perm_invent, calling this
3007 routine recursively, and we don't want the nested call
3008 to filter on unID'd items */
3009 iflags.override_ID = 0;
3011 for (i = 0; i < n; ++i) {
3012 otmp = selected[i].item.a_obj;
3013 if (otmp == &wizid_fakeobj) {
3014 identify_pack(0, FALSE);
3016 if (not_fully_identified(otmp))
3017 (void) identify(otmp);
3021 ret = selected[0].item.a_char;
3023 *out_cnt = selected[0].count;
3025 free((genericptr_t) selected);
3027 ret = !n ? '\0' : '\033'; /* cancelled */
3033 * If lets == NULL or "", list all objects in the inventory. Otherwise,
3034 * list all objects with object classes that match the order in lets.
3036 * Returns the letter identifier of a selected item, or 0 if nothing
3040 display_inventory(lets, want_reply)
3044 return display_pickinv(lets, (char *) 0, (char *) 0,
3045 want_reply, (long *) 0);
3049 * Show what is current using inventory letters.
3053 display_used_invlets(avoidlet)
3058 char *invlet = flags.inv_order;
3059 int n, classcount, invdone = 0;
3062 menu_item *selected;
3065 win = create_nhwindow(NHW_MENU);
3068 any = zeroany; /* set all bits to zero */
3070 for (otmp = invent; otmp; otmp = otmp->nobj) {
3071 ilet = otmp->invlet;
3072 if (ilet == avoidlet)
3074 if (!flags.sortpack || otmp->oclass == *invlet) {
3075 if (flags.sortpack && !classcount) {
3076 any = zeroany; /* zero */
3077 add_menu(win, NO_GLYPH, &any, 0, 0,
3078 iflags.menu_headings,
3079 let_to_name(*invlet, FALSE, FALSE),
3084 add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng),
3085 &any, ilet, 0, ATR_NONE,
3086 doname(otmp), MENU_UNSELECTED);
3089 if (flags.sortpack && *++invlet)
3093 end_menu(win, "Inventory letters used:");
3095 n = select_menu(win, PICK_ONE, &selected);
3097 ret = selected[0].item.a_char;
3098 free((genericptr_t) selected);
3100 ret = !n ? '\0' : '\033'; /* cancelled */
3101 destroy_nhwindow(win);
3107 * Returns the number of unpaid items within the given list. This includes
3108 * contained objects.
3119 if (Has_contents(list))
3120 count += count_unpaid(list->cobj);
3127 * Returns the number of items with b/u/c/unknown within the given list.
3128 * This does NOT include contained objects.
3130 * Assumes that the hero sees or touches or otherwise senses the objects
3131 * at some point: bknown is forced for priest[ess], like in xname().
3134 count_buc(list, type, filterfunc)
3137 boolean FDECL((*filterfunc), (OBJ_P));
3141 for (; list; list = list->nobj) {
3142 /* priests always know bless/curse state */
3143 if (Role_if(PM_PRIEST))
3144 list->bknown = (list->oclass != COIN_CLASS);
3145 /* some actions exclude some or most items */
3146 if (filterfunc && !(*filterfunc)(list))
3149 /* coins are either uncursed or unknown based upon option setting */
3150 if (list->oclass == COIN_CLASS) {
3151 if (type == (iflags.goldX ? BUC_UNKNOWN : BUC_UNCURSED))
3155 /* check whether this object matches the requested type */
3157 ? (type == BUC_UNKNOWN)
3158 : list->blessed ? (type == BUC_BLESSED)
3159 : list->cursed ? (type == BUC_CURSED)
3160 : (type == BUC_UNCURSED))
3166 /* similar to count_buc(), but tallies all states at once
3167 rather than looking for a specific type */
3169 tally_BUCX(list, by_nexthere, bcp, ucp, ccp, xcp, ocp)
3171 boolean by_nexthere;
3172 int *bcp, *ucp, *ccp, *xcp, *ocp;
3174 /* Future extensions:
3175 * Skip current_container when list is invent, uchain when
3176 * first object of list is located on the floor. 'ocp' will then
3177 * have a function again (it was a counter for having skipped gold,
3178 * but that's not skipped anymore).
3180 *bcp = *ucp = *ccp = *xcp = *ocp = 0;
3181 for ( ; list; list = (by_nexthere ? list->nexthere : list->nobj)) {
3182 /* priests always know bless/curse state */
3183 if (Role_if(PM_PRIEST))
3184 list->bknown = (list->oclass != COIN_CLASS);
3185 /* coins are either uncursed or unknown based upon option setting */
3186 if (list->oclass == COIN_CLASS) {
3193 /* ordinary items */
3196 else if (list->blessed)
3198 else if (list->cursed)
3200 else /* neither blessed nor cursed => uncursed */
3205 /* count everything inside a container, or just shop-owned items inside */
3207 count_contents(container, nested, quantity, everything, newdrop)
3208 struct obj *container;
3209 boolean nested, /* include contents of any nested containers */
3210 quantity, /* count all vs count separate stacks */
3211 everything, /* all objects vs only unpaid objects */
3212 newdrop; /* on floor, but hero-owned items haven't been marked
3213 * no_charge yet and shop-owned items are still marked
3214 * unpaid -- used when asking the player whether to sell */
3216 struct obj *otmp, *topc;
3217 boolean shoppy = FALSE;
3220 if (!everything && !newdrop) {
3223 for (topc = container; topc->where == OBJ_CONTAINED;
3224 topc = topc->ocontainer)
3226 if (topc->where == OBJ_FLOOR && get_obj_location(topc, &x, &y, 0))
3227 shoppy = costly_spot(x, y);
3229 for (otmp = container->cobj; otmp; otmp = otmp->nobj) {
3230 if (nested && Has_contents(otmp))
3231 count += count_contents(otmp, nested, quantity, everything,
3233 if (everything || otmp->unpaid || (shoppy && !otmp->no_charge))
3234 count += quantity ? otmp->quan : 1L;
3243 struct obj *otmp, *marker, *contnr;
3245 char *invlet = flags.inv_order;
3246 int classcount, count, num_so_far;
3249 count = count_unpaid(invent);
3250 otmp = marker = contnr = (struct obj *) 0;
3253 otmp = find_unpaid(invent, &marker);
3254 contnr = unknwn_contnr_contents(otmp);
3256 if (otmp && !contnr) {
3257 /* 1 item; use pline instead of popup menu */
3258 cost = unpaid_cost(otmp, FALSE);
3259 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
3260 pline1(xprname(otmp, distant_name(otmp, doname),
3261 carried(otmp) ? otmp->invlet : CONTAINED_SYM,
3263 iflags.suppress_price--;
3267 win = create_nhwindow(NHW_MENU);
3269 num_so_far = 0; /* count of # printed so far */
3270 if (!flags.invlet_constant)
3275 for (otmp = invent; otmp; otmp = otmp->nobj) {
3276 ilet = otmp->invlet;
3278 if (!flags.sortpack || otmp->oclass == *invlet) {
3279 if (flags.sortpack && !classcount) {
3280 putstr(win, 0, let_to_name(*invlet, TRUE, FALSE));
3284 totcost += cost = unpaid_cost(otmp, FALSE);
3285 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
3286 putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
3287 ilet, TRUE, cost, 0L));
3288 iflags.suppress_price--;
3293 } while (flags.sortpack && (*++invlet));
3295 if (count > num_so_far) {
3296 /* something unpaid is contained */
3298 putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE, FALSE));
3300 * Search through the container objects in the inventory for
3301 * unpaid items. The top level inventory items have already
3304 for (otmp = invent; otmp; otmp = otmp->nobj) {
3305 if (Has_contents(otmp)) {
3308 marker = (struct obj *) 0; /* haven't found any */
3309 while (find_unpaid(otmp->cobj, &marker)) {
3310 totcost += cost = unpaid_cost(marker, FALSE);
3313 iflags.suppress_price++; /* suppress "(unpaid)" sfx */
3315 xprname(marker, distant_name(marker, doname),
3316 CONTAINED_SYM, TRUE, cost, 0L));
3317 iflags.suppress_price--;
3320 if (!otmp->cknown) {
3321 char contbuf[BUFSZ];
3323 /* Shopkeeper knows what to charge for contents */
3325 Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
3327 Sprintf(contbuf, "%s
\82Ì
\92\86\90g", xname(otmp));
3329 xprname((struct obj *) 0, contbuf, CONTAINED_SYM,
3330 TRUE, contcost, 0L));
3339 xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
3342 xprname((struct obj *) 0, "
\8d\87\8cv
\81F", '*', FALSE, totcost, 0L));
3344 display_nhwindow(win, FALSE);
3345 destroy_nhwindow(win);
3348 /* query objlist callback: return TRUE if obj type matches "this_type" */
3349 static int this_type;
3355 boolean res = (obj->oclass == this_type);
3357 if (obj->oclass == COIN_CLASS) {
3358 /* if filtering by bless/curse state, gold is classified as
3359 either unknown or uncursed based on user option setting */
3360 if (this_type && index("BUCX", this_type))
3361 res = (this_type == (iflags.goldX ? 'X' : 'U'));
3363 switch (this_type) {
3365 res = (obj->bknown && obj->blessed);
3368 res = (obj->bknown && !(obj->blessed || obj->cursed));
3371 res = (obj->bknown && obj->cursed);
3377 break; /* use 'res' as-is */
3383 /* the 'I' command */
3389 char *extra_types, types[BUFSZ];
3390 int class_count, oclass, unpaid_count, itemcount;
3391 int bcnt, ccnt, ucnt, xcnt, ocnt;
3392 boolean billx = *u.ushops && doinvbill(0);
3393 menu_item *pick_list;
3394 boolean traditional = TRUE;
3396 const char *prompt = "What type of object do you want an inventory of?";
3398 const char *prompt = "
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\8e\9d\82¿
\95¨
\82ð
\8c©
\82Ü
\82·
\82©
\81H";
3400 if (!invent && !billx) {
3402 You("aren't carrying anything.");
3404 You("
\82»
\82Ì
\8eí
\97Þ
\82Ì
\95¨
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3407 unpaid_count = count_unpaid(invent);
3408 tally_BUCX(invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
3410 if (flags.menu_style != MENU_TRADITIONAL) {
3411 if (flags.menu_style == MENU_FULL
3412 || flags.menu_style == MENU_PARTIAL) {
3413 traditional = FALSE;
3425 n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
3428 this_type = c = pick_list[0].item.a_int;
3429 free((genericptr_t) pick_list);
3433 /* collect a list of classes of objects carried, for use as a prompt
3436 class_count = collect_obj_classes(types, invent, FALSE,
3437 (boolean FDECL((*), (OBJ_P))) 0,
3439 if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
3440 types[class_count++] = ' ';
3442 types[class_count++] = 'u';
3444 types[class_count++] = 'x';
3446 types[class_count++] = 'B';
3448 types[class_count++] = 'U';
3450 types[class_count++] = 'C';
3452 types[class_count++] = 'X';
3453 types[class_count] = '\0';
3454 /* add everything not already included; user won't see these */
3455 extra_types = eos(types);
3456 *extra_types++ = '\033';
3458 *extra_types++ = 'u';
3460 *extra_types++ = 'x';
3462 *extra_types++ = 'B';
3464 *extra_types++ = 'U';
3466 *extra_types++ = 'C';
3468 *extra_types++ = 'X';
3469 *extra_types = '\0'; /* for index() */
3470 for (i = 0; i < MAXOCLASSES; i++)
3471 if (!index(types, def_oc_syms[i].sym)) {
3472 *extra_types++ = def_oc_syms[i].sym;
3473 *extra_types = '\0';
3476 if (class_count > 1) {
3477 c = yn_function(prompt, types, '\0');
3480 clear_nhwindow(WIN_MESSAGE);
3484 /* only one thing to itemize */
3493 if (c == 'x' || (c == 'X' && billx && !xcnt)) {
3495 (void) doinvbill(1);
3498 pline("No used-up objects%s.",
3499 unpaid_count ? " on your shopping bill" : "");
3501 pline("
\8eg
\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\95¨
\82Í%s
\82È
\82¢
\81D",
3502 unpaid_count ? "
\8f¤
\93X
\82Ì
\90¿
\8b\81\8f\91\82É
\82Í" : "");
3506 if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
3511 You("are not carrying any unpaid objects.");
3513 You("
\96¢
\95¥
\82¢
\82Ì
\83A
\83C
\83e
\83\80\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3517 if (index("BUCX", c))
3518 oclass = c; /* not a class but understood by this_type_only() */
3520 oclass = def_char_to_objclass(c); /* change to object class */
3522 if (oclass == COIN_CLASS)
3524 if (index(types, c) > index(types, '\033')) {
3525 /* '> ESC' => hidden choice, something known not to be carried */
3526 const char *before = "", *after = "";
3531 before = "known to be blessed ";
3533 before = "
\8fj
\95\9f\82³
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3537 before = "known to be uncursed ";
3539 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3543 before = "known to be cursed ";
3545 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3549 after = " whose blessed/uncursed/cursed status is unknown";
3551 after = "
\8fj
\95\9f\81^
\8eô
\82¢
\82ª
\82í
\82©
\82ç
\82È
\82¢";
3552 break; /* better phrasing is desirable */
3554 /* 'c' is an object class, because we've already handled
3555 all the non-class letters which were put into 'types[]';
3556 could/should move object class names[] array from below
3557 to somewhere above so that we can access it here (via
3558 lcase(strcpy(classnamebuf, names[(int) c]))), but the
3559 game-play value of doing so is low... */
3563 before = "
\82»
\82Ì
\82æ
\82¤
\82È";
3567 You("have no %sobjects%s.", before, after);
3569 You("%s%s
\82à
\82Ì
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", before, after);
3574 if (query_objlist((char *) 0, &invent,
3575 ((flags.invlet_constant ? USE_INVLET : 0)
3577 &pick_list, PICK_NONE, this_type_only) > 0)
3578 free((genericptr_t) pick_list);
3582 /* return a string describing the dungeon feature at <x,y> if there
3583 is one worth mentioning at that location; otherwise null */
3585 dfeature_at(x, y, buf)
3589 struct rm *lev = &levl[x][y];
3590 int ltyp = lev->typ, cmap = -1;
3591 const char *dfeature = 0;
3592 static char altbuf[BUFSZ];
3594 if (IS_DOOR(ltyp)) {
3595 switch (lev->doormask) {
3598 break; /* "doorway" */
3601 break; /* "open door" */
3604 dfeature = "broken door";
3606 dfeature = "
\89ó
\82ê
\82½
\94à";
3610 break; /* "closed door" */
3612 /* override door description for open drawbridge */
3613 if (is_drawbridge_wall(x, y) >= 0)
3615 dfeature = "open drawbridge portcullis", cmap = -1;
3617 dfeature = "
\8d~
\82è
\82Ä
\82¢
\82é
\92µ
\82Ë
\8b´", cmap = -1;
3618 } else if (IS_FOUNTAIN(ltyp))
3619 cmap = S_fountain; /* "fountain" */
3620 else if (IS_THRONE(ltyp))
3621 cmap = S_throne; /* "opulent throne" */
3622 else if (is_lava(x, y))
3623 cmap = S_lava; /* "molten lava" */
3624 else if (is_ice(x, y))
3625 cmap = S_ice; /* "ice" */
3626 else if (is_pool(x, y))
3628 dfeature = "pool of water";
3630 dfeature = "
\90\85\82½
\82Ü
\82è";
3631 else if (IS_SINK(ltyp))
3632 cmap = S_sink; /* "sink" */
3633 else if (IS_ALTAR(ltyp)) {
3635 Sprintf(altbuf, "%saltar to %s (%s)",
3636 ((lev->altarmask & AM_SHRINE)
3637 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3641 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3643 Sprintf(altbuf, "%s%s
\82Ì
\8dÕ
\92d(%s)",
3644 ((lev->altarmask & AM_SHRINE)
3645 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3649 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3652 } else if ((x == xupstair && y == yupstair)
3653 || (x == sstairs.sx && y == sstairs.sy && sstairs.up))
3654 cmap = S_upstair; /* "staircase up" */
3655 else if ((x == xdnstair && y == ydnstair)
3656 || (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
3657 cmap = S_dnstair; /* "staircase down" */
3658 else if (x == xupladder && y == yupladder)
3659 cmap = S_upladder; /* "ladder up" */
3660 else if (x == xdnladder && y == ydnladder)
3661 cmap = S_dnladder; /* "ladder down" */
3662 else if (ltyp == DRAWBRIDGE_DOWN)
3663 cmap = S_vodbridge; /* "lowered drawbridge" */
3664 else if (ltyp == DBWALL)
3665 cmap = S_vcdbridge; /* "raised drawbridge" */
3666 else if (IS_GRAVE(ltyp))
3667 cmap = S_grave; /* "grave" */
3668 else if (ltyp == TREE)
3669 cmap = S_tree; /* "tree" */
3670 else if (ltyp == IRONBARS)
3672 dfeature = "set of iron bars";
3674 dfeature = "
\93S
\82Ì
\96_";
3677 dfeature = defsyms[cmap].explanation;
3679 Strcpy(buf, dfeature);
3683 /* look at what is here; if there are many objects (pile_limit or more),
3684 don't show them unless obj_cnt is 0 */
3686 look_here(obj_cnt, picked_some)
3687 int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progress */
3688 boolean picked_some;
3693 const char *verb = Blind ? "feel" : "see";
3695 const char *verb = Blind ? "
\82ª
\82 \82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½" : "
\82ð
\82Ý
\82Â
\82¯
\82½";
3697 const char *dfeature = (char *) 0;
3698 char fbuf[BUFSZ], fbuf2[BUFSZ];
3700 boolean skip_objects, felt_cockatrice = FALSE;
3702 /* default pile_limit is 5; a value of 0 means "never skip"
3703 (and 1 effectively forces "always skip") */
3704 skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
3705 if (u.uswallow && u.ustuck) {
3706 struct monst *mtmp = u.ustuck;
3710 * Engulfer's inventory can include worn items (specific case is
3711 * Juiblex being created with an amulet as random defensive item)
3712 * which will be flagged as "(being worn)". This code includes
3713 * such a worn item under the header "Contents of <mon>'s stomach",
3714 * a nifty trick for how/where to wear stuff. The situation is
3715 * rare enough to turn a blind eye.
3717 * 3.6.3: Pickup has been changed to decline to pick up a worn
3718 * item from inside an engulfer, but if player tries, it just
3719 * says "you can't" without giving a reason why (which would be
3720 * something along the lines of "because it's worn on the outside
3721 * so is unreachable from in here...").
3724 Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
3725 mbodypart(mtmp, STOMACH));
3727 Sprintf(fbuf, "%s
\82Ì%s
\82Ì
\92\86\90g", mon_nam(mtmp),
3728 mbodypart(mtmp, STOMACH));
3730 #if 0 /*JP*//*
\8cê
\8f\87\82ª
\88á
\82¤
\82Ì
\82Å
\91f
\92¼
\82É*/
3731 /* Skip "Contents of " by using fbuf index 12 */
3732 You("%s to %s what is lying in %s.", Blind ? "try" : "look around",
3735 You("%s
\82Ì%s
\82É
\89½
\82ª
\82 \82é
\82©%s
\81D",
3736 mon_nam(mtmp), mbodypart(mtmp, STOMACH),
3737 Blind ? "
\82³
\82®
\82Á
\82½" : "
\8c©
\89ñ
\82µ
\82½");
3739 otmp = mtmp->minvent;
3741 for (; otmp; otmp = otmp->nobj) {
3742 /* If swallower is an animal, it should have become stone
3744 if (otmp->otyp == CORPSE)
3745 feel_cockatrice(otmp, FALSE);
3749 Strcpy(fbuf, "You feel");
3752 Sprintf(fbuf, "
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F", Blind ? "
\82ç
\82µ
\82¢" : "");
3754 (void) display_minventory(mtmp, MINV_ALL | PICK_NONE, fbuf);
3757 You("%s no objects here.", verb);
3759 pline(Blind ? "
\82 \82È
\82½
\82Í
\89½
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D"
3760 : "
\82 \82È
\82½
\82Í
\89½
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3765 if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen)
3767 There("is %s here.",
3769 pline("
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D",
3770 an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
3772 otmp = level.objects[u.ux][u.uy];
3773 dfeature = dfeature_at(u.ux, u.uy, fbuf2);
3775 if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
3777 if (dfeature && !strcmp(dfeature, "
\90\85\82½
\82Ü
\82è") && Underwater)
3781 boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
3784 if (dfeature && !strncmp(dfeature, "altar ", 6)) {
3786 if (dfeature && !STRNCMP2(dfeature, "
\8dÕ
\92d")) {
3787 /* don't say "altar" twice, dfeature has more info */
3789 You("try to feel what is here.");
3791 You("
\82±
\82±
\82É
\89½
\82ª
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3794 const char *where = (Blind && !can_reach_floor(TRUE))
3795 ? "lying beneath you"
3796 : "lying here on the ",
3797 *onwhat = (Blind && !can_reach_floor(TRUE))
3799 : surface(u.ux, u.uy);
3801 You("try to feel what is %s%s.", drift ? "floating here" : where,
3802 drift ? "" : onwhat);
3805 You("
\89½
\82ª
\95\82\82¢
\82Ä
\82¢
\82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3806 } else if (Blind && !can_reach_floor(TRUE)) {
3807 You("
\89½
\82ª
\91«
\89º
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3809 You("
\89½
\82ª%s
\82Ì
\8fã
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D", surface(u.ux, u.uy));
3813 if (dfeature && !drift && !strcmp(dfeature, surface(u.ux, u.uy)))
3814 dfeature = 0; /* ice already identified */
3815 if (!can_reach_floor(TRUE)) {
3817 pline("But you can't reach it!");
3819 pline("
\82µ
\82©
\82µ
\93Í
\82©
\82È
\82¢
\81I");
3826 Sprintf(fbuf, "There is %s here.", an(dfeature));
3828 Sprintf(fbuf, "
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D", an(dfeature));
3830 if (!otmp || is_lava(u.ux, u.uy)
3831 || (is_pool(u.ux, u.uy) && !Underwater)) {
3834 read_engr_at(u.ux, u.uy); /* Eric Backus */
3835 if (!skip_objects && (Blind || !dfeature))
3837 You("%s no objects here.", verb);
3840 "
\82È
\82É
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82·
\82é
\81D" :
3841 "
\82È
\82É
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3845 /* we know there is something here */
3850 read_engr_at(u.ux, u.uy); /* Eric Backus */
3851 if (obj_cnt == 1 && otmp->quan == 1L)
3853 There("is %s object here.", picked_some ? "another" : "an");
3855 There("
\82±
\82±
\82É
\82Í%s
\88ê
\82Â
\82à
\82Ì
\82ª
\82 \82é
\81D", picked_some ? "
\82à
\82¤" : "");
3858 There("are %s%s objects here.",
3864 picked_some ? " more" : "");
3866 pline("
\82±
\82±
\82É
\82Í%s%s
\82à
\82Ì
\82ª
\82 \82é
\81D",
3867 picked_some ? "
\82³
\82ç
\82É" : "",
3869 ? "
\82¢
\82
\82Â
\82©
\82Ì"
3870 : "
\82½
\82
\82³
\82ñ
\82Ì");
3872 for (; otmp; otmp = otmp->nexthere)
3873 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3874 #if 0 /*JP*//*"It's (corpse_name), unfortunately"*/
3881 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3882 poly_when_stoned(youmonst.data)
3884 : ", unfortunately");
3887 poly_when_stoned(youmonst.data)
3889 : "
\8ec
\94O
\82È
\82ª
\82ç",
3890 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3892 ? "
\82ð
\8aÜ
\82ñ
\82Å
\82¢
\82é"
3895 feel_cockatrice(otmp, FALSE);
3898 } else if (!otmp->nexthere) {
3899 /* only one object */
3902 read_engr_at(u.ux, u.uy); /* Eric Backus */
3904 You("%s here %s.", verb, doname_with_price(otmp));
3906 pline("%s%s
\81D", doname_with_price(otmp), verb);
3907 iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
3908 if (otmp->otyp == CORPSE)
3909 feel_cockatrice(otmp, FALSE);
3913 display_nhwindow(WIN_MESSAGE, FALSE);
3914 tmpwin = create_nhwindow(NHW_MENU);
3916 putstr(tmpwin, 0, fbuf);
3917 putstr(tmpwin, 0, "");
3920 Sprintf(buf, "%s that %s here:",
3921 picked_some ? "Other things" : "Things",
3922 Blind ? "you feel" : "are");
3924 Sprintf(buf, "%s
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F",
3925 picked_some ? "
\91¼
\82É" : "",
3926 Blind ? "
\82ç
\82µ
\82¢" : "");
3928 putstr(tmpwin, 0, buf);
3929 for (; otmp; otmp = otmp->nexthere) {
3930 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3931 felt_cockatrice = TRUE;
3933 Sprintf(buf, "%s...", doname(otmp));
3935 Sprintf(buf, "%s
\81D
\81D
\81D", doname(otmp));
3936 putstr(tmpwin, 0, buf);
3939 putstr(tmpwin, 0, doname_with_price(otmp));
3941 display_nhwindow(tmpwin, TRUE);
3942 destroy_nhwindow(tmpwin);
3943 if (felt_cockatrice)
3944 feel_cockatrice(otmp, FALSE);
3945 read_engr_at(u.ux, u.uy); /* Eric Backus */
3950 /* the ':' command - explicitly look at what is here, including all objects */
3957 MSGTYPE={norep,noshow} "You see here"
3958 interfere with feedback from the look-here command */
3959 hide_unhide_msgtypes(TRUE, MSGTYP_MASK_REP_SHOW);
3960 res = look_here(0, FALSE);
3961 /* restore normal msgtype handling */
3962 hide_unhide_msgtypes(FALSE, MSGTYP_MASK_REP_SHOW);
3967 will_feel_cockatrice(otmp, force_touch)
3969 boolean force_touch;
3971 if ((Blind || force_touch) && !uarmg && !Stone_resistance
3972 && (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
3978 feel_cockatrice(otmp, force_touch)
3980 boolean force_touch;
3984 if (will_feel_cockatrice(otmp, force_touch)) {
3985 /* "the <cockatrice> corpse" */
3986 Strcpy(kbuf, corpse_xname(otmp, (const char *) 0, CXN_PFX_THE));
3988 if (poly_when_stoned(youmonst.data))
3990 You("touched %s with your bare %s.", kbuf,
3991 makeplural(body_part(HAND)));
3993 You("%s
\82Ì
\8e\80\91Ì
\82É
\91f%s
\82Å
\90G
\82Á
\82½
\81D", kbuf,
3998 pline("Touching %s is a fatal mistake...", kbuf);
4000 pline("%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82é
\82Ì
\82Í
\92v
\96½
\93I
\82È
\8aÔ
\88á
\82¢
\82¾
\81D
\81D
\81D", kbuf);
4001 /* normalize body shape here; hand, not body_part(HAND) */
4003 Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
4005 Sprintf(kbuf, "%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82Ä", killer_xname(otmp));
4006 /* will call polymon() for the poly_when_stoned() case */
4017 for (otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
4018 if (otmp != obj && merged(&obj, &otmp))
4023 /* returns TRUE if obj & otmp can be merged; used in invent.c and mkobj.c */
4026 register struct obj *otmp, *obj;
4028 int objnamelth = 0, otmpnamelth = 0;
4030 /* fail if already the same object, if different types, if either is
4031 explicitly marked to prevent merge, or if not mergable in general */
4032 if (obj == otmp || obj->otyp != otmp->otyp
4033 || obj->nomerge || otmp->nomerge || !objects[obj->otyp].oc_merge)
4036 /* coins of the same kind will always merge */
4037 if (obj->oclass == COIN_CLASS)
4040 if (obj->bypass != otmp->bypass
4041 || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed)
4046 /* Checks beyond this point either aren't applicable to globs
4047 * or don't inhibit their merger.
4050 if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
4051 || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
4052 || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit)
4055 if (obj->oclass == FOOD_CLASS
4056 && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
4059 if (obj->dknown != otmp->dknown
4060 || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
4061 || obj->oeroded != otmp->oeroded || obj->oeroded2 != otmp->oeroded2
4062 || obj->greased != otmp->greased)
4065 if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
4066 && (obj->oerodeproof != otmp->oerodeproof
4067 || obj->rknown != otmp->rknown))
4070 if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
4071 if (obj->corpsenm != otmp->corpsenm)
4075 /* hatching eggs don't merge; ditto for revivable corpses */
4076 if ((obj->otyp == EGG && (obj->timed || otmp->timed))
4077 || (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM
4078 && is_reviver(&mons[otmp->corpsenm])))
4081 /* allow candle merging only if their ages are close */
4082 /* see begin_burn() for a reference for the magic "25" */
4083 if (Is_candle(obj) && obj->age / 25 != otmp->age / 25)
4086 /* burning potions of oil never merge */
4087 if (obj->otyp == POT_OIL && obj->lamplit)
4090 /* don't merge surcharged item with base-cost item */
4091 if (obj->unpaid && !same_price(obj, otmp))
4094 /* if they have names, make sure they're the same */
4095 objnamelth = strlen(safe_oname(obj));
4096 otmpnamelth = strlen(safe_oname(otmp));
4097 if ((objnamelth != otmpnamelth
4098 && ((objnamelth && otmpnamelth) || obj->otyp == CORPSE))
4099 || (objnamelth && otmpnamelth
4100 && strncmp(ONAME(obj), ONAME(otmp), objnamelth)))
4103 /* for the moment, any additional information is incompatible */
4104 if (has_omonst(obj) || has_omid(obj) || has_olong(obj) || has_omonst(otmp)
4105 || has_omid(otmp) || has_olong(otmp))
4108 if (obj->oartifact != otmp->oartifact)
4111 if (obj->known == otmp->known || !objects[otmp->otyp].oc_uses_known) {
4112 return (boolean) objects[obj->otyp].oc_merge;
4117 /* the '$' command */
4121 /* the messages used to refer to "carrying gold", but that didn't
4122 take containers into account */
4123 long umoney = money_cnt(invent);
4127 Your("wallet is empty.");
4129 Your("
\8dà
\95z
\82Í
\8bó
\82Á
\82Û
\82¾
\81D");
4132 Your("wallet contains %ld %s.", umoney, currency(umoney));
4134 Your("
\8dà
\95z
\82É
\82Í%ld%s
\93ü
\82Á
\82Ä
\82¢
\82é
\81D", umoney, currency(umoney));
4135 shopper_financial_report();
4139 /* the ')' command */
4145 You("are empty %s.", body_part(HANDED));
4147 if(!uwep) You("%s
\82É
\95\90\8aí
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D", body_part(HAND));
4149 prinv((char *) 0, uwep, 0L);
4151 prinv((char *) 0, uswapwep, 0L);
4156 /* caller is responsible for checking !wearing_armor() */
4158 noarmor(report_uskin)
4159 boolean report_uskin;
4161 if (!uskin || !report_uskin) {
4163 You("are not wearing any armor.");
4165 You("
\8aZ
\82ð
\92\85\82Ä
\82¢
\82È
\82¢
\81D");
4167 char *p, *uskinname, buf[BUFSZ];
4169 uskinname = strcpy(buf, simpleonames(uskin));
4171 /* shorten "set of <color> dragon scales" to "<color> scales"
4172 and "<color> dragon scale mail" to "<color> scale mail" */
4173 if (!strncmpi(uskinname, "set of ", 7))
4175 if ((p = strstri(uskinname, " dragon ")) != 0)
4176 while ((p[1] = p[8]) != '\0')
4178 #else /*
\81u<
\90F>
\83h
\83\89\83S
\83\93\82Ì
\97Ø
\81v
\82ð
\81u<
\90F>
\82Ì
\97Ø
\81v
\82É
\82·
\82é*/
4179 if ((p = strstri(uskinname, "
\83h
\83\89\83S
\83\93\82Ì
\97Ø")) != 0)
4184 You("are not wearing armor but have %s embedded in your skin.",
4186 You("
\82Í
\8aZ
\82ð
\92\85\82Ä
\82¢
\82È
\82¢
\82ª
\81C%s
\82ª
\94§
\82É
\96\84\82ß
\8d\9e\82Ü
\82ê
\82Ä
\82¢
\82é
\81D",
4191 /* the '[' command */
4196 register int ct = 0;
4198 * Note: players sometimes get here by pressing a function key which
4199 * transmits ''ESC [ <something>'' rather than by pressing '[';
4200 * there's nothing we can--or should-do about that here.
4203 if (!wearing_armor()) {
4207 lets[ct++] = obj_to_let(uarmu);
4209 lets[ct++] = obj_to_let(uarm);
4211 lets[ct++] = obj_to_let(uarmc);
4213 lets[ct++] = obj_to_let(uarmh);
4215 lets[ct++] = obj_to_let(uarms);
4217 lets[ct++] = obj_to_let(uarmg);
4219 lets[ct++] = obj_to_let(uarmf);
4221 (void) display_inventory(lets, FALSE);
4226 /* the '=' command */
4230 if (!uleft && !uright)
4232 You("are not wearing any rings.");
4234 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
4237 register int ct = 0;
4240 lets[ct++] = obj_to_let(uleft);
4242 lets[ct++] = obj_to_let(uright);
4244 (void) display_inventory(lets, FALSE);
4249 /* the '"' command */
4255 You("are not wearing an amulet.");
4257 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
4259 prinv((char *) 0, uamul, 0L);
4267 if ((obj->owornmask & (W_TOOL | W_SADDLE)) != 0L)
4269 if (obj->oclass != TOOL_CLASS)
4271 return (boolean) (obj == uwep || obj->lamplit
4272 || (obj->otyp == LEASH && obj->leashmon));
4275 /* the '(' command */
4283 for (otmp = invent; otmp; otmp = otmp->nobj)
4284 if (tool_in_use(otmp))
4285 lets[ct++] = obj_to_let(otmp);
4289 You("are not using any tools.");
4291 You("
\8eg
\82¦
\82é
\93¹
\8bï
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4293 (void) display_inventory(lets, FALSE);
4297 /* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
4298 show inventory of all currently wielded, worn, or used objects */
4306 for (otmp = invent; otmp; otmp = otmp->nobj)
4307 if (is_worn(otmp) || tool_in_use(otmp))
4308 lets[ct++] = obj_to_let(otmp);
4312 You("are not wearing or wielding anything.");
4314 You("
\89½
\82à
\92\85\82Ä
\82¢
\82È
\82¢
\82µ
\81C
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
4316 (void) display_inventory(lets, FALSE);
4321 * uses up an object that's on the floor, charging for it as necessary
4324 useupf(obj, numused)
4325 register struct obj *obj;
4328 register struct obj *otmp;
4329 boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
4331 /* burn_floor_objects() keeps an object pointer that it tries to
4332 * useupf() multiple times, so obj must survive if plural */
4333 if (obj->quan > numused)
4334 otmp = splitobj(obj, numused);
4337 if (costly_spot(otmp->ox, otmp->oy)) {
4338 if (index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
4339 addtobill(otmp, FALSE, FALSE, FALSE);
4341 (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
4344 if (at_u && u.uundetected && hides_under(youmonst.data))
4345 (void) hideunder(&youmonst);
4349 * Conversion from a class to a string for printing.
4350 * This must match the object class order.
4352 STATIC_VAR NEARDATA const char *names[] = {
4354 0, "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", "Tools",
4355 "Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
4356 "Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
4358 0, "
\96
\82È
\95¨
\91Ì", "
\95\90\8aí", "
\8aZ", "
\8ew
\97Ö", "
\96\82\8f\9c\82¯", "
\93¹
\8bï",
4359 "
\90H
\97¿", "
\96ò", "
\8aª
\95¨", "
\96\82\96@
\8f\91", "
\8fñ", "
\8bà
\89Ý",
4360 "
\95ó
\90Î", "
\8aâ
\82Ü
\82½
\82Í
\92¤
\91\9c", "
\93S
\8b\85", "
\8d½", "
\93Å"
4363 STATIC_VAR NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
4365 STATIC_VAR NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
4367 STATIC_VAR NEARDATA const char *oth_names[] = { "
\8bl
\82ß
\82ç
\82ê
\82½
\93¹
\8bï" };
4369 STATIC_VAR NEARDATA char *invbuf = (char *) 0;
4370 STATIC_VAR NEARDATA unsigned invbufsiz = 0;
4373 let_to_name(let, unpaid, showsym)
4375 boolean unpaid, showsym;
4377 const char *ocsymfmt = " ('%c')";
4378 const int invbuf_sympadding = 8; /* arbitrary */
4379 const char *class_name;
4381 int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
4385 class_name = names[oclass];
4386 else if ((pos = index(oth_symbols, let)) != 0)
4387 class_name = oth_names[pos - oth_symbols];
4389 class_name = names[0];
4392 len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "")
4394 len = strlen(class_name) + (unpaid ? sizeof "
\96¢
\95¥
\82¢
\82Ì" : sizeof "")
4395 + (oclass ? (strlen(ocsymfmt) + invbuf_sympadding) : 0);
4396 if (len > invbufsiz) {
4398 free((genericptr_t) invbuf);
4399 invbufsiz = len + 10; /* add slop to reduce incremental realloc */
4400 invbuf = (char *) alloc(invbufsiz);
4404 Strcat(strcpy(invbuf, "Unpaid "), class_name);
4406 Strcat(strcpy(invbuf, "
\96¢
\95¥
\82¢
\82Ì"), class_name);
4408 Strcpy(invbuf, class_name);
4409 if ((oclass != 0) && showsym) {
4410 char *bp = eos(invbuf);
4411 int mlen = invbuf_sympadding - strlen(class_name);
4412 while (--mlen > 0) {
4417 Sprintf(eos(invbuf), ocsymfmt, def_oc_syms[oclass].sym);
4422 /* release the static buffer used by let_to_name() */
4427 free((genericptr_t) invbuf), invbuf = (char *) 0;
4431 /* give consecutive letters to every item in inventory (for !fixinv mode);
4432 gold is always forced to '$' slot at head of list */
4437 struct obj *obj, *prevobj, *goldobj;
4439 /* first, remove [first instance of] gold from invent, if present */
4440 prevobj = goldobj = 0;
4441 for (obj = invent; obj; prevobj = obj, obj = obj->nobj)
4442 if (obj->oclass == COIN_CLASS) {
4445 prevobj->nobj = goldobj->nobj;
4447 invent = goldobj->nobj;
4450 /* second, re-letter the rest of the list */
4451 for (obj = invent, i = 0; obj; obj = obj->nobj, i++)
4453 (i < 26) ? ('a' + i) : (i < 52) ? ('A' + i - 26) : NOINVSYM;
4454 /* third, assign gold the "letter" '$' and re-insert it at head */
4456 goldobj->invlet = GOLD_SYM;
4457 goldobj->nobj = invent;
4467 * User specifies a 'from' slot for inventory stack to move,
4468 * then a 'to' slot for its destination. Open slots and those
4469 * filled by compatible stacks are listed as likely candidates
4470 * but user can pick any inventory letter (including 'from').
4472 * to == from, 'from' has a name
4473 * All compatible items (same name or no name) are gathered
4474 * into the 'from' stack. No count is allowed.
4475 * to == from, 'from' does not have a name
4476 * All compatible items without a name are gathered into the
4477 * 'from' stack. No count is allowed. Compatible stacks with
4478 * names are left as-is.
4479 * to != from, no count
4480 * Move 'from' to 'to'. If 'to' is not empty, merge 'from'
4481 * into it if possible, otherwise swap it with the 'from' slot.
4482 * to != from, count given
4483 * If the user specifies a count when choosing the 'from' slot,
4484 * and that count is less than the full size of the stack,
4485 * then the stack will be split. The 'count' portion is moved
4486 * to the destination, and the only candidate for merging with
4487 * it is the stack already at the 'to' slot, if any. When the
4488 * destination is non-empty but won't merge, whatever is there
4489 * will be moved to an open slot; if there isn't any open slot
4490 * available, the adjustment attempt fails.
4492 * To minimize merging for 'from == to', unnamed stacks will
4493 * merge with named 'from' but named ones won't merge with
4494 * unnamed 'from'. Otherwise attempting to collect all unnamed
4495 * stacks would lump the first compatible named stack with them
4496 * and give them its name.
4498 * To maximize merging for 'from != to', compatible stacks will
4499 * merge when either lacks a name (or they already have the same
4500 * name). When no count is given and one stack has a name and
4501 * the other doesn't, the merged result will have that name.
4502 * However, when splitting results in a merger, the name of the
4503 * destination overrides that of the source, even if destination
4504 * is unnamed and source is named.
4507 doorganize() /* inventory organizer by Del Lamb */
4509 struct obj *obj, *otmp, *splitting, *bumped;
4510 int ix, cur, trycnt, goldstacks;
4513 #define GOLD_OFFSET 1
4514 #define OVRFLW_INDX (GOLD_OFFSET + 52) /* past gold and 2*26 letters */
4515 char lets[1 + 52 + 1 + 1]; /* room for '$a-zA-Z#\0' */
4517 char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
4518 char *objname, *otmpname;
4519 const char *adj_type;
4520 boolean ever_mind = FALSE, collect;
4522 /* when no invent, or just gold in '$' slot, there's nothing to adjust */
4523 if (!invent || (invent->oclass == COIN_CLASS
4524 && invent->invlet == GOLD_SYM && !invent->nobj)) {
4526 You("aren't carrying anything %s.",
4527 !invent ? "to adjust" : "adjustable");
4529 You("
\8f\87\8f\98\82ð
\95Ï
\82¦
\82é
\82à
\82Ì
\82ð
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4534 if (!flags.invlet_constant)
4536 /* get object the user wants to organize (the 'from' slot) */
4537 allowall[0] = ALLOW_COUNT;
4538 allowall[1] = ALL_CLASSES;
4540 for (goldstacks = 0, otmp = invent; otmp; otmp = otmp->nobj) {
4541 /* gold should never end up in a letter slot, nor should two '$'
4542 slots occur, but if they ever do, allow #adjust to handle them
4543 (in the past, things like this have happened, usually due to
4544 bknown being erroneously set on one stack, clear on another;
4545 object merger isn't fooled by that anymore) */
4546 if (otmp->oclass == COIN_CLASS
4547 && (otmp->invlet != GOLD_SYM || ++goldstacks > 1)) {
4548 allowall[1] = COIN_CLASS;
4549 allowall[2] = ALL_CLASSES;
4554 if (!(obj = getobj(allowall, "adjust")))
4557 /* figure out whether user gave a split count to getobj() */
4558 splitting = bumped = 0;
4559 for (otmp = invent; otmp; otmp = otmp->nobj)
4560 if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
4561 if (otmp->invlet == obj->invlet)
4566 /* initialize the list with all lower and upper case letters */
4567 lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' ';
4568 for (ix = GOLD_OFFSET, let = 'a'; let <= 'z';)
4570 for (let = 'A'; let <= 'Z';)
4572 lets[OVRFLW_INDX] = ' ';
4573 lets[sizeof lets - 1] = '\0';
4574 /* for floating inv letters, truncate list after the first open slot */
4575 if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
4576 lets[ix + (splitting ? 0 : 1)] = '\0';
4578 /* blank out all the letters currently in use in the inventory
4579 except those that will be merged with the selected object */
4580 for (otmp = invent; otmp; otmp = otmp->nobj)
4581 if (otmp != obj && !mergable(otmp, obj)) {
4583 if (let >= 'a' && let <= 'z')
4584 lets[GOLD_OFFSET + let - 'a'] = ' ';
4585 else if (let >= 'A' && let <= 'Z')
4586 lets[GOLD_OFFSET + let - 'A' + 26] = ' ';
4587 /* overflow defaults to off, but it we find a stack using that
4588 slot, switch to on -- the opposite of normal invlet handling */
4589 else if (let == NOINVSYM)
4590 lets[OVRFLW_INDX] = NOINVSYM;
4593 /* compact the list by removing all the blanks */
4594 for (ix = cur = 0; lets[ix]; ix++)
4595 if (lets[ix] != ' ' && cur++ < ix)
4596 lets[cur - 1] = lets[ix];
4598 /* and by dashing runs of letters */
4602 /* get 'to' slot to use as destination */
4604 Sprintf(qbuf, "Adjust letter to what [%s]%s?", lets,
4605 invent ? " (? see used letters)" : "");
4607 Sprintf(qbuf, "
\82Ç
\82Ì
\95¶
\8e\9a\82É
\92²
\90®
\82µ
\82Ü
\82·
\82©[%s]%s
\81H", lets,
4608 invent ? " (?
\82Å
\8eg
\82Á
\82Ä
\82¢
\82é
\95¶
\8e\9a\82ð
\95\
\8e¦)" : "");
4610 for (trycnt = 1; ; ++trycnt) {
4611 let = yn_function(qbuf, (char *) 0, '\0');
4612 if (let == '?' || let == '*') {
4613 let = display_used_invlets(splitting ? obj->invlet : 0);
4619 if (index(quitchars, let)
4620 /* adjusting to same slot is meaningful since all
4621 compatible stacks get collected along the way,
4622 but splitting to same slot is not */
4623 || (splitting && let == obj->invlet)) {
4626 (void) merged(&splitting, &obj);
4630 } else if (let == GOLD_SYM && obj->oclass != COIN_CLASS) {
4632 pline("Only gold coins may be moved into the '%c' slot.",
4635 pline("'%c'
\82É
\82Å
\82«
\82é
\82Ì
\82Í
\8bà
\89Ý
\82¾
\82¯
\81D",
4641 /* letter() classifies '@' as one; compactify() can put '-' in lets;
4642 the only thing of interest that index() might find is '$' or '#'
4643 since letter() catches everything else that we put into lets[] */
4644 if ((letter(let) && let != '@') || (index(lets, let) && let != '-'))
4645 break; /* got one */
4649 pline("Select an inventory slot letter."); /* else try again */
4651 pline("
\8e\9d\82¿
\95¨
\82Ì
\95¶
\8e\9a\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢
\81D");
4655 collect = (let == obj->invlet);
4656 /* change the inventory and print the resulting item */
4658 adj_type = collect ? "Collecting" : !splitting ? "Moving:" : "Splitting:";
4660 adj_type = collect ? "
\82ð
\8fW
\82ß
\82½
\81D" : !splitting ? "
\82ð
\88Ú
\93®
\82µ
\82½
\81D" : "
\82ð
\95ª
\8a\84\82µ
\82½
\81D";
4663 * don't use freeinv/addinv to avoid double-touching artifacts,
4664 * dousing lamps, losing luck, cursing loadstone, etc.
4666 extract_nobj(obj, &invent);
4668 for (otmp = invent; otmp;) {
4669 /* it's tempting to pull this outside the loop, but merged() could
4670 free ONAME(obj) [via obfree()] and replace it with ONAME(otmp) */
4671 objname = has_oname(obj) ? ONAME(obj) : (char *) 0;
4674 /* Collecting: #adjust an inventory stack into its same slot;
4675 keep it there and merge other compatible stacks into it.
4676 Traditional inventory behavior is to merge unnamed stacks
4677 with compatible named ones; we only want that if it is
4678 the 'from' stack (obj) with a name and candidate (otmp)
4679 without one, not unnamed 'from' with named candidate. */
4680 otmpname = has_oname(otmp) ? ONAME(otmp) : (char *) 0;
4681 if ((!otmpname || (objname && !strcmp(objname, otmpname)))
4682 && merged(&otmp, &obj)) {
4684 adj_type = "Merging:";
4686 adj_type = "
\82ð
\8d\87\82í
\82¹
\82½
\81D";
4689 extract_nobj(obj, &invent);
4690 continue; /* otmp has already been updated */
4692 } else if (otmp->invlet == let) {
4693 /* Moving or splitting: don't merge extra compatible stacks.
4694 Found 'otmp' in destination slot; merge if compatible,
4695 otherwise bump whatever is there to an open slot. */
4698 adj_type = "Swapping:";
4700 adj_type = "
\82ð
\8cð
\8a·
\82µ
\82½
\81D";
4701 otmp->invlet = obj->invlet;
4703 /* strip 'from' name if it has one */
4704 if (objname && !obj->oartifact)
4705 ONAME(obj) = (char *) 0;
4706 if (!mergable(otmp, obj)) {
4707 /* won't merge; put 'from' name back */
4709 ONAME(obj) = objname;
4711 /* will merge; discard 'from' name */
4713 free((genericptr_t) objname), objname = 0;
4716 if (merged(&otmp, &obj)) {
4718 adj_type = "Splitting and merging:";
4720 adj_type = "
\82ð
\95ª
\8a\84\82µ
\82Ä
\8d\87\82í
\82¹
\82½
\81D";
4722 extract_nobj(obj, &invent);
4723 } else if (inv_cnt(FALSE) >= 52) {
4724 (void) merged(&splitting, &obj); /* undo split */
4725 /* "knapsack cannot accommodate any more items" */
4727 Your("pack is too full.");
4729 Your("
\8e\9d\82¿
\95¨
\82Í
\88ê
\94t
\82¾
\81D");
4733 extract_nobj(bumped, &invent);
4735 } /* moving vs splitting */
4736 break; /* not collecting and found 'to' slot */
4741 /* inline addinv; insert loose object at beginning of inventory */
4744 obj->where = OBJ_INVENT;
4748 /* splitting the 'from' stack is causing an incompatible
4749 stack in the 'to' slot to be moved into an open one;
4750 we need to do another inline insertion to inventory */
4751 assigninvlet(bumped);
4752 bumped->nobj = invent;
4753 bumped->where = OBJ_INVENT;
4758 /* messages deferred until inventory has been fully reestablished */
4759 prinv(adj_type, obj, 0L);
4762 prinv("Moving:", bumped, 0L);
4764 prinv("
\88Ú
\93®:", bumped, 0L);
4766 clear_splitobjs(); /* reset splitobj context */
4771 /* common to display_minventory and display_cinventory */
4773 invdisp_nothing(hdr, txt)
4774 const char *hdr, *txt;
4778 menu_item *selected;
4781 win = create_nhwindow(NHW_MENU);
4783 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr,
4785 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
4786 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
4787 end_menu(win, (char *) 0);
4788 if (select_menu(win, PICK_NONE, &selected) > 0)
4789 free((genericptr_t) selected);
4790 destroy_nhwindow(win);
4794 /* query_objlist callback: return things that are worn or wielded */
4796 worn_wield_only(obj)
4800 /* check for things that *are* worn or wielded (only used for monsters,
4801 so we don't worry about excluding W_CHAIN, W_ARTI and the like) */
4802 return (boolean) (obj->owornmask != 0L);
4804 /* this used to check for things that *might* be worn or wielded,
4805 but that's not particularly interesting */
4806 if (is_weptool(obj) || is_wet_towel(obj) || obj->otyp == MEAT_RING)
4808 return (boolean) (obj->oclass == WEAPON_CLASS
4809 || obj->oclass == ARMOR_CLASS
4810 || obj->oclass == AMULET_CLASS
4811 || obj->oclass == RING_CLASS);
4816 * Display a monster's inventory.
4817 * Returns a pointer to the object from the monster's inventory selected
4818 * or NULL if nothing was selected.
4820 * By default, only worn and wielded items are displayed. The caller
4821 * can pick one. Modifier flags are:
4823 * PICK_NONE, PICK_ONE - standard menu control
4824 * PICK_ANY - allowed, but we only return a single object
4825 * MINV_NOLET - nothing selectable
4826 * MINV_ALL - display all inventory
4829 display_minventory(mon, dflags, title)
4830 register struct monst *mon;
4837 menu_item *selected = 0;
4838 int do_all = (dflags & MINV_ALL) != 0,
4839 incl_hero = (do_all && u.uswallow && mon == u.ustuck),
4840 have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
4841 pickings = (dflags & MINV_PICKMASK);
4844 Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
4845 do_all ? "possessions" : "armament");
4847 Sprintf(tmp, "%s
\82Ì%s
\81F", Monnam(mon),
4848 do_all ? "
\8e\9d\82¿
\95¨" : "
\91\95\94õ");
4851 if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
4852 /* Fool the 'weapon in hand' routine into
4853 * displaying 'weapon in claw', etc. properly.
4855 youmonst.data = mon->data;
4856 /* in case inside a shop, don't append "for sale" prices */
4857 iflags.suppress_price++;
4859 n = query_objlist(title ? title : tmp, &(mon->minvent),
4860 (INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0)),
4861 &selected, pickings,
4862 do_all ? allow_all : worn_wield_only);
4864 iflags.suppress_price--;
4865 /* was 'set_uasmon();' but that potentially has side-effects */
4866 youmonst.data = &mons[u.umonnum]; /* most basic part of set_uasmon */
4869 invdisp_nothing(title ? title : tmp, "(none)");
4871 invdisp_nothing(title ? title : tmp, "(
\89½
\82à
\82È
\82¢)");
4876 ret = selected[0].item.a_obj;
4877 free((genericptr_t) selected);
4879 ret = (struct obj *) 0;
4884 * Display the contents of a container in inventory style.
4885 * Currently, this is only used for statues, via wand of probing.
4888 display_cinventory(obj)
4889 register struct obj *obj;
4894 menu_item *selected = 0;
4897 (void) safe_qbuf(qbuf, "Contents of ", ":", obj, doname, ansimpleoname,
4900 (void) safe_qbuf(qbuf, "", "
\82Ì
\92\86\90g
\81F", obj, doname, ansimpleoname,
4905 n = query_objlist(qbuf, &(obj->cobj), INVORDER_SORT,
4906 &selected, PICK_NONE, allow_all);
4909 invdisp_nothing(qbuf, "(empty)");
4911 invdisp_nothing(qbuf, "(
\8bó
\82Á
\82Û)");
4915 ret = selected[0].item.a_obj;
4916 free((genericptr_t) selected);
4918 ret = (struct obj *) 0;
4923 /* query objlist callback: return TRUE if obj is at given location */
4930 return (obj->ox == only.x && obj->oy == only.y);
4934 * Display a list of buried items in inventory style. Return a non-zero
4935 * value if there were items at that spot.
4937 * Currently, this is only used with a wand of probing zapped downwards.
4940 display_binventory(x, y, as_if_seen)
4945 menu_item *selected = 0;
4948 /* count # of objects here */
4949 for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
4950 if (obj->ox == x && obj->oy == y) {
4960 if (query_objlist("Things that are buried here:",
4962 if (query_objlist("
\82±
\82±
\82É
\96\84\82ß
\82ç
\82ê
\82Ä
\82¢
\82é
\82à
\82Ì
\81F",
4963 &level.buriedobjlist, INVORDER_SORT,
4964 &selected, PICK_NONE, only_here) > 0)
4965 free((genericptr_t) selected);
4966 only.x = only.y = 0;