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-2018 */
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) { /* '-' */
1408 char *suf = (char *) 0;
1411 if ((bp = strstr(buf, " on the ")) != 0) {
1412 /* rub on the stone[s] */
1416 if ((bp = strstr(buf, " or ")) != 0) {
1418 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:1886: int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
1908 pickup.c:3145: 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",
2292 (dot && use_invlet ? obj->invlet : let),
2293 (txt ? txt : doname(obj)), cost, currency(cost));
2296 iflags.menu_tab_sep ? "%c - %s\t%6ld%s"
2297 : "%c - %-45s %6ld%s",
2298 (dot && use_invlet ? obj->invlet : let),
2299 (txt ? txt : doname(obj)), cost, currency(cost));
2302 /* ordinary inventory display or pickup message */
2303 Sprintf(li, "%c - %s%s", (use_invlet ? obj->invlet : let),
2305 (txt ? txt : doname(obj)), (dot ? "." : ""));
2307 (txt ? txt : doname(obj)), (dot ? "
\81D" : ""));
2310 obj->quan = savequan;
2315 /* the 'i' command */
2319 (void) display_inventory((char *) 0, FALSE);
2326 * Scan the given list of objects. If last_found is NULL, return the first
2327 * unpaid object found. If last_found is not NULL, then skip over unpaid
2328 * objects until last_found is reached, then set last_found to NULL so the
2329 * next unpaid object is returned. This routine recursively follows
2332 STATIC_OVL struct obj *
2333 find_unpaid(list, last_found)
2334 struct obj *list, **last_found;
2341 /* still looking for previous unpaid object */
2342 if (list == *last_found)
2343 *last_found = (struct obj *) 0;
2345 return ((*last_found = list));
2347 if (Has_contents(list)) {
2348 if ((obj = find_unpaid(list->cobj, last_found)) != 0)
2353 return (struct obj *) 0;
2356 /* for perm_invent when operating on a partial inventory display, so that
2357 the persistent one doesn't get shrunk during filtering for item selection
2358 then regrown to full inventory, possibly being resized in the process */
2359 static winid cached_pickinv_win = WIN_ERR;
2362 free_pickinv_cache()
2364 if (cached_pickinv_win != WIN_ERR) {
2365 destroy_nhwindow(cached_pickinv_win);
2366 cached_pickinv_win = WIN_ERR;
2371 * Internal function used by display_inventory and getobj that can display
2372 * inventory and return a count as well as a letter. If out_cnt is not null,
2373 * any count returned from the menu selection is placed here.
2376 display_pickinv(lets, xtra_choice, query, want_reply, out_cnt)
2377 register const char *lets;
2378 const char *xtra_choice; /* "fingers", pick hands rather than an object */
2384 static const char not_carrying_anything[] = "Not carrying anything";
2386 static const char not_carrying_anything[] = "
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢";
2389 char *invlet = flags.inv_order;
2391 winid win; /* windows being used */
2393 menu_item *selected;
2396 lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
2398 if (flags.perm_invent && (lets || xtra_choice)) {
2399 /* partial inventory in perm_invent setting; don't operate on
2400 full inventory window, use an alternate one instead; create
2401 the first time needed and keep it for re-use as needed later */
2402 if (cached_pickinv_win == WIN_ERR)
2403 cached_pickinv_win = create_nhwindow(NHW_MENU);
2404 win = cached_pickinv_win;
2409 * Exit early if no inventory -- but keep going if we are doing
2410 * a permanent inventory update. We need to keep going so the
2411 * permanent inventory window updates itself to remove the last
2412 * item(s) dropped. One down side: the addition of the exception
2413 * for permanent inventory window updates _can_ pop the window
2414 * up when it's not displayed -- even if it's empty -- because we
2415 * don't know at this level if its up or not. This may not be
2416 * an issue if empty checks are done before hand and the call
2417 * to here is short circuited away.
2419 * 2: our count here is only to distinguish between 0 and 1 and
2420 * more than 1; for the last one, we don't need a precise number.
2421 * For perm_invent update we force 'more than 1'.
2423 n = (flags.perm_invent && !lets && !want_reply) ? 2
2424 : lets ? (int) strlen(lets)
2425 : !invent ? 0 : !invent->nobj ? 1 : 2;
2426 /* for xtra_choice, there's another 'item' not included in initial 'n';
2427 for !lets (full invent) and for override_ID (wizard mode identify),
2428 skip message_menu handling of single item even if item count was 1 */
2429 if (xtra_choice || (n == 1 && (!lets || iflags.override_ID)))
2434 pline("%s.", not_carrying_anything);
2436 pline("%s
\81D", not_carrying_anything);
2440 /* oxymoron? temporarily assign permanent inventory letters */
2441 if (!flags.invlet_constant)
2444 if (n == 1 && !iflags.force_invmenu) {
2445 /* when only one item of interest, use pline instead of menus;
2446 we actually use a fake message-line menu in order to allow
2447 the user to perform selection at the --More-- prompt for tty */
2450 /* xtra_choice is "bare hands" (wield), "fingertip" (Engrave),
2451 "nothing" (ready Quiver), or "fingers" (apply grease) */
2452 ret = message_menu(HANDS_SYM, PICK_ONE,
2453 xprname((struct obj *) 0, xtra_choice,
2454 HANDS_SYM, TRUE, 0L, 0L)); /* '-' */
2456 for (otmp = invent; otmp; otmp = otmp->nobj)
2457 if (!lets || otmp->invlet == lets[0])
2460 ret = message_menu(otmp->invlet,
2461 want_reply ? PICK_ONE : PICK_NONE,
2462 xprname(otmp, (char *) 0, lets[0],
2466 *out_cnt = -1L; /* select all */
2471 (((flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET)
2472 | (flags.sortpack ? SORTLOOT_PACK : 0)),
2477 if (wizard && iflags.override_ID) {
2478 char prompt[QBUFSZ];
2481 /* wiz_identify stuffed the wiz_identify command character (^I)
2482 into iflags.override_ID for our use as an accelerator */
2483 Sprintf(prompt, "Debug Identify (%s to permanently identify)",
2484 visctrl(iflags.override_ID));
2485 add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
2486 prompt, MENU_UNSELECTED);
2487 } else if (xtra_choice) {
2488 /* wizard override ID and xtra_choice are mutually exclusive */
2490 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2491 "Miscellaneous", MENU_UNSELECTED);
2492 any.a_char = HANDS_SYM; /* '-' */
2493 add_menu(win, NO_GLYPH, &any, HANDS_SYM, 0, ATR_NONE,
2494 xtra_choice, MENU_UNSELECTED);
2498 for (otmp = invent; otmp; otmp = otmp->nobj) {
2499 if (lets && !index(lets, otmp->invlet))
2501 if (!flags.sortpack || otmp->oclass == *invlet) {
2502 any = zeroany; /* all bits zero */
2503 ilet = otmp->invlet;
2504 if (flags.sortpack && !classcount) {
2505 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2506 let_to_name(*invlet, FALSE,
2507 (want_reply && iflags.menu_head_objsym)),
2512 add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE,
2513 doname(otmp), MENU_UNSELECTED);
2516 if (flags.sortpack) {
2519 if (--invlet != venom_inv) {
2524 if (iflags.force_invmenu && lets && want_reply) {
2527 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2528 "Special", MENU_UNSELECTED);
2530 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2531 "
\93Á
\8eê", MENU_UNSELECTED);
2535 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
2536 "(list everything)", MENU_UNSELECTED);
2538 add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
2539 "(
\91S
\82Ä
\82Ì
\88ê
\97\97)", MENU_UNSELECTED);
2542 /* for permanent inventory where we intend to show everything but
2543 nothing has been listed (because there isn't anyhing to list;
2544 recognized via any.a_char still being zero; the n==0 case above
2545 gets skipped for perm_invent), put something into the menu */
2546 if (flags.perm_invent && !lets && !any.a_char) {
2548 add_menu(win, NO_GLYPH, &any, 0, 0, 0,
2549 not_carrying_anything, MENU_UNSELECTED);
2552 end_menu(win, query && *query ? query : (char *) 0);
2554 n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
2556 ret = selected[0].item.a_char;
2558 *out_cnt = selected[0].count;
2559 free((genericptr_t) selected);
2561 ret = !n ? '\0' : '\033'; /* cancelled */
2567 * If lets == NULL or "", list all objects in the inventory. Otherwise,
2568 * list all objects with object classes that match the order in lets.
2570 * Returns the letter identifier of a selected item, or 0 if nothing
2574 display_inventory(lets, want_reply)
2578 return display_pickinv(lets, (char *) 0, (char *) 0,
2579 want_reply, (long *) 0);
2583 * Show what is current using inventory letters.
2587 display_used_invlets(avoidlet)
2592 char *invlet = flags.inv_order;
2593 int n, classcount, invdone = 0;
2596 menu_item *selected;
2599 win = create_nhwindow(NHW_MENU);
2602 any = zeroany; /* set all bits to zero */
2604 for (otmp = invent; otmp; otmp = otmp->nobj) {
2605 ilet = otmp->invlet;
2606 if (ilet == avoidlet)
2608 if (!flags.sortpack || otmp->oclass == *invlet) {
2609 if (flags.sortpack && !classcount) {
2610 any = zeroany; /* zero */
2611 add_menu(win, NO_GLYPH, &any, 0, 0,
2612 iflags.menu_headings,
2613 let_to_name(*invlet, FALSE, FALSE),
2618 add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE,
2619 doname(otmp), MENU_UNSELECTED);
2622 if (flags.sortpack && *++invlet)
2626 end_menu(win, "Inventory letters used:");
2628 n = select_menu(win, PICK_ONE, &selected);
2630 ret = selected[0].item.a_char;
2631 free((genericptr_t) selected);
2633 ret = !n ? '\0' : '\033'; /* cancelled */
2634 destroy_nhwindow(win);
2640 * Returns the number of unpaid items within the given list. This includes
2641 * contained objects.
2652 if (Has_contents(list))
2653 count += count_unpaid(list->cobj);
2660 * Returns the number of items with b/u/c/unknown within the given list.
2661 * This does NOT include contained objects.
2663 * Assumes that the hero sees or touches or otherwise senses the objects
2664 * at some point: bknown is forced for priest[ess], like in xname().
2667 count_buc(list, type, filterfunc)
2670 boolean FDECL((*filterfunc), (OBJ_P));
2674 for (; list; list = list->nobj) {
2675 /* priests always know bless/curse state */
2676 if (Role_if(PM_PRIEST))
2677 list->bknown = (list->oclass != COIN_CLASS);
2678 /* some actions exclude some or most items */
2679 if (filterfunc && !(*filterfunc)(list))
2682 /* coins are either uncursed or unknown based upon option setting */
2683 if (list->oclass == COIN_CLASS) {
2684 if (type == (iflags.goldX ? BUC_UNKNOWN : BUC_UNCURSED))
2688 /* check whether this object matches the requested type */
2690 ? (type == BUC_UNKNOWN)
2691 : list->blessed ? (type == BUC_BLESSED)
2692 : list->cursed ? (type == BUC_CURSED)
2693 : (type == BUC_UNCURSED))
2699 /* similar to count_buc(), but tallies all states at once
2700 rather than looking for a specific type */
2702 tally_BUCX(list, by_nexthere, bcp, ucp, ccp, xcp, ocp)
2704 boolean by_nexthere;
2705 int *bcp, *ucp, *ccp, *xcp, *ocp;
2707 /* Future extensions:
2708 * Skip current_container when list is invent, uchain when
2709 * first object of list is located on the floor. 'ocp' will then
2710 * have a function again (it was a counter for having skipped gold,
2711 * but that's not skipped anymore).
2713 *bcp = *ucp = *ccp = *xcp = *ocp = 0;
2714 for ( ; list; list = (by_nexthere ? list->nexthere : list->nobj)) {
2715 /* priests always know bless/curse state */
2716 if (Role_if(PM_PRIEST))
2717 list->bknown = (list->oclass != COIN_CLASS);
2718 /* coins are either uncursed or unknown based upon option setting */
2719 if (list->oclass == COIN_CLASS) {
2726 /* ordinary items */
2729 else if (list->blessed)
2731 else if (list->cursed)
2733 else /* neither blessed nor cursed => uncursed */
2739 count_contents(container, nested, quantity, everything)
2740 struct obj *container;
2741 boolean nested, /* include contents of any nested containers */
2742 quantity, /* count all vs count separate stacks */
2743 everything; /* all objects vs only unpaid objects */
2748 for (otmp = container->cobj; otmp; otmp = otmp->nobj) {
2749 if (nested && Has_contents(otmp))
2750 count += count_contents(otmp, nested, quantity, everything);
2751 if (everything || otmp->unpaid)
2752 count += quantity ? otmp->quan : 1L;
2761 struct obj *otmp, *marker, *contnr;
2763 char *invlet = flags.inv_order;
2764 int classcount, count, num_so_far;
2767 count = count_unpaid(invent);
2768 otmp = marker = contnr = (struct obj *) 0;
2771 otmp = find_unpaid(invent, &marker);
2772 contnr = unknwn_contnr_contents(otmp);
2774 if (otmp && !contnr) {
2775 /* 1 item; use pline instead of popup menu */
2776 cost = unpaid_cost(otmp, FALSE);
2777 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
2778 pline1(xprname(otmp, distant_name(otmp, doname),
2779 carried(otmp) ? otmp->invlet : CONTAINED_SYM,
2781 iflags.suppress_price--;
2785 win = create_nhwindow(NHW_MENU);
2787 num_so_far = 0; /* count of # printed so far */
2788 if (!flags.invlet_constant)
2793 for (otmp = invent; otmp; otmp = otmp->nobj) {
2794 ilet = otmp->invlet;
2796 if (!flags.sortpack || otmp->oclass == *invlet) {
2797 if (flags.sortpack && !classcount) {
2798 putstr(win, 0, let_to_name(*invlet, TRUE, FALSE));
2802 totcost += cost = unpaid_cost(otmp, FALSE);
2803 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
2804 putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
2805 ilet, TRUE, cost, 0L));
2806 iflags.suppress_price--;
2811 } while (flags.sortpack && (*++invlet));
2813 if (count > num_so_far) {
2814 /* something unpaid is contained */
2816 putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE, FALSE));
2818 * Search through the container objects in the inventory for
2819 * unpaid items. The top level inventory items have already
2822 for (otmp = invent; otmp; otmp = otmp->nobj) {
2823 if (Has_contents(otmp)) {
2826 marker = (struct obj *) 0; /* haven't found any */
2827 while (find_unpaid(otmp->cobj, &marker)) {
2828 totcost += cost = unpaid_cost(marker, FALSE);
2831 iflags.suppress_price++; /* suppress "(unpaid)" sfx */
2833 xprname(marker, distant_name(marker, doname),
2834 CONTAINED_SYM, TRUE, cost, 0L));
2835 iflags.suppress_price--;
2838 if (!otmp->cknown) {
2839 char contbuf[BUFSZ];
2841 /* Shopkeeper knows what to charge for contents */
2842 Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
2844 xprname((struct obj *) 0, contbuf, CONTAINED_SYM,
2845 TRUE, contcost, 0L));
2854 xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
2857 xprname((struct obj *) 0, "
\8d\87\8cv
\81F", '*', FALSE, totcost, 0L));
2859 display_nhwindow(win, FALSE);
2860 destroy_nhwindow(win);
2863 /* query objlist callback: return TRUE if obj type matches "this_type" */
2864 static int this_type;
2870 boolean res = (obj->oclass == this_type);
2872 if (obj->oclass == COIN_CLASS) {
2873 /* if filtering by bless/curse state, gold is classified as
2874 either unknown or uncursed based on user option setting */
2875 if (this_type && index("BUCX", this_type))
2876 res = (this_type == (iflags.goldX ? 'X' : 'U'));
2878 switch (this_type) {
2880 res = (obj->bknown && obj->blessed);
2883 res = (obj->bknown && !(obj->blessed || obj->cursed));
2886 res = (obj->bknown && obj->cursed);
2892 break; /* use 'res' as-is */
2898 /* the 'I' command */
2904 char *extra_types, types[BUFSZ];
2905 int class_count, oclass, unpaid_count, itemcount;
2906 int bcnt, ccnt, ucnt, xcnt, ocnt;
2907 boolean billx = *u.ushops && doinvbill(0);
2908 menu_item *pick_list;
2909 boolean traditional = TRUE;
2911 const char *prompt = "What type of object do you want an inventory of?";
2913 const char *prompt = "
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\8e\9d\82¿
\95¨
\82ð
\8c©
\82Ü
\82·
\82©
\81H";
2915 if (!invent && !billx) {
2917 You("aren't carrying anything.");
2919 You("
\82»
\82Ì
\8eí
\97Þ
\82Ì
\95¨
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
2922 unpaid_count = count_unpaid(invent);
2923 tally_BUCX(invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
2925 if (flags.menu_style != MENU_TRADITIONAL) {
2926 if (flags.menu_style == MENU_FULL
2927 || flags.menu_style == MENU_PARTIAL) {
2928 traditional = FALSE;
2940 n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
2943 this_type = c = pick_list[0].item.a_int;
2944 free((genericptr_t) pick_list);
2948 /* collect a list of classes of objects carried, for use as a prompt
2951 class_count = collect_obj_classes(types, invent, FALSE,
2952 (boolean FDECL((*), (OBJ_P))) 0,
2954 if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
2955 types[class_count++] = ' ';
2957 types[class_count++] = 'u';
2959 types[class_count++] = 'x';
2961 types[class_count++] = 'B';
2963 types[class_count++] = 'U';
2965 types[class_count++] = 'C';
2967 types[class_count++] = 'X';
2968 types[class_count] = '\0';
2969 /* add everything not already included; user won't see these */
2970 extra_types = eos(types);
2971 *extra_types++ = '\033';
2973 *extra_types++ = 'u';
2975 *extra_types++ = 'x';
2977 *extra_types++ = 'B';
2979 *extra_types++ = 'U';
2981 *extra_types++ = 'C';
2983 *extra_types++ = 'X';
2984 *extra_types = '\0'; /* for index() */
2985 for (i = 0; i < MAXOCLASSES; i++)
2986 if (!index(types, def_oc_syms[i].sym)) {
2987 *extra_types++ = def_oc_syms[i].sym;
2988 *extra_types = '\0';
2991 if (class_count > 1) {
2992 c = yn_function(prompt, types, '\0');
2995 clear_nhwindow(WIN_MESSAGE);
2999 /* only one thing to itemize */
3008 if (c == 'x' || (c == 'X' && billx && !xcnt)) {
3010 (void) doinvbill(1);
3013 pline("No used-up objects%s.",
3014 unpaid_count ? " on your shopping bill" : "");
3016 pline("
\8eg
\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\95¨
\82Í%s
\82È
\82¢
\81D",
3017 unpaid_count ? "
\8f¤
\93X
\82Ì
\90¿
\8b\81\8f\91\82É
\82Í" : "");
3021 if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
3026 You("are not carrying any unpaid objects.");
3028 You("
\96¢
\95¥
\82¢
\82Ì
\83A
\83C
\83e
\83\80\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3032 if (index("BUCX", c))
3033 oclass = c; /* not a class but understood by this_type_only() */
3035 oclass = def_char_to_objclass(c); /* change to object class */
3037 if (oclass == COIN_CLASS)
3039 if (index(types, c) > index(types, '\033')) {
3040 /* '> ESC' => hidden choice, something known not to be carried */
3041 const char *before = "", *after = "";
3046 before = "known to be blessed ";
3048 before = "
\8fj
\95\9f\82³
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3052 before = "known to be uncursed ";
3054 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82È
\82¢
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3058 before = "known to be cursed ";
3060 before = "
\8eô
\82í
\82ê
\82Ä
\82¢
\82é
\82Æ
\82í
\82©
\82Á
\82Ä
\82¢
\82é";
3064 after = " whose blessed/uncursed/cursed status is unknown";
3066 after = "
\8fj
\95\9f\81^
\8eô
\82¢
\82ª
\82í
\82©
\82ç
\82È
\82¢";
3067 break; /* better phrasing is desirable */
3069 /* 'c' is an object class, because we've already handled
3070 all the non-class letters which were put into 'types[]';
3071 could/should move object class names[] array from below
3072 to somewhere above so that we can access it here (via
3073 lcase(strcpy(classnamebuf, names[(int) c]))), but the
3074 game-play value of doing so is low... */
3078 before = "
\82»
\82Ì
\82æ
\82¤
\82È";
3082 You("have no %sobjects%s.", before, after);
3084 You("%s%s
\82à
\82Ì
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", before, after);
3089 if (query_objlist((char *) 0, &invent,
3090 ((flags.invlet_constant ? USE_INVLET : 0)
3092 &pick_list, PICK_NONE, this_type_only) > 0)
3093 free((genericptr_t) pick_list);
3097 /* return a string describing the dungeon feature at <x,y> if there
3098 is one worth mentioning at that location; otherwise null */
3100 dfeature_at(x, y, buf)
3104 struct rm *lev = &levl[x][y];
3105 int ltyp = lev->typ, cmap = -1;
3106 const char *dfeature = 0;
3107 static char altbuf[BUFSZ];
3109 if (IS_DOOR(ltyp)) {
3110 switch (lev->doormask) {
3113 break; /* "doorway" */
3116 break; /* "open door" */
3119 dfeature = "broken door";
3121 dfeature = "
\89ó
\82ê
\82½
\94à";
3125 break; /* "closed door" */
3127 /* override door description for open drawbridge */
3128 if (is_drawbridge_wall(x, y) >= 0)
3130 dfeature = "open drawbridge portcullis", cmap = -1;
3132 dfeature = "
\8d~
\82è
\82Ä
\82¢
\82é
\92µ
\82Ë
\8b´", cmap = -1;
3133 } else if (IS_FOUNTAIN(ltyp))
3134 cmap = S_fountain; /* "fountain" */
3135 else if (IS_THRONE(ltyp))
3136 cmap = S_throne; /* "opulent throne" */
3137 else if (is_lava(x, y))
3138 cmap = S_lava; /* "molten lava" */
3139 else if (is_ice(x, y))
3140 cmap = S_ice; /* "ice" */
3141 else if (is_pool(x, y))
3143 dfeature = "pool of water";
3145 dfeature = "
\90\85\82½
\82Ü
\82è";
3146 else if (IS_SINK(ltyp))
3147 cmap = S_sink; /* "sink" */
3148 else if (IS_ALTAR(ltyp)) {
3150 Sprintf(altbuf, "%saltar to %s (%s)",
3151 ((lev->altarmask & AM_SHRINE)
3152 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3156 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3158 Sprintf(altbuf, "%s%s
\82Ì
\8dÕ
\92d(%s)",
3159 ((lev->altarmask & AM_SHRINE)
3160 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
3164 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
3167 } else if ((x == xupstair && y == yupstair)
3168 || (x == sstairs.sx && y == sstairs.sy && sstairs.up))
3169 cmap = S_upstair; /* "staircase up" */
3170 else if ((x == xdnstair && y == ydnstair)
3171 || (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
3172 cmap = S_dnstair; /* "staircase down" */
3173 else if (x == xupladder && y == yupladder)
3174 cmap = S_upladder; /* "ladder up" */
3175 else if (x == xdnladder && y == ydnladder)
3176 cmap = S_dnladder; /* "ladder down" */
3177 else if (ltyp == DRAWBRIDGE_DOWN)
3178 cmap = S_vodbridge; /* "lowered drawbridge" */
3179 else if (ltyp == DBWALL)
3180 cmap = S_vcdbridge; /* "raised drawbridge" */
3181 else if (IS_GRAVE(ltyp))
3182 cmap = S_grave; /* "grave" */
3183 else if (ltyp == TREE)
3184 cmap = S_tree; /* "tree" */
3185 else if (ltyp == IRONBARS)
3187 dfeature = "set of iron bars";
3189 dfeature = "
\93S
\82Ì
\96_";
3192 dfeature = defsyms[cmap].explanation;
3194 Strcpy(buf, dfeature);
3198 /* look at what is here; if there are many objects (pile_limit or more),
3199 don't show them unless obj_cnt is 0 */
3201 look_here(obj_cnt, picked_some)
3202 int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progress */
3203 boolean picked_some;
3208 const char *verb = Blind ? "feel" : "see";
3210 const char *verb = Blind ? "
\82ª
\82 \82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½" : "
\82ð
\82Ý
\82Â
\82¯
\82½";
3212 const char *dfeature = (char *) 0;
3213 char fbuf[BUFSZ], fbuf2[BUFSZ];
3215 boolean skip_objects, felt_cockatrice = FALSE;
3217 /* default pile_limit is 5; a value of 0 means "never skip"
3218 (and 1 effectively forces "always skip") */
3219 skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
3220 if (u.uswallow && u.ustuck) {
3221 struct monst *mtmp = u.ustuck;
3224 Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
3225 mbodypart(mtmp, STOMACH));
3227 Sprintf(fbuf, "%s
\82Ì%s
\82Ì
\92\86\90g", mon_nam(mtmp),
3228 mbodypart(mtmp, STOMACH));
3230 #if 0 /*JP*//*
\8cê
\8f\87\82ª
\88á
\82¤
\82Ì
\82Å
\91f
\92¼
\82É*/
3231 /* Skip "Contents of " by using fbuf index 12 */
3232 You("%s to %s what is lying in %s.", Blind ? "try" : "look around",
3235 You("%s
\82Ì%s
\82É
\89½
\82ª
\82 \82é
\82©%s
\81D",
3236 mon_nam(mtmp), mbodypart(mtmp, STOMACH),
3237 Blind ? "
\82³
\82®
\82Á
\82½" : "
\8c©
\89ñ
\82µ
\82½");
3239 otmp = mtmp->minvent;
3241 for (; otmp; otmp = otmp->nobj) {
3242 /* If swallower is an animal, it should have become stone
3244 if (otmp->otyp == CORPSE)
3245 feel_cockatrice(otmp, FALSE);
3249 Strcpy(fbuf, "You feel");
3252 Sprintf(fbuf, "
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F", Blind ? "
\82ç
\82µ
\82¢" : "");
3254 (void) display_minventory(mtmp, MINV_ALL | PICK_NONE, fbuf);
3257 You("%s no objects here.", verb);
3259 pline(Blind ? "
\82 \82È
\82½
\82Í
\89½
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D"
3260 : "
\82 \82È
\82½
\82Í
\89½
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3265 if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen)
3267 There("is %s here.",
3269 pline("
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D",
3270 an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
3272 otmp = level.objects[u.ux][u.uy];
3273 dfeature = dfeature_at(u.ux, u.uy, fbuf2);
3275 if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
3277 if (dfeature && !strcmp(dfeature, "
\90\85\82½
\82Ü
\82è") && Underwater)
3281 boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
3284 if (dfeature && !strncmp(dfeature, "altar ", 6)) {
3286 if (dfeature && !strncmp(dfeature, "
\8dÕ
\92d", 4)) {
3287 /* don't say "altar" twice, dfeature has more info */
3289 You("try to feel what is here.");
3291 You("
\82±
\82±
\82É
\89½
\82ª
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3294 const char *where = (Blind && !can_reach_floor(TRUE))
3295 ? "lying beneath you"
3296 : "lying here on the ",
3297 *onwhat = (Blind && !can_reach_floor(TRUE))
3299 : surface(u.ux, u.uy);
3301 You("try to feel what is %s%s.", drift ? "floating here" : where,
3302 drift ? "" : onwhat);
3305 You("
\89½
\82ª
\95\82\82¢
\82Ä
\82¢
\82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3306 } else if (Blind && !can_reach_floor(TRUE)) {
3307 You("
\89½
\82ª
\91«
\89º
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
3309 You("
\89½
\82ª%s
\82Ì
\8fã
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D", surface(u.ux, u.uy));
3313 if (dfeature && !drift && !strcmp(dfeature, surface(u.ux, u.uy)))
3314 dfeature = 0; /* ice already identified */
3315 if (!can_reach_floor(TRUE)) {
3317 pline("But you can't reach it!");
3319 pline("
\82µ
\82©
\82µ
\93Í
\82©
\82È
\82¢
\81I");
3326 Sprintf(fbuf, "There is %s here.", an(dfeature));
3328 Sprintf(fbuf, "
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D", an(dfeature));
3330 if (!otmp || is_lava(u.ux, u.uy)
3331 || (is_pool(u.ux, u.uy) && !Underwater)) {
3334 read_engr_at(u.ux, u.uy); /* Eric Backus */
3335 if (!skip_objects && (Blind || !dfeature))
3337 You("%s no objects here.", verb);
3340 "
\82È
\82É
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82·
\82é
\81D" :
3341 "
\82È
\82É
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3345 /* we know there is something here */
3350 read_engr_at(u.ux, u.uy); /* Eric Backus */
3351 if (obj_cnt == 1 && otmp->quan == 1L)
3353 There("is %s object here.", picked_some ? "another" : "an");
3355 There("
\82±
\82±
\82É
\82Í%s
\88ê
\82Â
\82à
\82Ì
\82ª
\82 \82é
\81D", picked_some ? "
\82à
\82¤" : "");
3358 There("are %s%s objects here.",
3364 picked_some ? " more" : "");
3366 pline("
\82±
\82±
\82É
\82Í%s%s
\82à
\82Ì
\82ª
\82 \82é
\81D",
3367 picked_some ? "
\82³
\82ç
\82É" : "",
3369 ? "
\82¢
\82
\82Â
\82©
\82Ì"
3370 : "
\82½
\82
\82³
\82ñ
\82Ì");
3372 for (; otmp; otmp = otmp->nexthere)
3373 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3374 #if 0 /*JP*//*"It's (corpse_name), unfortunately"*/
3381 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3382 poly_when_stoned(youmonst.data)
3384 : ", unfortunately");
3387 poly_when_stoned(youmonst.data)
3389 : "
\8ec
\94O
\82È
\82ª
\82ç",
3390 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3392 ? "
\82ð
\8aÜ
\82ñ
\82Å
\82¢
\82é"
3395 feel_cockatrice(otmp, FALSE);
3398 } else if (!otmp->nexthere) {
3399 /* only one object */
3402 read_engr_at(u.ux, u.uy); /* Eric Backus */
3404 You("%s here %s.", verb, doname_with_price(otmp));
3406 pline("%s%s
\81D", doname_with_price(otmp), verb);
3407 iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
3408 if (otmp->otyp == CORPSE)
3409 feel_cockatrice(otmp, FALSE);
3413 display_nhwindow(WIN_MESSAGE, FALSE);
3414 tmpwin = create_nhwindow(NHW_MENU);
3416 putstr(tmpwin, 0, fbuf);
3417 putstr(tmpwin, 0, "");
3420 Sprintf(buf, "%s that %s here:",
3421 picked_some ? "Other things" : "Things",
3422 Blind ? "you feel" : "are");
3424 Sprintf(buf, "%s
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F",
3425 picked_some ? "
\91¼
\82É" : "",
3426 Blind ? "
\82ç
\82µ
\82¢" : "");
3428 putstr(tmpwin, 0, buf);
3429 for (; otmp; otmp = otmp->nexthere) {
3430 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3431 felt_cockatrice = TRUE;
3433 Sprintf(buf, "%s...", doname(otmp));
3435 Sprintf(buf, "%s
\81D
\81D
\81D", doname(otmp));
3436 putstr(tmpwin, 0, buf);
3439 putstr(tmpwin, 0, doname_with_price(otmp));
3441 display_nhwindow(tmpwin, TRUE);
3442 destroy_nhwindow(tmpwin);
3443 if (felt_cockatrice)
3444 feel_cockatrice(otmp, FALSE);
3445 read_engr_at(u.ux, u.uy); /* Eric Backus */
3450 /* the ':' command - explicitly look at what is here, including all objects */
3457 MSGTYPE={norep,noshow} "You see here"
3458 interfere with feedback from the look-here command */
3459 hide_unhide_msgtypes(TRUE, MSGTYP_MASK_REP_SHOW);
3460 res = look_here(0, FALSE);
3461 /* restore normal msgtype handling */
3462 hide_unhide_msgtypes(FALSE, MSGTYP_MASK_REP_SHOW);
3467 will_feel_cockatrice(otmp, force_touch)
3469 boolean force_touch;
3471 if ((Blind || force_touch) && !uarmg && !Stone_resistance
3472 && (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
3478 feel_cockatrice(otmp, force_touch)
3480 boolean force_touch;
3484 if (will_feel_cockatrice(otmp, force_touch)) {
3485 /* "the <cockatrice> corpse" */
3486 Strcpy(kbuf, corpse_xname(otmp, (const char *) 0, CXN_PFX_THE));
3488 if (poly_when_stoned(youmonst.data))
3490 You("touched %s with your bare %s.", kbuf,
3491 makeplural(body_part(HAND)));
3493 You("%s
\82Ì
\8e\80\91Ì
\82É
\91f%s
\82Å
\90G
\82Á
\82½
\81D", kbuf,
3498 pline("Touching %s is a fatal mistake...", kbuf);
3500 pline("%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82é
\82Ì
\82Í
\92v
\96½
\93I
\82È
\8aÔ
\88á
\82¢
\82¾
\81D
\81D
\81D", kbuf);
3501 /* normalize body shape here; hand, not body_part(HAND) */
3503 Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
3505 Sprintf(kbuf, "%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82Ä", killer_xname(otmp));
3506 /* will call polymon() for the poly_when_stoned() case */
3517 for (otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
3518 if (otmp != obj && merged(&obj, &otmp))
3523 /* returns TRUE if obj & otmp can be merged; used in invent.c and mkobj.c */
3526 register struct obj *otmp, *obj;
3528 int objnamelth = 0, otmpnamelth = 0;
3531 return FALSE; /* already the same object */
3532 if (obj->otyp != otmp->otyp)
3533 return FALSE; /* different types */
3534 if (obj->nomerge) /* explicitly marked to prevent merge */
3537 /* coins of the same kind will always merge */
3538 if (obj->oclass == COIN_CLASS)
3541 if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
3542 || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed
3543 || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
3544 || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
3545 || obj->bypass != otmp->bypass)
3550 /* Checks beyond this point either aren't applicable to globs
3551 * or don't inhibit their merger.
3554 if (obj->oclass == FOOD_CLASS
3555 && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
3558 if (obj->dknown != otmp->dknown
3559 || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
3560 || obj->oeroded != otmp->oeroded || obj->oeroded2 != otmp->oeroded2
3561 || obj->greased != otmp->greased)
3564 if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
3565 && (obj->oerodeproof != otmp->oerodeproof
3566 || obj->rknown != otmp->rknown))
3569 if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
3570 if (obj->corpsenm != otmp->corpsenm)
3574 /* hatching eggs don't merge; ditto for revivable corpses */
3575 if ((obj->otyp == EGG && (obj->timed || otmp->timed))
3576 || (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM
3577 && is_reviver(&mons[otmp->corpsenm])))
3580 /* allow candle merging only if their ages are close */
3581 /* see begin_burn() for a reference for the magic "25" */
3582 if (Is_candle(obj) && obj->age / 25 != otmp->age / 25)
3585 /* burning potions of oil never merge */
3586 if (obj->otyp == POT_OIL && obj->lamplit)
3589 /* don't merge surcharged item with base-cost item */
3590 if (obj->unpaid && !same_price(obj, otmp))
3593 /* if they have names, make sure they're the same */
3594 objnamelth = strlen(safe_oname(obj));
3595 otmpnamelth = strlen(safe_oname(otmp));
3596 if ((objnamelth != otmpnamelth
3597 && ((objnamelth && otmpnamelth) || obj->otyp == CORPSE))
3598 || (objnamelth && otmpnamelth
3599 && strncmp(ONAME(obj), ONAME(otmp), objnamelth)))
3602 /* for the moment, any additional information is incompatible */
3603 if (has_omonst(obj) || has_omid(obj) || has_olong(obj) || has_omonst(otmp)
3604 || has_omid(otmp) || has_olong(otmp))
3607 if (obj->oartifact != otmp->oartifact)
3610 if (obj->known == otmp->known || !objects[otmp->otyp].oc_uses_known) {
3611 return (boolean) objects[obj->otyp].oc_merge;
3616 /* the '$' command */
3620 /* the messages used to refer to "carrying gold", but that didn't
3621 take containers into account */
3622 long umoney = money_cnt(invent);
3625 Your("wallet is empty.");
3627 Your("
\8dà
\95z
\82Í
\8bó
\82Á
\82Û
\82¾
\81D");
3630 Your("wallet contains %ld %s.", umoney, currency(umoney));
3632 Your("
\8dà
\95z
\82É
\82Í%ld%s
\93ü
\82Á
\82Ä
\82¢
\82é
\81D", umoney, currency(umoney));
3633 shopper_financial_report();
3637 /* the ')' command */
3643 You("are empty %s.", body_part(HANDED));
3645 if(!uwep) You("%s
\82É
\95\90\8aí
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D", body_part(HAND));
3647 prinv((char *) 0, uwep, 0L);
3649 prinv((char *) 0, uswapwep, 0L);
3654 /* caller is responsible for checking !wearing_armor() */
3656 noarmor(report_uskin)
3657 boolean report_uskin;
3659 if (!uskin || !report_uskin) {
3661 You("are not wearing any armor.");
3663 You("
\8aZ
\82ð
\92\85\82Ä
\82¢
\82È
\82¢
\81D");
3665 char *p, *uskinname, buf[BUFSZ];
3667 uskinname = strcpy(buf, simpleonames(uskin));
3669 /* shorten "set of <color> dragon scales" to "<color> scales"
3670 and "<color> dragon scale mail" to "<color> scale mail" */
3671 if (!strncmpi(uskinname, "set of ", 7))
3673 if ((p = strstri(uskinname, " dragon ")) != 0)
3674 while ((p[1] = p[8]) != '\0')
3676 #else /*
\81u<
\90F>
\83h
\83\89\83S
\83\93\82Ì
\97Ø
\81v
\82ð
\81u<
\90F>
\82Ì
\97Ø
\81v
\82É
\82·
\82é*/
3677 if ((p = strstri(uskinname, "
\83h
\83\89\83S
\83\93\82Ì
\97Ø")) != 0)
3682 You("are not wearing armor but have %s embedded in your skin.",
3684 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",
3689 /* the '[' command */
3694 register int ct = 0;
3696 * Note: players sometimes get here by pressing a function key which
3697 * transmits ''ESC [ <something>'' rather than by pressing '[';
3698 * there's nothing we can--or should-do about that here.
3701 if (!wearing_armor()) {
3705 lets[ct++] = obj_to_let(uarmu);
3707 lets[ct++] = obj_to_let(uarm);
3709 lets[ct++] = obj_to_let(uarmc);
3711 lets[ct++] = obj_to_let(uarmh);
3713 lets[ct++] = obj_to_let(uarms);
3715 lets[ct++] = obj_to_let(uarmg);
3717 lets[ct++] = obj_to_let(uarmf);
3719 (void) display_inventory(lets, FALSE);
3724 /* the '=' command */
3728 if (!uleft && !uright)
3730 You("are not wearing any rings.");
3732 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
3735 register int ct = 0;
3738 lets[ct++] = obj_to_let(uleft);
3740 lets[ct++] = obj_to_let(uright);
3742 (void) display_inventory(lets, FALSE);
3747 /* the '"' command */
3753 You("are not wearing an amulet.");
3755 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
3757 prinv((char *) 0, uamul, 0L);
3765 if ((obj->owornmask & (W_TOOL | W_SADDLE)) != 0L)
3767 if (obj->oclass != TOOL_CLASS)
3769 return (boolean) (obj == uwep || obj->lamplit
3770 || (obj->otyp == LEASH && obj->leashmon));
3773 /* the '(' command */
3781 for (otmp = invent; otmp; otmp = otmp->nobj)
3782 if (tool_in_use(otmp))
3783 lets[ct++] = obj_to_let(otmp);
3787 You("are not using any tools.");
3789 You("
\8eg
\82¦
\82é
\93¹
\8bï
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3791 (void) display_inventory(lets, FALSE);
3795 /* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
3796 show inventory of all currently wielded, worn, or used objects */
3804 for (otmp = invent; otmp; otmp = otmp->nobj)
3805 if (is_worn(otmp) || tool_in_use(otmp))
3806 lets[ct++] = obj_to_let(otmp);
3810 You("are not wearing or wielding anything.");
3812 You("
\89½
\82à
\92\85\82Ä
\82¢
\82È
\82¢
\82µ
\81C
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
3814 (void) display_inventory(lets, FALSE);
3819 * uses up an object that's on the floor, charging for it as necessary
3822 useupf(obj, numused)
3823 register struct obj *obj;
3826 register struct obj *otmp;
3827 boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
3829 /* burn_floor_objects() keeps an object pointer that it tries to
3830 * useupf() multiple times, so obj must survive if plural */
3831 if (obj->quan > numused)
3832 otmp = splitobj(obj, numused);
3835 if (costly_spot(otmp->ox, otmp->oy)) {
3836 if (index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
3837 addtobill(otmp, FALSE, FALSE, FALSE);
3839 (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
3842 if (at_u && u.uundetected && hides_under(youmonst.data))
3843 (void) hideunder(&youmonst);
3847 * Conversion from a class to a string for printing.
3848 * This must match the object class order.
3850 STATIC_VAR NEARDATA const char *names[] = {
3852 0, "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", "Tools",
3853 "Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
3854 "Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
3856 0, "
\96
\82È
\95¨
\91Ì", "
\95\90\8aí", "
\8aZ", "
\8ew
\97Ö", "
\96\82\8f\9c\82¯", "
\93¹
\8bï",
3857 "
\90H
\97¿", "
\96ò", "
\8aª
\95¨", "
\96\82\96@
\8f\91", "
\8fñ", "
\8bà
\89Ý",
3858 "
\95ó
\90Î", "
\8aâ
\82Ü
\82½
\82Í
\92¤
\91\9c", "
\93S
\8b\85", "
\8d½", "
\93Å"
3861 STATIC_VAR NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
3863 STATIC_VAR NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
3865 STATIC_VAR NEARDATA const char *oth_names[] = { "
\8bl
\82ß
\82ç
\82ê
\82½
\93¹
\8bï" };
3867 STATIC_VAR NEARDATA char *invbuf = (char *) 0;
3868 STATIC_VAR NEARDATA unsigned invbufsiz = 0;
3871 let_to_name(let, unpaid, showsym)
3873 boolean unpaid, showsym;
3875 const char *ocsymfmt = " ('%c')";
3876 const int invbuf_sympadding = 8; /* arbitrary */
3877 const char *class_name;
3879 int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
3883 class_name = names[oclass];
3884 else if ((pos = index(oth_symbols, let)) != 0)
3885 class_name = oth_names[pos - oth_symbols];
3887 class_name = names[0];
3890 len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "")
3892 len = strlen(class_name) + (unpaid ? sizeof "
\96¢
\95¥
\82¢
\82Ì" : sizeof "")
3893 + (oclass ? (strlen(ocsymfmt) + invbuf_sympadding) : 0);
3894 if (len > invbufsiz) {
3896 free((genericptr_t) invbuf);
3897 invbufsiz = len + 10; /* add slop to reduce incremental realloc */
3898 invbuf = (char *) alloc(invbufsiz);
3902 Strcat(strcpy(invbuf, "Unpaid "), class_name);
3904 Strcat(strcpy(invbuf, "
\96¢
\95¥
\82¢
\82Ì"), class_name);
3906 Strcpy(invbuf, class_name);
3907 if ((oclass != 0) && showsym) {
3908 char *bp = eos(invbuf);
3909 int mlen = invbuf_sympadding - strlen(class_name);
3910 while (--mlen > 0) {
3915 Sprintf(eos(invbuf), ocsymfmt, def_oc_syms[oclass].sym);
3920 /* release the static buffer used by let_to_name() */
3925 free((genericptr_t) invbuf), invbuf = (char *) 0;
3929 /* give consecutive letters to every item in inventory (for !fixinv mode);
3930 gold is always forced to '$' slot at head of list */
3935 struct obj *obj, *prevobj, *goldobj;
3937 /* first, remove [first instance of] gold from invent, if present */
3938 prevobj = goldobj = 0;
3939 for (obj = invent; obj; prevobj = obj, obj = obj->nobj)
3940 if (obj->oclass == COIN_CLASS) {
3943 prevobj->nobj = goldobj->nobj;
3945 invent = goldobj->nobj;
3948 /* second, re-letter the rest of the list */
3949 for (obj = invent, i = 0; obj; obj = obj->nobj, i++)
3951 (i < 26) ? ('a' + i) : (i < 52) ? ('A' + i - 26) : NOINVSYM;
3952 /* third, assign gold the "letter" '$' and re-insert it at head */
3954 goldobj->invlet = GOLD_SYM;
3955 goldobj->nobj = invent;
3965 * User specifies a 'from' slot for inventory stack to move,
3966 * then a 'to' slot for its destination. Open slots and those
3967 * filled by compatible stacks are listed as likely candidates
3968 * but user can pick any inventory letter (including 'from').
3970 * to == from, 'from' has a name
3971 * All compatible items (same name or no name) are gathered
3972 * into the 'from' stack. No count is allowed.
3973 * to == from, 'from' does not have a name
3974 * All compatible items without a name are gathered into the
3975 * 'from' stack. No count is allowed. Compatible stacks with
3976 * names are left as-is.
3977 * to != from, no count
3978 * Move 'from' to 'to'. If 'to' is not empty, merge 'from'
3979 * into it if possible, otherwise swap it with the 'from' slot.
3980 * to != from, count given
3981 * If the user specifies a count when choosing the 'from' slot,
3982 * and that count is less than the full size of the stack,
3983 * then the stack will be split. The 'count' portion is moved
3984 * to the destination, and the only candidate for merging with
3985 * it is the stack already at the 'to' slot, if any. When the
3986 * destination is non-empty but won't merge, whatever is there
3987 * will be moved to an open slot; if there isn't any open slot
3988 * available, the adjustment attempt fails.
3990 * To minimize merging for 'from == to', unnamed stacks will
3991 * merge with named 'from' but named ones won't merge with
3992 * unnamed 'from'. Otherwise attempting to collect all unnamed
3993 * stacks would lump the first compatible named stack with them
3994 * and give them its name.
3996 * To maximize merging for 'from != to', compatible stacks will
3997 * merge when either lacks a name (or they already have the same
3998 * name). When no count is given and one stack has a name and
3999 * the other doesn't, the merged result will have that name.
4000 * However, when splitting results in a merger, the name of the
4001 * destination overrides that of the source, even if destination
4002 * is unnamed and source is named.
4005 doorganize() /* inventory organizer by Del Lamb */
4007 struct obj *obj, *otmp, *splitting, *bumped;
4008 int ix, cur, trycnt, goldstacks;
4011 #define GOLD_OFFSET 1
4012 #define OVRFLW_INDX (GOLD_OFFSET + 52) /* past gold and 2*26 letters */
4013 char lets[1 + 52 + 1 + 1]; /* room for '$a-zA-Z#\0' */
4015 char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
4016 char *objname, *otmpname;
4017 const char *adj_type;
4018 boolean ever_mind = FALSE, collect;
4022 You("aren't carrying anything to adjust.");
4024 You("
\8f\87\8f\98\82ð
\95Ï
\82¦
\82é
\82à
\82Ì
\82ð
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
4028 if (!flags.invlet_constant)
4030 /* get object the user wants to organize (the 'from' slot) */
4031 allowall[0] = ALLOW_COUNT;
4032 allowall[1] = ALL_CLASSES;
4034 for (goldstacks = 0, otmp = invent; otmp; otmp = otmp->nobj) {
4035 /* gold should never end up in a letter slot, nor should two '$'
4036 slots occur, but if they ever do, allow #adjust to handle them
4037 (in the past, things like this have happened, usually due to
4038 bknown being erroneously set on one stack, clear on another;
4039 object merger isn't fooled by that anymore) */
4040 if (otmp->oclass == COIN_CLASS
4041 && (otmp->invlet != GOLD_SYM || ++goldstacks > 1)) {
4042 allowall[1] = COIN_CLASS;
4043 allowall[2] = ALL_CLASSES;
4048 if (!(obj = getobj(allowall, "adjust")))
4051 /* figure out whether user gave a split count to getobj() */
4052 splitting = bumped = 0;
4053 for (otmp = invent; otmp; otmp = otmp->nobj)
4054 if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
4055 if (otmp->invlet == obj->invlet)
4060 /* initialize the list with all lower and upper case letters */
4061 lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' ';
4062 for (ix = GOLD_OFFSET, let = 'a'; let <= 'z';)
4064 for (let = 'A'; let <= 'Z';)
4066 lets[OVRFLW_INDX] = ' ';
4067 lets[sizeof lets - 1] = '\0';
4068 /* for floating inv letters, truncate list after the first open slot */
4069 if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
4070 lets[ix + (splitting ? 0 : 1)] = '\0';
4072 /* blank out all the letters currently in use in the inventory
4073 except those that will be merged with the selected object */
4074 for (otmp = invent; otmp; otmp = otmp->nobj)
4075 if (otmp != obj && !mergable(otmp, obj)) {
4077 if (let >= 'a' && let <= 'z')
4078 lets[GOLD_OFFSET + let - 'a'] = ' ';
4079 else if (let >= 'A' && let <= 'Z')
4080 lets[GOLD_OFFSET + let - 'A' + 26] = ' ';
4081 /* overflow defaults to off, but it we find a stack using that
4082 slot, switch to on -- the opposite of normal invlet handling */
4083 else if (let == NOINVSYM)
4084 lets[OVRFLW_INDX] = NOINVSYM;
4087 /* compact the list by removing all the blanks */
4088 for (ix = cur = 0; lets[ix]; ix++)
4089 if (lets[ix] != ' ' && cur++ < ix)
4090 lets[cur - 1] = lets[ix];
4092 /* and by dashing runs of letters */
4096 /* get 'to' slot to use as destination */
4098 Sprintf(qbuf, "Adjust letter to what [%s]%s?", lets,
4099 invent ? " (? see used letters)" : "");
4101 Sprintf(qbuf, "
\82Ç
\82Ì
\95¶
\8e\9a\82É
\92²
\90®
\82µ
\82Ü
\82·
\82©[%s]%s
\81H", lets,
4102 invent ? " (?
\82Å
\8eg
\82Á
\82Ä
\82¢
\82é
\95¶
\8e\9a\82ð
\95\
\8e¦)" : "");
4104 for (trycnt = 1; ; ++trycnt) {
4105 let = yn_function(qbuf, (char *) 0, '\0');
4106 if (let == '?' || let == '*') {
4107 let = display_used_invlets(splitting ? obj->invlet : 0);
4113 if (index(quitchars, let)
4114 /* adjusting to same slot is meaningful since all
4115 compatible stacks get collected along the way,
4116 but splitting to same slot is not */
4117 || (splitting && let == obj->invlet)) {
4120 (void) merged(&splitting, &obj);
4124 } else if (let == GOLD_SYM && obj->oclass != COIN_CLASS) {
4126 pline("Only gold coins may be moved into the '%c' slot.",
4129 pline("'%c'
\82É
\82Å
\82«
\82é
\82Ì
\82Í
\8bà
\89Ý
\82¾
\82¯
\81D",
4135 /* letter() classifies '@' as one; compactify() can put '-' in lets;
4136 the only thing of interest that index() might find is '$' or '#'
4137 since letter() catches everything else that we put into lets[] */
4138 if ((letter(let) && let != '@') || (index(lets, let) && let != '-'))
4139 break; /* got one */
4143 pline("Select an inventory slot letter."); /* else try again */
4145 pline("
\8e\9d\82¿
\95¨
\82Ì
\95¶
\8e\9a\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢
\81D");
4149 collect = (let == obj->invlet);
4150 /* change the inventory and print the resulting item */
4152 adj_type = collect ? "Collecting" : !splitting ? "Moving:" : "Splitting:";
4154 adj_type = collect ? "
\82ð
\8fW
\82ß
\82½
\81D" : !splitting ? "
\82ð
\88Ú
\93®
\82µ
\82½
\81D" : "
\82ð
\95ª
\8a\84\82µ
\82½
\81D";
4157 * don't use freeinv/addinv to avoid double-touching artifacts,
4158 * dousing lamps, losing luck, cursing loadstone, etc.
4160 extract_nobj(obj, &invent);
4162 for (otmp = invent; otmp;) {
4163 /* it's tempting to pull this outside the loop, but merged() could
4164 free ONAME(obj) [via obfree()] and replace it with ONAME(otmp) */
4165 objname = has_oname(obj) ? ONAME(obj) : (char *) 0;
4168 /* Collecting: #adjust an inventory stack into its same slot;
4169 keep it there and merge other compatible stacks into it.
4170 Traditional inventory behavior is to merge unnamed stacks
4171 with compatible named ones; we only want that if it is
4172 the 'from' stack (obj) with a name and candidate (otmp)
4173 without one, not unnamed 'from' with named candidate. */
4174 otmpname = has_oname(otmp) ? ONAME(otmp) : (char *) 0;
4175 if ((!otmpname || (objname && !strcmp(objname, otmpname)))
4176 && merged(&otmp, &obj)) {
4178 adj_type = "Merging:";
4180 adj_type = "
\82ð
\8d\87\82í
\82¹
\82½
\81D";
4183 extract_nobj(obj, &invent);
4184 continue; /* otmp has already been updated */
4186 } else if (otmp->invlet == let) {
4187 /* Moving or splitting: don't merge extra compatible stacks.
4188 Found 'otmp' in destination slot; merge if compatible,
4189 otherwise bump whatever is there to an open slot. */
4192 adj_type = "Swapping:";
4194 adj_type = "
\82ð
\8cð
\8a·
\82µ
\82½
\81D";
4195 otmp->invlet = obj->invlet;
4197 /* strip 'from' name if it has one */
4198 if (objname && !obj->oartifact)
4199 ONAME(obj) = (char *) 0;
4200 if (!mergable(otmp, obj)) {
4201 /* won't merge; put 'from' name back */
4203 ONAME(obj) = objname;
4205 /* will merge; discard 'from' name */
4207 free((genericptr_t) objname), objname = 0;
4210 if (merged(&otmp, &obj)) {
4212 adj_type = "Splitting and merging:";
4214 adj_type = "
\82ð
\95ª
\8a\84\82µ
\82Ä
\8d\87\82í
\82¹
\82½
\81D";
4216 extract_nobj(obj, &invent);
4217 } else if (inv_cnt(FALSE) >= 52) {
4218 (void) merged(&splitting, &obj); /* undo split */
4219 /* "knapsack cannot accommodate any more items" */
4221 Your("pack is too full.");
4223 Your("
\8e\9d\82¿
\95¨
\82Í
\88ê
\94t
\82¾
\81D");
4227 extract_nobj(bumped, &invent);
4229 } /* moving vs splitting */
4230 break; /* not collecting and found 'to' slot */
4235 /* inline addinv; insert loose object at beginning of inventory */
4238 obj->where = OBJ_INVENT;
4242 /* splitting the 'from' stack is causing an incompatible
4243 stack in the 'to' slot to be moved into an open one;
4244 we need to do another inline insertion to inventory */
4245 assigninvlet(bumped);
4246 bumped->nobj = invent;
4247 bumped->where = OBJ_INVENT;
4252 /* messages deferred until inventory has been fully reestablished */
4253 prinv(adj_type, obj, 0L);
4256 prinv("Moving:", bumped, 0L);
4258 prinv("
\88Ú
\93®:", bumped, 0L);
4260 clear_splitobjs(); /* reset splitobj context */
4265 /* common to display_minventory and display_cinventory */
4267 invdisp_nothing(hdr, txt)
4268 const char *hdr, *txt;
4272 menu_item *selected;
4275 win = create_nhwindow(NHW_MENU);
4277 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr,
4279 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
4280 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
4281 end_menu(win, (char *) 0);
4282 if (select_menu(win, PICK_NONE, &selected) > 0)
4283 free((genericptr_t) selected);
4284 destroy_nhwindow(win);
4288 /* query_objlist callback: return things that are worn or wielded */
4290 worn_wield_only(obj)
4294 /* check for things that *are* worn or wielded (only used for monsters,
4295 so we don't worry about excluding W_CHAIN, W_ARTI and the like) */
4296 return (boolean) (obj->owornmask != 0L);
4298 /* this used to check for things that *might* be worn or wielded,
4299 but that's not particularly interesting */
4300 if (is_weptool(obj) || is_wet_towel(obj) || obj->otyp == MEAT_RING)
4302 return (boolean) (obj->oclass == WEAPON_CLASS
4303 || obj->oclass == ARMOR_CLASS
4304 || obj->oclass == AMULET_CLASS
4305 || obj->oclass == RING_CLASS);
4310 * Display a monster's inventory.
4311 * Returns a pointer to the object from the monster's inventory selected
4312 * or NULL if nothing was selected.
4314 * By default, only worn and wielded items are displayed. The caller
4315 * can pick one. Modifier flags are:
4317 * PICK_NONE, PICK_ONE - standard menu control
4318 * PICK_ANY - allowed, but we only return a single object
4319 * MINV_NOLET - nothing selectable
4320 * MINV_ALL - display all inventory
4323 display_minventory(mon, dflags, title)
4324 register struct monst *mon;
4331 menu_item *selected = 0;
4332 int do_all = (dflags & MINV_ALL) != 0,
4333 incl_hero = (do_all && u.uswallow && mon == u.ustuck),
4334 have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
4335 pickings = (dflags & MINV_PICKMASK);
4338 Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
4339 do_all ? "possessions" : "armament");
4341 Sprintf(tmp, "%s
\82Ì%s
\81F", Monnam(mon),
4342 do_all ? "
\8e\9d\82¿
\95¨" : "
\91\95\94õ");
4345 if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
4346 /* Fool the 'weapon in hand' routine into
4347 * displaying 'weapon in claw', etc. properly.
4349 youmonst.data = mon->data;
4351 n = query_objlist(title ? title : tmp, &(mon->minvent),
4352 (INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0)),
4353 &selected, pickings,
4354 do_all ? allow_all : worn_wield_only);
4358 invdisp_nothing(title ? title : tmp, "(none)");
4360 invdisp_nothing(title ? title : tmp, "(
\89½
\82à
\82È
\82¢)");
4365 ret = selected[0].item.a_obj;
4366 free((genericptr_t) selected);
4368 ret = (struct obj *) 0;
4373 * Display the contents of a container in inventory style.
4374 * Currently, this is only used for statues, via wand of probing.
4377 display_cinventory(obj)
4378 register struct obj *obj;
4383 menu_item *selected = 0;
4386 (void) safe_qbuf(qbuf, "Contents of ", ":", obj, doname, ansimpleoname,
4389 (void) safe_qbuf(qbuf, "", "
\82Ì
\92\86\90g
\81F", obj, doname, ansimpleoname,
4394 n = query_objlist(qbuf, &(obj->cobj), INVORDER_SORT,
4395 &selected, PICK_NONE, allow_all);
4398 invdisp_nothing(qbuf, "(empty)");
4400 invdisp_nothing(qbuf, "(
\8bó
\82Á
\82Û)");
4404 ret = selected[0].item.a_obj;
4405 free((genericptr_t) selected);
4407 ret = (struct obj *) 0;
4412 /* query objlist callback: return TRUE if obj is at given location */
4419 return (obj->ox == only.x && obj->oy == only.y);
4423 * Display a list of buried items in inventory style. Return a non-zero
4424 * value if there were items at that spot.
4426 * Currently, this is only used with a wand of probing zapped downwards.
4429 display_binventory(x, y, as_if_seen)
4434 menu_item *selected = 0;
4437 /* count # of objects here */
4438 for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
4439 if (obj->ox == x && obj->oy == y) {
4449 if (query_objlist("Things that are buried here:",
4451 if (query_objlist("
\82±
\82±
\82É
\96\84\82ß
\82ç
\82ê
\82Ä
\82¢
\82é
\82à
\82Ì
\81F",
4452 &level.buriedobjlist, INVORDER_SORT,
4453 &selected, PICK_NONE, only_here) > 0)
4454 free((genericptr_t) selected);
4455 only.x = only.y = 0;