1 /* NetHack 3.6 invent.c $NHDT-Date: 1519672703 2018/02/26 19:18:23 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.225 $ */
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-2016 */
9 /* JNetHack may be freely redistributed. See license for details. */
14 #define CONTAINED_SYM '>' /* designator for inside a container */
17 STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (const genericptr,
19 STATIC_DCL void NDECL(reorder_invent);
20 STATIC_DCL void FDECL(noarmor, (BOOLEAN_P));
21 STATIC_DCL void FDECL(invdisp_nothing, (const char *, const char *));
22 STATIC_DCL boolean FDECL(worn_wield_only, (struct obj *));
23 STATIC_DCL boolean FDECL(only_here, (struct obj *));
24 STATIC_DCL void FDECL(compactify, (char *));
25 STATIC_DCL boolean FDECL(taking_off, (const char *));
26 STATIC_DCL boolean FDECL(putting_on, (const char *));
27 STATIC_PTR int FDECL(ckunpaid, (struct obj *));
28 STATIC_PTR int FDECL(ckvalidcat, (struct obj *));
29 STATIC_PTR char *FDECL(safeq_xprname, (struct obj *));
30 STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
31 STATIC_DCL char FDECL(display_pickinv, (const char *, const char *,
32 const char *, BOOLEAN_P, long *));
33 STATIC_DCL char FDECL(display_used_invlets, (CHAR_P));
34 STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
35 STATIC_DCL void NDECL(dounpaid);
36 STATIC_DCL struct obj *FDECL(find_unpaid, (struct obj *, struct obj **));
37 STATIC_DCL void FDECL(menu_identify, (int));
38 STATIC_DCL boolean FDECL(tool_in_use, (struct obj *));
39 STATIC_DCL char FDECL(obj_to_let, (struct obj *));
41 static int lastinvnr = 51; /* 0 ... 51 (never saved&restored) */
43 /* wizards can wish for venom, which will become an invisible inventory
44 * item without this. putting it in inv_order would mean venom would
45 * suddenly become a choice for all the inventory-class commands, which
46 * would probably cause mass confusion. the test for inventory venom
47 * is only WIZARD and not wizard because the wizard can leave venom lying
48 * around on a bones level for normal players to find. [Note to the
49 * confused: 'WIZARD' used to be a compile-time conditional so this was
50 * guarded by #ifdef WIZARD/.../#endif.]
52 static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */
54 struct sortloot_item {
58 unsigned sortlootmode = 0;
60 /* qsort comparison routine for sortloot() */
61 STATIC_OVL int CFDECLSPEC
62 sortloot_cmp(vptr1, vptr2)
63 const genericptr vptr1;
64 const genericptr vptr2;
66 struct sortloot_item *sli1 = (struct sortloot_item *) vptr1,
67 *sli2 = (struct sortloot_item *) vptr2;
68 struct obj *obj1 = sli1->obj,
71 char *cls1, *cls2, nam1[BUFSZ], nam2[BUFSZ];
72 int val1, val2, c, namcmp;
74 /* order by object class like inventory display */
75 if ((sortlootmode & SORTLOOT_PACK) != 0) {
76 cls1 = index(flags.inv_order, obj1->oclass);
77 cls2 = index(flags.inv_order, obj2->oclass);
79 return (int) (cls1 - cls2);
81 if ((sortlootmode & SORTLOOT_INVLET) != 0) {
82 ; /* skip sub-classes when sorting by packorder+invlet */
84 /* for armor, group by sub-category */
85 } else if (obj1->oclass == ARMOR_CLASS) {
86 static int armcat[7 + 1];
89 /* one-time init; we want to control the order */
90 armcat[ARM_HELM] = 1; /* [2] */
91 armcat[ARM_GLOVES] = 2; /* [3] */
92 armcat[ARM_BOOTS] = 3; /* [4] */
93 armcat[ARM_SHIELD] = 4; /* [1] */
94 armcat[ARM_CLOAK] = 5; /* [5] */
95 armcat[ARM_SHIRT] = 6; /* [6] */
96 armcat[ARM_SUIT] = 7; /* [0] */
99 val1 = armcat[objects[obj1->otyp].oc_armcat];
100 val2 = armcat[objects[obj2->otyp].oc_armcat];
104 /* for weapons, group by ammo (arrows, bolts), launcher (bows),
105 missile (dart, boomerang), stackable (daggers, knives, spears),
106 'other' (swords, axes, &c), polearm */
107 } else if (obj1->oclass == WEAPON_CLASS) {
108 val1 = objects[obj1->otyp].oc_skill;
110 ? (val1 >= -P_CROSSBOW && val1 <= -P_BOW) ? 1 : 3
111 : (val1 >= P_BOW && val1 <= P_CROSSBOW) ? 2
112 : (val1 == P_SPEAR || val1 == P_DAGGER
113 || val1 == P_KNIFE) ? 4 : !is_pole(obj1) ? 5 : 6;
114 val2 = objects[obj2->otyp].oc_skill;
116 ? (val2 >= -P_CROSSBOW && val2 <= -P_BOW) ? 1 : 3
117 : (val2 >= P_BOW && val2 <= P_CROSSBOW) ? 2
118 : (val2 == P_SPEAR || val2 == P_DAGGER
119 || val2 == P_KNIFE) ? 4 : !is_pole(obj2) ? 5 : 6;
125 /* order by assigned inventory letter */
126 if ((sortlootmode & SORTLOOT_INVLET) != 0) {
128 val1 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
129 : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
131 : (c == '#') ? 1 + 52 + 1
132 : 1 + 52 + 1 + 1; /* none of the above */
134 val2 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
135 : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
137 : (c == '#') ? 1 + 52 + 1
138 : 1 + 52 + 1 + 1; /* none of the above */
143 if ((sortlootmode & SORTLOOT_LOOT) == 0)
147 * Sort object names in lexicographical order, ignoring quantity.
149 /* Force diluted potions to come out after undiluted of same type;
150 obj->odiluted overloads obj->oeroded. */
151 sav1.odiluted = obj1->odiluted;
152 sav2.odiluted = obj2->odiluted;
153 if (obj1->oclass == POTION_CLASS)
155 if (obj1->oclass == POTION_CLASS)
157 /* Force holy and unholy water to sort adjacent to water rather
158 than among 'h's and 'u's. BUCX order will keep them distinct. */
159 Strcpy(nam1, cxname_singular(obj1));
160 if (obj1->otyp == POT_WATER && obj1->bknown
161 && (obj1->blessed || obj1->cursed))
162 (void) strsubst(nam1, obj1->blessed ? "holy " : "unholy ", "");
163 Strcpy(nam2, cxname_singular(obj2));
164 if (obj2->otyp == POT_WATER && obj2->bknown
165 && (obj2->blessed || obj2->cursed))
166 (void) strsubst(nam2, obj2->blessed ? "holy " : "unholy ", "");
167 obj1->odiluted = sav1.odiluted;
168 obj2->odiluted = sav2.odiluted;
170 if ((namcmp = strcmpi(nam1, nam2)) != 0)
174 val1 = obj1->bknown ? (obj1->blessed ? 3 : !obj1->cursed ? 2 : 1) : 0;
175 val2 = obj2->bknown ? (obj2->blessed ? 3 : !obj2->cursed ? 2 : 1) : 0;
177 return val2 - val1; /* bigger is better */
179 /* Sort by greasing. This will put the objects in degreasing order. */
180 val1 = obj1->greased;
181 val2 = obj2->greased;
183 return val2 - val1; /* bigger is better */
185 /* Sort by erosion. The effective amount is what matters. */
186 val1 = greatest_erosion(obj1);
187 val2 = greatest_erosion(obj2);
189 return val1 - val2; /* bigger is WORSE */
191 /* Sort by erodeproofing. Map known-invulnerable to 1, and both
192 known-vulnerable and unknown-vulnerability to 0, because that's
193 how they're displayed. */
194 val1 = obj1->rknown && obj1->oerodeproof;
195 val2 = obj2->rknown && obj2->oerodeproof;
197 return val2 - val1; /* bigger is better */
199 /* Sort by enchantment. Map unknown to -1000, which is comfortably
200 below the range of obj->spe. oc_uses_known means that obj->known
201 matters, which usually indirectly means that obj->spe is relevant.
202 Lots of objects use obj->spe for some other purpose (see obj.h). */
203 if (objects[obj1->otyp].oc_uses_known
204 /* exclude eggs (laid by you) and tins (homemade, pureed, &c) */
205 && obj1->oclass != FOOD_CLASS) {
206 val1 = obj1->known ? obj1->spe : -1000;
207 val2 = obj2->known ? obj2->spe : -1000;
209 return val2 - val1; /* bigger is better */
213 /* They're identical, as far as we're concerned. We want
214 to force a deterministic order, and do so by producing a
215 stable sort: maintain the original order of equal items. */
216 return (sli1->indx - sli2->indx);
220 sortloot(olist, mode, by_nexthere)
222 unsigned mode; /* flags for sortloot_cmp() */
223 boolean by_nexthere; /* T: traverse via obj->nexthere, F: via obj->nobj */
225 struct sortloot_item *sliarray, osli, nsli;
226 struct obj *o, **nxt_p;
228 boolean already_sorted = TRUE;
230 sortlootmode = mode; /* extra input for sortloot_cmp() */
231 for (n = osli.indx = 0, osli.obj = *olist; (o = osli.obj) != 0;
233 nsli.obj = by_nexthere ? o->nexthere : o->nobj;
234 nsli.indx = (int) ++n;
235 if (nsli.obj && already_sorted
236 && sortloot_cmp((genericptr_t) &osli, (genericptr_t) &nsli) > 0)
237 already_sorted = FALSE;
239 if (n > 1 && !already_sorted) {
240 sliarray = (struct sortloot_item *) alloc(n * sizeof *sliarray);
241 for (i = 0, o = *olist; o;
242 ++i, o = by_nexthere ? o->nexthere : o->nobj)
243 sliarray[i].obj = o, sliarray[i].indx = (int) i;
245 qsort((genericptr_t) sliarray, n, sizeof *sliarray, sortloot_cmp);
246 for (i = 0; i < n; ++i) {
248 nxt_p = by_nexthere ? &(o->nexthere) : &(o->nobj);
249 *nxt_p = (i < n - 1) ? sliarray[i + 1].obj : (struct obj *) 0;
251 *olist = sliarray[0].obj;
252 free((genericptr_t) sliarray);
259 register struct obj *otmp;
263 register struct obj *obj;
265 /* there should be at most one of these in inventory... */
266 if (otmp->oclass == COIN_CLASS) {
267 otmp->invlet = GOLD_SYM;
271 for (i = 0; i < 52; i++)
273 for (obj = invent; obj; obj = obj->nobj)
276 if ('a' <= i && i <= 'z')
277 inuse[i - 'a'] = TRUE;
278 else if ('A' <= i && i <= 'Z')
279 inuse[i - 'A' + 26] = TRUE;
280 if (i == otmp->invlet)
283 if ((i = otmp->invlet)
284 && (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
286 for (i = lastinvnr + 1; i != lastinvnr; i++) {
295 (inuse[i] ? NOINVSYM : (i < 26) ? ('a' + i) : ('A' + i - 26));
299 /* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */
300 #define inv_rank(o) ((o)->invlet ^ 040)
302 /* sort the inventory; used by addinv() and doorganize() */
306 struct obj *otmp, *prev, *next;
307 boolean need_more_sorting;
311 * We expect at most one item to be out of order, so this
312 * isn't nearly as inefficient as it may first appear.
314 need_more_sorting = FALSE;
315 for (otmp = invent, prev = 0; otmp;) {
317 if (next && inv_rank(next) < inv_rank(otmp)) {
318 need_more_sorting = TRUE;
323 otmp->nobj = next->nobj;
331 } while (need_more_sorting);
336 /* scan a list of objects to see whether another object will merge with
337 one of them; used in pickup.c when all 52 inventory slots are in use,
338 to figure out whether another object could still be picked up */
340 merge_choice(objlist, obj)
341 struct obj *objlist, *obj;
346 if (obj->otyp == SCR_SCARE_MONSTER) /* punt on these */
347 return (struct obj *) 0;
348 /* if this is an item on the shop floor, the attributes it will
349 have when carried are different from what they are now; prevent
350 that from eliciting an incorrect result from mergable() */
351 save_nocharge = obj->no_charge;
352 if (objlist == invent && obj->where == OBJ_FLOOR
353 && (shkp = shop_keeper(inside_shop(obj->ox, obj->oy))) != 0) {
356 /* A billable object won't have its `unpaid' bit set, so would
357 erroneously seem to be a candidate to merge with a similar
358 ordinary object. That's no good, because once it's really
359 picked up, it won't merge after all. It might merge with
360 another unpaid object, but we can't check that here (depends
361 too much upon shk's bill) and if it doesn't merge it would
362 end up in the '#' overflow inventory slot, so reject it now. */
363 else if (inhishop(shkp))
364 return (struct obj *) 0;
367 if (mergable(objlist, obj))
369 objlist = objlist->nobj;
371 obj->no_charge = save_nocharge;
375 /* merge obj with otmp and delete obj if types agree */
378 struct obj **potmp, **pobj;
380 register struct obj *otmp = *potmp, *obj = *pobj;
382 if (mergable(otmp, obj)) {
383 /* Approximate age: we do it this way because if we were to
384 * do it "accurately" (merge only when ages are identical)
385 * we'd wind up never merging any corpses.
386 * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
388 * Don't do the age manipulation if lit. We would need
389 * to stop the burn on both items, then merge the age,
390 * then restart the burn. Glob ages are averaged in the
391 * absorb routine, which uses weight rather than quantity
392 * to adjust for proportion (glob quantity is always 1).
394 if (!obj->lamplit && !obj->globby)
395 otmp->age = ((otmp->age * otmp->quan) + (obj->age * obj->quan))
396 / (otmp->quan + obj->quan);
398 otmp->quan += obj->quan;
399 /* temporary special case for gold objects!!!! */
400 if (otmp->oclass == COIN_CLASS)
401 otmp->owt = weight(otmp), otmp->bknown = 0;
402 /* and puddings!!!1!!one! */
403 else if (!Is_pudding(otmp))
404 otmp->owt += obj->owt;
405 if (!has_oname(otmp) && has_oname(obj))
406 otmp = *potmp = oname(otmp, ONAME(obj));
407 obj_extract_self(obj);
409 /* really should merge the timeouts */
411 obj_merge_light_sources(obj, otmp);
413 obj_stop_timers(obj); /* follows lights */
415 /* fixup for `#adjust' merging wielded darts, daggers, &c */
416 if (obj->owornmask && carried(otmp)) {
417 long wmask = otmp->owornmask | obj->owornmask;
419 /* Both the items might be worn in competing slots;
420 merger preference (regardless of which is which):
421 primary weapon + alternate weapon -> primary weapon;
422 primary weapon + quiver -> primary weapon;
423 alternate weapon + quiver -> alternate weapon.
424 (Prior to 3.3.0, it was not possible for the two
425 stacks to be worn in different slots and `obj'
426 didn't need to be unworn when merging.) */
429 else if (wmask & W_SWAPWEP)
431 else if (wmask & W_QUIVER)
434 impossible("merging strangely worn items (%lx)", wmask);
435 wmask = otmp->owornmask;
437 if ((otmp->owornmask & ~wmask) != 0L)
439 setworn(otmp, wmask);
442 /* (this should not be necessary, since items
443 already in a monster's inventory don't ever get
444 merged into other objects [only vice versa]) */
445 } else if (obj->owornmask && mcarried(otmp)) {
446 if (obj == MON_WEP(otmp->ocarry)) {
447 MON_WEP(otmp->ocarry) = otmp;
448 otmp->owornmask = W_WEP;
453 /* handle puddings a bit differently; absorption will free the
454 other object automatically so we can just return out from here */
456 pudding_merge_message(otmp, obj);
457 obj_absorb(potmp, pobj);
461 obfree(obj, otmp); /* free(obj), bill->otmp */
468 * Adjust hero intrinsics as if this object was being added to the hero's
469 * inventory. Called _before_ the object has been added to the hero's
472 * This is called when adding objects to the hero's inventory normally (via
473 * addinv) or when an object in the hero's inventory has been polymorphed
476 * It may be valid to merge this code with with addinv_core2().
482 if (obj->oclass == COIN_CLASS) {
484 } else if (obj->otyp == AMULET_OF_YENDOR) {
486 impossible("already have amulet?");
488 u.uachieve.amulet = 1;
489 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
491 impossible("already have candelabrum?");
493 u.uachieve.menorah = 1;
494 } else if (obj->otyp == BELL_OF_OPENING) {
496 impossible("already have silver bell?");
499 } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
501 impossible("already have the book?");
504 } else if (obj->oartifact) {
505 if (is_quest_artifact(obj)) {
506 if (u.uhave.questart)
507 impossible("already have quest artifact?");
508 u.uhave.questart = 1;
511 set_artifact_intrinsic(obj, 1, W_ART);
514 /* "special achievements" aren't discoverable during play, they
515 end up being recorded in XLOGFILE at end of game, nowhere else;
516 record_achieve_special overloads corpsenm which is ordinarily
517 initialized to NON_PM (-1) rather than to 0; any special prize
518 must never be a corpse, egg, tin, figurine, or statue because
519 their use of obj->corpsenm for monster type would conflict,
520 nor be a leash (corpsenm overloaded for m_id of leashed
521 monster) or a novel (corpsenm overloaded for novel index) */
522 if (is_mines_prize(obj)) {
523 u.uachieve.mines_luckstone = 1;
524 obj->record_achieve_special = NON_PM;
525 } else if (is_soko_prize(obj)) {
526 u.uachieve.finish_sokoban = 1;
527 obj->record_achieve_special = NON_PM;
532 * Adjust hero intrinsics as if this object was being added to the hero's
533 * inventory. Called _after_ the object has been added to the hero's
536 * This is called when adding objects to the hero's inventory normally (via
537 * addinv) or when an object in the hero's inventory has been polymorphed
544 if (confers_luck(obj)) {
545 /* new luckstone must be in inventory by this point
546 * for correct calculation */
552 * Add obj to the hero's inventory. Make sure the object is "free".
553 * Adjust hero attributes as necessary.
559 struct obj *otmp, *prev;
560 int saved_otyp = (int) obj->otyp; /* for panic */
561 boolean obj_was_thrown;
563 if (obj->where != OBJ_FREE)
564 panic("addinv: obj not free");
565 /* normally addtobill() clears no_charge when items in a shop are
566 picked up, but won't do so if the shop has become untended */
567 obj->no_charge = 0; /* should not be set in hero's invent */
568 if (Has_contents(obj))
569 picked_container(obj); /* clear no_charge */
570 obj_was_thrown = obj->was_thrown;
571 obj->was_thrown = 0; /* not meaningful for invent */
575 /* merge with quiver in preference to any other inventory slot
576 in case quiver and wielded weapon are both eligible; adding
577 extra to quivered stack is more useful than to wielded one */
578 if (uquiver && merged(&uquiver, &obj)) {
581 panic("addinv: null obj after quiver merge otyp=%d", saved_otyp);
584 /* merge if possible; find end of chain in the process */
585 for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj)
586 if (merged(&otmp, &obj)) {
589 panic("addinv: null obj after merge otyp=%d", saved_otyp);
592 /* didn't merge, so insert into chain */
594 if (flags.invlet_constant || !prev) {
595 obj->nobj = invent; /* insert at beginning */
597 if (flags.invlet_constant)
600 prev->nobj = obj; /* insert at end */
603 obj->where = OBJ_INVENT;
605 /* fill empty quiver if obj was thrown */
606 if (flags.pickup_thrown && !uquiver && obj_was_thrown
607 /* if Mjollnir is thrown and fails to return, we want to
608 auto-pick it when we move to its spot, but not into quiver;
609 aklyses behave like Mjollnir when thrown while wielded, but
610 we lack sufficient information here make them exceptions */
611 && obj->oartifact != ART_MJOLLNIR
612 && (throwing_weapon(obj) || is_ammo(obj)))
616 carry_obj_effects(obj); /* carrying affects the obj */
622 * Some objects are affected by being carried.
623 * Make those adjustments here. Called _after_ the object
624 * has been added to the hero's or monster's inventory,
625 * and after hero's intrinsics have been updated.
628 carry_obj_effects(obj)
631 /* Cursed figurines can spontaneously transform when carried. */
632 if (obj->otyp == FIGURINE) {
633 if (obj->cursed && obj->corpsenm != NON_PM
634 && !dead_species(obj->corpsenm, TRUE)) {
635 attach_fig_transform_timeout(obj);
640 /* Add an item to the inventory unless we're fumbling or it refuses to be
641 * held (via touch_artifact), and give a message.
642 * If there aren't any free inventory slots, we'll drop it instead.
643 * If both success and failure messages are NULL, then we're just doing the
644 * fumbling/slot-limit checking for a silent grab. In any case,
645 * touch_artifact will print its own messages if they are warranted.
648 hold_another_object(obj, drop_fmt, drop_arg, hold_msg)
650 const char *drop_fmt, *drop_arg, *hold_msg;
655 obj->dknown = 1; /* maximize mergibility */
656 if (obj->oartifact) {
657 /* place_object may change these */
658 boolean crysknife = (obj->otyp == CRYSKNIFE);
659 int oerode = obj->oerodeproof;
660 boolean wasUpolyd = Upolyd;
662 /* in case touching this object turns out to be fatal */
663 place_object(obj, u.ux, u.uy);
665 if (!touch_artifact(obj, &youmonst)) {
666 obj_extract_self(obj); /* remove it from the floor */
667 dropy(obj); /* now put it back again :-) */
669 } else if (wasUpolyd && !Upolyd) {
670 /* loose your grip if you revert your form */
672 pline(drop_fmt, drop_arg);
673 obj_extract_self(obj);
677 obj_extract_self(obj);
679 obj->otyp = CRYSKNIFE;
680 obj->oerodeproof = oerode;
685 pline(drop_fmt, drop_arg);
688 long oquan = obj->quan;
689 int prev_encumbr = near_capacity(); /* before addinv() */
691 /* encumbrance only matters if it would now become worse
692 than max( current_value, stressed ) */
693 if (prev_encumbr < MOD_ENCUMBER)
694 prev_encumbr = MOD_ENCUMBER;
695 /* addinv() may redraw the entire inventory, overwriting
696 drop_arg when it comes from something like doname() */
698 drop_arg = strcpy(buf, drop_arg);
701 if (inv_cnt(FALSE) > 52 || ((obj->otyp != LOADSTONE || !obj->cursed)
702 && near_capacity() > prev_encumbr)) {
704 pline(drop_fmt, drop_arg);
705 /* undo any merge which took place */
706 if (obj->quan > oquan)
707 obj = splitobj(obj, oquan);
710 if (flags.autoquiver && !uquiver && !obj->owornmask
711 && (is_missile(obj) || ammo_and_launcher(obj, uwep)
712 || ammo_and_launcher(obj, uswapwep)))
714 if (hold_msg || drop_fmt)
715 prinv(hold_msg, obj, oquan);
721 /* useup() all of an item regardless of its quantity */
728 obfree(obj, (struct obj *) 0); /* deletes contents also */
733 register struct obj *obj;
735 /* Note: This works correctly for containers because they (containers)
737 if (obj->quan > 1L) {
738 obj->in_use = FALSE; /* no longer in use */
740 obj->owt = weight(obj);
747 /* use one charge from an item and possibly incur shop debt for it */
749 consume_obj_charge(obj, maybe_unpaid)
751 boolean maybe_unpaid; /* false if caller handles shop billing */
761 * Adjust hero's attributes as if this object was being removed from the
762 * hero's inventory. This should only be called from freeinv() and
763 * where we are polymorphing an object already in the hero's inventory.
765 * Should think of a better name...
771 if (obj->oclass == COIN_CLASS) {
774 } else if (obj->otyp == AMULET_OF_YENDOR) {
776 impossible("don't have amulet?");
778 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
779 if (!u.uhave.menorah)
780 impossible("don't have candelabrum?");
782 } else if (obj->otyp == BELL_OF_OPENING) {
784 impossible("don't have silver bell?");
786 } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
788 impossible("don't have the book?");
790 } else if (obj->oartifact) {
791 if (is_quest_artifact(obj)) {
792 if (!u.uhave.questart)
793 impossible("don't have quest artifact?");
794 u.uhave.questart = 0;
796 set_artifact_intrinsic(obj, 0, W_ART);
799 if (obj->otyp == LOADSTONE) {
801 } else if (confers_luck(obj)) {
804 } else if (obj->otyp == FIGURINE && obj->timed) {
805 (void) stop_timer(FIG_TRANSFORM, obj_to_any(obj));
809 /* remove an object from the hero's inventory */
812 register struct obj *obj;
814 extract_nobj(obj, &invent);
823 struct obj *otmp, *otmp2;
825 for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
828 /* after unpunish(), or might get deallocated chain */
829 otmp2 = otmp->nexthere;
836 /* destroy object in fobj chain (if unpaid, it remains on the bill) */
839 register struct obj *obj;
843 if (obj->otyp == AMULET_OF_YENDOR
844 || obj->otyp == CANDELABRUM_OF_INVOCATION
845 || obj->otyp == BELL_OF_OPENING
846 || obj->otyp == SPE_BOOK_OF_THE_DEAD) {
847 /* player might be doing something stupid, but we
848 * can't guarantee that. assume special artifacts
849 * are indestructible via drawbridges, and exploding
850 * chests, and golem creation, and ...
854 update_map = (obj->where == OBJ_FLOOR);
855 obj_extract_self(obj);
857 newsym(obj->ox, obj->oy);
858 obfree(obj, (struct obj *) 0); /* frees contents also */
861 /* try to find a particular type of object at designated map location */
867 register struct obj *otmp;
869 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
870 if (otmp->otyp == otyp)
876 /* sobj_at(&c) traversal -- find next object of specified type */
878 nxtobj(obj, type, by_nexthere)
883 register struct obj *otmp;
885 otmp = obj; /* start with the object after this one */
887 otmp = !by_nexthere ? otmp->nobj : otmp->nexthere;
890 } while (otmp->otyp != type);
899 register struct obj *otmp;
901 for (otmp = invent; otmp; otmp = otmp->nobj)
902 if (otmp->otyp == type)
904 return (struct obj *) 0;
907 /* Fictional and not-so-fictional currencies.
908 * http://concord.wikia.com/wiki/List_of_Fictional_Currencies
910 static const char *const currencies[] = {
912 "Altarian Dollar", /* The Hitchhiker's Guide to the Galaxy */
913 "Ankh-Morpork Dollar", /* Discworld */
914 "auric", /* The Domination of Draka */
915 "buckazoid", /* Space Quest */
916 "cirbozoid", /* Starslip */
917 "credit chit", /* Deus Ex */
918 "cubit", /* Battlestar Galactica */
919 "Flanian Pobble Bead", /* The Hitchhiker's Guide to the Galaxy */
920 "fretzer", /* Jules Verne */
921 "imperial credit", /* Star Wars */
922 "Hong Kong Luna Dollar", /* The Moon is a Harsh Mistress */
923 "kongbuck", /* Snow Crash */
924 "nanite", /* System Shock 2 */
925 "quatloo", /* Star Trek, Sim City */
926 "simoleon", /* Sim City */
927 "solari", /* Spaceballs */
928 "spacebuck", /* Spaceballs */
929 "sporebuck", /* Spore */
930 "Triganic Pu", /* The Hitchhiker's Guide to the Galaxy */
931 "woolong", /* Cowboy Bebop */
932 "zorkmid", /* Zork, NetHack */
934 "
\83A
\83\8b\83^
\83C
\83\8b\81E
\83h
\83\8b", /* The Hitchhiker's Guide to the Galaxy */
935 "
\83A
\83\93\83N
\83\82\83\8b\83|
\81[
\83N
\81E
\83h
\83\8b", /* Discworld */
936 "
\83\86\81[
\83\8a\83b
\83N", /* The Domination of Draka */
937 "
\83o
\83b
\83J
\83]
\83C
\83h", /* Space Quest */
938 "
\83T
\81[
\83{
\83]
\83C
\83h", /* Starslip */
939 "
\83N
\83\8c\83W
\83b
\83g
\81E
\83`
\83b
\83g", /* Deus Ex */
940 "
\83L
\83\85\81[
\83r
\83b
\83g", /* Battlestar Galactica */
941 "
\83t
\83\8c\83j
\83A
\83\93\81E
\83s
\83b
\83u
\83\8b\81E
\83r
\81[
\83h", /* The Hitchhiker's Guide to the Galaxy */
942 "
\83t
\83\8c\83b
\83c
\83@", /* Jules Verne */
943 "
\92é
\8d\91\83N
\83\8c\83W
\83b
\83g", /* Star Wars */
944 "
\8d\81\8d`
\8c\8e\83h
\83\8b", /* The Moon is a Harsh Mistress */
945 "
\83R
\83\93\83o
\83b
\83N", /* Snow Crash */
946 "
\83i
\81[
\83i
\83C
\83g", /* System Shock 2 */
947 "
\83N
\83@
\83g
\83\8d", /* Star Trek, Sim City */
948 "
\83V
\83\82\83\8c\83I
\83\93", /* Sim City */
949 "
\83\
\83\89\83\8a", /* Spaceballs */
950 "
\83X
\83y
\81[
\83X
\83o
\83b
\83N", /* Spaceballs */
951 "
\83X
\83|
\83A
\83o
\83b
\83N", /* Spore */
952 "
\83g
\83\89\83C
\83K
\83j
\83b
\83N
\81E
\83v
\81[", /* The Hitchhiker's Guide to the Galaxy */
953 "
\83E
\81[
\83\8d\83\93", /* Cowboy Bebop */
954 "
\83S
\81[
\83\8b\83h", /* Zork, NetHack */
965 res = Hallucination ? currencies[rn2(SIZE(currencies))] : "zorkmid";
967 res = makeplural(res);
969 res = Hallucination ? currencies[rn2(SIZE(currencies))] : "
\83S
\81[
\83\8b\83h";
977 register struct obj *otmp;
979 for (otmp = invent; otmp; otmp = otmp->nobj)
980 if (otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
989 register struct obj *otmp;
991 for (otmp = invent; otmp; otmp = otmp->nobj)
992 if (otmp->otyp == SPE_NOVEL)
994 return (struct obj *) 0;
1000 register struct obj *objchn;
1005 if (objchn->o_id == id)
1007 if (Has_contents(objchn) && (temp = o_on(id, objchn->cobj)))
1009 objchn = objchn->nobj;
1011 return (struct obj *) 0;
1016 register struct obj *obj;
1019 register struct obj *otmp;
1021 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
1031 register struct obj *obj = level.objects[x][y];
1034 if (obj->oclass == COIN_CLASS)
1036 obj = obj->nexthere;
1038 return (struct obj *) 0;
1041 /* compact a string of inventory letters by dashing runs of letters */
1046 register int i1 = 1, i2 = 1;
1047 register char ilet, ilet1, ilet2;
1051 buf[++i2] = buf[++i1];
1054 if (ilet == ilet1 + 1) {
1055 if (ilet1 == ilet2 + 1)
1056 buf[i2 - 1] = ilet1 = '-';
1057 else if (ilet2 == '-') {
1058 buf[i2 - 1] = ++ilet1;
1059 buf[i2] = buf[++i1];
1063 } else if (ilet == NOINVSYM) {
1064 /* compact three or more consecutive '#'
1065 characters into "#-#" */
1066 if (i2 >= 2 && buf[i2 - 2] == NOINVSYM && buf[i2 - 1] == NOINVSYM)
1068 else if (i2 >= 3 && buf[i2 - 3] == NOINVSYM && buf[i2 - 2] == '-'
1069 && buf[i2 - 1] == NOINVSYM)
1074 buf[++i2] = buf[++i1];
1079 /* some objects shouldn't be split when count given to getobj or askchain */
1084 return !((obj->otyp == LOADSTONE && obj->cursed)
1085 || (obj == uwep && welded(uwep)));
1088 /* match the prompt for either 'T' or 'R' command */
1093 return !strcmp(action, "take off") || !strcmp(action, "remove");
1096 /* match the prompt for either 'W' or 'P' command */
1101 return !strcmp(action, "wear") || !strcmp(action, "put on");
1106 * struct obj *xxx: object to do something with.
1107 * (struct obj *) 0 error return: no object.
1108 * &zeroobj explicitly no object (as in w-).
1109 !!!! test if gold can be used in unusual ways (eaten etc.)
1110 !!!! may be able to remove "usegold"
1113 ** word
\82É
\82Í
\89p
\8cê
\82Å
\93®
\8e\8c\82ª
\93ü
\82é
\81D
1115 **
\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
1116 **
\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
1121 register const char *let, *word;
1123 register struct obj *otmp;
1125 char buf[BUFSZ], qbuf[QBUFSZ];
1126 char lets[BUFSZ], altlets[BUFSZ], *ap;
1127 register int foo = 0;
1128 register char *bp = buf;
1129 xchar allowcnt = 0; /* 0, 1 or 2 */
1130 boolean usegold = FALSE; /* can't use gold because its illegal */
1131 boolean allowall = FALSE;
1132 boolean allownone = FALSE;
1133 boolean useboulder = FALSE;
1136 boolean cntgiven = FALSE;
1137 boolean msggiven = FALSE;
1138 boolean oneloop = FALSE;
1146 struct trans_verb *tv = trans_verb(word);
1150 joshi = tv->particle;
1152 if (*let == ALLOW_COUNT)
1153 let++, allowcnt = 1;
1154 if (*let == COIN_CLASS)
1155 let++, usegold = TRUE;
1157 /* Equivalent of an "ugly check" for gold */
1158 if (usegold && !strcmp(word, "eat")
1159 && (!metallivorous(youmonst.data)
1160 || youmonst.data == &mons[PM_RUST_MONSTER]))
1163 if (*let == ALL_CLASSES)
1164 let++, allowall = TRUE;
1165 if (*let == ALLOW_NONE)
1166 let++, allownone = TRUE;
1167 /* "ugly check" for reading fortune cookies, part 1.
1168 * The normal 'ugly check' keeps the object on the inventory list.
1169 * We don't want to do that for shirts/cookies, so the check for
1170 * them is handled a bit differently (and also requires that we set
1171 * allowall in the caller).
1173 if (allowall && !strcmp(word, "read"))
1176 /* another ugly check: show boulders (not statues) */
1177 if (*let == WEAPON_CLASS && !strcmp(word, "throw")
1178 && throws_rocks(youmonst.data))
1182 *bp++ = HANDS_SYM, *bp++ = ' '; /* '-' */
1185 if (!flags.invlet_constant)
1188 /* in case invent is in packorder, force it to be in invlet
1189 order before collecing candidate inventory letters;
1190 if player responds with '?' or '*' it will be changed
1191 back by display_pickinv(), but by then we'll have 'lets'
1192 and so won't have to re-sort in the for(;;) loop below */
1193 sortloot(&invent, SORTLOOT_INVLET, FALSE);
1195 for (otmp = invent; otmp; otmp = otmp->nobj) {
1196 if (&bp[foo] == &buf[sizeof buf - 1]
1197 || ap == &altlets[sizeof altlets - 1]) {
1198 /* we must have a huge number of NOINVSYM items somehow */
1199 impossible("getobj: inventory overflow");
1203 if (!*let || index(let, otmp->oclass)
1204 || (usegold && otmp->invlet == GOLD_SYM)
1205 || (useboulder && otmp->otyp == BOULDER)) {
1206 register int otyp = otmp->otyp;
1208 bp[foo++] = otmp->invlet;
1209 /* clang-format off */
1211 /* ugly check: remove inappropriate things */
1213 (taking_off(word) /* exclude if not worn */
1214 && !(otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
1215 || (putting_on(word) /* exclude if already worn */
1216 && (otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
1217 #if 0 /* 3.4.1 -- include currently wielded weapon among 'wield' choices */
1218 || (!strcmp(word, "wield")
1219 && (otmp->owornmask & W_WEP))
1221 || (!strcmp(word, "ready") /* exclude when wielded... */
1222 && ((otmp == uwep || (otmp == uswapwep && u.twoweap))
1223 && otmp->quan == 1L)) /* ...unless more than one */
1224 || ((!strcmp(word, "dip") || !strcmp(word, "grease"))
1225 && inaccessible_equipment(otmp, (const char *) 0, FALSE))
1230 /* Second ugly check; unlike the first it won't trigger an
1231 * "else" in "you don't have anything else to ___".
1235 && ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING)
1236 || (otmp->oclass == TOOL_CLASS && otyp != BLINDFOLD
1237 && otyp != TOWEL && otyp != LENSES)))
1238 || (!strcmp(word, "wield")
1239 && (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
1240 || (!strcmp(word, "eat") && !is_edible(otmp))
1241 || (!strcmp(word, "sacrifice")
1242 && (otyp != CORPSE && otyp != AMULET_OF_YENDOR
1243 && otyp != FAKE_AMULET_OF_YENDOR))
1244 || (!strcmp(word, "write with")
1245 && (otmp->oclass == TOOL_CLASS
1246 && otyp != MAGIC_MARKER && otyp != TOWEL))
1247 || (!strcmp(word, "tin")
1248 && (otyp != CORPSE || !tinnable(otmp)))
1249 || (!strcmp(word, "rub")
1250 && ((otmp->oclass == TOOL_CLASS && otyp != OIL_LAMP
1251 && otyp != MAGIC_LAMP && otyp != BRASS_LANTERN)
1252 || (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
1253 || (!strcmp(word, "use or apply")
1254 /* Picks, axes, pole-weapons, bullwhips */
1255 && ((otmp->oclass == WEAPON_CLASS
1256 && !is_pick(otmp) && !is_axe(otmp)
1257 && !is_pole(otmp) && otyp != BULLWHIP)
1258 || (otmp->oclass == POTION_CLASS
1259 /* only applicable potion is oil, and it will only
1260 be offered as a choice when already discovered */
1261 && (otyp != POT_OIL || !otmp->dknown
1262 || !objects[POT_OIL].oc_name_known))
1263 || (otmp->oclass == FOOD_CLASS
1264 && otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF)
1265 || (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
1266 || (!strcmp(word, "invoke")
1268 && !objects[otyp].oc_unique
1269 && (otyp != FAKE_AMULET_OF_YENDOR || otmp->known)
1270 && otyp != CRYSTAL_BALL /* synonym for apply */
1271 /* note: presenting the possibility of invoking non-artifact
1272 mirrors and/or lamps is simply a cruel deception... */
1274 && otyp != MAGIC_LAMP
1275 && (otyp != OIL_LAMP /* don't list known oil lamp */
1276 || (otmp->dknown && objects[OIL_LAMP].oc_name_known)))
1277 || (!strcmp(word, "untrap with")
1278 && ((otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE)
1279 || (otmp->oclass == POTION_CLASS
1280 /* only applicable potion is oil, and it will only
1281 be offered as a choice when already discovered */
1282 && (otyp != POT_OIL || !otmp->dknown
1283 || !objects[POT_OIL].oc_name_known))))
1284 || (!strcmp(word, "tip") && !Is_container(otmp)
1285 /* include horn of plenty if sufficiently discovered */
1286 && (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown
1287 || !objects[HORN_OF_PLENTY].oc_name_known))
1288 || (!strcmp(word, "charge") && !is_chargeable(otmp))
1289 || (!strcmp(word, "open") && otyp != TIN)
1290 || (!strcmp(word, "call") && !objtyp_is_callable(otyp))
1291 || (!strcmp(word, "adjust") && otmp->oclass == COIN_CLASS
1296 /* Third ugly check: acceptable but not listed as likely
1297 * candidates in the prompt or in the inventory subset if
1298 * player responds with '?'.
1301 /* ugly check for unworn armor that can't be worn */
1302 (putting_on(word) && *let == ARMOR_CLASS
1303 && !canwearobj(otmp, &dummymask, FALSE))
1304 /* or armor with 'P' or 'R' or accessory with 'W' or 'T' */
1305 || ((putting_on(word) || taking_off(word))
1306 && ((*let == ARMOR_CLASS) ^ (otmp->oclass == ARMOR_CLASS)))
1307 /* or unsuitable items rubbed on known touchstone */
1308 || (!strncmp(word, "rub on the stone", 16)
1309 && *let == GEM_CLASS && otmp->dknown
1310 && objects[otyp].oc_name_known)
1311 /* suppress corpses on astral, amulets elsewhere */
1312 || (!strcmp(word, "sacrifice")
1313 /* (!astral && amulet) || (astral && !amulet) */
1314 && (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
1315 /* suppress container being stashed into */
1316 || (!strcmp(word, "stash") && !ck_bag(otmp))
1317 /* worn armor (shirt, suit) covered by worn armor (suit, cloak)
1318 or accessory (ring) covered by cursed worn armor (gloves) */
1319 || (taking_off(word)
1320 && inaccessible_equipment(otmp, (const char *) 0,
1321 (boolean) (otmp->oclass == RING_CLASS)))
1322 || (!strcmp(word, "write on")
1323 && (!(otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER)
1324 || !otmp->dknown || !objects[otyp].oc_name_known))
1326 /* acceptable but not listed as likely candidate */
1329 *ap++ = otmp->invlet;
1332 /* clang-format on */
1334 /* "ugly check" for reading fortune cookies, part 2 */
1335 if ((!strcmp(word, "read") && is_readable(otmp)))
1336 allowall = usegold = TRUE;
1341 if (foo == 0 && bp > buf && bp[-1] == ' ')
1343 Strcpy(lets, bp); /* necessary since we destroy buf */
1344 if (foo > 5) /* compactify string */
1348 if (!foo && !allowall && !allownone) {
1350 You("don't have anything %sto %s.", foox ? "else " : "", word);
1352 You("%s%s
\82à
\82Ì
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", foox ? "
\91¼
\82É" : "", jconj(jword, "
\82ê
\82é"));
1353 return (struct obj *) 0;
1354 } else if (!strcmp(word, "write on")) { /* ugly check for magic marker */
1355 /* we wanted all scrolls and books in altlets[], but that came with
1356 'allowall' which we don't want since it prevents "silly thing"
1357 result if anything other than scroll or spellbook is chosen */
1364 Sprintf(qbuf, "What do you want to %s?", word);
1366 Sprintf(qbuf, "%s%s%s
\82©
\81H", what, joshi, jpolite(jword));
1369 else if (iflags.force_invmenu) {
1370 /* don't overwrite a possible quitchars */
1372 ilet = *let ? '?' : '*';
1374 putmsghistory(qbuf, FALSE);
1379 Strcat(qbuf, " [*]");
1381 Sprintf(eos(qbuf), " [%s or ?*]", buf);
1382 ilet = yn_function(qbuf, (char *) 0, '\0');
1389 pline("No count allowed with this command.");
1391 pline("
\82±
\82Ì
\83R
\83}
\83\93\83h
\82É
\90\94\8e\9a\82Í
\82Â
\82©
\82¦
\82È
\82¢
\81D");
1394 ilet = get_count(NULL, ilet, LARGEST_INT, &tmpcnt, TRUE);
1400 if (index(quitchars, ilet)) {
1403 return (struct obj *) 0;
1405 if (ilet == HANDS_SYM) { /* '-' */
1407 char *suf = (char *) 0;
1410 if ((bp = strstr(buf, " on the ")) != 0) {
1411 /* rub on the stone[s] */
1415 if ((bp = strstr(buf, " or ")) != 0) {
1417 bp = (rn2(2) ? buf : (bp + 4));
1421 You("mime %s something%s%s.", ing_suffix(bp), suf ? " " : "",
1424 You("
\89½
\82©
\82ð%s
\82Ó
\82è
\82ð
\82µ
\82½
\81D", bp);
1427 return (allownone ? &zeroobj : (struct obj *) 0);
1430 /* since gold is now kept in inventory, we need to do processing for
1431 select-from-invent before checking whether gold has been picked */
1432 if (ilet == '?' || ilet == '*') {
1433 char *allowed_choices = (ilet == '?') ? lets : (char *) 0;
1435 char menuquery[QBUFSZ];
1437 menuquery[0] = qbuf[0] = '\0';
1438 if (iflags.force_invmenu)
1439 Sprintf(menuquery, "What do you want to %s?", word);
1440 if (!strcmp(word, "grease"))
1441 Sprintf(qbuf, "your %s", makeplural(body_part(FINGER)));
1442 else if (!strcmp(word, "write with"))
1443 Sprintf(qbuf, "your %s", body_part(FINGERTIP));
1444 else if (!strcmp(word, "wield"))
1445 Sprintf(qbuf, "your %s %s%s", uarmg ? "gloved" : "bare",
1446 makeplural(body_part(HAND)),
1447 !uwep ? " (wielded)" : "");
1448 else if (!strcmp(word, "ready"))
1449 Sprintf(qbuf, "empty quiver%s",
1450 !uquiver ? " (nothing readied)" : "");
1452 if (ilet == '?' && !*lets && *altlets)
1453 allowed_choices = altlets;
1454 ilet = display_pickinv(allowed_choices, *qbuf ? qbuf : (char *) 0,
1456 TRUE, allowcnt ? &ctmp : (long *) 0);
1459 if (ilet == HANDS_SYM)
1461 if (ilet == '\033') {
1464 return (struct obj *) 0;
1468 if (allowcnt && ctmp >= 0) {
1472 /* they typed a letter (not a space) at the prompt */
1474 /* find the item which was picked */
1475 for (otmp = invent; otmp; otmp = otmp->nobj)
1476 if (otmp->invlet == ilet)
1478 /* some items have restrictions */
1479 if (ilet == def_oc_syms[COIN_CLASS].sym
1480 /* guard against the [hypothetical] chace of having more
1481 than one invent slot of gold and picking the non-'$' one */
1482 || (otmp && otmp->oclass == COIN_CLASS)) {
1485 You("cannot %s gold.", word);
1487 You("
\8bà
\89Ý%s%s
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D", joshi, jword);
1488 return (struct obj *) 0;
1490 /* Historic note: early Nethack had a bug which was
1491 * first reported for Larn, where trying to drop 2^32-n
1492 * gold pieces was allowed, and did interesting things
1493 * to your money supply. The LRS is the tax bureau
1496 if (cntgiven && cnt <= 0) {
1500 "LRS would be very interested to know you have that much.");
1502 "
\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");
1503 return (struct obj *) 0;
1506 if (cntgiven && !strcmp(word, "throw")) {
1507 /* permit counts for throwing gold, but don't accept
1508 * counts for other things since the throw code will
1509 * split off a single item anyway */
1511 return (struct obj *) 0;
1512 if (cnt > 1 && (ilet != def_oc_syms[COIN_CLASS].sym
1513 && !(otmp && otmp->oclass == COIN_CLASS))) {
1515 You("can only throw one item at a time.");
1517 You("
\93¯
\8e\9e\82É
\82½
\82
\82³
\82ñ
\82Ì
\82à
\82Ì
\82ð
\93\8a\82°
\82ç
\82ê
\82È
\82¢
\81D");
1521 context.botl = 1; /* May have changed the amount of money */
1523 /* [we used to set otmp (by finding ilet in invent) here, but
1524 that's been moved above so that otmp can be checked earlier] */
1525 /* verify the chosen object */
1528 You("don't have that object.");
1530 You("
\82»
\82ñ
\82È
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
1532 return (struct obj *) 0;
1534 } else if (cnt < 0 || otmp->quan < cnt) {
1536 You("don't have that many! You have only %ld.", otmp->quan);
1538 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);
1540 return (struct obj *) 0;
1545 if (!allowall && let && !index(let, otmp->oclass)
1546 && !(usegold && otmp->oclass == COIN_CLASS)) {
1548 silly_thing(word, otmp);
1550 silly_thing(jword, otmp);
1552 return (struct obj *) 0;
1556 return (struct obj *) 0;
1557 if (cnt != otmp->quan) {
1558 /* don't split a stack of cursed loadstones */
1559 if (splittable(otmp))
1560 otmp = splitobj(otmp, cnt);
1561 else if (otmp->otyp == LOADSTONE && otmp->cursed)
1562 /* kludge for canletgo()'s can't-drop-this message */
1563 otmp->corpsenm = (int) cnt;
1570 silly_thing(word, otmp)
1574 #if 1 /* 'P','R' vs 'W','T' handling is obsolete */
1577 const char *s1, *s2, *s3;
1578 int ocls = otmp->oclass, otyp = otmp->otyp;
1581 /* check for attempted use of accessory commands ('P','R') on armor
1582 and for corresponding armor commands ('W','T') on accessories */
1583 if (ocls == ARMOR_CLASS) {
1585 if (!strcmp(word, "put on"))
1586 s1 = "W", s2 = "wear", s3 = "";
1587 else if (!strcmp(word, "remove"))
1588 s1 = "T", s2 = "take", s3 = " off";
1590 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1591 s1 = "W", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1592 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1593 s1 = "T", s2 = "
\82Í
\82¸
\82·", s3 = "";
1595 } else if ((ocls == RING_CLASS || otyp == MEAT_RING)
1596 || ocls == AMULET_CLASS
1597 || (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
1599 if (!strcmp(word, "wear"))
1600 s1 = "P", s2 = "put", s3 = " on";
1601 else if (!strcmp(word, "take off"))
1602 s1 = "R", s2 = "remove", s3 = "";
1604 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1605 s1 = "P", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1606 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1607 s1 = "R", s2 = "
\82Í
\82¸
\82·", s3 = "";
1612 pline("Use the '%s' command to %s %s%s.", s1, s2,
1613 !(is_plural(otmp) || pair_of(otmp)) ? "that" : "those", s3);
1615 pline("
\82»
\82ê
\82ð%s
\82É
\82Í'%s'
\83R
\83}
\83\93\83h
\82ð
\8eg
\82¤
\82±
\82Æ
\81D", s2, s1);
1619 pline(silly_thing_to, word);
1626 /* use allow_category() from pickup.c */
1627 return (int) allow_category(otmp);
1634 return (otmp->unpaid || (Has_contents(otmp) && count_unpaid(otmp->cobj)));
1640 return (boolean) (uarm || uarmc || uarmf || uarmg
1641 || uarmh || uarms || uarmu);
1648 return (otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_SADDLE | W_WEAPON))
1653 /* extra xprname() input that askchain() can't pass through safe_qbuf() */
1654 STATIC_VAR struct xprnctx {
1659 /* safe_qbuf() -> short_oname() callback */
1664 return xprname(obj, (char *) 0, safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
1668 /* alternate safe_qbuf() -> short_oname() callback */
1670 safeq_shortxprname(obj)
1673 return xprname(obj, ansimpleoname(obj), safeq_xprn_ctx.let,
1674 safeq_xprn_ctx.dot, 0L, 0L);
1677 static NEARDATA const char removeables[] = { ARMOR_CLASS, WEAPON_CLASS,
1678 RING_CLASS, AMULET_CLASS,
1681 /* Interactive version of getobj - used for Drop, Identify, and Takeoff (A).
1682 Return the number of times fn was called successfully.
1683 If combo is TRUE, we just use this to get a category list. */
1684 /*JP CHECK: 3.6.0
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
1685 do.c:962: || (result = ggetobj("drop", drop, 0, FALSE, (unsigned *) 0)) < -1)
1686 do.c:1009: i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
1687 do_wear.c:2955: || (result = ggetobj("take off", select_off, 0, FALSE,
1688 do_wear.c:3007: if (ggetobj("take off", select_off, 0, TRUE, (unsigned *) 0) == -2)
1689 invent.c:2014: n = ggetobj("identify", identify, id_limit, FALSE,
1692 ggetobj(word, fn, mx, combo, resultflags)
1694 int FDECL((*fn), (OBJ_P)), mx;
1695 boolean combo; /* combination menu flag */
1696 unsigned *resultflags;
1698 int FDECL((*ckfn), (OBJ_P)) = (int FDECL((*), (OBJ_P))) 0;
1699 boolean FDECL((*ofilter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
1700 boolean takeoff, ident, allflag, m_seen;
1702 int oletct, iletct, unpaid, oc_of_sym;
1703 char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 10];
1704 char extra_removeables[3 + 1]; /* uwep,uswapwep,uquiver */
1705 char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
1707 const char *joshi = "
\82ð";
1710 const struct trans_verb *tv = trans_verb(word);
1712 joshi = tv->particle;
1717 You("have nothing to %s.", word);
1719 You("%s
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", jcan(jword));
1721 *resultflags = ALL_FINISHED;
1726 takeoff = ident = allflag = m_seen = FALSE;
1727 add_valid_menu_class(0); /* reset */
1728 if (taking_off(word)) {
1731 } else if (!strcmp(word, "identify")) {
1733 ofilter = not_fully_identified;
1736 iletct = collect_obj_classes(ilets, invent, FALSE, ofilter, &itemcount);
1737 unpaid = count_unpaid(invent);
1739 if (ident && !iletct) {
1740 return -1; /* no further identifications */
1741 } else if (invent) {
1742 ilets[iletct++] = ' ';
1744 ilets[iletct++] = 'u';
1745 if (count_buc(invent, BUC_BLESSED, ofilter))
1746 ilets[iletct++] = 'B';
1747 if (count_buc(invent, BUC_UNCURSED, ofilter))
1748 ilets[iletct++] = 'U';
1749 if (count_buc(invent, BUC_CURSED, ofilter))
1750 ilets[iletct++] = 'C';
1751 if (count_buc(invent, BUC_UNKNOWN, ofilter))
1752 ilets[iletct++] = 'X';
1753 ilets[iletct++] = 'a';
1755 ilets[iletct++] = 'i';
1757 ilets[iletct++] = 'm'; /* allow menu presentation on request */
1758 ilets[iletct] = '\0';
1762 Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]",
1765 Sprintf(qbuf,"
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\82à
\82Ì%s%s
\82©
\81H[%s]", joshi,
1766 jpolite(jword), ilets);
1769 if (buf[0] == '\033')
1771 if (index(buf, 'i')) {
1772 char ailets[1+26+26+1+5+1]; /* $ + a-z + A-Z + # + slop + \0 */
1775 /* applicable inventory letters; if empty, show entire invent */
1778 for (otmp = invent; otmp; otmp = otmp->nobj)
1779 /* index() check: limit overflow items to one '#' */
1780 if ((*ofilter)(otmp) && !index(ailets, otmp->invlet))
1781 (void) strkitten(ailets, otmp->invlet);
1782 if (display_inventory(ailets, TRUE) == '\033')
1788 extra_removeables[0] = '\0';
1790 /* arbitrary types of items can be placed in the weapon slots
1791 [any duplicate entries in extra_removeables[] won't matter] */
1793 (void) strkitten(extra_removeables, uwep->oclass);
1795 (void) strkitten(extra_removeables, uswapwep->oclass);
1797 (void) strkitten(extra_removeables, uquiver->oclass);
1801 olets[oletct = 0] = '\0';
1802 while ((sym = *ip++) != '\0') {
1805 oc_of_sym = def_char_to_objclass(sym);
1806 if (takeoff && oc_of_sym != MAXOCLASSES) {
1807 if (index(extra_removeables, oc_of_sym)) {
1808 ; /* skip rest of takeoff checks */
1809 } else if (!index(removeables, oc_of_sym)) {
1811 pline("Not applicable.");
1813 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
1815 } else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
1818 } else if (oc_of_sym == WEAPON_CLASS && !uwep && !uswapwep
1821 You("are not wielding anything.");
1823 You("
\89½
\82à
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
1825 } else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
1827 You("are not wearing rings.");
1829 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
1831 } else if (oc_of_sym == AMULET_CLASS && !uamul) {
1833 You("are not wearing an amulet.");
1835 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
1837 } else if (oc_of_sym == TOOL_CLASS && !ublindf) {
1839 You("are not wearing a blindfold.");
1841 You("
\96Ú
\89B
\82µ
\82ð
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
1846 if (oc_of_sym == COIN_CLASS && !combo) {
1848 } else if (sym == 'a') {
1850 } else if (sym == 'A') {
1851 ; /* same as the default */
1852 } else if (sym == 'u') {
1853 add_valid_menu_class('u');
1855 } else if (index("BUCX", sym)) {
1856 add_valid_menu_class(sym); /* 'B','U','C',or 'X' */
1858 } else if (sym == 'm') {
1860 } else if (oc_of_sym == MAXOCLASSES) {
1862 You("don't have any %c's.", sym);
1864 You("%c
\82É
\91®
\82·
\82é
\95¨
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", sym);
1865 } else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */
1866 if (!index(olets, oc_of_sym)) {
1867 add_valid_menu_class(oc_of_sym);
1868 olets[oletct++] = oc_of_sym;
1876 || (!oletct && ckfn != ckunpaid && ckfn != ckvalidcat))
1878 } else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) {
1881 /* !!!! test gold dropping */
1882 } else if (allowgold == 2 && !oletct) {
1883 return 1; /* you dropped gold (or at least tried to) */
1886 int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
1888 * askchain() has already finished the job in this case
1889 * so set a special flag to convey that back to the caller
1890 * so that it won't continue processing.
1891 * Fix for bug C331-1 reported by Irina Rempt-Drijfhout.
1893 if (combo && allflag && resultflags)
1894 *resultflags |= ALL_FINISHED;
1900 * Walk through the chain starting at objchn and ask for all objects
1901 * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
1902 * whether the action in question (i.e., fn) has to be performed.
1903 * If allflag then no questions are asked. Mx gives the max number
1904 * of objects to be treated. Return the number of objects treated.
1906 /*JP CHECK: 3.6.0
\82Å
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
1907 invent.c:1728: int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
1908 pickup.c:2882: if (askchain(objlist, (one_by_one ? (char *) 0 : selection), allflag,
1909 word
\82É
\82Í
\93®
\8e\8c\82ª
\89p
\8cê
\82Å
\93ü
\82é
\81B
1912 askchain(objchn, olets, allflag, fn, ckfn, mx, word)
1913 struct obj **objchn;
1915 const char *olets, *word; /* olets is an Obj Class char array */
1916 int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
1918 struct obj *otmp, *otmpo;
1919 register char sym, ilet;
1920 register int cnt = 0, dud = 0, tmp;
1921 boolean takeoff, nodot, ident, take_out, put_in, first, ininv, bycat;
1922 char qbuf[QBUFSZ], qpfx[QBUFSZ];
1924 takeoff = taking_off(word);
1925 ident = !strcmp(word, "identify");
1926 take_out = !strcmp(word, "take out");
1927 put_in = !strcmp(word, "put in");
1928 nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
1929 || takeoff || take_out || put_in);
1930 ininv = (*objchn == invent);
1931 bycat = (menu_class_present('u')
1932 || menu_class_present('B') || menu_class_present('U')
1933 || menu_class_present('C') || menu_class_present('X'));
1935 /* someday maybe we'll sort by 'olets' too (temporarily replace
1936 flags.packorder and pass SORTLOOT_PACK), but not yet... */
1937 sortloot(objchn, SORTLOOT_INVLET, FALSE);
1941 * Interrogate in the object class order specified.
1942 * For example, if a person specifies =/ then first all rings
1943 * will be asked about followed by all wands. -dgk
1947 if (*objchn && (*objchn)->oclass == COIN_CLASS)
1948 ilet--; /* extra iteration */
1950 * Multiple Drop can change the invent chain while it operates
1951 * (dropping a burning potion of oil while levitating creates
1952 * an explosion which can destroy inventory items), so simple
1954 * for (otmp = *objchn; otmp; otmp = otmp2) {
1955 * otmp2 = otmp->nobj;
1958 * is inadequate here. Use each object's bypass bit to keep
1959 * track of which list elements have already been processed.
1961 bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */
1962 while ((otmp = nxt_unbypassed_obj(*objchn)) != 0) {
1965 else if (ilet == 'Z')
1966 ilet = NOINVSYM; /* '#' */
1969 if (olets && *olets && otmp->oclass != *olets)
1971 if (takeoff && !is_worn(otmp))
1973 if (ident && !not_fully_identified(otmp))
1975 if (ckfn && !(*ckfn)(otmp))
1977 if (bycat && !ckvalidcat(otmp))
1980 safeq_xprn_ctx.let = ilet;
1981 safeq_xprn_ctx.dot = !nodot;
1984 /* traditional_loot() skips prompting when only one
1985 class of objects is involved, so prefix the first
1986 object being queried here with an explanation why */
1987 if (take_out || put_in)
1988 Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
1992 (void) safe_qbuf(qbuf, qpfx, "?", otmp,
1993 ininv ? safeq_xprname : doname,
1994 ininv ? safeq_shortxprname : ansimpleoname,
1997 (void) safe_qbuf(qbuf, qpfx, "
\81H", otmp,
1998 ininv ? safeq_xprname : doname,
1999 ininv ? safeq_shortxprname : ansimpleoname,
2000 "
\83A
\83C
\83e
\83\80");
2002 sym = (takeoff || ident || otmp->quan < 2L) ? nyaq(qbuf)
2009 /* Number was entered; split the object unless it corresponds
2010 to 'none' or 'all'. 2 special cases: cursed loadstones and
2011 welded weapons (eg, multiple daggers) will remain as merged
2012 unit; done to avoid splitting an object that won't be
2013 droppable (even if we're picking up rather than dropping). */
2018 if (yn_number < otmp->quan && splittable(otmp))
2019 otmp = splitobj(otmp, yn_number);
2029 if (container_gone(fn)) {
2030 /* otmp caused magic bag to explode;
2031 both are now gone */
2032 otmp = 0; /* and return */
2033 } else if (otmp && otmp != otmpo) {
2034 /* split occurred, merge again */
2035 (void) merged(&otmpo, &otmp);
2049 /* special case for seffects() */
2055 if (olets && *olets && *++olets)
2057 if (!takeoff && (dud || cnt))
2059 pline("That was all.");
2061 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
2062 else if (!dud && !cnt)
2064 pline("No applicable objects.");
2066 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2068 bypass_objlist(*objchn, FALSE);
2073 * Object identification routines:
2076 /* make an object actually be identified; no display updating */
2078 fully_identify_obj(otmp)
2081 makeknown(otmp->otyp);
2082 if (otmp->oartifact)
2083 discover_artifact((xchar) otmp->oartifact);
2084 otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
2085 if (Is_container(otmp) || otmp->otyp == STATUE)
2086 otmp->cknown = otmp->lknown = 1;
2087 if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
2088 learn_egg_type(otmp->corpsenm);
2091 /* ggetobj callback routine; identify an object and give immediate feedback */
2096 fully_identify_obj(otmp);
2097 prinv((char *) 0, otmp, 0L);
2101 /* menu of unidentified objects; select and identify up to id_limit of them */
2103 menu_identify(id_limit)
2106 menu_item *pick_list;
2107 int n, i, first = 1, tryct = 5;
2109 /* assumptions: id_limit > 0 and at least one unID'd item is present */
2113 Sprintf(buf, "What would you like to identify %s?",
2114 first ? "first" : "next");
2116 Sprintf(buf, "
\82Ç
\82ê
\82ð%s
\82É
\8e¯
\95Ê
\82µ
\82Ü
\82·
\82©
\81H",
2117 first ? "
\8dÅ
\8f\89" : "
\8e\9f");
2119 n = query_objlist(buf, &invent, (SIGNAL_NOMENU | SIGNAL_ESCAPE
2120 | USE_INVLET | INVORDER_SORT),
2121 &pick_list, PICK_ANY, not_fully_identified);
2126 for (i = 0; i < n; i++, id_limit--)
2127 (void) identify(pick_list[i].item.a_obj);
2128 free((genericptr_t) pick_list);
2129 mark_synch(); /* Before we loop to pop open another menu */
2131 } else if (n == -2) { /* player used ESC to quit menu */
2133 } else if (n == -1) { /* no eligible items found */
2135 pline("That was all.");
2137 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
2139 } else if (!--tryct) { /* stop re-prompting */
2140 pline1(thats_enough_tries);
2142 } else { /* try again */
2144 pline("Choose an item; use ESC to decline.");
2146 pline("
\83A
\83C
\83e
\83\80\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢;
\82â
\82ß
\82é
\82È
\82çESC
\81D");
2151 /* dialog with user to identify a given number of items; 0 means all */
2153 identify_pack(id_limit, learning_id)
2155 boolean learning_id; /* true if we just read unknown identify scroll */
2157 struct obj *obj, *the_obj;
2161 the_obj = 0; /* if unid_cnt ends up 1, this will be it */
2162 for (obj = invent; obj; obj = obj->nobj)
2163 if (not_fully_identified(obj))
2164 ++unid_cnt, the_obj = obj;
2168 You("have already identified all %sof your possessions.",
2169 learning_id ? "the rest " : "");
2171 You("%s
\91S
\82Ä
\82Ì
\8f\8a\97L
\95¨
\82ð
\8e¯
\95Ê
\82µ
\82Ä
\82µ
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D",
2172 learning_id ? "
\8ec
\82è" : "");
2174 } else if (!id_limit || id_limit >= unid_cnt) {
2175 /* identify everything */
2176 if (unid_cnt == 1) {
2177 (void) identify(the_obj);
2179 /* TODO: use fully_identify_obj and cornline/menu/whatever here
2181 for (obj = invent; obj; obj = obj->nobj)
2182 if (not_fully_identified(obj))
2183 (void) identify(obj);
2186 /* identify up to `id_limit' items */
2188 if (flags.menu_style == MENU_TRADITIONAL)
2190 n = ggetobj("identify", identify, id_limit, FALSE,
2193 break; /* quit or no eligible items */
2194 } while ((id_limit -= n) > 0);
2195 if (n == 0 || n < -1)
2196 menu_identify(id_limit);
2201 /* called when regaining sight; mark inventory objects which were picked
2202 up while blind as now having been seen */
2204 learn_unseen_invent()
2209 return; /* sanity check */
2211 for (otmp = invent; otmp; otmp = otmp->nobj) {
2213 continue; /* already seen */
2214 /* set dknown, perhaps bknown (for priest[ess]) */
2217 * If object->eknown gets implemented (see learnwand(zap.c)),
2218 * handle deferred discovery here.
2224 /* should of course only be called for things in invent */
2229 if (!flags.invlet_constant) {
2230 obj->invlet = NOINVSYM;
2237 * Print the indicated quantity of the given object. If quan == 0L then use
2238 * the current quantity.
2241 prinv(prefix, obj, quan)
2249 pline("%s%s%s", prefix, *prefix ? " " : "",
2250 xprname(obj, (char *) 0, obj_to_let(obj), TRUE, 0L, quan));
2253 xprname(obj, (char *)0, obj_to_let(obj), *prefix ? FALSE : TRUE, 0L, quan),
2259 xprname(obj, txt, let, dot, cost, quan)
2261 const char *txt; /* text to print instead of obj */
2262 char let; /* inventory letter */
2263 boolean dot; /* append period; (dot && cost => Iu) */
2264 long cost; /* cost (for inventory of unpaid or expended items) */
2265 long quan; /* if non-0, print this quantity, not obj->quan */
2267 #ifdef LINT /* handle static char li[BUFSZ]; */
2270 static char li[BUFSZ];
2272 boolean use_invlet = (flags.invlet_constant
2273 && let != CONTAINED_SYM && let != HANDS_SYM);
2277 savequan = obj->quan;
2282 * - Then obj == null and 'txt' refers to hands or fingers.
2283 * * Then obj == null and we are printing a total amount.
2284 * > Then the object is contained and doesn't have an inventory letter.
2286 if (cost != 0 || let == '*') {
2287 /* if dot is true, we're doing Iu, otherwise Ix */
2290 iflags.menu_tab_sep ? "%c - %s\t%6ld %s"
2291 : "%c - %-45s %6ld %s",
2293 iflags.menu_tab_sep ? "%c - %s\t%6ld%s"
2294 : "%c - %-45s %6ld%s",
2296 (dot && use_invlet ? obj->invlet : let),
2297 (txt ? txt : doname(obj)), cost, currency(cost));
2299 /* ordinary inventory display or pickup message */
2300 Sprintf(li, "%c - %s%s", (use_invlet ? obj->invlet : let),
2302 (txt ? txt : doname(obj)), (dot ? "." : ""));
2304 (txt ? txt : doname(obj)), (dot ? "
\81D" : ""));
2307 obj->quan = savequan;
2312 /* the 'i' command */
2316 (void) display_inventory((char *) 0, FALSE);
2323 * Scan the given list of objects. If last_found is NULL, return the first
2324 * unpaid object found. If last_found is not NULL, then skip over unpaid
2325 * objects until last_found is reached, then set last_found to NULL so the
2326 * next unpaid object is returned. This routine recursively follows
2329 STATIC_OVL struct obj *
2330 find_unpaid(list, last_found)
2331 struct obj *list, **last_found;
2338 /* still looking for previous unpaid object */
2339 if (list == *last_found)
2340 *last_found = (struct obj *) 0;
2342 return ((*last_found = list));
2344 if (Has_contents(list)) {
2345 if ((obj = find_unpaid(list->cobj, last_found)) != 0)
2350 return (struct obj *) 0;
2353 /* for perm_invent when operating on a partial inventory display, so that
2354 the persistent one doesn't get shrunk during filtering for item selection
2355 then regrown to full inventory, possibly being resized in the process */
2356 static winid cached_pickinv_win = WIN_ERR;
2359 free_pickinv_cache()
2361 if (cached_pickinv_win != WIN_ERR) {
2362 destroy_nhwindow(cached_pickinv_win);
2363 cached_pickinv_win = WIN_ERR;
2368 * Internal function used by display_inventory and getobj that can display
2369 * inventory and return a count as well as a letter. If out_cnt is not null,
2370 * any count returned from the menu selection is placed here.
2373 display_pickinv(lets, xtra_choice, query, want_reply, out_cnt)
2374 register const char *lets;
2375 const char *xtra_choice; /* "fingers", pick hands rather than an object */
2381 static const char not_carrying_anything[] = "Not carrying anything";
2383 static const char not_carrying_anything[] = "
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢";
2386 char *invlet = flags.inv_order;
2388 winid win; /* windows being used */
2390 menu_item *selected;
2393 lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
2395 if (flags.perm_invent && (lets || xtra_choice)) {
2396 /* partial inventory in perm_invent setting; don't operate on
2397 full inventory window, use an alternate one instead; create
2398 the first time needed and keep it for re-use as needed later */
2399 if (cached_pickinv_win == WIN_ERR)
2400 cached_pickinv_win = create_nhwindow(NHW_MENU);
2401 win = cached_pickinv_win;
2406 * Exit early if no inventory -- but keep going if we are doing
2407 * a permanent inventory update. We need to keep going so the
2408 * permanent inventory window updates itself to remove the last
2409 * item(s) dropped. One down side: the addition of the exception
2410 * for permanent inventory window updates _can_ pop the window
2411 * up when it's not displayed -- even if it's empty -- because we
2412 * don't know at this level if its up or not. This may not be
2413 * an issue if empty checks are done before hand and the call
2414 * to here is short circuited away.
2416 * 2: our count here is only to distinguish between 0 and 1 and
2417 * more than 1; for the last one, we don't need a precise number.
2418 * For perm_invent update we force 'more than 1'.
2420 n = (flags.perm_invent && !lets && !want_reply) ? 2
2421 : lets ? (int) strlen(lets)
2422 : !invent ? 0 : !invent->nobj ? 1 : 2;
2423 /* for xtra_choice, there's another 'item' not included in initial 'n';
2424 for !lets (full invent) and for override_ID (wizard mode identify),
2425 skip message_menu handling of single item even if item count was 1 */
2426 if (xtra_choice || (n == 1 && (!lets || iflags.override_ID)))
2431 pline("%s.", not_carrying_anything);
2433 pline("%s
\81D", not_carrying_anything);
2437 /* oxymoron? temporarily assign permanent inventory letters */
2438 if (!flags.invlet_constant)
2441 if (n == 1 && !iflags.force_invmenu) {
2442 /* when only one item of interest, use pline instead of menus;
2443 we actually use a fake message-line menu in order to allow
2444 the user to perform selection at the --More-- prompt for tty */
2447 /* xtra_choice is "bare hands" (wield), "fingertip" (Engrave),
2448 "nothing" (ready Quiver), or "fingers" (apply grease) */
2449 ret = message_menu(HANDS_SYM, PICK_ONE,
2450 xprname((struct obj *) 0, xtra_choice,
2451 HANDS_SYM, TRUE, 0L, 0L)); /* '-' */
2453 for (otmp = invent; otmp; otmp = otmp->nobj)
2454 if (!lets || otmp->invlet == lets[0])
2457 ret = message_menu(otmp->invlet,
2458 want_reply ? PICK_ONE : PICK_NONE,
2459 xprname(otmp, (char *) 0, lets[0],
2463 *out_cnt = -1L; /* select all */
2468 (((flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET)
2469 | (flags.sortpack ? SORTLOOT_PACK : 0)),
2474 if (wizard && iflags.override_ID) {
2475 char prompt[QBUFSZ];
2478 /* wiz_identify stuffed the wiz_identify command character (^I)
2479 into iflags.override_ID for our use as an accelerator */
2480 Sprintf(prompt, "Debug Identify (%s to permanently identify)",
2481 visctrl(iflags.override_ID));
2482 add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
2483 prompt, MENU_UNSELECTED);
2484 } else if (xtra_choice) {
2485 /* wizard override ID and xtra_choice are mutually exclusive */
2487 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2488 "Miscellaneous", MENU_UNSELECTED);
2489 any.a_char = HANDS_SYM; /* '-' */
2490 add_menu(win, NO_GLYPH, &any, HANDS_SYM, 0, ATR_NONE,
2491 xtra_choice, MENU_UNSELECTED);
2495 for (otmp = invent; otmp; otmp = otmp->nobj) {
2496 if (lets && !index(lets, otmp->invlet))
2498 if (!flags.sortpack || otmp->oclass == *invlet) {
2499 any = zeroany; /* all bits zero */
2500 ilet = otmp->invlet;
2501 if (flags.sortpack && !classcount) {
2502 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2503 let_to_name(*invlet, FALSE,
2504 (want_reply && iflags.menu_head_objsym)),
2509 add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE,
2510 doname(otmp), MENU_UNSELECTED);
2513 if (flags.sortpack) {
2516 if (--invlet != venom_inv) {
2521 if (iflags.force_invmenu && lets && want_reply) {
2523 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2524 "Special", MENU_UNSELECTED);
2526 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
2527 "(list everything)", MENU_UNSELECTED);
2529 /* for permanent inventory where we intend to show everything but
2530 nothing has been listed (because there isn't anyhing to list;
2531 recognized via any.a_char still being zero; the n==0 case above
2532 gets skipped for perm_invent), put something into the menu */
2533 if (flags.perm_invent && !lets && !any.a_char) {
2535 add_menu(win, NO_GLYPH, &any, 0, 0, 0,
2536 not_carrying_anything, MENU_UNSELECTED);
2539 end_menu(win, query && *query ? query : (char *) 0);
2541 n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
2543 ret = selected[0].item.a_char;
2545 *out_cnt = selected[0].count;
2546 free((genericptr_t) selected);
2548 ret = !n ? '\0' : '\033'; /* cancelled */
2554 * If lets == NULL or "", list all objects in the inventory. Otherwise,
2555 * list all objects with object classes that match the order in lets.
2557 * Returns the letter identifier of a selected item, or 0 if nothing
2561 display_inventory(lets, want_reply)
2565 return display_pickinv(lets, (char *) 0, (char *) 0,
2566 want_reply, (long *) 0);
2570 * Show what is current using inventory letters.
2574 display_used_invlets(avoidlet)
2579 char *invlet = flags.inv_order;
2580 int n, classcount, invdone = 0;
2583 menu_item *selected;
2586 win = create_nhwindow(NHW_MENU);
2589 any = zeroany; /* set all bits to zero */
2591 for (otmp = invent; otmp; otmp = otmp->nobj) {
2592 ilet = otmp->invlet;
2593 if (ilet == avoidlet)
2595 if (!flags.sortpack || otmp->oclass == *invlet) {
2596 if (flags.sortpack && !classcount) {
2597 any = zeroany; /* zero */
2598 add_menu(win, NO_GLYPH, &any, 0, 0,
2599 iflags.menu_headings,
2600 let_to_name(*invlet, FALSE, FALSE),
2605 add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE,
2606 doname(otmp), MENU_UNSELECTED);
2609 if (flags.sortpack && *++invlet)
2613 end_menu(win, "Inventory letters used:");
2615 n = select_menu(win, PICK_ONE, &selected);
2617 ret = selected[0].item.a_char;
2618 free((genericptr_t) selected);
2620 ret = !n ? '\0' : '\033'; /* cancelled */
2621 destroy_nhwindow(win);
2627 * Returns the number of unpaid items within the given list. This includes
2628 * contained objects.
2639 if (Has_contents(list))
2640 count += count_unpaid(list->cobj);
2647 * Returns the number of items with b/u/c/unknown within the given list.
2648 * This does NOT include contained objects.
2650 * Assumes that the hero sees or touches or otherwise senses the objects
2651 * at some point: bknown is forced for priest[ess], like in xname().
2654 count_buc(list, type, filterfunc)
2657 boolean FDECL((*filterfunc), (OBJ_P));
2661 for (; list; list = list->nobj) {
2662 /* priests always know bless/curse state */
2663 if (Role_if(PM_PRIEST))
2664 list->bknown = (list->oclass != COIN_CLASS);
2665 /* some actions exclude some or most items */
2666 if (filterfunc && !(*filterfunc)(list))
2669 /* coins are either uncursed or unknown based upon option setting */
2670 if (list->oclass == COIN_CLASS) {
2671 if (type == (iflags.goldX ? BUC_UNKNOWN : BUC_UNCURSED))
2675 /* check whether this object matches the requested type */
2677 ? (type == BUC_UNKNOWN)
2678 : list->blessed ? (type == BUC_BLESSED)
2679 : list->cursed ? (type == BUC_CURSED)
2680 : (type == BUC_UNCURSED))
2686 /* similar to count_buc(), but tallies all states at once
2687 rather than looking for a specific type */
2689 tally_BUCX(list, by_nexthere, bcp, ucp, ccp, xcp, ocp)
2691 boolean by_nexthere;
2692 int *bcp, *ucp, *ccp, *xcp, *ocp;
2694 /* Future extensions:
2695 * Skip current_container when list is invent, uchain when
2696 * first object of list is located on the floor. 'ocp' will then
2697 * have a function again (it was a counter for having skipped gold,
2698 * but that's not skipped anymore).
2700 *bcp = *ucp = *ccp = *xcp = *ocp = 0;
2701 for ( ; list; list = (by_nexthere ? list->nexthere : list->nobj)) {
2702 /* priests always know bless/curse state */
2703 if (Role_if(PM_PRIEST))
2704 list->bknown = (list->oclass != COIN_CLASS);
2705 /* coins are either uncursed or unknown based upon option setting */
2706 if (list->oclass == COIN_CLASS) {
2713 /* ordinary items */
2716 else if (list->blessed)
2718 else if (list->cursed)
2720 else /* neither blessed nor cursed => uncursed */
2726 count_contents(container, nested, quantity, everything)
2727 struct obj *container;
2728 boolean nested, /* include contents of any nested containers */
2729 quantity, /* count all vs count separate stacks */
2730 everything; /* all objects vs only unpaid objects */
2735 for (otmp = container->cobj; otmp; otmp = otmp->nobj) {
2736 if (nested && Has_contents(otmp))
2737 count += count_contents(otmp, nested, quantity, everything);
2738 if (everything || otmp->unpaid)
2739 count += quantity ? otmp->quan : 1L;
2748 struct obj *otmp, *marker, *contnr;
2750 char *invlet = flags.inv_order;
2751 int classcount, count, num_so_far;
2754 count = count_unpaid(invent);
2755 otmp = marker = contnr = (struct obj *) 0;
2758 otmp = find_unpaid(invent, &marker);
2759 contnr = unknwn_contnr_contents(otmp);
2761 if (otmp && !contnr) {
2762 /* 1 item; use pline instead of popup menu */
2763 cost = unpaid_cost(otmp, FALSE);
2764 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
2765 pline1(xprname(otmp, distant_name(otmp, doname),
2766 carried(otmp) ? otmp->invlet : CONTAINED_SYM,
2768 iflags.suppress_price--;
2772 win = create_nhwindow(NHW_MENU);
2774 num_so_far = 0; /* count of # printed so far */
2775 if (!flags.invlet_constant)
2780 for (otmp = invent; otmp; otmp = otmp->nobj) {
2781 ilet = otmp->invlet;
2783 if (!flags.sortpack || otmp->oclass == *invlet) {
2784 if (flags.sortpack && !classcount) {
2785 putstr(win, 0, let_to_name(*invlet, TRUE, FALSE));
2789 totcost += cost = unpaid_cost(otmp, FALSE);
2790 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
2791 putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
2792 ilet, TRUE, cost, 0L));
2793 iflags.suppress_price--;
2798 } while (flags.sortpack && (*++invlet));
2800 if (count > num_so_far) {
2801 /* something unpaid is contained */
2803 putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE, FALSE));
2805 * Search through the container objects in the inventory for
2806 * unpaid items. The top level inventory items have already
2809 for (otmp = invent; otmp; otmp = otmp->nobj) {
2810 if (Has_contents(otmp)) {
2813 marker = (struct obj *) 0; /* haven't found any */
2814 while (find_unpaid(otmp->cobj, &marker)) {
2815 totcost += cost = unpaid_cost(marker, FALSE);
2818 iflags.suppress_price++; /* suppress "(unpaid)" sfx */
2820 xprname(marker, distant_name(marker, doname),
2821 CONTAINED_SYM, TRUE, cost, 0L));
2822 iflags.suppress_price--;
2825 if (!otmp->cknown) {
2826 char contbuf[BUFSZ];
2828 /* Shopkeeper knows what to charge for contents */
2829 Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
2831 xprname((struct obj *) 0, contbuf, CONTAINED_SYM,
2832 TRUE, contcost, 0L));
2841 xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
2844 xprname((struct obj *) 0, "
\8d\87\8cv
\81F", '*', FALSE, totcost, 0L));
2846 display_nhwindow(win, FALSE);
2847 destroy_nhwindow(win);
2850 /* query objlist callback: return TRUE if obj type matches "this_type" */
2851 static int this_type;
2857 boolean res = (obj->oclass == this_type);
2859 if (obj->oclass == COIN_CLASS) {
2860 /* if filtering by bless/curse state, gold is classified as
2861 either unknown or uncursed based on user option setting */
2862 if (this_type && index("BUCX", this_type))
2863 res = (this_type == (iflags.goldX ? 'X' : 'U'));
2865 switch (this_type) {
2867 res = (obj->bknown && obj->blessed);
2870 res = (obj->bknown && !(obj->blessed || obj->cursed));
2873 res = (obj->bknown && obj->cursed);
2879 break; /* use 'res' as-is */
2885 /* the 'I' command */
2891 char *extra_types, types[BUFSZ];
2892 int class_count, oclass, unpaid_count, itemcount;
2893 int bcnt, ccnt, ucnt, xcnt, ocnt;
2894 boolean billx = *u.ushops && doinvbill(0);
2895 menu_item *pick_list;
2896 boolean traditional = TRUE;
2898 const char *prompt = "What type of object do you want an inventory of?";
2900 const char *prompt = "
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\8e\9d\82¿
\95¨
\82ð
\8c©
\82Ü
\82·
\82©
\81H";
2902 if (!invent && !billx) {
2904 You("aren't carrying anything.");
2906 You("
\82»
\82Ì
\8eí
\97Þ
\82Ì
\95¨
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
2909 unpaid_count = count_unpaid(invent);
2910 tally_BUCX(invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
2912 if (flags.menu_style != MENU_TRADITIONAL) {
2913 if (flags.menu_style == MENU_FULL
2914 || flags.menu_style == MENU_PARTIAL) {
2915 traditional = FALSE;
2927 n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
2930 this_type = c = pick_list[0].item.a_int;
2931 free((genericptr_t) pick_list);
2935 /* collect a list of classes of objects carried, for use as a prompt
2938 class_count = collect_obj_classes(types, invent, FALSE,
2939 (boolean FDECL((*), (OBJ_P))) 0,
2941 if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
2942 types[class_count++] = ' ';
2944 types[class_count++] = 'u';
2946 types[class_count++] = 'x';
2948 types[class_count++] = 'B';
2950 types[class_count++] = 'U';
2952 types[class_count++] = 'C';
2954 types[class_count++] = 'X';
2955 types[class_count] = '\0';
2956 /* add everything not already included; user won't see these */
2957 extra_types = eos(types);
2958 *extra_types++ = '\033';
2960 *extra_types++ = 'u';
2962 *extra_types++ = 'x';
2964 *extra_types++ = 'B';
2966 *extra_types++ = 'U';
2968 *extra_types++ = 'C';
2970 *extra_types++ = 'X';
2971 *extra_types = '\0'; /* for index() */
2972 for (i = 0; i < MAXOCLASSES; i++)
2973 if (!index(types, def_oc_syms[i].sym)) {
2974 *extra_types++ = def_oc_syms[i].sym;
2975 *extra_types = '\0';
2978 if (class_count > 1) {
2979 c = yn_function(prompt, types, '\0');
2982 clear_nhwindow(WIN_MESSAGE);
2986 /* only one thing to itemize */
2995 if (c == 'x' || (c == 'X' && billx && !xcnt)) {
2997 (void) doinvbill(1);
3000 pline("No used-up objects%s.",
3001 unpaid_count ? " on your shopping bill" : "");
3003 pline("
\8eg
\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\95¨
\82Í%s
\82È
\82¢
\81D",
3004 unpaid_count ? "
\8f¤
\93X
\82Ì
\90¿
\8b\81\8f\91\82É
\82Í" : "");
3008 if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
3013 You("are not carrying any unpaid objects.");
3015 You("
\96¢
\95¥
\82¢
\82Ì
\83A
\83C
\83e
\83\80\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3019 if (index("BUCX", c))
3020 oclass = c; /* not a class but understood by this_type_only() */
3022 oclass = def_char_to_objclass(c); /* change to object class */
3024 if (oclass == COIN_CLASS)
3026 if (index(types, c) > index(types, '\033')) {
3027 /* '> ESC' => hidden choice, something known not to be carried */
3028 const char *before = "", *after = "";
3033 before = "known to be blessed ";
3035 before = "
\8fj
\95\9f\82³
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3039 before = "known to be uncursed ";
3041 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3045 before = "known to be cursed ";
3047 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3051 after = " whose blessed/uncursed/cursed status is unknown";
3053 after = "
\8fj
\95\9f\81^
\8eô
\82¢
\82ª
\82í
\82©
\82ç
\82È
\82¢";
3054 break; /* better phrasing is desirable */
3056 /* 'c' is an object class, because we've already handled
3057 all the non-class letters which were put into 'types[]';
3058 could/should move object class names[] array from below
3059 to somewhere above so that we can access it here (via
3060 lcase(strcpy(classnamebuf, names[(int) c]))), but the
3061 game-play value of doing so is low... */
3065 before = "
\82»
\82Ì
\82æ
\82¤
\82È";
3069 You("have no %sobjects%s.", before, after);
3071 You("%s%s
\82à
\82Ì
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", before, after);
3076 if (query_objlist((char *) 0, &invent,
3077 ((flags.invlet_constant ? USE_INVLET : 0)
3079 &pick_list, PICK_NONE, this_type_only) > 0)
3080 free((genericptr_t) pick_list);
3084 /* return a string describing the dungeon feature at <x,y> if there
3085 is one worth mentioning at that location; otherwise null */
3087 dfeature_at(x, y, buf)
3091 struct rm *lev = &levl[x][y];
3092 int ltyp = lev->typ, cmap = -1;
3093 const char *dfeature = 0;
3094 static char altbuf[BUFSZ];
3096 if (IS_DOOR(ltyp)) {
3097 switch (lev->doormask) {
3100 break; /* "doorway" */
3103 break; /* "open door" */
3106 dfeature = "broken door";
3108 dfeature = "
\89ó
\82ê
\82½
\94à";
3112 break; /* "closed door" */
3114 /* override door description for open drawbridge */
3115 if (is_drawbridge_wall(x, y) >= 0)
3117 dfeature = "open drawbridge portcullis", cmap = -1;
3119 dfeature = "
\8d~
\82è
\82Ä
\82¢
\82é
\92µ
\82Ë
\8b´", cmap = -1;
3120 } else if (IS_FOUNTAIN(ltyp))
3121 cmap = S_fountain; /* "fountain" */
3122 else if (IS_THRONE(ltyp))
3123 cmap = S_throne; /* "opulent throne" */
3124 else if (is_lava(x, y))
3125 cmap = S_lava; /* "molten lava" */
3126 else if (is_ice(x, y))
3127 cmap = S_ice; /* "ice" */
3128 else if (is_pool(x, y))
3130 dfeature = "pool of water";
3132 dfeature = "
\90\85\82½
\82Ü
\82è";
3133 else if (IS_SINK(ltyp))
3134 cmap = S_sink; /* "sink" */
3135 else if (IS_ALTAR(ltyp)) {
3137 Sprintf(altbuf, "%saltar to %s (%s)",
3138 ((lev->altarmask & AM_SHRINE)
3139 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3143 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3145 Sprintf(altbuf, "%s%s
\82Ì
\8dÕ
\92d(%s)",
3146 ((lev->altarmask & AM_SHRINE)
3147 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3151 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3154 } else if ((x == xupstair && y == yupstair)
3155 || (x == sstairs.sx && y == sstairs.sy && sstairs.up))
3156 cmap = S_upstair; /* "staircase up" */
3157 else if ((x == xdnstair && y == ydnstair)
3158 || (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
3159 cmap = S_dnstair; /* "staircase down" */
3160 else if (x == xupladder && y == yupladder)
3161 cmap = S_upladder; /* "ladder up" */
3162 else if (x == xdnladder && y == ydnladder)
3163 cmap = S_dnladder; /* "ladder down" */
3164 else if (ltyp == DRAWBRIDGE_DOWN)
3165 cmap = S_vodbridge; /* "lowered drawbridge" */
3166 else if (ltyp == DBWALL)
3167 cmap = S_vcdbridge; /* "raised drawbridge" */
3168 else if (IS_GRAVE(ltyp))
3169 cmap = S_grave; /* "grave" */
3170 else if (ltyp == TREE)
3171 cmap = S_tree; /* "tree" */
3172 else if (ltyp == IRONBARS)
3174 dfeature = "set of iron bars";
3176 dfeature = "
\93S
\82Ì
\96_";
3179 dfeature = defsyms[cmap].explanation;
3181 Strcpy(buf, dfeature);
3185 /* look at what is here; if there are many objects (pile_limit or more),
3186 don't show them unless obj_cnt is 0 */
3188 look_here(obj_cnt, picked_some)
3189 int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progress */
3190 boolean picked_some;
3195 const char *verb = Blind ? "feel" : "see";
3197 const char *verb = Blind ? "
\82ª
\82 \82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½" : "
\82ð
\82Ý
\82Â
\82¯
\82½";
3199 const char *dfeature = (char *) 0;
3200 char fbuf[BUFSZ], fbuf2[BUFSZ];
3202 boolean skip_objects, felt_cockatrice = FALSE;
3204 /* default pile_limit is 5; a value of 0 means "never skip"
3205 (and 1 effectively forces "always skip") */
3206 skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
3207 if (u.uswallow && u.ustuck) {
3208 struct monst *mtmp = u.ustuck;
3211 Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
3212 mbodypart(mtmp, STOMACH));
3214 Sprintf(fbuf, "%s
\82Ì%s
\82Ì
\92\86\90g", mon_nam(mtmp),
3215 mbodypart(mtmp, STOMACH));
3217 #if 0 /*JP*//*
\8cê
\8f\87\82ª
\88á
\82¤
\82Ì
\82Å
\91f
\92¼
\82É*/
3218 /* Skip "Contents of " by using fbuf index 12 */
3219 You("%s to %s what is lying in %s.", Blind ? "try" : "look around",
3222 You("%s
\82Ì%s
\82É
\89½
\82ª
\82 \82é
\82©%s
\81D",
3223 mon_nam(mtmp), mbodypart(mtmp, STOMACH),
3224 Blind ? "
\82³
\82®
\82Á
\82½" : "
\8c©
\89ñ
\82µ
\82½");
3226 otmp = mtmp->minvent;
3228 for (; otmp; otmp = otmp->nobj) {
3229 /* If swallower is an animal, it should have become stone
3231 if (otmp->otyp == CORPSE)
3232 feel_cockatrice(otmp, FALSE);
3236 Strcpy(fbuf, "You feel");
3239 Sprintf(fbuf, "
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F", Blind ? "
\82ç
\82µ
\82¢" : "");
3241 (void) display_minventory(mtmp, MINV_ALL | PICK_NONE, fbuf);
3244 You("%s no objects here.", verb);
3246 pline(Blind ? "
\82 \82È
\82½
\82Í
\89½
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D"
3247 : "
\82 \82È
\82½
\82Í
\89½
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3252 if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen)
3254 There("is %s here.",
3256 pline("
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D",
3257 an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
3259 otmp = level.objects[u.ux][u.uy];
3260 dfeature = dfeature_at(u.ux, u.uy, fbuf2);
3262 if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
3264 if (dfeature && !strcmp(dfeature, "
\90\85\82½
\82Ü
\82è") && Underwater)
3268 boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
3271 if (dfeature && !strncmp(dfeature, "altar ", 6)) {
3273 if (dfeature && !strncmp(dfeature, "
\8dÕ
\92d", 4)) {
3274 /* don't say "altar" twice, dfeature has more info */
3276 You("try to feel what is here.");
3278 You("
\82±
\82±
\82É
\89½
\82ª
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3281 const char *where = (Blind && !can_reach_floor(TRUE))
3282 ? "lying beneath you"
3283 : "lying here on the ",
3284 *onwhat = (Blind && !can_reach_floor(TRUE))
3286 : surface(u.ux, u.uy);
3288 You("try to feel what is %s%s.", drift ? "floating here" : where,
3289 drift ? "" : onwhat);
3292 You("
\89½
\82ª
\95\82\82¢
\82Ä
\82¢
\82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3293 } else if (Blind && !can_reach_floor(TRUE)) {
3294 You("
\89½
\82ª
\91«
\89º
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3296 You("
\89½
\82ª%s
\82Ì
\8fã
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D", surface(u.ux, u.uy));
3300 if (dfeature && !drift && !strcmp(dfeature, surface(u.ux, u.uy)))
3301 dfeature = 0; /* ice already identified */
3302 if (!can_reach_floor(TRUE)) {
3304 pline("But you can't reach it!");
3306 pline("
\82µ
\82©
\82µ
\93Í
\82©
\82È
\82¢
\81I");
3313 Sprintf(fbuf, "There is %s here.", an(dfeature));
3315 Sprintf(fbuf, "
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D", an(dfeature));
3317 if (!otmp || is_lava(u.ux, u.uy)
3318 || (is_pool(u.ux, u.uy) && !Underwater)) {
3321 read_engr_at(u.ux, u.uy); /* Eric Backus */
3322 if (!skip_objects && (Blind || !dfeature))
3324 You("%s no objects here.", verb);
3327 "
\82È
\82É
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82·
\82é
\81D" :
3328 "
\82È
\82É
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3332 /* we know there is something here */
3337 read_engr_at(u.ux, u.uy); /* Eric Backus */
3338 if (obj_cnt == 1 && otmp->quan == 1L)
3340 There("is %s object here.", picked_some ? "another" : "an");
3342 There("
\82±
\82±
\82É
\82Í%s
\88ê
\82Â
\82à
\82Ì
\82ª
\82 \82é
\81D", picked_some ? "
\82à
\82¤" : "");
3345 There("are %s%s objects here.",
3351 picked_some ? " more" : "");
3353 pline("
\82±
\82±
\82É
\82Í%s%s
\82à
\82Ì
\82ª
\82 \82é
\81D",
3354 picked_some ? "
\82³
\82ç
\82É" : "",
3356 ? "
\82¢
\82
\82Â
\82©
\82Ì"
3357 : "
\82½
\82
\82³
\82ñ
\82Ì");
3359 for (; otmp; otmp = otmp->nexthere)
3360 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3361 #if 0 /*JP*//*"It's (corpse_name), unfortunately"*/
3368 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3369 poly_when_stoned(youmonst.data)
3371 : ", unfortunately");
3374 poly_when_stoned(youmonst.data)
3376 : "
\8ec
\94O
\82È
\82ª
\82ç",
3377 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3379 ? "
\82ð
\8aÜ
\82ñ
\82Å
\82¢
\82é"
3382 feel_cockatrice(otmp, FALSE);
3385 } else if (!otmp->nexthere) {
3386 /* only one object */
3389 read_engr_at(u.ux, u.uy); /* Eric Backus */
3391 You("%s here %s.", verb, doname_with_price(otmp));
3393 pline("%s%s
\81D", doname_with_price(otmp), verb);
3394 iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
3395 if (otmp->otyp == CORPSE)
3396 feel_cockatrice(otmp, FALSE);
3400 display_nhwindow(WIN_MESSAGE, FALSE);
3401 tmpwin = create_nhwindow(NHW_MENU);
3403 putstr(tmpwin, 0, fbuf);
3404 putstr(tmpwin, 0, "");
3407 Sprintf(buf, "%s that %s here:",
3408 picked_some ? "Other things" : "Things",
3409 Blind ? "you feel" : "are");
3411 Sprintf(buf, "%s
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F",
3412 picked_some ? "
\91¼
\82É" : "",
3413 Blind ? "
\82ç
\82µ
\82¢" : "");
3415 putstr(tmpwin, 0, buf);
3416 for (; otmp; otmp = otmp->nexthere) {
3417 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3418 felt_cockatrice = TRUE;
3420 Sprintf(buf, "%s...", doname(otmp));
3422 Sprintf(buf, "%s
\81D
\81D
\81D", doname(otmp));
3423 putstr(tmpwin, 0, buf);
3426 putstr(tmpwin, 0, doname_with_price(otmp));
3428 display_nhwindow(tmpwin, TRUE);
3429 destroy_nhwindow(tmpwin);
3430 if (felt_cockatrice)
3431 feel_cockatrice(otmp, FALSE);
3432 read_engr_at(u.ux, u.uy); /* Eric Backus */
3437 /* the ':' command - explicitly look at what is here, including all objects */
3444 MSGTYPE={norep,noshow} "You see here"
3445 interfere with feedback from the look-here command */
3446 hide_unhide_msgtypes(TRUE, MSGTYP_MASK_REP_SHOW);
3447 res = look_here(0, FALSE);
3448 /* restore normal msgtype handling */
3449 hide_unhide_msgtypes(FALSE, MSGTYP_MASK_REP_SHOW);
3454 will_feel_cockatrice(otmp, force_touch)
3456 boolean force_touch;
3458 if ((Blind || force_touch) && !uarmg && !Stone_resistance
3459 && (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
3465 feel_cockatrice(otmp, force_touch)
3467 boolean force_touch;
3471 if (will_feel_cockatrice(otmp, force_touch)) {
3472 /* "the <cockatrice> corpse" */
3473 Strcpy(kbuf, corpse_xname(otmp, (const char *) 0, CXN_PFX_THE));
3475 if (poly_when_stoned(youmonst.data))
3477 You("touched %s with your bare %s.", kbuf,
3478 makeplural(body_part(HAND)));
3480 You("%s
\82Ì
\8e\80\91Ì
\82É
\91f%s
\82Å
\90G
\82Á
\82½
\81D", kbuf,
3485 pline("Touching %s is a fatal mistake...", kbuf);
3487 pline("%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82é
\82Ì
\82Í
\92v
\96½
\93I
\82È
\8aÔ
\88á
\82¢
\82¾
\81D
\81D
\81D", kbuf);
3488 /* normalize body shape here; hand, not body_part(HAND) */
3490 Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
3492 Sprintf(kbuf, "%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82Ä", killer_xname(otmp));
3493 /* will call polymon() for the poly_when_stoned() case */
3504 for (otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
3505 if (otmp != obj && merged(&obj, &otmp))
3510 /* returns TRUE if obj & otmp can be merged; used in invent.c and mkobj.c */
3513 register struct obj *otmp, *obj;
3515 int objnamelth = 0, otmpnamelth = 0;
3518 return FALSE; /* already the same object */
3519 if (obj->otyp != otmp->otyp)
3520 return FALSE; /* different types */
3521 if (obj->nomerge) /* explicitly marked to prevent merge */
3524 /* coins of the same kind will always merge */
3525 if (obj->oclass == COIN_CLASS)
3528 if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
3529 || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed
3530 || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
3531 || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
3532 || obj->bypass != otmp->bypass)
3537 /* Checks beyond this point either aren't applicable to globs
3538 * or don't inhibit their merger.
3541 if (obj->oclass == FOOD_CLASS
3542 && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
3545 if (obj->dknown != otmp->dknown
3546 || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
3547 || obj->oeroded != otmp->oeroded || obj->oeroded2 != otmp->oeroded2
3548 || obj->greased != otmp->greased)
3551 if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
3552 && (obj->oerodeproof != otmp->oerodeproof
3553 || obj->rknown != otmp->rknown))
3556 if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
3557 if (obj->corpsenm != otmp->corpsenm)
3561 /* hatching eggs don't merge; ditto for revivable corpses */
3562 if ((obj->otyp == EGG && (obj->timed || otmp->timed))
3563 || (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM
3564 && is_reviver(&mons[otmp->corpsenm])))
3567 /* allow candle merging only if their ages are close */
3568 /* see begin_burn() for a reference for the magic "25" */
3569 if (Is_candle(obj) && obj->age / 25 != otmp->age / 25)
3572 /* burning potions of oil never merge */
3573 if (obj->otyp == POT_OIL && obj->lamplit)
3576 /* don't merge surcharged item with base-cost item */
3577 if (obj->unpaid && !same_price(obj, otmp))
3580 /* if they have names, make sure they're the same */
3581 objnamelth = strlen(safe_oname(obj));
3582 otmpnamelth = strlen(safe_oname(otmp));
3583 if ((objnamelth != otmpnamelth
3584 && ((objnamelth && otmpnamelth) || obj->otyp == CORPSE))
3585 || (objnamelth && otmpnamelth
3586 && strncmp(ONAME(obj), ONAME(otmp), objnamelth)))
3589 /* for the moment, any additional information is incompatible */
3590 if (has_omonst(obj) || has_omid(obj) || has_olong(obj) || has_omonst(otmp)
3591 || has_omid(otmp) || has_olong(otmp))
3594 if (obj->oartifact != otmp->oartifact)
3597 if (obj->known == otmp->known || !objects[otmp->otyp].oc_uses_known) {
3598 return (boolean) objects[obj->otyp].oc_merge;
3603 /* the '$' command */
3607 /* the messages used to refer to "carrying gold", but that didn't
3608 take containers into account */
3609 long umoney = money_cnt(invent);
3612 Your("wallet is empty.");
3614 Your("
\8dà
\95z
\82Í
\8bó
\82Á
\82Û
\82¾
\81D");
3617 Your("wallet contains %ld %s.", umoney, currency(umoney));
3619 Your("
\8dà
\95z
\82É
\82Í%ld%s
\93ü
\82Á
\82Ä
\82¢
\82é
\81D", umoney, currency(umoney));
3620 shopper_financial_report();
3624 /* the ')' command */
3630 You("are empty %s.", body_part(HANDED));
3632 if(!uwep) You("%s
\82É
\95\90\8aí
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D", body_part(HAND));
3634 prinv((char *) 0, uwep, 0L);
3636 prinv((char *) 0, uswapwep, 0L);
3641 /* caller is responsible for checking !wearing_armor() */
3643 noarmor(report_uskin)
3644 boolean report_uskin;
3646 if (!uskin || !report_uskin) {
3648 You("are not wearing any armor.");
3650 You("
\8aZ
\82ð
\92\85\82Ä
\82¢
\82È
\82¢
\81D");
3652 char *p, *uskinname, buf[BUFSZ];
3654 uskinname = strcpy(buf, simpleonames(uskin));
3656 /* shorten "set of <color> dragon scales" to "<color> scales"
3657 and "<color> dragon scale mail" to "<color> scale mail" */
3658 if (!strncmpi(uskinname, "set of ", 7))
3660 if ((p = strstri(uskinname, " dragon ")) != 0)
3661 while ((p[1] = p[8]) != '\0')
3663 #else /*
\81u<
\90F>
\83h
\83\89\83S
\83\93\82Ì
\97Ø
\81v
\82ð
\81u<
\90F>
\82Ì
\97Ø
\81v
\82É
\82·
\82é*/
3664 if ((p = strstri(uskinname, "
\83h
\83\89\83S
\83\93\82Ì
\97Ø")) != 0)
3669 You("are not wearing armor but have %s embedded in your skin.",
3671 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",
3676 /* the '[' command */
3681 register int ct = 0;
3683 * Note: players sometimes get here by pressing a function key which
3684 * transmits ''ESC [ <something>'' rather than by pressing '[';
3685 * there's nothing we can--or should-do about that here.
3688 if (!wearing_armor()) {
3692 lets[ct++] = obj_to_let(uarmu);
3694 lets[ct++] = obj_to_let(uarm);
3696 lets[ct++] = obj_to_let(uarmc);
3698 lets[ct++] = obj_to_let(uarmh);
3700 lets[ct++] = obj_to_let(uarms);
3702 lets[ct++] = obj_to_let(uarmg);
3704 lets[ct++] = obj_to_let(uarmf);
3706 (void) display_inventory(lets, FALSE);
3711 /* the '=' command */
3715 if (!uleft && !uright)
3717 You("are not wearing any rings.");
3719 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
3722 register int ct = 0;
3725 lets[ct++] = obj_to_let(uleft);
3727 lets[ct++] = obj_to_let(uright);
3729 (void) display_inventory(lets, FALSE);
3734 /* the '"' command */
3740 You("are not wearing an amulet.");
3742 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
3744 prinv((char *) 0, uamul, 0L);
3752 if ((obj->owornmask & (W_TOOL | W_SADDLE)) != 0L)
3754 if (obj->oclass != TOOL_CLASS)
3756 return (boolean) (obj == uwep || obj->lamplit
3757 || (obj->otyp == LEASH && obj->leashmon));
3760 /* the '(' command */
3768 for (otmp = invent; otmp; otmp = otmp->nobj)
3769 if (tool_in_use(otmp))
3770 lets[ct++] = obj_to_let(otmp);
3774 You("are not using any tools.");
3776 You("
\8eg
\82¦
\82é
\93¹
\8bï
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3778 (void) display_inventory(lets, FALSE);
3782 /* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
3783 show inventory of all currently wielded, worn, or used objects */
3791 for (otmp = invent; otmp; otmp = otmp->nobj)
3792 if (is_worn(otmp) || tool_in_use(otmp))
3793 lets[ct++] = obj_to_let(otmp);
3797 You("are not wearing or wielding anything.");
3799 You("
\89½
\82à
\92\85\82Ä
\82¢
\82È
\82¢
\82µ
\81C
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
3801 (void) display_inventory(lets, FALSE);
3806 * uses up an object that's on the floor, charging for it as necessary
3809 useupf(obj, numused)
3810 register struct obj *obj;
3813 register struct obj *otmp;
3814 boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
3816 /* burn_floor_objects() keeps an object pointer that it tries to
3817 * useupf() multiple times, so obj must survive if plural */
3818 if (obj->quan > numused)
3819 otmp = splitobj(obj, numused);
3822 if (costly_spot(otmp->ox, otmp->oy)) {
3823 if (index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
3824 addtobill(otmp, FALSE, FALSE, FALSE);
3826 (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
3829 if (at_u && u.uundetected && hides_under(youmonst.data))
3830 (void) hideunder(&youmonst);
3834 * Conversion from a class to a string for printing.
3835 * This must match the object class order.
3837 STATIC_VAR NEARDATA const char *names[] = {
3839 0, "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", "Tools",
3840 "Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
3841 "Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
3843 0, "
\96
\82È
\95¨
\91Ì", "
\95\90\8aí", "
\8aZ", "
\8ew
\97Ö", "
\96\82\8f\9c\82¯", "
\93¹
\8bï",
3844 "
\90H
\97¿", "
\96ò", "
\8aª
\95¨", "
\96\82\96@
\8f\91", "
\8fñ", "
\8bà
\89Ý",
3845 "
\95ó
\90Î", "
\8aâ
\82Ü
\82½
\82Í
\92¤
\91\9c", "
\93S
\8b\85", "
\8d½", "
\93Å"
3848 STATIC_VAR NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
3850 STATIC_VAR NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
3852 STATIC_VAR NEARDATA const char *oth_names[] = { "
\8bl
\82ß
\82ç
\82ê
\82½
\93¹
\8bï" };
3854 STATIC_VAR NEARDATA char *invbuf = (char *) 0;
3855 STATIC_VAR NEARDATA unsigned invbufsiz = 0;
3858 let_to_name(let, unpaid, showsym)
3860 boolean unpaid, showsym;
3862 const char *ocsymfmt = " ('%c')";
3863 const int invbuf_sympadding = 8; /* arbitrary */
3864 const char *class_name;
3866 int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
3870 class_name = names[oclass];
3871 else if ((pos = index(oth_symbols, let)) != 0)
3872 class_name = oth_names[pos - oth_symbols];
3874 class_name = names[0];
3877 len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "")
3879 len = strlen(class_name) + (unpaid ? sizeof "
\96¢
\95¥
\82¢
\82Ì" : sizeof "")
3880 + (oclass ? (strlen(ocsymfmt) + invbuf_sympadding) : 0);
3881 if (len > invbufsiz) {
3883 free((genericptr_t) invbuf);
3884 invbufsiz = len + 10; /* add slop to reduce incremental realloc */
3885 invbuf = (char *) alloc(invbufsiz);
3889 Strcat(strcpy(invbuf, "Unpaid "), class_name);
3891 Strcat(strcpy(invbuf, "
\96¢
\95¥
\82¢
\82Ì"), class_name);
3893 Strcpy(invbuf, class_name);
3894 if ((oclass != 0) && showsym) {
3895 char *bp = eos(invbuf);
3896 int mlen = invbuf_sympadding - strlen(class_name);
3897 while (--mlen > 0) {
3902 Sprintf(eos(invbuf), ocsymfmt, def_oc_syms[oclass].sym);
3907 /* release the static buffer used by let_to_name() */
3912 free((genericptr_t) invbuf), invbuf = (char *) 0;
3916 /* give consecutive letters to every item in inventory (for !fixinv mode);
3917 gold is always forced to '$' slot at head of list */
3922 struct obj *obj, *prevobj, *goldobj;
3924 /* first, remove [first instance of] gold from invent, if present */
3925 prevobj = goldobj = 0;
3926 for (obj = invent; obj; prevobj = obj, obj = obj->nobj)
3927 if (obj->oclass == COIN_CLASS) {
3930 prevobj->nobj = goldobj->nobj;
3932 invent = goldobj->nobj;
3935 /* second, re-letter the rest of the list */
3936 for (obj = invent, i = 0; obj; obj = obj->nobj, i++)
3938 (i < 26) ? ('a' + i) : (i < 52) ? ('A' + i - 26) : NOINVSYM;
3939 /* third, assign gold the "letter" '$' and re-insert it at head */
3941 goldobj->invlet = GOLD_SYM;
3942 goldobj->nobj = invent;
3952 * User specifies a 'from' slot for inventory stack to move,
3953 * then a 'to' slot for its destination. Open slots and those
3954 * filled by compatible stacks are listed as likely candidates
3955 * but user can pick any inventory letter (including 'from').
3957 * to == from, 'from' has a name
3958 * All compatible items (same name or no name) are gathered
3959 * into the 'from' stack. No count is allowed.
3960 * to == from, 'from' does not have a name
3961 * All compatible items without a name are gathered into the
3962 * 'from' stack. No count is allowed. Compatible stacks with
3963 * names are left as-is.
3964 * to != from, no count
3965 * Move 'from' to 'to'. If 'to' is not empty, merge 'from'
3966 * into it if possible, otherwise swap it with the 'from' slot.
3967 * to != from, count given
3968 * If the user specifies a count when choosing the 'from' slot,
3969 * and that count is less than the full size of the stack,
3970 * then the stack will be split. The 'count' portion is moved
3971 * to the destination, and the only candidate for merging with
3972 * it is the stack already at the 'to' slot, if any. When the
3973 * destination is non-empty but won't merge, whatever is there
3974 * will be moved to an open slot; if there isn't any open slot
3975 * available, the adjustment attempt fails.
3977 * To minimize merging for 'from == to', unnamed stacks will
3978 * merge with named 'from' but named ones won't merge with
3979 * unnamed 'from'. Otherwise attempting to collect all unnamed
3980 * stacks would lump the first compatible named stack with them
3981 * and give them its name.
3983 * To maximize merging for 'from != to', compatible stacks will
3984 * merge when either lacks a name (or they already have the same
3985 * name). When no count is given and one stack has a name and
3986 * the other doesn't, the merged result will have that name.
3987 * However, when splitting results in a merger, the name of the
3988 * destination overrides that of the source, even if destination
3989 * is unnamed and source is named.
3992 doorganize() /* inventory organizer by Del Lamb */
3994 struct obj *obj, *otmp, *splitting, *bumped;
3995 int ix, cur, trycnt, goldstacks;
3998 #define GOLD_OFFSET 1
3999 #define OVRFLW_INDX (GOLD_OFFSET + 52) /* past gold and 2*26 letters */
4000 char lets[1 + 52 + 1 + 1]; /* room for '$a-zA-Z#\0' */
4002 char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
4003 char *objname, *otmpname;
4004 const char *adj_type;
4005 boolean ever_mind = FALSE, collect;
4009 You("aren't carrying anything to adjust.");
4011 You("
\8f\87\8f\98\82ð
\95Ï
\82¦
\82é
\82à
\82Ì
\82ð
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4015 if (!flags.invlet_constant)
4017 /* get object the user wants to organize (the 'from' slot) */
4018 allowall[0] = ALLOW_COUNT;
4019 allowall[1] = ALL_CLASSES;
4021 for (goldstacks = 0, otmp = invent; otmp; otmp = otmp->nobj) {
4022 /* gold should never end up in a letter slot, nor should two '$'
4023 slots occur, but if they ever do, allow #adjust to handle them
4024 (in the past, things like this have happened, usually due to
4025 bknown being erroneously set on one stack, clear on another;
4026 object merger isn't fooled by that anymore) */
4027 if (otmp->oclass == COIN_CLASS
4028 && (otmp->invlet != GOLD_SYM || ++goldstacks > 1)) {
4029 allowall[1] = COIN_CLASS;
4030 allowall[2] = ALL_CLASSES;
4035 if (!(obj = getobj(allowall, "adjust")))
4038 /* figure out whether user gave a split count to getobj() */
4039 splitting = bumped = 0;
4040 for (otmp = invent; otmp; otmp = otmp->nobj)
4041 if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
4042 if (otmp->invlet == obj->invlet)
4047 /* initialize the list with all lower and upper case letters */
4048 lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' ';
4049 for (ix = GOLD_OFFSET, let = 'a'; let <= 'z';)
4051 for (let = 'A'; let <= 'Z';)
4053 lets[OVRFLW_INDX] = ' ';
4054 lets[sizeof lets - 1] = '\0';
4055 /* for floating inv letters, truncate list after the first open slot */
4056 if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
4057 lets[ix + (splitting ? 0 : 1)] = '\0';
4059 /* blank out all the letters currently in use in the inventory
4060 except those that will be merged with the selected object */
4061 for (otmp = invent; otmp; otmp = otmp->nobj)
4062 if (otmp != obj && !mergable(otmp, obj)) {
4064 if (let >= 'a' && let <= 'z')
4065 lets[GOLD_OFFSET + let - 'a'] = ' ';
4066 else if (let >= 'A' && let <= 'Z')
4067 lets[GOLD_OFFSET + let - 'A' + 26] = ' ';
4068 /* overflow defaults to off, but it we find a stack using that
4069 slot, switch to on -- the opposite of normal invlet handling */
4070 else if (let == NOINVSYM)
4071 lets[OVRFLW_INDX] = NOINVSYM;
4074 /* compact the list by removing all the blanks */
4075 for (ix = cur = 0; lets[ix]; ix++)
4076 if (lets[ix] != ' ' && cur++ < ix)
4077 lets[cur - 1] = lets[ix];
4079 /* and by dashing runs of letters */
4083 /* get 'to' slot to use as destination */
4085 Sprintf(qbuf, "Adjust letter to what [%s]%s?", lets,
4086 invent ? " (? see used letters)" : "");
4088 Sprintf(qbuf, "
\82Ç
\82Ì
\95¶
\8e\9a\82É
\92²
\90®
\82µ
\82Ü
\82·
\82©[%s]%s
\81H", lets,
4089 invent ? " (?
\82Å
\8eg
\82Á
\82Ä
\82¢
\82é
\95¶
\8e\9a\82ð
\95\
\8e¦)" : "");
4091 for (trycnt = 1; ; ++trycnt) {
4092 let = yn_function(qbuf, (char *) 0, '\0');
4093 if (let == '?' || let == '*') {
4094 let = display_used_invlets(splitting ? obj->invlet : 0);
4100 if (index(quitchars, let)
4101 /* adjusting to same slot is meaningful since all
4102 compatible stacks get collected along the way,
4103 but splitting to same slot is not */
4104 || (splitting && let == obj->invlet)) {
4107 (void) merged(&splitting, &obj);
4111 } else if (let == GOLD_SYM && obj->oclass != COIN_CLASS) {
4112 pline("Only gold coins may be moved into the '%c' slot.",
4117 /* letter() classifies '@' as one; compactify() can put '-' in lets;
4118 the only thing of interest that index() might find is '$' or '#'
4119 since letter() catches everything else that we put into lets[] */
4120 if ((letter(let) && let != '@') || (index(lets, let) && let != '-'))
4121 break; /* got one */
4125 pline("Select an inventory slot letter."); /* else try again */
4127 pline("
\8e\9d\82¿
\95¨
\82Ì
\95¶
\8e\9a\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢
\81D");
4131 collect = (let == obj->invlet);
4132 /* change the inventory and print the resulting item */
4134 adj_type = collect ? "Collecting" : !splitting ? "Moving:" : "Splitting:";
4136 adj_type = collect ? "
\82ð
\8fW
\82ß
\82½
\81D" : !splitting ? "
\82ð
\88Ú
\93®
\82µ
\82½
\81D" : "
\82ð
\95ª
\8a\84\82µ
\82½
\81D";
4139 * don't use freeinv/addinv to avoid double-touching artifacts,
4140 * dousing lamps, losing luck, cursing loadstone, etc.
4142 extract_nobj(obj, &invent);
4144 for (otmp = invent; otmp;) {
4145 /* it's tempting to pull this outside the loop, but merged() could
4146 free ONAME(obj) [via obfree()] and replace it with ONAME(otmp) */
4147 objname = has_oname(obj) ? ONAME(obj) : (char *) 0;
4150 /* Collecting: #adjust an inventory stack into its same slot;
4151 keep it there and merge other compatible stacks into it.
4152 Traditional inventory behavior is to merge unnamed stacks
4153 with compatible named ones; we only want that if it is
4154 the 'from' stack (obj) with a name and candidate (otmp)
4155 without one, not unnamed 'from' with named candidate. */
4156 otmpname = has_oname(otmp) ? ONAME(otmp) : (char *) 0;
4157 if ((!otmpname || (objname && !strcmp(objname, otmpname)))
4158 && merged(&otmp, &obj)) {
4160 adj_type = "Merging:";
4162 adj_type = "
\82ð
\8d\87\82í
\82¹
\82½
\81D";
4165 extract_nobj(obj, &invent);
4166 continue; /* otmp has already been updated */
4168 } else if (otmp->invlet == let) {
4169 /* Moving or splitting: don't merge extra compatible stacks.
4170 Found 'otmp' in destination slot; merge if compatible,
4171 otherwise bump whatever is there to an open slot. */
4174 adj_type = "Swapping:";
4176 adj_type = "
\82ð
\8cð
\8a·
\82µ
\82½
\81D";
4177 otmp->invlet = obj->invlet;
4179 /* strip 'from' name if it has one */
4180 if (objname && !obj->oartifact)
4181 ONAME(obj) = (char *) 0;
4182 if (!mergable(otmp, obj)) {
4183 /* won't merge; put 'from' name back */
4185 ONAME(obj) = objname;
4187 /* will merge; discard 'from' name */
4189 free((genericptr_t) objname), objname = 0;
4192 if (merged(&otmp, &obj)) {
4194 adj_type = "Splitting and merging:";
4196 adj_type = "
\82ð
\95ª
\8a\84\82µ
\82Ä
\8d\87\82í
\82¹
\82½
\81D";
4198 extract_nobj(obj, &invent);
4199 } else if (inv_cnt(FALSE) >= 52) {
4200 (void) merged(&splitting, &obj); /* undo split */
4201 /* "knapsack cannot accommodate any more items" */
4203 Your("pack is too full.");
4205 Your("
\8e\9d\82¿
\95¨
\82Í
\88ê
\94t
\82¾
\81D");
4209 extract_nobj(bumped, &invent);
4211 } /* moving vs splitting */
4212 break; /* not collecting and found 'to' slot */
4217 /* inline addinv; insert loose object at beginning of inventory */
4220 obj->where = OBJ_INVENT;
4224 /* splitting the 'from' stack is causing an incompatible
4225 stack in the 'to' slot to be moved into an open one;
4226 we need to do another inline insertion to inventory */
4227 assigninvlet(bumped);
4228 bumped->nobj = invent;
4229 bumped->where = OBJ_INVENT;
4234 /* messages deferred until inventory has been fully reestablished */
4235 prinv(adj_type, obj, 0L);
4238 prinv("Moving:", bumped, 0L);
4240 prinv("
\88Ú
\93®:", bumped, 0L);
4242 clear_splitobjs(); /* reset splitobj context */
4247 /* common to display_minventory and display_cinventory */
4249 invdisp_nothing(hdr, txt)
4250 const char *hdr, *txt;
4254 menu_item *selected;
4257 win = create_nhwindow(NHW_MENU);
4259 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr,
4261 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
4262 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
4263 end_menu(win, (char *) 0);
4264 if (select_menu(win, PICK_NONE, &selected) > 0)
4265 free((genericptr_t) selected);
4266 destroy_nhwindow(win);
4270 /* query_objlist callback: return things that are worn or wielded */
4272 worn_wield_only(obj)
4276 /* check for things that *are* worn or wielded (only used for monsters,
4277 so we don't worry about excluding W_CHAIN, W_ARTI and the like) */
4278 return (boolean) (obj->owornmask != 0L);
4280 /* this used to check for things that *might* be worn or wielded,
4281 but that's not particularly interesting */
4282 if (is_weptool(obj) || is_wet_towel(obj) || obj->otyp == MEAT_RING)
4284 return (boolean) (obj->oclass == WEAPON_CLASS
4285 || obj->oclass == ARMOR_CLASS
4286 || obj->oclass == AMULET_CLASS
4287 || obj->oclass == RING_CLASS);
4292 * Display a monster's inventory.
4293 * Returns a pointer to the object from the monster's inventory selected
4294 * or NULL if nothing was selected.
4296 * By default, only worn and wielded items are displayed. The caller
4297 * can pick one. Modifier flags are:
4299 * PICK_NONE, PICK_ONE - standard menu control
4300 * PICK_ANY - allowed, but we only return a single object
4301 * MINV_NOLET - nothing selectable
4302 * MINV_ALL - display all inventory
4305 display_minventory(mon, dflags, title)
4306 register struct monst *mon;
4313 menu_item *selected = 0;
4314 int do_all = (dflags & MINV_ALL) != 0,
4315 incl_hero = (do_all && u.uswallow && mon == u.ustuck),
4316 have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
4317 pickings = (dflags & MINV_PICKMASK);
4320 Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
4321 do_all ? "possessions" : "armament");
4323 Sprintf(tmp, "%s
\82Ì%s
\81F", Monnam(mon),
4324 do_all ? "
\8e\9d\82¿
\95¨" : "
\91\95\94õ");
4327 if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
4328 /* Fool the 'weapon in hand' routine into
4329 * displaying 'weapon in claw', etc. properly.
4331 youmonst.data = mon->data;
4333 n = query_objlist(title ? title : tmp, &(mon->minvent),
4334 (INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0)),
4335 &selected, pickings,
4336 do_all ? allow_all : worn_wield_only);
4340 invdisp_nothing(title ? title : tmp, "(none)");
4342 invdisp_nothing(title ? title : tmp, "(
\89½
\82à
\82È
\82¢)");
4347 ret = selected[0].item.a_obj;
4348 free((genericptr_t) selected);
4350 ret = (struct obj *) 0;
4355 * Display the contents of a container in inventory style.
4356 * Currently, this is only used for statues, via wand of probing.
4359 display_cinventory(obj)
4360 register struct obj *obj;
4365 menu_item *selected = 0;
4368 (void) safe_qbuf(qbuf, "Contents of ", ":", obj, doname, ansimpleoname,
4371 (void) safe_qbuf(qbuf, "", "
\82Ì
\92\86\90g
\81F", obj, doname, ansimpleoname,
4376 n = query_objlist(qbuf, &(obj->cobj), INVORDER_SORT,
4377 &selected, PICK_NONE, allow_all);
4380 invdisp_nothing(qbuf, "(empty)");
4382 invdisp_nothing(qbuf, "(
\8bó
\82Á
\82Û)");
4386 ret = selected[0].item.a_obj;
4387 free((genericptr_t) selected);
4389 ret = (struct obj *) 0;
4394 /* query objlist callback: return TRUE if obj is at given location */
4401 return (obj->ox == only.x && obj->oy == only.y);
4405 * Display a list of buried items in inventory style. Return a non-zero
4406 * value if there were items at that spot.
4408 * Currently, this is only used with a wand of probing zapped downwards.
4411 display_binventory(x, y, as_if_seen)
4416 menu_item *selected = 0;
4419 /* count # of objects here */
4420 for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
4421 if (obj->ox == x && obj->oy == y) {
4431 if (query_objlist("Things that are buried here:",
4433 if (query_objlist("
\82±
\82±
\82É
\96\84\82ß
\82ç
\82ê
\82Ä
\82¢
\82é
\82à
\82Ì
\81F",
4434 &level.buriedobjlist, INVORDER_SORT,
4435 &selected, PICK_NONE, only_here) > 0)
4436 free((genericptr_t) selected);
4437 only.x = only.y = 0;