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-2021 */
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)
1785 Sprintf(menuquery, "What do you want to %s?", word);
1787 Sprintf(menuquery, "%s%s%s
\82©
\81H", what, joshi, jpolite(jword));
1788 if (!strcmp(word, "grease"))
1790 Sprintf(qbuf, "your %s", fingers_or_gloves(FALSE));
1792 Sprintf(qbuf, "
\82 \82È
\82½
\82Ì%s", fingers_or_gloves(FALSE));
1793 else if (!strcmp(word, "write with"))
1795 Sprintf(qbuf, "your %s", body_part(FINGERTIP));
1797 Sprintf(qbuf, "
\82 \82È
\82½
\82Ì%s", body_part(FINGERTIP));
1798 else if (!strcmp(word, "wield"))
1800 Sprintf(qbuf, "your %s %s%s", uarmg ? "gloved" : "bare",
1801 makeplural(body_part(HAND)),
1802 !uwep ? " (wielded)" : "");
1804 Sprintf(qbuf, "
\89½
\82à
\8eè
\82É
\82µ
\82È
\82¢%s",
1805 !uwep ? "(
\8c»
\8dÝ)" : "");
1807 else if (!strcmp(word, "ready"))
1809 Sprintf(qbuf, "empty quiver%s",
1810 !uquiver ? " (nothing readied)" : "");
1812 Sprintf(qbuf, "
\8bó
\82Ì
\96î
\93\9b%s",
1813 !uquiver ? " (
\89½
\82à
\8f\80\94õ
\82µ
\82Ä
\82¢
\82È
\82¢)" : "");
1816 if (ilet == '?' && !*lets && *altlets)
1817 allowed_choices = altlets;
1818 ilet = display_pickinv(allowed_choices, *qbuf ? qbuf : (char *) 0,
1820 TRUE, allowcnt ? &ctmp : (long *) 0);
1823 if (ilet == HANDS_SYM)
1824 return (struct obj *) &zeroobj; /* cast away 'const' */
1825 if (ilet == '\033') {
1828 return (struct obj *) 0;
1832 if (allowcnt && ctmp >= 0) {
1836 /* they typed a letter (not a space) at the prompt */
1838 /* find the item which was picked */
1839 for (otmp = invent; otmp; otmp = otmp->nobj)
1840 if (otmp->invlet == ilet)
1842 /* some items have restrictions */
1843 if (ilet == def_oc_syms[COIN_CLASS].sym
1844 /* guard against the [hypothetical] chace of having more
1845 than one invent slot of gold and picking the non-'$' one */
1846 || (otmp && otmp->oclass == COIN_CLASS)) {
1849 You("cannot %s gold.", word);
1851 You("
\8bà
\89Ý%s%s
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D", joshi, jword);
1852 return (struct obj *) 0;
1854 /* Historic note: early Nethack had a bug which was
1855 * first reported for Larn, where trying to drop 2^32-n
1856 * gold pieces was allowed, and did interesting things
1857 * to your money supply. The LRS is the tax bureau
1860 if (cntgiven && cnt <= 0) {
1864 "LRS would be very interested to know you have that much.");
1866 "
\82»
\82Ì
\8bZ
\82Í
\82Æ
\82 \82é
\83Q
\81[
\83\80\82Ì
\83J
\83W
\83m
\82Å
\8eg
\82¦
\82½
\82¯
\82Ç
\81C
\82à
\82Í
\82â
\8eg
\82¦
\82È
\82¢
\82æ
\81D");
1867 return (struct obj *) 0;
1870 if (cntgiven && !strcmp(word, "throw")) {
1871 /* permit counts for throwing gold, but don't accept
1872 * counts for other things since the throw code will
1873 * split off a single item anyway */
1875 return (struct obj *) 0;
1876 if (cnt > 1 && (ilet != def_oc_syms[COIN_CLASS].sym
1877 && !(otmp && otmp->oclass == COIN_CLASS))) {
1879 You("can only throw one item at a time.");
1881 You("
\93¯
\8e\9e\82É
\82½
\82
\82³
\82ñ
\82Ì
\82à
\82Ì
\82ð
\93\8a\82°
\82ç
\82ê
\82È
\82¢
\81D");
1885 context.botl = 1; /* May have changed the amount of money */
1887 /* [we used to set otmp (by finding ilet in invent) here, but
1888 that's been moved above so that otmp can be checked earlier] */
1889 /* verify the chosen object */
1892 You("don't have that object.");
1894 You("
\82»
\82ñ
\82È
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
1896 return (struct obj *) 0;
1898 } else if (cnt < 0 || otmp->quan < cnt) {
1900 You("don't have that many! You have only %ld.", otmp->quan);
1902 pline("
\82»
\82ñ
\82È
\82É
\82½
\82
\82³
\82ñ
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81I
\82¹
\82¢
\82º
\82¢%ld%s
\82Á
\82Ä
\82Æ
\82±
\82¾
\81D", otmp->quan, numeral(otmp));
1904 return (struct obj *) 0;
1909 if (!allowall && let && !index(let, otmp->oclass)
1910 && !(usegold && otmp->oclass == COIN_CLASS)) {
1912 silly_thing(word, otmp);
1914 silly_thing(jword, otmp);
1916 return (struct obj *) 0;
1920 return (struct obj *) 0;
1921 if (cnt != otmp->quan) {
1922 /* don't split a stack of cursed loadstones */
1923 if (splittable(otmp))
1924 otmp = splitobj(otmp, cnt);
1925 else if (otmp->otyp == LOADSTONE && otmp->cursed)
1926 /* kludge for canletgo()'s can't-drop-this message */
1927 otmp->corpsenm = (int) cnt;
1934 silly_thing(word, otmp)
1938 #if 1 /* 'P','R' vs 'W','T' handling is obsolete */
1941 const char *s1, *s2, *s3;
1942 int ocls = otmp->oclass, otyp = otmp->otyp;
1945 /* check for attempted use of accessory commands ('P','R') on armor
1946 and for corresponding armor commands ('W','T') on accessories */
1947 if (ocls == ARMOR_CLASS) {
1949 if (!strcmp(word, "put on"))
1950 s1 = "W", s2 = "wear", s3 = "";
1951 else if (!strcmp(word, "remove"))
1952 s1 = "T", s2 = "take", s3 = " off";
1954 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1955 s1 = "W", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1956 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1957 s1 = "T", s2 = "
\82Í
\82¸
\82·", s3 = "";
1959 } else if ((ocls == RING_CLASS || otyp == MEAT_RING)
1960 || ocls == AMULET_CLASS
1961 || (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
1963 if (!strcmp(word, "wear"))
1964 s1 = "P", s2 = "put", s3 = " on";
1965 else if (!strcmp(word, "take off"))
1966 s1 = "R", s2 = "remove", s3 = "";
1968 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1969 s1 = "P", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1970 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1971 s1 = "R", s2 = "
\82Í
\82¸
\82·", s3 = "";
1976 pline("Use the '%s' command to %s %s%s.", s1, s2,
1977 !(is_plural(otmp) || pair_of(otmp)) ? "that" : "those", s3);
1979 pline("
\82»
\82ê
\82ð%s
\82É
\82Í'%s'
\83R
\83}
\83\93\83h
\82ð
\8eg
\82¤
\82±
\82Æ
\81D", s2, s1);
1983 pline(silly_thing_to, word);
1990 /* use allow_category() from pickup.c */
1991 return (int) allow_category(otmp);
1998 return (otmp->unpaid || (Has_contents(otmp) && count_unpaid(otmp->cobj)));
2004 return (boolean) (uarm || uarmc || uarmf || uarmg
2005 || uarmh || uarms || uarmu);
2012 return (otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_SADDLE | W_WEAPONS))
2017 /* extra xprname() input that askchain() can't pass through safe_qbuf() */
2018 STATIC_VAR struct xprnctx {
2023 /* safe_qbuf() -> short_oname() callback */
2028 return xprname(obj, (char *) 0, safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
2032 /* alternate safe_qbuf() -> short_oname() callback */
2034 safeq_shortxprname(obj)
2037 return xprname(obj, ansimpleoname(obj), safeq_xprn_ctx.let,
2038 safeq_xprn_ctx.dot, 0L, 0L);
2041 static NEARDATA const char removeables[] = { ARMOR_CLASS, WEAPON_CLASS,
2042 RING_CLASS, AMULET_CLASS,
2045 /* Interactive version of getobj - used for Drop, Identify, and Takeoff (A).
2046 Return the number of times fn was called successfully.
2047 If combo is TRUE, we just use this to get a category list. */
2048 /*JP CHECK: 3.6.0
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
2049 do.c:962: || (result = ggetobj("drop", drop, 0, FALSE, (unsigned *) 0)) < -1)
2050 do.c:1009: i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
2051 do_wear.c:2955: || (result = ggetobj("take off", select_off, 0, FALSE,
2052 do_wear.c:3007: if (ggetobj("take off", select_off, 0, TRUE, (unsigned *) 0) == -2)
2053 invent.c:2014: n = ggetobj("identify", identify, id_limit, FALSE,
2056 ggetobj(word, fn, mx, combo, resultflags)
2058 int FDECL((*fn), (OBJ_P)), mx;
2059 boolean combo; /* combination menu flag */
2060 unsigned *resultflags;
2062 int FDECL((*ckfn), (OBJ_P)) = (int FDECL((*), (OBJ_P))) 0;
2063 boolean FDECL((*ofilter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
2064 boolean takeoff, ident, allflag, m_seen;
2066 int oletct, iletct, unpaid, oc_of_sym;
2067 char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 10];
2068 char extra_removeables[3 + 1]; /* uwep,uswapwep,uquiver */
2069 char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
2071 const char *joshi = "
\82ð";
2074 const struct trans_verb *tv = trans_verb(word);
2076 joshi = tv->particle;
2081 You("have nothing to %s.", word);
2083 You("%s
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", jcan(jword));
2085 *resultflags = ALL_FINISHED;
2090 takeoff = ident = allflag = m_seen = FALSE;
2091 add_valid_menu_class(0); /* reset */
2092 if (taking_off(word)) {
2095 } else if (!strcmp(word, "identify")) {
2097 ofilter = not_fully_identified;
2100 iletct = collect_obj_classes(ilets, invent, FALSE, ofilter, &itemcount);
2101 unpaid = count_unpaid(invent);
2103 if (ident && !iletct) {
2104 return -1; /* no further identifications */
2105 } else if (invent) {
2106 ilets[iletct++] = ' ';
2108 ilets[iletct++] = 'u';
2109 if (count_buc(invent, BUC_BLESSED, ofilter))
2110 ilets[iletct++] = 'B';
2111 if (count_buc(invent, BUC_UNCURSED, ofilter))
2112 ilets[iletct++] = 'U';
2113 if (count_buc(invent, BUC_CURSED, ofilter))
2114 ilets[iletct++] = 'C';
2115 if (count_buc(invent, BUC_UNKNOWN, ofilter))
2116 ilets[iletct++] = 'X';
2117 ilets[iletct++] = 'a';
2119 ilets[iletct++] = 'i';
2121 ilets[iletct++] = 'm'; /* allow menu presentation on request */
2122 ilets[iletct] = '\0';
2126 Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]",
2129 Sprintf(qbuf,"
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\82à
\82Ì%s%s
\82©
\81H[%s]", joshi,
2130 jpolite(jword), ilets);
2133 if (buf[0] == '\033')
2135 if (index(buf, 'i')) {
2136 char ailets[1+26+26+1+5+1]; /* $ + a-z + A-Z + # + slop + \0 */
2139 /* applicable inventory letters; if empty, show entire invent */
2142 for (otmp = invent; otmp; otmp = otmp->nobj)
2143 /* index() check: limit overflow items to one '#' */
2144 if ((*ofilter)(otmp) && !index(ailets, otmp->invlet))
2145 (void) strkitten(ailets, otmp->invlet);
2146 if (display_inventory(ailets, TRUE) == '\033')
2152 extra_removeables[0] = '\0';
2154 /* arbitrary types of items can be placed in the weapon slots
2155 [any duplicate entries in extra_removeables[] won't matter] */
2157 (void) strkitten(extra_removeables, uwep->oclass);
2159 (void) strkitten(extra_removeables, uswapwep->oclass);
2161 (void) strkitten(extra_removeables, uquiver->oclass);
2165 olets[oletct = 0] = '\0';
2166 while ((sym = *ip++) != '\0') {
2169 oc_of_sym = def_char_to_objclass(sym);
2170 if (takeoff && oc_of_sym != MAXOCLASSES) {
2171 if (index(extra_removeables, oc_of_sym)) {
2172 ; /* skip rest of takeoff checks */
2173 } else if (!index(removeables, oc_of_sym)) {
2175 pline("Not applicable.");
2177 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2179 } else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
2182 } else if (oc_of_sym == WEAPON_CLASS && !uwep && !uswapwep
2185 You("are not wielding anything.");
2187 You("
\89½
\82à
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
2189 } else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
2191 You("are not wearing rings.");
2193 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
2195 } else if (oc_of_sym == AMULET_CLASS && !uamul) {
2197 You("are not wearing an amulet.");
2199 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
2201 } else if (oc_of_sym == TOOL_CLASS && !ublindf) {
2203 You("are not wearing a blindfold.");
2205 You("
\96Ú
\89B
\82µ
\82ð
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
2210 if (oc_of_sym == COIN_CLASS && !combo) {
2212 } else if (sym == 'a') {
2214 } else if (sym == 'A') {
2215 ; /* same as the default */
2216 } else if (sym == 'u') {
2217 add_valid_menu_class('u');
2219 } else if (index("BUCX", sym)) {
2220 add_valid_menu_class(sym); /* 'B','U','C',or 'X' */
2222 } else if (sym == 'm') {
2224 } else if (oc_of_sym == MAXOCLASSES) {
2226 You("don't have any %c's.", sym);
2228 You("%c
\82É
\91®
\82·
\82é
\95¨
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", sym);
2229 } else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */
2230 if (!index(olets, oc_of_sym)) {
2231 add_valid_menu_class(oc_of_sym);
2232 olets[oletct++] = oc_of_sym;
2240 || (!oletct && ckfn != ckunpaid && ckfn != ckvalidcat))
2242 } else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) {
2245 /* !!!! test gold dropping */
2246 } else if (allowgold == 2 && !oletct) {
2247 return 1; /* you dropped gold (or at least tried to) */
2250 int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
2252 * askchain() has already finished the job in this case
2253 * so set a special flag to convey that back to the caller
2254 * so that it won't continue processing.
2255 * Fix for bug C331-1 reported by Irina Rempt-Drijfhout.
2257 if (combo && allflag && resultflags)
2258 *resultflags |= ALL_FINISHED;
2264 * Walk through the chain starting at objchn and ask for all objects
2265 * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
2266 * whether the action in question (i.e., fn) has to be performed.
2267 * If allflag then no questions are asked. Mx gives the max number
2268 * of objects to be treated. Return the number of objects treated.
2270 /*JP CHECK: 3.6.2
\82Å
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
2271 invent.c:2228: int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
2272 pickup.c:3208: if (askchain(objlist, (one_by_one ? (char *) 0 : selection), allflag,
2273 word
\82É
\82Í
\93®
\8e\8c\82ª
\89p
\8cê
\82Å
\93ü
\82é
\81B
2276 askchain(objchn, olets, allflag, fn, ckfn, mx, word)
2277 struct obj **objchn; /* *objchn might change */
2279 const char *olets, *word; /* olets is an Obj Class char array */
2280 int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
2282 struct obj *otmp, *otmpo;
2283 register char sym, ilet;
2284 int cnt = 0, dud = 0, tmp;
2285 boolean takeoff, nodot, ident, take_out, put_in, first, ininv, bycat;
2286 char qbuf[QBUFSZ], qpfx[QBUFSZ];
2287 Loot *sortedchn = 0;
2289 takeoff = taking_off(word);
2290 ident = !strcmp(word, "identify");
2291 take_out = !strcmp(word, "take out");
2292 put_in = !strcmp(word, "put in");
2293 nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
2294 || takeoff || take_out || put_in);
2295 ininv = (*objchn == invent);
2296 bycat = (menu_class_present('u')
2297 || menu_class_present('B') || menu_class_present('U')
2298 || menu_class_present('C') || menu_class_present('X'));
2300 /* someday maybe we'll sort by 'olets' too (temporarily replace
2301 flags.packorder and pass SORTLOOT_PACK), but not yet... */
2302 sortedchn = sortloot(objchn, SORTLOOT_INVLET, FALSE,
2303 (boolean FDECL((*), (OBJ_P))) 0);
2307 * Interrogate in the object class order specified.
2308 * For example, if a person specifies =/ then first all rings
2309 * will be asked about followed by all wands. -dgk
2313 if (*objchn && (*objchn)->oclass == COIN_CLASS)
2314 ilet--; /* extra iteration */
2316 * Multiple Drop can change the invent chain while it operates
2317 * (dropping a burning potion of oil while levitating creates
2318 * an explosion which can destroy inventory items), so simple
2320 * for (otmp = *objchn; otmp; otmp = otmp2) {
2321 * otmp2 = otmp->nobj;
2324 * is inadequate here. Use each object's bypass bit to keep
2325 * track of which list elements have already been processed.
2327 bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */
2328 while ((otmp = nxt_unbypassed_loot(sortedchn, *objchn)) != 0) {
2331 else if (ilet == 'Z')
2332 ilet = NOINVSYM; /* '#' */
2335 if (olets && *olets && otmp->oclass != *olets)
2337 if (takeoff && !is_worn(otmp))
2339 if (ident && !not_fully_identified(otmp))
2341 if (ckfn && !(*ckfn)(otmp))
2343 if (bycat && !ckvalidcat(otmp))
2346 safeq_xprn_ctx.let = ilet;
2347 safeq_xprn_ctx.dot = !nodot;
2350 /* traditional_loot() skips prompting when only one
2351 class of objects is involved, so prefix the first
2352 object being queried here with an explanation why */
2353 if (take_out || put_in)
2354 Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
2358 (void) safe_qbuf(qbuf, qpfx, "?", otmp,
2359 ininv ? safeq_xprname : doname,
2360 ininv ? safeq_shortxprname : ansimpleoname,
2363 (void) safe_qbuf(qbuf, qpfx, "
\81H", otmp,
2364 ininv ? safeq_xprname : doname,
2365 ininv ? safeq_shortxprname : ansimpleoname,
2366 "
\83A
\83C
\83e
\83\80");
2368 sym = (takeoff || ident || otmp->quan < 2L) ? nyaq(qbuf)
2375 /* Number was entered; split the object unless it corresponds
2376 to 'none' or 'all'. 2 special cases: cursed loadstones and
2377 welded weapons (eg, multiple daggers) will remain as merged
2378 unit; done to avoid splitting an object that won't be
2379 droppable (even if we're picking up rather than dropping). */
2384 if (yn_number < otmp->quan && splittable(otmp))
2385 otmp = splitobj(otmp, yn_number);
2395 if (container_gone(fn)) {
2396 /* otmp caused magic bag to explode;
2397 both are now gone */
2398 otmp = 0; /* and return */
2399 } else if (otmp && otmp != otmpo) {
2400 /* split occurred, merge again */
2401 (void) merged(&otmpo, &otmp);
2415 /* special case for seffects() */
2421 if (olets && *olets && *++olets)
2424 if (!takeoff && (dud || cnt))
2426 pline("That was all.");
2428 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
2429 else if (!dud && !cnt)
2431 pline("No applicable objects.");
2433 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2435 unsortloot(&sortedchn);
2436 bypass_objlist(*objchn, FALSE);
2441 * Object identification routines:
2444 /* make an object actually be identified; no display updating */
2446 fully_identify_obj(otmp)
2449 makeknown(otmp->otyp);
2450 if (otmp->oartifact)
2451 discover_artifact((xchar) otmp->oartifact);
2452 otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
2453 if (Is_container(otmp) || otmp->otyp == STATUE)
2454 otmp->cknown = otmp->lknown = 1;
2455 if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
2456 learn_egg_type(otmp->corpsenm);
2459 /* ggetobj callback routine; identify an object and give immediate feedback */
2464 fully_identify_obj(otmp);
2465 prinv((char *) 0, otmp, 0L);
2469 /* menu of unidentified objects; select and identify up to id_limit of them */
2471 menu_identify(id_limit)
2474 menu_item *pick_list;
2475 int n, i, first = 1, tryct = 5;
2477 /* assumptions: id_limit > 0 and at least one unID'd item is present */
2481 Sprintf(buf, "What would you like to identify %s?",
2482 first ? "first" : "next");
2484 Sprintf(buf, "
\82Ç
\82ê
\82ð%s
\82É
\8e¯
\95Ê
\82µ
\82Ü
\82·
\82©
\81H",
2485 first ? "
\8dÅ
\8f\89" : "
\8e\9f");
2487 n = query_objlist(buf, &invent, (SIGNAL_NOMENU | SIGNAL_ESCAPE
2488 | USE_INVLET | INVORDER_SORT),
2489 &pick_list, PICK_ANY, not_fully_identified);
2494 for (i = 0; i < n; i++, id_limit--)
2495 (void) identify(pick_list[i].item.a_obj);
2496 free((genericptr_t) pick_list);
2497 mark_synch(); /* Before we loop to pop open another menu */
2499 } else if (n == -2) { /* player used ESC to quit menu */
2501 } else if (n == -1) { /* no eligible items found */
2503 pline("That was all.");
2505 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
2507 } else if (!--tryct) { /* stop re-prompting */
2508 pline1(thats_enough_tries);
2510 } else { /* try again */
2512 pline("Choose an item; use ESC to decline.");
2514 pline("
\83A
\83C
\83e
\83\80\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢;
\82â
\82ß
\82é
\82È
\82çESC
\81D");
2518 /* count the unidentified items */
2520 count_unidentified(objchn)
2526 for (obj = objchn; obj; obj = obj->nobj)
2527 if (not_fully_identified(obj))
2532 /* dialog with user to identify a given number of items; 0 means all */
2534 identify_pack(id_limit, learning_id)
2536 boolean learning_id; /* true if we just read unknown identify scroll */
2539 int n, unid_cnt = count_unidentified(invent);
2543 You("have already identified all %sof your possessions.",
2544 learning_id ? "the rest " : "");
2546 You("%s
\91S
\82Ä
\82Ì
\8f\8a\97L
\95¨
\82ð
\8e¯
\95Ê
\82µ
\82Ä
\82µ
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D",
2547 learning_id ? "
\8ec
\82è" : "");
2549 } else if (!id_limit || id_limit >= unid_cnt) {
2550 /* identify everything */
2551 /* TODO: use fully_identify_obj and cornline/menu/whatever here */
2552 for (obj = invent; obj; obj = obj->nobj) {
2553 if (not_fully_identified(obj)) {
2554 (void) identify(obj);
2560 /* identify up to `id_limit' items */
2562 if (flags.menu_style == MENU_TRADITIONAL)
2564 n = ggetobj("identify", identify, id_limit, FALSE,
2567 break; /* quit or no eligible items */
2568 } while ((id_limit -= n) > 0);
2569 if (n == 0 || n < -1)
2570 menu_identify(id_limit);
2575 /* called when regaining sight; mark inventory objects which were picked
2576 up while blind as now having been seen */
2578 learn_unseen_invent()
2583 return; /* sanity check */
2585 for (otmp = invent; otmp; otmp = otmp->nobj) {
2587 continue; /* already seen */
2588 /* set dknown, perhaps bknown (for priest[ess]) */
2591 * If object->eknown gets implemented (see learnwand(zap.c)),
2592 * handle deferred discovery here.
2598 /* persistent inventory window is maintained by interface code;
2599 'update_inventory' used to be a macro for
2600 (*windowprocs.win_update_inventory) but the restore hackery
2601 was getting out of hand; this is now a central call point */
2609 * Ought to check (windowprocs.wincap2 & WC2_PERM_INVENT) here....
2611 * We currently don't skip this call when iflags.perm_invent is False
2612 * because curses uses that to disable a previous perm_invent window
2613 * (after toggle via 'O'; perhaps the options code should handle that).
2615 (*windowprocs.win_update_inventory)();
2618 /* should of course only be called for things in invent */
2623 if (!flags.invlet_constant) {
2624 obj->invlet = NOINVSYM;
2631 * Print the indicated quantity of the given object. If quan == 0L then use
2632 * the current quantity.
2635 prinv(prefix, obj, quan)
2643 pline("%s%s%s", prefix, *prefix ? " " : "",
2644 xprname(obj, (char *) 0, obj_to_let(obj), TRUE, 0L, quan));
2647 xprname(obj, (char *)0, obj_to_let(obj), *prefix ? FALSE : TRUE, 0L, quan),
2653 xprname(obj, txt, let, dot, cost, quan)
2655 const char *txt; /* text to print instead of obj */
2656 char let; /* inventory letter */
2657 boolean dot; /* append period; (dot && cost => Iu) */
2658 long cost; /* cost (for inventory of unpaid or expended items) */
2659 long quan; /* if non-0, print this quantity, not obj->quan */
2661 #ifdef LINT /* handle static char li[BUFSZ]; */
2664 static char li[BUFSZ];
2666 boolean use_invlet = (flags.invlet_constant
2667 && let != CONTAINED_SYM && let != HANDS_SYM);
2671 savequan = obj->quan;
2676 * - Then obj == null and 'txt' refers to hands or fingers.
2677 * * Then obj == null and we are printing a total amount.
2678 * > Then the object is contained and doesn't have an inventory letter.
2680 if (cost != 0 || let == '*') {
2681 /* if dot is true, we're doing Iu, otherwise Ix */
2684 iflags.menu_tab_sep ? "%c - %s\t%6ld %s"
2685 : "%c - %-45s %6ld %s",
2686 (dot && use_invlet ? obj->invlet : let),
2687 (txt ? txt : doname(obj)), cost, currency(cost));
2690 iflags.menu_tab_sep ? "%c - %s\t%6ld%s"
2691 : "%c - %-45s %6ld%s",
2692 (dot && use_invlet ? obj->invlet : let),
2693 (txt ? txt : doname(obj)), cost, currency(cost));
2696 /* ordinary inventory display or pickup message */
2697 Sprintf(li, "%c - %s%s", (use_invlet ? obj->invlet : let),
2699 (txt ? txt : doname(obj)), (dot ? "." : ""));
2701 (txt ? txt : doname(obj)), (dot ? "
\81D" : ""));
2704 obj->quan = savequan;
2709 /* the 'i' command */
2713 (void) display_inventory((char *) 0, FALSE);
2720 * Scan the given list of objects. If last_found is NULL, return the first
2721 * unpaid object found. If last_found is not NULL, then skip over unpaid
2722 * objects until last_found is reached, then set last_found to NULL so the
2723 * next unpaid object is returned. This routine recursively follows
2726 STATIC_OVL struct obj *
2727 find_unpaid(list, last_found)
2728 struct obj *list, **last_found;
2735 /* still looking for previous unpaid object */
2736 if (list == *last_found)
2737 *last_found = (struct obj *) 0;
2739 return ((*last_found = list));
2741 if (Has_contents(list)) {
2742 if ((obj = find_unpaid(list->cobj, last_found)) != 0)
2747 return (struct obj *) 0;
2750 /* for perm_invent when operating on a partial inventory display, so that
2751 the persistent one doesn't get shrunk during filtering for item selection
2752 then regrown to full inventory, possibly being resized in the process */
2753 static winid cached_pickinv_win = WIN_ERR;
2756 free_pickinv_cache()
2758 if (cached_pickinv_win != WIN_ERR) {
2759 destroy_nhwindow(cached_pickinv_win);
2760 cached_pickinv_win = WIN_ERR;
2765 * Internal function used by display_inventory and getobj that can display
2766 * inventory and return a count as well as a letter. If out_cnt is not null,
2767 * any count returned from the menu selection is placed here.
2770 display_pickinv(lets, xtra_choice, query, want_reply, out_cnt)
2771 register const char *lets;
2772 const char *xtra_choice; /* "fingers", pick hands rather than an object */
2778 static const char not_carrying_anything[] = "Not carrying anything";
2780 static const char not_carrying_anything[] = "
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢";
2781 struct obj *otmp, wizid_fakeobj;
2783 char *invlet = flags.inv_order;
2785 winid win; /* windows being used */
2787 menu_item *selected;
2789 Loot *sortedinvent, *srtinv;
2790 boolean wizid = (wizard && iflags.override_ID), gotsomething = FALSE;
2793 lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
2795 if (iflags.perm_invent && (lets || xtra_choice || wizid)) {
2796 /* partial inventory in perm_invent setting; don't operate on
2797 full inventory window, use an alternate one instead; create
2798 the first time needed and keep it for re-use as needed later */
2799 if (cached_pickinv_win == WIN_ERR)
2800 cached_pickinv_win = create_nhwindow(NHW_MENU);
2801 win = cached_pickinv_win;
2806 * Exit early if no inventory -- but keep going if we are doing
2807 * a permanent inventory update. We need to keep going so the
2808 * permanent inventory window updates itself to remove the last
2809 * item(s) dropped. One down side: the addition of the exception
2810 * for permanent inventory window updates _can_ pop the window
2811 * up when it's not displayed -- even if it's empty -- because we
2812 * don't know at this level if its up or not. This may not be
2813 * an issue if empty checks are done before hand and the call
2814 * to here is short circuited away.
2816 * 2: our count here is only to distinguish between 0 and 1 and
2817 * more than 1; for the last one, we don't need a precise number.
2818 * For perm_invent update we force 'more than 1'.
2820 n = (iflags.perm_invent && !lets && !want_reply) ? 2
2821 : lets ? (int) strlen(lets)
2822 : !invent ? 0 : !invent->nobj ? 1 : 2;
2823 /* for xtra_choice, there's another 'item' not included in initial 'n';
2824 for !lets (full invent) and for override_ID (wizard mode identify),
2825 skip message_menu handling of single item even if item count was 1 */
2826 if (xtra_choice || (n == 1 && (!lets || iflags.override_ID)))
2831 pline("%s.", not_carrying_anything);
2833 pline("%s
\81D", not_carrying_anything);
2837 /* oxymoron? temporarily assign permanent inventory letters */
2838 if (!flags.invlet_constant)
2841 if (n == 1 && !iflags.force_invmenu) {
2842 /* when only one item of interest, use pline instead of menus;
2843 we actually use a fake message-line menu in order to allow
2844 the user to perform selection at the --More-- prompt for tty */
2847 /* xtra_choice is "bare hands" (wield), "fingertip" (Engrave),
2848 "nothing" (ready Quiver), or "fingers" (apply grease) */
2849 ret = message_menu(HANDS_SYM, PICK_ONE,
2850 xprname((struct obj *) 0, xtra_choice,
2851 HANDS_SYM, TRUE, 0L, 0L)); /* '-' */
2853 for (otmp = invent; otmp; otmp = otmp->nobj)
2854 if (!lets || otmp->invlet == lets[0])
2857 ret = message_menu(otmp->invlet,
2858 want_reply ? PICK_ONE : PICK_NONE,
2859 xprname(otmp, (char *) 0, lets[0],
2863 *out_cnt = -1L; /* select all */
2867 sortflags = (flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET;
2869 sortflags |= SORTLOOT_PACK;
2870 sortedinvent = sortloot(&invent, sortflags, FALSE,
2871 (boolean FDECL((*), (OBJ_P))) 0);
2875 if (wizard && iflags.override_ID) {
2877 char prompt[QBUFSZ];
2879 unid_cnt = count_unidentified(invent);
2880 Sprintf(prompt, "Debug Identify"); /* 'title' rather than 'prompt' */
2882 Sprintf(eos(prompt),
2883 " -- unidentified or partially identified item%s",
2885 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, prompt, MENU_UNSELECTED);
2887 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
2888 "(all items are permanently identified already)",
2890 gotsomething = TRUE;
2892 any.a_obj = &wizid_fakeobj;
2893 Sprintf(prompt, "select %s to permanently identify",
2894 (unid_cnt == 1) ? "it": "any or all of them");
2895 /* wiz_identify stuffed the wiz_identify command character (^I)
2896 into iflags.override_ID for our use as an accelerator;
2897 it could be ambiguous if player has assigned a letter to
2898 the #wizidentify command, so include it as a group accelator
2899 but use '_' as the primary selector */
2901 Sprintf(eos(prompt), " (%s for all)",
2902 visctrl(iflags.override_ID));
2903 add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
2904 prompt, MENU_UNSELECTED);
2905 gotsomething = TRUE;
2907 } else if (xtra_choice) {
2908 /* wizard override ID and xtra_choice are mutually exclusive */
2910 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2911 "Miscellaneous", MENU_UNSELECTED);
2912 any.a_char = HANDS_SYM; /* '-' */
2913 add_menu(win, NO_GLYPH, &any, HANDS_SYM, 0, ATR_NONE,
2914 xtra_choice, MENU_UNSELECTED);
2915 gotsomething = TRUE;
2919 for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
2920 if (lets && !index(lets, otmp->invlet))
2922 if (!flags.sortpack || otmp->oclass == *invlet) {
2923 if (wizid && !not_fully_identified(otmp))
2925 any = zeroany; /* all bits zero */
2926 ilet = otmp->invlet;
2927 if (flags.sortpack && !classcount) {
2928 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2929 let_to_name(*invlet, FALSE,
2930 (want_reply && iflags.menu_head_objsym)),
2938 add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng), &any, ilet,
2939 wizid ? def_oc_syms[(int) otmp->oclass].sym : 0,
2940 ATR_NONE, doname(otmp), MENU_UNSELECTED);
2941 gotsomething = TRUE;
2944 if (flags.sortpack) {
2947 if (--invlet != venom_inv) {
2952 if (iflags.force_invmenu && lets && want_reply) {
2955 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2956 "Special", MENU_UNSELECTED);
2958 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2959 "
\93Á
\8eê", MENU_UNSELECTED);
2963 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
2964 "(list everything)", MENU_UNSELECTED);
2966 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
2967 "(
\91S
\82Ä
\82Ì
\88ê
\97\97)", MENU_UNSELECTED);
2969 gotsomething = TRUE;
2971 unsortloot(&sortedinvent);
2972 /* for permanent inventory where we intend to show everything but
2973 nothing has been listed (because there isn't anyhing to list;
2974 the n==0 case above gets skipped for perm_invent), put something
2976 if (iflags.perm_invent && !lets && !gotsomething) {
2978 add_menu(win, NO_GLYPH, &any, 0, 0, 0,
2979 not_carrying_anything, MENU_UNSELECTED);
2982 end_menu(win, query && *query ? query : (char *) 0);
2984 n = select_menu(win,
2985 wizid ? PICK_ANY : want_reply ? PICK_ONE : PICK_NONE,
2991 /* identifying items will update perm_invent, calling this
2992 routine recursively, and we don't want the nested call
2993 to filter on unID'd items */
2994 iflags.override_ID = 0;
2996 for (i = 0; i < n; ++i) {
2997 otmp = selected[i].item.a_obj;
2998 if (otmp == &wizid_fakeobj) {
2999 identify_pack(0, FALSE);
3001 if (not_fully_identified(otmp))
3002 (void) identify(otmp);
3006 ret = selected[0].item.a_char;
3008 *out_cnt = selected[0].count;
3010 free((genericptr_t) selected);
3012 ret = !n ? '\0' : '\033'; /* cancelled */
3018 * If lets == NULL or "", list all objects in the inventory. Otherwise,
3019 * list all objects with object classes that match the order in lets.
3021 * Returns the letter identifier of a selected item, or 0 if nothing
3025 display_inventory(lets, want_reply)
3029 return display_pickinv(lets, (char *) 0, (char *) 0,
3030 want_reply, (long *) 0);
3034 * Show what is current using inventory letters.
3038 display_used_invlets(avoidlet)
3043 char *invlet = flags.inv_order;
3044 int n, classcount, invdone = 0;
3047 menu_item *selected;
3050 win = create_nhwindow(NHW_MENU);
3053 any = zeroany; /* set all bits to zero */
3055 for (otmp = invent; otmp; otmp = otmp->nobj) {
3056 ilet = otmp->invlet;
3057 if (ilet == avoidlet)
3059 if (!flags.sortpack || otmp->oclass == *invlet) {
3060 if (flags.sortpack && !classcount) {
3061 any = zeroany; /* zero */
3062 add_menu(win, NO_GLYPH, &any, 0, 0,
3063 iflags.menu_headings,
3064 let_to_name(*invlet, FALSE, FALSE),
3069 add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng),
3070 &any, ilet, 0, ATR_NONE,
3071 doname(otmp), MENU_UNSELECTED);
3074 if (flags.sortpack && *++invlet)
3078 end_menu(win, "Inventory letters used:");
3080 n = select_menu(win, PICK_ONE, &selected);
3082 ret = selected[0].item.a_char;
3083 free((genericptr_t) selected);
3085 ret = !n ? '\0' : '\033'; /* cancelled */
3086 destroy_nhwindow(win);
3092 * Returns the number of unpaid items within the given list. This includes
3093 * contained objects.
3104 if (Has_contents(list))
3105 count += count_unpaid(list->cobj);
3112 * Returns the number of items with b/u/c/unknown within the given list.
3113 * This does NOT include contained objects.
3115 * Assumes that the hero sees or touches or otherwise senses the objects
3116 * at some point: bknown is forced for priest[ess], like in xname().
3119 count_buc(list, type, filterfunc)
3122 boolean FDECL((*filterfunc), (OBJ_P));
3126 for (; list; list = list->nobj) {
3127 /* priests always know bless/curse state */
3128 if (Role_if(PM_PRIEST))
3129 list->bknown = (list->oclass != COIN_CLASS);
3130 /* some actions exclude some or most items */
3131 if (filterfunc && !(*filterfunc)(list))
3134 /* coins are either uncursed or unknown based upon option setting */
3135 if (list->oclass == COIN_CLASS) {
3136 if (type == (iflags.goldX ? BUC_UNKNOWN : BUC_UNCURSED))
3140 /* check whether this object matches the requested type */
3142 ? (type == BUC_UNKNOWN)
3143 : list->blessed ? (type == BUC_BLESSED)
3144 : list->cursed ? (type == BUC_CURSED)
3145 : (type == BUC_UNCURSED))
3151 /* similar to count_buc(), but tallies all states at once
3152 rather than looking for a specific type */
3154 tally_BUCX(list, by_nexthere, bcp, ucp, ccp, xcp, ocp)
3156 boolean by_nexthere;
3157 int *bcp, *ucp, *ccp, *xcp, *ocp;
3159 /* Future extensions:
3160 * Skip current_container when list is invent, uchain when
3161 * first object of list is located on the floor. 'ocp' will then
3162 * have a function again (it was a counter for having skipped gold,
3163 * but that's not skipped anymore).
3165 *bcp = *ucp = *ccp = *xcp = *ocp = 0;
3166 for ( ; list; list = (by_nexthere ? list->nexthere : list->nobj)) {
3167 /* priests always know bless/curse state */
3168 if (Role_if(PM_PRIEST))
3169 list->bknown = (list->oclass != COIN_CLASS);
3170 /* coins are either uncursed or unknown based upon option setting */
3171 if (list->oclass == COIN_CLASS) {
3178 /* ordinary items */
3181 else if (list->blessed)
3183 else if (list->cursed)
3185 else /* neither blessed nor cursed => uncursed */
3190 /* count everything inside a container, or just shop-owned items inside */
3192 count_contents(container, nested, quantity, everything, newdrop)
3193 struct obj *container;
3194 boolean nested, /* include contents of any nested containers */
3195 quantity, /* count all vs count separate stacks */
3196 everything, /* all objects vs only unpaid objects */
3197 newdrop; /* on floor, but hero-owned items haven't been marked
3198 * no_charge yet and shop-owned items are still marked
3199 * unpaid -- used when asking the player whether to sell */
3201 struct obj *otmp, *topc;
3202 boolean shoppy = FALSE;
3205 if (!everything && !newdrop) {
3208 for (topc = container; topc->where == OBJ_CONTAINED;
3209 topc = topc->ocontainer)
3211 if (topc->where == OBJ_FLOOR && get_obj_location(topc, &x, &y, 0))
3212 shoppy = costly_spot(x, y);
3214 for (otmp = container->cobj; otmp; otmp = otmp->nobj) {
3215 if (nested && Has_contents(otmp))
3216 count += count_contents(otmp, nested, quantity, everything,
3218 if (everything || otmp->unpaid || (shoppy && !otmp->no_charge))
3219 count += quantity ? otmp->quan : 1L;
3228 struct obj *otmp, *marker, *contnr;
3230 char *invlet = flags.inv_order;
3231 int classcount, count, num_so_far;
3234 count = count_unpaid(invent);
3235 otmp = marker = contnr = (struct obj *) 0;
3238 otmp = find_unpaid(invent, &marker);
3239 contnr = unknwn_contnr_contents(otmp);
3241 if (otmp && !contnr) {
3242 /* 1 item; use pline instead of popup menu */
3243 cost = unpaid_cost(otmp, FALSE);
3244 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
3245 pline1(xprname(otmp, distant_name(otmp, doname),
3246 carried(otmp) ? otmp->invlet : CONTAINED_SYM,
3248 iflags.suppress_price--;
3252 win = create_nhwindow(NHW_MENU);
3254 num_so_far = 0; /* count of # printed so far */
3255 if (!flags.invlet_constant)
3260 for (otmp = invent; otmp; otmp = otmp->nobj) {
3261 ilet = otmp->invlet;
3263 if (!flags.sortpack || otmp->oclass == *invlet) {
3264 if (flags.sortpack && !classcount) {
3265 putstr(win, 0, let_to_name(*invlet, TRUE, FALSE));
3269 totcost += cost = unpaid_cost(otmp, FALSE);
3270 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
3271 putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
3272 ilet, TRUE, cost, 0L));
3273 iflags.suppress_price--;
3278 } while (flags.sortpack && (*++invlet));
3280 if (count > num_so_far) {
3281 /* something unpaid is contained */
3283 putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE, FALSE));
3285 * Search through the container objects in the inventory for
3286 * unpaid items. The top level inventory items have already
3289 for (otmp = invent; otmp; otmp = otmp->nobj) {
3290 if (Has_contents(otmp)) {
3293 marker = (struct obj *) 0; /* haven't found any */
3294 while (find_unpaid(otmp->cobj, &marker)) {
3295 totcost += cost = unpaid_cost(marker, FALSE);
3298 iflags.suppress_price++; /* suppress "(unpaid)" sfx */
3300 xprname(marker, distant_name(marker, doname),
3301 CONTAINED_SYM, TRUE, cost, 0L));
3302 iflags.suppress_price--;
3305 if (!otmp->cknown) {
3306 char contbuf[BUFSZ];
3308 /* Shopkeeper knows what to charge for contents */
3310 Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
3312 Sprintf(contbuf, "%s
\82Ì
\92\86\90g", xname(otmp));
3314 xprname((struct obj *) 0, contbuf, CONTAINED_SYM,
3315 TRUE, contcost, 0L));
3324 xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
3327 xprname((struct obj *) 0, "
\8d\87\8cv
\81F", '*', FALSE, totcost, 0L));
3329 display_nhwindow(win, FALSE);
3330 destroy_nhwindow(win);
3333 /* query objlist callback: return TRUE if obj type matches "this_type" */
3334 static int this_type;
3340 boolean res = (obj->oclass == this_type);
3342 if (obj->oclass == COIN_CLASS) {
3343 /* if filtering by bless/curse state, gold is classified as
3344 either unknown or uncursed based on user option setting */
3345 if (this_type && index("BUCX", this_type))
3346 res = (this_type == (iflags.goldX ? 'X' : 'U'));
3348 switch (this_type) {
3350 res = (obj->bknown && obj->blessed);
3353 res = (obj->bknown && !(obj->blessed || obj->cursed));
3356 res = (obj->bknown && obj->cursed);
3362 break; /* use 'res' as-is */
3368 /* the 'I' command */
3374 char *extra_types, types[BUFSZ];
3375 int class_count, oclass, unpaid_count, itemcount;
3376 int bcnt, ccnt, ucnt, xcnt, ocnt;
3377 boolean billx = *u.ushops && doinvbill(0);
3378 menu_item *pick_list;
3379 boolean traditional = TRUE;
3381 const char *prompt = "What type of object do you want an inventory of?";
3383 const char *prompt = "
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\8e\9d\82¿
\95¨
\82ð
\8c©
\82Ü
\82·
\82©
\81H";
3385 if (!invent && !billx) {
3387 You("aren't carrying anything.");
3389 You("
\82»
\82Ì
\8eí
\97Þ
\82Ì
\95¨
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3392 unpaid_count = count_unpaid(invent);
3393 tally_BUCX(invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
3395 if (flags.menu_style != MENU_TRADITIONAL) {
3396 if (flags.menu_style == MENU_FULL
3397 || flags.menu_style == MENU_PARTIAL) {
3398 traditional = FALSE;
3410 n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
3413 this_type = c = pick_list[0].item.a_int;
3414 free((genericptr_t) pick_list);
3418 /* collect a list of classes of objects carried, for use as a prompt
3421 class_count = collect_obj_classes(types, invent, FALSE,
3422 (boolean FDECL((*), (OBJ_P))) 0,
3424 if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
3425 types[class_count++] = ' ';
3427 types[class_count++] = 'u';
3429 types[class_count++] = 'x';
3431 types[class_count++] = 'B';
3433 types[class_count++] = 'U';
3435 types[class_count++] = 'C';
3437 types[class_count++] = 'X';
3438 types[class_count] = '\0';
3439 /* add everything not already included; user won't see these */
3440 extra_types = eos(types);
3441 *extra_types++ = '\033';
3443 *extra_types++ = 'u';
3445 *extra_types++ = 'x';
3447 *extra_types++ = 'B';
3449 *extra_types++ = 'U';
3451 *extra_types++ = 'C';
3453 *extra_types++ = 'X';
3454 *extra_types = '\0'; /* for index() */
3455 for (i = 0; i < MAXOCLASSES; i++)
3456 if (!index(types, def_oc_syms[i].sym)) {
3457 *extra_types++ = def_oc_syms[i].sym;
3458 *extra_types = '\0';
3461 if (class_count > 1) {
3462 c = yn_function(prompt, types, '\0');
3465 clear_nhwindow(WIN_MESSAGE);
3469 /* only one thing to itemize */
3478 if (c == 'x' || (c == 'X' && billx && !xcnt)) {
3480 (void) doinvbill(1);
3483 pline("No used-up objects%s.",
3484 unpaid_count ? " on your shopping bill" : "");
3486 pline("
\8eg
\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\95¨
\82Í%s
\82È
\82¢
\81D",
3487 unpaid_count ? "
\8f¤
\93X
\82Ì
\90¿
\8b\81\8f\91\82É
\82Í" : "");
3491 if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
3496 You("are not carrying any unpaid objects.");
3498 You("
\96¢
\95¥
\82¢
\82Ì
\83A
\83C
\83e
\83\80\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3502 if (index("BUCX", c))
3503 oclass = c; /* not a class but understood by this_type_only() */
3505 oclass = def_char_to_objclass(c); /* change to object class */
3507 if (oclass == COIN_CLASS)
3509 if (index(types, c) > index(types, '\033')) {
3510 /* '> ESC' => hidden choice, something known not to be carried */
3511 const char *before = "", *after = "";
3516 before = "known to be blessed ";
3518 before = "
\8fj
\95\9f\82³
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3522 before = "known to be uncursed ";
3524 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3528 before = "known to be cursed ";
3530 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3534 after = " whose blessed/uncursed/cursed status is unknown";
3536 after = "
\8fj
\95\9f\81^
\8eô
\82¢
\82ª
\82í
\82©
\82ç
\82È
\82¢";
3537 break; /* better phrasing is desirable */
3539 /* 'c' is an object class, because we've already handled
3540 all the non-class letters which were put into 'types[]';
3541 could/should move object class names[] array from below
3542 to somewhere above so that we can access it here (via
3543 lcase(strcpy(classnamebuf, names[(int) c]))), but the
3544 game-play value of doing so is low... */
3548 before = "
\82»
\82Ì
\82æ
\82¤
\82È";
3552 You("have no %sobjects%s.", before, after);
3554 You("%s%s
\82à
\82Ì
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", before, after);
3559 if (query_objlist((char *) 0, &invent,
3560 ((flags.invlet_constant ? USE_INVLET : 0)
3562 &pick_list, PICK_NONE, this_type_only) > 0)
3563 free((genericptr_t) pick_list);
3567 /* return a string describing the dungeon feature at <x,y> if there
3568 is one worth mentioning at that location; otherwise null */
3570 dfeature_at(x, y, buf)
3574 struct rm *lev = &levl[x][y];
3575 int ltyp = lev->typ, cmap = -1;
3576 const char *dfeature = 0;
3577 static char altbuf[BUFSZ];
3579 if (IS_DOOR(ltyp)) {
3580 switch (lev->doormask) {
3583 break; /* "doorway" */
3586 break; /* "open door" */
3589 dfeature = "broken door";
3591 dfeature = "
\89ó
\82ê
\82½
\94à";
3595 break; /* "closed door" */
3597 /* override door description for open drawbridge */
3598 if (is_drawbridge_wall(x, y) >= 0)
3600 dfeature = "open drawbridge portcullis", cmap = -1;
3602 dfeature = "
\8d~
\82è
\82Ä
\82¢
\82é
\92µ
\82Ë
\8b´", cmap = -1;
3603 } else if (IS_FOUNTAIN(ltyp))
3604 cmap = S_fountain; /* "fountain" */
3605 else if (IS_THRONE(ltyp))
3606 cmap = S_throne; /* "opulent throne" */
3607 else if (is_lava(x, y))
3608 cmap = S_lava; /* "molten lava" */
3609 else if (is_ice(x, y))
3610 cmap = S_ice; /* "ice" */
3611 else if (is_pool(x, y))
3613 dfeature = "pool of water";
3615 dfeature = "
\90\85\82½
\82Ü
\82è";
3616 else if (IS_SINK(ltyp))
3617 cmap = S_sink; /* "sink" */
3618 else if (IS_ALTAR(ltyp)) {
3620 Sprintf(altbuf, "%saltar to %s (%s)",
3621 ((lev->altarmask & AM_SHRINE)
3622 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3626 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3628 Sprintf(altbuf, "%s%s
\82Ì
\8dÕ
\92d(%s)",
3629 ((lev->altarmask & AM_SHRINE)
3630 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3634 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3637 } else if ((x == xupstair && y == yupstair)
3638 || (x == sstairs.sx && y == sstairs.sy && sstairs.up))
3639 cmap = S_upstair; /* "staircase up" */
3640 else if ((x == xdnstair && y == ydnstair)
3641 || (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
3642 cmap = S_dnstair; /* "staircase down" */
3643 else if (x == xupladder && y == yupladder)
3644 cmap = S_upladder; /* "ladder up" */
3645 else if (x == xdnladder && y == ydnladder)
3646 cmap = S_dnladder; /* "ladder down" */
3647 else if (ltyp == DRAWBRIDGE_DOWN)
3648 cmap = S_vodbridge; /* "lowered drawbridge" */
3649 else if (ltyp == DBWALL)
3650 cmap = S_vcdbridge; /* "raised drawbridge" */
3651 else if (IS_GRAVE(ltyp))
3652 cmap = S_grave; /* "grave" */
3653 else if (ltyp == TREE)
3654 cmap = S_tree; /* "tree" */
3655 else if (ltyp == IRONBARS)
3657 dfeature = "set of iron bars";
3659 dfeature = "
\93S
\82Ì
\96_";
3662 dfeature = defsyms[cmap].explanation;
3664 Strcpy(buf, dfeature);
3668 /* look at what is here; if there are many objects (pile_limit or more),
3669 don't show them unless obj_cnt is 0 */
3671 look_here(obj_cnt, picked_some)
3672 int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progress */
3673 boolean picked_some;
3678 const char *verb = Blind ? "feel" : "see";
3680 const char *verb = Blind ? "
\82ª
\82 \82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½" : "
\82ð
\82Ý
\82Â
\82¯
\82½";
3682 const char *dfeature = (char *) 0;
3683 char fbuf[BUFSZ], fbuf2[BUFSZ];
3685 boolean skip_objects, felt_cockatrice = FALSE;
3687 /* default pile_limit is 5; a value of 0 means "never skip"
3688 (and 1 effectively forces "always skip") */
3689 skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
3690 if (u.uswallow && u.ustuck) {
3691 struct monst *mtmp = u.ustuck;
3695 * Engulfer's inventory can include worn items (specific case is
3696 * Juiblex being created with an amulet as random defensive item)
3697 * which will be flagged as "(being worn)". This code includes
3698 * such a worn item under the header "Contents of <mon>'s stomach",
3699 * a nifty trick for how/where to wear stuff. The situation is
3700 * rare enough to turn a blind eye.
3702 * 3.6.3: Pickup has been changed to decline to pick up a worn
3703 * item from inside an engulfer, but if player tries, it just
3704 * says "you can't" without giving a reason why (which would be
3705 * something along the lines of "because it's worn on the outside
3706 * so is unreachable from in here...").
3709 Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
3710 mbodypart(mtmp, STOMACH));
3712 Sprintf(fbuf, "%s
\82Ì%s
\82Ì
\92\86\90g", mon_nam(mtmp),
3713 mbodypart(mtmp, STOMACH));
3715 #if 0 /*JP*//*
\8cê
\8f\87\82ª
\88á
\82¤
\82Ì
\82Å
\91f
\92¼
\82É*/
3716 /* Skip "Contents of " by using fbuf index 12 */
3717 You("%s to %s what is lying in %s.", Blind ? "try" : "look around",
3720 You("%s
\82Ì%s
\82É
\89½
\82ª
\82 \82é
\82©%s
\81D",
3721 mon_nam(mtmp), mbodypart(mtmp, STOMACH),
3722 Blind ? "
\82³
\82®
\82Á
\82½" : "
\8c©
\89ñ
\82µ
\82½");
3724 otmp = mtmp->minvent;
3726 for (; otmp; otmp = otmp->nobj) {
3727 /* If swallower is an animal, it should have become stone
3729 if (otmp->otyp == CORPSE)
3730 feel_cockatrice(otmp, FALSE);
3734 Strcpy(fbuf, "You feel");
3737 Sprintf(fbuf, "
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F", Blind ? "
\82ç
\82µ
\82¢" : "");
3739 (void) display_minventory(mtmp, MINV_ALL | PICK_NONE, fbuf);
3742 You("%s no objects here.", verb);
3744 pline(Blind ? "
\82 \82È
\82½
\82Í
\89½
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D"
3745 : "
\82 \82È
\82½
\82Í
\89½
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3750 if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen)
3752 There("is %s here.",
3754 pline("
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D",
3755 an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
3757 otmp = level.objects[u.ux][u.uy];
3758 dfeature = dfeature_at(u.ux, u.uy, fbuf2);
3760 if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
3762 if (dfeature && !strcmp(dfeature, "
\90\85\82½
\82Ü
\82è") && Underwater)
3766 boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
3769 if (dfeature && !strncmp(dfeature, "altar ", 6)) {
3771 if (dfeature && !strncmp(dfeature, "
\8dÕ
\92d", 4)) {
3772 /* don't say "altar" twice, dfeature has more info */
3774 You("try to feel what is here.");
3776 You("
\82±
\82±
\82É
\89½
\82ª
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3779 const char *where = (Blind && !can_reach_floor(TRUE))
3780 ? "lying beneath you"
3781 : "lying here on the ",
3782 *onwhat = (Blind && !can_reach_floor(TRUE))
3784 : surface(u.ux, u.uy);
3786 You("try to feel what is %s%s.", drift ? "floating here" : where,
3787 drift ? "" : onwhat);
3790 You("
\89½
\82ª
\95\82\82¢
\82Ä
\82¢
\82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3791 } else if (Blind && !can_reach_floor(TRUE)) {
3792 You("
\89½
\82ª
\91«
\89º
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3794 You("
\89½
\82ª%s
\82Ì
\8fã
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D", surface(u.ux, u.uy));
3798 if (dfeature && !drift && !strcmp(dfeature, surface(u.ux, u.uy)))
3799 dfeature = 0; /* ice already identified */
3800 if (!can_reach_floor(TRUE)) {
3802 pline("But you can't reach it!");
3804 pline("
\82µ
\82©
\82µ
\93Í
\82©
\82È
\82¢
\81I");
3811 Sprintf(fbuf, "There is %s here.", an(dfeature));
3813 Sprintf(fbuf, "
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D", an(dfeature));
3815 if (!otmp || is_lava(u.ux, u.uy)
3816 || (is_pool(u.ux, u.uy) && !Underwater)) {
3819 read_engr_at(u.ux, u.uy); /* Eric Backus */
3820 if (!skip_objects && (Blind || !dfeature))
3822 You("%s no objects here.", verb);
3825 "
\82È
\82É
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82·
\82é
\81D" :
3826 "
\82È
\82É
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3830 /* we know there is something here */
3835 read_engr_at(u.ux, u.uy); /* Eric Backus */
3836 if (obj_cnt == 1 && otmp->quan == 1L)
3838 There("is %s object here.", picked_some ? "another" : "an");
3840 There("
\82±
\82±
\82É
\82Í%s
\88ê
\82Â
\82à
\82Ì
\82ª
\82 \82é
\81D", picked_some ? "
\82à
\82¤" : "");
3843 There("are %s%s objects here.",
3849 picked_some ? " more" : "");
3851 pline("
\82±
\82±
\82É
\82Í%s%s
\82à
\82Ì
\82ª
\82 \82é
\81D",
3852 picked_some ? "
\82³
\82ç
\82É" : "",
3854 ? "
\82¢
\82
\82Â
\82©
\82Ì"
3855 : "
\82½
\82
\82³
\82ñ
\82Ì");
3857 for (; otmp; otmp = otmp->nexthere)
3858 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3859 #if 0 /*JP*//*"It's (corpse_name), unfortunately"*/
3866 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3867 poly_when_stoned(youmonst.data)
3869 : ", unfortunately");
3872 poly_when_stoned(youmonst.data)
3874 : "
\8ec
\94O
\82È
\82ª
\82ç",
3875 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3877 ? "
\82ð
\8aÜ
\82ñ
\82Å
\82¢
\82é"
3880 feel_cockatrice(otmp, FALSE);
3883 } else if (!otmp->nexthere) {
3884 /* only one object */
3887 read_engr_at(u.ux, u.uy); /* Eric Backus */
3889 You("%s here %s.", verb, doname_with_price(otmp));
3891 pline("%s%s
\81D", doname_with_price(otmp), verb);
3892 iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
3893 if (otmp->otyp == CORPSE)
3894 feel_cockatrice(otmp, FALSE);
3898 display_nhwindow(WIN_MESSAGE, FALSE);
3899 tmpwin = create_nhwindow(NHW_MENU);
3901 putstr(tmpwin, 0, fbuf);
3902 putstr(tmpwin, 0, "");
3905 Sprintf(buf, "%s that %s here:",
3906 picked_some ? "Other things" : "Things",
3907 Blind ? "you feel" : "are");
3909 Sprintf(buf, "%s
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F",
3910 picked_some ? "
\91¼
\82É" : "",
3911 Blind ? "
\82ç
\82µ
\82¢" : "");
3913 putstr(tmpwin, 0, buf);
3914 for (; otmp; otmp = otmp->nexthere) {
3915 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3916 felt_cockatrice = TRUE;
3918 Sprintf(buf, "%s...", doname(otmp));
3920 Sprintf(buf, "%s
\81D
\81D
\81D", doname(otmp));
3921 putstr(tmpwin, 0, buf);
3924 putstr(tmpwin, 0, doname_with_price(otmp));
3926 display_nhwindow(tmpwin, TRUE);
3927 destroy_nhwindow(tmpwin);
3928 if (felt_cockatrice)
3929 feel_cockatrice(otmp, FALSE);
3930 read_engr_at(u.ux, u.uy); /* Eric Backus */
3935 /* the ':' command - explicitly look at what is here, including all objects */
3942 MSGTYPE={norep,noshow} "You see here"
3943 interfere with feedback from the look-here command */
3944 hide_unhide_msgtypes(TRUE, MSGTYP_MASK_REP_SHOW);
3945 res = look_here(0, FALSE);
3946 /* restore normal msgtype handling */
3947 hide_unhide_msgtypes(FALSE, MSGTYP_MASK_REP_SHOW);
3952 will_feel_cockatrice(otmp, force_touch)
3954 boolean force_touch;
3956 if ((Blind || force_touch) && !uarmg && !Stone_resistance
3957 && (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
3963 feel_cockatrice(otmp, force_touch)
3965 boolean force_touch;
3969 if (will_feel_cockatrice(otmp, force_touch)) {
3970 /* "the <cockatrice> corpse" */
3971 Strcpy(kbuf, corpse_xname(otmp, (const char *) 0, CXN_PFX_THE));
3973 if (poly_when_stoned(youmonst.data))
3975 You("touched %s with your bare %s.", kbuf,
3976 makeplural(body_part(HAND)));
3978 You("%s
\82Ì
\8e\80\91Ì
\82É
\91f%s
\82Å
\90G
\82Á
\82½
\81D", kbuf,
3983 pline("Touching %s is a fatal mistake...", kbuf);
3985 pline("%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82é
\82Ì
\82Í
\92v
\96½
\93I
\82È
\8aÔ
\88á
\82¢
\82¾
\81D
\81D
\81D", kbuf);
3986 /* normalize body shape here; hand, not body_part(HAND) */
3988 Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
3990 Sprintf(kbuf, "%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82Ä", killer_xname(otmp));
3991 /* will call polymon() for the poly_when_stoned() case */
4002 for (otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
4003 if (otmp != obj && merged(&obj, &otmp))
4008 /* returns TRUE if obj & otmp can be merged; used in invent.c and mkobj.c */
4011 register struct obj *otmp, *obj;
4013 int objnamelth = 0, otmpnamelth = 0;
4015 /* fail if already the same object, if different types, if either is
4016 explicitly marked to prevent merge, or if not mergable in general */
4017 if (obj == otmp || obj->otyp != otmp->otyp
4018 || obj->nomerge || otmp->nomerge || !objects[obj->otyp].oc_merge)
4021 /* coins of the same kind will always merge */
4022 if (obj->oclass == COIN_CLASS)
4025 if (obj->bypass != otmp->bypass
4026 || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed)
4031 /* Checks beyond this point either aren't applicable to globs
4032 * or don't inhibit their merger.
4035 if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
4036 || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
4037 || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit)
4040 if (obj->oclass == FOOD_CLASS
4041 && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
4044 if (obj->dknown != otmp->dknown
4045 || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
4046 || obj->oeroded != otmp->oeroded || obj->oeroded2 != otmp->oeroded2
4047 || obj->greased != otmp->greased)
4050 if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
4051 && (obj->oerodeproof != otmp->oerodeproof
4052 || obj->rknown != otmp->rknown))
4055 if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
4056 if (obj->corpsenm != otmp->corpsenm)
4060 /* hatching eggs don't merge; ditto for revivable corpses */
4061 if ((obj->otyp == EGG && (obj->timed || otmp->timed))
4062 || (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM
4063 && is_reviver(&mons[otmp->corpsenm])))
4066 /* allow candle merging only if their ages are close */
4067 /* see begin_burn() for a reference for the magic "25" */
4068 if (Is_candle(obj) && obj->age / 25 != otmp->age / 25)
4071 /* burning potions of oil never merge */
4072 if (obj->otyp == POT_OIL && obj->lamplit)
4075 /* don't merge surcharged item with base-cost item */
4076 if (obj->unpaid && !same_price(obj, otmp))
4079 /* if they have names, make sure they're the same */
4080 objnamelth = strlen(safe_oname(obj));
4081 otmpnamelth = strlen(safe_oname(otmp));
4082 if ((objnamelth != otmpnamelth
4083 && ((objnamelth && otmpnamelth) || obj->otyp == CORPSE))
4084 || (objnamelth && otmpnamelth
4085 && strncmp(ONAME(obj), ONAME(otmp), objnamelth)))
4088 /* for the moment, any additional information is incompatible */
4089 if (has_omonst(obj) || has_omid(obj) || has_olong(obj) || has_omonst(otmp)
4090 || has_omid(otmp) || has_olong(otmp))
4093 if (obj->oartifact != otmp->oartifact)
4096 if (obj->known == otmp->known || !objects[otmp->otyp].oc_uses_known) {
4097 return (boolean) objects[obj->otyp].oc_merge;
4102 /* the '$' command */
4106 /* the messages used to refer to "carrying gold", but that didn't
4107 take containers into account */
4108 long umoney = money_cnt(invent);
4112 Your("wallet is empty.");
4114 Your("
\8dà
\95z
\82Í
\8bó
\82Á
\82Û
\82¾
\81D");
4117 Your("wallet contains %ld %s.", umoney, currency(umoney));
4119 Your("
\8dà
\95z
\82É
\82Í%ld%s
\93ü
\82Á
\82Ä
\82¢
\82é
\81D", umoney, currency(umoney));
4120 shopper_financial_report();
4124 /* the ')' command */
4130 You("are empty %s.", body_part(HANDED));
4132 if(!uwep) You("%s
\82É
\95\90\8aí
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D", body_part(HAND));
4134 prinv((char *) 0, uwep, 0L);
4136 prinv((char *) 0, uswapwep, 0L);
4141 /* caller is responsible for checking !wearing_armor() */
4143 noarmor(report_uskin)
4144 boolean report_uskin;
4146 if (!uskin || !report_uskin) {
4148 You("are not wearing any armor.");
4150 You("
\8aZ
\82ð
\92\85\82Ä
\82¢
\82È
\82¢
\81D");
4152 char *p, *uskinname, buf[BUFSZ];
4154 uskinname = strcpy(buf, simpleonames(uskin));
4156 /* shorten "set of <color> dragon scales" to "<color> scales"
4157 and "<color> dragon scale mail" to "<color> scale mail" */
4158 if (!strncmpi(uskinname, "set of ", 7))
4160 if ((p = strstri(uskinname, " dragon ")) != 0)
4161 while ((p[1] = p[8]) != '\0')
4163 #else /*
\81u<
\90F>
\83h
\83\89\83S
\83\93\82Ì
\97Ø
\81v
\82ð
\81u<
\90F>
\82Ì
\97Ø
\81v
\82É
\82·
\82é*/
4164 if ((p = strstri(uskinname, "
\83h
\83\89\83S
\83\93\82Ì
\97Ø")) != 0)
4169 You("are not wearing armor but have %s embedded in your skin.",
4171 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",
4176 /* the '[' command */
4181 register int ct = 0;
4183 * Note: players sometimes get here by pressing a function key which
4184 * transmits ''ESC [ <something>'' rather than by pressing '[';
4185 * there's nothing we can--or should-do about that here.
4188 if (!wearing_armor()) {
4192 lets[ct++] = obj_to_let(uarmu);
4194 lets[ct++] = obj_to_let(uarm);
4196 lets[ct++] = obj_to_let(uarmc);
4198 lets[ct++] = obj_to_let(uarmh);
4200 lets[ct++] = obj_to_let(uarms);
4202 lets[ct++] = obj_to_let(uarmg);
4204 lets[ct++] = obj_to_let(uarmf);
4206 (void) display_inventory(lets, FALSE);
4211 /* the '=' command */
4215 if (!uleft && !uright)
4217 You("are not wearing any rings.");
4219 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
4222 register int ct = 0;
4225 lets[ct++] = obj_to_let(uleft);
4227 lets[ct++] = obj_to_let(uright);
4229 (void) display_inventory(lets, FALSE);
4234 /* the '"' command */
4240 You("are not wearing an amulet.");
4242 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
4244 prinv((char *) 0, uamul, 0L);
4252 if ((obj->owornmask & (W_TOOL | W_SADDLE)) != 0L)
4254 if (obj->oclass != TOOL_CLASS)
4256 return (boolean) (obj == uwep || obj->lamplit
4257 || (obj->otyp == LEASH && obj->leashmon));
4260 /* the '(' command */
4268 for (otmp = invent; otmp; otmp = otmp->nobj)
4269 if (tool_in_use(otmp))
4270 lets[ct++] = obj_to_let(otmp);
4274 You("are not using any tools.");
4276 You("
\8eg
\82¦
\82é
\93¹
\8bï
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4278 (void) display_inventory(lets, FALSE);
4282 /* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
4283 show inventory of all currently wielded, worn, or used objects */
4291 for (otmp = invent; otmp; otmp = otmp->nobj)
4292 if (is_worn(otmp) || tool_in_use(otmp))
4293 lets[ct++] = obj_to_let(otmp);
4297 You("are not wearing or wielding anything.");
4299 You("
\89½
\82à
\92\85\82Ä
\82¢
\82È
\82¢
\82µ
\81C
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
4301 (void) display_inventory(lets, FALSE);
4306 * uses up an object that's on the floor, charging for it as necessary
4309 useupf(obj, numused)
4310 register struct obj *obj;
4313 register struct obj *otmp;
4314 boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
4316 /* burn_floor_objects() keeps an object pointer that it tries to
4317 * useupf() multiple times, so obj must survive if plural */
4318 if (obj->quan > numused)
4319 otmp = splitobj(obj, numused);
4322 if (costly_spot(otmp->ox, otmp->oy)) {
4323 if (index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
4324 addtobill(otmp, FALSE, FALSE, FALSE);
4326 (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
4329 if (at_u && u.uundetected && hides_under(youmonst.data))
4330 (void) hideunder(&youmonst);
4334 * Conversion from a class to a string for printing.
4335 * This must match the object class order.
4337 STATIC_VAR NEARDATA const char *names[] = {
4339 0, "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", "Tools",
4340 "Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
4341 "Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
4343 0, "
\96
\82È
\95¨
\91Ì", "
\95\90\8aí", "
\8aZ", "
\8ew
\97Ö", "
\96\82\8f\9c\82¯", "
\93¹
\8bï",
4344 "
\90H
\97¿", "
\96ò", "
\8aª
\95¨", "
\96\82\96@
\8f\91", "
\8fñ", "
\8bà
\89Ý",
4345 "
\95ó
\90Î", "
\8aâ
\82Ü
\82½
\82Í
\92¤
\91\9c", "
\93S
\8b\85", "
\8d½", "
\93Å"
4348 STATIC_VAR NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
4350 STATIC_VAR NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
4352 STATIC_VAR NEARDATA const char *oth_names[] = { "
\8bl
\82ß
\82ç
\82ê
\82½
\93¹
\8bï" };
4354 STATIC_VAR NEARDATA char *invbuf = (char *) 0;
4355 STATIC_VAR NEARDATA unsigned invbufsiz = 0;
4358 let_to_name(let, unpaid, showsym)
4360 boolean unpaid, showsym;
4362 const char *ocsymfmt = " ('%c')";
4363 const int invbuf_sympadding = 8; /* arbitrary */
4364 const char *class_name;
4366 int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
4370 class_name = names[oclass];
4371 else if ((pos = index(oth_symbols, let)) != 0)
4372 class_name = oth_names[pos - oth_symbols];
4374 class_name = names[0];
4377 len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "")
4379 len = strlen(class_name) + (unpaid ? sizeof "
\96¢
\95¥
\82¢
\82Ì" : sizeof "")
4380 + (oclass ? (strlen(ocsymfmt) + invbuf_sympadding) : 0);
4381 if (len > invbufsiz) {
4383 free((genericptr_t) invbuf);
4384 invbufsiz = len + 10; /* add slop to reduce incremental realloc */
4385 invbuf = (char *) alloc(invbufsiz);
4389 Strcat(strcpy(invbuf, "Unpaid "), class_name);
4391 Strcat(strcpy(invbuf, "
\96¢
\95¥
\82¢
\82Ì"), class_name);
4393 Strcpy(invbuf, class_name);
4394 if ((oclass != 0) && showsym) {
4395 char *bp = eos(invbuf);
4396 int mlen = invbuf_sympadding - strlen(class_name);
4397 while (--mlen > 0) {
4402 Sprintf(eos(invbuf), ocsymfmt, def_oc_syms[oclass].sym);
4407 /* release the static buffer used by let_to_name() */
4412 free((genericptr_t) invbuf), invbuf = (char *) 0;
4416 /* give consecutive letters to every item in inventory (for !fixinv mode);
4417 gold is always forced to '$' slot at head of list */
4422 struct obj *obj, *prevobj, *goldobj;
4424 /* first, remove [first instance of] gold from invent, if present */
4425 prevobj = goldobj = 0;
4426 for (obj = invent; obj; prevobj = obj, obj = obj->nobj)
4427 if (obj->oclass == COIN_CLASS) {
4430 prevobj->nobj = goldobj->nobj;
4432 invent = goldobj->nobj;
4435 /* second, re-letter the rest of the list */
4436 for (obj = invent, i = 0; obj; obj = obj->nobj, i++)
4438 (i < 26) ? ('a' + i) : (i < 52) ? ('A' + i - 26) : NOINVSYM;
4439 /* third, assign gold the "letter" '$' and re-insert it at head */
4441 goldobj->invlet = GOLD_SYM;
4442 goldobj->nobj = invent;
4452 * User specifies a 'from' slot for inventory stack to move,
4453 * then a 'to' slot for its destination. Open slots and those
4454 * filled by compatible stacks are listed as likely candidates
4455 * but user can pick any inventory letter (including 'from').
4457 * to == from, 'from' has a name
4458 * All compatible items (same name or no name) are gathered
4459 * into the 'from' stack. No count is allowed.
4460 * to == from, 'from' does not have a name
4461 * All compatible items without a name are gathered into the
4462 * 'from' stack. No count is allowed. Compatible stacks with
4463 * names are left as-is.
4464 * to != from, no count
4465 * Move 'from' to 'to'. If 'to' is not empty, merge 'from'
4466 * into it if possible, otherwise swap it with the 'from' slot.
4467 * to != from, count given
4468 * If the user specifies a count when choosing the 'from' slot,
4469 * and that count is less than the full size of the stack,
4470 * then the stack will be split. The 'count' portion is moved
4471 * to the destination, and the only candidate for merging with
4472 * it is the stack already at the 'to' slot, if any. When the
4473 * destination is non-empty but won't merge, whatever is there
4474 * will be moved to an open slot; if there isn't any open slot
4475 * available, the adjustment attempt fails.
4477 * To minimize merging for 'from == to', unnamed stacks will
4478 * merge with named 'from' but named ones won't merge with
4479 * unnamed 'from'. Otherwise attempting to collect all unnamed
4480 * stacks would lump the first compatible named stack with them
4481 * and give them its name.
4483 * To maximize merging for 'from != to', compatible stacks will
4484 * merge when either lacks a name (or they already have the same
4485 * name). When no count is given and one stack has a name and
4486 * the other doesn't, the merged result will have that name.
4487 * However, when splitting results in a merger, the name of the
4488 * destination overrides that of the source, even if destination
4489 * is unnamed and source is named.
4492 doorganize() /* inventory organizer by Del Lamb */
4494 struct obj *obj, *otmp, *splitting, *bumped;
4495 int ix, cur, trycnt, goldstacks;
4498 #define GOLD_OFFSET 1
4499 #define OVRFLW_INDX (GOLD_OFFSET + 52) /* past gold and 2*26 letters */
4500 char lets[1 + 52 + 1 + 1]; /* room for '$a-zA-Z#\0' */
4502 char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
4503 char *objname, *otmpname;
4504 const char *adj_type;
4505 boolean ever_mind = FALSE, collect;
4507 /* when no invent, or just gold in '$' slot, there's nothing to adjust */
4508 if (!invent || (invent->oclass == COIN_CLASS
4509 && invent->invlet == GOLD_SYM && !invent->nobj)) {
4511 You("aren't carrying anything %s.",
4512 !invent ? "to adjust" : "adjustable");
4514 You("
\8f\87\8f\98\82ð
\95Ï
\82¦
\82é
\82à
\82Ì
\82ð
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4519 if (!flags.invlet_constant)
4521 /* get object the user wants to organize (the 'from' slot) */
4522 allowall[0] = ALLOW_COUNT;
4523 allowall[1] = ALL_CLASSES;
4525 for (goldstacks = 0, otmp = invent; otmp; otmp = otmp->nobj) {
4526 /* gold should never end up in a letter slot, nor should two '$'
4527 slots occur, but if they ever do, allow #adjust to handle them
4528 (in the past, things like this have happened, usually due to
4529 bknown being erroneously set on one stack, clear on another;
4530 object merger isn't fooled by that anymore) */
4531 if (otmp->oclass == COIN_CLASS
4532 && (otmp->invlet != GOLD_SYM || ++goldstacks > 1)) {
4533 allowall[1] = COIN_CLASS;
4534 allowall[2] = ALL_CLASSES;
4539 if (!(obj = getobj(allowall, "adjust")))
4542 /* figure out whether user gave a split count to getobj() */
4543 splitting = bumped = 0;
4544 for (otmp = invent; otmp; otmp = otmp->nobj)
4545 if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
4546 if (otmp->invlet == obj->invlet)
4551 /* initialize the list with all lower and upper case letters */
4552 lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' ';
4553 for (ix = GOLD_OFFSET, let = 'a'; let <= 'z';)
4555 for (let = 'A'; let <= 'Z';)
4557 lets[OVRFLW_INDX] = ' ';
4558 lets[sizeof lets - 1] = '\0';
4559 /* for floating inv letters, truncate list after the first open slot */
4560 if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
4561 lets[ix + (splitting ? 0 : 1)] = '\0';
4563 /* blank out all the letters currently in use in the inventory
4564 except those that will be merged with the selected object */
4565 for (otmp = invent; otmp; otmp = otmp->nobj)
4566 if (otmp != obj && !mergable(otmp, obj)) {
4568 if (let >= 'a' && let <= 'z')
4569 lets[GOLD_OFFSET + let - 'a'] = ' ';
4570 else if (let >= 'A' && let <= 'Z')
4571 lets[GOLD_OFFSET + let - 'A' + 26] = ' ';
4572 /* overflow defaults to off, but it we find a stack using that
4573 slot, switch to on -- the opposite of normal invlet handling */
4574 else if (let == NOINVSYM)
4575 lets[OVRFLW_INDX] = NOINVSYM;
4578 /* compact the list by removing all the blanks */
4579 for (ix = cur = 0; lets[ix]; ix++)
4580 if (lets[ix] != ' ' && cur++ < ix)
4581 lets[cur - 1] = lets[ix];
4583 /* and by dashing runs of letters */
4587 /* get 'to' slot to use as destination */
4589 Sprintf(qbuf, "Adjust letter to what [%s]%s?", lets,
4590 invent ? " (? see used letters)" : "");
4592 Sprintf(qbuf, "
\82Ç
\82Ì
\95¶
\8e\9a\82É
\92²
\90®
\82µ
\82Ü
\82·
\82©[%s]%s
\81H", lets,
4593 invent ? " (?
\82Å
\8eg
\82Á
\82Ä
\82¢
\82é
\95¶
\8e\9a\82ð
\95\
\8e¦)" : "");
4595 for (trycnt = 1; ; ++trycnt) {
4596 let = yn_function(qbuf, (char *) 0, '\0');
4597 if (let == '?' || let == '*') {
4598 let = display_used_invlets(splitting ? obj->invlet : 0);
4604 if (index(quitchars, let)
4605 /* adjusting to same slot is meaningful since all
4606 compatible stacks get collected along the way,
4607 but splitting to same slot is not */
4608 || (splitting && let == obj->invlet)) {
4611 (void) merged(&splitting, &obj);
4615 } else if (let == GOLD_SYM && obj->oclass != COIN_CLASS) {
4617 pline("Only gold coins may be moved into the '%c' slot.",
4620 pline("'%c'
\82É
\82Å
\82«
\82é
\82Ì
\82Í
\8bà
\89Ý
\82¾
\82¯
\81D",
4626 /* letter() classifies '@' as one; compactify() can put '-' in lets;
4627 the only thing of interest that index() might find is '$' or '#'
4628 since letter() catches everything else that we put into lets[] */
4629 if ((letter(let) && let != '@') || (index(lets, let) && let != '-'))
4630 break; /* got one */
4634 pline("Select an inventory slot letter."); /* else try again */
4636 pline("
\8e\9d\82¿
\95¨
\82Ì
\95¶
\8e\9a\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢
\81D");
4640 collect = (let == obj->invlet);
4641 /* change the inventory and print the resulting item */
4643 adj_type = collect ? "Collecting" : !splitting ? "Moving:" : "Splitting:";
4645 adj_type = collect ? "
\82ð
\8fW
\82ß
\82½
\81D" : !splitting ? "
\82ð
\88Ú
\93®
\82µ
\82½
\81D" : "
\82ð
\95ª
\8a\84\82µ
\82½
\81D";
4648 * don't use freeinv/addinv to avoid double-touching artifacts,
4649 * dousing lamps, losing luck, cursing loadstone, etc.
4651 extract_nobj(obj, &invent);
4653 for (otmp = invent; otmp;) {
4654 /* it's tempting to pull this outside the loop, but merged() could
4655 free ONAME(obj) [via obfree()] and replace it with ONAME(otmp) */
4656 objname = has_oname(obj) ? ONAME(obj) : (char *) 0;
4659 /* Collecting: #adjust an inventory stack into its same slot;
4660 keep it there and merge other compatible stacks into it.
4661 Traditional inventory behavior is to merge unnamed stacks
4662 with compatible named ones; we only want that if it is
4663 the 'from' stack (obj) with a name and candidate (otmp)
4664 without one, not unnamed 'from' with named candidate. */
4665 otmpname = has_oname(otmp) ? ONAME(otmp) : (char *) 0;
4666 if ((!otmpname || (objname && !strcmp(objname, otmpname)))
4667 && merged(&otmp, &obj)) {
4669 adj_type = "Merging:";
4671 adj_type = "
\82ð
\8d\87\82í
\82¹
\82½
\81D";
4674 extract_nobj(obj, &invent);
4675 continue; /* otmp has already been updated */
4677 } else if (otmp->invlet == let) {
4678 /* Moving or splitting: don't merge extra compatible stacks.
4679 Found 'otmp' in destination slot; merge if compatible,
4680 otherwise bump whatever is there to an open slot. */
4683 adj_type = "Swapping:";
4685 adj_type = "
\82ð
\8cð
\8a·
\82µ
\82½
\81D";
4686 otmp->invlet = obj->invlet;
4688 /* strip 'from' name if it has one */
4689 if (objname && !obj->oartifact)
4690 ONAME(obj) = (char *) 0;
4691 if (!mergable(otmp, obj)) {
4692 /* won't merge; put 'from' name back */
4694 ONAME(obj) = objname;
4696 /* will merge; discard 'from' name */
4698 free((genericptr_t) objname), objname = 0;
4701 if (merged(&otmp, &obj)) {
4703 adj_type = "Splitting and merging:";
4705 adj_type = "
\82ð
\95ª
\8a\84\82µ
\82Ä
\8d\87\82í
\82¹
\82½
\81D";
4707 extract_nobj(obj, &invent);
4708 } else if (inv_cnt(FALSE) >= 52) {
4709 (void) merged(&splitting, &obj); /* undo split */
4710 /* "knapsack cannot accommodate any more items" */
4712 Your("pack is too full.");
4714 Your("
\8e\9d\82¿
\95¨
\82Í
\88ê
\94t
\82¾
\81D");
4718 extract_nobj(bumped, &invent);
4720 } /* moving vs splitting */
4721 break; /* not collecting and found 'to' slot */
4726 /* inline addinv; insert loose object at beginning of inventory */
4729 obj->where = OBJ_INVENT;
4733 /* splitting the 'from' stack is causing an incompatible
4734 stack in the 'to' slot to be moved into an open one;
4735 we need to do another inline insertion to inventory */
4736 assigninvlet(bumped);
4737 bumped->nobj = invent;
4738 bumped->where = OBJ_INVENT;
4743 /* messages deferred until inventory has been fully reestablished */
4744 prinv(adj_type, obj, 0L);
4747 prinv("Moving:", bumped, 0L);
4749 prinv("
\88Ú
\93®:", bumped, 0L);
4751 clear_splitobjs(); /* reset splitobj context */
4756 /* common to display_minventory and display_cinventory */
4758 invdisp_nothing(hdr, txt)
4759 const char *hdr, *txt;
4763 menu_item *selected;
4766 win = create_nhwindow(NHW_MENU);
4768 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr,
4770 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
4771 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
4772 end_menu(win, (char *) 0);
4773 if (select_menu(win, PICK_NONE, &selected) > 0)
4774 free((genericptr_t) selected);
4775 destroy_nhwindow(win);
4779 /* query_objlist callback: return things that are worn or wielded */
4781 worn_wield_only(obj)
4785 /* check for things that *are* worn or wielded (only used for monsters,
4786 so we don't worry about excluding W_CHAIN, W_ARTI and the like) */
4787 return (boolean) (obj->owornmask != 0L);
4789 /* this used to check for things that *might* be worn or wielded,
4790 but that's not particularly interesting */
4791 if (is_weptool(obj) || is_wet_towel(obj) || obj->otyp == MEAT_RING)
4793 return (boolean) (obj->oclass == WEAPON_CLASS
4794 || obj->oclass == ARMOR_CLASS
4795 || obj->oclass == AMULET_CLASS
4796 || obj->oclass == RING_CLASS);
4801 * Display a monster's inventory.
4802 * Returns a pointer to the object from the monster's inventory selected
4803 * or NULL if nothing was selected.
4805 * By default, only worn and wielded items are displayed. The caller
4806 * can pick one. Modifier flags are:
4808 * PICK_NONE, PICK_ONE - standard menu control
4809 * PICK_ANY - allowed, but we only return a single object
4810 * MINV_NOLET - nothing selectable
4811 * MINV_ALL - display all inventory
4814 display_minventory(mon, dflags, title)
4815 register struct monst *mon;
4822 menu_item *selected = 0;
4823 int do_all = (dflags & MINV_ALL) != 0,
4824 incl_hero = (do_all && u.uswallow && mon == u.ustuck),
4825 have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
4826 pickings = (dflags & MINV_PICKMASK);
4829 Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
4830 do_all ? "possessions" : "armament");
4832 Sprintf(tmp, "%s
\82Ì%s
\81F", Monnam(mon),
4833 do_all ? "
\8e\9d\82¿
\95¨" : "
\91\95\94õ");
4836 if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
4837 /* Fool the 'weapon in hand' routine into
4838 * displaying 'weapon in claw', etc. properly.
4840 youmonst.data = mon->data;
4841 /* in case inside a shop, don't append "for sale" prices */
4842 iflags.suppress_price++;
4844 n = query_objlist(title ? title : tmp, &(mon->minvent),
4845 (INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0)),
4846 &selected, pickings,
4847 do_all ? allow_all : worn_wield_only);
4849 iflags.suppress_price--;
4850 /* was 'set_uasmon();' but that potentially has side-effects */
4851 youmonst.data = &mons[u.umonnum]; /* most basic part of set_uasmon */
4854 invdisp_nothing(title ? title : tmp, "(none)");
4856 invdisp_nothing(title ? title : tmp, "(
\89½
\82à
\82È
\82¢)");
4861 ret = selected[0].item.a_obj;
4862 free((genericptr_t) selected);
4864 ret = (struct obj *) 0;
4869 * Display the contents of a container in inventory style.
4870 * Currently, this is only used for statues, via wand of probing.
4873 display_cinventory(obj)
4874 register struct obj *obj;
4879 menu_item *selected = 0;
4882 (void) safe_qbuf(qbuf, "Contents of ", ":", obj, doname, ansimpleoname,
4885 (void) safe_qbuf(qbuf, "", "
\82Ì
\92\86\90g
\81F", obj, doname, ansimpleoname,
4890 n = query_objlist(qbuf, &(obj->cobj), INVORDER_SORT,
4891 &selected, PICK_NONE, allow_all);
4894 invdisp_nothing(qbuf, "(empty)");
4896 invdisp_nothing(qbuf, "(
\8bó
\82Á
\82Û)");
4900 ret = selected[0].item.a_obj;
4901 free((genericptr_t) selected);
4903 ret = (struct obj *) 0;
4908 /* query objlist callback: return TRUE if obj is at given location */
4915 return (obj->ox == only.x && obj->oy == only.y);
4919 * Display a list of buried items in inventory style. Return a non-zero
4920 * value if there were items at that spot.
4922 * Currently, this is only used with a wand of probing zapped downwards.
4925 display_binventory(x, y, as_if_seen)
4930 menu_item *selected = 0;
4933 /* count # of objects here */
4934 for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
4935 if (obj->ox == x && obj->oy == y) {
4945 if (query_objlist("Things that are buried here:",
4947 if (query_objlist("
\82±
\82±
\82É
\96\84\82ß
\82ç
\82ê
\82Ä
\82¢
\82é
\82à
\82Ì
\81F",
4948 &level.buriedobjlist, INVORDER_SORT,
4949 &selected, PICK_NONE, only_here) > 0)
4950 free((genericptr_t) selected);
4951 only.x = only.y = 0;