1 /* NetHack 3.6 invent.c $NHDT-Date: 1575245062 2019/12/02 00:04:22 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.267 $ */
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-2020 */
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É" : "", jconj(jword, "
\82ê
\82é"));
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)
1784 Sprintf(menuquery, "What do you want to %s?", word);
1785 if (!strcmp(word, "grease"))
1786 Sprintf(qbuf, "your %s", fingers_or_gloves(FALSE));
1787 else if (!strcmp(word, "write with"))
1788 Sprintf(qbuf, "your %s", body_part(FINGERTIP));
1789 else if (!strcmp(word, "wield"))
1790 Sprintf(qbuf, "your %s %s%s", uarmg ? "gloved" : "bare",
1791 makeplural(body_part(HAND)),
1792 !uwep ? " (wielded)" : "");
1793 else if (!strcmp(word, "ready"))
1794 Sprintf(qbuf, "empty quiver%s",
1795 !uquiver ? " (nothing readied)" : "");
1797 if (ilet == '?' && !*lets && *altlets)
1798 allowed_choices = altlets;
1799 ilet = display_pickinv(allowed_choices, *qbuf ? qbuf : (char *) 0,
1801 TRUE, allowcnt ? &ctmp : (long *) 0);
1804 if (ilet == HANDS_SYM)
1805 return (struct obj *) &zeroobj; /* cast away 'const' */
1806 if (ilet == '\033') {
1809 return (struct obj *) 0;
1813 if (allowcnt && ctmp >= 0) {
1817 /* they typed a letter (not a space) at the prompt */
1819 /* find the item which was picked */
1820 for (otmp = invent; otmp; otmp = otmp->nobj)
1821 if (otmp->invlet == ilet)
1823 /* some items have restrictions */
1824 if (ilet == def_oc_syms[COIN_CLASS].sym
1825 /* guard against the [hypothetical] chace of having more
1826 than one invent slot of gold and picking the non-'$' one */
1827 || (otmp && otmp->oclass == COIN_CLASS)) {
1830 You("cannot %s gold.", word);
1832 You("
\8bà
\89Ý%s%s
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D", joshi, jword);
1833 return (struct obj *) 0;
1835 /* Historic note: early Nethack had a bug which was
1836 * first reported for Larn, where trying to drop 2^32-n
1837 * gold pieces was allowed, and did interesting things
1838 * to your money supply. The LRS is the tax bureau
1841 if (cntgiven && cnt <= 0) {
1845 "LRS would be very interested to know you have that much.");
1847 "
\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");
1848 return (struct obj *) 0;
1851 if (cntgiven && !strcmp(word, "throw")) {
1852 /* permit counts for throwing gold, but don't accept
1853 * counts for other things since the throw code will
1854 * split off a single item anyway */
1856 return (struct obj *) 0;
1857 if (cnt > 1 && (ilet != def_oc_syms[COIN_CLASS].sym
1858 && !(otmp && otmp->oclass == COIN_CLASS))) {
1860 You("can only throw one item at a time.");
1862 You("
\93¯
\8e\9e\82É
\82½
\82
\82³
\82ñ
\82Ì
\82à
\82Ì
\82ð
\93\8a\82°
\82ç
\82ê
\82È
\82¢
\81D");
1866 context.botl = 1; /* May have changed the amount of money */
1868 /* [we used to set otmp (by finding ilet in invent) here, but
1869 that's been moved above so that otmp can be checked earlier] */
1870 /* verify the chosen object */
1873 You("don't have that object.");
1875 You("
\82»
\82ñ
\82È
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
1877 return (struct obj *) 0;
1879 } else if (cnt < 0 || otmp->quan < cnt) {
1881 You("don't have that many! You have only %ld.", otmp->quan);
1883 pline("
\82»
\82ñ
\82È
\82É
\82½
\82
\82³
\82ñ
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81I
\82¹
\82¢
\82º
\82¢%ld
\8cÂ
\82Á
\82Ä
\82Æ
\82±
\82¾
\81D", otmp->quan);
1885 return (struct obj *) 0;
1890 if (!allowall && let && !index(let, otmp->oclass)
1891 && !(usegold && otmp->oclass == COIN_CLASS)) {
1893 silly_thing(word, otmp);
1895 silly_thing(jword, otmp);
1897 return (struct obj *) 0;
1901 return (struct obj *) 0;
1902 if (cnt != otmp->quan) {
1903 /* don't split a stack of cursed loadstones */
1904 if (splittable(otmp))
1905 otmp = splitobj(otmp, cnt);
1906 else if (otmp->otyp == LOADSTONE && otmp->cursed)
1907 /* kludge for canletgo()'s can't-drop-this message */
1908 otmp->corpsenm = (int) cnt;
1915 silly_thing(word, otmp)
1919 #if 1 /* 'P','R' vs 'W','T' handling is obsolete */
1922 const char *s1, *s2, *s3;
1923 int ocls = otmp->oclass, otyp = otmp->otyp;
1926 /* check for attempted use of accessory commands ('P','R') on armor
1927 and for corresponding armor commands ('W','T') on accessories */
1928 if (ocls == ARMOR_CLASS) {
1930 if (!strcmp(word, "put on"))
1931 s1 = "W", s2 = "wear", s3 = "";
1932 else if (!strcmp(word, "remove"))
1933 s1 = "T", s2 = "take", s3 = " off";
1935 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1936 s1 = "W", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1937 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1938 s1 = "T", s2 = "
\82Í
\82¸
\82·", s3 = "";
1940 } else if ((ocls == RING_CLASS || otyp == MEAT_RING)
1941 || ocls == AMULET_CLASS
1942 || (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
1944 if (!strcmp(word, "wear"))
1945 s1 = "P", s2 = "put", s3 = " on";
1946 else if (!strcmp(word, "take off"))
1947 s1 = "R", s2 = "remove", s3 = "";
1949 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1950 s1 = "P", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1951 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1952 s1 = "R", s2 = "
\82Í
\82¸
\82·", s3 = "";
1957 pline("Use the '%s' command to %s %s%s.", s1, s2,
1958 !(is_plural(otmp) || pair_of(otmp)) ? "that" : "those", s3);
1960 pline("
\82»
\82ê
\82ð%s
\82É
\82Í'%s'
\83R
\83}
\83\93\83h
\82ð
\8eg
\82¤
\82±
\82Æ
\81D", s2, s1);
1964 pline(silly_thing_to, word);
1971 /* use allow_category() from pickup.c */
1972 return (int) allow_category(otmp);
1979 return (otmp->unpaid || (Has_contents(otmp) && count_unpaid(otmp->cobj)));
1985 return (boolean) (uarm || uarmc || uarmf || uarmg
1986 || uarmh || uarms || uarmu);
1993 return (otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_SADDLE | W_WEAPONS))
1998 /* extra xprname() input that askchain() can't pass through safe_qbuf() */
1999 STATIC_VAR struct xprnctx {
2004 /* safe_qbuf() -> short_oname() callback */
2009 return xprname(obj, (char *) 0, safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
2013 /* alternate safe_qbuf() -> short_oname() callback */
2015 safeq_shortxprname(obj)
2018 return xprname(obj, ansimpleoname(obj), safeq_xprn_ctx.let,
2019 safeq_xprn_ctx.dot, 0L, 0L);
2022 static NEARDATA const char removeables[] = { ARMOR_CLASS, WEAPON_CLASS,
2023 RING_CLASS, AMULET_CLASS,
2026 /* Interactive version of getobj - used for Drop, Identify, and Takeoff (A).
2027 Return the number of times fn was called successfully.
2028 If combo is TRUE, we just use this to get a category list. */
2029 /*JP CHECK: 3.6.0
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
2030 do.c:962: || (result = ggetobj("drop", drop, 0, FALSE, (unsigned *) 0)) < -1)
2031 do.c:1009: i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
2032 do_wear.c:2955: || (result = ggetobj("take off", select_off, 0, FALSE,
2033 do_wear.c:3007: if (ggetobj("take off", select_off, 0, TRUE, (unsigned *) 0) == -2)
2034 invent.c:2014: n = ggetobj("identify", identify, id_limit, FALSE,
2037 ggetobj(word, fn, mx, combo, resultflags)
2039 int FDECL((*fn), (OBJ_P)), mx;
2040 boolean combo; /* combination menu flag */
2041 unsigned *resultflags;
2043 int FDECL((*ckfn), (OBJ_P)) = (int FDECL((*), (OBJ_P))) 0;
2044 boolean FDECL((*ofilter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
2045 boolean takeoff, ident, allflag, m_seen;
2047 int oletct, iletct, unpaid, oc_of_sym;
2048 char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 10];
2049 char extra_removeables[3 + 1]; /* uwep,uswapwep,uquiver */
2050 char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
2052 const char *joshi = "
\82ð";
2055 const struct trans_verb *tv = trans_verb(word);
2057 joshi = tv->particle;
2062 You("have nothing to %s.", word);
2064 You("%s
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", jcan(jword));
2066 *resultflags = ALL_FINISHED;
2071 takeoff = ident = allflag = m_seen = FALSE;
2072 add_valid_menu_class(0); /* reset */
2073 if (taking_off(word)) {
2076 } else if (!strcmp(word, "identify")) {
2078 ofilter = not_fully_identified;
2081 iletct = collect_obj_classes(ilets, invent, FALSE, ofilter, &itemcount);
2082 unpaid = count_unpaid(invent);
2084 if (ident && !iletct) {
2085 return -1; /* no further identifications */
2086 } else if (invent) {
2087 ilets[iletct++] = ' ';
2089 ilets[iletct++] = 'u';
2090 if (count_buc(invent, BUC_BLESSED, ofilter))
2091 ilets[iletct++] = 'B';
2092 if (count_buc(invent, BUC_UNCURSED, ofilter))
2093 ilets[iletct++] = 'U';
2094 if (count_buc(invent, BUC_CURSED, ofilter))
2095 ilets[iletct++] = 'C';
2096 if (count_buc(invent, BUC_UNKNOWN, ofilter))
2097 ilets[iletct++] = 'X';
2098 ilets[iletct++] = 'a';
2100 ilets[iletct++] = 'i';
2102 ilets[iletct++] = 'm'; /* allow menu presentation on request */
2103 ilets[iletct] = '\0';
2107 Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]",
2110 Sprintf(qbuf,"
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\82à
\82Ì%s%s
\82©
\81H[%s]", joshi,
2111 jpolite(jword), ilets);
2114 if (buf[0] == '\033')
2116 if (index(buf, 'i')) {
2117 char ailets[1+26+26+1+5+1]; /* $ + a-z + A-Z + # + slop + \0 */
2120 /* applicable inventory letters; if empty, show entire invent */
2123 for (otmp = invent; otmp; otmp = otmp->nobj)
2124 /* index() check: limit overflow items to one '#' */
2125 if ((*ofilter)(otmp) && !index(ailets, otmp->invlet))
2126 (void) strkitten(ailets, otmp->invlet);
2127 if (display_inventory(ailets, TRUE) == '\033')
2133 extra_removeables[0] = '\0';
2135 /* arbitrary types of items can be placed in the weapon slots
2136 [any duplicate entries in extra_removeables[] won't matter] */
2138 (void) strkitten(extra_removeables, uwep->oclass);
2140 (void) strkitten(extra_removeables, uswapwep->oclass);
2142 (void) strkitten(extra_removeables, uquiver->oclass);
2146 olets[oletct = 0] = '\0';
2147 while ((sym = *ip++) != '\0') {
2150 oc_of_sym = def_char_to_objclass(sym);
2151 if (takeoff && oc_of_sym != MAXOCLASSES) {
2152 if (index(extra_removeables, oc_of_sym)) {
2153 ; /* skip rest of takeoff checks */
2154 } else if (!index(removeables, oc_of_sym)) {
2156 pline("Not applicable.");
2158 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2160 } else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
2163 } else if (oc_of_sym == WEAPON_CLASS && !uwep && !uswapwep
2166 You("are not wielding anything.");
2168 You("
\89½
\82à
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
2170 } else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
2172 You("are not wearing rings.");
2174 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
2176 } else if (oc_of_sym == AMULET_CLASS && !uamul) {
2178 You("are not wearing an amulet.");
2180 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
2182 } else if (oc_of_sym == TOOL_CLASS && !ublindf) {
2184 You("are not wearing a blindfold.");
2186 You("
\96Ú
\89B
\82µ
\82ð
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
2191 if (oc_of_sym == COIN_CLASS && !combo) {
2193 } else if (sym == 'a') {
2195 } else if (sym == 'A') {
2196 ; /* same as the default */
2197 } else if (sym == 'u') {
2198 add_valid_menu_class('u');
2200 } else if (index("BUCX", sym)) {
2201 add_valid_menu_class(sym); /* 'B','U','C',or 'X' */
2203 } else if (sym == 'm') {
2205 } else if (oc_of_sym == MAXOCLASSES) {
2207 You("don't have any %c's.", sym);
2209 You("%c
\82É
\91®
\82·
\82é
\95¨
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", sym);
2210 } else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */
2211 if (!index(olets, oc_of_sym)) {
2212 add_valid_menu_class(oc_of_sym);
2213 olets[oletct++] = oc_of_sym;
2221 || (!oletct && ckfn != ckunpaid && ckfn != ckvalidcat))
2223 } else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) {
2226 /* !!!! test gold dropping */
2227 } else if (allowgold == 2 && !oletct) {
2228 return 1; /* you dropped gold (or at least tried to) */
2231 int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
2233 * askchain() has already finished the job in this case
2234 * so set a special flag to convey that back to the caller
2235 * so that it won't continue processing.
2236 * Fix for bug C331-1 reported by Irina Rempt-Drijfhout.
2238 if (combo && allflag && resultflags)
2239 *resultflags |= ALL_FINISHED;
2245 * Walk through the chain starting at objchn and ask for all objects
2246 * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
2247 * whether the action in question (i.e., fn) has to be performed.
2248 * If allflag then no questions are asked. Mx gives the max number
2249 * of objects to be treated. Return the number of objects treated.
2251 /*JP CHECK: 3.6.2
\82Å
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
2252 invent.c:2228: int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
2253 pickup.c:3208: if (askchain(objlist, (one_by_one ? (char *) 0 : selection), allflag,
2254 word
\82É
\82Í
\93®
\8e\8c\82ª
\89p
\8cê
\82Å
\93ü
\82é
\81B
2257 askchain(objchn, olets, allflag, fn, ckfn, mx, word)
2258 struct obj **objchn; /* *objchn might change */
2260 const char *olets, *word; /* olets is an Obj Class char array */
2261 int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
2263 struct obj *otmp, *otmpo;
2264 register char sym, ilet;
2265 int cnt = 0, dud = 0, tmp;
2266 boolean takeoff, nodot, ident, take_out, put_in, first, ininv, bycat;
2267 char qbuf[QBUFSZ], qpfx[QBUFSZ];
2268 Loot *sortedchn = 0;
2270 takeoff = taking_off(word);
2271 ident = !strcmp(word, "identify");
2272 take_out = !strcmp(word, "take out");
2273 put_in = !strcmp(word, "put in");
2274 nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
2275 || takeoff || take_out || put_in);
2276 ininv = (*objchn == invent);
2277 bycat = (menu_class_present('u')
2278 || menu_class_present('B') || menu_class_present('U')
2279 || menu_class_present('C') || menu_class_present('X'));
2281 /* someday maybe we'll sort by 'olets' too (temporarily replace
2282 flags.packorder and pass SORTLOOT_PACK), but not yet... */
2283 sortedchn = sortloot(objchn, SORTLOOT_INVLET, FALSE,
2284 (boolean FDECL((*), (OBJ_P))) 0);
2288 * Interrogate in the object class order specified.
2289 * For example, if a person specifies =/ then first all rings
2290 * will be asked about followed by all wands. -dgk
2294 if (*objchn && (*objchn)->oclass == COIN_CLASS)
2295 ilet--; /* extra iteration */
2297 * Multiple Drop can change the invent chain while it operates
2298 * (dropping a burning potion of oil while levitating creates
2299 * an explosion which can destroy inventory items), so simple
2301 * for (otmp = *objchn; otmp; otmp = otmp2) {
2302 * otmp2 = otmp->nobj;
2305 * is inadequate here. Use each object's bypass bit to keep
2306 * track of which list elements have already been processed.
2308 bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */
2309 while ((otmp = nxt_unbypassed_loot(sortedchn, *objchn)) != 0) {
2312 else if (ilet == 'Z')
2313 ilet = NOINVSYM; /* '#' */
2316 if (olets && *olets && otmp->oclass != *olets)
2318 if (takeoff && !is_worn(otmp))
2320 if (ident && !not_fully_identified(otmp))
2322 if (ckfn && !(*ckfn)(otmp))
2324 if (bycat && !ckvalidcat(otmp))
2327 safeq_xprn_ctx.let = ilet;
2328 safeq_xprn_ctx.dot = !nodot;
2331 /* traditional_loot() skips prompting when only one
2332 class of objects is involved, so prefix the first
2333 object being queried here with an explanation why */
2334 if (take_out || put_in)
2335 Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
2339 (void) safe_qbuf(qbuf, qpfx, "?", otmp,
2340 ininv ? safeq_xprname : doname,
2341 ininv ? safeq_shortxprname : ansimpleoname,
2344 (void) safe_qbuf(qbuf, qpfx, "
\81H", otmp,
2345 ininv ? safeq_xprname : doname,
2346 ininv ? safeq_shortxprname : ansimpleoname,
2347 "
\83A
\83C
\83e
\83\80");
2349 sym = (takeoff || ident || otmp->quan < 2L) ? nyaq(qbuf)
2356 /* Number was entered; split the object unless it corresponds
2357 to 'none' or 'all'. 2 special cases: cursed loadstones and
2358 welded weapons (eg, multiple daggers) will remain as merged
2359 unit; done to avoid splitting an object that won't be
2360 droppable (even if we're picking up rather than dropping). */
2365 if (yn_number < otmp->quan && splittable(otmp))
2366 otmp = splitobj(otmp, yn_number);
2376 if (container_gone(fn)) {
2377 /* otmp caused magic bag to explode;
2378 both are now gone */
2379 otmp = 0; /* and return */
2380 } else if (otmp && otmp != otmpo) {
2381 /* split occurred, merge again */
2382 (void) merged(&otmpo, &otmp);
2396 /* special case for seffects() */
2402 if (olets && *olets && *++olets)
2405 if (!takeoff && (dud || cnt))
2407 pline("That was all.");
2409 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
2410 else if (!dud && !cnt)
2412 pline("No applicable objects.");
2414 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2416 unsortloot(&sortedchn);
2417 bypass_objlist(*objchn, FALSE);
2422 * Object identification routines:
2425 /* make an object actually be identified; no display updating */
2427 fully_identify_obj(otmp)
2430 makeknown(otmp->otyp);
2431 if (otmp->oartifact)
2432 discover_artifact((xchar) otmp->oartifact);
2433 otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
2434 if (Is_container(otmp) || otmp->otyp == STATUE)
2435 otmp->cknown = otmp->lknown = 1;
2436 if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
2437 learn_egg_type(otmp->corpsenm);
2440 /* ggetobj callback routine; identify an object and give immediate feedback */
2445 fully_identify_obj(otmp);
2446 prinv((char *) 0, otmp, 0L);
2450 /* menu of unidentified objects; select and identify up to id_limit of them */
2452 menu_identify(id_limit)
2455 menu_item *pick_list;
2456 int n, i, first = 1, tryct = 5;
2458 /* assumptions: id_limit > 0 and at least one unID'd item is present */
2462 Sprintf(buf, "What would you like to identify %s?",
2463 first ? "first" : "next");
2465 Sprintf(buf, "
\82Ç
\82ê
\82ð%s
\82É
\8e¯
\95Ê
\82µ
\82Ü
\82·
\82©
\81H",
2466 first ? "
\8dÅ
\8f\89" : "
\8e\9f");
2468 n = query_objlist(buf, &invent, (SIGNAL_NOMENU | SIGNAL_ESCAPE
2469 | USE_INVLET | INVORDER_SORT),
2470 &pick_list, PICK_ANY, not_fully_identified);
2475 for (i = 0; i < n; i++, id_limit--)
2476 (void) identify(pick_list[i].item.a_obj);
2477 free((genericptr_t) pick_list);
2478 mark_synch(); /* Before we loop to pop open another menu */
2480 } else if (n == -2) { /* player used ESC to quit menu */
2482 } else if (n == -1) { /* no eligible items found */
2484 pline("That was all.");
2486 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
2488 } else if (!--tryct) { /* stop re-prompting */
2489 pline1(thats_enough_tries);
2491 } else { /* try again */
2493 pline("Choose an item; use ESC to decline.");
2495 pline("
\83A
\83C
\83e
\83\80\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢;
\82â
\82ß
\82é
\82È
\82çESC
\81D");
2499 /* count the unidentified items */
2501 count_unidentified(objchn)
2507 for (obj = objchn; obj; obj = obj->nobj)
2508 if (not_fully_identified(obj))
2513 /* dialog with user to identify a given number of items; 0 means all */
2515 identify_pack(id_limit, learning_id)
2517 boolean learning_id; /* true if we just read unknown identify scroll */
2520 int n, unid_cnt = count_unidentified(invent);
2524 You("have already identified all %sof your possessions.",
2525 learning_id ? "the rest " : "");
2527 You("%s
\91S
\82Ä
\82Ì
\8f\8a\97L
\95¨
\82ð
\8e¯
\95Ê
\82µ
\82Ä
\82µ
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D",
2528 learning_id ? "
\8ec
\82è" : "");
2530 } else if (!id_limit || id_limit >= unid_cnt) {
2531 /* identify everything */
2532 /* TODO: use fully_identify_obj and cornline/menu/whatever here */
2533 for (obj = invent; obj; obj = obj->nobj) {
2534 if (not_fully_identified(obj)) {
2535 (void) identify(obj);
2541 /* identify up to `id_limit' items */
2543 if (flags.menu_style == MENU_TRADITIONAL)
2545 n = ggetobj("identify", identify, id_limit, FALSE,
2548 break; /* quit or no eligible items */
2549 } while ((id_limit -= n) > 0);
2550 if (n == 0 || n < -1)
2551 menu_identify(id_limit);
2556 /* called when regaining sight; mark inventory objects which were picked
2557 up while blind as now having been seen */
2559 learn_unseen_invent()
2564 return; /* sanity check */
2566 for (otmp = invent; otmp; otmp = otmp->nobj) {
2568 continue; /* already seen */
2569 /* set dknown, perhaps bknown (for priest[ess]) */
2572 * If object->eknown gets implemented (see learnwand(zap.c)),
2573 * handle deferred discovery here.
2579 /* persistent inventory window is maintained by interface code;
2580 'update_inventory' used to be a macro for
2581 (*windowprocs.win_update_inventory) but the restore hackery
2582 was getting out of hand; this is now a central call point */
2590 * Ought to check (windowprocs.wincap2 & WC2_PERM_INVENT) here....
2592 * We currently don't skip this call when iflags.perm_invent is False
2593 * because curses uses that to disable a previous perm_invent window
2594 * (after toggle via 'O'; perhaps the options code should handle that).
2596 (*windowprocs.win_update_inventory)();
2599 /* should of course only be called for things in invent */
2604 if (!flags.invlet_constant) {
2605 obj->invlet = NOINVSYM;
2612 * Print the indicated quantity of the given object. If quan == 0L then use
2613 * the current quantity.
2616 prinv(prefix, obj, quan)
2624 pline("%s%s%s", prefix, *prefix ? " " : "",
2625 xprname(obj, (char *) 0, obj_to_let(obj), TRUE, 0L, quan));
2628 xprname(obj, (char *)0, obj_to_let(obj), *prefix ? FALSE : TRUE, 0L, quan),
2634 xprname(obj, txt, let, dot, cost, quan)
2636 const char *txt; /* text to print instead of obj */
2637 char let; /* inventory letter */
2638 boolean dot; /* append period; (dot && cost => Iu) */
2639 long cost; /* cost (for inventory of unpaid or expended items) */
2640 long quan; /* if non-0, print this quantity, not obj->quan */
2642 #ifdef LINT /* handle static char li[BUFSZ]; */
2645 static char li[BUFSZ];
2647 boolean use_invlet = (flags.invlet_constant
2648 && let != CONTAINED_SYM && let != HANDS_SYM);
2652 savequan = obj->quan;
2657 * - Then obj == null and 'txt' refers to hands or fingers.
2658 * * Then obj == null and we are printing a total amount.
2659 * > Then the object is contained and doesn't have an inventory letter.
2661 if (cost != 0 || let == '*') {
2662 /* if dot is true, we're doing Iu, otherwise Ix */
2665 iflags.menu_tab_sep ? "%c - %s\t%6ld %s"
2666 : "%c - %-45s %6ld %s",
2667 (dot && use_invlet ? obj->invlet : let),
2668 (txt ? txt : doname(obj)), cost, currency(cost));
2671 iflags.menu_tab_sep ? "%c - %s\t%6ld%s"
2672 : "%c - %-45s %6ld%s",
2673 (dot && use_invlet ? obj->invlet : let),
2674 (txt ? txt : doname(obj)), cost, currency(cost));
2677 /* ordinary inventory display or pickup message */
2678 Sprintf(li, "%c - %s%s", (use_invlet ? obj->invlet : let),
2680 (txt ? txt : doname(obj)), (dot ? "." : ""));
2682 (txt ? txt : doname(obj)), (dot ? "
\81D" : ""));
2685 obj->quan = savequan;
2690 /* the 'i' command */
2694 (void) display_inventory((char *) 0, FALSE);
2701 * Scan the given list of objects. If last_found is NULL, return the first
2702 * unpaid object found. If last_found is not NULL, then skip over unpaid
2703 * objects until last_found is reached, then set last_found to NULL so the
2704 * next unpaid object is returned. This routine recursively follows
2707 STATIC_OVL struct obj *
2708 find_unpaid(list, last_found)
2709 struct obj *list, **last_found;
2716 /* still looking for previous unpaid object */
2717 if (list == *last_found)
2718 *last_found = (struct obj *) 0;
2720 return ((*last_found = list));
2722 if (Has_contents(list)) {
2723 if ((obj = find_unpaid(list->cobj, last_found)) != 0)
2728 return (struct obj *) 0;
2731 /* for perm_invent when operating on a partial inventory display, so that
2732 the persistent one doesn't get shrunk during filtering for item selection
2733 then regrown to full inventory, possibly being resized in the process */
2734 static winid cached_pickinv_win = WIN_ERR;
2737 free_pickinv_cache()
2739 if (cached_pickinv_win != WIN_ERR) {
2740 destroy_nhwindow(cached_pickinv_win);
2741 cached_pickinv_win = WIN_ERR;
2746 * Internal function used by display_inventory and getobj that can display
2747 * inventory and return a count as well as a letter. If out_cnt is not null,
2748 * any count returned from the menu selection is placed here.
2751 display_pickinv(lets, xtra_choice, query, want_reply, out_cnt)
2752 register const char *lets;
2753 const char *xtra_choice; /* "fingers", pick hands rather than an object */
2759 static const char not_carrying_anything[] = "Not carrying anything";
2761 static const char not_carrying_anything[] = "
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢";
2762 struct obj *otmp, wizid_fakeobj;
2764 char *invlet = flags.inv_order;
2766 winid win; /* windows being used */
2768 menu_item *selected;
2770 Loot *sortedinvent, *srtinv;
2771 boolean wizid = (wizard && iflags.override_ID), gotsomething = FALSE;
2774 lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
2776 if (iflags.perm_invent && (lets || xtra_choice || wizid)) {
2777 /* partial inventory in perm_invent setting; don't operate on
2778 full inventory window, use an alternate one instead; create
2779 the first time needed and keep it for re-use as needed later */
2780 if (cached_pickinv_win == WIN_ERR)
2781 cached_pickinv_win = create_nhwindow(NHW_MENU);
2782 win = cached_pickinv_win;
2787 * Exit early if no inventory -- but keep going if we are doing
2788 * a permanent inventory update. We need to keep going so the
2789 * permanent inventory window updates itself to remove the last
2790 * item(s) dropped. One down side: the addition of the exception
2791 * for permanent inventory window updates _can_ pop the window
2792 * up when it's not displayed -- even if it's empty -- because we
2793 * don't know at this level if its up or not. This may not be
2794 * an issue if empty checks are done before hand and the call
2795 * to here is short circuited away.
2797 * 2: our count here is only to distinguish between 0 and 1 and
2798 * more than 1; for the last one, we don't need a precise number.
2799 * For perm_invent update we force 'more than 1'.
2801 n = (iflags.perm_invent && !lets && !want_reply) ? 2
2802 : lets ? (int) strlen(lets)
2803 : !invent ? 0 : !invent->nobj ? 1 : 2;
2804 /* for xtra_choice, there's another 'item' not included in initial 'n';
2805 for !lets (full invent) and for override_ID (wizard mode identify),
2806 skip message_menu handling of single item even if item count was 1 */
2807 if (xtra_choice || (n == 1 && (!lets || iflags.override_ID)))
2812 pline("%s.", not_carrying_anything);
2814 pline("%s
\81D", not_carrying_anything);
2818 /* oxymoron? temporarily assign permanent inventory letters */
2819 if (!flags.invlet_constant)
2822 if (n == 1 && !iflags.force_invmenu) {
2823 /* when only one item of interest, use pline instead of menus;
2824 we actually use a fake message-line menu in order to allow
2825 the user to perform selection at the --More-- prompt for tty */
2828 /* xtra_choice is "bare hands" (wield), "fingertip" (Engrave),
2829 "nothing" (ready Quiver), or "fingers" (apply grease) */
2830 ret = message_menu(HANDS_SYM, PICK_ONE,
2831 xprname((struct obj *) 0, xtra_choice,
2832 HANDS_SYM, TRUE, 0L, 0L)); /* '-' */
2834 for (otmp = invent; otmp; otmp = otmp->nobj)
2835 if (!lets || otmp->invlet == lets[0])
2838 ret = message_menu(otmp->invlet,
2839 want_reply ? PICK_ONE : PICK_NONE,
2840 xprname(otmp, (char *) 0, lets[0],
2844 *out_cnt = -1L; /* select all */
2848 sortflags = (flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET;
2850 sortflags |= SORTLOOT_PACK;
2851 sortedinvent = sortloot(&invent, sortflags, FALSE,
2852 (boolean FDECL((*), (OBJ_P))) 0);
2856 if (wizard && iflags.override_ID) {
2858 char prompt[QBUFSZ];
2860 unid_cnt = count_unidentified(invent);
2861 Sprintf(prompt, "Debug Identify"); /* 'title' rather than 'prompt' */
2863 Sprintf(eos(prompt),
2864 " -- unidentified or partially identified item%s",
2866 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, prompt, MENU_UNSELECTED);
2868 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
2869 "(all items are permanently identified already)",
2871 gotsomething = TRUE;
2873 any.a_obj = &wizid_fakeobj;
2874 Sprintf(prompt, "select %s to permanently identify",
2875 (unid_cnt == 1) ? "it": "any or all of them");
2876 /* wiz_identify stuffed the wiz_identify command character (^I)
2877 into iflags.override_ID for our use as an accelerator;
2878 it could be ambiguous if player has assigned a letter to
2879 the #wizidentify command, so include it as a group accelator
2880 but use '_' as the primary selector */
2882 Sprintf(eos(prompt), " (%s for all)",
2883 visctrl(iflags.override_ID));
2884 add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
2885 prompt, MENU_UNSELECTED);
2886 gotsomething = TRUE;
2888 } else if (xtra_choice) {
2889 /* wizard override ID and xtra_choice are mutually exclusive */
2891 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2892 "Miscellaneous", MENU_UNSELECTED);
2893 any.a_char = HANDS_SYM; /* '-' */
2894 add_menu(win, NO_GLYPH, &any, HANDS_SYM, 0, ATR_NONE,
2895 xtra_choice, MENU_UNSELECTED);
2896 gotsomething = TRUE;
2900 for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
2901 if (lets && !index(lets, otmp->invlet))
2903 if (!flags.sortpack || otmp->oclass == *invlet) {
2904 if (wizid && !not_fully_identified(otmp))
2906 any = zeroany; /* all bits zero */
2907 ilet = otmp->invlet;
2908 if (flags.sortpack && !classcount) {
2909 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2910 let_to_name(*invlet, FALSE,
2911 (want_reply && iflags.menu_head_objsym)),
2919 add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng), &any, ilet,
2920 wizid ? def_oc_syms[(int) otmp->oclass].sym : 0,
2921 ATR_NONE, doname(otmp), MENU_UNSELECTED);
2922 gotsomething = TRUE;
2925 if (flags.sortpack) {
2928 if (--invlet != venom_inv) {
2933 if (iflags.force_invmenu && lets && want_reply) {
2936 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2937 "Special", MENU_UNSELECTED);
2939 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2940 "
\93Á
\8eê", MENU_UNSELECTED);
2944 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
2945 "(list everything)", MENU_UNSELECTED);
2947 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
2948 "(
\91S
\82Ä
\82Ì
\88ê
\97\97)", MENU_UNSELECTED);
2950 gotsomething = TRUE;
2952 unsortloot(&sortedinvent);
2953 /* for permanent inventory where we intend to show everything but
2954 nothing has been listed (because there isn't anyhing to list;
2955 the n==0 case above gets skipped for perm_invent), put something
2957 if (iflags.perm_invent && !lets && !gotsomething) {
2959 add_menu(win, NO_GLYPH, &any, 0, 0, 0,
2960 not_carrying_anything, MENU_UNSELECTED);
2963 end_menu(win, query && *query ? query : (char *) 0);
2965 n = select_menu(win,
2966 wizid ? PICK_ANY : want_reply ? PICK_ONE : PICK_NONE,
2972 /* identifying items will update perm_invent, calling this
2973 routine recursively, and we don't want the nested call
2974 to filter on unID'd items */
2975 iflags.override_ID = 0;
2977 for (i = 0; i < n; ++i) {
2978 otmp = selected[i].item.a_obj;
2979 if (otmp == &wizid_fakeobj) {
2980 identify_pack(0, FALSE);
2982 if (not_fully_identified(otmp))
2983 (void) identify(otmp);
2987 ret = selected[0].item.a_char;
2989 *out_cnt = selected[0].count;
2991 free((genericptr_t) selected);
2993 ret = !n ? '\0' : '\033'; /* cancelled */
2999 * If lets == NULL or "", list all objects in the inventory. Otherwise,
3000 * list all objects with object classes that match the order in lets.
3002 * Returns the letter identifier of a selected item, or 0 if nothing
3006 display_inventory(lets, want_reply)
3010 return display_pickinv(lets, (char *) 0, (char *) 0,
3011 want_reply, (long *) 0);
3015 * Show what is current using inventory letters.
3019 display_used_invlets(avoidlet)
3024 char *invlet = flags.inv_order;
3025 int n, classcount, invdone = 0;
3028 menu_item *selected;
3031 win = create_nhwindow(NHW_MENU);
3034 any = zeroany; /* set all bits to zero */
3036 for (otmp = invent; otmp; otmp = otmp->nobj) {
3037 ilet = otmp->invlet;
3038 if (ilet == avoidlet)
3040 if (!flags.sortpack || otmp->oclass == *invlet) {
3041 if (flags.sortpack && !classcount) {
3042 any = zeroany; /* zero */
3043 add_menu(win, NO_GLYPH, &any, 0, 0,
3044 iflags.menu_headings,
3045 let_to_name(*invlet, FALSE, FALSE),
3050 add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng),
3051 &any, ilet, 0, ATR_NONE,
3052 doname(otmp), MENU_UNSELECTED);
3055 if (flags.sortpack && *++invlet)
3059 end_menu(win, "Inventory letters used:");
3061 n = select_menu(win, PICK_ONE, &selected);
3063 ret = selected[0].item.a_char;
3064 free((genericptr_t) selected);
3066 ret = !n ? '\0' : '\033'; /* cancelled */
3067 destroy_nhwindow(win);
3073 * Returns the number of unpaid items within the given list. This includes
3074 * contained objects.
3085 if (Has_contents(list))
3086 count += count_unpaid(list->cobj);
3093 * Returns the number of items with b/u/c/unknown within the given list.
3094 * This does NOT include contained objects.
3096 * Assumes that the hero sees or touches or otherwise senses the objects
3097 * at some point: bknown is forced for priest[ess], like in xname().
3100 count_buc(list, type, filterfunc)
3103 boolean FDECL((*filterfunc), (OBJ_P));
3107 for (; list; list = list->nobj) {
3108 /* priests always know bless/curse state */
3109 if (Role_if(PM_PRIEST))
3110 list->bknown = (list->oclass != COIN_CLASS);
3111 /* some actions exclude some or most items */
3112 if (filterfunc && !(*filterfunc)(list))
3115 /* coins are either uncursed or unknown based upon option setting */
3116 if (list->oclass == COIN_CLASS) {
3117 if (type == (iflags.goldX ? BUC_UNKNOWN : BUC_UNCURSED))
3121 /* check whether this object matches the requested type */
3123 ? (type == BUC_UNKNOWN)
3124 : list->blessed ? (type == BUC_BLESSED)
3125 : list->cursed ? (type == BUC_CURSED)
3126 : (type == BUC_UNCURSED))
3132 /* similar to count_buc(), but tallies all states at once
3133 rather than looking for a specific type */
3135 tally_BUCX(list, by_nexthere, bcp, ucp, ccp, xcp, ocp)
3137 boolean by_nexthere;
3138 int *bcp, *ucp, *ccp, *xcp, *ocp;
3140 /* Future extensions:
3141 * Skip current_container when list is invent, uchain when
3142 * first object of list is located on the floor. 'ocp' will then
3143 * have a function again (it was a counter for having skipped gold,
3144 * but that's not skipped anymore).
3146 *bcp = *ucp = *ccp = *xcp = *ocp = 0;
3147 for ( ; list; list = (by_nexthere ? list->nexthere : list->nobj)) {
3148 /* priests always know bless/curse state */
3149 if (Role_if(PM_PRIEST))
3150 list->bknown = (list->oclass != COIN_CLASS);
3151 /* coins are either uncursed or unknown based upon option setting */
3152 if (list->oclass == COIN_CLASS) {
3159 /* ordinary items */
3162 else if (list->blessed)
3164 else if (list->cursed)
3166 else /* neither blessed nor cursed => uncursed */
3171 /* count everything inside a container, or just shop-owned items inside */
3173 count_contents(container, nested, quantity, everything, newdrop)
3174 struct obj *container;
3175 boolean nested, /* include contents of any nested containers */
3176 quantity, /* count all vs count separate stacks */
3177 everything, /* all objects vs only unpaid objects */
3178 newdrop; /* on floor, but hero-owned items haven't been marked
3179 * no_charge yet and shop-owned items are still marked
3180 * unpaid -- used when asking the player whether to sell */
3182 struct obj *otmp, *topc;
3183 boolean shoppy = FALSE;
3186 if (!everything && !newdrop) {
3189 for (topc = container; topc->where == OBJ_CONTAINED;
3190 topc = topc->ocontainer)
3192 if (topc->where == OBJ_FLOOR && get_obj_location(topc, &x, &y, 0))
3193 shoppy = costly_spot(x, y);
3195 for (otmp = container->cobj; otmp; otmp = otmp->nobj) {
3196 if (nested && Has_contents(otmp))
3197 count += count_contents(otmp, nested, quantity, everything,
3199 if (everything || otmp->unpaid || (shoppy && !otmp->no_charge))
3200 count += quantity ? otmp->quan : 1L;
3209 struct obj *otmp, *marker, *contnr;
3211 char *invlet = flags.inv_order;
3212 int classcount, count, num_so_far;
3215 count = count_unpaid(invent);
3216 otmp = marker = contnr = (struct obj *) 0;
3219 otmp = find_unpaid(invent, &marker);
3220 contnr = unknwn_contnr_contents(otmp);
3222 if (otmp && !contnr) {
3223 /* 1 item; use pline instead of popup menu */
3224 cost = unpaid_cost(otmp, FALSE);
3225 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
3226 pline1(xprname(otmp, distant_name(otmp, doname),
3227 carried(otmp) ? otmp->invlet : CONTAINED_SYM,
3229 iflags.suppress_price--;
3233 win = create_nhwindow(NHW_MENU);
3235 num_so_far = 0; /* count of # printed so far */
3236 if (!flags.invlet_constant)
3241 for (otmp = invent; otmp; otmp = otmp->nobj) {
3242 ilet = otmp->invlet;
3244 if (!flags.sortpack || otmp->oclass == *invlet) {
3245 if (flags.sortpack && !classcount) {
3246 putstr(win, 0, let_to_name(*invlet, TRUE, FALSE));
3250 totcost += cost = unpaid_cost(otmp, FALSE);
3251 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
3252 putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
3253 ilet, TRUE, cost, 0L));
3254 iflags.suppress_price--;
3259 } while (flags.sortpack && (*++invlet));
3261 if (count > num_so_far) {
3262 /* something unpaid is contained */
3264 putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE, FALSE));
3266 * Search through the container objects in the inventory for
3267 * unpaid items. The top level inventory items have already
3270 for (otmp = invent; otmp; otmp = otmp->nobj) {
3271 if (Has_contents(otmp)) {
3274 marker = (struct obj *) 0; /* haven't found any */
3275 while (find_unpaid(otmp->cobj, &marker)) {
3276 totcost += cost = unpaid_cost(marker, FALSE);
3279 iflags.suppress_price++; /* suppress "(unpaid)" sfx */
3281 xprname(marker, distant_name(marker, doname),
3282 CONTAINED_SYM, TRUE, cost, 0L));
3283 iflags.suppress_price--;
3286 if (!otmp->cknown) {
3287 char contbuf[BUFSZ];
3289 /* Shopkeeper knows what to charge for contents */
3291 Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
3293 Sprintf(contbuf, "%s
\82Ì
\92\86\90g", xname(otmp));
3295 xprname((struct obj *) 0, contbuf, CONTAINED_SYM,
3296 TRUE, contcost, 0L));
3305 xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
3308 xprname((struct obj *) 0, "
\8d\87\8cv
\81F", '*', FALSE, totcost, 0L));
3310 display_nhwindow(win, FALSE);
3311 destroy_nhwindow(win);
3314 /* query objlist callback: return TRUE if obj type matches "this_type" */
3315 static int this_type;
3321 boolean res = (obj->oclass == this_type);
3323 if (obj->oclass == COIN_CLASS) {
3324 /* if filtering by bless/curse state, gold is classified as
3325 either unknown or uncursed based on user option setting */
3326 if (this_type && index("BUCX", this_type))
3327 res = (this_type == (iflags.goldX ? 'X' : 'U'));
3329 switch (this_type) {
3331 res = (obj->bknown && obj->blessed);
3334 res = (obj->bknown && !(obj->blessed || obj->cursed));
3337 res = (obj->bknown && obj->cursed);
3343 break; /* use 'res' as-is */
3349 /* the 'I' command */
3355 char *extra_types, types[BUFSZ];
3356 int class_count, oclass, unpaid_count, itemcount;
3357 int bcnt, ccnt, ucnt, xcnt, ocnt;
3358 boolean billx = *u.ushops && doinvbill(0);
3359 menu_item *pick_list;
3360 boolean traditional = TRUE;
3362 const char *prompt = "What type of object do you want an inventory of?";
3364 const char *prompt = "
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\8e\9d\82¿
\95¨
\82ð
\8c©
\82Ü
\82·
\82©
\81H";
3366 if (!invent && !billx) {
3368 You("aren't carrying anything.");
3370 You("
\82»
\82Ì
\8eí
\97Þ
\82Ì
\95¨
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3373 unpaid_count = count_unpaid(invent);
3374 tally_BUCX(invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
3376 if (flags.menu_style != MENU_TRADITIONAL) {
3377 if (flags.menu_style == MENU_FULL
3378 || flags.menu_style == MENU_PARTIAL) {
3379 traditional = FALSE;
3391 n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
3394 this_type = c = pick_list[0].item.a_int;
3395 free((genericptr_t) pick_list);
3399 /* collect a list of classes of objects carried, for use as a prompt
3402 class_count = collect_obj_classes(types, invent, FALSE,
3403 (boolean FDECL((*), (OBJ_P))) 0,
3405 if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
3406 types[class_count++] = ' ';
3408 types[class_count++] = 'u';
3410 types[class_count++] = 'x';
3412 types[class_count++] = 'B';
3414 types[class_count++] = 'U';
3416 types[class_count++] = 'C';
3418 types[class_count++] = 'X';
3419 types[class_count] = '\0';
3420 /* add everything not already included; user won't see these */
3421 extra_types = eos(types);
3422 *extra_types++ = '\033';
3424 *extra_types++ = 'u';
3426 *extra_types++ = 'x';
3428 *extra_types++ = 'B';
3430 *extra_types++ = 'U';
3432 *extra_types++ = 'C';
3434 *extra_types++ = 'X';
3435 *extra_types = '\0'; /* for index() */
3436 for (i = 0; i < MAXOCLASSES; i++)
3437 if (!index(types, def_oc_syms[i].sym)) {
3438 *extra_types++ = def_oc_syms[i].sym;
3439 *extra_types = '\0';
3442 if (class_count > 1) {
3443 c = yn_function(prompt, types, '\0');
3446 clear_nhwindow(WIN_MESSAGE);
3450 /* only one thing to itemize */
3459 if (c == 'x' || (c == 'X' && billx && !xcnt)) {
3461 (void) doinvbill(1);
3464 pline("No used-up objects%s.",
3465 unpaid_count ? " on your shopping bill" : "");
3467 pline("
\8eg
\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\95¨
\82Í%s
\82È
\82¢
\81D",
3468 unpaid_count ? "
\8f¤
\93X
\82Ì
\90¿
\8b\81\8f\91\82É
\82Í" : "");
3472 if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
3477 You("are not carrying any unpaid objects.");
3479 You("
\96¢
\95¥
\82¢
\82Ì
\83A
\83C
\83e
\83\80\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3483 if (index("BUCX", c))
3484 oclass = c; /* not a class but understood by this_type_only() */
3486 oclass = def_char_to_objclass(c); /* change to object class */
3488 if (oclass == COIN_CLASS)
3490 if (index(types, c) > index(types, '\033')) {
3491 /* '> ESC' => hidden choice, something known not to be carried */
3492 const char *before = "", *after = "";
3497 before = "known to be blessed ";
3499 before = "
\8fj
\95\9f\82³
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3503 before = "known to be uncursed ";
3505 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3509 before = "known to be cursed ";
3511 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3515 after = " whose blessed/uncursed/cursed status is unknown";
3517 after = "
\8fj
\95\9f\81^
\8eô
\82¢
\82ª
\82í
\82©
\82ç
\82È
\82¢";
3518 break; /* better phrasing is desirable */
3520 /* 'c' is an object class, because we've already handled
3521 all the non-class letters which were put into 'types[]';
3522 could/should move object class names[] array from below
3523 to somewhere above so that we can access it here (via
3524 lcase(strcpy(classnamebuf, names[(int) c]))), but the
3525 game-play value of doing so is low... */
3529 before = "
\82»
\82Ì
\82æ
\82¤
\82È";
3533 You("have no %sobjects%s.", before, after);
3535 You("%s%s
\82à
\82Ì
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", before, after);
3540 if (query_objlist((char *) 0, &invent,
3541 ((flags.invlet_constant ? USE_INVLET : 0)
3543 &pick_list, PICK_NONE, this_type_only) > 0)
3544 free((genericptr_t) pick_list);
3548 /* return a string describing the dungeon feature at <x,y> if there
3549 is one worth mentioning at that location; otherwise null */
3551 dfeature_at(x, y, buf)
3555 struct rm *lev = &levl[x][y];
3556 int ltyp = lev->typ, cmap = -1;
3557 const char *dfeature = 0;
3558 static char altbuf[BUFSZ];
3560 if (IS_DOOR(ltyp)) {
3561 switch (lev->doormask) {
3564 break; /* "doorway" */
3567 break; /* "open door" */
3570 dfeature = "broken door";
3572 dfeature = "
\89ó
\82ê
\82½
\94à";
3576 break; /* "closed door" */
3578 /* override door description for open drawbridge */
3579 if (is_drawbridge_wall(x, y) >= 0)
3581 dfeature = "open drawbridge portcullis", cmap = -1;
3583 dfeature = "
\8d~
\82è
\82Ä
\82¢
\82é
\92µ
\82Ë
\8b´", cmap = -1;
3584 } else if (IS_FOUNTAIN(ltyp))
3585 cmap = S_fountain; /* "fountain" */
3586 else if (IS_THRONE(ltyp))
3587 cmap = S_throne; /* "opulent throne" */
3588 else if (is_lava(x, y))
3589 cmap = S_lava; /* "molten lava" */
3590 else if (is_ice(x, y))
3591 cmap = S_ice; /* "ice" */
3592 else if (is_pool(x, y))
3594 dfeature = "pool of water";
3596 dfeature = "
\90\85\82½
\82Ü
\82è";
3597 else if (IS_SINK(ltyp))
3598 cmap = S_sink; /* "sink" */
3599 else if (IS_ALTAR(ltyp)) {
3601 Sprintf(altbuf, "%saltar to %s (%s)",
3602 ((lev->altarmask & AM_SHRINE)
3603 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3607 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3609 Sprintf(altbuf, "%s%s
\82Ì
\8dÕ
\92d(%s)",
3610 ((lev->altarmask & AM_SHRINE)
3611 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3615 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3618 } else if ((x == xupstair && y == yupstair)
3619 || (x == sstairs.sx && y == sstairs.sy && sstairs.up))
3620 cmap = S_upstair; /* "staircase up" */
3621 else if ((x == xdnstair && y == ydnstair)
3622 || (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
3623 cmap = S_dnstair; /* "staircase down" */
3624 else if (x == xupladder && y == yupladder)
3625 cmap = S_upladder; /* "ladder up" */
3626 else if (x == xdnladder && y == ydnladder)
3627 cmap = S_dnladder; /* "ladder down" */
3628 else if (ltyp == DRAWBRIDGE_DOWN)
3629 cmap = S_vodbridge; /* "lowered drawbridge" */
3630 else if (ltyp == DBWALL)
3631 cmap = S_vcdbridge; /* "raised drawbridge" */
3632 else if (IS_GRAVE(ltyp))
3633 cmap = S_grave; /* "grave" */
3634 else if (ltyp == TREE)
3635 cmap = S_tree; /* "tree" */
3636 else if (ltyp == IRONBARS)
3638 dfeature = "set of iron bars";
3640 dfeature = "
\93S
\82Ì
\96_";
3643 dfeature = defsyms[cmap].explanation;
3645 Strcpy(buf, dfeature);
3649 /* look at what is here; if there are many objects (pile_limit or more),
3650 don't show them unless obj_cnt is 0 */
3652 look_here(obj_cnt, picked_some)
3653 int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progress */
3654 boolean picked_some;
3659 const char *verb = Blind ? "feel" : "see";
3661 const char *verb = Blind ? "
\82ª
\82 \82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½" : "
\82ð
\82Ý
\82Â
\82¯
\82½";
3663 const char *dfeature = (char *) 0;
3664 char fbuf[BUFSZ], fbuf2[BUFSZ];
3666 boolean skip_objects, felt_cockatrice = FALSE;
3668 /* default pile_limit is 5; a value of 0 means "never skip"
3669 (and 1 effectively forces "always skip") */
3670 skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
3671 if (u.uswallow && u.ustuck) {
3672 struct monst *mtmp = u.ustuck;
3676 * Engulfer's inventory can include worn items (specific case is
3677 * Juiblex being created with an amulet as random defensive item)
3678 * which will be flagged as "(being worn)". This code includes
3679 * such a worn item under the header "Contents of <mon>'s stomach",
3680 * a nifty trick for how/where to wear stuff. The situation is
3681 * rare enough to turn a blind eye.
3683 * 3.6.3: Pickup has been changed to decline to pick up a worn
3684 * item from inside an engulfer, but if player tries, it just
3685 * says "you can't" without giving a reason why (which would be
3686 * something along the lines of "because it's worn on the outside
3687 * so is unreachable from in here...").
3690 Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
3691 mbodypart(mtmp, STOMACH));
3693 Sprintf(fbuf, "%s
\82Ì%s
\82Ì
\92\86\90g", mon_nam(mtmp),
3694 mbodypart(mtmp, STOMACH));
3696 #if 0 /*JP*//*
\8cê
\8f\87\82ª
\88á
\82¤
\82Ì
\82Å
\91f
\92¼
\82É*/
3697 /* Skip "Contents of " by using fbuf index 12 */
3698 You("%s to %s what is lying in %s.", Blind ? "try" : "look around",
3701 You("%s
\82Ì%s
\82É
\89½
\82ª
\82 \82é
\82©%s
\81D",
3702 mon_nam(mtmp), mbodypart(mtmp, STOMACH),
3703 Blind ? "
\82³
\82®
\82Á
\82½" : "
\8c©
\89ñ
\82µ
\82½");
3705 otmp = mtmp->minvent;
3707 for (; otmp; otmp = otmp->nobj) {
3708 /* If swallower is an animal, it should have become stone
3710 if (otmp->otyp == CORPSE)
3711 feel_cockatrice(otmp, FALSE);
3715 Strcpy(fbuf, "You feel");
3718 Sprintf(fbuf, "
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F", Blind ? "
\82ç
\82µ
\82¢" : "");
3720 (void) display_minventory(mtmp, MINV_ALL | PICK_NONE, fbuf);
3723 You("%s no objects here.", verb);
3725 pline(Blind ? "
\82 \82È
\82½
\82Í
\89½
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D"
3726 : "
\82 \82È
\82½
\82Í
\89½
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3731 if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen)
3733 There("is %s here.",
3735 pline("
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D",
3736 an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
3738 otmp = level.objects[u.ux][u.uy];
3739 dfeature = dfeature_at(u.ux, u.uy, fbuf2);
3741 if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
3743 if (dfeature && !strcmp(dfeature, "
\90\85\82½
\82Ü
\82è") && Underwater)
3747 boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
3750 if (dfeature && !strncmp(dfeature, "altar ", 6)) {
3752 if (dfeature && !strncmp(dfeature, "
\8dÕ
\92d", 4)) {
3753 /* don't say "altar" twice, dfeature has more info */
3755 You("try to feel what is here.");
3757 You("
\82±
\82±
\82É
\89½
\82ª
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3760 const char *where = (Blind && !can_reach_floor(TRUE))
3761 ? "lying beneath you"
3762 : "lying here on the ",
3763 *onwhat = (Blind && !can_reach_floor(TRUE))
3765 : surface(u.ux, u.uy);
3767 You("try to feel what is %s%s.", drift ? "floating here" : where,
3768 drift ? "" : onwhat);
3771 You("
\89½
\82ª
\95\82\82¢
\82Ä
\82¢
\82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3772 } else if (Blind && !can_reach_floor(TRUE)) {
3773 You("
\89½
\82ª
\91«
\89º
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3775 You("
\89½
\82ª%s
\82Ì
\8fã
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D", surface(u.ux, u.uy));
3779 if (dfeature && !drift && !strcmp(dfeature, surface(u.ux, u.uy)))
3780 dfeature = 0; /* ice already identified */
3781 if (!can_reach_floor(TRUE)) {
3783 pline("But you can't reach it!");
3785 pline("
\82µ
\82©
\82µ
\93Í
\82©
\82È
\82¢
\81I");
3792 Sprintf(fbuf, "There is %s here.", an(dfeature));
3794 Sprintf(fbuf, "
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D", an(dfeature));
3796 if (!otmp || is_lava(u.ux, u.uy)
3797 || (is_pool(u.ux, u.uy) && !Underwater)) {
3800 read_engr_at(u.ux, u.uy); /* Eric Backus */
3801 if (!skip_objects && (Blind || !dfeature))
3803 You("%s no objects here.", verb);
3806 "
\82È
\82É
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82·
\82é
\81D" :
3807 "
\82È
\82É
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3811 /* we know there is something here */
3816 read_engr_at(u.ux, u.uy); /* Eric Backus */
3817 if (obj_cnt == 1 && otmp->quan == 1L)
3819 There("is %s object here.", picked_some ? "another" : "an");
3821 There("
\82±
\82±
\82É
\82Í%s
\88ê
\82Â
\82à
\82Ì
\82ª
\82 \82é
\81D", picked_some ? "
\82à
\82¤" : "");
3824 There("are %s%s objects here.",
3830 picked_some ? " more" : "");
3832 pline("
\82±
\82±
\82É
\82Í%s%s
\82à
\82Ì
\82ª
\82 \82é
\81D",
3833 picked_some ? "
\82³
\82ç
\82É" : "",
3835 ? "
\82¢
\82
\82Â
\82©
\82Ì"
3836 : "
\82½
\82
\82³
\82ñ
\82Ì");
3838 for (; otmp; otmp = otmp->nexthere)
3839 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3840 #if 0 /*JP*//*"It's (corpse_name), unfortunately"*/
3847 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3848 poly_when_stoned(youmonst.data)
3850 : ", unfortunately");
3853 poly_when_stoned(youmonst.data)
3855 : "
\8ec
\94O
\82È
\82ª
\82ç",
3856 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3858 ? "
\82ð
\8aÜ
\82ñ
\82Å
\82¢
\82é"
3861 feel_cockatrice(otmp, FALSE);
3864 } else if (!otmp->nexthere) {
3865 /* only one object */
3868 read_engr_at(u.ux, u.uy); /* Eric Backus */
3870 You("%s here %s.", verb, doname_with_price(otmp));
3872 pline("%s%s
\81D", doname_with_price(otmp), verb);
3873 iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
3874 if (otmp->otyp == CORPSE)
3875 feel_cockatrice(otmp, FALSE);
3879 display_nhwindow(WIN_MESSAGE, FALSE);
3880 tmpwin = create_nhwindow(NHW_MENU);
3882 putstr(tmpwin, 0, fbuf);
3883 putstr(tmpwin, 0, "");
3886 Sprintf(buf, "%s that %s here:",
3887 picked_some ? "Other things" : "Things",
3888 Blind ? "you feel" : "are");
3890 Sprintf(buf, "%s
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F",
3891 picked_some ? "
\91¼
\82É" : "",
3892 Blind ? "
\82ç
\82µ
\82¢" : "");
3894 putstr(tmpwin, 0, buf);
3895 for (; otmp; otmp = otmp->nexthere) {
3896 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3897 felt_cockatrice = TRUE;
3899 Sprintf(buf, "%s...", doname(otmp));
3901 Sprintf(buf, "%s
\81D
\81D
\81D", doname(otmp));
3902 putstr(tmpwin, 0, buf);
3905 putstr(tmpwin, 0, doname_with_price(otmp));
3907 display_nhwindow(tmpwin, TRUE);
3908 destroy_nhwindow(tmpwin);
3909 if (felt_cockatrice)
3910 feel_cockatrice(otmp, FALSE);
3911 read_engr_at(u.ux, u.uy); /* Eric Backus */
3916 /* the ':' command - explicitly look at what is here, including all objects */
3923 MSGTYPE={norep,noshow} "You see here"
3924 interfere with feedback from the look-here command */
3925 hide_unhide_msgtypes(TRUE, MSGTYP_MASK_REP_SHOW);
3926 res = look_here(0, FALSE);
3927 /* restore normal msgtype handling */
3928 hide_unhide_msgtypes(FALSE, MSGTYP_MASK_REP_SHOW);
3933 will_feel_cockatrice(otmp, force_touch)
3935 boolean force_touch;
3937 if ((Blind || force_touch) && !uarmg && !Stone_resistance
3938 && (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
3944 feel_cockatrice(otmp, force_touch)
3946 boolean force_touch;
3950 if (will_feel_cockatrice(otmp, force_touch)) {
3951 /* "the <cockatrice> corpse" */
3952 Strcpy(kbuf, corpse_xname(otmp, (const char *) 0, CXN_PFX_THE));
3954 if (poly_when_stoned(youmonst.data))
3956 You("touched %s with your bare %s.", kbuf,
3957 makeplural(body_part(HAND)));
3959 You("%s
\82Ì
\8e\80\91Ì
\82É
\91f%s
\82Å
\90G
\82Á
\82½
\81D", kbuf,
3964 pline("Touching %s is a fatal mistake...", kbuf);
3966 pline("%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82é
\82Ì
\82Í
\92v
\96½
\93I
\82È
\8aÔ
\88á
\82¢
\82¾
\81D
\81D
\81D", kbuf);
3967 /* normalize body shape here; hand, not body_part(HAND) */
3969 Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
3971 Sprintf(kbuf, "%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82Ä", killer_xname(otmp));
3972 /* will call polymon() for the poly_when_stoned() case */
3983 for (otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
3984 if (otmp != obj && merged(&obj, &otmp))
3989 /* returns TRUE if obj & otmp can be merged; used in invent.c and mkobj.c */
3992 register struct obj *otmp, *obj;
3994 int objnamelth = 0, otmpnamelth = 0;
3996 /* fail if already the same object, if different types, if either is
3997 explicitly marked to prevent merge, or if not mergable in general */
3998 if (obj == otmp || obj->otyp != otmp->otyp
3999 || obj->nomerge || otmp->nomerge || !objects[obj->otyp].oc_merge)
4002 /* coins of the same kind will always merge */
4003 if (obj->oclass == COIN_CLASS)
4006 if (obj->bypass != otmp->bypass
4007 || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed)
4012 /* Checks beyond this point either aren't applicable to globs
4013 * or don't inhibit their merger.
4016 if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
4017 || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
4018 || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit)
4021 if (obj->oclass == FOOD_CLASS
4022 && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
4025 if (obj->dknown != otmp->dknown
4026 || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
4027 || obj->oeroded != otmp->oeroded || obj->oeroded2 != otmp->oeroded2
4028 || obj->greased != otmp->greased)
4031 if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
4032 && (obj->oerodeproof != otmp->oerodeproof
4033 || obj->rknown != otmp->rknown))
4036 if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
4037 if (obj->corpsenm != otmp->corpsenm)
4041 /* hatching eggs don't merge; ditto for revivable corpses */
4042 if ((obj->otyp == EGG && (obj->timed || otmp->timed))
4043 || (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM
4044 && is_reviver(&mons[otmp->corpsenm])))
4047 /* allow candle merging only if their ages are close */
4048 /* see begin_burn() for a reference for the magic "25" */
4049 if (Is_candle(obj) && obj->age / 25 != otmp->age / 25)
4052 /* burning potions of oil never merge */
4053 if (obj->otyp == POT_OIL && obj->lamplit)
4056 /* don't merge surcharged item with base-cost item */
4057 if (obj->unpaid && !same_price(obj, otmp))
4060 /* if they have names, make sure they're the same */
4061 objnamelth = strlen(safe_oname(obj));
4062 otmpnamelth = strlen(safe_oname(otmp));
4063 if ((objnamelth != otmpnamelth
4064 && ((objnamelth && otmpnamelth) || obj->otyp == CORPSE))
4065 || (objnamelth && otmpnamelth
4066 && strncmp(ONAME(obj), ONAME(otmp), objnamelth)))
4069 /* for the moment, any additional information is incompatible */
4070 if (has_omonst(obj) || has_omid(obj) || has_olong(obj) || has_omonst(otmp)
4071 || has_omid(otmp) || has_olong(otmp))
4074 if (obj->oartifact != otmp->oartifact)
4077 if (obj->known == otmp->known || !objects[otmp->otyp].oc_uses_known) {
4078 return (boolean) objects[obj->otyp].oc_merge;
4083 /* the '$' command */
4087 /* the messages used to refer to "carrying gold", but that didn't
4088 take containers into account */
4089 long umoney = money_cnt(invent);
4093 Your("wallet is empty.");
4095 Your("
\8dà
\95z
\82Í
\8bó
\82Á
\82Û
\82¾
\81D");
4098 Your("wallet contains %ld %s.", umoney, currency(umoney));
4100 Your("
\8dà
\95z
\82É
\82Í%ld%s
\93ü
\82Á
\82Ä
\82¢
\82é
\81D", umoney, currency(umoney));
4101 shopper_financial_report();
4105 /* the ')' command */
4111 You("are empty %s.", body_part(HANDED));
4113 if(!uwep) You("%s
\82É
\95\90\8aí
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D", body_part(HAND));
4115 prinv((char *) 0, uwep, 0L);
4117 prinv((char *) 0, uswapwep, 0L);
4122 /* caller is responsible for checking !wearing_armor() */
4124 noarmor(report_uskin)
4125 boolean report_uskin;
4127 if (!uskin || !report_uskin) {
4129 You("are not wearing any armor.");
4131 You("
\8aZ
\82ð
\92\85\82Ä
\82¢
\82È
\82¢
\81D");
4133 char *p, *uskinname, buf[BUFSZ];
4135 uskinname = strcpy(buf, simpleonames(uskin));
4137 /* shorten "set of <color> dragon scales" to "<color> scales"
4138 and "<color> dragon scale mail" to "<color> scale mail" */
4139 if (!strncmpi(uskinname, "set of ", 7))
4141 if ((p = strstri(uskinname, " dragon ")) != 0)
4142 while ((p[1] = p[8]) != '\0')
4144 #else /*
\81u<
\90F>
\83h
\83\89\83S
\83\93\82Ì
\97Ø
\81v
\82ð
\81u<
\90F>
\82Ì
\97Ø
\81v
\82É
\82·
\82é*/
4145 if ((p = strstri(uskinname, "
\83h
\83\89\83S
\83\93\82Ì
\97Ø")) != 0)
4150 You("are not wearing armor but have %s embedded in your skin.",
4152 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",
4157 /* the '[' command */
4162 register int ct = 0;
4164 * Note: players sometimes get here by pressing a function key which
4165 * transmits ''ESC [ <something>'' rather than by pressing '[';
4166 * there's nothing we can--or should-do about that here.
4169 if (!wearing_armor()) {
4173 lets[ct++] = obj_to_let(uarmu);
4175 lets[ct++] = obj_to_let(uarm);
4177 lets[ct++] = obj_to_let(uarmc);
4179 lets[ct++] = obj_to_let(uarmh);
4181 lets[ct++] = obj_to_let(uarms);
4183 lets[ct++] = obj_to_let(uarmg);
4185 lets[ct++] = obj_to_let(uarmf);
4187 (void) display_inventory(lets, FALSE);
4192 /* the '=' command */
4196 if (!uleft && !uright)
4198 You("are not wearing any rings.");
4200 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
4203 register int ct = 0;
4206 lets[ct++] = obj_to_let(uleft);
4208 lets[ct++] = obj_to_let(uright);
4210 (void) display_inventory(lets, FALSE);
4215 /* the '"' command */
4221 You("are not wearing an amulet.");
4223 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
4225 prinv((char *) 0, uamul, 0L);
4233 if ((obj->owornmask & (W_TOOL | W_SADDLE)) != 0L)
4235 if (obj->oclass != TOOL_CLASS)
4237 return (boolean) (obj == uwep || obj->lamplit
4238 || (obj->otyp == LEASH && obj->leashmon));
4241 /* the '(' command */
4249 for (otmp = invent; otmp; otmp = otmp->nobj)
4250 if (tool_in_use(otmp))
4251 lets[ct++] = obj_to_let(otmp);
4255 You("are not using any tools.");
4257 You("
\8eg
\82¦
\82é
\93¹
\8bï
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4259 (void) display_inventory(lets, FALSE);
4263 /* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
4264 show inventory of all currently wielded, worn, or used objects */
4272 for (otmp = invent; otmp; otmp = otmp->nobj)
4273 if (is_worn(otmp) || tool_in_use(otmp))
4274 lets[ct++] = obj_to_let(otmp);
4278 You("are not wearing or wielding anything.");
4280 You("
\89½
\82à
\92\85\82Ä
\82¢
\82È
\82¢
\82µ
\81C
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
4282 (void) display_inventory(lets, FALSE);
4287 * uses up an object that's on the floor, charging for it as necessary
4290 useupf(obj, numused)
4291 register struct obj *obj;
4294 register struct obj *otmp;
4295 boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
4297 /* burn_floor_objects() keeps an object pointer that it tries to
4298 * useupf() multiple times, so obj must survive if plural */
4299 if (obj->quan > numused)
4300 otmp = splitobj(obj, numused);
4303 if (costly_spot(otmp->ox, otmp->oy)) {
4304 if (index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
4305 addtobill(otmp, FALSE, FALSE, FALSE);
4307 (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
4310 if (at_u && u.uundetected && hides_under(youmonst.data))
4311 (void) hideunder(&youmonst);
4315 * Conversion from a class to a string for printing.
4316 * This must match the object class order.
4318 STATIC_VAR NEARDATA const char *names[] = {
4320 0, "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", "Tools",
4321 "Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
4322 "Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
4324 0, "
\96
\82È
\95¨
\91Ì", "
\95\90\8aí", "
\8aZ", "
\8ew
\97Ö", "
\96\82\8f\9c\82¯", "
\93¹
\8bï",
4325 "
\90H
\97¿", "
\96ò", "
\8aª
\95¨", "
\96\82\96@
\8f\91", "
\8fñ", "
\8bà
\89Ý",
4326 "
\95ó
\90Î", "
\8aâ
\82Ü
\82½
\82Í
\92¤
\91\9c", "
\93S
\8b\85", "
\8d½", "
\93Å"
4329 STATIC_VAR NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
4331 STATIC_VAR NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
4333 STATIC_VAR NEARDATA const char *oth_names[] = { "
\8bl
\82ß
\82ç
\82ê
\82½
\93¹
\8bï" };
4335 STATIC_VAR NEARDATA char *invbuf = (char *) 0;
4336 STATIC_VAR NEARDATA unsigned invbufsiz = 0;
4339 let_to_name(let, unpaid, showsym)
4341 boolean unpaid, showsym;
4343 const char *ocsymfmt = " ('%c')";
4344 const int invbuf_sympadding = 8; /* arbitrary */
4345 const char *class_name;
4347 int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
4351 class_name = names[oclass];
4352 else if ((pos = index(oth_symbols, let)) != 0)
4353 class_name = oth_names[pos - oth_symbols];
4355 class_name = names[0];
4358 len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "")
4360 len = strlen(class_name) + (unpaid ? sizeof "
\96¢
\95¥
\82¢
\82Ì" : sizeof "")
4361 + (oclass ? (strlen(ocsymfmt) + invbuf_sympadding) : 0);
4362 if (len > invbufsiz) {
4364 free((genericptr_t) invbuf);
4365 invbufsiz = len + 10; /* add slop to reduce incremental realloc */
4366 invbuf = (char *) alloc(invbufsiz);
4370 Strcat(strcpy(invbuf, "Unpaid "), class_name);
4372 Strcat(strcpy(invbuf, "
\96¢
\95¥
\82¢
\82Ì"), class_name);
4374 Strcpy(invbuf, class_name);
4375 if ((oclass != 0) && showsym) {
4376 char *bp = eos(invbuf);
4377 int mlen = invbuf_sympadding - strlen(class_name);
4378 while (--mlen > 0) {
4383 Sprintf(eos(invbuf), ocsymfmt, def_oc_syms[oclass].sym);
4388 /* release the static buffer used by let_to_name() */
4393 free((genericptr_t) invbuf), invbuf = (char *) 0;
4397 /* give consecutive letters to every item in inventory (for !fixinv mode);
4398 gold is always forced to '$' slot at head of list */
4403 struct obj *obj, *prevobj, *goldobj;
4405 /* first, remove [first instance of] gold from invent, if present */
4406 prevobj = goldobj = 0;
4407 for (obj = invent; obj; prevobj = obj, obj = obj->nobj)
4408 if (obj->oclass == COIN_CLASS) {
4411 prevobj->nobj = goldobj->nobj;
4413 invent = goldobj->nobj;
4416 /* second, re-letter the rest of the list */
4417 for (obj = invent, i = 0; obj; obj = obj->nobj, i++)
4419 (i < 26) ? ('a' + i) : (i < 52) ? ('A' + i - 26) : NOINVSYM;
4420 /* third, assign gold the "letter" '$' and re-insert it at head */
4422 goldobj->invlet = GOLD_SYM;
4423 goldobj->nobj = invent;
4433 * User specifies a 'from' slot for inventory stack to move,
4434 * then a 'to' slot for its destination. Open slots and those
4435 * filled by compatible stacks are listed as likely candidates
4436 * but user can pick any inventory letter (including 'from').
4438 * to == from, 'from' has a name
4439 * All compatible items (same name or no name) are gathered
4440 * into the 'from' stack. No count is allowed.
4441 * to == from, 'from' does not have a name
4442 * All compatible items without a name are gathered into the
4443 * 'from' stack. No count is allowed. Compatible stacks with
4444 * names are left as-is.
4445 * to != from, no count
4446 * Move 'from' to 'to'. If 'to' is not empty, merge 'from'
4447 * into it if possible, otherwise swap it with the 'from' slot.
4448 * to != from, count given
4449 * If the user specifies a count when choosing the 'from' slot,
4450 * and that count is less than the full size of the stack,
4451 * then the stack will be split. The 'count' portion is moved
4452 * to the destination, and the only candidate for merging with
4453 * it is the stack already at the 'to' slot, if any. When the
4454 * destination is non-empty but won't merge, whatever is there
4455 * will be moved to an open slot; if there isn't any open slot
4456 * available, the adjustment attempt fails.
4458 * To minimize merging for 'from == to', unnamed stacks will
4459 * merge with named 'from' but named ones won't merge with
4460 * unnamed 'from'. Otherwise attempting to collect all unnamed
4461 * stacks would lump the first compatible named stack with them
4462 * and give them its name.
4464 * To maximize merging for 'from != to', compatible stacks will
4465 * merge when either lacks a name (or they already have the same
4466 * name). When no count is given and one stack has a name and
4467 * the other doesn't, the merged result will have that name.
4468 * However, when splitting results in a merger, the name of the
4469 * destination overrides that of the source, even if destination
4470 * is unnamed and source is named.
4473 doorganize() /* inventory organizer by Del Lamb */
4475 struct obj *obj, *otmp, *splitting, *bumped;
4476 int ix, cur, trycnt, goldstacks;
4479 #define GOLD_OFFSET 1
4480 #define OVRFLW_INDX (GOLD_OFFSET + 52) /* past gold and 2*26 letters */
4481 char lets[1 + 52 + 1 + 1]; /* room for '$a-zA-Z#\0' */
4483 char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
4484 char *objname, *otmpname;
4485 const char *adj_type;
4486 boolean ever_mind = FALSE, collect;
4488 /* when no invent, or just gold in '$' slot, there's nothing to adjust */
4489 if (!invent || (invent->oclass == COIN_CLASS
4490 && invent->invlet == GOLD_SYM && !invent->nobj)) {
4492 You("aren't carrying anything %s.",
4493 !invent ? "to adjust" : "adjustable");
4495 You("
\8f\87\8f\98\82ð
\95Ï
\82¦
\82é
\82à
\82Ì
\82ð
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4500 if (!flags.invlet_constant)
4502 /* get object the user wants to organize (the 'from' slot) */
4503 allowall[0] = ALLOW_COUNT;
4504 allowall[1] = ALL_CLASSES;
4506 for (goldstacks = 0, otmp = invent; otmp; otmp = otmp->nobj) {
4507 /* gold should never end up in a letter slot, nor should two '$'
4508 slots occur, but if they ever do, allow #adjust to handle them
4509 (in the past, things like this have happened, usually due to
4510 bknown being erroneously set on one stack, clear on another;
4511 object merger isn't fooled by that anymore) */
4512 if (otmp->oclass == COIN_CLASS
4513 && (otmp->invlet != GOLD_SYM || ++goldstacks > 1)) {
4514 allowall[1] = COIN_CLASS;
4515 allowall[2] = ALL_CLASSES;
4520 if (!(obj = getobj(allowall, "adjust")))
4523 /* figure out whether user gave a split count to getobj() */
4524 splitting = bumped = 0;
4525 for (otmp = invent; otmp; otmp = otmp->nobj)
4526 if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
4527 if (otmp->invlet == obj->invlet)
4532 /* initialize the list with all lower and upper case letters */
4533 lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' ';
4534 for (ix = GOLD_OFFSET, let = 'a'; let <= 'z';)
4536 for (let = 'A'; let <= 'Z';)
4538 lets[OVRFLW_INDX] = ' ';
4539 lets[sizeof lets - 1] = '\0';
4540 /* for floating inv letters, truncate list after the first open slot */
4541 if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
4542 lets[ix + (splitting ? 0 : 1)] = '\0';
4544 /* blank out all the letters currently in use in the inventory
4545 except those that will be merged with the selected object */
4546 for (otmp = invent; otmp; otmp = otmp->nobj)
4547 if (otmp != obj && !mergable(otmp, obj)) {
4549 if (let >= 'a' && let <= 'z')
4550 lets[GOLD_OFFSET + let - 'a'] = ' ';
4551 else if (let >= 'A' && let <= 'Z')
4552 lets[GOLD_OFFSET + let - 'A' + 26] = ' ';
4553 /* overflow defaults to off, but it we find a stack using that
4554 slot, switch to on -- the opposite of normal invlet handling */
4555 else if (let == NOINVSYM)
4556 lets[OVRFLW_INDX] = NOINVSYM;
4559 /* compact the list by removing all the blanks */
4560 for (ix = cur = 0; lets[ix]; ix++)
4561 if (lets[ix] != ' ' && cur++ < ix)
4562 lets[cur - 1] = lets[ix];
4564 /* and by dashing runs of letters */
4568 /* get 'to' slot to use as destination */
4570 Sprintf(qbuf, "Adjust letter to what [%s]%s?", lets,
4571 invent ? " (? see used letters)" : "");
4573 Sprintf(qbuf, "
\82Ç
\82Ì
\95¶
\8e\9a\82É
\92²
\90®
\82µ
\82Ü
\82·
\82©[%s]%s
\81H", lets,
4574 invent ? " (?
\82Å
\8eg
\82Á
\82Ä
\82¢
\82é
\95¶
\8e\9a\82ð
\95\
\8e¦)" : "");
4576 for (trycnt = 1; ; ++trycnt) {
4577 let = yn_function(qbuf, (char *) 0, '\0');
4578 if (let == '?' || let == '*') {
4579 let = display_used_invlets(splitting ? obj->invlet : 0);
4585 if (index(quitchars, let)
4586 /* adjusting to same slot is meaningful since all
4587 compatible stacks get collected along the way,
4588 but splitting to same slot is not */
4589 || (splitting && let == obj->invlet)) {
4592 (void) merged(&splitting, &obj);
4596 } else if (let == GOLD_SYM && obj->oclass != COIN_CLASS) {
4598 pline("Only gold coins may be moved into the '%c' slot.",
4601 pline("'%c'
\82É
\82Å
\82«
\82é
\82Ì
\82Í
\8bà
\89Ý
\82¾
\82¯
\81D",
4607 /* letter() classifies '@' as one; compactify() can put '-' in lets;
4608 the only thing of interest that index() might find is '$' or '#'
4609 since letter() catches everything else that we put into lets[] */
4610 if ((letter(let) && let != '@') || (index(lets, let) && let != '-'))
4611 break; /* got one */
4615 pline("Select an inventory slot letter."); /* else try again */
4617 pline("
\8e\9d\82¿
\95¨
\82Ì
\95¶
\8e\9a\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢
\81D");
4621 collect = (let == obj->invlet);
4622 /* change the inventory and print the resulting item */
4624 adj_type = collect ? "Collecting" : !splitting ? "Moving:" : "Splitting:";
4626 adj_type = collect ? "
\82ð
\8fW
\82ß
\82½
\81D" : !splitting ? "
\82ð
\88Ú
\93®
\82µ
\82½
\81D" : "
\82ð
\95ª
\8a\84\82µ
\82½
\81D";
4629 * don't use freeinv/addinv to avoid double-touching artifacts,
4630 * dousing lamps, losing luck, cursing loadstone, etc.
4632 extract_nobj(obj, &invent);
4634 for (otmp = invent; otmp;) {
4635 /* it's tempting to pull this outside the loop, but merged() could
4636 free ONAME(obj) [via obfree()] and replace it with ONAME(otmp) */
4637 objname = has_oname(obj) ? ONAME(obj) : (char *) 0;
4640 /* Collecting: #adjust an inventory stack into its same slot;
4641 keep it there and merge other compatible stacks into it.
4642 Traditional inventory behavior is to merge unnamed stacks
4643 with compatible named ones; we only want that if it is
4644 the 'from' stack (obj) with a name and candidate (otmp)
4645 without one, not unnamed 'from' with named candidate. */
4646 otmpname = has_oname(otmp) ? ONAME(otmp) : (char *) 0;
4647 if ((!otmpname || (objname && !strcmp(objname, otmpname)))
4648 && merged(&otmp, &obj)) {
4650 adj_type = "Merging:";
4652 adj_type = "
\82ð
\8d\87\82í
\82¹
\82½
\81D";
4655 extract_nobj(obj, &invent);
4656 continue; /* otmp has already been updated */
4658 } else if (otmp->invlet == let) {
4659 /* Moving or splitting: don't merge extra compatible stacks.
4660 Found 'otmp' in destination slot; merge if compatible,
4661 otherwise bump whatever is there to an open slot. */
4664 adj_type = "Swapping:";
4666 adj_type = "
\82ð
\8cð
\8a·
\82µ
\82½
\81D";
4667 otmp->invlet = obj->invlet;
4669 /* strip 'from' name if it has one */
4670 if (objname && !obj->oartifact)
4671 ONAME(obj) = (char *) 0;
4672 if (!mergable(otmp, obj)) {
4673 /* won't merge; put 'from' name back */
4675 ONAME(obj) = objname;
4677 /* will merge; discard 'from' name */
4679 free((genericptr_t) objname), objname = 0;
4682 if (merged(&otmp, &obj)) {
4684 adj_type = "Splitting and merging:";
4686 adj_type = "
\82ð
\95ª
\8a\84\82µ
\82Ä
\8d\87\82í
\82¹
\82½
\81D";
4688 extract_nobj(obj, &invent);
4689 } else if (inv_cnt(FALSE) >= 52) {
4690 (void) merged(&splitting, &obj); /* undo split */
4691 /* "knapsack cannot accommodate any more items" */
4693 Your("pack is too full.");
4695 Your("
\8e\9d\82¿
\95¨
\82Í
\88ê
\94t
\82¾
\81D");
4699 extract_nobj(bumped, &invent);
4701 } /* moving vs splitting */
4702 break; /* not collecting and found 'to' slot */
4707 /* inline addinv; insert loose object at beginning of inventory */
4710 obj->where = OBJ_INVENT;
4714 /* splitting the 'from' stack is causing an incompatible
4715 stack in the 'to' slot to be moved into an open one;
4716 we need to do another inline insertion to inventory */
4717 assigninvlet(bumped);
4718 bumped->nobj = invent;
4719 bumped->where = OBJ_INVENT;
4724 /* messages deferred until inventory has been fully reestablished */
4725 prinv(adj_type, obj, 0L);
4728 prinv("Moving:", bumped, 0L);
4730 prinv("
\88Ú
\93®:", bumped, 0L);
4732 clear_splitobjs(); /* reset splitobj context */
4737 /* common to display_minventory and display_cinventory */
4739 invdisp_nothing(hdr, txt)
4740 const char *hdr, *txt;
4744 menu_item *selected;
4747 win = create_nhwindow(NHW_MENU);
4749 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr,
4751 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
4752 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
4753 end_menu(win, (char *) 0);
4754 if (select_menu(win, PICK_NONE, &selected) > 0)
4755 free((genericptr_t) selected);
4756 destroy_nhwindow(win);
4760 /* query_objlist callback: return things that are worn or wielded */
4762 worn_wield_only(obj)
4766 /* check for things that *are* worn or wielded (only used for monsters,
4767 so we don't worry about excluding W_CHAIN, W_ARTI and the like) */
4768 return (boolean) (obj->owornmask != 0L);
4770 /* this used to check for things that *might* be worn or wielded,
4771 but that's not particularly interesting */
4772 if (is_weptool(obj) || is_wet_towel(obj) || obj->otyp == MEAT_RING)
4774 return (boolean) (obj->oclass == WEAPON_CLASS
4775 || obj->oclass == ARMOR_CLASS
4776 || obj->oclass == AMULET_CLASS
4777 || obj->oclass == RING_CLASS);
4782 * Display a monster's inventory.
4783 * Returns a pointer to the object from the monster's inventory selected
4784 * or NULL if nothing was selected.
4786 * By default, only worn and wielded items are displayed. The caller
4787 * can pick one. Modifier flags are:
4789 * PICK_NONE, PICK_ONE - standard menu control
4790 * PICK_ANY - allowed, but we only return a single object
4791 * MINV_NOLET - nothing selectable
4792 * MINV_ALL - display all inventory
4795 display_minventory(mon, dflags, title)
4796 register struct monst *mon;
4803 menu_item *selected = 0;
4804 int do_all = (dflags & MINV_ALL) != 0,
4805 incl_hero = (do_all && u.uswallow && mon == u.ustuck),
4806 have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
4807 pickings = (dflags & MINV_PICKMASK);
4810 Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
4811 do_all ? "possessions" : "armament");
4813 Sprintf(tmp, "%s
\82Ì%s
\81F", Monnam(mon),
4814 do_all ? "
\8e\9d\82¿
\95¨" : "
\91\95\94õ");
4817 if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
4818 /* Fool the 'weapon in hand' routine into
4819 * displaying 'weapon in claw', etc. properly.
4821 youmonst.data = mon->data;
4822 /* in case inside a shop, don't append "for sale" prices */
4823 iflags.suppress_price++;
4825 n = query_objlist(title ? title : tmp, &(mon->minvent),
4826 (INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0)),
4827 &selected, pickings,
4828 do_all ? allow_all : worn_wield_only);
4830 iflags.suppress_price--;
4831 /* was 'set_uasmon();' but that potentially has side-effects */
4832 youmonst.data = &mons[u.umonnum]; /* most basic part of set_uasmon */
4835 invdisp_nothing(title ? title : tmp, "(none)");
4837 invdisp_nothing(title ? title : tmp, "(
\89½
\82à
\82È
\82¢)");
4842 ret = selected[0].item.a_obj;
4843 free((genericptr_t) selected);
4845 ret = (struct obj *) 0;
4850 * Display the contents of a container in inventory style.
4851 * Currently, this is only used for statues, via wand of probing.
4854 display_cinventory(obj)
4855 register struct obj *obj;
4860 menu_item *selected = 0;
4863 (void) safe_qbuf(qbuf, "Contents of ", ":", obj, doname, ansimpleoname,
4866 (void) safe_qbuf(qbuf, "", "
\82Ì
\92\86\90g
\81F", obj, doname, ansimpleoname,
4871 n = query_objlist(qbuf, &(obj->cobj), INVORDER_SORT,
4872 &selected, PICK_NONE, allow_all);
4875 invdisp_nothing(qbuf, "(empty)");
4877 invdisp_nothing(qbuf, "(
\8bó
\82Á
\82Û)");
4881 ret = selected[0].item.a_obj;
4882 free((genericptr_t) selected);
4884 ret = (struct obj *) 0;
4889 /* query objlist callback: return TRUE if obj is at given location */
4896 return (obj->ox == only.x && obj->oy == only.y);
4900 * Display a list of buried items in inventory style. Return a non-zero
4901 * value if there were items at that spot.
4903 * Currently, this is only used with a wand of probing zapped downwards.
4906 display_binventory(x, y, as_if_seen)
4911 menu_item *selected = 0;
4914 /* count # of objects here */
4915 for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
4916 if (obj->ox == x && obj->oy == y) {
4926 if (query_objlist("Things that are buried here:",
4928 if (query_objlist("
\82±
\82±
\82É
\96\84\82ß
\82ç
\82ê
\82Ä
\82¢
\82é
\82à
\82Ì
\81F",
4929 &level.buriedobjlist, INVORDER_SORT,
4930 &selected, PICK_NONE, only_here) > 0)
4931 free((genericptr_t) selected);
4932 only.x = only.y = 0;