1 /* NetHack 3.6 invent.c $NHDT-Date: 1555196229 2019/04/13 22:57:09 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.253 $ */
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-2019 */
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 */
150 k = 4; /* 'other' tool */
154 /* [what about separating "partly eaten" within each group?] */
160 /* [maybe separate one-bite foods from rations and such?] */
161 k = obj->globby ? 6 : 2;
176 * Normally subclass takes priority over discovery status, but
177 * that would give away information for gems (assuming we'll
178 * group them as valuable gems, next glass, then gray stones,
179 * and finally rocks once they're all fully identified).
182 * 1) unseen gems and glass ("gem")
183 * 2) seen but undiscovered gems and glass ("blue gem"),
184 * 3) discovered gems ("sapphire"),
185 * 4) discovered glass ("worthless pieced of blue glass"),
186 * 5) unseen gray stones and rocks ("stone"),
187 * 6) seen but undiscovered gray stones ("gray stone"),
188 * 7) discovered gray stones ("touchstone"),
189 * 8) seen rocks ("rock").
191 switch (objects[obj->otyp].oc_material) {
193 k = !seen ? 1 : !discovered ? 2 : 3;
196 k = !seen ? 1 : !discovered ? 2 : 4;
198 default: /* MINERAL */
199 k = !seen ? 5 : (obj->otyp != ROCK) ? (!discovered ? 6 : 7) : 8;
204 /* other classes don't have subclasses; we assign a nonzero
205 value because sortloot() uses 0 to mean 'not yet classified' */
206 k = 1; /* any non-zero would do */
209 sort_item->subclass = (xchar) k;
210 /* discovery status */
211 k = !seen ? 1 /* unseen */
212 : (discovered || !OBJ_DESCR(objects[otyp])) ? 4
213 : (objects[otyp].oc_uname) ? 3 /* named (partially discovered) */
214 : 2; /* undiscovered */
215 sort_item->disco = (xchar) k;
218 /* sortloot() formatting routine; for alphabetizing, not shown to user */
225 char *res, *save_oname;
228 * Deal with things that xname() includes as a prefix. We don't
229 * want such because they change alphabetical ordering. First,
230 * remember 'obj's current settings.
232 saveo.odiluted = obj->odiluted;
233 saveo.blessed = obj->blessed, saveo.cursed = obj->cursed;
234 saveo.spe = obj->spe;
235 saveo.owt = obj->owt;
236 save_oname = has_oname(obj) ? ONAME(obj) : 0;
237 save_debug = flags.debug;
238 /* suppress "diluted" for potions and "holy/unholy" for water;
239 sortloot() will deal with them using other criteria than name */
240 if (obj->oclass == POTION_CLASS) {
242 if (obj->otyp == POT_WATER)
243 obj->blessed = 0, obj->cursed = 0;
245 /* make "wet towel" and "moist towel" format as "towel" so that all
246 three group together */
247 if (obj->otyp == TOWEL)
249 /* group "<size> glob of <foo>" by <foo> rather than by <size> */
251 obj->owt = 200; /* 200: weight of combined glob from ten creatures
252 (five or fewer is "small", more than fifteen is
253 "large", in between has no prefix) */
254 /* suppress user-assigned name */
255 if (save_oname && !obj->oartifact)
257 /* avoid wizard mode formatting variations */
258 if (wizard) { /* flags.debug */
259 /* paranoia: before toggling off wizard mode, guard against a
260 panic in xname() producing a normal mode panic save file */
261 program_state.something_worth_saving = 0;
265 res = cxname_singular(obj);
269 program_state.something_worth_saving = 1;
271 /* restore the object */
272 if (obj->oclass == POTION_CLASS) {
273 obj->odiluted = saveo.odiluted;
274 if (obj->otyp == POT_WATER)
275 obj->blessed = saveo.blessed, obj->cursed = saveo.cursed;
277 if (obj->otyp == TOWEL) {
278 obj->spe = saveo.spe;
279 /* give "towel" a suffix that will force wet ones to come first,
280 moist ones next, and dry ones last regardless of whether
281 they've been flagged as having spe known */
282 Strcat(res, is_wet_towel(obj) ? ((obj->spe >= 3) ? "x" : "y") : "z");
285 obj->owt = saveo.owt;
286 /* we've suppressed the size prefix (above); there normally won't
287 be more than one of a given creature type because they coalesce,
288 but globs with different bless/curse state won't merge so it is
289 feasible to have multiple at the same location; add a suffix to
290 get such sorted by size (small first) */
291 Strcat(res, (obj->owt <= 100) ? "a"
292 : (obj->owt <= 300) ? "b"
293 : (obj->owt <= 500) ? "c"
296 if (save_oname && !obj->oartifact)
297 ONAME(obj) = save_oname;
302 /* set by sortloot() for use by sortloot_cmp(); reset by sortloot when done */
303 static unsigned sortlootmode = 0;
305 /* qsort comparison routine for sortloot() */
306 STATIC_OVL int CFDECLSPEC
307 sortloot_cmp(vptr1, vptr2)
308 const genericptr vptr1;
309 const genericptr vptr2;
311 struct sortloot_item *sli1 = (struct sortloot_item *) vptr1,
312 *sli2 = (struct sortloot_item *) vptr2;
313 struct obj *obj1 = sli1->obj,
316 int val1, val2, c, namcmp;
318 /* order by object class unless we're doing by-invlet without sortpack */
319 if ((sortlootmode & (SORTLOOT_PACK | SORTLOOT_INVLET))
320 != SORTLOOT_INVLET) {
321 /* Classify each object at most once no matter how many
322 comparisons it is involved in. */
323 if (!sli1->orderclass)
324 loot_classify(sli1, obj1);
325 if (!sli2->orderclass)
326 loot_classify(sli2, obj2);
329 val1 = sli1->orderclass;
330 val2 = sli2->orderclass;
332 return (int) (val1 - val2);
334 /* skip sub-classes when ordering by sortpack+invlet */
335 if ((sortlootmode & SORTLOOT_INVLET) == 0) {
336 /* Class matches; sort by subclass. */
337 val1 = sli1->subclass;
338 val2 = sli2->subclass;
342 /* Class and subclass match; sort by discovery status:
343 * first unseen, then seen but not named or discovered,
344 * then named, lastly discovered.
347 * 3) dark green potion called confusion
348 * 4) potion of healing
349 * Multiple entries within each group will be put into
350 * alphabetical order below.
359 /* order by assigned inventory letter */
360 if ((sortlootmode & SORTLOOT_INVLET) != 0) {
362 val1 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
363 : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
365 : (c == '#') ? 1 + 52 + 1
366 : 1 + 52 + 1 + 1; /* none of the above */
368 val2 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
369 : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
371 : (c == '#') ? 1 + 52 + 1
372 : 1 + 52 + 1 + 1; /* none of the above */
377 if ((sortlootmode & SORTLOOT_LOOT) == 0)
381 * Sort object names in lexicographical order, ignoring quantity.
383 * Each obj gets formatted at most once (per sort) no matter how many
384 * comparisons it gets subjected to.
388 nam1 = sli1->str = dupstr(loot_xname(obj1));
391 nam2 = sli2->str = dupstr(loot_xname(obj2));
392 if ((namcmp = strcmpi(nam1, nam2)) != 0)
396 val1 = obj1->bknown ? (obj1->blessed ? 3 : !obj1->cursed ? 2 : 1) : 0;
397 val2 = obj2->bknown ? (obj2->blessed ? 3 : !obj2->cursed ? 2 : 1) : 0;
399 return val2 - val1; /* bigger is better */
401 /* Sort by greasing. This will put the objects in degreasing order. */
402 val1 = obj1->greased;
403 val2 = obj2->greased;
405 return val2 - val1; /* bigger is better */
407 /* Sort by erosion. The effective amount is what matters. */
408 val1 = greatest_erosion(obj1);
409 val2 = greatest_erosion(obj2);
411 return val1 - val2; /* bigger is WORSE */
413 /* Sort by erodeproofing. Map known-invulnerable to 1, and both
414 known-vulnerable and unknown-vulnerability to 0, because that's
415 how they're displayed. */
416 val1 = obj1->rknown && obj1->oerodeproof;
417 val2 = obj2->rknown && obj2->oerodeproof;
419 return val2 - val1; /* bigger is better */
421 /* Sort by enchantment. Map unknown to -1000, which is comfortably
422 below the range of obj->spe. oc_uses_known means that obj->known
423 matters, which usually indirectly means that obj->spe is relevant.
424 Lots of objects use obj->spe for some other purpose (see obj.h). */
425 if (objects[obj1->otyp].oc_uses_known
426 /* exclude eggs (laid by you) and tins (homemade, pureed, &c) */
427 && obj1->oclass != FOOD_CLASS) {
428 val1 = obj1->known ? obj1->spe : -1000;
429 val2 = obj2->known ? obj2->spe : -1000;
431 return val2 - val1; /* bigger is better */
435 /* They're identical, as far as we're concerned. We want
436 to force a deterministic order, and do so by producing a
437 stable sort: maintain the original order of equal items. */
438 return (sli1->indx - sli2->indx);
442 * sortloot() - the story so far...
444 * The original implementation constructed and returned an array
445 * of pointers to objects in the requested order. Callers had to
446 * count the number of objects, allocate the array, pass one
447 * object at a time to the routine which populates it, traverse
448 * the objects via stepping through the array, then free the
449 * array. The ordering process used a basic insertion sort which
450 * is fine for short lists but inefficient for long ones.
452 * 3.6.0 (and continuing with 3.6.1) changed all that so that
453 * sortloot was self-contained as far as callers were concerned.
454 * It reordered the linked list into the requested order and then
455 * normal list traversal was used to process it. It also switched
456 * to qsort() on the assumption that the C library implementation
457 * put some effort into sorting efficiently. It also checked
458 * whether the list was already sorted as it got ready to do the
459 * sorting, so re-examining inventory or a pile of objects without
460 * having changed anything would gobble up less CPU than a full
461 * sort. But it had at least two problems (aside from the ordinary
462 * complement of bugs):
463 * 1) some players wanted to get the original order back when they
464 * changed the 'sortloot' option back to 'none', but the list
465 * reordering made that infeasible;
466 * 2) object identification giving the 'ID whole pack' result
467 * would call makeknown() on each newly ID'd object, that would
468 * call update_inventory() to update the persistent inventory
469 * window if one existed, the interface would call the inventory
470 * display routine which would call sortloot() which might change
471 * the order of the list being traversed by the identify code,
472 * possibly skipping the ID of some objects. That could have been
473 * avoided by suppressing 'perm_invent' during identification
474 * (fragile) or by avoiding sortloot() during inventory display
477 * 3.6.2 reverts to the temporary array of ordered obj pointers
478 * but has sortloot() do the counting and allocation. Callers
479 * need to use array traversal instead of linked list traversal
480 * and need to free the temporary array when done. And the
481 * array contains 'struct sortloot_item' (aka 'Loot') entries
482 * instead of simple 'struct obj *' entries.
485 sortloot(olist, mode, by_nexthere, filterfunc)
486 struct obj **olist; /* previous version might have changed *olist, we don't */
487 unsigned mode; /* flags for sortloot_cmp() */
488 boolean by_nexthere; /* T: traverse via obj->nexthere, F: via obj->nobj */
489 boolean FDECL((*filterfunc), (OBJ_P));
494 boolean augment_filter;
496 for (n = 0, o = *olist; o; o = by_nexthere ? o->nexthere : o->nobj)
498 /* note: if there is a filter function, this might overallocate */
499 sliarray = (Loot *) alloc((n + 1) * sizeof *sliarray);
501 /* the 'keep cockatrice corpses' flag is overloaded with sort mode */
502 augment_filter = (mode & SORTLOOT_PETRIFY) ? TRUE : FALSE;
503 mode &= ~SORTLOOT_PETRIFY; /* remove flag, leaving mode */
504 /* populate aliarray[0..n-1] */
505 for (i = 0, o = *olist; o; o = by_nexthere ? o->nexthere : o->nobj) {
506 if (filterfunc && !(*filterfunc)(o)
507 /* caller may be asking us to override filterfunc (in order
508 to do a cockatrice corpse touch check during pickup even
509 if/when the filter rejects food class) */
510 && (!augment_filter || o->otyp != CORPSE
511 || !touch_petrifies(&mons[o->corpsenm])))
513 sliarray[i].obj = o, sliarray[i].indx = (int) i;
514 sliarray[i].str = (char *) 0;
515 sliarray[i].orderclass = sliarray[i].subclass = sliarray[i].disco = 0;
519 /* add a terminator so that we don't have to pass 'n' back to caller */
520 sliarray[n].obj = (struct obj *) 0, sliarray[n].indx = -1;
521 sliarray[n].str = (char *) 0;
522 sliarray[n].orderclass = sliarray[n].subclass = sliarray[n].disco = 0;
524 /* do the sort; if no sorting is requested, we'll just return
525 a sortloot_item array reflecting the current ordering */
527 sortlootmode = mode; /* extra input for sortloot_cmp() */
528 qsort((genericptr_t) sliarray, n, sizeof *sliarray, sortloot_cmp);
529 sortlootmode = 0; /* reset static mode flags */
530 /* if sortloot_cmp formatted any objects, discard their strings now */
531 for (i = 0; i < n; ++i)
533 free((genericptr_t) sliarray[i].str), sliarray[i].str = 0;
538 /* sortloot() callers should use this to free up memory it allocates */
540 unsortloot(loot_array_p)
544 free((genericptr_t) *loot_array_p), *loot_array_p = (Loot *) 0;
547 #if 0 /* 3.6.0 'revamp' */
549 sortloot(olist, mode, by_nexthere)
551 unsigned mode; /* flags for sortloot_cmp() */
552 boolean by_nexthere; /* T: traverse via obj->nexthere, F: via obj->nobj */
554 struct sortloot_item *sliarray, osli, nsli;
555 struct obj *o, **nxt_p;
557 boolean already_sorted = TRUE;
559 sortlootmode = mode; /* extra input for sortloot_cmp() */
560 for (n = osli.indx = 0, osli.obj = *olist; (o = osli.obj) != 0;
562 nsli.obj = by_nexthere ? o->nexthere : o->nobj;
563 nsli.indx = (int) ++n;
564 if (nsli.obj && already_sorted
565 && sortloot_cmp((genericptr_t) &osli, (genericptr_t) &nsli) > 0)
566 already_sorted = FALSE;
568 if (n > 1 && !already_sorted) {
569 sliarray = (struct sortloot_item *) alloc(n * sizeof *sliarray);
570 for (i = 0, o = *olist; o;
571 ++i, o = by_nexthere ? o->nexthere : o->nobj)
572 sliarray[i].obj = o, sliarray[i].indx = (int) i;
574 qsort((genericptr_t) sliarray, n, sizeof *sliarray, sortloot_cmp);
575 for (i = 0; i < n; ++i) {
577 nxt_p = by_nexthere ? &(o->nexthere) : &(o->nobj);
578 *nxt_p = (i < n - 1) ? sliarray[i + 1].obj : (struct obj *) 0;
580 *olist = sliarray[0].obj;
581 free((genericptr_t) sliarray);
589 register struct obj *otmp;
593 register struct obj *obj;
595 /* there should be at most one of these in inventory... */
596 if (otmp->oclass == COIN_CLASS) {
597 otmp->invlet = GOLD_SYM;
601 for (i = 0; i < 52; i++)
603 for (obj = invent; obj; obj = obj->nobj)
606 if ('a' <= i && i <= 'z')
607 inuse[i - 'a'] = TRUE;
608 else if ('A' <= i && i <= 'Z')
609 inuse[i - 'A' + 26] = TRUE;
610 if (i == otmp->invlet)
613 if ((i = otmp->invlet)
614 && (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
616 for (i = lastinvnr + 1; i != lastinvnr; i++) {
625 (inuse[i] ? NOINVSYM : (i < 26) ? ('a' + i) : ('A' + i - 26));
629 /* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */
630 #define inv_rank(o) ((o)->invlet ^ 040)
632 /* sort the inventory; used by addinv() and doorganize() */
636 struct obj *otmp, *prev, *next;
637 boolean need_more_sorting;
641 * We expect at most one item to be out of order, so this
642 * isn't nearly as inefficient as it may first appear.
644 need_more_sorting = FALSE;
645 for (otmp = invent, prev = 0; otmp;) {
647 if (next && inv_rank(next) < inv_rank(otmp)) {
648 need_more_sorting = TRUE;
653 otmp->nobj = next->nobj;
661 } while (need_more_sorting);
666 /* scan a list of objects to see whether another object will merge with
667 one of them; used in pickup.c when all 52 inventory slots are in use,
668 to figure out whether another object could still be picked up */
670 merge_choice(objlist, obj)
671 struct obj *objlist, *obj;
676 if (obj->otyp == SCR_SCARE_MONSTER) /* punt on these */
677 return (struct obj *) 0;
678 /* if this is an item on the shop floor, the attributes it will
679 have when carried are different from what they are now; prevent
680 that from eliciting an incorrect result from mergable() */
681 save_nocharge = obj->no_charge;
682 if (objlist == invent && obj->where == OBJ_FLOOR
683 && (shkp = shop_keeper(inside_shop(obj->ox, obj->oy))) != 0) {
686 /* A billable object won't have its `unpaid' bit set, so would
687 erroneously seem to be a candidate to merge with a similar
688 ordinary object. That's no good, because once it's really
689 picked up, it won't merge after all. It might merge with
690 another unpaid object, but we can't check that here (depends
691 too much upon shk's bill) and if it doesn't merge it would
692 end up in the '#' overflow inventory slot, so reject it now. */
693 else if (inhishop(shkp))
694 return (struct obj *) 0;
697 if (mergable(objlist, obj))
699 objlist = objlist->nobj;
701 obj->no_charge = save_nocharge;
705 /* merge obj with otmp and delete obj if types agree */
708 struct obj **potmp, **pobj;
710 register struct obj *otmp = *potmp, *obj = *pobj;
712 if (mergable(otmp, obj)) {
713 /* Approximate age: we do it this way because if we were to
714 * do it "accurately" (merge only when ages are identical)
715 * we'd wind up never merging any corpses.
716 * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
718 * Don't do the age manipulation if lit. We would need
719 * to stop the burn on both items, then merge the age,
720 * then restart the burn. Glob ages are averaged in the
721 * absorb routine, which uses weight rather than quantity
722 * to adjust for proportion (glob quantity is always 1).
724 if (!obj->lamplit && !obj->globby)
725 otmp->age = ((otmp->age * otmp->quan) + (obj->age * obj->quan))
726 / (otmp->quan + obj->quan);
728 otmp->quan += obj->quan;
729 /* temporary special case for gold objects!!!! */
730 if (otmp->oclass == COIN_CLASS)
731 otmp->owt = weight(otmp), otmp->bknown = 0;
732 /* and puddings!!!1!!one! */
733 else if (!Is_pudding(otmp))
734 otmp->owt += obj->owt;
735 if (!has_oname(otmp) && has_oname(obj))
736 otmp = *potmp = oname(otmp, ONAME(obj));
737 obj_extract_self(obj);
739 /* really should merge the timeouts */
741 obj_merge_light_sources(obj, otmp);
743 obj_stop_timers(obj); /* follows lights */
745 /* fixup for `#adjust' merging wielded darts, daggers, &c */
746 if (obj->owornmask && carried(otmp)) {
747 long wmask = otmp->owornmask | obj->owornmask;
749 /* Both the items might be worn in competing slots;
750 merger preference (regardless of which is which):
751 primary weapon + alternate weapon -> primary weapon;
752 primary weapon + quiver -> primary weapon;
753 alternate weapon + quiver -> alternate weapon.
754 (Prior to 3.3.0, it was not possible for the two
755 stacks to be worn in different slots and `obj'
756 didn't need to be unworn when merging.) */
759 else if (wmask & W_SWAPWEP)
761 else if (wmask & W_QUIVER)
764 impossible("merging strangely worn items (%lx)", wmask);
765 wmask = otmp->owornmask;
767 if ((otmp->owornmask & ~wmask) != 0L)
769 setworn(otmp, wmask);
772 /* (this should not be necessary, since items
773 already in a monster's inventory don't ever get
774 merged into other objects [only vice versa]) */
775 } else if (obj->owornmask && mcarried(otmp)) {
776 if (obj == MON_WEP(otmp->ocarry)) {
777 MON_WEP(otmp->ocarry) = otmp;
778 otmp->owornmask = W_WEP;
783 /* handle puddings a bit differently; absorption will free the
784 other object automatically so we can just return out from here */
786 pudding_merge_message(otmp, obj);
787 obj_absorb(potmp, pobj);
791 obfree(obj, otmp); /* free(obj), bill->otmp */
798 * Adjust hero intrinsics as if this object was being added to the hero's
799 * inventory. Called _before_ the object has been added to the hero's
802 * This is called when adding objects to the hero's inventory normally (via
803 * addinv) or when an object in the hero's inventory has been polymorphed
806 * It may be valid to merge this code with with addinv_core2().
812 if (obj->oclass == COIN_CLASS) {
814 } else if (obj->otyp == AMULET_OF_YENDOR) {
816 impossible("already have amulet?");
818 u.uachieve.amulet = 1;
819 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
821 impossible("already have candelabrum?");
823 u.uachieve.menorah = 1;
824 } else if (obj->otyp == BELL_OF_OPENING) {
826 impossible("already have silver bell?");
829 } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
831 impossible("already have the book?");
834 } else if (obj->oartifact) {
835 if (is_quest_artifact(obj)) {
836 if (u.uhave.questart)
837 impossible("already have quest artifact?");
838 u.uhave.questart = 1;
841 set_artifact_intrinsic(obj, 1, W_ART);
844 /* "special achievements" aren't discoverable during play, they
845 end up being recorded in XLOGFILE at end of game, nowhere else;
846 record_achieve_special overloads corpsenm which is ordinarily
847 initialized to NON_PM (-1) rather than to 0; any special prize
848 must never be a corpse, egg, tin, figurine, or statue because
849 their use of obj->corpsenm for monster type would conflict,
850 nor be a leash (corpsenm overloaded for m_id of leashed
851 monster) or a novel (corpsenm overloaded for novel index) */
852 if (is_mines_prize(obj)) {
853 u.uachieve.mines_luckstone = 1;
854 obj->record_achieve_special = NON_PM;
856 } else if (is_soko_prize(obj)) {
857 u.uachieve.finish_sokoban = 1;
858 obj->record_achieve_special = NON_PM;
864 * Adjust hero intrinsics as if this object was being added to the hero's
865 * inventory. Called _after_ the object has been added to the hero's
868 * This is called when adding objects to the hero's inventory normally (via
869 * addinv) or when an object in the hero's inventory has been polymorphed
876 if (confers_luck(obj)) {
877 /* new luckstone must be in inventory by this point
878 * for correct calculation */
884 * Add obj to the hero's inventory. Make sure the object is "free".
885 * Adjust hero attributes as necessary.
891 struct obj *otmp, *prev;
892 int saved_otyp = (int) obj->otyp; /* for panic */
893 boolean obj_was_thrown;
895 if (obj->where != OBJ_FREE)
896 panic("addinv: obj not free");
897 /* normally addtobill() clears no_charge when items in a shop are
898 picked up, but won't do so if the shop has become untended */
899 obj->no_charge = 0; /* should not be set in hero's invent */
900 if (Has_contents(obj))
901 picked_container(obj); /* clear no_charge */
902 obj_was_thrown = obj->was_thrown;
903 obj->was_thrown = 0; /* not meaningful for invent */
907 /* merge with quiver in preference to any other inventory slot
908 in case quiver and wielded weapon are both eligible; adding
909 extra to quivered stack is more useful than to wielded one */
910 if (uquiver && merged(&uquiver, &obj)) {
913 panic("addinv: null obj after quiver merge otyp=%d", saved_otyp);
916 /* merge if possible; find end of chain in the process */
917 for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj)
918 if (merged(&otmp, &obj)) {
921 panic("addinv: null obj after merge otyp=%d", saved_otyp);
924 /* didn't merge, so insert into chain */
926 if (flags.invlet_constant || !prev) {
927 obj->nobj = invent; /* insert at beginning */
929 if (flags.invlet_constant)
932 prev->nobj = obj; /* insert at end */
935 obj->where = OBJ_INVENT;
937 /* fill empty quiver if obj was thrown */
938 if (flags.pickup_thrown && !uquiver && obj_was_thrown
939 /* if Mjollnir is thrown and fails to return, we want to
940 auto-pick it when we move to its spot, but not into quiver;
941 aklyses behave like Mjollnir when thrown while wielded, but
942 we lack sufficient information here make them exceptions */
943 && obj->oartifact != ART_MJOLLNIR
944 && (throwing_weapon(obj) || is_ammo(obj)))
948 carry_obj_effects(obj); /* carrying affects the obj */
954 * Some objects are affected by being carried.
955 * Make those adjustments here. Called _after_ the object
956 * has been added to the hero's or monster's inventory,
957 * and after hero's intrinsics have been updated.
960 carry_obj_effects(obj)
963 /* Cursed figurines can spontaneously transform when carried. */
964 if (obj->otyp == FIGURINE) {
965 if (obj->cursed && obj->corpsenm != NON_PM
966 && !dead_species(obj->corpsenm, TRUE)) {
967 attach_fig_transform_timeout(obj);
972 /* Add an item to the inventory unless we're fumbling or it refuses to be
973 * held (via touch_artifact), and give a message.
974 * If there aren't any free inventory slots, we'll drop it instead.
975 * If both success and failure messages are NULL, then we're just doing the
976 * fumbling/slot-limit checking for a silent grab. In any case,
977 * touch_artifact will print its own messages if they are warranted.
980 hold_another_object(obj, drop_fmt, drop_arg, hold_msg)
982 const char *drop_fmt, *drop_arg, *hold_msg;
987 obj->dknown = 1; /* maximize mergibility */
988 if (obj->oartifact) {
989 /* place_object may change these */
990 boolean crysknife = (obj->otyp == CRYSKNIFE);
991 int oerode = obj->oerodeproof;
992 boolean wasUpolyd = Upolyd;
994 /* in case touching this object turns out to be fatal */
995 place_object(obj, u.ux, u.uy);
997 if (!touch_artifact(obj, &youmonst)) {
998 obj_extract_self(obj); /* remove it from the floor */
999 dropy(obj); /* now put it back again :-) */
1001 } else if (wasUpolyd && !Upolyd) {
1002 /* loose your grip if you revert your form */
1004 pline(drop_fmt, drop_arg);
1005 obj_extract_self(obj);
1009 obj_extract_self(obj);
1011 obj->otyp = CRYSKNIFE;
1012 obj->oerodeproof = oerode;
1017 obj = addinv(obj); /* dropping expects obj to be in invent */
1020 long oquan = obj->quan;
1021 int prev_encumbr = near_capacity(); /* before addinv() */
1023 /* encumbrance only matters if it would now become worse
1024 than max( current_value, stressed ) */
1025 if (prev_encumbr < MOD_ENCUMBER)
1026 prev_encumbr = MOD_ENCUMBER;
1027 /* addinv() may redraw the entire inventory, overwriting
1028 drop_arg when it comes from something like doname() */
1030 drop_arg = strcpy(buf, drop_arg);
1033 if (inv_cnt(FALSE) > 52 || ((obj->otyp != LOADSTONE || !obj->cursed)
1034 && near_capacity() > prev_encumbr)) {
1035 /* undo any merge which took place */
1036 if (obj->quan > oquan)
1037 obj = splitobj(obj, oquan);
1040 if (flags.autoquiver && !uquiver && !obj->owornmask
1041 && (is_missile(obj) || ammo_and_launcher(obj, uwep)
1042 || ammo_and_launcher(obj, uswapwep)))
1044 if (hold_msg || drop_fmt)
1045 prinv(hold_msg, obj, oquan);
1052 pline(drop_fmt, drop_arg);
1054 if (can_reach_floor(TRUE)) {
1058 hitfloor(obj, FALSE);
1060 return (struct obj *) 0; /* might be gone */
1063 /* useup() all of an item regardless of its quantity */
1070 obfree(obj, (struct obj *) 0); /* deletes contents also */
1075 register struct obj *obj;
1077 /* Note: This works correctly for containers because they (containers)
1079 if (obj->quan > 1L) {
1080 obj->in_use = FALSE; /* no longer in use */
1082 obj->owt = weight(obj);
1089 /* use one charge from an item and possibly incur shop debt for it */
1091 consume_obj_charge(obj, maybe_unpaid)
1093 boolean maybe_unpaid; /* false if caller handles shop billing */
1103 * Adjust hero's attributes as if this object was being removed from the
1104 * hero's inventory. This should only be called from freeinv() and
1105 * where we are polymorphing an object already in the hero's inventory.
1107 * Should think of a better name...
1113 if (obj->oclass == COIN_CLASS) {
1116 } else if (obj->otyp == AMULET_OF_YENDOR) {
1117 if (!u.uhave.amulet)
1118 impossible("don't have amulet?");
1120 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
1121 if (!u.uhave.menorah)
1122 impossible("don't have candelabrum?");
1123 u.uhave.menorah = 0;
1124 } else if (obj->otyp == BELL_OF_OPENING) {
1126 impossible("don't have silver bell?");
1128 } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1130 impossible("don't have the book?");
1132 } else if (obj->oartifact) {
1133 if (is_quest_artifact(obj)) {
1134 if (!u.uhave.questart)
1135 impossible("don't have quest artifact?");
1136 u.uhave.questart = 0;
1138 set_artifact_intrinsic(obj, 0, W_ART);
1141 if (obj->otyp == LOADSTONE) {
1143 } else if (confers_luck(obj)) {
1146 } else if (obj->otyp == FIGURINE && obj->timed) {
1147 (void) stop_timer(FIG_TRANSFORM, obj_to_any(obj));
1151 /* remove an object from the hero's inventory */
1154 register struct obj *obj;
1156 extract_nobj(obj, &invent);
1165 struct obj *otmp, *otmp2;
1167 for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
1170 /* after unpunish(), or might get deallocated chain */
1171 otmp2 = otmp->nexthere;
1178 /* destroy object in fobj chain (if unpaid, it remains on the bill) */
1181 register struct obj *obj;
1185 if (obj->otyp == AMULET_OF_YENDOR
1186 || obj->otyp == CANDELABRUM_OF_INVOCATION
1187 || obj->otyp == BELL_OF_OPENING
1188 || obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1189 /* player might be doing something stupid, but we
1190 * can't guarantee that. assume special artifacts
1191 * are indestructible via drawbridges, and exploding
1192 * chests, and golem creation, and ...
1196 update_map = (obj->where == OBJ_FLOOR);
1197 obj_extract_self(obj);
1199 newsym(obj->ox, obj->oy);
1200 obfree(obj, (struct obj *) 0); /* frees contents also */
1203 /* try to find a particular type of object at designated map location */
1209 register struct obj *otmp;
1211 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
1212 if (otmp->otyp == otyp)
1218 /* sobj_at(&c) traversal -- find next object of specified type */
1220 nxtobj(obj, type, by_nexthere)
1223 boolean by_nexthere;
1225 register struct obj *otmp;
1227 otmp = obj; /* start with the object after this one */
1229 otmp = !by_nexthere ? otmp->nobj : otmp->nexthere;
1232 } while (otmp->otyp != type);
1241 register struct obj *otmp;
1243 for (otmp = invent; otmp; otmp = otmp->nobj)
1244 if (otmp->otyp == type)
1246 return (struct obj *) 0;
1249 /* Fictional and not-so-fictional currencies.
1250 * http://concord.wikia.com/wiki/List_of_Fictional_Currencies
1252 static const char *const currencies[] = {
1254 "Altarian Dollar", /* The Hitchhiker's Guide to the Galaxy */
1255 "Ankh-Morpork Dollar", /* Discworld */
1256 "auric", /* The Domination of Draka */
1257 "buckazoid", /* Space Quest */
1258 "cirbozoid", /* Starslip */
1259 "credit chit", /* Deus Ex */
1260 "cubit", /* Battlestar Galactica */
1261 "Flanian Pobble Bead", /* The Hitchhiker's Guide to the Galaxy */
1262 "fretzer", /* Jules Verne */
1263 "imperial credit", /* Star Wars */
1264 "Hong Kong Luna Dollar", /* The Moon is a Harsh Mistress */
1265 "kongbuck", /* Snow Crash */
1266 "nanite", /* System Shock 2 */
1267 "quatloo", /* Star Trek, Sim City */
1268 "simoleon", /* Sim City */
1269 "solari", /* Spaceballs */
1270 "spacebuck", /* Spaceballs */
1271 "sporebuck", /* Spore */
1272 "Triganic Pu", /* The Hitchhiker's Guide to the Galaxy */
1273 "woolong", /* Cowboy Bebop */
1274 "zorkmid", /* Zork, NetHack */
1276 "
\83A
\83\8b\83^
\83C
\83\8b\81E
\83h
\83\8b", /* The Hitchhiker's Guide to the Galaxy */
1277 "
\83A
\83\93\83N
\83\82\83\8b\83|
\81[
\83N
\81E
\83h
\83\8b", /* Discworld */
1278 "
\83\86\81[
\83\8a\83b
\83N", /* The Domination of Draka */
1279 "
\83o
\83b
\83J
\83]
\83C
\83h", /* Space Quest */
1280 "
\83T
\81[
\83{
\83]
\83C
\83h", /* Starslip */
1281 "
\83N
\83\8c\83W
\83b
\83g
\81E
\83`
\83b
\83g", /* Deus Ex */
1282 "
\83L
\83\85\81[
\83r
\83b
\83g", /* Battlestar Galactica */
1283 "
\83t
\83\8c\83j
\83A
\83\93\81E
\83s
\83b
\83u
\83\8b\81E
\83r
\81[
\83h", /* The Hitchhiker's Guide to the Galaxy */
1284 "
\83t
\83\8c\83b
\83c
\83@", /* Jules Verne */
1285 "
\92é
\8d\91\83N
\83\8c\83W
\83b
\83g", /* Star Wars */
1286 "
\8d\81\8d`
\8c\8e\83h
\83\8b", /* The Moon is a Harsh Mistress */
1287 "
\83R
\83\93\83o
\83b
\83N", /* Snow Crash */
1288 "
\83i
\81[
\83i
\83C
\83g", /* System Shock 2 */
1289 "
\83N
\83@
\83g
\83\8d", /* Star Trek, Sim City */
1290 "
\83V
\83\82\83\8c\83I
\83\93", /* Sim City */
1291 "
\83\
\83\89\83\8a", /* Spaceballs */
1292 "
\83X
\83y
\81[
\83X
\83o
\83b
\83N", /* Spaceballs */
1293 "
\83X
\83|
\83A
\83o
\83b
\83N", /* Spore */
1294 "
\83g
\83\89\83C
\83K
\83j
\83b
\83N
\81E
\83v
\81[", /* The Hitchhiker's Guide to the Galaxy */
1295 "
\83E
\81[
\83\8d\83\93", /* Cowboy Bebop */
1296 "
\83S
\81[
\83\8b\83h", /* Zork, NetHack */
1307 res = Hallucination ? currencies[rn2(SIZE(currencies))] : "zorkmid";
1309 res = makeplural(res);
1311 res = Hallucination ? currencies[rn2(SIZE(currencies))] : "
\83S
\81[
\83\8b\83h";
1319 register struct obj *otmp;
1321 for (otmp = invent; otmp; otmp = otmp->nobj)
1322 if (otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
1331 register struct obj *otmp;
1333 for (otmp = invent; otmp; otmp = otmp->nobj)
1334 if (otmp->otyp == SPE_NOVEL)
1336 return (struct obj *) 0;
1342 register struct obj *objchn;
1347 if (objchn->o_id == id)
1349 if (Has_contents(objchn) && (temp = o_on(id, objchn->cobj)))
1351 objchn = objchn->nobj;
1353 return (struct obj *) 0;
1358 register struct obj *obj;
1361 register struct obj *otmp;
1363 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
1373 register struct obj *obj = level.objects[x][y];
1376 if (obj->oclass == COIN_CLASS)
1378 obj = obj->nexthere;
1380 return (struct obj *) 0;
1383 /* compact a string of inventory letters by dashing runs of letters */
1388 register int i1 = 1, i2 = 1;
1389 register char ilet, ilet1, ilet2;
1393 buf[++i2] = buf[++i1];
1396 if (ilet == ilet1 + 1) {
1397 if (ilet1 == ilet2 + 1)
1398 buf[i2 - 1] = ilet1 = '-';
1399 else if (ilet2 == '-') {
1400 buf[i2 - 1] = ++ilet1;
1401 buf[i2] = buf[++i1];
1405 } else if (ilet == NOINVSYM) {
1406 /* compact three or more consecutive '#'
1407 characters into "#-#" */
1408 if (i2 >= 2 && buf[i2 - 2] == NOINVSYM && buf[i2 - 1] == NOINVSYM)
1410 else if (i2 >= 3 && buf[i2 - 3] == NOINVSYM && buf[i2 - 2] == '-'
1411 && buf[i2 - 1] == NOINVSYM)
1416 buf[++i2] = buf[++i1];
1421 /* some objects shouldn't be split when count given to getobj or askchain */
1426 return !((obj->otyp == LOADSTONE && obj->cursed)
1427 || (obj == uwep && welded(uwep)));
1430 /* match the prompt for either 'T' or 'R' command */
1435 return !strcmp(action, "take off") || !strcmp(action, "remove");
1438 /* match the prompt for either 'W' or 'P' command */
1443 return !strcmp(action, "wear") || !strcmp(action, "put on");
1448 * struct obj *xxx: object to do something with.
1449 * (struct obj *) 0 error return: no object.
1450 * &zeroobj explicitly no object (as in w-).
1451 !!!! test if gold can be used in unusual ways (eaten etc.)
1452 !!!! may be able to remove "usegold"
1455 ** word
\82É
\82Í
\89p
\8cê
\82Å
\93®
\8e\8c\82ª
\93ü
\82é
\81D
1457 **
\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
1458 **
\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
1463 register const char *let, *word;
1465 register struct obj *otmp;
1466 register char ilet = 0;
1467 char buf[BUFSZ], qbuf[QBUFSZ];
1468 char lets[BUFSZ], altlets[BUFSZ], *ap;
1469 register int foo = 0;
1470 register char *bp = buf;
1471 xchar allowcnt = 0; /* 0, 1 or 2 */
1472 boolean usegold = FALSE; /* can't use gold because its illegal */
1473 boolean allowall = FALSE;
1474 boolean allownone = FALSE;
1475 boolean useboulder = FALSE;
1478 boolean cntgiven = FALSE;
1479 boolean msggiven = FALSE;
1480 boolean oneloop = FALSE;
1482 Loot *sortedinvent, *srtinv;
1489 struct trans_verb *tv = trans_verb(word);
1493 joshi = tv->particle;
1495 if (*let == ALLOW_COUNT)
1496 let++, allowcnt = 1;
1497 if (*let == COIN_CLASS)
1498 let++, usegold = TRUE;
1500 /* Equivalent of an "ugly check" for gold */
1501 if (usegold && !strcmp(word, "eat")
1502 && (!metallivorous(youmonst.data)
1503 || youmonst.data == &mons[PM_RUST_MONSTER]))
1506 if (*let == ALL_CLASSES)
1507 let++, allowall = TRUE;
1508 if (*let == ALLOW_NONE)
1509 let++, allownone = TRUE;
1510 /* "ugly check" for reading fortune cookies, part 1.
1511 * The normal 'ugly check' keeps the object on the inventory list.
1512 * We don't want to do that for shirts/cookies, so the check for
1513 * them is handled a bit differently (and also requires that we set
1514 * allowall in the caller).
1516 if (allowall && !strcmp(word, "read"))
1519 /* another ugly check: show boulders (not statues) */
1520 if (*let == WEAPON_CLASS && !strcmp(word, "throw")
1521 && throws_rocks(youmonst.data))
1525 *bp++ = HANDS_SYM, *bp++ = ' '; /* '-' */
1528 if (!flags.invlet_constant)
1531 /* force invent to be in invlet order before collecting candidate
1532 inventory letters */
1533 sortedinvent = sortloot(&invent, SORTLOOT_INVLET, FALSE,
1534 (boolean FDECL((*), (OBJ_P))) 0);
1536 for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
1537 if (&bp[foo] == &buf[sizeof buf - 1]
1538 || ap == &altlets[sizeof altlets - 1]) {
1539 /* we must have a huge number of NOINVSYM items somehow */
1540 impossible("getobj: inventory overflow");
1544 if (!*let || index(let, otmp->oclass)
1545 || (usegold && otmp->invlet == GOLD_SYM)
1546 || (useboulder && otmp->otyp == BOULDER)) {
1547 register int otyp = otmp->otyp;
1549 bp[foo++] = otmp->invlet;
1550 /* clang-format off */
1552 /* ugly check: remove inappropriate things */
1554 (taking_off(word) /* exclude if not worn */
1555 && !(otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
1556 || (putting_on(word) /* exclude if already worn */
1557 && (otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
1558 #if 0 /* 3.4.1 -- include currently wielded weapon among 'wield' choices */
1559 || (!strcmp(word, "wield")
1560 && (otmp->owornmask & W_WEP))
1562 || (!strcmp(word, "ready") /* exclude when wielded... */
1563 && ((otmp == uwep || (otmp == uswapwep && u.twoweap))
1564 && otmp->quan == 1L)) /* ...unless more than one */
1565 || ((!strcmp(word, "dip") || !strcmp(word, "grease"))
1566 && inaccessible_equipment(otmp, (const char *) 0, FALSE))
1571 /* Second ugly check; unlike the first it won't trigger an
1572 * "else" in "you don't have anything else to ___".
1576 && ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING)
1577 || (otmp->oclass == TOOL_CLASS && otyp != BLINDFOLD
1578 && otyp != TOWEL && otyp != LENSES)))
1579 || (!strcmp(word, "wield")
1580 && (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
1581 || (!strcmp(word, "eat") && !is_edible(otmp))
1582 || (!strcmp(word, "sacrifice")
1583 && (otyp != CORPSE && otyp != AMULET_OF_YENDOR
1584 && otyp != FAKE_AMULET_OF_YENDOR))
1585 || (!strcmp(word, "write with")
1586 && (otmp->oclass == TOOL_CLASS
1587 && otyp != MAGIC_MARKER && otyp != TOWEL))
1588 || (!strcmp(word, "tin")
1589 && (otyp != CORPSE || !tinnable(otmp)))
1590 || (!strcmp(word, "rub")
1591 && ((otmp->oclass == TOOL_CLASS && otyp != OIL_LAMP
1592 && otyp != MAGIC_LAMP && otyp != BRASS_LANTERN)
1593 || (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
1594 || (!strcmp(word, "use or apply")
1595 /* Picks, axes, pole-weapons, bullwhips */
1596 && ((otmp->oclass == WEAPON_CLASS
1597 && !is_pick(otmp) && !is_axe(otmp)
1598 && !is_pole(otmp) && otyp != BULLWHIP)
1599 || (otmp->oclass == POTION_CLASS
1600 /* only applicable potion is oil, and it will only
1601 be offered as a choice when already discovered */
1602 && (otyp != POT_OIL || !otmp->dknown
1603 || !objects[POT_OIL].oc_name_known))
1604 || (otmp->oclass == FOOD_CLASS
1605 && otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF)
1606 || (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
1607 || (!strcmp(word, "invoke")
1609 && !objects[otyp].oc_unique
1610 && (otyp != FAKE_AMULET_OF_YENDOR || otmp->known)
1611 && otyp != CRYSTAL_BALL /* synonym for apply */
1612 /* note: presenting the possibility of invoking non-artifact
1613 mirrors and/or lamps is simply a cruel deception... */
1615 && otyp != MAGIC_LAMP
1616 && (otyp != OIL_LAMP /* don't list known oil lamp */
1617 || (otmp->dknown && objects[OIL_LAMP].oc_name_known)))
1618 || (!strcmp(word, "untrap with")
1619 && ((otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE)
1620 || (otmp->oclass == POTION_CLASS
1621 /* only applicable potion is oil, and it will only
1622 be offered as a choice when already discovered */
1623 && (otyp != POT_OIL || !otmp->dknown
1624 || !objects[POT_OIL].oc_name_known))))
1625 || (!strcmp(word, "tip") && !Is_container(otmp)
1626 /* include horn of plenty if sufficiently discovered */
1627 && (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown
1628 || !objects[HORN_OF_PLENTY].oc_name_known))
1629 || (!strcmp(word, "charge") && !is_chargeable(otmp))
1630 || (!strcmp(word, "open") && otyp != TIN)
1631 || (!strcmp(word, "call") && !objtyp_is_callable(otyp))
1632 || (!strcmp(word, "adjust") && otmp->oclass == COIN_CLASS
1637 /* Third ugly check: acceptable but not listed as likely
1638 * candidates in the prompt or in the inventory subset if
1639 * player responds with '?'.
1642 /* ugly check for unworn armor that can't be worn */
1643 (putting_on(word) && *let == ARMOR_CLASS
1644 && !canwearobj(otmp, &dummymask, FALSE))
1645 /* or armor with 'P' or 'R' or accessory with 'W' or 'T' */
1646 || ((putting_on(word) || taking_off(word))
1647 && ((*let == ARMOR_CLASS) ^ (otmp->oclass == ARMOR_CLASS)))
1648 /* or unsuitable items rubbed on known touchstone */
1649 || (!strncmp(word, "rub on the stone", 16)
1650 && *let == GEM_CLASS && otmp->dknown
1651 && objects[otyp].oc_name_known)
1652 /* suppress corpses on astral, amulets elsewhere */
1653 || (!strcmp(word, "sacrifice")
1654 /* (!astral && amulet) || (astral && !amulet) */
1655 && (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
1656 /* suppress container being stashed into */
1657 || (!strcmp(word, "stash") && !ck_bag(otmp))
1658 /* worn armor (shirt, suit) covered by worn armor (suit, cloak)
1659 or accessory (ring) covered by cursed worn armor (gloves) */
1660 || (taking_off(word)
1661 && inaccessible_equipment(otmp, (const char *) 0,
1662 (boolean) (otmp->oclass == RING_CLASS)))
1663 || (!strcmp(word, "write on")
1664 && (!(otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER)
1665 || !otmp->dknown || !objects[otyp].oc_name_known))
1667 /* acceptable but not listed as likely candidate */
1670 *ap++ = otmp->invlet;
1673 /* clang-format on */
1675 /* "ugly check" for reading fortune cookies, part 2 */
1676 if ((!strcmp(word, "read") && is_readable(otmp)))
1677 allowall = usegold = TRUE;
1680 unsortloot(&sortedinvent);
1683 if (foo == 0 && bp > buf && bp[-1] == ' ')
1685 Strcpy(lets, bp); /* necessary since we destroy buf */
1686 if (foo > 5) /* compactify string */
1690 if (!foo && !allowall && !allownone) {
1692 You("don't have anything %sto %s.", foox ? "else " : "", word);
1694 You("%s%s
\82à
\82Ì
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", foox ? "
\91¼
\82É" : "", jconj(jword, "
\82ê
\82é"));
1695 return (struct obj *) 0;
1696 } else if (!strcmp(word, "write on")) { /* ugly check for magic marker */
1697 /* we wanted all scrolls and books in altlets[], but that came with
1698 'allowall' which we don't want since it prevents "silly thing"
1699 result if anything other than scroll or spellbook is chosen */
1706 Sprintf(qbuf, "What do you want to %s?", word);
1708 Sprintf(qbuf, "%s%s%s
\82©
\81H", what, joshi, jpolite(jword));
1711 else if (iflags.force_invmenu) {
1712 /* don't overwrite a possible quitchars */
1714 ilet = *let ? '?' : '*';
1716 putmsghistory(qbuf, FALSE);
1721 Strcat(qbuf, " [*]");
1723 Sprintf(eos(qbuf), " [%s or ?*]", buf);
1724 ilet = yn_function(qbuf, (char *) 0, '\0');
1731 pline("No count allowed with this command.");
1733 pline("
\82±
\82Ì
\83R
\83}
\83\93\83h
\82É
\90\94\8e\9a\82Í
\82Â
\82©
\82¦
\82È
\82¢
\81D");
1736 ilet = get_count(NULL, ilet, LARGEST_INT, &tmpcnt, TRUE);
1742 if (index(quitchars, ilet)) {
1745 return (struct obj *) 0;
1747 if (ilet == HANDS_SYM) { /* '-' */
1750 char *suf = (char *) 0;
1753 if ((bp = strstr(buf, " on the ")) != 0) {
1754 /* rub on the stone[s] */
1758 if ((bp = strstr(buf, " or ")) != 0) {
1760 bp = (rn2(2) ? buf : (bp + 4));
1763 You("mime %s something%s%s.", ing_suffix(bp), suf ? " " : "",
1766 You("
\89½
\82©
\82ð%s
\82Ó
\82è
\82ð
\82µ
\82½
\81D", bp);
1769 return (allownone ? (struct obj *) &zeroobj : (struct obj *) 0);
1772 /* since gold is now kept in inventory, we need to do processing for
1773 select-from-invent before checking whether gold has been picked */
1774 if (ilet == '?' || ilet == '*') {
1775 char *allowed_choices = (ilet == '?') ? lets : (char *) 0;
1777 char menuquery[QBUFSZ];
1779 menuquery[0] = qbuf[0] = '\0';
1780 if (iflags.force_invmenu)
1781 Sprintf(menuquery, "What do you want to %s?", word);
1782 if (!strcmp(word, "grease"))
1783 Sprintf(qbuf, "your %s", makeplural(body_part(FINGER)));
1784 else if (!strcmp(word, "write with"))
1785 Sprintf(qbuf, "your %s", body_part(FINGERTIP));
1786 else if (!strcmp(word, "wield"))
1787 Sprintf(qbuf, "your %s %s%s", uarmg ? "gloved" : "bare",
1788 makeplural(body_part(HAND)),
1789 !uwep ? " (wielded)" : "");
1790 else if (!strcmp(word, "ready"))
1791 Sprintf(qbuf, "empty quiver%s",
1792 !uquiver ? " (nothing readied)" : "");
1794 if (ilet == '?' && !*lets && *altlets)
1795 allowed_choices = altlets;
1796 ilet = display_pickinv(allowed_choices, *qbuf ? qbuf : (char *) 0,
1798 TRUE, allowcnt ? &ctmp : (long *) 0);
1801 if (ilet == HANDS_SYM)
1802 return (struct obj *) &zeroobj; /* cast away 'const' */
1803 if (ilet == '\033') {
1806 return (struct obj *) 0;
1810 if (allowcnt && ctmp >= 0) {
1814 /* they typed a letter (not a space) at the prompt */
1816 /* find the item which was picked */
1817 for (otmp = invent; otmp; otmp = otmp->nobj)
1818 if (otmp->invlet == ilet)
1820 /* some items have restrictions */
1821 if (ilet == def_oc_syms[COIN_CLASS].sym
1822 /* guard against the [hypothetical] chace of having more
1823 than one invent slot of gold and picking the non-'$' one */
1824 || (otmp && otmp->oclass == COIN_CLASS)) {
1827 You("cannot %s gold.", word);
1829 You("
\8bà
\89Ý%s%s
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D", joshi, jword);
1830 return (struct obj *) 0;
1832 /* Historic note: early Nethack had a bug which was
1833 * first reported for Larn, where trying to drop 2^32-n
1834 * gold pieces was allowed, and did interesting things
1835 * to your money supply. The LRS is the tax bureau
1838 if (cntgiven && cnt <= 0) {
1842 "LRS would be very interested to know you have that much.");
1844 "
\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");
1845 return (struct obj *) 0;
1848 if (cntgiven && !strcmp(word, "throw")) {
1849 /* permit counts for throwing gold, but don't accept
1850 * counts for other things since the throw code will
1851 * split off a single item anyway */
1853 return (struct obj *) 0;
1854 if (cnt > 1 && (ilet != def_oc_syms[COIN_CLASS].sym
1855 && !(otmp && otmp->oclass == COIN_CLASS))) {
1857 You("can only throw one item at a time.");
1859 You("
\93¯
\8e\9e\82É
\82½
\82
\82³
\82ñ
\82Ì
\82à
\82Ì
\82ð
\93\8a\82°
\82ç
\82ê
\82È
\82¢
\81D");
1863 context.botl = 1; /* May have changed the amount of money */
1865 /* [we used to set otmp (by finding ilet in invent) here, but
1866 that's been moved above so that otmp can be checked earlier] */
1867 /* verify the chosen object */
1870 You("don't have that object.");
1872 You("
\82»
\82ñ
\82È
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
1874 return (struct obj *) 0;
1876 } else if (cnt < 0 || otmp->quan < cnt) {
1878 You("don't have that many! You have only %ld.", otmp->quan);
1880 pline("
\82»
\82ñ
\82È
\82É
\82½
\82
\82³
\82ñ
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81I
\82¹
\82¢
\82º
\82¢%ld
\8cÂ
\82Á
\82Ä
\82Æ
\82±
\82¾
\81D", otmp->quan);
1882 return (struct obj *) 0;
1887 if (!allowall && let && !index(let, otmp->oclass)
1888 && !(usegold && otmp->oclass == COIN_CLASS)) {
1890 silly_thing(word, otmp);
1892 silly_thing(jword, otmp);
1894 return (struct obj *) 0;
1898 return (struct obj *) 0;
1899 if (cnt != otmp->quan) {
1900 /* don't split a stack of cursed loadstones */
1901 if (splittable(otmp))
1902 otmp = splitobj(otmp, cnt);
1903 else if (otmp->otyp == LOADSTONE && otmp->cursed)
1904 /* kludge for canletgo()'s can't-drop-this message */
1905 otmp->corpsenm = (int) cnt;
1912 silly_thing(word, otmp)
1916 #if 1 /* 'P','R' vs 'W','T' handling is obsolete */
1919 const char *s1, *s2, *s3;
1920 int ocls = otmp->oclass, otyp = otmp->otyp;
1923 /* check for attempted use of accessory commands ('P','R') on armor
1924 and for corresponding armor commands ('W','T') on accessories */
1925 if (ocls == ARMOR_CLASS) {
1927 if (!strcmp(word, "put on"))
1928 s1 = "W", s2 = "wear", s3 = "";
1929 else if (!strcmp(word, "remove"))
1930 s1 = "T", s2 = "take", s3 = " off";
1932 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1933 s1 = "W", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1934 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1935 s1 = "T", s2 = "
\82Í
\82¸
\82·", s3 = "";
1937 } else if ((ocls == RING_CLASS || otyp == MEAT_RING)
1938 || ocls == AMULET_CLASS
1939 || (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
1941 if (!strcmp(word, "wear"))
1942 s1 = "P", s2 = "put", s3 = " on";
1943 else if (!strcmp(word, "take off"))
1944 s1 = "R", s2 = "remove", s3 = "";
1946 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1947 s1 = "P", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1948 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1949 s1 = "R", s2 = "
\82Í
\82¸
\82·", s3 = "";
1954 pline("Use the '%s' command to %s %s%s.", s1, s2,
1955 !(is_plural(otmp) || pair_of(otmp)) ? "that" : "those", s3);
1957 pline("
\82»
\82ê
\82ð%s
\82É
\82Í'%s'
\83R
\83}
\83\93\83h
\82ð
\8eg
\82¤
\82±
\82Æ
\81D", s2, s1);
1961 pline(silly_thing_to, word);
1968 /* use allow_category() from pickup.c */
1969 return (int) allow_category(otmp);
1976 return (otmp->unpaid || (Has_contents(otmp) && count_unpaid(otmp->cobj)));
1982 return (boolean) (uarm || uarmc || uarmf || uarmg
1983 || uarmh || uarms || uarmu);
1990 return (otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_SADDLE | W_WEAPON))
1995 /* extra xprname() input that askchain() can't pass through safe_qbuf() */
1996 STATIC_VAR struct xprnctx {
2001 /* safe_qbuf() -> short_oname() callback */
2006 return xprname(obj, (char *) 0, safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
2010 /* alternate safe_qbuf() -> short_oname() callback */
2012 safeq_shortxprname(obj)
2015 return xprname(obj, ansimpleoname(obj), safeq_xprn_ctx.let,
2016 safeq_xprn_ctx.dot, 0L, 0L);
2019 static NEARDATA const char removeables[] = { ARMOR_CLASS, WEAPON_CLASS,
2020 RING_CLASS, AMULET_CLASS,
2023 /* Interactive version of getobj - used for Drop, Identify, and Takeoff (A).
2024 Return the number of times fn was called successfully.
2025 If combo is TRUE, we just use this to get a category list. */
2026 /*JP CHECK: 3.6.0
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
2027 do.c:962: || (result = ggetobj("drop", drop, 0, FALSE, (unsigned *) 0)) < -1)
2028 do.c:1009: i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
2029 do_wear.c:2955: || (result = ggetobj("take off", select_off, 0, FALSE,
2030 do_wear.c:3007: if (ggetobj("take off", select_off, 0, TRUE, (unsigned *) 0) == -2)
2031 invent.c:2014: n = ggetobj("identify", identify, id_limit, FALSE,
2034 ggetobj(word, fn, mx, combo, resultflags)
2036 int FDECL((*fn), (OBJ_P)), mx;
2037 boolean combo; /* combination menu flag */
2038 unsigned *resultflags;
2040 int FDECL((*ckfn), (OBJ_P)) = (int FDECL((*), (OBJ_P))) 0;
2041 boolean FDECL((*ofilter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
2042 boolean takeoff, ident, allflag, m_seen;
2044 int oletct, iletct, unpaid, oc_of_sym;
2045 char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 10];
2046 char extra_removeables[3 + 1]; /* uwep,uswapwep,uquiver */
2047 char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
2049 const char *joshi = "
\82ð";
2052 const struct trans_verb *tv = trans_verb(word);
2054 joshi = tv->particle;
2059 You("have nothing to %s.", word);
2061 You("%s
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", jcan(jword));
2063 *resultflags = ALL_FINISHED;
2068 takeoff = ident = allflag = m_seen = FALSE;
2069 add_valid_menu_class(0); /* reset */
2070 if (taking_off(word)) {
2073 } else if (!strcmp(word, "identify")) {
2075 ofilter = not_fully_identified;
2078 iletct = collect_obj_classes(ilets, invent, FALSE, ofilter, &itemcount);
2079 unpaid = count_unpaid(invent);
2081 if (ident && !iletct) {
2082 return -1; /* no further identifications */
2083 } else if (invent) {
2084 ilets[iletct++] = ' ';
2086 ilets[iletct++] = 'u';
2087 if (count_buc(invent, BUC_BLESSED, ofilter))
2088 ilets[iletct++] = 'B';
2089 if (count_buc(invent, BUC_UNCURSED, ofilter))
2090 ilets[iletct++] = 'U';
2091 if (count_buc(invent, BUC_CURSED, ofilter))
2092 ilets[iletct++] = 'C';
2093 if (count_buc(invent, BUC_UNKNOWN, ofilter))
2094 ilets[iletct++] = 'X';
2095 ilets[iletct++] = 'a';
2097 ilets[iletct++] = 'i';
2099 ilets[iletct++] = 'm'; /* allow menu presentation on request */
2100 ilets[iletct] = '\0';
2104 Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]",
2107 Sprintf(qbuf,"
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\82à
\82Ì%s%s
\82©
\81H[%s]", joshi,
2108 jpolite(jword), ilets);
2111 if (buf[0] == '\033')
2113 if (index(buf, 'i')) {
2114 char ailets[1+26+26+1+5+1]; /* $ + a-z + A-Z + # + slop + \0 */
2117 /* applicable inventory letters; if empty, show entire invent */
2120 for (otmp = invent; otmp; otmp = otmp->nobj)
2121 /* index() check: limit overflow items to one '#' */
2122 if ((*ofilter)(otmp) && !index(ailets, otmp->invlet))
2123 (void) strkitten(ailets, otmp->invlet);
2124 if (display_inventory(ailets, TRUE) == '\033')
2130 extra_removeables[0] = '\0';
2132 /* arbitrary types of items can be placed in the weapon slots
2133 [any duplicate entries in extra_removeables[] won't matter] */
2135 (void) strkitten(extra_removeables, uwep->oclass);
2137 (void) strkitten(extra_removeables, uswapwep->oclass);
2139 (void) strkitten(extra_removeables, uquiver->oclass);
2143 olets[oletct = 0] = '\0';
2144 while ((sym = *ip++) != '\0') {
2147 oc_of_sym = def_char_to_objclass(sym);
2148 if (takeoff && oc_of_sym != MAXOCLASSES) {
2149 if (index(extra_removeables, oc_of_sym)) {
2150 ; /* skip rest of takeoff checks */
2151 } else if (!index(removeables, oc_of_sym)) {
2153 pline("Not applicable.");
2155 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2157 } else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
2160 } else if (oc_of_sym == WEAPON_CLASS && !uwep && !uswapwep
2163 You("are not wielding anything.");
2165 You("
\89½
\82à
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
2167 } else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
2169 You("are not wearing rings.");
2171 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
2173 } else if (oc_of_sym == AMULET_CLASS && !uamul) {
2175 You("are not wearing an amulet.");
2177 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
2179 } else if (oc_of_sym == TOOL_CLASS && !ublindf) {
2181 You("are not wearing a blindfold.");
2183 You("
\96Ú
\89B
\82µ
\82ð
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
2188 if (oc_of_sym == COIN_CLASS && !combo) {
2190 } else if (sym == 'a') {
2192 } else if (sym == 'A') {
2193 ; /* same as the default */
2194 } else if (sym == 'u') {
2195 add_valid_menu_class('u');
2197 } else if (index("BUCX", sym)) {
2198 add_valid_menu_class(sym); /* 'B','U','C',or 'X' */
2200 } else if (sym == 'm') {
2202 } else if (oc_of_sym == MAXOCLASSES) {
2204 You("don't have any %c's.", sym);
2206 You("%c
\82É
\91®
\82·
\82é
\95¨
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", sym);
2207 } else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */
2208 if (!index(olets, oc_of_sym)) {
2209 add_valid_menu_class(oc_of_sym);
2210 olets[oletct++] = oc_of_sym;
2218 || (!oletct && ckfn != ckunpaid && ckfn != ckvalidcat))
2220 } else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) {
2223 /* !!!! test gold dropping */
2224 } else if (allowgold == 2 && !oletct) {
2225 return 1; /* you dropped gold (or at least tried to) */
2228 int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
2230 * askchain() has already finished the job in this case
2231 * so set a special flag to convey that back to the caller
2232 * so that it won't continue processing.
2233 * Fix for bug C331-1 reported by Irina Rempt-Drijfhout.
2235 if (combo && allflag && resultflags)
2236 *resultflags |= ALL_FINISHED;
2242 * Walk through the chain starting at objchn and ask for all objects
2243 * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
2244 * whether the action in question (i.e., fn) has to be performed.
2245 * If allflag then no questions are asked. Mx gives the max number
2246 * of objects to be treated. Return the number of objects treated.
2248 /*JP CHECK: 3.6.0
\82Å
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
2249 invent.c:1886: int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
2250 pickup.c:3145: if (askchain(objlist, (one_by_one ? (char *) 0 : selection), allflag,
2251 word
\82É
\82Í
\93®
\8e\8c\82ª
\89p
\8cê
\82Å
\93ü
\82é
\81B
2254 askchain(objchn, olets, allflag, fn, ckfn, mx, word)
2255 struct obj **objchn; /* *objchn might change */
2257 const char *olets, *word; /* olets is an Obj Class char array */
2258 int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
2260 struct obj *otmp, *otmpo;
2261 register char sym, ilet;
2262 int cnt = 0, dud = 0, tmp;
2263 boolean takeoff, nodot, ident, take_out, put_in, first, ininv, bycat;
2264 char qbuf[QBUFSZ], qpfx[QBUFSZ];
2265 Loot *sortedchn = 0;
2267 takeoff = taking_off(word);
2268 ident = !strcmp(word, "identify");
2269 take_out = !strcmp(word, "take out");
2270 put_in = !strcmp(word, "put in");
2271 nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
2272 || takeoff || take_out || put_in);
2273 ininv = (*objchn == invent);
2274 bycat = (menu_class_present('u')
2275 || menu_class_present('B') || menu_class_present('U')
2276 || menu_class_present('C') || menu_class_present('X'));
2278 /* someday maybe we'll sort by 'olets' too (temporarily replace
2279 flags.packorder and pass SORTLOOT_PACK), but not yet... */
2280 sortedchn = sortloot(objchn, SORTLOOT_INVLET, FALSE,
2281 (boolean FDECL((*), (OBJ_P))) 0);
2285 * Interrogate in the object class order specified.
2286 * For example, if a person specifies =/ then first all rings
2287 * will be asked about followed by all wands. -dgk
2291 if (*objchn && (*objchn)->oclass == COIN_CLASS)
2292 ilet--; /* extra iteration */
2294 * Multiple Drop can change the invent chain while it operates
2295 * (dropping a burning potion of oil while levitating creates
2296 * an explosion which can destroy inventory items), so simple
2298 * for (otmp = *objchn; otmp; otmp = otmp2) {
2299 * otmp2 = otmp->nobj;
2302 * is inadequate here. Use each object's bypass bit to keep
2303 * track of which list elements have already been processed.
2305 bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */
2306 while ((otmp = nxt_unbypassed_loot(sortedchn, *objchn)) != 0) {
2309 else if (ilet == 'Z')
2310 ilet = NOINVSYM; /* '#' */
2313 if (olets && *olets && otmp->oclass != *olets)
2315 if (takeoff && !is_worn(otmp))
2317 if (ident && !not_fully_identified(otmp))
2319 if (ckfn && !(*ckfn)(otmp))
2321 if (bycat && !ckvalidcat(otmp))
2324 safeq_xprn_ctx.let = ilet;
2325 safeq_xprn_ctx.dot = !nodot;
2328 /* traditional_loot() skips prompting when only one
2329 class of objects is involved, so prefix the first
2330 object being queried here with an explanation why */
2331 if (take_out || put_in)
2332 Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
2336 (void) safe_qbuf(qbuf, qpfx, "?", otmp,
2337 ininv ? safeq_xprname : doname,
2338 ininv ? safeq_shortxprname : ansimpleoname,
2341 (void) safe_qbuf(qbuf, qpfx, "
\81H", otmp,
2342 ininv ? safeq_xprname : doname,
2343 ininv ? safeq_shortxprname : ansimpleoname,
2344 "
\83A
\83C
\83e
\83\80");
2346 sym = (takeoff || ident || otmp->quan < 2L) ? nyaq(qbuf)
2353 /* Number was entered; split the object unless it corresponds
2354 to 'none' or 'all'. 2 special cases: cursed loadstones and
2355 welded weapons (eg, multiple daggers) will remain as merged
2356 unit; done to avoid splitting an object that won't be
2357 droppable (even if we're picking up rather than dropping). */
2362 if (yn_number < otmp->quan && splittable(otmp))
2363 otmp = splitobj(otmp, yn_number);
2373 if (container_gone(fn)) {
2374 /* otmp caused magic bag to explode;
2375 both are now gone */
2376 otmp = 0; /* and return */
2377 } else if (otmp && otmp != otmpo) {
2378 /* split occurred, merge again */
2379 (void) merged(&otmpo, &otmp);
2393 /* special case for seffects() */
2399 if (olets && *olets && *++olets)
2402 if (!takeoff && (dud || cnt))
2404 pline("That was all.");
2406 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
2407 else if (!dud && !cnt)
2409 pline("No applicable objects.");
2411 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2413 unsortloot(&sortedchn);
2414 bypass_objlist(*objchn, FALSE);
2419 * Object identification routines:
2422 /* make an object actually be identified; no display updating */
2424 fully_identify_obj(otmp)
2427 makeknown(otmp->otyp);
2428 if (otmp->oartifact)
2429 discover_artifact((xchar) otmp->oartifact);
2430 otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
2431 if (Is_container(otmp) || otmp->otyp == STATUE)
2432 otmp->cknown = otmp->lknown = 1;
2433 if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
2434 learn_egg_type(otmp->corpsenm);
2437 /* ggetobj callback routine; identify an object and give immediate feedback */
2442 fully_identify_obj(otmp);
2443 prinv((char *) 0, otmp, 0L);
2447 /* menu of unidentified objects; select and identify up to id_limit of them */
2449 menu_identify(id_limit)
2452 menu_item *pick_list;
2453 int n, i, first = 1, tryct = 5;
2455 /* assumptions: id_limit > 0 and at least one unID'd item is present */
2459 Sprintf(buf, "What would you like to identify %s?",
2460 first ? "first" : "next");
2462 Sprintf(buf, "
\82Ç
\82ê
\82ð%s
\82É
\8e¯
\95Ê
\82µ
\82Ü
\82·
\82©
\81H",
2463 first ? "
\8dÅ
\8f\89" : "
\8e\9f");
2465 n = query_objlist(buf, &invent, (SIGNAL_NOMENU | SIGNAL_ESCAPE
2466 | USE_INVLET | INVORDER_SORT),
2467 &pick_list, PICK_ANY, not_fully_identified);
2472 for (i = 0; i < n; i++, id_limit--)
2473 (void) identify(pick_list[i].item.a_obj);
2474 free((genericptr_t) pick_list);
2475 mark_synch(); /* Before we loop to pop open another menu */
2477 } else if (n == -2) { /* player used ESC to quit menu */
2479 } else if (n == -1) { /* no eligible items found */
2481 pline("That was all.");
2483 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
2485 } else if (!--tryct) { /* stop re-prompting */
2486 pline1(thats_enough_tries);
2488 } else { /* try again */
2490 pline("Choose an item; use ESC to decline.");
2492 pline("
\83A
\83C
\83e
\83\80\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢;
\82â
\82ß
\82é
\82È
\82çESC
\81D");
2496 /* count the unidentified items */
2498 count_unidentified(objchn)
2504 for (obj = objchn; obj; obj = obj->nobj)
2505 if (not_fully_identified(obj))
2510 /* dialog with user to identify a given number of items; 0 means all */
2512 identify_pack(id_limit, learning_id)
2514 boolean learning_id; /* true if we just read unknown identify scroll */
2517 int n, unid_cnt = count_unidentified(invent);
2521 You("have already identified all %sof your possessions.",
2522 learning_id ? "the rest " : "");
2524 You("%s
\91S
\82Ä
\82Ì
\8f\8a\97L
\95¨
\82ð
\8e¯
\95Ê
\82µ
\82Ä
\82µ
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D",
2525 learning_id ? "
\8ec
\82è" : "");
2527 } else if (!id_limit || id_limit >= unid_cnt) {
2528 /* identify everything */
2529 /* TODO: use fully_identify_obj and cornline/menu/whatever here */
2530 for (obj = invent; obj; obj = obj->nobj) {
2531 if (not_fully_identified(obj)) {
2532 (void) identify(obj);
2538 /* identify up to `id_limit' items */
2540 if (flags.menu_style == MENU_TRADITIONAL)
2542 n = ggetobj("identify", identify, id_limit, FALSE,
2545 break; /* quit or no eligible items */
2546 } while ((id_limit -= n) > 0);
2547 if (n == 0 || n < -1)
2548 menu_identify(id_limit);
2553 /* called when regaining sight; mark inventory objects which were picked
2554 up while blind as now having been seen */
2556 learn_unseen_invent()
2561 return; /* sanity check */
2563 for (otmp = invent; otmp; otmp = otmp->nobj) {
2565 continue; /* already seen */
2566 /* set dknown, perhaps bknown (for priest[ess]) */
2569 * If object->eknown gets implemented (see learnwand(zap.c)),
2570 * handle deferred discovery here.
2576 /* should of course only be called for things in invent */
2581 if (!flags.invlet_constant) {
2582 obj->invlet = NOINVSYM;
2589 * Print the indicated quantity of the given object. If quan == 0L then use
2590 * the current quantity.
2593 prinv(prefix, obj, quan)
2601 pline("%s%s%s", prefix, *prefix ? " " : "",
2602 xprname(obj, (char *) 0, obj_to_let(obj), TRUE, 0L, quan));
2605 xprname(obj, (char *)0, obj_to_let(obj), *prefix ? FALSE : TRUE, 0L, quan),
2611 xprname(obj, txt, let, dot, cost, quan)
2613 const char *txt; /* text to print instead of obj */
2614 char let; /* inventory letter */
2615 boolean dot; /* append period; (dot && cost => Iu) */
2616 long cost; /* cost (for inventory of unpaid or expended items) */
2617 long quan; /* if non-0, print this quantity, not obj->quan */
2619 #ifdef LINT /* handle static char li[BUFSZ]; */
2622 static char li[BUFSZ];
2624 boolean use_invlet = (flags.invlet_constant
2625 && let != CONTAINED_SYM && let != HANDS_SYM);
2629 savequan = obj->quan;
2634 * - Then obj == null and 'txt' refers to hands or fingers.
2635 * * Then obj == null and we are printing a total amount.
2636 * > Then the object is contained and doesn't have an inventory letter.
2638 if (cost != 0 || let == '*') {
2639 /* if dot is true, we're doing Iu, otherwise Ix */
2642 iflags.menu_tab_sep ? "%c - %s\t%6ld %s"
2643 : "%c - %-45s %6ld %s",
2644 (dot && use_invlet ? obj->invlet : let),
2645 (txt ? txt : doname(obj)), cost, currency(cost));
2648 iflags.menu_tab_sep ? "%c - %s\t%6ld%s"
2649 : "%c - %-45s %6ld%s",
2650 (dot && use_invlet ? obj->invlet : let),
2651 (txt ? txt : doname(obj)), cost, currency(cost));
2654 /* ordinary inventory display or pickup message */
2655 Sprintf(li, "%c - %s%s", (use_invlet ? obj->invlet : let),
2657 (txt ? txt : doname(obj)), (dot ? "." : ""));
2659 (txt ? txt : doname(obj)), (dot ? "
\81D" : ""));
2662 obj->quan = savequan;
2667 /* the 'i' command */
2671 (void) display_inventory((char *) 0, FALSE);
2678 * Scan the given list of objects. If last_found is NULL, return the first
2679 * unpaid object found. If last_found is not NULL, then skip over unpaid
2680 * objects until last_found is reached, then set last_found to NULL so the
2681 * next unpaid object is returned. This routine recursively follows
2684 STATIC_OVL struct obj *
2685 find_unpaid(list, last_found)
2686 struct obj *list, **last_found;
2693 /* still looking for previous unpaid object */
2694 if (list == *last_found)
2695 *last_found = (struct obj *) 0;
2697 return ((*last_found = list));
2699 if (Has_contents(list)) {
2700 if ((obj = find_unpaid(list->cobj, last_found)) != 0)
2705 return (struct obj *) 0;
2708 /* for perm_invent when operating on a partial inventory display, so that
2709 the persistent one doesn't get shrunk during filtering for item selection
2710 then regrown to full inventory, possibly being resized in the process */
2711 static winid cached_pickinv_win = WIN_ERR;
2714 free_pickinv_cache()
2716 if (cached_pickinv_win != WIN_ERR) {
2717 destroy_nhwindow(cached_pickinv_win);
2718 cached_pickinv_win = WIN_ERR;
2723 * Internal function used by display_inventory and getobj that can display
2724 * inventory and return a count as well as a letter. If out_cnt is not null,
2725 * any count returned from the menu selection is placed here.
2728 display_pickinv(lets, xtra_choice, query, want_reply, out_cnt)
2729 register const char *lets;
2730 const char *xtra_choice; /* "fingers", pick hands rather than an object */
2736 static const char not_carrying_anything[] = "Not carrying anything";
2738 static const char not_carrying_anything[] = "
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢";
2739 struct obj *otmp, wizid_fakeobj;
2741 char *invlet = flags.inv_order;
2743 winid win; /* windows being used */
2745 menu_item *selected;
2747 Loot *sortedinvent, *srtinv;
2748 boolean wizid = FALSE;
2751 lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
2753 if (iflags.perm_invent && (lets || xtra_choice)) {
2754 /* partial inventory in perm_invent setting; don't operate on
2755 full inventory window, use an alternate one instead; create
2756 the first time needed and keep it for re-use as needed later */
2757 if (cached_pickinv_win == WIN_ERR)
2758 cached_pickinv_win = create_nhwindow(NHW_MENU);
2759 win = cached_pickinv_win;
2764 * Exit early if no inventory -- but keep going if we are doing
2765 * a permanent inventory update. We need to keep going so the
2766 * permanent inventory window updates itself to remove the last
2767 * item(s) dropped. One down side: the addition of the exception
2768 * for permanent inventory window updates _can_ pop the window
2769 * up when it's not displayed -- even if it's empty -- because we
2770 * don't know at this level if its up or not. This may not be
2771 * an issue if empty checks are done before hand and the call
2772 * to here is short circuited away.
2774 * 2: our count here is only to distinguish between 0 and 1 and
2775 * more than 1; for the last one, we don't need a precise number.
2776 * For perm_invent update we force 'more than 1'.
2778 n = (iflags.perm_invent && !lets && !want_reply) ? 2
2779 : lets ? (int) strlen(lets)
2780 : !invent ? 0 : !invent->nobj ? 1 : 2;
2781 /* for xtra_choice, there's another 'item' not included in initial 'n';
2782 for !lets (full invent) and for override_ID (wizard mode identify),
2783 skip message_menu handling of single item even if item count was 1 */
2784 if (xtra_choice || (n == 1 && (!lets || iflags.override_ID)))
2789 pline("%s.", not_carrying_anything);
2791 pline("%s
\81D", not_carrying_anything);
2795 /* oxymoron? temporarily assign permanent inventory letters */
2796 if (!flags.invlet_constant)
2799 if (n == 1 && !iflags.force_invmenu) {
2800 /* when only one item of interest, use pline instead of menus;
2801 we actually use a fake message-line menu in order to allow
2802 the user to perform selection at the --More-- prompt for tty */
2805 /* xtra_choice is "bare hands" (wield), "fingertip" (Engrave),
2806 "nothing" (ready Quiver), or "fingers" (apply grease) */
2807 ret = message_menu(HANDS_SYM, PICK_ONE,
2808 xprname((struct obj *) 0, xtra_choice,
2809 HANDS_SYM, TRUE, 0L, 0L)); /* '-' */
2811 for (otmp = invent; otmp; otmp = otmp->nobj)
2812 if (!lets || otmp->invlet == lets[0])
2815 ret = message_menu(otmp->invlet,
2816 want_reply ? PICK_ONE : PICK_NONE,
2817 xprname(otmp, (char *) 0, lets[0],
2821 *out_cnt = -1L; /* select all */
2825 sortflags = (flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET;
2827 sortflags |= SORTLOOT_PACK;
2828 sortedinvent = sortloot(&invent, sortflags, FALSE,
2829 (boolean FDECL((*), (OBJ_P))) 0);
2833 if (wizard && iflags.override_ID) {
2835 char prompt[QBUFSZ];
2837 unid_cnt = count_unidentified(invent);
2838 Sprintf(prompt, "Debug Identify"); /* 'title' rather than 'prompt' */
2840 Sprintf(eos(prompt),
2841 " -- unidentified or partially identified item%s",
2843 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, prompt, MENU_UNSELECTED);
2845 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
2846 "(all items are permanently identified already)",
2849 any.a_obj = &wizid_fakeobj;
2850 Sprintf(prompt, "select %s to permanently identify",
2851 (unid_cnt == 1) ? "it": "any or all of them");
2852 /* wiz_identify stuffed the wiz_identify command character (^I)
2853 into iflags.override_ID for our use as an accelerator;
2854 it could be ambiguous if player has assigned a letter to
2855 the #wizidentify command */
2857 Sprintf(eos(prompt), " (%s for all)",
2858 visctrl(iflags.override_ID));
2859 add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
2860 prompt, MENU_UNSELECTED);
2863 } else if (xtra_choice) {
2864 /* wizard override ID and xtra_choice are mutually exclusive */
2866 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2867 "Miscellaneous", MENU_UNSELECTED);
2868 any.a_char = HANDS_SYM; /* '-' */
2869 add_menu(win, NO_GLYPH, &any, HANDS_SYM, 0, ATR_NONE,
2870 xtra_choice, MENU_UNSELECTED);
2874 for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
2875 if (lets && !index(lets, otmp->invlet))
2877 if (!flags.sortpack || otmp->oclass == *invlet) {
2878 if (wizid && !not_fully_identified(otmp))
2880 any = zeroany; /* all bits zero */
2881 ilet = otmp->invlet;
2882 if (flags.sortpack && !classcount) {
2883 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2884 let_to_name(*invlet, FALSE,
2885 (want_reply && iflags.menu_head_objsym)),
2893 add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng), &any, ilet,
2894 wizid ? def_oc_syms[(int) otmp->oclass].sym : 0,
2895 ATR_NONE, doname(otmp), MENU_UNSELECTED);
2898 if (flags.sortpack) {
2901 if (--invlet != venom_inv) {
2906 if (iflags.force_invmenu && lets && want_reply) {
2909 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2910 "Special", MENU_UNSELECTED);
2912 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2913 "
\93Á
\8eê", MENU_UNSELECTED);
2917 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
2918 "(list everything)", MENU_UNSELECTED);
2920 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
2921 "(
\91S
\82Ä
\82Ì
\88ê
\97\97)", MENU_UNSELECTED);
2924 unsortloot(&sortedinvent);
2925 /* for permanent inventory where we intend to show everything but
2926 nothing has been listed (because there isn't anyhing to list;
2927 recognized via any.a_char still being zero; the n==0 case above
2928 gets skipped for perm_invent), put something into the menu */
2929 if (iflags.perm_invent && !lets && !any.a_char) {
2931 add_menu(win, NO_GLYPH, &any, 0, 0, 0,
2932 not_carrying_anything, MENU_UNSELECTED);
2935 end_menu(win, query && *query ? query : (char *) 0);
2937 n = select_menu(win,
2938 wizid ? PICK_ANY : want_reply ? PICK_ONE : PICK_NONE,
2945 for (i = 0; i < n; ++i) {
2946 otmp = selected[i].item.a_obj;
2947 if (otmp == &wizid_fakeobj) {
2948 identify_pack(0, FALSE);
2950 if (not_fully_identified(otmp))
2951 (void) identify(otmp);
2955 ret = selected[0].item.a_char;
2957 *out_cnt = selected[0].count;
2959 free((genericptr_t) selected);
2961 ret = !n ? '\0' : '\033'; /* cancelled */
2967 * If lets == NULL or "", list all objects in the inventory. Otherwise,
2968 * list all objects with object classes that match the order in lets.
2970 * Returns the letter identifier of a selected item, or 0 if nothing
2974 display_inventory(lets, want_reply)
2978 return display_pickinv(lets, (char *) 0, (char *) 0,
2979 want_reply, (long *) 0);
2983 * Show what is current using inventory letters.
2987 display_used_invlets(avoidlet)
2992 char *invlet = flags.inv_order;
2993 int n, classcount, invdone = 0;
2996 menu_item *selected;
2999 win = create_nhwindow(NHW_MENU);
3002 any = zeroany; /* set all bits to zero */
3004 for (otmp = invent; otmp; otmp = otmp->nobj) {
3005 ilet = otmp->invlet;
3006 if (ilet == avoidlet)
3008 if (!flags.sortpack || otmp->oclass == *invlet) {
3009 if (flags.sortpack && !classcount) {
3010 any = zeroany; /* zero */
3011 add_menu(win, NO_GLYPH, &any, 0, 0,
3012 iflags.menu_headings,
3013 let_to_name(*invlet, FALSE, FALSE),
3018 add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng),
3019 &any, ilet, 0, ATR_NONE,
3020 doname(otmp), MENU_UNSELECTED);
3023 if (flags.sortpack && *++invlet)
3027 end_menu(win, "Inventory letters used:");
3029 n = select_menu(win, PICK_ONE, &selected);
3031 ret = selected[0].item.a_char;
3032 free((genericptr_t) selected);
3034 ret = !n ? '\0' : '\033'; /* cancelled */
3035 destroy_nhwindow(win);
3041 * Returns the number of unpaid items within the given list. This includes
3042 * contained objects.
3053 if (Has_contents(list))
3054 count += count_unpaid(list->cobj);
3061 * Returns the number of items with b/u/c/unknown within the given list.
3062 * This does NOT include contained objects.
3064 * Assumes that the hero sees or touches or otherwise senses the objects
3065 * at some point: bknown is forced for priest[ess], like in xname().
3068 count_buc(list, type, filterfunc)
3071 boolean FDECL((*filterfunc), (OBJ_P));
3075 for (; list; list = list->nobj) {
3076 /* priests always know bless/curse state */
3077 if (Role_if(PM_PRIEST))
3078 list->bknown = (list->oclass != COIN_CLASS);
3079 /* some actions exclude some or most items */
3080 if (filterfunc && !(*filterfunc)(list))
3083 /* coins are either uncursed or unknown based upon option setting */
3084 if (list->oclass == COIN_CLASS) {
3085 if (type == (iflags.goldX ? BUC_UNKNOWN : BUC_UNCURSED))
3089 /* check whether this object matches the requested type */
3091 ? (type == BUC_UNKNOWN)
3092 : list->blessed ? (type == BUC_BLESSED)
3093 : list->cursed ? (type == BUC_CURSED)
3094 : (type == BUC_UNCURSED))
3100 /* similar to count_buc(), but tallies all states at once
3101 rather than looking for a specific type */
3103 tally_BUCX(list, by_nexthere, bcp, ucp, ccp, xcp, ocp)
3105 boolean by_nexthere;
3106 int *bcp, *ucp, *ccp, *xcp, *ocp;
3108 /* Future extensions:
3109 * Skip current_container when list is invent, uchain when
3110 * first object of list is located on the floor. 'ocp' will then
3111 * have a function again (it was a counter for having skipped gold,
3112 * but that's not skipped anymore).
3114 *bcp = *ucp = *ccp = *xcp = *ocp = 0;
3115 for ( ; list; list = (by_nexthere ? list->nexthere : list->nobj)) {
3116 /* priests always know bless/curse state */
3117 if (Role_if(PM_PRIEST))
3118 list->bknown = (list->oclass != COIN_CLASS);
3119 /* coins are either uncursed or unknown based upon option setting */
3120 if (list->oclass == COIN_CLASS) {
3127 /* ordinary items */
3130 else if (list->blessed)
3132 else if (list->cursed)
3134 else /* neither blessed nor cursed => uncursed */
3139 /* count everything inside a container, or just shop-owned items inside */
3141 count_contents(container, nested, quantity, everything)
3142 struct obj *container;
3143 boolean nested, /* include contents of any nested containers */
3144 quantity, /* count all vs count separate stacks */
3145 everything; /* all objects vs only unpaid objects */
3147 struct obj *otmp, *topc;
3148 boolean shoppy = FALSE;
3152 for (topc = container; topc->where == OBJ_CONTAINED;
3153 topc = topc->ocontainer)
3155 if (topc->where == OBJ_FLOOR) {
3158 (void) get_obj_location(topc, &x, &y, CONTAINED_TOO);
3159 shoppy = costly_spot(x, y);
3162 for (otmp = container->cobj; otmp; otmp = otmp->nobj) {
3163 if (nested && Has_contents(otmp))
3164 count += count_contents(otmp, nested, quantity, everything);
3165 if (everything || otmp->unpaid || (shoppy && !otmp->no_charge))
3166 count += quantity ? otmp->quan : 1L;
3175 struct obj *otmp, *marker, *contnr;
3177 char *invlet = flags.inv_order;
3178 int classcount, count, num_so_far;
3181 count = count_unpaid(invent);
3182 otmp = marker = contnr = (struct obj *) 0;
3185 otmp = find_unpaid(invent, &marker);
3186 contnr = unknwn_contnr_contents(otmp);
3188 if (otmp && !contnr) {
3189 /* 1 item; use pline instead of popup menu */
3190 cost = unpaid_cost(otmp, FALSE);
3191 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
3192 pline1(xprname(otmp, distant_name(otmp, doname),
3193 carried(otmp) ? otmp->invlet : CONTAINED_SYM,
3195 iflags.suppress_price--;
3199 win = create_nhwindow(NHW_MENU);
3201 num_so_far = 0; /* count of # printed so far */
3202 if (!flags.invlet_constant)
3207 for (otmp = invent; otmp; otmp = otmp->nobj) {
3208 ilet = otmp->invlet;
3210 if (!flags.sortpack || otmp->oclass == *invlet) {
3211 if (flags.sortpack && !classcount) {
3212 putstr(win, 0, let_to_name(*invlet, TRUE, FALSE));
3216 totcost += cost = unpaid_cost(otmp, FALSE);
3217 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
3218 putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
3219 ilet, TRUE, cost, 0L));
3220 iflags.suppress_price--;
3225 } while (flags.sortpack && (*++invlet));
3227 if (count > num_so_far) {
3228 /* something unpaid is contained */
3230 putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE, FALSE));
3232 * Search through the container objects in the inventory for
3233 * unpaid items. The top level inventory items have already
3236 for (otmp = invent; otmp; otmp = otmp->nobj) {
3237 if (Has_contents(otmp)) {
3240 marker = (struct obj *) 0; /* haven't found any */
3241 while (find_unpaid(otmp->cobj, &marker)) {
3242 totcost += cost = unpaid_cost(marker, FALSE);
3245 iflags.suppress_price++; /* suppress "(unpaid)" sfx */
3247 xprname(marker, distant_name(marker, doname),
3248 CONTAINED_SYM, TRUE, cost, 0L));
3249 iflags.suppress_price--;
3252 if (!otmp->cknown) {
3253 char contbuf[BUFSZ];
3255 /* Shopkeeper knows what to charge for contents */
3256 Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
3258 xprname((struct obj *) 0, contbuf, CONTAINED_SYM,
3259 TRUE, contcost, 0L));
3268 xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
3271 xprname((struct obj *) 0, "
\8d\87\8cv
\81F", '*', FALSE, totcost, 0L));
3273 display_nhwindow(win, FALSE);
3274 destroy_nhwindow(win);
3277 /* query objlist callback: return TRUE if obj type matches "this_type" */
3278 static int this_type;
3284 boolean res = (obj->oclass == this_type);
3286 if (obj->oclass == COIN_CLASS) {
3287 /* if filtering by bless/curse state, gold is classified as
3288 either unknown or uncursed based on user option setting */
3289 if (this_type && index("BUCX", this_type))
3290 res = (this_type == (iflags.goldX ? 'X' : 'U'));
3292 switch (this_type) {
3294 res = (obj->bknown && obj->blessed);
3297 res = (obj->bknown && !(obj->blessed || obj->cursed));
3300 res = (obj->bknown && obj->cursed);
3306 break; /* use 'res' as-is */
3312 /* the 'I' command */
3318 char *extra_types, types[BUFSZ];
3319 int class_count, oclass, unpaid_count, itemcount;
3320 int bcnt, ccnt, ucnt, xcnt, ocnt;
3321 boolean billx = *u.ushops && doinvbill(0);
3322 menu_item *pick_list;
3323 boolean traditional = TRUE;
3325 const char *prompt = "What type of object do you want an inventory of?";
3327 const char *prompt = "
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\8e\9d\82¿
\95¨
\82ð
\8c©
\82Ü
\82·
\82©
\81H";
3329 if (!invent && !billx) {
3331 You("aren't carrying anything.");
3333 You("
\82»
\82Ì
\8eí
\97Þ
\82Ì
\95¨
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3336 unpaid_count = count_unpaid(invent);
3337 tally_BUCX(invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
3339 if (flags.menu_style != MENU_TRADITIONAL) {
3340 if (flags.menu_style == MENU_FULL
3341 || flags.menu_style == MENU_PARTIAL) {
3342 traditional = FALSE;
3354 n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
3357 this_type = c = pick_list[0].item.a_int;
3358 free((genericptr_t) pick_list);
3362 /* collect a list of classes of objects carried, for use as a prompt
3365 class_count = collect_obj_classes(types, invent, FALSE,
3366 (boolean FDECL((*), (OBJ_P))) 0,
3368 if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
3369 types[class_count++] = ' ';
3371 types[class_count++] = 'u';
3373 types[class_count++] = 'x';
3375 types[class_count++] = 'B';
3377 types[class_count++] = 'U';
3379 types[class_count++] = 'C';
3381 types[class_count++] = 'X';
3382 types[class_count] = '\0';
3383 /* add everything not already included; user won't see these */
3384 extra_types = eos(types);
3385 *extra_types++ = '\033';
3387 *extra_types++ = 'u';
3389 *extra_types++ = 'x';
3391 *extra_types++ = 'B';
3393 *extra_types++ = 'U';
3395 *extra_types++ = 'C';
3397 *extra_types++ = 'X';
3398 *extra_types = '\0'; /* for index() */
3399 for (i = 0; i < MAXOCLASSES; i++)
3400 if (!index(types, def_oc_syms[i].sym)) {
3401 *extra_types++ = def_oc_syms[i].sym;
3402 *extra_types = '\0';
3405 if (class_count > 1) {
3406 c = yn_function(prompt, types, '\0');
3409 clear_nhwindow(WIN_MESSAGE);
3413 /* only one thing to itemize */
3422 if (c == 'x' || (c == 'X' && billx && !xcnt)) {
3424 (void) doinvbill(1);
3427 pline("No used-up objects%s.",
3428 unpaid_count ? " on your shopping bill" : "");
3430 pline("
\8eg
\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\95¨
\82Í%s
\82È
\82¢
\81D",
3431 unpaid_count ? "
\8f¤
\93X
\82Ì
\90¿
\8b\81\8f\91\82É
\82Í" : "");
3435 if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
3440 You("are not carrying any unpaid objects.");
3442 You("
\96¢
\95¥
\82¢
\82Ì
\83A
\83C
\83e
\83\80\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3446 if (index("BUCX", c))
3447 oclass = c; /* not a class but understood by this_type_only() */
3449 oclass = def_char_to_objclass(c); /* change to object class */
3451 if (oclass == COIN_CLASS)
3453 if (index(types, c) > index(types, '\033')) {
3454 /* '> ESC' => hidden choice, something known not to be carried */
3455 const char *before = "", *after = "";
3460 before = "known to be blessed ";
3462 before = "
\8fj
\95\9f\82³
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3466 before = "known to be uncursed ";
3468 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3472 before = "known to be cursed ";
3474 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3478 after = " whose blessed/uncursed/cursed status is unknown";
3480 after = "
\8fj
\95\9f\81^
\8eô
\82¢
\82ª
\82í
\82©
\82ç
\82È
\82¢";
3481 break; /* better phrasing is desirable */
3483 /* 'c' is an object class, because we've already handled
3484 all the non-class letters which were put into 'types[]';
3485 could/should move object class names[] array from below
3486 to somewhere above so that we can access it here (via
3487 lcase(strcpy(classnamebuf, names[(int) c]))), but the
3488 game-play value of doing so is low... */
3492 before = "
\82»
\82Ì
\82æ
\82¤
\82È";
3496 You("have no %sobjects%s.", before, after);
3498 You("%s%s
\82à
\82Ì
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", before, after);
3503 if (query_objlist((char *) 0, &invent,
3504 ((flags.invlet_constant ? USE_INVLET : 0)
3506 &pick_list, PICK_NONE, this_type_only) > 0)
3507 free((genericptr_t) pick_list);
3511 /* return a string describing the dungeon feature at <x,y> if there
3512 is one worth mentioning at that location; otherwise null */
3514 dfeature_at(x, y, buf)
3518 struct rm *lev = &levl[x][y];
3519 int ltyp = lev->typ, cmap = -1;
3520 const char *dfeature = 0;
3521 static char altbuf[BUFSZ];
3523 if (IS_DOOR(ltyp)) {
3524 switch (lev->doormask) {
3527 break; /* "doorway" */
3530 break; /* "open door" */
3533 dfeature = "broken door";
3535 dfeature = "
\89ó
\82ê
\82½
\94à";
3539 break; /* "closed door" */
3541 /* override door description for open drawbridge */
3542 if (is_drawbridge_wall(x, y) >= 0)
3544 dfeature = "open drawbridge portcullis", cmap = -1;
3546 dfeature = "
\8d~
\82è
\82Ä
\82¢
\82é
\92µ
\82Ë
\8b´", cmap = -1;
3547 } else if (IS_FOUNTAIN(ltyp))
3548 cmap = S_fountain; /* "fountain" */
3549 else if (IS_THRONE(ltyp))
3550 cmap = S_throne; /* "opulent throne" */
3551 else if (is_lava(x, y))
3552 cmap = S_lava; /* "molten lava" */
3553 else if (is_ice(x, y))
3554 cmap = S_ice; /* "ice" */
3555 else if (is_pool(x, y))
3557 dfeature = "pool of water";
3559 dfeature = "
\90\85\82½
\82Ü
\82è";
3560 else if (IS_SINK(ltyp))
3561 cmap = S_sink; /* "sink" */
3562 else if (IS_ALTAR(ltyp)) {
3564 Sprintf(altbuf, "%saltar to %s (%s)",
3565 ((lev->altarmask & AM_SHRINE)
3566 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3570 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3572 Sprintf(altbuf, "%s%s
\82Ì
\8dÕ
\92d(%s)",
3573 ((lev->altarmask & AM_SHRINE)
3574 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3578 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3581 } else if ((x == xupstair && y == yupstair)
3582 || (x == sstairs.sx && y == sstairs.sy && sstairs.up))
3583 cmap = S_upstair; /* "staircase up" */
3584 else if ((x == xdnstair && y == ydnstair)
3585 || (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
3586 cmap = S_dnstair; /* "staircase down" */
3587 else if (x == xupladder && y == yupladder)
3588 cmap = S_upladder; /* "ladder up" */
3589 else if (x == xdnladder && y == ydnladder)
3590 cmap = S_dnladder; /* "ladder down" */
3591 else if (ltyp == DRAWBRIDGE_DOWN)
3592 cmap = S_vodbridge; /* "lowered drawbridge" */
3593 else if (ltyp == DBWALL)
3594 cmap = S_vcdbridge; /* "raised drawbridge" */
3595 else if (IS_GRAVE(ltyp))
3596 cmap = S_grave; /* "grave" */
3597 else if (ltyp == TREE)
3598 cmap = S_tree; /* "tree" */
3599 else if (ltyp == IRONBARS)
3601 dfeature = "set of iron bars";
3603 dfeature = "
\93S
\82Ì
\96_";
3606 dfeature = defsyms[cmap].explanation;
3608 Strcpy(buf, dfeature);
3612 /* look at what is here; if there are many objects (pile_limit or more),
3613 don't show them unless obj_cnt is 0 */
3615 look_here(obj_cnt, picked_some)
3616 int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progress */
3617 boolean picked_some;
3622 const char *verb = Blind ? "feel" : "see";
3624 const char *verb = Blind ? "
\82ª
\82 \82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½" : "
\82ð
\82Ý
\82Â
\82¯
\82½";
3626 const char *dfeature = (char *) 0;
3627 char fbuf[BUFSZ], fbuf2[BUFSZ];
3629 boolean skip_objects, felt_cockatrice = FALSE;
3631 /* default pile_limit is 5; a value of 0 means "never skip"
3632 (and 1 effectively forces "always skip") */
3633 skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
3634 if (u.uswallow && u.ustuck) {
3635 struct monst *mtmp = u.ustuck;
3638 Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
3639 mbodypart(mtmp, STOMACH));
3641 Sprintf(fbuf, "%s
\82Ì%s
\82Ì
\92\86\90g", mon_nam(mtmp),
3642 mbodypart(mtmp, STOMACH));
3644 #if 0 /*JP*//*
\8cê
\8f\87\82ª
\88á
\82¤
\82Ì
\82Å
\91f
\92¼
\82É*/
3645 /* Skip "Contents of " by using fbuf index 12 */
3646 You("%s to %s what is lying in %s.", Blind ? "try" : "look around",
3649 You("%s
\82Ì%s
\82É
\89½
\82ª
\82 \82é
\82©%s
\81D",
3650 mon_nam(mtmp), mbodypart(mtmp, STOMACH),
3651 Blind ? "
\82³
\82®
\82Á
\82½" : "
\8c©
\89ñ
\82µ
\82½");
3653 otmp = mtmp->minvent;
3655 for (; otmp; otmp = otmp->nobj) {
3656 /* If swallower is an animal, it should have become stone
3658 if (otmp->otyp == CORPSE)
3659 feel_cockatrice(otmp, FALSE);
3663 Strcpy(fbuf, "You feel");
3666 Sprintf(fbuf, "
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F", Blind ? "
\82ç
\82µ
\82¢" : "");
3668 (void) display_minventory(mtmp, MINV_ALL | PICK_NONE, fbuf);
3671 You("%s no objects here.", verb);
3673 pline(Blind ? "
\82 \82È
\82½
\82Í
\89½
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D"
3674 : "
\82 \82È
\82½
\82Í
\89½
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3679 if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen)
3681 There("is %s here.",
3683 pline("
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D",
3684 an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
3686 otmp = level.objects[u.ux][u.uy];
3687 dfeature = dfeature_at(u.ux, u.uy, fbuf2);
3689 if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
3691 if (dfeature && !strcmp(dfeature, "
\90\85\82½
\82Ü
\82è") && Underwater)
3695 boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
3698 if (dfeature && !strncmp(dfeature, "altar ", 6)) {
3700 if (dfeature && !strncmp(dfeature, "
\8dÕ
\92d", 4)) {
3701 /* don't say "altar" twice, dfeature has more info */
3703 You("try to feel what is here.");
3705 You("
\82±
\82±
\82É
\89½
\82ª
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3708 const char *where = (Blind && !can_reach_floor(TRUE))
3709 ? "lying beneath you"
3710 : "lying here on the ",
3711 *onwhat = (Blind && !can_reach_floor(TRUE))
3713 : surface(u.ux, u.uy);
3715 You("try to feel what is %s%s.", drift ? "floating here" : where,
3716 drift ? "" : onwhat);
3719 You("
\89½
\82ª
\95\82\82¢
\82Ä
\82¢
\82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3720 } else if (Blind && !can_reach_floor(TRUE)) {
3721 You("
\89½
\82ª
\91«
\89º
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3723 You("
\89½
\82ª%s
\82Ì
\8fã
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D", surface(u.ux, u.uy));
3727 if (dfeature && !drift && !strcmp(dfeature, surface(u.ux, u.uy)))
3728 dfeature = 0; /* ice already identified */
3729 if (!can_reach_floor(TRUE)) {
3731 pline("But you can't reach it!");
3733 pline("
\82µ
\82©
\82µ
\93Í
\82©
\82È
\82¢
\81I");
3740 Sprintf(fbuf, "There is %s here.", an(dfeature));
3742 Sprintf(fbuf, "
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D", an(dfeature));
3744 if (!otmp || is_lava(u.ux, u.uy)
3745 || (is_pool(u.ux, u.uy) && !Underwater)) {
3748 read_engr_at(u.ux, u.uy); /* Eric Backus */
3749 if (!skip_objects && (Blind || !dfeature))
3751 You("%s no objects here.", verb);
3754 "
\82È
\82É
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82·
\82é
\81D" :
3755 "
\82È
\82É
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3759 /* we know there is something here */
3764 read_engr_at(u.ux, u.uy); /* Eric Backus */
3765 if (obj_cnt == 1 && otmp->quan == 1L)
3767 There("is %s object here.", picked_some ? "another" : "an");
3769 There("
\82±
\82±
\82É
\82Í%s
\88ê
\82Â
\82à
\82Ì
\82ª
\82 \82é
\81D", picked_some ? "
\82à
\82¤" : "");
3772 There("are %s%s objects here.",
3778 picked_some ? " more" : "");
3780 pline("
\82±
\82±
\82É
\82Í%s%s
\82à
\82Ì
\82ª
\82 \82é
\81D",
3781 picked_some ? "
\82³
\82ç
\82É" : "",
3783 ? "
\82¢
\82
\82Â
\82©
\82Ì"
3784 : "
\82½
\82
\82³
\82ñ
\82Ì");
3786 for (; otmp; otmp = otmp->nexthere)
3787 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3788 #if 0 /*JP*//*"It's (corpse_name), unfortunately"*/
3795 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3796 poly_when_stoned(youmonst.data)
3798 : ", unfortunately");
3801 poly_when_stoned(youmonst.data)
3803 : "
\8ec
\94O
\82È
\82ª
\82ç",
3804 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3806 ? "
\82ð
\8aÜ
\82ñ
\82Å
\82¢
\82é"
3809 feel_cockatrice(otmp, FALSE);
3812 } else if (!otmp->nexthere) {
3813 /* only one object */
3816 read_engr_at(u.ux, u.uy); /* Eric Backus */
3818 You("%s here %s.", verb, doname_with_price(otmp));
3820 pline("%s%s
\81D", doname_with_price(otmp), verb);
3821 iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
3822 if (otmp->otyp == CORPSE)
3823 feel_cockatrice(otmp, FALSE);
3827 display_nhwindow(WIN_MESSAGE, FALSE);
3828 tmpwin = create_nhwindow(NHW_MENU);
3830 putstr(tmpwin, 0, fbuf);
3831 putstr(tmpwin, 0, "");
3834 Sprintf(buf, "%s that %s here:",
3835 picked_some ? "Other things" : "Things",
3836 Blind ? "you feel" : "are");
3838 Sprintf(buf, "%s
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F",
3839 picked_some ? "
\91¼
\82É" : "",
3840 Blind ? "
\82ç
\82µ
\82¢" : "");
3842 putstr(tmpwin, 0, buf);
3843 for (; otmp; otmp = otmp->nexthere) {
3844 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3845 felt_cockatrice = TRUE;
3847 Sprintf(buf, "%s...", doname(otmp));
3849 Sprintf(buf, "%s
\81D
\81D
\81D", doname(otmp));
3850 putstr(tmpwin, 0, buf);
3853 putstr(tmpwin, 0, doname_with_price(otmp));
3855 display_nhwindow(tmpwin, TRUE);
3856 destroy_nhwindow(tmpwin);
3857 if (felt_cockatrice)
3858 feel_cockatrice(otmp, FALSE);
3859 read_engr_at(u.ux, u.uy); /* Eric Backus */
3864 /* the ':' command - explicitly look at what is here, including all objects */
3871 MSGTYPE={norep,noshow} "You see here"
3872 interfere with feedback from the look-here command */
3873 hide_unhide_msgtypes(TRUE, MSGTYP_MASK_REP_SHOW);
3874 res = look_here(0, FALSE);
3875 /* restore normal msgtype handling */
3876 hide_unhide_msgtypes(FALSE, MSGTYP_MASK_REP_SHOW);
3881 will_feel_cockatrice(otmp, force_touch)
3883 boolean force_touch;
3885 if ((Blind || force_touch) && !uarmg && !Stone_resistance
3886 && (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
3892 feel_cockatrice(otmp, force_touch)
3894 boolean force_touch;
3898 if (will_feel_cockatrice(otmp, force_touch)) {
3899 /* "the <cockatrice> corpse" */
3900 Strcpy(kbuf, corpse_xname(otmp, (const char *) 0, CXN_PFX_THE));
3902 if (poly_when_stoned(youmonst.data))
3904 You("touched %s with your bare %s.", kbuf,
3905 makeplural(body_part(HAND)));
3907 You("%s
\82Ì
\8e\80\91Ì
\82É
\91f%s
\82Å
\90G
\82Á
\82½
\81D", kbuf,
3912 pline("Touching %s is a fatal mistake...", kbuf);
3914 pline("%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82é
\82Ì
\82Í
\92v
\96½
\93I
\82È
\8aÔ
\88á
\82¢
\82¾
\81D
\81D
\81D", kbuf);
3915 /* normalize body shape here; hand, not body_part(HAND) */
3917 Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
3919 Sprintf(kbuf, "%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82Ä", killer_xname(otmp));
3920 /* will call polymon() for the poly_when_stoned() case */
3931 for (otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
3932 if (otmp != obj && merged(&obj, &otmp))
3937 /* returns TRUE if obj & otmp can be merged; used in invent.c and mkobj.c */
3940 register struct obj *otmp, *obj;
3942 int objnamelth = 0, otmpnamelth = 0;
3944 /* fail if already the same object, if different types, if either is
3945 explicitly marked to prevent merge, or if not mergable in general */
3946 if (obj == otmp || obj->otyp != otmp->otyp
3947 || obj->nomerge || otmp->nomerge || !objects[obj->otyp].oc_merge)
3950 /* coins of the same kind will always merge */
3951 if (obj->oclass == COIN_CLASS)
3954 if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
3955 || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed
3956 || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
3957 || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
3958 || obj->bypass != otmp->bypass)
3963 /* Checks beyond this point either aren't applicable to globs
3964 * or don't inhibit their merger.
3967 if (obj->oclass == FOOD_CLASS
3968 && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
3971 if (obj->dknown != otmp->dknown
3972 || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
3973 || obj->oeroded != otmp->oeroded || obj->oeroded2 != otmp->oeroded2
3974 || obj->greased != otmp->greased)
3977 if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
3978 && (obj->oerodeproof != otmp->oerodeproof
3979 || obj->rknown != otmp->rknown))
3982 if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
3983 if (obj->corpsenm != otmp->corpsenm)
3987 /* hatching eggs don't merge; ditto for revivable corpses */
3988 if ((obj->otyp == EGG && (obj->timed || otmp->timed))
3989 || (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM
3990 && is_reviver(&mons[otmp->corpsenm])))
3993 /* allow candle merging only if their ages are close */
3994 /* see begin_burn() for a reference for the magic "25" */
3995 if (Is_candle(obj) && obj->age / 25 != otmp->age / 25)
3998 /* burning potions of oil never merge */
3999 if (obj->otyp == POT_OIL && obj->lamplit)
4002 /* don't merge surcharged item with base-cost item */
4003 if (obj->unpaid && !same_price(obj, otmp))
4006 /* if they have names, make sure they're the same */
4007 objnamelth = strlen(safe_oname(obj));
4008 otmpnamelth = strlen(safe_oname(otmp));
4009 if ((objnamelth != otmpnamelth
4010 && ((objnamelth && otmpnamelth) || obj->otyp == CORPSE))
4011 || (objnamelth && otmpnamelth
4012 && strncmp(ONAME(obj), ONAME(otmp), objnamelth)))
4015 /* for the moment, any additional information is incompatible */
4016 if (has_omonst(obj) || has_omid(obj) || has_olong(obj) || has_omonst(otmp)
4017 || has_omid(otmp) || has_olong(otmp))
4020 if (obj->oartifact != otmp->oartifact)
4023 if (obj->known == otmp->known || !objects[otmp->otyp].oc_uses_known) {
4024 return (boolean) objects[obj->otyp].oc_merge;
4029 /* the '$' command */
4033 /* the messages used to refer to "carrying gold", but that didn't
4034 take containers into account */
4035 long umoney = money_cnt(invent);
4039 Your("wallet is empty.");
4041 Your("
\8dà
\95z
\82Í
\8bó
\82Á
\82Û
\82¾
\81D");
4044 Your("wallet contains %ld %s.", umoney, currency(umoney));
4046 Your("
\8dà
\95z
\82É
\82Í%ld%s
\93ü
\82Á
\82Ä
\82¢
\82é
\81D", umoney, currency(umoney));
4047 shopper_financial_report();
4051 /* the ')' command */
4057 You("are empty %s.", body_part(HANDED));
4059 if(!uwep) You("%s
\82É
\95\90\8aí
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D", body_part(HAND));
4061 prinv((char *) 0, uwep, 0L);
4063 prinv((char *) 0, uswapwep, 0L);
4068 /* caller is responsible for checking !wearing_armor() */
4070 noarmor(report_uskin)
4071 boolean report_uskin;
4073 if (!uskin || !report_uskin) {
4075 You("are not wearing any armor.");
4077 You("
\8aZ
\82ð
\92\85\82Ä
\82¢
\82È
\82¢
\81D");
4079 char *p, *uskinname, buf[BUFSZ];
4081 uskinname = strcpy(buf, simpleonames(uskin));
4083 /* shorten "set of <color> dragon scales" to "<color> scales"
4084 and "<color> dragon scale mail" to "<color> scale mail" */
4085 if (!strncmpi(uskinname, "set of ", 7))
4087 if ((p = strstri(uskinname, " dragon ")) != 0)
4088 while ((p[1] = p[8]) != '\0')
4090 #else /*
\81u<
\90F>
\83h
\83\89\83S
\83\93\82Ì
\97Ø
\81v
\82ð
\81u<
\90F>
\82Ì
\97Ø
\81v
\82É
\82·
\82é*/
4091 if ((p = strstri(uskinname, "
\83h
\83\89\83S
\83\93\82Ì
\97Ø")) != 0)
4096 You("are not wearing armor but have %s embedded in your skin.",
4098 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",
4103 /* the '[' command */
4108 register int ct = 0;
4110 * Note: players sometimes get here by pressing a function key which
4111 * transmits ''ESC [ <something>'' rather than by pressing '[';
4112 * there's nothing we can--or should-do about that here.
4115 if (!wearing_armor()) {
4119 lets[ct++] = obj_to_let(uarmu);
4121 lets[ct++] = obj_to_let(uarm);
4123 lets[ct++] = obj_to_let(uarmc);
4125 lets[ct++] = obj_to_let(uarmh);
4127 lets[ct++] = obj_to_let(uarms);
4129 lets[ct++] = obj_to_let(uarmg);
4131 lets[ct++] = obj_to_let(uarmf);
4133 (void) display_inventory(lets, FALSE);
4138 /* the '=' command */
4142 if (!uleft && !uright)
4144 You("are not wearing any rings.");
4146 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
4149 register int ct = 0;
4152 lets[ct++] = obj_to_let(uleft);
4154 lets[ct++] = obj_to_let(uright);
4156 (void) display_inventory(lets, FALSE);
4161 /* the '"' command */
4167 You("are not wearing an amulet.");
4169 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
4171 prinv((char *) 0, uamul, 0L);
4179 if ((obj->owornmask & (W_TOOL | W_SADDLE)) != 0L)
4181 if (obj->oclass != TOOL_CLASS)
4183 return (boolean) (obj == uwep || obj->lamplit
4184 || (obj->otyp == LEASH && obj->leashmon));
4187 /* the '(' command */
4195 for (otmp = invent; otmp; otmp = otmp->nobj)
4196 if (tool_in_use(otmp))
4197 lets[ct++] = obj_to_let(otmp);
4201 You("are not using any tools.");
4203 You("
\8eg
\82¦
\82é
\93¹
\8bï
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4205 (void) display_inventory(lets, FALSE);
4209 /* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
4210 show inventory of all currently wielded, worn, or used objects */
4218 for (otmp = invent; otmp; otmp = otmp->nobj)
4219 if (is_worn(otmp) || tool_in_use(otmp))
4220 lets[ct++] = obj_to_let(otmp);
4224 You("are not wearing or wielding anything.");
4226 You("
\89½
\82à
\92\85\82Ä
\82¢
\82È
\82¢
\82µ
\81C
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
4228 (void) display_inventory(lets, FALSE);
4233 * uses up an object that's on the floor, charging for it as necessary
4236 useupf(obj, numused)
4237 register struct obj *obj;
4240 register struct obj *otmp;
4241 boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
4243 /* burn_floor_objects() keeps an object pointer that it tries to
4244 * useupf() multiple times, so obj must survive if plural */
4245 if (obj->quan > numused)
4246 otmp = splitobj(obj, numused);
4249 if (costly_spot(otmp->ox, otmp->oy)) {
4250 if (index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
4251 addtobill(otmp, FALSE, FALSE, FALSE);
4253 (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
4256 if (at_u && u.uundetected && hides_under(youmonst.data))
4257 (void) hideunder(&youmonst);
4261 * Conversion from a class to a string for printing.
4262 * This must match the object class order.
4264 STATIC_VAR NEARDATA const char *names[] = {
4266 0, "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", "Tools",
4267 "Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
4268 "Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
4270 0, "
\96
\82È
\95¨
\91Ì", "
\95\90\8aí", "
\8aZ", "
\8ew
\97Ö", "
\96\82\8f\9c\82¯", "
\93¹
\8bï",
4271 "
\90H
\97¿", "
\96ò", "
\8aª
\95¨", "
\96\82\96@
\8f\91", "
\8fñ", "
\8bà
\89Ý",
4272 "
\95ó
\90Î", "
\8aâ
\82Ü
\82½
\82Í
\92¤
\91\9c", "
\93S
\8b\85", "
\8d½", "
\93Å"
4275 STATIC_VAR NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
4277 STATIC_VAR NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
4279 STATIC_VAR NEARDATA const char *oth_names[] = { "
\8bl
\82ß
\82ç
\82ê
\82½
\93¹
\8bï" };
4281 STATIC_VAR NEARDATA char *invbuf = (char *) 0;
4282 STATIC_VAR NEARDATA unsigned invbufsiz = 0;
4285 let_to_name(let, unpaid, showsym)
4287 boolean unpaid, showsym;
4289 const char *ocsymfmt = " ('%c')";
4290 const int invbuf_sympadding = 8; /* arbitrary */
4291 const char *class_name;
4293 int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
4297 class_name = names[oclass];
4298 else if ((pos = index(oth_symbols, let)) != 0)
4299 class_name = oth_names[pos - oth_symbols];
4301 class_name = names[0];
4304 len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "")
4306 len = strlen(class_name) + (unpaid ? sizeof "
\96¢
\95¥
\82¢
\82Ì" : sizeof "")
4307 + (oclass ? (strlen(ocsymfmt) + invbuf_sympadding) : 0);
4308 if (len > invbufsiz) {
4310 free((genericptr_t) invbuf);
4311 invbufsiz = len + 10; /* add slop to reduce incremental realloc */
4312 invbuf = (char *) alloc(invbufsiz);
4316 Strcat(strcpy(invbuf, "Unpaid "), class_name);
4318 Strcat(strcpy(invbuf, "
\96¢
\95¥
\82¢
\82Ì"), class_name);
4320 Strcpy(invbuf, class_name);
4321 if ((oclass != 0) && showsym) {
4322 char *bp = eos(invbuf);
4323 int mlen = invbuf_sympadding - strlen(class_name);
4324 while (--mlen > 0) {
4329 Sprintf(eos(invbuf), ocsymfmt, def_oc_syms[oclass].sym);
4334 /* release the static buffer used by let_to_name() */
4339 free((genericptr_t) invbuf), invbuf = (char *) 0;
4343 /* give consecutive letters to every item in inventory (for !fixinv mode);
4344 gold is always forced to '$' slot at head of list */
4349 struct obj *obj, *prevobj, *goldobj;
4351 /* first, remove [first instance of] gold from invent, if present */
4352 prevobj = goldobj = 0;
4353 for (obj = invent; obj; prevobj = obj, obj = obj->nobj)
4354 if (obj->oclass == COIN_CLASS) {
4357 prevobj->nobj = goldobj->nobj;
4359 invent = goldobj->nobj;
4362 /* second, re-letter the rest of the list */
4363 for (obj = invent, i = 0; obj; obj = obj->nobj, i++)
4365 (i < 26) ? ('a' + i) : (i < 52) ? ('A' + i - 26) : NOINVSYM;
4366 /* third, assign gold the "letter" '$' and re-insert it at head */
4368 goldobj->invlet = GOLD_SYM;
4369 goldobj->nobj = invent;
4379 * User specifies a 'from' slot for inventory stack to move,
4380 * then a 'to' slot for its destination. Open slots and those
4381 * filled by compatible stacks are listed as likely candidates
4382 * but user can pick any inventory letter (including 'from').
4384 * to == from, 'from' has a name
4385 * All compatible items (same name or no name) are gathered
4386 * into the 'from' stack. No count is allowed.
4387 * to == from, 'from' does not have a name
4388 * All compatible items without a name are gathered into the
4389 * 'from' stack. No count is allowed. Compatible stacks with
4390 * names are left as-is.
4391 * to != from, no count
4392 * Move 'from' to 'to'. If 'to' is not empty, merge 'from'
4393 * into it if possible, otherwise swap it with the 'from' slot.
4394 * to != from, count given
4395 * If the user specifies a count when choosing the 'from' slot,
4396 * and that count is less than the full size of the stack,
4397 * then the stack will be split. The 'count' portion is moved
4398 * to the destination, and the only candidate for merging with
4399 * it is the stack already at the 'to' slot, if any. When the
4400 * destination is non-empty but won't merge, whatever is there
4401 * will be moved to an open slot; if there isn't any open slot
4402 * available, the adjustment attempt fails.
4404 * To minimize merging for 'from == to', unnamed stacks will
4405 * merge with named 'from' but named ones won't merge with
4406 * unnamed 'from'. Otherwise attempting to collect all unnamed
4407 * stacks would lump the first compatible named stack with them
4408 * and give them its name.
4410 * To maximize merging for 'from != to', compatible stacks will
4411 * merge when either lacks a name (or they already have the same
4412 * name). When no count is given and one stack has a name and
4413 * the other doesn't, the merged result will have that name.
4414 * However, when splitting results in a merger, the name of the
4415 * destination overrides that of the source, even if destination
4416 * is unnamed and source is named.
4419 doorganize() /* inventory organizer by Del Lamb */
4421 struct obj *obj, *otmp, *splitting, *bumped;
4422 int ix, cur, trycnt, goldstacks;
4425 #define GOLD_OFFSET 1
4426 #define OVRFLW_INDX (GOLD_OFFSET + 52) /* past gold and 2*26 letters */
4427 char lets[1 + 52 + 1 + 1]; /* room for '$a-zA-Z#\0' */
4429 char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
4430 char *objname, *otmpname;
4431 const char *adj_type;
4432 boolean ever_mind = FALSE, collect;
4436 You("aren't carrying anything to adjust.");
4438 You("
\8f\87\8f\98\82ð
\95Ï
\82¦
\82é
\82à
\82Ì
\82ð
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4442 if (!flags.invlet_constant)
4444 /* get object the user wants to organize (the 'from' slot) */
4445 allowall[0] = ALLOW_COUNT;
4446 allowall[1] = ALL_CLASSES;
4448 for (goldstacks = 0, otmp = invent; otmp; otmp = otmp->nobj) {
4449 /* gold should never end up in a letter slot, nor should two '$'
4450 slots occur, but if they ever do, allow #adjust to handle them
4451 (in the past, things like this have happened, usually due to
4452 bknown being erroneously set on one stack, clear on another;
4453 object merger isn't fooled by that anymore) */
4454 if (otmp->oclass == COIN_CLASS
4455 && (otmp->invlet != GOLD_SYM || ++goldstacks > 1)) {
4456 allowall[1] = COIN_CLASS;
4457 allowall[2] = ALL_CLASSES;
4462 if (!(obj = getobj(allowall, "adjust")))
4465 /* figure out whether user gave a split count to getobj() */
4466 splitting = bumped = 0;
4467 for (otmp = invent; otmp; otmp = otmp->nobj)
4468 if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
4469 if (otmp->invlet == obj->invlet)
4474 /* initialize the list with all lower and upper case letters */
4475 lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' ';
4476 for (ix = GOLD_OFFSET, let = 'a'; let <= 'z';)
4478 for (let = 'A'; let <= 'Z';)
4480 lets[OVRFLW_INDX] = ' ';
4481 lets[sizeof lets - 1] = '\0';
4482 /* for floating inv letters, truncate list after the first open slot */
4483 if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
4484 lets[ix + (splitting ? 0 : 1)] = '\0';
4486 /* blank out all the letters currently in use in the inventory
4487 except those that will be merged with the selected object */
4488 for (otmp = invent; otmp; otmp = otmp->nobj)
4489 if (otmp != obj && !mergable(otmp, obj)) {
4491 if (let >= 'a' && let <= 'z')
4492 lets[GOLD_OFFSET + let - 'a'] = ' ';
4493 else if (let >= 'A' && let <= 'Z')
4494 lets[GOLD_OFFSET + let - 'A' + 26] = ' ';
4495 /* overflow defaults to off, but it we find a stack using that
4496 slot, switch to on -- the opposite of normal invlet handling */
4497 else if (let == NOINVSYM)
4498 lets[OVRFLW_INDX] = NOINVSYM;
4501 /* compact the list by removing all the blanks */
4502 for (ix = cur = 0; lets[ix]; ix++)
4503 if (lets[ix] != ' ' && cur++ < ix)
4504 lets[cur - 1] = lets[ix];
4506 /* and by dashing runs of letters */
4510 /* get 'to' slot to use as destination */
4512 Sprintf(qbuf, "Adjust letter to what [%s]%s?", lets,
4513 invent ? " (? see used letters)" : "");
4515 Sprintf(qbuf, "
\82Ç
\82Ì
\95¶
\8e\9a\82É
\92²
\90®
\82µ
\82Ü
\82·
\82©[%s]%s
\81H", lets,
4516 invent ? " (?
\82Å
\8eg
\82Á
\82Ä
\82¢
\82é
\95¶
\8e\9a\82ð
\95\
\8e¦)" : "");
4518 for (trycnt = 1; ; ++trycnt) {
4519 let = yn_function(qbuf, (char *) 0, '\0');
4520 if (let == '?' || let == '*') {
4521 let = display_used_invlets(splitting ? obj->invlet : 0);
4527 if (index(quitchars, let)
4528 /* adjusting to same slot is meaningful since all
4529 compatible stacks get collected along the way,
4530 but splitting to same slot is not */
4531 || (splitting && let == obj->invlet)) {
4534 (void) merged(&splitting, &obj);
4538 } else if (let == GOLD_SYM && obj->oclass != COIN_CLASS) {
4540 pline("Only gold coins may be moved into the '%c' slot.",
4543 pline("'%c'
\82É
\82Å
\82«
\82é
\82Ì
\82Í
\8bà
\89Ý
\82¾
\82¯
\81D",
4549 /* letter() classifies '@' as one; compactify() can put '-' in lets;
4550 the only thing of interest that index() might find is '$' or '#'
4551 since letter() catches everything else that we put into lets[] */
4552 if ((letter(let) && let != '@') || (index(lets, let) && let != '-'))
4553 break; /* got one */
4557 pline("Select an inventory slot letter."); /* else try again */
4559 pline("
\8e\9d\82¿
\95¨
\82Ì
\95¶
\8e\9a\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢
\81D");
4563 collect = (let == obj->invlet);
4564 /* change the inventory and print the resulting item */
4566 adj_type = collect ? "Collecting" : !splitting ? "Moving:" : "Splitting:";
4568 adj_type = collect ? "
\82ð
\8fW
\82ß
\82½
\81D" : !splitting ? "
\82ð
\88Ú
\93®
\82µ
\82½
\81D" : "
\82ð
\95ª
\8a\84\82µ
\82½
\81D";
4571 * don't use freeinv/addinv to avoid double-touching artifacts,
4572 * dousing lamps, losing luck, cursing loadstone, etc.
4574 extract_nobj(obj, &invent);
4576 for (otmp = invent; otmp;) {
4577 /* it's tempting to pull this outside the loop, but merged() could
4578 free ONAME(obj) [via obfree()] and replace it with ONAME(otmp) */
4579 objname = has_oname(obj) ? ONAME(obj) : (char *) 0;
4582 /* Collecting: #adjust an inventory stack into its same slot;
4583 keep it there and merge other compatible stacks into it.
4584 Traditional inventory behavior is to merge unnamed stacks
4585 with compatible named ones; we only want that if it is
4586 the 'from' stack (obj) with a name and candidate (otmp)
4587 without one, not unnamed 'from' with named candidate. */
4588 otmpname = has_oname(otmp) ? ONAME(otmp) : (char *) 0;
4589 if ((!otmpname || (objname && !strcmp(objname, otmpname)))
4590 && merged(&otmp, &obj)) {
4592 adj_type = "Merging:";
4594 adj_type = "
\82ð
\8d\87\82í
\82¹
\82½
\81D";
4597 extract_nobj(obj, &invent);
4598 continue; /* otmp has already been updated */
4600 } else if (otmp->invlet == let) {
4601 /* Moving or splitting: don't merge extra compatible stacks.
4602 Found 'otmp' in destination slot; merge if compatible,
4603 otherwise bump whatever is there to an open slot. */
4606 adj_type = "Swapping:";
4608 adj_type = "
\82ð
\8cð
\8a·
\82µ
\82½
\81D";
4609 otmp->invlet = obj->invlet;
4611 /* strip 'from' name if it has one */
4612 if (objname && !obj->oartifact)
4613 ONAME(obj) = (char *) 0;
4614 if (!mergable(otmp, obj)) {
4615 /* won't merge; put 'from' name back */
4617 ONAME(obj) = objname;
4619 /* will merge; discard 'from' name */
4621 free((genericptr_t) objname), objname = 0;
4624 if (merged(&otmp, &obj)) {
4626 adj_type = "Splitting and merging:";
4628 adj_type = "
\82ð
\95ª
\8a\84\82µ
\82Ä
\8d\87\82í
\82¹
\82½
\81D";
4630 extract_nobj(obj, &invent);
4631 } else if (inv_cnt(FALSE) >= 52) {
4632 (void) merged(&splitting, &obj); /* undo split */
4633 /* "knapsack cannot accommodate any more items" */
4635 Your("pack is too full.");
4637 Your("
\8e\9d\82¿
\95¨
\82Í
\88ê
\94t
\82¾
\81D");
4641 extract_nobj(bumped, &invent);
4643 } /* moving vs splitting */
4644 break; /* not collecting and found 'to' slot */
4649 /* inline addinv; insert loose object at beginning of inventory */
4652 obj->where = OBJ_INVENT;
4656 /* splitting the 'from' stack is causing an incompatible
4657 stack in the 'to' slot to be moved into an open one;
4658 we need to do another inline insertion to inventory */
4659 assigninvlet(bumped);
4660 bumped->nobj = invent;
4661 bumped->where = OBJ_INVENT;
4666 /* messages deferred until inventory has been fully reestablished */
4667 prinv(adj_type, obj, 0L);
4670 prinv("Moving:", bumped, 0L);
4672 prinv("
\88Ú
\93®:", bumped, 0L);
4674 clear_splitobjs(); /* reset splitobj context */
4679 /* common to display_minventory and display_cinventory */
4681 invdisp_nothing(hdr, txt)
4682 const char *hdr, *txt;
4686 menu_item *selected;
4689 win = create_nhwindow(NHW_MENU);
4691 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr,
4693 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
4694 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
4695 end_menu(win, (char *) 0);
4696 if (select_menu(win, PICK_NONE, &selected) > 0)
4697 free((genericptr_t) selected);
4698 destroy_nhwindow(win);
4702 /* query_objlist callback: return things that are worn or wielded */
4704 worn_wield_only(obj)
4708 /* check for things that *are* worn or wielded (only used for monsters,
4709 so we don't worry about excluding W_CHAIN, W_ARTI and the like) */
4710 return (boolean) (obj->owornmask != 0L);
4712 /* this used to check for things that *might* be worn or wielded,
4713 but that's not particularly interesting */
4714 if (is_weptool(obj) || is_wet_towel(obj) || obj->otyp == MEAT_RING)
4716 return (boolean) (obj->oclass == WEAPON_CLASS
4717 || obj->oclass == ARMOR_CLASS
4718 || obj->oclass == AMULET_CLASS
4719 || obj->oclass == RING_CLASS);
4724 * Display a monster's inventory.
4725 * Returns a pointer to the object from the monster's inventory selected
4726 * or NULL if nothing was selected.
4728 * By default, only worn and wielded items are displayed. The caller
4729 * can pick one. Modifier flags are:
4731 * PICK_NONE, PICK_ONE - standard menu control
4732 * PICK_ANY - allowed, but we only return a single object
4733 * MINV_NOLET - nothing selectable
4734 * MINV_ALL - display all inventory
4737 display_minventory(mon, dflags, title)
4738 register struct monst *mon;
4745 menu_item *selected = 0;
4746 int do_all = (dflags & MINV_ALL) != 0,
4747 incl_hero = (do_all && u.uswallow && mon == u.ustuck),
4748 have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
4749 pickings = (dflags & MINV_PICKMASK);
4752 Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
4753 do_all ? "possessions" : "armament");
4755 Sprintf(tmp, "%s
\82Ì%s
\81F", Monnam(mon),
4756 do_all ? "
\8e\9d\82¿
\95¨" : "
\91\95\94õ");
4759 if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
4760 /* Fool the 'weapon in hand' routine into
4761 * displaying 'weapon in claw', etc. properly.
4763 youmonst.data = mon->data;
4764 /* in case inside a shop, don't append "for sale" prices */
4765 iflags.suppress_price++;
4767 n = query_objlist(title ? title : tmp, &(mon->minvent),
4768 (INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0)),
4769 &selected, pickings,
4770 do_all ? allow_all : worn_wield_only);
4772 iflags.suppress_price--;
4773 /* was 'set_uasmon();' but that potentially has side-effects */
4774 youmonst.data = &mons[u.umonnum]; /* most basic part of set_uasmon */
4777 invdisp_nothing(title ? title : tmp, "(none)");
4779 invdisp_nothing(title ? title : tmp, "(
\89½
\82à
\82È
\82¢)");
4784 ret = selected[0].item.a_obj;
4785 free((genericptr_t) selected);
4787 ret = (struct obj *) 0;
4792 * Display the contents of a container in inventory style.
4793 * Currently, this is only used for statues, via wand of probing.
4796 display_cinventory(obj)
4797 register struct obj *obj;
4802 menu_item *selected = 0;
4805 (void) safe_qbuf(qbuf, "Contents of ", ":", obj, doname, ansimpleoname,
4808 (void) safe_qbuf(qbuf, "", "
\82Ì
\92\86\90g
\81F", obj, doname, ansimpleoname,
4813 n = query_objlist(qbuf, &(obj->cobj), INVORDER_SORT,
4814 &selected, PICK_NONE, allow_all);
4817 invdisp_nothing(qbuf, "(empty)");
4819 invdisp_nothing(qbuf, "(
\8bó
\82Á
\82Û)");
4823 ret = selected[0].item.a_obj;
4824 free((genericptr_t) selected);
4826 ret = (struct obj *) 0;
4831 /* query objlist callback: return TRUE if obj is at given location */
4838 return (obj->ox == only.x && obj->oy == only.y);
4842 * Display a list of buried items in inventory style. Return a non-zero
4843 * value if there were items at that spot.
4845 * Currently, this is only used with a wand of probing zapped downwards.
4848 display_binventory(x, y, as_if_seen)
4853 menu_item *selected = 0;
4856 /* count # of objects here */
4857 for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
4858 if (obj->ox == x && obj->oy == y) {
4868 if (query_objlist("Things that are buried here:",
4870 if (query_objlist("
\82±
\82±
\82É
\96\84\82ß
\82ç
\82ê
\82Ä
\82¢
\82é
\82à
\82Ì
\81F",
4871 &level.buriedobjlist, INVORDER_SORT,
4872 &selected, PICK_NONE, only_here) > 0)
4873 free((genericptr_t) selected);
4874 only.x = only.y = 0;