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.2
\82Å
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
2249 invent.c:2228: int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
2250 pickup.c:3208: 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 */
3257 Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
3259 Sprintf(contbuf, "%s
\82Ì
\92\86\90g", xname(otmp));
3261 xprname((struct obj *) 0, contbuf, CONTAINED_SYM,
3262 TRUE, contcost, 0L));
3271 xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
3274 xprname((struct obj *) 0, "
\8d\87\8cv
\81F", '*', FALSE, totcost, 0L));
3276 display_nhwindow(win, FALSE);
3277 destroy_nhwindow(win);
3280 /* query objlist callback: return TRUE if obj type matches "this_type" */
3281 static int this_type;
3287 boolean res = (obj->oclass == this_type);
3289 if (obj->oclass == COIN_CLASS) {
3290 /* if filtering by bless/curse state, gold is classified as
3291 either unknown or uncursed based on user option setting */
3292 if (this_type && index("BUCX", this_type))
3293 res = (this_type == (iflags.goldX ? 'X' : 'U'));
3295 switch (this_type) {
3297 res = (obj->bknown && obj->blessed);
3300 res = (obj->bknown && !(obj->blessed || obj->cursed));
3303 res = (obj->bknown && obj->cursed);
3309 break; /* use 'res' as-is */
3315 /* the 'I' command */
3321 char *extra_types, types[BUFSZ];
3322 int class_count, oclass, unpaid_count, itemcount;
3323 int bcnt, ccnt, ucnt, xcnt, ocnt;
3324 boolean billx = *u.ushops && doinvbill(0);
3325 menu_item *pick_list;
3326 boolean traditional = TRUE;
3328 const char *prompt = "What type of object do you want an inventory of?";
3330 const char *prompt = "
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\8e\9d\82¿
\95¨
\82ð
\8c©
\82Ü
\82·
\82©
\81H";
3332 if (!invent && !billx) {
3334 You("aren't carrying anything.");
3336 You("
\82»
\82Ì
\8eí
\97Þ
\82Ì
\95¨
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3339 unpaid_count = count_unpaid(invent);
3340 tally_BUCX(invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
3342 if (flags.menu_style != MENU_TRADITIONAL) {
3343 if (flags.menu_style == MENU_FULL
3344 || flags.menu_style == MENU_PARTIAL) {
3345 traditional = FALSE;
3357 n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
3360 this_type = c = pick_list[0].item.a_int;
3361 free((genericptr_t) pick_list);
3365 /* collect a list of classes of objects carried, for use as a prompt
3368 class_count = collect_obj_classes(types, invent, FALSE,
3369 (boolean FDECL((*), (OBJ_P))) 0,
3371 if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
3372 types[class_count++] = ' ';
3374 types[class_count++] = 'u';
3376 types[class_count++] = 'x';
3378 types[class_count++] = 'B';
3380 types[class_count++] = 'U';
3382 types[class_count++] = 'C';
3384 types[class_count++] = 'X';
3385 types[class_count] = '\0';
3386 /* add everything not already included; user won't see these */
3387 extra_types = eos(types);
3388 *extra_types++ = '\033';
3390 *extra_types++ = 'u';
3392 *extra_types++ = 'x';
3394 *extra_types++ = 'B';
3396 *extra_types++ = 'U';
3398 *extra_types++ = 'C';
3400 *extra_types++ = 'X';
3401 *extra_types = '\0'; /* for index() */
3402 for (i = 0; i < MAXOCLASSES; i++)
3403 if (!index(types, def_oc_syms[i].sym)) {
3404 *extra_types++ = def_oc_syms[i].sym;
3405 *extra_types = '\0';
3408 if (class_count > 1) {
3409 c = yn_function(prompt, types, '\0');
3412 clear_nhwindow(WIN_MESSAGE);
3416 /* only one thing to itemize */
3425 if (c == 'x' || (c == 'X' && billx && !xcnt)) {
3427 (void) doinvbill(1);
3430 pline("No used-up objects%s.",
3431 unpaid_count ? " on your shopping bill" : "");
3433 pline("
\8eg
\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\95¨
\82Í%s
\82È
\82¢
\81D",
3434 unpaid_count ? "
\8f¤
\93X
\82Ì
\90¿
\8b\81\8f\91\82É
\82Í" : "");
3438 if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
3443 You("are not carrying any unpaid objects.");
3445 You("
\96¢
\95¥
\82¢
\82Ì
\83A
\83C
\83e
\83\80\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3449 if (index("BUCX", c))
3450 oclass = c; /* not a class but understood by this_type_only() */
3452 oclass = def_char_to_objclass(c); /* change to object class */
3454 if (oclass == COIN_CLASS)
3456 if (index(types, c) > index(types, '\033')) {
3457 /* '> ESC' => hidden choice, something known not to be carried */
3458 const char *before = "", *after = "";
3463 before = "known to be blessed ";
3465 before = "
\8fj
\95\9f\82³
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3469 before = "known to be uncursed ";
3471 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3475 before = "known to be cursed ";
3477 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3481 after = " whose blessed/uncursed/cursed status is unknown";
3483 after = "
\8fj
\95\9f\81^
\8eô
\82¢
\82ª
\82í
\82©
\82ç
\82È
\82¢";
3484 break; /* better phrasing is desirable */
3486 /* 'c' is an object class, because we've already handled
3487 all the non-class letters which were put into 'types[]';
3488 could/should move object class names[] array from below
3489 to somewhere above so that we can access it here (via
3490 lcase(strcpy(classnamebuf, names[(int) c]))), but the
3491 game-play value of doing so is low... */
3495 before = "
\82»
\82Ì
\82æ
\82¤
\82È";
3499 You("have no %sobjects%s.", before, after);
3501 You("%s%s
\82à
\82Ì
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", before, after);
3506 if (query_objlist((char *) 0, &invent,
3507 ((flags.invlet_constant ? USE_INVLET : 0)
3509 &pick_list, PICK_NONE, this_type_only) > 0)
3510 free((genericptr_t) pick_list);
3514 /* return a string describing the dungeon feature at <x,y> if there
3515 is one worth mentioning at that location; otherwise null */
3517 dfeature_at(x, y, buf)
3521 struct rm *lev = &levl[x][y];
3522 int ltyp = lev->typ, cmap = -1;
3523 const char *dfeature = 0;
3524 static char altbuf[BUFSZ];
3526 if (IS_DOOR(ltyp)) {
3527 switch (lev->doormask) {
3530 break; /* "doorway" */
3533 break; /* "open door" */
3536 dfeature = "broken door";
3538 dfeature = "
\89ó
\82ê
\82½
\94à";
3542 break; /* "closed door" */
3544 /* override door description for open drawbridge */
3545 if (is_drawbridge_wall(x, y) >= 0)
3547 dfeature = "open drawbridge portcullis", cmap = -1;
3549 dfeature = "
\8d~
\82è
\82Ä
\82¢
\82é
\92µ
\82Ë
\8b´", cmap = -1;
3550 } else if (IS_FOUNTAIN(ltyp))
3551 cmap = S_fountain; /* "fountain" */
3552 else if (IS_THRONE(ltyp))
3553 cmap = S_throne; /* "opulent throne" */
3554 else if (is_lava(x, y))
3555 cmap = S_lava; /* "molten lava" */
3556 else if (is_ice(x, y))
3557 cmap = S_ice; /* "ice" */
3558 else if (is_pool(x, y))
3560 dfeature = "pool of water";
3562 dfeature = "
\90\85\82½
\82Ü
\82è";
3563 else if (IS_SINK(ltyp))
3564 cmap = S_sink; /* "sink" */
3565 else if (IS_ALTAR(ltyp)) {
3567 Sprintf(altbuf, "%saltar to %s (%s)",
3568 ((lev->altarmask & AM_SHRINE)
3569 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3573 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3575 Sprintf(altbuf, "%s%s
\82Ì
\8dÕ
\92d(%s)",
3576 ((lev->altarmask & AM_SHRINE)
3577 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3581 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3584 } else if ((x == xupstair && y == yupstair)
3585 || (x == sstairs.sx && y == sstairs.sy && sstairs.up))
3586 cmap = S_upstair; /* "staircase up" */
3587 else if ((x == xdnstair && y == ydnstair)
3588 || (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
3589 cmap = S_dnstair; /* "staircase down" */
3590 else if (x == xupladder && y == yupladder)
3591 cmap = S_upladder; /* "ladder up" */
3592 else if (x == xdnladder && y == ydnladder)
3593 cmap = S_dnladder; /* "ladder down" */
3594 else if (ltyp == DRAWBRIDGE_DOWN)
3595 cmap = S_vodbridge; /* "lowered drawbridge" */
3596 else if (ltyp == DBWALL)
3597 cmap = S_vcdbridge; /* "raised drawbridge" */
3598 else if (IS_GRAVE(ltyp))
3599 cmap = S_grave; /* "grave" */
3600 else if (ltyp == TREE)
3601 cmap = S_tree; /* "tree" */
3602 else if (ltyp == IRONBARS)
3604 dfeature = "set of iron bars";
3606 dfeature = "
\93S
\82Ì
\96_";
3609 dfeature = defsyms[cmap].explanation;
3611 Strcpy(buf, dfeature);
3615 /* look at what is here; if there are many objects (pile_limit or more),
3616 don't show them unless obj_cnt is 0 */
3618 look_here(obj_cnt, picked_some)
3619 int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progress */
3620 boolean picked_some;
3625 const char *verb = Blind ? "feel" : "see";
3627 const char *verb = Blind ? "
\82ª
\82 \82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½" : "
\82ð
\82Ý
\82Â
\82¯
\82½";
3629 const char *dfeature = (char *) 0;
3630 char fbuf[BUFSZ], fbuf2[BUFSZ];
3632 boolean skip_objects, felt_cockatrice = FALSE;
3634 /* default pile_limit is 5; a value of 0 means "never skip"
3635 (and 1 effectively forces "always skip") */
3636 skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
3637 if (u.uswallow && u.ustuck) {
3638 struct monst *mtmp = u.ustuck;
3641 Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
3642 mbodypart(mtmp, STOMACH));
3644 Sprintf(fbuf, "%s
\82Ì%s
\82Ì
\92\86\90g", mon_nam(mtmp),
3645 mbodypart(mtmp, STOMACH));
3647 #if 0 /*JP*//*
\8cê
\8f\87\82ª
\88á
\82¤
\82Ì
\82Å
\91f
\92¼
\82É*/
3648 /* Skip "Contents of " by using fbuf index 12 */
3649 You("%s to %s what is lying in %s.", Blind ? "try" : "look around",
3652 You("%s
\82Ì%s
\82É
\89½
\82ª
\82 \82é
\82©%s
\81D",
3653 mon_nam(mtmp), mbodypart(mtmp, STOMACH),
3654 Blind ? "
\82³
\82®
\82Á
\82½" : "
\8c©
\89ñ
\82µ
\82½");
3656 otmp = mtmp->minvent;
3658 for (; otmp; otmp = otmp->nobj) {
3659 /* If swallower is an animal, it should have become stone
3661 if (otmp->otyp == CORPSE)
3662 feel_cockatrice(otmp, FALSE);
3666 Strcpy(fbuf, "You feel");
3669 Sprintf(fbuf, "
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F", Blind ? "
\82ç
\82µ
\82¢" : "");
3671 (void) display_minventory(mtmp, MINV_ALL | PICK_NONE, fbuf);
3674 You("%s no objects here.", verb);
3676 pline(Blind ? "
\82 \82È
\82½
\82Í
\89½
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D"
3677 : "
\82 \82È
\82½
\82Í
\89½
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3682 if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen)
3684 There("is %s here.",
3686 pline("
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D",
3687 an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
3689 otmp = level.objects[u.ux][u.uy];
3690 dfeature = dfeature_at(u.ux, u.uy, fbuf2);
3692 if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
3694 if (dfeature && !strcmp(dfeature, "
\90\85\82½
\82Ü
\82è") && Underwater)
3698 boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
3701 if (dfeature && !strncmp(dfeature, "altar ", 6)) {
3703 if (dfeature && !strncmp(dfeature, "
\8dÕ
\92d", 4)) {
3704 /* don't say "altar" twice, dfeature has more info */
3706 You("try to feel what is here.");
3708 You("
\82±
\82±
\82É
\89½
\82ª
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3711 const char *where = (Blind && !can_reach_floor(TRUE))
3712 ? "lying beneath you"
3713 : "lying here on the ",
3714 *onwhat = (Blind && !can_reach_floor(TRUE))
3716 : surface(u.ux, u.uy);
3718 You("try to feel what is %s%s.", drift ? "floating here" : where,
3719 drift ? "" : onwhat);
3722 You("
\89½
\82ª
\95\82\82¢
\82Ä
\82¢
\82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3723 } else if (Blind && !can_reach_floor(TRUE)) {
3724 You("
\89½
\82ª
\91«
\89º
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3726 You("
\89½
\82ª%s
\82Ì
\8fã
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D", surface(u.ux, u.uy));
3730 if (dfeature && !drift && !strcmp(dfeature, surface(u.ux, u.uy)))
3731 dfeature = 0; /* ice already identified */
3732 if (!can_reach_floor(TRUE)) {
3734 pline("But you can't reach it!");
3736 pline("
\82µ
\82©
\82µ
\93Í
\82©
\82È
\82¢
\81I");
3743 Sprintf(fbuf, "There is %s here.", an(dfeature));
3745 Sprintf(fbuf, "
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D", an(dfeature));
3747 if (!otmp || is_lava(u.ux, u.uy)
3748 || (is_pool(u.ux, u.uy) && !Underwater)) {
3751 read_engr_at(u.ux, u.uy); /* Eric Backus */
3752 if (!skip_objects && (Blind || !dfeature))
3754 You("%s no objects here.", verb);
3757 "
\82È
\82É
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82·
\82é
\81D" :
3758 "
\82È
\82É
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3762 /* we know there is something here */
3767 read_engr_at(u.ux, u.uy); /* Eric Backus */
3768 if (obj_cnt == 1 && otmp->quan == 1L)
3770 There("is %s object here.", picked_some ? "another" : "an");
3772 There("
\82±
\82±
\82É
\82Í%s
\88ê
\82Â
\82à
\82Ì
\82ª
\82 \82é
\81D", picked_some ? "
\82à
\82¤" : "");
3775 There("are %s%s objects here.",
3781 picked_some ? " more" : "");
3783 pline("
\82±
\82±
\82É
\82Í%s%s
\82à
\82Ì
\82ª
\82 \82é
\81D",
3784 picked_some ? "
\82³
\82ç
\82É" : "",
3786 ? "
\82¢
\82
\82Â
\82©
\82Ì"
3787 : "
\82½
\82
\82³
\82ñ
\82Ì");
3789 for (; otmp; otmp = otmp->nexthere)
3790 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3791 #if 0 /*JP*//*"It's (corpse_name), unfortunately"*/
3798 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3799 poly_when_stoned(youmonst.data)
3801 : ", unfortunately");
3804 poly_when_stoned(youmonst.data)
3806 : "
\8ec
\94O
\82È
\82ª
\82ç",
3807 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3809 ? "
\82ð
\8aÜ
\82ñ
\82Å
\82¢
\82é"
3812 feel_cockatrice(otmp, FALSE);
3815 } else if (!otmp->nexthere) {
3816 /* only one object */
3819 read_engr_at(u.ux, u.uy); /* Eric Backus */
3821 You("%s here %s.", verb, doname_with_price(otmp));
3823 pline("%s%s
\81D", doname_with_price(otmp), verb);
3824 iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
3825 if (otmp->otyp == CORPSE)
3826 feel_cockatrice(otmp, FALSE);
3830 display_nhwindow(WIN_MESSAGE, FALSE);
3831 tmpwin = create_nhwindow(NHW_MENU);
3833 putstr(tmpwin, 0, fbuf);
3834 putstr(tmpwin, 0, "");
3837 Sprintf(buf, "%s that %s here:",
3838 picked_some ? "Other things" : "Things",
3839 Blind ? "you feel" : "are");
3841 Sprintf(buf, "%s
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F",
3842 picked_some ? "
\91¼
\82É" : "",
3843 Blind ? "
\82ç
\82µ
\82¢" : "");
3845 putstr(tmpwin, 0, buf);
3846 for (; otmp; otmp = otmp->nexthere) {
3847 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3848 felt_cockatrice = TRUE;
3850 Sprintf(buf, "%s...", doname(otmp));
3852 Sprintf(buf, "%s
\81D
\81D
\81D", doname(otmp));
3853 putstr(tmpwin, 0, buf);
3856 putstr(tmpwin, 0, doname_with_price(otmp));
3858 display_nhwindow(tmpwin, TRUE);
3859 destroy_nhwindow(tmpwin);
3860 if (felt_cockatrice)
3861 feel_cockatrice(otmp, FALSE);
3862 read_engr_at(u.ux, u.uy); /* Eric Backus */
3867 /* the ':' command - explicitly look at what is here, including all objects */
3874 MSGTYPE={norep,noshow} "You see here"
3875 interfere with feedback from the look-here command */
3876 hide_unhide_msgtypes(TRUE, MSGTYP_MASK_REP_SHOW);
3877 res = look_here(0, FALSE);
3878 /* restore normal msgtype handling */
3879 hide_unhide_msgtypes(FALSE, MSGTYP_MASK_REP_SHOW);
3884 will_feel_cockatrice(otmp, force_touch)
3886 boolean force_touch;
3888 if ((Blind || force_touch) && !uarmg && !Stone_resistance
3889 && (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
3895 feel_cockatrice(otmp, force_touch)
3897 boolean force_touch;
3901 if (will_feel_cockatrice(otmp, force_touch)) {
3902 /* "the <cockatrice> corpse" */
3903 Strcpy(kbuf, corpse_xname(otmp, (const char *) 0, CXN_PFX_THE));
3905 if (poly_when_stoned(youmonst.data))
3907 You("touched %s with your bare %s.", kbuf,
3908 makeplural(body_part(HAND)));
3910 You("%s
\82Ì
\8e\80\91Ì
\82É
\91f%s
\82Å
\90G
\82Á
\82½
\81D", kbuf,
3915 pline("Touching %s is a fatal mistake...", kbuf);
3917 pline("%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82é
\82Ì
\82Í
\92v
\96½
\93I
\82È
\8aÔ
\88á
\82¢
\82¾
\81D
\81D
\81D", kbuf);
3918 /* normalize body shape here; hand, not body_part(HAND) */
3920 Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
3922 Sprintf(kbuf, "%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82Ä", killer_xname(otmp));
3923 /* will call polymon() for the poly_when_stoned() case */
3934 for (otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
3935 if (otmp != obj && merged(&obj, &otmp))
3940 /* returns TRUE if obj & otmp can be merged; used in invent.c and mkobj.c */
3943 register struct obj *otmp, *obj;
3945 int objnamelth = 0, otmpnamelth = 0;
3947 /* fail if already the same object, if different types, if either is
3948 explicitly marked to prevent merge, or if not mergable in general */
3949 if (obj == otmp || obj->otyp != otmp->otyp
3950 || obj->nomerge || otmp->nomerge || !objects[obj->otyp].oc_merge)
3953 /* coins of the same kind will always merge */
3954 if (obj->oclass == COIN_CLASS)
3957 if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
3958 || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed
3959 || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
3960 || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
3961 || obj->bypass != otmp->bypass)
3966 /* Checks beyond this point either aren't applicable to globs
3967 * or don't inhibit their merger.
3970 if (obj->oclass == FOOD_CLASS
3971 && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
3974 if (obj->dknown != otmp->dknown
3975 || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
3976 || obj->oeroded != otmp->oeroded || obj->oeroded2 != otmp->oeroded2
3977 || obj->greased != otmp->greased)
3980 if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
3981 && (obj->oerodeproof != otmp->oerodeproof
3982 || obj->rknown != otmp->rknown))
3985 if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
3986 if (obj->corpsenm != otmp->corpsenm)
3990 /* hatching eggs don't merge; ditto for revivable corpses */
3991 if ((obj->otyp == EGG && (obj->timed || otmp->timed))
3992 || (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM
3993 && is_reviver(&mons[otmp->corpsenm])))
3996 /* allow candle merging only if their ages are close */
3997 /* see begin_burn() for a reference for the magic "25" */
3998 if (Is_candle(obj) && obj->age / 25 != otmp->age / 25)
4001 /* burning potions of oil never merge */
4002 if (obj->otyp == POT_OIL && obj->lamplit)
4005 /* don't merge surcharged item with base-cost item */
4006 if (obj->unpaid && !same_price(obj, otmp))
4009 /* if they have names, make sure they're the same */
4010 objnamelth = strlen(safe_oname(obj));
4011 otmpnamelth = strlen(safe_oname(otmp));
4012 if ((objnamelth != otmpnamelth
4013 && ((objnamelth && otmpnamelth) || obj->otyp == CORPSE))
4014 || (objnamelth && otmpnamelth
4015 && strncmp(ONAME(obj), ONAME(otmp), objnamelth)))
4018 /* for the moment, any additional information is incompatible */
4019 if (has_omonst(obj) || has_omid(obj) || has_olong(obj) || has_omonst(otmp)
4020 || has_omid(otmp) || has_olong(otmp))
4023 if (obj->oartifact != otmp->oartifact)
4026 if (obj->known == otmp->known || !objects[otmp->otyp].oc_uses_known) {
4027 return (boolean) objects[obj->otyp].oc_merge;
4032 /* the '$' command */
4036 /* the messages used to refer to "carrying gold", but that didn't
4037 take containers into account */
4038 long umoney = money_cnt(invent);
4042 Your("wallet is empty.");
4044 Your("
\8dà
\95z
\82Í
\8bó
\82Á
\82Û
\82¾
\81D");
4047 Your("wallet contains %ld %s.", umoney, currency(umoney));
4049 Your("
\8dà
\95z
\82É
\82Í%ld%s
\93ü
\82Á
\82Ä
\82¢
\82é
\81D", umoney, currency(umoney));
4050 shopper_financial_report();
4054 /* the ')' command */
4060 You("are empty %s.", body_part(HANDED));
4062 if(!uwep) You("%s
\82É
\95\90\8aí
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D", body_part(HAND));
4064 prinv((char *) 0, uwep, 0L);
4066 prinv((char *) 0, uswapwep, 0L);
4071 /* caller is responsible for checking !wearing_armor() */
4073 noarmor(report_uskin)
4074 boolean report_uskin;
4076 if (!uskin || !report_uskin) {
4078 You("are not wearing any armor.");
4080 You("
\8aZ
\82ð
\92\85\82Ä
\82¢
\82È
\82¢
\81D");
4082 char *p, *uskinname, buf[BUFSZ];
4084 uskinname = strcpy(buf, simpleonames(uskin));
4086 /* shorten "set of <color> dragon scales" to "<color> scales"
4087 and "<color> dragon scale mail" to "<color> scale mail" */
4088 if (!strncmpi(uskinname, "set of ", 7))
4090 if ((p = strstri(uskinname, " dragon ")) != 0)
4091 while ((p[1] = p[8]) != '\0')
4093 #else /*
\81u<
\90F>
\83h
\83\89\83S
\83\93\82Ì
\97Ø
\81v
\82ð
\81u<
\90F>
\82Ì
\97Ø
\81v
\82É
\82·
\82é*/
4094 if ((p = strstri(uskinname, "
\83h
\83\89\83S
\83\93\82Ì
\97Ø")) != 0)
4099 You("are not wearing armor but have %s embedded in your skin.",
4101 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",
4106 /* the '[' command */
4111 register int ct = 0;
4113 * Note: players sometimes get here by pressing a function key which
4114 * transmits ''ESC [ <something>'' rather than by pressing '[';
4115 * there's nothing we can--or should-do about that here.
4118 if (!wearing_armor()) {
4122 lets[ct++] = obj_to_let(uarmu);
4124 lets[ct++] = obj_to_let(uarm);
4126 lets[ct++] = obj_to_let(uarmc);
4128 lets[ct++] = obj_to_let(uarmh);
4130 lets[ct++] = obj_to_let(uarms);
4132 lets[ct++] = obj_to_let(uarmg);
4134 lets[ct++] = obj_to_let(uarmf);
4136 (void) display_inventory(lets, FALSE);
4141 /* the '=' command */
4145 if (!uleft && !uright)
4147 You("are not wearing any rings.");
4149 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
4152 register int ct = 0;
4155 lets[ct++] = obj_to_let(uleft);
4157 lets[ct++] = obj_to_let(uright);
4159 (void) display_inventory(lets, FALSE);
4164 /* the '"' command */
4170 You("are not wearing an amulet.");
4172 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
4174 prinv((char *) 0, uamul, 0L);
4182 if ((obj->owornmask & (W_TOOL | W_SADDLE)) != 0L)
4184 if (obj->oclass != TOOL_CLASS)
4186 return (boolean) (obj == uwep || obj->lamplit
4187 || (obj->otyp == LEASH && obj->leashmon));
4190 /* the '(' command */
4198 for (otmp = invent; otmp; otmp = otmp->nobj)
4199 if (tool_in_use(otmp))
4200 lets[ct++] = obj_to_let(otmp);
4204 You("are not using any tools.");
4206 You("
\8eg
\82¦
\82é
\93¹
\8bï
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4208 (void) display_inventory(lets, FALSE);
4212 /* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
4213 show inventory of all currently wielded, worn, or used objects */
4221 for (otmp = invent; otmp; otmp = otmp->nobj)
4222 if (is_worn(otmp) || tool_in_use(otmp))
4223 lets[ct++] = obj_to_let(otmp);
4227 You("are not wearing or wielding anything.");
4229 You("
\89½
\82à
\92\85\82Ä
\82¢
\82È
\82¢
\82µ
\81C
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
4231 (void) display_inventory(lets, FALSE);
4236 * uses up an object that's on the floor, charging for it as necessary
4239 useupf(obj, numused)
4240 register struct obj *obj;
4243 register struct obj *otmp;
4244 boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
4246 /* burn_floor_objects() keeps an object pointer that it tries to
4247 * useupf() multiple times, so obj must survive if plural */
4248 if (obj->quan > numused)
4249 otmp = splitobj(obj, numused);
4252 if (costly_spot(otmp->ox, otmp->oy)) {
4253 if (index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
4254 addtobill(otmp, FALSE, FALSE, FALSE);
4256 (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
4259 if (at_u && u.uundetected && hides_under(youmonst.data))
4260 (void) hideunder(&youmonst);
4264 * Conversion from a class to a string for printing.
4265 * This must match the object class order.
4267 STATIC_VAR NEARDATA const char *names[] = {
4269 0, "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", "Tools",
4270 "Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
4271 "Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
4273 0, "
\96
\82È
\95¨
\91Ì", "
\95\90\8aí", "
\8aZ", "
\8ew
\97Ö", "
\96\82\8f\9c\82¯", "
\93¹
\8bï",
4274 "
\90H
\97¿", "
\96ò", "
\8aª
\95¨", "
\96\82\96@
\8f\91", "
\8fñ", "
\8bà
\89Ý",
4275 "
\95ó
\90Î", "
\8aâ
\82Ü
\82½
\82Í
\92¤
\91\9c", "
\93S
\8b\85", "
\8d½", "
\93Å"
4278 STATIC_VAR NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
4280 STATIC_VAR NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
4282 STATIC_VAR NEARDATA const char *oth_names[] = { "
\8bl
\82ß
\82ç
\82ê
\82½
\93¹
\8bï" };
4284 STATIC_VAR NEARDATA char *invbuf = (char *) 0;
4285 STATIC_VAR NEARDATA unsigned invbufsiz = 0;
4288 let_to_name(let, unpaid, showsym)
4290 boolean unpaid, showsym;
4292 const char *ocsymfmt = " ('%c')";
4293 const int invbuf_sympadding = 8; /* arbitrary */
4294 const char *class_name;
4296 int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
4300 class_name = names[oclass];
4301 else if ((pos = index(oth_symbols, let)) != 0)
4302 class_name = oth_names[pos - oth_symbols];
4304 class_name = names[0];
4307 len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "")
4309 len = strlen(class_name) + (unpaid ? sizeof "
\96¢
\95¥
\82¢
\82Ì" : sizeof "")
4310 + (oclass ? (strlen(ocsymfmt) + invbuf_sympadding) : 0);
4311 if (len > invbufsiz) {
4313 free((genericptr_t) invbuf);
4314 invbufsiz = len + 10; /* add slop to reduce incremental realloc */
4315 invbuf = (char *) alloc(invbufsiz);
4319 Strcat(strcpy(invbuf, "Unpaid "), class_name);
4321 Strcat(strcpy(invbuf, "
\96¢
\95¥
\82¢
\82Ì"), class_name);
4323 Strcpy(invbuf, class_name);
4324 if ((oclass != 0) && showsym) {
4325 char *bp = eos(invbuf);
4326 int mlen = invbuf_sympadding - strlen(class_name);
4327 while (--mlen > 0) {
4332 Sprintf(eos(invbuf), ocsymfmt, def_oc_syms[oclass].sym);
4337 /* release the static buffer used by let_to_name() */
4342 free((genericptr_t) invbuf), invbuf = (char *) 0;
4346 /* give consecutive letters to every item in inventory (for !fixinv mode);
4347 gold is always forced to '$' slot at head of list */
4352 struct obj *obj, *prevobj, *goldobj;
4354 /* first, remove [first instance of] gold from invent, if present */
4355 prevobj = goldobj = 0;
4356 for (obj = invent; obj; prevobj = obj, obj = obj->nobj)
4357 if (obj->oclass == COIN_CLASS) {
4360 prevobj->nobj = goldobj->nobj;
4362 invent = goldobj->nobj;
4365 /* second, re-letter the rest of the list */
4366 for (obj = invent, i = 0; obj; obj = obj->nobj, i++)
4368 (i < 26) ? ('a' + i) : (i < 52) ? ('A' + i - 26) : NOINVSYM;
4369 /* third, assign gold the "letter" '$' and re-insert it at head */
4371 goldobj->invlet = GOLD_SYM;
4372 goldobj->nobj = invent;
4382 * User specifies a 'from' slot for inventory stack to move,
4383 * then a 'to' slot for its destination. Open slots and those
4384 * filled by compatible stacks are listed as likely candidates
4385 * but user can pick any inventory letter (including 'from').
4387 * to == from, 'from' has a name
4388 * All compatible items (same name or no name) are gathered
4389 * into the 'from' stack. No count is allowed.
4390 * to == from, 'from' does not have a name
4391 * All compatible items without a name are gathered into the
4392 * 'from' stack. No count is allowed. Compatible stacks with
4393 * names are left as-is.
4394 * to != from, no count
4395 * Move 'from' to 'to'. If 'to' is not empty, merge 'from'
4396 * into it if possible, otherwise swap it with the 'from' slot.
4397 * to != from, count given
4398 * If the user specifies a count when choosing the 'from' slot,
4399 * and that count is less than the full size of the stack,
4400 * then the stack will be split. The 'count' portion is moved
4401 * to the destination, and the only candidate for merging with
4402 * it is the stack already at the 'to' slot, if any. When the
4403 * destination is non-empty but won't merge, whatever is there
4404 * will be moved to an open slot; if there isn't any open slot
4405 * available, the adjustment attempt fails.
4407 * To minimize merging for 'from == to', unnamed stacks will
4408 * merge with named 'from' but named ones won't merge with
4409 * unnamed 'from'. Otherwise attempting to collect all unnamed
4410 * stacks would lump the first compatible named stack with them
4411 * and give them its name.
4413 * To maximize merging for 'from != to', compatible stacks will
4414 * merge when either lacks a name (or they already have the same
4415 * name). When no count is given and one stack has a name and
4416 * the other doesn't, the merged result will have that name.
4417 * However, when splitting results in a merger, the name of the
4418 * destination overrides that of the source, even if destination
4419 * is unnamed and source is named.
4422 doorganize() /* inventory organizer by Del Lamb */
4424 struct obj *obj, *otmp, *splitting, *bumped;
4425 int ix, cur, trycnt, goldstacks;
4428 #define GOLD_OFFSET 1
4429 #define OVRFLW_INDX (GOLD_OFFSET + 52) /* past gold and 2*26 letters */
4430 char lets[1 + 52 + 1 + 1]; /* room for '$a-zA-Z#\0' */
4432 char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
4433 char *objname, *otmpname;
4434 const char *adj_type;
4435 boolean ever_mind = FALSE, collect;
4439 You("aren't carrying anything to adjust.");
4441 You("
\8f\87\8f\98\82ð
\95Ï
\82¦
\82é
\82à
\82Ì
\82ð
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4445 if (!flags.invlet_constant)
4447 /* get object the user wants to organize (the 'from' slot) */
4448 allowall[0] = ALLOW_COUNT;
4449 allowall[1] = ALL_CLASSES;
4451 for (goldstacks = 0, otmp = invent; otmp; otmp = otmp->nobj) {
4452 /* gold should never end up in a letter slot, nor should two '$'
4453 slots occur, but if they ever do, allow #adjust to handle them
4454 (in the past, things like this have happened, usually due to
4455 bknown being erroneously set on one stack, clear on another;
4456 object merger isn't fooled by that anymore) */
4457 if (otmp->oclass == COIN_CLASS
4458 && (otmp->invlet != GOLD_SYM || ++goldstacks > 1)) {
4459 allowall[1] = COIN_CLASS;
4460 allowall[2] = ALL_CLASSES;
4465 if (!(obj = getobj(allowall, "adjust")))
4468 /* figure out whether user gave a split count to getobj() */
4469 splitting = bumped = 0;
4470 for (otmp = invent; otmp; otmp = otmp->nobj)
4471 if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
4472 if (otmp->invlet == obj->invlet)
4477 /* initialize the list with all lower and upper case letters */
4478 lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' ';
4479 for (ix = GOLD_OFFSET, let = 'a'; let <= 'z';)
4481 for (let = 'A'; let <= 'Z';)
4483 lets[OVRFLW_INDX] = ' ';
4484 lets[sizeof lets - 1] = '\0';
4485 /* for floating inv letters, truncate list after the first open slot */
4486 if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
4487 lets[ix + (splitting ? 0 : 1)] = '\0';
4489 /* blank out all the letters currently in use in the inventory
4490 except those that will be merged with the selected object */
4491 for (otmp = invent; otmp; otmp = otmp->nobj)
4492 if (otmp != obj && !mergable(otmp, obj)) {
4494 if (let >= 'a' && let <= 'z')
4495 lets[GOLD_OFFSET + let - 'a'] = ' ';
4496 else if (let >= 'A' && let <= 'Z')
4497 lets[GOLD_OFFSET + let - 'A' + 26] = ' ';
4498 /* overflow defaults to off, but it we find a stack using that
4499 slot, switch to on -- the opposite of normal invlet handling */
4500 else if (let == NOINVSYM)
4501 lets[OVRFLW_INDX] = NOINVSYM;
4504 /* compact the list by removing all the blanks */
4505 for (ix = cur = 0; lets[ix]; ix++)
4506 if (lets[ix] != ' ' && cur++ < ix)
4507 lets[cur - 1] = lets[ix];
4509 /* and by dashing runs of letters */
4513 /* get 'to' slot to use as destination */
4515 Sprintf(qbuf, "Adjust letter to what [%s]%s?", lets,
4516 invent ? " (? see used letters)" : "");
4518 Sprintf(qbuf, "
\82Ç
\82Ì
\95¶
\8e\9a\82É
\92²
\90®
\82µ
\82Ü
\82·
\82©[%s]%s
\81H", lets,
4519 invent ? " (?
\82Å
\8eg
\82Á
\82Ä
\82¢
\82é
\95¶
\8e\9a\82ð
\95\
\8e¦)" : "");
4521 for (trycnt = 1; ; ++trycnt) {
4522 let = yn_function(qbuf, (char *) 0, '\0');
4523 if (let == '?' || let == '*') {
4524 let = display_used_invlets(splitting ? obj->invlet : 0);
4530 if (index(quitchars, let)
4531 /* adjusting to same slot is meaningful since all
4532 compatible stacks get collected along the way,
4533 but splitting to same slot is not */
4534 || (splitting && let == obj->invlet)) {
4537 (void) merged(&splitting, &obj);
4541 } else if (let == GOLD_SYM && obj->oclass != COIN_CLASS) {
4543 pline("Only gold coins may be moved into the '%c' slot.",
4546 pline("'%c'
\82É
\82Å
\82«
\82é
\82Ì
\82Í
\8bà
\89Ý
\82¾
\82¯
\81D",
4552 /* letter() classifies '@' as one; compactify() can put '-' in lets;
4553 the only thing of interest that index() might find is '$' or '#'
4554 since letter() catches everything else that we put into lets[] */
4555 if ((letter(let) && let != '@') || (index(lets, let) && let != '-'))
4556 break; /* got one */
4560 pline("Select an inventory slot letter."); /* else try again */
4562 pline("
\8e\9d\82¿
\95¨
\82Ì
\95¶
\8e\9a\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢
\81D");
4566 collect = (let == obj->invlet);
4567 /* change the inventory and print the resulting item */
4569 adj_type = collect ? "Collecting" : !splitting ? "Moving:" : "Splitting:";
4571 adj_type = collect ? "
\82ð
\8fW
\82ß
\82½
\81D" : !splitting ? "
\82ð
\88Ú
\93®
\82µ
\82½
\81D" : "
\82ð
\95ª
\8a\84\82µ
\82½
\81D";
4574 * don't use freeinv/addinv to avoid double-touching artifacts,
4575 * dousing lamps, losing luck, cursing loadstone, etc.
4577 extract_nobj(obj, &invent);
4579 for (otmp = invent; otmp;) {
4580 /* it's tempting to pull this outside the loop, but merged() could
4581 free ONAME(obj) [via obfree()] and replace it with ONAME(otmp) */
4582 objname = has_oname(obj) ? ONAME(obj) : (char *) 0;
4585 /* Collecting: #adjust an inventory stack into its same slot;
4586 keep it there and merge other compatible stacks into it.
4587 Traditional inventory behavior is to merge unnamed stacks
4588 with compatible named ones; we only want that if it is
4589 the 'from' stack (obj) with a name and candidate (otmp)
4590 without one, not unnamed 'from' with named candidate. */
4591 otmpname = has_oname(otmp) ? ONAME(otmp) : (char *) 0;
4592 if ((!otmpname || (objname && !strcmp(objname, otmpname)))
4593 && merged(&otmp, &obj)) {
4595 adj_type = "Merging:";
4597 adj_type = "
\82ð
\8d\87\82í
\82¹
\82½
\81D";
4600 extract_nobj(obj, &invent);
4601 continue; /* otmp has already been updated */
4603 } else if (otmp->invlet == let) {
4604 /* Moving or splitting: don't merge extra compatible stacks.
4605 Found 'otmp' in destination slot; merge if compatible,
4606 otherwise bump whatever is there to an open slot. */
4609 adj_type = "Swapping:";
4611 adj_type = "
\82ð
\8cð
\8a·
\82µ
\82½
\81D";
4612 otmp->invlet = obj->invlet;
4614 /* strip 'from' name if it has one */
4615 if (objname && !obj->oartifact)
4616 ONAME(obj) = (char *) 0;
4617 if (!mergable(otmp, obj)) {
4618 /* won't merge; put 'from' name back */
4620 ONAME(obj) = objname;
4622 /* will merge; discard 'from' name */
4624 free((genericptr_t) objname), objname = 0;
4627 if (merged(&otmp, &obj)) {
4629 adj_type = "Splitting and merging:";
4631 adj_type = "
\82ð
\95ª
\8a\84\82µ
\82Ä
\8d\87\82í
\82¹
\82½
\81D";
4633 extract_nobj(obj, &invent);
4634 } else if (inv_cnt(FALSE) >= 52) {
4635 (void) merged(&splitting, &obj); /* undo split */
4636 /* "knapsack cannot accommodate any more items" */
4638 Your("pack is too full.");
4640 Your("
\8e\9d\82¿
\95¨
\82Í
\88ê
\94t
\82¾
\81D");
4644 extract_nobj(bumped, &invent);
4646 } /* moving vs splitting */
4647 break; /* not collecting and found 'to' slot */
4652 /* inline addinv; insert loose object at beginning of inventory */
4655 obj->where = OBJ_INVENT;
4659 /* splitting the 'from' stack is causing an incompatible
4660 stack in the 'to' slot to be moved into an open one;
4661 we need to do another inline insertion to inventory */
4662 assigninvlet(bumped);
4663 bumped->nobj = invent;
4664 bumped->where = OBJ_INVENT;
4669 /* messages deferred until inventory has been fully reestablished */
4670 prinv(adj_type, obj, 0L);
4673 prinv("Moving:", bumped, 0L);
4675 prinv("
\88Ú
\93®:", bumped, 0L);
4677 clear_splitobjs(); /* reset splitobj context */
4682 /* common to display_minventory and display_cinventory */
4684 invdisp_nothing(hdr, txt)
4685 const char *hdr, *txt;
4689 menu_item *selected;
4692 win = create_nhwindow(NHW_MENU);
4694 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr,
4696 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
4697 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
4698 end_menu(win, (char *) 0);
4699 if (select_menu(win, PICK_NONE, &selected) > 0)
4700 free((genericptr_t) selected);
4701 destroy_nhwindow(win);
4705 /* query_objlist callback: return things that are worn or wielded */
4707 worn_wield_only(obj)
4711 /* check for things that *are* worn or wielded (only used for monsters,
4712 so we don't worry about excluding W_CHAIN, W_ARTI and the like) */
4713 return (boolean) (obj->owornmask != 0L);
4715 /* this used to check for things that *might* be worn or wielded,
4716 but that's not particularly interesting */
4717 if (is_weptool(obj) || is_wet_towel(obj) || obj->otyp == MEAT_RING)
4719 return (boolean) (obj->oclass == WEAPON_CLASS
4720 || obj->oclass == ARMOR_CLASS
4721 || obj->oclass == AMULET_CLASS
4722 || obj->oclass == RING_CLASS);
4727 * Display a monster's inventory.
4728 * Returns a pointer to the object from the monster's inventory selected
4729 * or NULL if nothing was selected.
4731 * By default, only worn and wielded items are displayed. The caller
4732 * can pick one. Modifier flags are:
4734 * PICK_NONE, PICK_ONE - standard menu control
4735 * PICK_ANY - allowed, but we only return a single object
4736 * MINV_NOLET - nothing selectable
4737 * MINV_ALL - display all inventory
4740 display_minventory(mon, dflags, title)
4741 register struct monst *mon;
4748 menu_item *selected = 0;
4749 int do_all = (dflags & MINV_ALL) != 0,
4750 incl_hero = (do_all && u.uswallow && mon == u.ustuck),
4751 have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
4752 pickings = (dflags & MINV_PICKMASK);
4755 Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
4756 do_all ? "possessions" : "armament");
4758 Sprintf(tmp, "%s
\82Ì%s
\81F", Monnam(mon),
4759 do_all ? "
\8e\9d\82¿
\95¨" : "
\91\95\94õ");
4762 if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
4763 /* Fool the 'weapon in hand' routine into
4764 * displaying 'weapon in claw', etc. properly.
4766 youmonst.data = mon->data;
4767 /* in case inside a shop, don't append "for sale" prices */
4768 iflags.suppress_price++;
4770 n = query_objlist(title ? title : tmp, &(mon->minvent),
4771 (INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0)),
4772 &selected, pickings,
4773 do_all ? allow_all : worn_wield_only);
4775 iflags.suppress_price--;
4776 /* was 'set_uasmon();' but that potentially has side-effects */
4777 youmonst.data = &mons[u.umonnum]; /* most basic part of set_uasmon */
4780 invdisp_nothing(title ? title : tmp, "(none)");
4782 invdisp_nothing(title ? title : tmp, "(
\89½
\82à
\82È
\82¢)");
4787 ret = selected[0].item.a_obj;
4788 free((genericptr_t) selected);
4790 ret = (struct obj *) 0;
4795 * Display the contents of a container in inventory style.
4796 * Currently, this is only used for statues, via wand of probing.
4799 display_cinventory(obj)
4800 register struct obj *obj;
4805 menu_item *selected = 0;
4808 (void) safe_qbuf(qbuf, "Contents of ", ":", obj, doname, ansimpleoname,
4811 (void) safe_qbuf(qbuf, "", "
\82Ì
\92\86\90g
\81F", obj, doname, ansimpleoname,
4816 n = query_objlist(qbuf, &(obj->cobj), INVORDER_SORT,
4817 &selected, PICK_NONE, allow_all);
4820 invdisp_nothing(qbuf, "(empty)");
4822 invdisp_nothing(qbuf, "(
\8bó
\82Á
\82Û)");
4826 ret = selected[0].item.a_obj;
4827 free((genericptr_t) selected);
4829 ret = (struct obj *) 0;
4834 /* query objlist callback: return TRUE if obj is at given location */
4841 return (obj->ox == only.x && obj->oy == only.y);
4845 * Display a list of buried items in inventory style. Return a non-zero
4846 * value if there were items at that spot.
4848 * Currently, this is only used with a wand of probing zapped downwards.
4851 display_binventory(x, y, as_if_seen)
4856 menu_item *selected = 0;
4859 /* count # of objects here */
4860 for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
4861 if (obj->ox == x && obj->oy == y) {
4871 if (query_objlist("Things that are buried here:",
4873 if (query_objlist("
\82±
\82±
\82É
\96\84\82ß
\82ç
\82ê
\82Ä
\82¢
\82é
\82à
\82Ì
\81F",
4874 &level.buriedobjlist, INVORDER_SORT,
4875 &selected, PICK_NONE, only_here) > 0)
4876 free((genericptr_t) selected);
4877 only.x = only.y = 0;