1 /* NetHack 3.6 invent.c $NHDT-Date: 1447576348 2015/11/15 08:32:28 $ $NHDT-Branch: master $:$NHDT-Revision: 1.179 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
8 /* JNetHack may be freely redistributed. See license for details. */
13 #define CONTAINED_SYM '>' /* designator for inside a container */
15 STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (struct obj *, struct obj *));
16 STATIC_DCL void NDECL(reorder_invent);
17 STATIC_DCL boolean FDECL(mergable, (struct obj *, struct obj *));
18 STATIC_DCL void FDECL(noarmor, (BOOLEAN_P));
19 STATIC_DCL void FDECL(invdisp_nothing, (const char *, const char *));
20 STATIC_DCL boolean FDECL(worn_wield_only, (struct obj *));
21 STATIC_DCL boolean FDECL(only_here, (struct obj *));
22 STATIC_DCL void FDECL(compactify, (char *));
23 STATIC_DCL boolean FDECL(splittable, (struct obj *));
24 STATIC_DCL boolean FDECL(taking_off, (const char *));
25 STATIC_DCL boolean FDECL(putting_on, (const char *));
26 STATIC_PTR int FDECL(ckunpaid, (struct obj *));
27 STATIC_PTR int FDECL(ckvalidcat, (struct obj *));
28 STATIC_PTR char *FDECL(safeq_xprname, (struct obj *));
29 STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
30 STATIC_DCL char FDECL(display_pickinv, (const char *, BOOLEAN_P, long *));
31 STATIC_DCL char FDECL(display_used_invlets, (CHAR_P));
32 STATIC_DCL void FDECL(tally_BUCX,
33 (struct obj *, int *, int *, int *, int *, int *));
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 STATIC_OVL int CFDECLSPEC
55 sortloot_cmp(obj1, obj2)
62 /* Sort object names in lexicographical order, ignoring quantity. */
63 int name_cmp = strcmpi(cxname_singular(obj1), cxname_singular(obj2));
69 /* Sort by BUC. Map blessed to 4, uncursed to 2, cursed to 1, and unknown
72 ? (obj1->blessed << 2)
73 + ((!obj1->blessed && !obj1->cursed) << 1) + obj1->cursed
76 ? (obj2->blessed << 2)
77 + ((!obj2->blessed && !obj2->cursed) << 1) + obj2->cursed
80 return val2 - val1; /* Because bigger is better. */
83 /* Sort by greasing. This will put the objects in degreasing order. */
87 return val2 - val1; /* Because bigger is better. */
90 /* Sort by erosion. The effective amount is what matters. */
91 val1 = greatest_erosion(obj1);
92 val2 = greatest_erosion(obj2);
94 return val1 - val2; /* Because bigger is WORSE. */
97 /* Sort by erodeproofing. Map known-invulnerable to 1, and both
98 * known-vulnerable and unknown-vulnerability to 0, because that's how
99 * they're displayed. */
100 val1 = obj1->rknown && obj1->oerodeproof;
101 val2 = obj2->rknown && obj2->oerodeproof;
103 return val2 - val1; /* Because bigger is better. */
106 /* Sort by enchantment. Map unknown to -1000, which is comfortably below
107 * the range of ->spe. */
108 val1 = obj1->known ? obj1->spe : -1000;
109 val2 = obj2->known ? obj2->spe : -1000;
111 return val2 - val1; /* Because bigger is better. */
114 /* They're identical, as far as we're concerned,
115 but we want to force a determistic order between them. */
116 return (obj1->o_id > obj2->o_id) ? 1 : -1;
123 return (struct obj **) alloc(n * sizeof(struct obj *));
127 objarr_set(otmp, idx, oarray, dosort)
135 for (j = idx; j; j--) {
136 if (sortloot_cmp(otmp, oarray[j - 1]) > 0)
138 oarray[j] = oarray[j - 1];
148 register struct obj *otmp;
152 register struct obj *obj;
154 /* there should be at most one of these in inventory... */
155 if (otmp->oclass == COIN_CLASS) {
156 otmp->invlet = GOLD_SYM;
160 for (i = 0; i < 52; i++)
162 for (obj = invent; obj; obj = obj->nobj)
165 if ('a' <= i && i <= 'z')
166 inuse[i - 'a'] = TRUE;
167 else if ('A' <= i && i <= 'Z')
168 inuse[i - 'A' + 26] = TRUE;
169 if (i == otmp->invlet)
172 if ((i = otmp->invlet)
173 && (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
175 for (i = lastinvnr + 1; i != lastinvnr; i++) {
184 (inuse[i] ? NOINVSYM : (i < 26) ? ('a' + i) : ('A' + i - 26));
188 /* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */
189 #define inv_rank(o) ((o)->invlet ^ 040)
191 /* sort the inventory; used by addinv() and doorganize() */
195 struct obj *otmp, *prev, *next;
196 boolean need_more_sorting;
200 * We expect at most one item to be out of order, so this
201 * isn't nearly as inefficient as it may first appear.
203 need_more_sorting = FALSE;
204 for (otmp = invent, prev = 0; otmp;) {
206 if (next && inv_rank(next) < inv_rank(otmp)) {
207 need_more_sorting = TRUE;
212 otmp->nobj = next->nobj;
220 } while (need_more_sorting);
225 /* scan a list of objects to see whether another object will merge with
226 one of them; used in pickup.c when all 52 inventory slots are in use,
227 to figure out whether another object could still be picked up */
229 merge_choice(objlist, obj)
230 struct obj *objlist, *obj;
235 if (obj->otyp == SCR_SCARE_MONSTER) /* punt on these */
236 return (struct obj *) 0;
237 /* if this is an item on the shop floor, the attributes it will
238 have when carried are different from what they are now; prevent
239 that from eliciting an incorrect result from mergable() */
240 save_nocharge = obj->no_charge;
241 if (objlist == invent && obj->where == OBJ_FLOOR
242 && (shkp = shop_keeper(inside_shop(obj->ox, obj->oy))) != 0) {
245 /* A billable object won't have its `unpaid' bit set, so would
246 erroneously seem to be a candidate to merge with a similar
247 ordinary object. That's no good, because once it's really
248 picked up, it won't merge after all. It might merge with
249 another unpaid object, but we can't check that here (depends
250 too much upon shk's bill) and if it doesn't merge it would
251 end up in the '#' overflow inventory slot, so reject it now. */
252 else if (inhishop(shkp))
253 return (struct obj *) 0;
256 if (mergable(objlist, obj))
258 objlist = objlist->nobj;
260 obj->no_charge = save_nocharge;
264 /* merge obj with otmp and delete obj if types agree */
267 struct obj **potmp, **pobj;
269 register struct obj *otmp = *potmp, *obj = *pobj;
271 if (mergable(otmp, obj)) {
272 /* Approximate age: we do it this way because if we were to
273 * do it "accurately" (merge only when ages are identical)
274 * we'd wind up never merging any corpses.
275 * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
277 * Don't do the age manipulation if lit. We would need
278 * to stop the burn on both items, then merge the age,
279 * then restart the burn.
282 otmp->age = ((otmp->age * otmp->quan) + (obj->age * obj->quan))
283 / (otmp->quan + obj->quan);
285 otmp->quan += obj->quan;
286 /* temporary special case for gold objects!!!! */
287 if (otmp->oclass == COIN_CLASS)
288 otmp->owt = weight(otmp);
289 /* and puddings!!!1!!one! */
290 else if (!Is_pudding(otmp))
291 otmp->owt += obj->owt;
292 if (!has_oname(otmp) && has_oname(obj))
293 otmp = *potmp = oname(otmp, ONAME(obj));
294 obj_extract_self(obj);
296 /* really should merge the timeouts */
298 obj_merge_light_sources(obj, otmp);
300 obj_stop_timers(obj); /* follows lights */
302 /* fixup for `#adjust' merging wielded darts, daggers, &c */
303 if (obj->owornmask && carried(otmp)) {
304 long wmask = otmp->owornmask | obj->owornmask;
306 /* Both the items might be worn in competing slots;
307 merger preference (regardless of which is which):
308 primary weapon + alternate weapon -> primary weapon;
309 primary weapon + quiver -> primary weapon;
310 alternate weapon + quiver -> alternate weapon.
311 (Prior to 3.3.0, it was not possible for the two
312 stacks to be worn in different slots and `obj'
313 didn't need to be unworn when merging.) */
316 else if (wmask & W_SWAPWEP)
318 else if (wmask & W_QUIVER)
321 impossible("merging strangely worn items (%lx)", wmask);
322 wmask = otmp->owornmask;
324 if ((otmp->owornmask & ~wmask) != 0L)
326 setworn(otmp, wmask);
329 /* (this should not be necessary, since items
330 already in a monster's inventory don't ever get
331 merged into other objects [only vice versa]) */
332 } else if (obj->owornmask && mcarried(otmp)) {
333 if (obj == MON_WEP(otmp->ocarry)) {
334 MON_WEP(otmp->ocarry) = otmp;
335 otmp->owornmask = W_WEP;
340 /* handle puddings a bit differently; absorption will
341 * free the other object automatically so we can just
342 * return out from here. */
343 if (Is_pudding(obj)) {
344 pudding_merge_message(otmp, obj);
345 obj_absorb(potmp, pobj);
349 obfree(obj, otmp); /* free(obj), bill->otmp */
356 * Adjust hero intrinsics as if this object was being added to the hero's
357 * inventory. Called _before_ the object has been added to the hero's
360 * This is called when adding objects to the hero's inventory normally (via
361 * addinv) or when an object in the hero's inventory has been polymorphed
364 * It may be valid to merge this code with with addinv_core2().
370 if (obj->oclass == COIN_CLASS) {
372 } else if (obj->otyp == AMULET_OF_YENDOR) {
374 impossible("already have amulet?");
376 u.uachieve.amulet = 1;
377 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
379 impossible("already have candelabrum?");
381 u.uachieve.menorah = 1;
382 } else if (obj->otyp == BELL_OF_OPENING) {
384 impossible("already have silver bell?");
387 } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
389 impossible("already have the book?");
392 } else if (obj->oartifact) {
393 if (is_quest_artifact(obj)) {
394 if (u.uhave.questart)
395 impossible("already have quest artifact?");
396 u.uhave.questart = 1;
399 set_artifact_intrinsic(obj, 1, W_ART);
401 if (obj->otyp == LUCKSTONE && obj->record_achieve_special) {
402 u.uachieve.mines_luckstone = 1;
403 obj->record_achieve_special = 0;
404 } else if ((obj->otyp == AMULET_OF_REFLECTION
405 || obj->otyp == BAG_OF_HOLDING)
406 && obj->record_achieve_special) {
407 u.uachieve.finish_sokoban = 1;
408 obj->record_achieve_special = 0;
413 * Adjust hero intrinsics as if this object was being added to the hero's
414 * inventory. Called _after_ the object has been added to the hero's
417 * This is called when adding objects to the hero's inventory normally (via
418 * addinv) or when an object in the hero's inventory has been polymorphed
425 if (confers_luck(obj)) {
426 /* new luckstone must be in inventory by this point
427 * for correct calculation */
433 * Add obj to the hero's inventory. Make sure the object is "free".
434 * Adjust hero attributes as necessary.
440 struct obj *otmp, *prev;
441 int saved_otyp = (int) obj->otyp; /* for panic */
443 if (obj->where != OBJ_FREE)
444 panic("addinv: obj not free");
445 /* normally addtobill() clears no_charge when items in a shop are
446 picked up, but won't do so if the shop has become untended */
447 obj->no_charge = 0; /* should not be set in hero's invent */
448 if (Has_contents(obj))
449 picked_container(obj); /* clear no_charge */
450 obj->was_thrown = 0; /* not meaningful for invent */
454 /* merge with quiver in preference to any other inventory slot
455 in case quiver and wielded weapon are both eligible; adding
456 extra to quivered stack is more useful than to wielded one */
457 if (uquiver && merged(&uquiver, &obj)) {
460 panic("addinv: null obj after quiver merge otyp=%d", saved_otyp);
463 /* merge if possible; find end of chain in the process */
464 for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj)
465 if (merged(&otmp, &obj)) {
468 panic("addinv: null obj after merge otyp=%d", saved_otyp);
471 /* didn't merge, so insert into chain */
473 if (flags.invlet_constant || !prev) {
474 obj->nobj = invent; /* insert at beginning */
476 if (flags.invlet_constant)
479 prev->nobj = obj; /* insert at end */
482 obj->where = OBJ_INVENT;
486 carry_obj_effects(obj); /* carrying affects the obj */
492 * Some objects are affected by being carried.
493 * Make those adjustments here. Called _after_ the object
494 * has been added to the hero's or monster's inventory,
495 * and after hero's intrinsics have been updated.
498 carry_obj_effects(obj)
501 /* Cursed figurines can spontaneously transform
503 if (obj->otyp == FIGURINE) {
504 if (obj->cursed && obj->corpsenm != NON_PM
505 && !dead_species(obj->corpsenm, TRUE)) {
506 attach_fig_transform_timeout(obj);
511 /* Add an item to the inventory unless we're fumbling or it refuses to be
512 * held (via touch_artifact), and give a message.
513 * If there aren't any free inventory slots, we'll drop it instead.
514 * If both success and failure messages are NULL, then we're just doing the
515 * fumbling/slot-limit checking for a silent grab. In any case,
516 * touch_artifact will print its own messages if they are warranted.
519 hold_another_object(obj, drop_fmt, drop_arg, hold_msg)
521 const char *drop_fmt, *drop_arg, *hold_msg;
526 obj->dknown = 1; /* maximize mergibility */
527 if (obj->oartifact) {
528 /* place_object may change these */
529 boolean crysknife = (obj->otyp == CRYSKNIFE);
530 int oerode = obj->oerodeproof;
531 boolean wasUpolyd = Upolyd;
533 /* in case touching this object turns out to be fatal */
534 place_object(obj, u.ux, u.uy);
536 if (!touch_artifact(obj, &youmonst)) {
537 obj_extract_self(obj); /* remove it from the floor */
538 dropy(obj); /* now put it back again :-) */
540 } else if (wasUpolyd && !Upolyd) {
541 /* loose your grip if you revert your form */
543 pline(drop_fmt, drop_arg);
544 obj_extract_self(obj);
548 obj_extract_self(obj);
550 obj->otyp = CRYSKNIFE;
551 obj->oerodeproof = oerode;
556 pline(drop_fmt, drop_arg);
559 long oquan = obj->quan;
560 int prev_encumbr = near_capacity(); /* before addinv() */
562 /* encumbrance only matters if it would now become worse
563 than max( current_value, stressed ) */
564 if (prev_encumbr < MOD_ENCUMBER)
565 prev_encumbr = MOD_ENCUMBER;
566 /* addinv() may redraw the entire inventory, overwriting
567 drop_arg when it comes from something like doname() */
569 drop_arg = strcpy(buf, drop_arg);
572 if (inv_cnt(FALSE) > 52 || ((obj->otyp != LOADSTONE || !obj->cursed)
573 && near_capacity() > prev_encumbr)) {
575 pline(drop_fmt, drop_arg);
576 /* undo any merge which took place */
577 if (obj->quan > oquan)
578 obj = splitobj(obj, oquan);
581 if (flags.autoquiver && !uquiver && !obj->owornmask
582 && (is_missile(obj) || ammo_and_launcher(obj, uwep)
583 || ammo_and_launcher(obj, uswapwep)))
585 if (hold_msg || drop_fmt)
586 prinv(hold_msg, obj, oquan);
592 /* useup() all of an item regardless of its quantity */
599 obfree(obj, (struct obj *) 0); /* deletes contents also */
604 register struct obj *obj;
606 /* Note: This works correctly for containers because they (containers)
608 if (obj->quan > 1L) {
609 obj->in_use = FALSE; /* no longer in use */
611 obj->owt = weight(obj);
618 /* use one charge from an item and possibly incur shop debt for it */
620 consume_obj_charge(obj, maybe_unpaid)
622 boolean maybe_unpaid; /* false if caller handles shop billing */
632 * Adjust hero's attributes as if this object was being removed from the
633 * hero's inventory. This should only be called from freeinv() and
634 * where we are polymorphing an object already in the hero's inventory.
636 * Should think of a better name...
642 if (obj->oclass == COIN_CLASS) {
645 } else if (obj->otyp == AMULET_OF_YENDOR) {
647 impossible("don't have amulet?");
649 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
650 if (!u.uhave.menorah)
651 impossible("don't have candelabrum?");
653 } else if (obj->otyp == BELL_OF_OPENING) {
655 impossible("don't have silver bell?");
657 } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
659 impossible("don't have the book?");
661 } else if (obj->oartifact) {
662 if (is_quest_artifact(obj)) {
663 if (!u.uhave.questart)
664 impossible("don't have quest artifact?");
665 u.uhave.questart = 0;
667 set_artifact_intrinsic(obj, 0, W_ART);
670 if (obj->otyp == LOADSTONE) {
672 } else if (confers_luck(obj)) {
675 } else if (obj->otyp == FIGURINE && obj->timed) {
676 (void) stop_timer(FIG_TRANSFORM, obj_to_any(obj));
680 /* remove an object from the hero's inventory */
683 register struct obj *obj;
685 extract_nobj(obj, &invent);
694 struct obj *otmp, *otmp2;
696 for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
699 /* after unpunish(), or might get deallocated chain */
700 otmp2 = otmp->nexthere;
707 /* destroy object in fobj chain (if unpaid, it remains on the bill) */
710 register struct obj *obj;
714 if (obj->otyp == AMULET_OF_YENDOR
715 || obj->otyp == CANDELABRUM_OF_INVOCATION
716 || obj->otyp == BELL_OF_OPENING
717 || obj->otyp == SPE_BOOK_OF_THE_DEAD) {
718 /* player might be doing something stupid, but we
719 * can't guarantee that. assume special artifacts
720 * are indestructible via drawbridges, and exploding
721 * chests, and golem creation, and ...
725 update_map = (obj->where == OBJ_FLOOR);
726 obj_extract_self(obj);
728 newsym(obj->ox, obj->oy);
729 obfree(obj, (struct obj *) 0); /* frees contents also */
732 /* try to find a particular type of object at designated map location */
738 register struct obj *otmp;
740 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
741 if (otmp->otyp == otyp)
747 /* sobj_at(&c) traversal -- find next object of specified type */
749 nxtobj(obj, type, by_nexthere)
754 register struct obj *otmp;
756 otmp = obj; /* start with the object after this one */
758 otmp = !by_nexthere ? otmp->nobj : otmp->nexthere;
761 } while (otmp->otyp != type);
770 register struct obj *otmp;
772 for (otmp = invent; otmp; otmp = otmp->nobj)
773 if (otmp->otyp == type)
775 return (struct obj *) 0;
778 /* Fictional and not-so-fictional currencies.
779 * http://concord.wikia.com/wiki/List_of_Fictional_Currencies
781 static const char *const currencies[] = {
782 "Altarian Dollar", /* The Hitchhiker's Guide to the Galaxy */
783 "Ankh-Morpork Dollar", /* Discworld */
784 "auric", /* The Domination of Draka */
785 "buckazoid", /* Space Quest */
786 "cirbozoid", /* Starslip */
787 "credit chit", /* Deus Ex */
788 "cubit", /* Battlestar Galactica */
789 "Flanian Pobble Bead", /* The Hitchhiker's Guide to the Galaxy */
790 "fretzer", /* Jules Verne */
791 "imperial credit", /* Star Wars */
792 "Hong Kong Luna Dollar", /* The Moon is a Harsh Mistress */
793 "kongbuck", /* Snow Crash */
794 "nanite", /* System Shock 2 */
795 "quatloo", /* Star Trek, Sim City */
796 "simoleon", /* Sim City */
797 "solari", /* Spaceballs */
798 "spacebuck", /* Spaceballs */
799 "sporebuck", /* Spore */
800 "Triganic Pu", /* The Hitchhiker's Guide to the Galaxy */
801 "woolong", /* Cowboy Bebop */
802 "zorkmid", /* Zork, NetHack */
812 res = Hallucination ? currencies[rn2(SIZE(currencies))] : "zorkmid";
814 res = makeplural(res);
816 res = Hallucination ? currencies[rn2(SIZE(currencies))] : "
\83S
\81[
\83\8b\83h";
824 register struct obj *otmp;
826 for (otmp = invent; otmp; otmp = otmp->nobj)
827 if (otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
836 register struct obj *otmp;
838 for (otmp = invent; otmp; otmp = otmp->nobj)
839 if (otmp->otyp == SPE_NOVEL)
841 return (struct obj *) 0;
847 register struct obj *objchn;
852 if (objchn->o_id == id)
854 if (Has_contents(objchn) && (temp = o_on(id, objchn->cobj)))
856 objchn = objchn->nobj;
858 return (struct obj *) 0;
863 register struct obj *obj;
866 register struct obj *otmp;
868 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
878 register struct obj *obj = level.objects[x][y];
881 if (obj->oclass == COIN_CLASS)
885 return (struct obj *) 0;
888 /* compact a string of inventory letters by dashing runs of letters */
893 register int i1 = 1, i2 = 1;
894 register char ilet, ilet1, ilet2;
898 buf[++i2] = buf[++i1];
901 if (ilet == ilet1 + 1) {
902 if (ilet1 == ilet2 + 1)
903 buf[i2 - 1] = ilet1 = '-';
904 else if (ilet2 == '-') {
905 buf[i2 - 1] = ++ilet1;
910 } else if (ilet == NOINVSYM) {
911 /* compact three or more consecutive '#'
912 characters into "#-#" */
913 if (i2 >= 2 && buf[i2 - 2] == NOINVSYM && buf[i2 - 1] == NOINVSYM)
915 else if (i2 >= 3 && buf[i2 - 3] == NOINVSYM && buf[i2 - 2] == '-'
916 && buf[i2 - 1] == NOINVSYM)
921 buf[++i2] = buf[++i1];
926 /* some objects shouldn't be split when count given to getobj or askchain */
931 return !((obj->otyp == LOADSTONE && obj->cursed)
932 || (obj == uwep && welded(uwep)));
935 /* match the prompt for either 'T' or 'R' command */
940 return !strcmp(action, "take off") || !strcmp(action, "remove");
943 /* match the prompt for either 'W' or 'P' command */
948 return !strcmp(action, "wear") || !strcmp(action, "put on");
953 * struct obj *xxx: object to do something with.
954 * (struct obj *) 0 error return: no object.
955 * &zeroobj explicitly no object (as in w-).
956 !!!! test if gold can be used in unusual ways (eaten etc.)
957 !!!! may be able to remove "usegold"
960 ** word
\82É
\82Í
\89p
\8cê
\82Å
\93®
\8e\8c\82ª
\93ü
\82é
\81D
962 **
\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
963 **
\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
968 register const char *let, *word;
970 register struct obj *otmp;
972 char buf[BUFSZ], qbuf[QBUFSZ];
973 char lets[BUFSZ], altlets[BUFSZ], *ap;
974 register int foo = 0;
975 register char *bp = buf;
976 xchar allowcnt = 0; /* 0, 1 or 2 */
977 struct obj *firstobj = invent;
978 boolean usegold = FALSE; /* can't use gold because its illegal */
979 boolean allowall = FALSE;
980 boolean allownone = FALSE;
981 boolean useboulder = FALSE;
992 struct trans_verb *tv = trans_verb(word);
996 joshi = tv->particle;
998 if (*let == ALLOW_COUNT)
1000 if (*let == COIN_CLASS)
1001 let++, usegold = TRUE;
1003 /* Equivalent of an "ugly check" for gold */
1004 if (usegold && !strcmp(word, "eat")
1005 && (!metallivorous(youmonst.data)
1006 || youmonst.data == &mons[PM_RUST_MONSTER]))
1009 if (*let == ALL_CLASSES)
1010 let++, allowall = TRUE;
1011 if (*let == ALLOW_NONE)
1012 let++, allownone = TRUE;
1013 /* "ugly check" for reading fortune cookies, part 1.
1014 * The normal 'ugly check' keeps the object on the inventory list.
1015 * We don't want to do that for shirts/cookies, so the check for
1016 * them is handled a bit differently (and also requires that we set
1017 * allowall in the caller).
1019 if (allowall && !strcmp(word, "read"))
1022 /* another ugly check: show boulders (not statues) */
1023 if (*let == WEAPON_CLASS && !strcmp(word, "throw")
1024 && throws_rocks(youmonst.data))
1029 if (bp > buf && bp[-1] == '-')
1033 if (!flags.invlet_constant)
1036 for (otmp = firstobj; otmp; otmp = otmp->nobj) {
1037 if (&bp[foo] == &buf[sizeof buf - 1]
1038 || ap == &altlets[sizeof altlets - 1]) {
1039 /* we must have a huge number of NOINVSYM items somehow */
1040 impossible("getobj: inventory overflow");
1044 if (!*let || index(let, otmp->oclass)
1045 || (usegold && otmp->invlet == GOLD_SYM)
1046 || (useboulder && otmp->otyp == BOULDER)) {
1047 register int otyp = otmp->otyp;
1048 bp[foo++] = otmp->invlet;
1050 /* clang-format off */
1052 /* ugly check: remove inappropriate things */
1054 (taking_off(word) /* exclude if not worn */
1055 && !(otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
1056 || (putting_on(word) /* exclude if already worn */
1057 && (otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
1058 #if 0 /* 3.4.1 -- include currently wielded weapon among 'wield' choices */
1059 || (!strcmp(word, "wield")
1060 && (otmp->owornmask & W_WEP))
1062 || (!strcmp(word, "ready") /* exclude if wielded */
1063 && (otmp == uwep || (otmp == uswapwep && u.twoweap)))
1064 || ((!strcmp(word, "dip") || !strcmp(word, "grease"))
1065 && inaccessible_equipment(otmp, (const char *) 0, FALSE))
1070 /* Second ugly check; unlike the first it won't trigger an
1071 * "else" in "you don't have anything else to ___".
1075 && ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING)
1076 || (otmp->oclass == TOOL_CLASS && otyp != BLINDFOLD
1077 && otyp != TOWEL && otyp != LENSES)))
1078 || (!strcmp(word, "wield")
1079 && (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
1080 || (!strcmp(word, "eat") && !is_edible(otmp))
1081 || (!strcmp(word, "sacrifice")
1082 && (otyp != CORPSE && otyp != AMULET_OF_YENDOR
1083 && otyp != FAKE_AMULET_OF_YENDOR))
1084 || (!strcmp(word, "write with")
1085 && (otmp->oclass == TOOL_CLASS
1086 && otyp != MAGIC_MARKER && otyp != TOWEL))
1087 || (!strcmp(word, "tin")
1088 && (otyp != CORPSE || !tinnable(otmp)))
1089 || (!strcmp(word, "rub")
1090 && ((otmp->oclass == TOOL_CLASS && otyp != OIL_LAMP
1091 && otyp != MAGIC_LAMP && otyp != BRASS_LANTERN)
1092 || (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
1093 || (!strcmp(word, "use or apply")
1094 /* Picks, axes, pole-weapons, bullwhips */
1095 && ((otmp->oclass == WEAPON_CLASS
1096 && !is_pick(otmp) && !is_axe(otmp)
1097 && !is_pole(otmp) && otyp != BULLWHIP)
1098 || (otmp->oclass == POTION_CLASS
1099 /* only applicable potion is oil, and it will only
1100 be offered as a choice when already discovered */
1101 && (otyp != POT_OIL || !otmp->dknown
1102 || !objects[POT_OIL].oc_name_known))
1103 || (otmp->oclass == FOOD_CLASS
1104 && otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF)
1105 || (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
1106 || (!strcmp(word, "invoke")
1108 && !objects[otyp].oc_unique
1109 && (otyp != FAKE_AMULET_OF_YENDOR || otmp->known)
1110 && otyp != CRYSTAL_BALL /* synonym for apply */
1111 /* note: presenting the possibility of invoking non-artifact
1112 mirrors and/or lamps is simply a cruel deception... */
1114 && otyp != MAGIC_LAMP
1115 && (otyp != OIL_LAMP /* don't list known oil lamp */
1116 || (otmp->dknown && objects[OIL_LAMP].oc_name_known)))
1117 || (!strcmp(word, "untrap with")
1118 && ((otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE)
1119 || (otmp->oclass == POTION_CLASS
1120 /* only applicable potion is oil, and it will only
1121 be offered as a choice when already discovered */
1122 && (otyp != POT_OIL || !otmp->dknown
1123 || !objects[POT_OIL].oc_name_known))))
1124 || (!strcmp(word, "tip") && !Is_container(otmp)
1125 /* include horn of plenty if sufficiently discovered */
1126 && (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown
1127 || !objects[HORN_OF_PLENTY].oc_name_known))
1128 || (!strcmp(word, "charge") && !is_chargeable(otmp))
1129 || (!strcmp(word, "call") && !objtyp_is_callable(otyp))
1133 /* Third ugly check: acceptable but not listed as likely
1134 * candidates in the prompt or in the inventory subset if
1135 * player responds with '?'.
1138 /* ugly check for unworn armor that can't be worn */
1139 (putting_on(word) && *let == ARMOR_CLASS
1140 && !canwearobj(otmp, &dummymask, FALSE))
1141 /* or armor with 'P' or 'R' or accessory with 'W' or 'T' */
1142 || ((putting_on(word) || taking_off(word))
1143 && ((*let == ARMOR_CLASS) ^ (otmp->oclass == ARMOR_CLASS)))
1144 /* or unsuitable items rubbed on known touchstone */
1145 || (!strncmp(word, "rub on the stone", 16)
1146 && *let == GEM_CLASS && otmp->dknown
1147 && objects[otyp].oc_name_known)
1148 /* suppress corpses on astral, amulets elsewhere */
1149 || (!strcmp(word, "sacrifice")
1150 /* (!astral && amulet) || (astral && !amulet) */
1151 && (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
1152 /* suppress container being stashed into */
1153 || (!strcmp(word, "stash") && !ck_bag(otmp))
1154 /* worn armor or accessory covered by cursed worn armor */
1155 || (taking_off(word)
1156 && inaccessible_equipment(otmp, (const char *) 0, TRUE))
1158 /* acceptable but not listed as likely candidate */
1161 *ap++ = otmp->invlet;
1164 /* clang-format on */
1166 /* "ugly check" for reading fortune cookies, part 2 */
1167 if ((!strcmp(word, "read") && is_readable(otmp)))
1168 allowall = usegold = TRUE;
1173 if (foo == 0 && bp > buf && bp[-1] == ' ')
1175 Strcpy(lets, bp); /* necessary since we destroy buf */
1176 if (foo > 5) /* compactify string */
1180 if (!foo && !allowall && !allownone) {
1182 You("don't have anything %sto %s.", foox ? "else " : "", word);
1184 You("%s%s
\82à
\82Ì
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", foox ? "
\91¼
\82É" : "", jconj(jword, "
\82ê
\82é"));
1185 return (struct obj *) 0;
1190 allowcnt = 1; /* abort previous count */
1194 Sprintf(qbuf, "What do you want to %s? [*]", word);
1196 Sprintf(qbuf, "%s%s%s
\82©
\81H[*]", what, joshi, jpolite(jword));
1199 Sprintf(qbuf, "What do you want to %s? [%s or ?*]", word, buf);
1201 Sprintf(qbuf, "%s%s%s
\82©
\81H[%s or ?*]", what, joshi, jpolite(jword), buf);
1206 ilet = yn_function(qbuf, (char *) 0, '\0');
1207 if (digit(ilet) && !allowcnt) {
1209 pline("No count allowed with this command.");
1211 pline("
\82±
\82Ì
\83R
\83}
\83\93\83h
\82É
\90\94\8e\9a\82Í
\82Â
\82©
\82¦
\82È
\82¢
\81D");
1216 while (digit(ilet)) {
1217 if (ilet != '?' && ilet != '*')
1219 /* accumulate unless cnt has overflowed */
1222 cnt = 10L * cnt + (long) (ilet - '0');
1223 /* signal presence of cnt */
1224 allowcnt = (cnt >= prevcnt) ? 2 : 3;
1228 if (allowcnt == 3) {
1229 /* overflow detected; force cnt to be invalid */
1233 if (index(quitchars, ilet)) {
1236 return (struct obj *) 0;
1240 char *suf = (char *) 0;
1243 if ((bp = strstr(buf, " on the ")) != 0) {
1244 /* rub on the stone[s] */
1248 if ((bp = strstr(buf, " or ")) != 0) {
1250 bp = (rn2(2) ? buf : (bp + 4));
1253 You("mime %s something%s%s.", ing_suffix(bp), suf ? " " : "",
1256 return (allownone ? &zeroobj : (struct obj *) 0);
1258 /* since gold is now kept in inventory, we need to do processing for
1259 select-from-invent before checking whether gold has been picked */
1260 if (ilet == '?' || ilet == '*') {
1261 char *allowed_choices = (ilet == '?') ? lets : (char *) 0;
1264 if (ilet == '?' && !*lets && *altlets)
1265 allowed_choices = altlets;
1266 ilet = display_pickinv(allowed_choices, TRUE,
1267 allowcnt ? &ctmp : (long *) 0);
1270 if (allowcnt && ctmp >= 0) {
1276 if (ilet == '\033') {
1279 return (struct obj *) 0;
1281 /* they typed a letter (not a space) at the prompt */
1283 /* find the item which was picked */
1284 for (otmp = invent; otmp; otmp = otmp->nobj)
1285 if (otmp->invlet == ilet)
1287 /* some items have restrictions */
1288 if (ilet == def_oc_syms[COIN_CLASS].sym
1289 /* guard against the [hypothetical] chace of having more
1290 than one invent slot of gold and picking the non-'$' one */
1291 || (otmp && otmp->oclass == COIN_CLASS)) {
1294 You("cannot %s gold.", word);
1296 You("
\8bà
\89Ý%s%s
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D", joshi, jword);
1297 return (struct obj *) 0;
1299 /* Historic note: early Nethack had a bug which was
1300 * first reported for Larn, where trying to drop 2^32-n
1301 * gold pieces was allowed, and did interesting things
1302 * to your money supply. The LRS is the tax bureau
1305 if (allowcnt == 2 && cnt <= 0) {
1306 if (cnt < 0 || !prezero)
1309 "LRS would be very interested to know you have that much.");
1311 "
\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");
1312 return (struct obj *) 0;
1315 if (allowcnt == 2 && !strcmp(word, "throw")) {
1316 /* permit counts for throwing gold, but don't accept
1317 * counts for other things since the throw code will
1318 * split off a single item anyway */
1319 if (ilet != def_oc_syms[COIN_CLASS].sym
1320 && !(otmp && otmp->oclass == COIN_CLASS))
1322 if (cnt == 0 && prezero)
1323 return (struct obj *) 0;
1326 You("can only throw one item at a time.");
1328 You("
\93¯
\8e\9e\82É
\82½
\82
\82³
\82ñ
\82Ì
\82à
\82Ì
\82ð
\93\8a\82°
\82ç
\82ê
\82È
\82¢
\81D");
1332 context.botl = 1; /* May have changed the amount of money */
1334 /* [we used to set otmp (by finding ilet in invent) here, but
1335 that's been moved above so that otmp can be checked earlier] */
1336 /* verify the chosen object */
1339 You("don't have that object.");
1341 You("
\82»
\82ñ
\82È
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
1343 return (struct obj *) 0;
1345 } else if (cnt < 0 || otmp->quan < cnt) {
1347 You("don't have that many! You have only %ld.", otmp->quan);
1349 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);
1351 return (struct obj *) 0;
1356 if (!allowall && let && !index(let, otmp->oclass)
1357 && !(usegold && otmp->oclass == COIN_CLASS)) {
1359 silly_thing(word, otmp);
1361 silly_thing(jword, otmp);
1363 return (struct obj *) 0;
1365 if (allowcnt == 2) { /* cnt given */
1367 return (struct obj *) 0;
1368 if (cnt != otmp->quan) {
1369 /* don't split a stack of cursed loadstones */
1370 if (splittable(otmp))
1371 otmp = splitobj(otmp, cnt);
1372 else if (otmp->otyp == LOADSTONE && otmp->cursed)
1373 /* kludge for canletgo()'s can't-drop-this message */
1374 otmp->corpsenm = (int) cnt;
1381 silly_thing(word, otmp)
1385 #if 1 /* 'P','R' vs 'W','T' handling is obsolete */
1388 const char *s1, *s2, *s3, *what;
1389 int ocls = otmp->oclass, otyp = otmp->otyp;
1392 /* check for attempted use of accessory commands ('P','R') on armor
1393 and for corresponding armor commands ('W','T') on accessories */
1394 if (ocls == ARMOR_CLASS) {
1396 if (!strcmp(word, "put on"))
1397 s1 = "W", s2 = "wear", s3 = "";
1398 else if (!strcmp(word, "remove"))
1399 s1 = "T", s2 = "take", s3 = " off";
1401 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1402 s1 = "W", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1403 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1404 s1 = "T", s2 = "
\82Í
\82¸
\82·", s3 = "";
1406 } else if ((ocls == RING_CLASS || otyp == MEAT_RING)
1407 || ocls == AMULET_CLASS
1408 || (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
1410 if (!strcmp(word, "wear"))
1411 s1 = "P", s2 = "put", s3 = " on";
1412 else if (!strcmp(word, "take off"))
1413 s1 = "R", s2 = "remove", s3 = "";
1415 if (!strcmp(word, "
\90g
\82É
\82Â
\82¯
\82é"))
1416 s1 = "P", s2 = "
\90g
\82É
\82Â
\82¯
\82é", s3 = "";
1417 else if (!strcmp(word, "
\82Í
\82¸
\82·"))
1418 s1 = "R", s2 = "
\82Í
\82¸
\82·", s3 = "";
1424 /* quantity for armor and accessory objects is always 1,
1425 but some things should be referred to as plural */
1426 if (otyp == LENSES || is_gloves(otmp) || is_boots(otmp))
1430 pline("Use the '%s' command to %s %s%s.", s1, s2, what, s3);
1432 pline("
\82»
\82ê
\82ð%s
\82É
\82Í'%s'
\83R
\83}
\83\93\83h
\82ð
\8eg
\82¤
\82±
\82Æ
\81D", s2, s1);
1435 pline(silly_thing_to, word);
1442 /* use allow_category() from pickup.c */
1443 return (int) allow_category(otmp);
1450 return (otmp->unpaid || (Has_contents(otmp) && count_unpaid(otmp->cobj)));
1456 return (boolean) (uarm || uarmc || uarmf || uarmg
1457 || uarmh || uarms || uarmu);
1464 return (otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_SADDLE | W_WEAPON))
1469 /* extra xprname() input that askchain() can't pass through safe_qbuf() */
1470 STATIC_VAR struct xprnctx {
1475 /* safe_qbuf() -> short_oname() callback */
1480 return xprname(obj, (char *) 0, safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
1484 /* alternate safe_qbuf() -> short_oname() callback */
1486 safeq_shortxprname(obj)
1489 return xprname(obj, ansimpleoname(obj), safeq_xprn_ctx.let,
1490 safeq_xprn_ctx.dot, 0L, 0L);
1493 static NEARDATA const char removeables[] = { ARMOR_CLASS, WEAPON_CLASS,
1494 RING_CLASS, AMULET_CLASS,
1497 /* interactive version of getobj - used for Drop, Identify and */
1498 /* Takeoff (A). Return the number of times fn was called successfully */
1499 /* If combo is TRUE, we just use this to get a category list */
1500 /*JP CHECK: 3.4.3
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
1501 do.c:864: (result = ggetobj("drop", drop, 0, FALSE, (unsigned *)0)) < -1)
1502 do.c:925: i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
1503 do_wear.c:2538: (result = ggetobj("take off", select_off, 0, FALSE, (unsigned *)0)) < -1)
1504 do_wear.c:2586: if (ggetobj("take off", select_off, 0, TRUE, (unsigned *)0) == -2)
1505 invent.c:1782: n = ggetobj("identify", identify, id_limit, FALSE, (unsigned *)0);
1508 ggetobj(word, fn, mx, combo, resultflags)
1510 int FDECL((*fn), (OBJ_P)), mx;
1511 boolean combo; /* combination menu flag */
1512 unsigned *resultflags;
1514 int FDECL((*ckfn), (OBJ_P)) = (int FDECL((*), (OBJ_P))) 0;
1515 boolean FDECL((*filter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
1516 boolean takeoff, ident, allflag, m_seen;
1518 int oletct, iletct, unpaid, oc_of_sym;
1519 char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 5];
1520 char extra_removeables[3 + 1]; /* uwep,uswapwep,uquiver */
1521 char buf[BUFSZ], qbuf[QBUFSZ];
1523 const char *joshi = "
\82ð";
1526 const struct trans_verb *tv = trans_verb(word);
1528 joshi = tv->particle;
1533 takeoff = ident = allflag = m_seen = FALSE;
1536 You("have nothing to %s.", word);
1538 You("%s
\82à
\82Ì
\82Í
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", jcan(jword));
1541 add_valid_menu_class(0); /* reset */
1542 if (taking_off(word)) {
1545 } else if (!strcmp(word, "identify")) {
1547 filter = not_fully_identified;
1550 iletct = collect_obj_classes(ilets, invent, FALSE, filter, &itemcount);
1551 unpaid = count_unpaid(invent);
1553 if (ident && !iletct) {
1554 return -1; /* no further identifications */
1555 } else if (!takeoff && (unpaid || invent)) {
1556 ilets[iletct++] = ' ';
1558 ilets[iletct++] = 'u';
1559 if (count_buc(invent, BUC_BLESSED))
1560 ilets[iletct++] = 'B';
1561 if (count_buc(invent, BUC_UNCURSED))
1562 ilets[iletct++] = 'U';
1563 if (count_buc(invent, BUC_CURSED))
1564 ilets[iletct++] = 'C';
1565 if (count_buc(invent, BUC_UNKNOWN))
1566 ilets[iletct++] = 'X';
1568 ilets[iletct++] = 'a';
1569 } else if (takeoff && invent) {
1570 ilets[iletct++] = ' ';
1572 ilets[iletct++] = 'i';
1574 ilets[iletct++] = 'm'; /* allow menu presentation on request */
1575 ilets[iletct] = '\0';
1579 Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]", word,
1582 Sprintf(qbuf,"
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\82à
\82Ì%s%s
\82©
\81H[%s]", joshi,
1583 jpolite(jword), ilets);
1586 if (buf[0] == '\033')
1588 if (index(buf, 'i')) {
1589 if (display_inventory((char *) 0, TRUE) == '\033')
1595 extra_removeables[0] = '\0';
1597 /* arbitrary types of items can be placed in the weapon slots
1598 [any duplicate entries in extra_removeables[] won't matter] */
1600 (void) strkitten(extra_removeables, uwep->oclass);
1602 (void) strkitten(extra_removeables, uswapwep->oclass);
1604 (void) strkitten(extra_removeables, uquiver->oclass);
1608 olets[oletct = 0] = '\0';
1609 while ((sym = *ip++) != '\0') {
1612 oc_of_sym = def_char_to_objclass(sym);
1613 if (takeoff && oc_of_sym != MAXOCLASSES) {
1614 if (index(extra_removeables, oc_of_sym)) {
1615 ; /* skip rest of takeoff checks */
1616 } else if (!index(removeables, oc_of_sym)) {
1618 pline("Not applicable.");
1620 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
1622 } else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
1625 } else if (oc_of_sym == WEAPON_CLASS && !uwep && !uswapwep
1628 You("are not wielding anything.");
1630 You("
\89½
\82à
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
1632 } else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
1634 You("are not wearing rings.");
1636 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
1638 } else if (oc_of_sym == AMULET_CLASS && !uamul) {
1640 You("are not wearing an amulet.");
1642 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
1644 } else if (oc_of_sym == TOOL_CLASS && !ublindf) {
1646 You("are not wearing a blindfold.");
1648 You("
\96Ú
\89B
\82µ
\82ð
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
1653 if (oc_of_sym == COIN_CLASS && !combo) {
1655 } else if (sym == 'a') {
1657 } else if (sym == 'A') {
1658 /* same as the default */;
1659 } else if (sym == 'u') {
1660 add_valid_menu_class('u');
1662 } else if (sym == 'B') {
1663 add_valid_menu_class('B');
1665 } else if (sym == 'U') {
1666 add_valid_menu_class('U');
1668 } else if (sym == 'C') {
1669 add_valid_menu_class('C');
1671 } else if (sym == 'X') {
1672 add_valid_menu_class('X');
1674 } else if (sym == 'm') {
1676 } else if (oc_of_sym == MAXOCLASSES) {
1678 You("don't have any %c's.", sym);
1680 You("%c
\82É
\91®
\82·
\82é
\95¨
\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", sym);
1681 } else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */
1682 if (!index(olets, oc_of_sym)) {
1683 add_valid_menu_class(oc_of_sym);
1684 olets[oletct++] = oc_of_sym;
1691 return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3;
1692 } else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) {
1695 /* !!!! test gold dropping */
1696 } else if (allowgold == 2 && !oletct) {
1697 return 1; /* you dropped gold (or at least tried to) */
1700 int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
1702 * askchain() has already finished the job in this case
1703 * so set a special flag to convey that back to the caller
1704 * so that it won't continue processing.
1705 * Fix for bug C331-1 reported by Irina Rempt-Drijfhout.
1707 if (combo && allflag && resultflags)
1708 *resultflags |= ALL_FINISHED;
1714 * Walk through the chain starting at objchn and ask for all objects
1715 * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
1716 * whether the action in question (i.e., fn) has to be performed.
1717 * If allflag then no questions are asked. Max gives the max nr of
1718 * objects to be treated. Return the number of objects treated.
1720 /*JP CHECK: 3.4.3
\82Å
\82Ì
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
1721 invent.c:1512:ggetobj() int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
1722 pickup.c:2615:("nodot") if (askchain((struct obj **)¤t_container->cobj,
1723 pickup.c:2711:("nodot") (void) askchain((struct obj **)&invent,
1724 word
\82É
\82Í
\93®
\8e\8c\82ª
\89p
\8cê
\82Å
\93ü
\82é
\81B
1727 askchain(objchn, olets, allflag, fn, ckfn, mx, word)
1728 struct obj **objchn;
1729 register int allflag, mx;
1730 register const char *olets, *word; /* olets is an Obj Class char array */
1731 register int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
1733 struct obj *otmp, *otmpo;
1734 register char sym, ilet;
1735 register int cnt = 0, dud = 0, tmp;
1736 boolean takeoff, nodot, ident, take_out, put_in, first, ininv;
1737 char qbuf[QBUFSZ], qpfx[QBUFSZ];
1739 takeoff = taking_off(word);
1740 ident = !strcmp(word, "identify");
1741 take_out = !strcmp(word, "take out");
1742 put_in = !strcmp(word, "put in");
1743 nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
1744 || takeoff || take_out || put_in);
1745 ininv = (*objchn == invent);
1747 /* Changed so the askchain is interrogated in the order specified.
1748 * For example, if a person specifies =/ then first all rings will be
1749 * asked about followed by all wands -dgk
1753 if (*objchn && (*objchn)->oclass == COIN_CLASS)
1754 ilet--; /* extra iteration */
1756 * Multiple Drop can change the invent chain while it operates
1757 * (dropping a burning potion of oil while levitating creates
1758 * an explosion which can destroy inventory items), so simple
1760 * for (otmp = *objchn; otmp; otmp = otmp2) {
1761 * otmp2 = otmp->nobj;
1764 * is inadequate here. Use each object's bypass bit to keep
1765 * track of which list elements have already been processed.
1767 bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */
1768 while ((otmp = nxt_unbypassed_obj(*objchn)) != 0) {
1773 if (olets && *olets && otmp->oclass != *olets)
1775 if (takeoff && !is_worn(otmp))
1777 if (ident && !not_fully_identified(otmp))
1779 if (ckfn && !(*ckfn)(otmp))
1782 safeq_xprn_ctx.let = ilet;
1783 safeq_xprn_ctx.dot = !nodot;
1786 /* traditional_loot() skips prompting when only one
1787 class of objects is involved, so prefix the first
1788 object being queried here with an explanation why */
1789 if (take_out || put_in)
1790 Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
1795 qbuf, qpfx, "?", otmp, ininv ? safeq_xprname : doname,
1796 ininv ? safeq_shortxprname : ansimpleoname, "item");
1799 qbuf, qpfx, "
\81H", otmp, ininv ? safeq_xprname : doname,
1800 ininv ? safeq_shortxprname : ansimpleoname, "
\83A
\83C
\83e
\83\80");
1802 sym = (takeoff || ident || otmp->quan < 2L) ? nyaq(qbuf)
1809 /* Number was entered; split the object unless it corresponds
1810 to 'none' or 'all'. 2 special cases: cursed loadstones and
1811 welded weapons (eg, multiple daggers) will remain as merged
1812 unit; done to avoid splitting an object that won't be
1813 droppable (even if we're picking up rather than dropping).
1819 if (yn_number < otmp->quan && splittable(otmp))
1820 otmp = splitobj(otmp, yn_number);
1829 if (container_gone(fn)) {
1830 /* otmp caused magic bag to explode;
1831 both are now gone */
1832 otmp = 0; /* and return */
1833 } else if (otmp && otmp != otmpo) {
1834 /* split occurred, merge again */
1835 (void) merged(&otmpo, &otmp);
1848 /* special case for seffects() */
1854 if (olets && *olets && *++olets)
1856 if (!takeoff && (dud || cnt))
1858 pline("That was all.");
1860 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
1861 else if (!dud && !cnt)
1863 pline("No applicable objects.");
1865 pline("
\82»
\82ê
\82Í
\82Å
\82«
\82È
\82¢
\81D");
1867 bypass_objlist(*objchn, FALSE);
1872 * Object identification routines:
1875 /* make an object actually be identified; no display updating */
1877 fully_identify_obj(otmp)
1880 makeknown(otmp->otyp);
1881 if (otmp->oartifact)
1882 discover_artifact((xchar) otmp->oartifact);
1883 otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
1884 if (Is_container(otmp) || otmp->otyp == STATUE)
1885 otmp->cknown = otmp->lknown = 1;
1886 if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
1887 learn_egg_type(otmp->corpsenm);
1890 /* ggetobj callback routine; identify an object and give immediate feedback */
1895 fully_identify_obj(otmp);
1896 prinv((char *) 0, otmp, 0L);
1900 /* menu of unidentified objects; select and identify up to id_limit of them */
1902 menu_identify(id_limit)
1905 menu_item *pick_list;
1906 int n, i, first = 1, tryct = 5;
1908 /* assumptions: id_limit > 0 and at least one unID'd item is present */
1912 Sprintf(buf, "What would you like to identify %s?",
1913 first ? "first" : "next");
1915 Sprintf(buf, "
\82Ç
\82ê
\82ð%s
\82É
\8e¯
\95Ê
\82µ
\82Ü
\82·
\82©
\81H",
1916 first ? "
\8dÅ
\8f\89" : "
\8e\9f");
1918 n = query_objlist(buf, invent, SIGNAL_NOMENU | SIGNAL_ESCAPE
1919 | USE_INVLET | INVORDER_SORT,
1920 &pick_list, PICK_ANY, not_fully_identified);
1925 for (i = 0; i < n; i++, id_limit--)
1926 (void) identify(pick_list[i].item.a_obj);
1927 free((genericptr_t) pick_list);
1928 mark_synch(); /* Before we loop to pop open another menu */
1930 } else if (n == -2) { /* player used ESC to quit menu */
1932 } else if (n == -1) { /* no eligible items found */
1934 pline("That was all.");
1936 pline("
\82±
\82ê
\82Å
\91S
\95\94\82¾
\81D");
1938 } else if (!--tryct) { /* stop re-prompting */
1939 pline1(thats_enough_tries);
1941 } else { /* try again */
1942 pline("Choose an item; use ESC to decline.");
1947 /* dialog with user to identify a given number of items; 0 means all */
1949 identify_pack(id_limit, learning_id)
1951 boolean learning_id; /* true if we just read unknown identify scroll */
1953 struct obj *obj, *the_obj;
1957 the_obj = 0; /* if unid_cnt ends up 1, this will be it */
1958 for (obj = invent; obj; obj = obj->nobj)
1959 if (not_fully_identified(obj))
1960 ++unid_cnt, the_obj = obj;
1964 You("have already identified all %sof your possessions.",
1965 learning_id ? "the rest " : "");
1967 You("%s
\91S
\82Ä
\82Ì
\8f\8a\97L
\95¨
\82ð
\8e¯
\95Ê
\82µ
\82Ä
\82µ
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D",
1968 learning_id ? "
\8ec
\82è" : "");
1970 } else if (!id_limit || id_limit >= unid_cnt) {
1971 /* identify everything */
1972 if (unid_cnt == 1) {
1973 (void) identify(the_obj);
1975 /* TODO: use fully_identify_obj and cornline/menu/whatever here
1977 for (obj = invent; obj; obj = obj->nobj)
1978 if (not_fully_identified(obj))
1979 (void) identify(obj);
1982 /* identify up to `id_limit' items */
1984 if (flags.menu_style == MENU_TRADITIONAL)
1986 n = ggetobj("identify", identify, id_limit, FALSE,
1989 break; /* quit or no eligible items */
1990 } while ((id_limit -= n) > 0);
1991 if (n == 0 || n < -1)
1992 menu_identify(id_limit);
1997 /* called when regaining sight; mark inventory objects which were picked
1998 up while blind as now having been seen */
2000 learn_unseen_invent()
2005 return; /* sanity check */
2007 for (otmp = invent; otmp; otmp = otmp->nobj) {
2009 continue; /* already seen */
2010 /* set dknown, perhaps bknown (for priest[ess]) */
2013 * If object->eknown gets implemented (see learnwand(zap.c)),
2014 * handle deferred discovery here.
2020 /* should of course only be called for things in invent */
2025 if (!flags.invlet_constant) {
2026 obj->invlet = NOINVSYM;
2033 * Print the indicated quantity of the given object. If quan == 0L then use
2034 * the current quantity.
2037 prinv(prefix, obj, quan)
2045 pline("%s%s%s", prefix, *prefix ? " " : "",
2046 xprname(obj, (char *) 0, obj_to_let(obj), TRUE, 0L, quan));
2049 xprname(obj, (char *)0, obj_to_let(obj), *prefix ? FALSE : TRUE, 0L, quan),
2055 xprname(obj, txt, let, dot, cost, quan)
2057 const char *txt; /* text to print instead of obj */
2058 char let; /* inventory letter */
2059 boolean dot; /* append period; (dot && cost => Iu) */
2060 long cost; /* cost (for inventory of unpaid or expended items) */
2061 long quan; /* if non-0, print this quantity, not obj->quan */
2063 #ifdef LINT /* handle static char li[BUFSZ]; */
2066 static char li[BUFSZ];
2068 boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM;
2072 savequan = obj->quan;
2078 * * Then obj == null and we are printing a total amount.
2079 * > Then the object is contained and doesn't have an inventory letter.
2081 if (cost != 0 || let == '*') {
2082 /* if dot is true, we're doing Iu, otherwise Ix */
2084 Sprintf(li, "%c - %-45s %6ld %s",
2086 Sprintf(li, "%c - %-45s %6ld%s",
2088 (dot && use_invlet ? obj->invlet : let),
2089 (txt ? txt : doname(obj)), cost, currency(cost));
2091 /* ordinary inventory display or pickup message */
2092 Sprintf(li, "%c - %s%s", (use_invlet ? obj->invlet : let),
2094 (txt ? txt : doname(obj)), (dot ? "." : ""));
2096 (txt ? txt : doname(obj)), (dot ? "
\81D" : ""));
2099 obj->quan = savequan;
2104 /* the 'i' command */
2108 (void) display_inventory((char *) 0, FALSE);
2115 * Scan the given list of objects. If last_found is NULL, return the first
2116 * unpaid object found. If last_found is not NULL, then skip over unpaid
2117 * objects until last_found is reached, then set last_found to NULL so the
2118 * next unpaid object is returned. This routine recursively follows
2121 STATIC_OVL struct obj *
2122 find_unpaid(list, last_found)
2123 struct obj *list, **last_found;
2130 /* still looking for previous unpaid object */
2131 if (list == *last_found)
2132 *last_found = (struct obj *) 0;
2134 return ((*last_found = list));
2136 if (Has_contents(list)) {
2137 if ((obj = find_unpaid(list->cobj, last_found)) != 0)
2142 return (struct obj *) 0;
2145 /* for perm_invent when operating on a partial inventory display, so that
2146 the persistent one doesn't get shrunk during filtering for item selection
2147 then regrown to full inventory, possibly being resized in the process */
2148 static winid cached_pickinv_win = WIN_ERR;
2151 free_pickinv_cache()
2153 if (cached_pickinv_win != WIN_ERR) {
2154 destroy_nhwindow(cached_pickinv_win);
2155 cached_pickinv_win = WIN_ERR;
2160 * Internal function used by display_inventory and getobj that can display
2161 * inventory and return a count as well as a letter. If out_cnt is not null,
2162 * any count returned from the menu selection is placed here.
2165 display_pickinv(lets, want_reply, out_cnt)
2166 register const char *lets;
2172 char *invlet = flags.inv_order;
2173 int i, n, classcount;
2174 winid win; /* windows being used */
2176 menu_item *selected;
2177 struct obj **oarray;
2179 if (flags.perm_invent && lets && *lets) {
2180 /* partial inventory in perm_invent setting; don't operate on
2181 full inventory window, use an alternate one instead; create
2182 the first time needed and keep it for re-use as needed later */
2183 if (cached_pickinv_win == WIN_ERR)
2184 cached_pickinv_win = create_nhwindow(NHW_MENU);
2185 win = cached_pickinv_win;
2190 * Exit early if no inventory -- but keep going if we are doing
2191 * a permanent inventory update. We need to keep going so the
2192 * permanent inventory window updates itself to remove the last
2193 * item(s) dropped. One down side: the addition of the exception
2194 * for permanent inventory window updates _can_ pop the window
2195 * up when it's not displayed -- even if it's empty -- because we
2196 * don't know at this level if its up or not. This may not be
2197 * an issue if empty checks are done before hand and the call
2198 * to here is short circuited away.
2200 if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
2202 pline("Not carrying anything.");
2204 pline("
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
2208 /* oxymoron? temporarily assign permanent inventory letters */
2209 if (!flags.invlet_constant)
2212 if (lets && strlen(lets) == 1 && !iflags.override_ID) {
2213 /* when only one item of interest, use pline instead of menus;
2214 we actually use a fake message-line menu in order to allow
2215 the user to perform selection at the --More-- prompt for tty */
2217 for (otmp = invent; otmp; otmp = otmp->nobj) {
2218 if (otmp->invlet == lets[0]) {
2220 lets[0], want_reply ? PICK_ONE : PICK_NONE,
2221 xprname(otmp, (char *) 0, lets[0], TRUE, 0L, 0L));
2223 *out_cnt = -1L; /* select all */
2230 /* count the number of items */
2231 for (n = 0, otmp = invent; otmp; otmp = otmp->nobj)
2232 if (!lets || !*lets || index(lets, otmp->invlet))
2235 oarray = objarr_init(n);
2237 /* Add objects to the array */
2239 for (otmp = invent; otmp; otmp = otmp->nobj)
2240 if (!lets || !*lets || index(lets, otmp->invlet)) {
2241 objarr_set(otmp, i++, oarray, (flags.sortloot == 'f'));
2246 if (wizard && iflags.override_ID) {
2249 /* wiz_identify stuffed the wiz_identify cmd character
2250 into iflags.override_ID */
2251 Sprintf(prompt, "Debug Identify (%s to permanently identify)",
2252 visctrl(iflags.override_ID));
2253 add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
2254 prompt, MENU_UNSELECTED);
2258 any = zeroany; /* set all bits to zero */
2259 for (i = 0; i < n; i++) {
2261 ilet = otmp->invlet;
2262 any = zeroany; /* zero */
2263 if (!flags.sortpack || otmp->oclass == *invlet) {
2264 if (flags.sortpack && !classcount) {
2265 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
2266 let_to_name(*invlet, FALSE,
2267 (want_reply && iflags.menu_head_objsym)),
2272 add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE,
2273 doname(otmp), MENU_UNSELECTED);
2276 if (flags.sortpack) {
2279 if (--invlet != venom_inv) {
2285 end_menu(win, (char *) 0);
2287 n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
2289 ret = selected[0].item.a_char;
2291 *out_cnt = selected[0].count;
2292 free((genericptr_t) selected);
2294 ret = !n ? '\0' : '\033'; /* cancelled */
2300 * If lets == NULL or "", list all objects in the inventory. Otherwise,
2301 * list all objects with object classes that match the order in lets.
2303 * Returns the letter identifier of a selected item, or 0 if nothing
2307 display_inventory(lets, want_reply)
2311 return display_pickinv(lets, want_reply, (long *) 0);
2315 * Show what is current using inventory letters.
2319 display_used_invlets(avoidlet)
2324 char *invlet = flags.inv_order;
2325 int n, classcount, invdone = 0;
2328 menu_item *selected;
2331 win = create_nhwindow(NHW_MENU);
2334 any = zeroany; /* set all bits to zero */
2336 for (otmp = invent; otmp; otmp = otmp->nobj) {
2337 ilet = otmp->invlet;
2338 if (ilet == avoidlet)
2340 if (!flags.sortpack || otmp->oclass == *invlet) {
2341 if (flags.sortpack && !classcount) {
2342 any = zeroany; /* zero */
2343 add_menu(win, NO_GLYPH, &any, 0, 0,
2344 iflags.menu_headings,
2345 let_to_name(*invlet, FALSE, FALSE),
2350 add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE,
2351 doname(otmp), MENU_UNSELECTED);
2354 if (flags.sortpack && *++invlet)
2358 end_menu(win, "Inventory letters used:");
2360 n = select_menu(win, PICK_NONE, &selected);
2362 ret = selected[0].item.a_char;
2363 free((genericptr_t) selected);
2365 ret = !n ? '\0' : '\033'; /* cancelled */
2366 destroy_nhwindow(win);
2372 * Returns the number of unpaid items within the given list. This includes
2373 * contained objects.
2384 if (Has_contents(list))
2385 count += count_unpaid(list->cobj);
2392 * Returns the number of items with b/u/c/unknown within the given list.
2393 * This does NOT include contained objects.
2395 * Assumes that the hero sees or touches or otherwise senses the objects
2396 * at some point: bknown is forced for priest[ess], like in xname().
2399 count_buc(list, type)
2405 for (; list; list = list->nobj) {
2406 /* coins are "none of the above" as far as BUCX filtering goes */
2407 if (list->oclass == COIN_CLASS)
2409 /* priests always know bless/curse state */
2410 if (Role_if(PM_PRIEST))
2413 /* check whether this object matches the requested type */
2415 ? (type == BUC_UNKNOWN)
2416 : list->blessed ? (type == BUC_BLESSED)
2417 : list->cursed ? (type == BUC_CURSED)
2418 : (type == BUC_UNCURSED))
2424 /* similar to count_buc(), but tallies all states at once
2425 rather than looking for a specific type */
2427 tally_BUCX(list, bcp, ucp, ccp, xcp, ocp)
2429 int *bcp, *ucp, *ccp, *xcp, *ocp;
2431 *bcp = *ucp = *ccp = *xcp = *ocp = 0;
2432 for (; list; list = list->nobj) {
2433 if (list->oclass == COIN_CLASS) {
2434 ++(*ocp); /* "other" */
2437 /* priests always know bless/curse state */
2438 if (Role_if(PM_PRIEST))
2443 else if (list->blessed)
2445 else if (list->cursed)
2447 else /* neither blessed nor cursed => uncursed */
2453 count_contents(container, nested, quantity, everything)
2454 struct obj *container;
2455 boolean nested, /* include contents of any nested containers */
2456 quantity, /* count all vs count separate stacks */
2457 everything; /* all objects vs only unpaid objects */
2462 for (otmp = container->cobj; otmp; otmp = otmp->nobj) {
2463 if (nested && Has_contents(otmp))
2464 count += count_contents(otmp, nested, quantity, everything);
2465 if (everything || otmp->unpaid)
2466 count += quantity ? otmp->quan : 1L;
2475 struct obj *otmp, *marker;
2477 char *invlet = flags.inv_order;
2478 int classcount, count, num_so_far;
2481 count = count_unpaid(invent);
2484 marker = (struct obj *) 0;
2485 otmp = find_unpaid(invent, &marker);
2486 cost = unpaid_cost(otmp, FALSE);
2487 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
2488 pline1(xprname(otmp, distant_name(otmp, doname),
2489 carried(otmp) ? otmp->invlet : CONTAINED_SYM, TRUE,
2491 iflags.suppress_price--;
2495 win = create_nhwindow(NHW_MENU);
2497 num_so_far = 0; /* count of # printed so far */
2498 if (!flags.invlet_constant)
2503 for (otmp = invent; otmp; otmp = otmp->nobj) {
2504 ilet = otmp->invlet;
2506 if (!flags.sortpack || otmp->oclass == *invlet) {
2507 if (flags.sortpack && !classcount) {
2508 putstr(win, 0, let_to_name(*invlet, TRUE, FALSE));
2512 totcost += cost = unpaid_cost(otmp, FALSE);
2513 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
2514 putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
2515 ilet, TRUE, cost, 0L));
2516 iflags.suppress_price--;
2521 } while (flags.sortpack && (*++invlet));
2523 if (count > num_so_far) {
2524 /* something unpaid is contained */
2526 putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE, FALSE));
2528 * Search through the container objects in the inventory for
2529 * unpaid items. The top level inventory items have already
2532 for (otmp = invent; otmp; otmp = otmp->nobj) {
2533 if (Has_contents(otmp)) {
2536 marker = (struct obj *) 0; /* haven't found any */
2537 while (find_unpaid(otmp->cobj, &marker)) {
2538 totcost += cost = unpaid_cost(marker, FALSE);
2541 iflags.suppress_price++; /* suppress "(unpaid)" sfx */
2543 xprname(marker, distant_name(marker, doname),
2544 CONTAINED_SYM, TRUE, cost, 0L));
2545 iflags.suppress_price--;
2548 if (!otmp->cknown) {
2549 char contbuf[BUFSZ];
2551 /* Shopkeeper knows what to charge for contents */
2552 Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
2554 xprname((struct obj *) 0, contbuf, CONTAINED_SYM,
2555 TRUE, contcost, 0L));
2564 xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
2567 xprname((struct obj *) 0, "
\8d\87\8cv
\81F", '*', FALSE, totcost, 0L));
2569 display_nhwindow(win, FALSE);
2570 destroy_nhwindow(win);
2573 /* query objlist callback: return TRUE if obj type matches "this_type" */
2574 static int this_type;
2580 boolean res = (obj->oclass == this_type);
2582 if (obj->oclass != COIN_CLASS) {
2583 switch (this_type) {
2585 res = (obj->bknown && obj->blessed);
2588 res = (obj->bknown && !(obj->blessed || obj->cursed));
2591 res = (obj->bknown && obj->cursed);
2597 break; /* use 'res' as-is */
2603 /* the 'I' command */
2609 char *extra_types, types[BUFSZ];
2610 int class_count, oclass, unpaid_count, itemcount;
2611 int bcnt, ccnt, ucnt, xcnt, ocnt;
2612 boolean billx = *u.ushops && doinvbill(0);
2613 menu_item *pick_list;
2614 boolean traditional = TRUE;
2616 const char *prompt = "What type of object do you want an inventory of?";
2618 const char *prompt = "
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\8e\9d\82¿
\95¨
\82ð
\8c©
\82Ü
\82·
\82©
\81H";
2620 if (!invent && !billx) {
2622 You("aren't carrying anything.");
2624 You("
\82»
\82Ì
\8eí
\97Þ
\82Ì
\95¨
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
2627 unpaid_count = count_unpaid(invent);
2628 tally_BUCX(invent, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
2630 if (flags.menu_style != MENU_TRADITIONAL) {
2631 if (flags.menu_style == MENU_FULL
2632 || flags.menu_style == MENU_PARTIAL) {
2633 traditional = FALSE;
2645 n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
2648 this_type = c = pick_list[0].item.a_int;
2649 free((genericptr_t) pick_list);
2653 /* collect a list of classes of objects carried, for use as a prompt
2657 collect_obj_classes(types, invent, FALSE,
2658 (boolean FDECL((*), (OBJ_P))) 0, &itemcount);
2659 if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
2660 types[class_count++] = ' ';
2662 types[class_count++] = 'u';
2664 types[class_count++] = 'x';
2666 types[class_count++] = 'B';
2668 types[class_count++] = 'U';
2670 types[class_count++] = 'C';
2672 types[class_count++] = 'X';
2673 types[class_count] = '\0';
2674 /* add everything not already included; user won't see these */
2675 extra_types = eos(types);
2676 *extra_types++ = '\033';
2678 *extra_types++ = 'u';
2680 *extra_types++ = 'x';
2682 *extra_types++ = 'B';
2684 *extra_types++ = 'U';
2686 *extra_types++ = 'C';
2688 *extra_types++ = 'X';
2689 *extra_types = '\0'; /* for index() */
2690 for (i = 0; i < MAXOCLASSES; i++)
2691 if (!index(types, def_oc_syms[i].sym)) {
2692 *extra_types++ = def_oc_syms[i].sym;
2693 *extra_types = '\0';
2696 if (class_count > 1) {
2697 c = yn_function(prompt, types, '\0');
2700 clear_nhwindow(WIN_MESSAGE);
2704 /* only one thing to itemize */
2713 if (c == 'x' || (c == 'X' && billx && !xcnt)) {
2715 (void) doinvbill(1);
2718 pline("No used-up objects%s.",
2719 unpaid_count ? " on your shopping bill" : "");
2721 pline("
\8eg
\82Á
\82Ä
\82µ
\82Ü
\82Á
\82½
\95¨
\82Í%s
\82È
\82¢
\81D",
2722 unpaid_count ? "
\8f¤
\93X
\82Ì
\90¿
\8b\81\8f\91\82É
\82Í" : "");
2726 if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
2731 You("are not carrying any unpaid objects.");
2733 You("
\96¢
\95¥
\82¢
\82Ì
\83A
\83C
\83e
\83\80\82ð
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
2737 if (index("BUCX", c))
2738 oclass = c; /* not a class but understood by this_type_only() */
2740 oclass = def_char_to_objclass(c); /* change to object class */
2742 if (oclass == COIN_CLASS)
2744 if (index(types, c) > index(types, '\033')) {
2745 /* '> ESC' => hidden choice, something known not to be carried */
2746 const char *which = 0;
2750 which = "known to be blessed";
2753 which = "known to be uncursed";
2756 which = "known to be cursed";
2760 "have no objects whose blessed/uncursed/cursed status is unknown.");
2761 break; /* better phrasing is desirable */
2766 which = "
\82»
\82Ì
\82æ
\82¤
\82È";
2771 You("have no %s objects.", which);
2773 You("%s
\82à
\82Ì
\82Í
\89½
\82à
\8e\9d\82Á
\82Ä
\82¢
\82È
\82¢
\81D", which);
2778 if (query_objlist((char *) 0, invent,
2779 (flags.invlet_constant ? USE_INVLET : 0)
2781 &pick_list, PICK_NONE, this_type_only) > 0)
2782 free((genericptr_t) pick_list);
2786 /* return a string describing the dungeon feature at <x,y> if there
2787 is one worth mentioning at that location; otherwise null */
2789 dfeature_at(x, y, buf)
2793 struct rm *lev = &levl[x][y];
2794 int ltyp = lev->typ, cmap = -1;
2795 const char *dfeature = 0;
2796 static char altbuf[BUFSZ];
2798 if (IS_DOOR(ltyp)) {
2799 switch (lev->doormask) {
2802 break; /* "doorway" */
2805 break; /* "open door" */
2808 dfeature = "broken door";
2810 dfeature = "
\89ó
\82ê
\82½
\94à";
2814 break; /* "closed door" */
2816 /* override door description for open drawbridge */
2817 if (is_drawbridge_wall(x, y) >= 0)
2819 dfeature = "open drawbridge portcullis", cmap = -1;
2821 dfeature = "
\8d~
\82è
\82Ä
\82¢
\82é
\92µ
\82Ë
\8b´", cmap = -1;
2822 } else if (IS_FOUNTAIN(ltyp))
2823 cmap = S_fountain; /* "fountain" */
2824 else if (IS_THRONE(ltyp))
2825 cmap = S_throne; /* "opulent throne" */
2826 else if (is_lava(x, y))
2827 cmap = S_lava; /* "molten lava" */
2828 else if (is_ice(x, y))
2829 cmap = S_ice; /* "ice" */
2830 else if (is_pool(x, y))
2832 dfeature = "pool of water";
2834 dfeature = "
\90\85\82½
\82Ü
\82è";
2835 else if (IS_SINK(ltyp))
2836 cmap = S_sink; /* "sink" */
2837 else if (IS_ALTAR(ltyp)) {
2839 Sprintf(altbuf, "%saltar to %s (%s)",
2840 ((lev->altarmask & AM_SHRINE)
2841 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
2845 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
2847 Sprintf(altbuf, "%s%s
\82Ì
\8dÕ
\92d(%s)",
2848 ((lev->altarmask & AM_SHRINE)
2849 && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
2853 align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
2856 } else if ((x == xupstair && y == yupstair)
2857 || (x == sstairs.sx && y == sstairs.sy && sstairs.up))
2858 cmap = S_upstair; /* "staircase up" */
2859 else if ((x == xdnstair && y == ydnstair)
2860 || (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
2861 cmap = S_dnstair; /* "staircase down" */
2862 else if (x == xupladder && y == yupladder)
2863 cmap = S_upladder; /* "ladder up" */
2864 else if (x == xdnladder && y == ydnladder)
2865 cmap = S_dnladder; /* "ladder down" */
2866 else if (ltyp == DRAWBRIDGE_DOWN)
2867 cmap = S_vodbridge; /* "lowered drawbridge" */
2868 else if (ltyp == DBWALL)
2869 cmap = S_vcdbridge; /* "raised drawbridge" */
2870 else if (IS_GRAVE(ltyp))
2871 cmap = S_grave; /* "grave" */
2872 else if (ltyp == TREE)
2873 cmap = S_tree; /* "tree" */
2874 else if (ltyp == IRONBARS)
2876 dfeature = "set of iron bars";
2878 dfeature = "
\93S
\82Ì
\96_";
2881 dfeature = defsyms[cmap].explanation;
2883 Strcpy(buf, dfeature);
2887 /* look at what is here; if there are many objects (pile_limit or more),
2888 don't show them unless obj_cnt is 0 */
2890 look_here(obj_cnt, picked_some)
2891 int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progress */
2892 boolean picked_some;
2897 const char *verb = Blind ? "feel" : "see";
2899 const char *verb = Blind ? "
\82ª
\82 \82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½" : "
\82ð
\82Ý
\82Â
\82¯
\82½";
2901 const char *dfeature = (char *) 0;
2902 char fbuf[BUFSZ], fbuf2[BUFSZ];
2904 boolean skip_objects, felt_cockatrice = FALSE;
2906 /* default pile_limit is 5; a value of 0 means "never skip"
2907 (and 1 effectively forces "always skip") */
2908 skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
2909 if (u.uswallow && u.ustuck) {
2910 struct monst *mtmp = u.ustuck;
2912 Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
2913 mbodypart(mtmp, STOMACH));
2915 Sprintf(fbuf, "%s
\82Ì%s
\82Ì
\92\86\90g", mon_nam(mtmp),
2916 mbodypart(mtmp, STOMACH));
2918 #if 0 /*JP*//*
\8cê
\8f\87\82ª
\88á
\82¤
\82Ì
\82Å
\91f
\92¼
\82É*/
2919 /* Skip "Contents of " by using fbuf index 12 */
2920 You("%s to %s what is lying in %s.", Blind ? "try" : "look around",
2923 You("%s
\82Ì%s
\82É
\89½
\82ª
\82 \82é
\82©%s
\81D",
2924 mon_nam(mtmp), mbodypart(mtmp, STOMACH),
2925 Blind ? "
\82³
\82®
\82Á
\82½" : "
\8c©
\89ñ
\82µ
\82½");
2927 otmp = mtmp->minvent;
2929 for (; otmp; otmp = otmp->nobj) {
2930 /* If swallower is an animal, it should have become stone
2932 if (otmp->otyp == CORPSE)
2933 feel_cockatrice(otmp, FALSE);
2937 Strcpy(fbuf, "You feel");
2940 Sprintf(fbuf, "
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F", Blind ? "
\82ç
\82µ
\82¢" : "");
2942 (void) display_minventory(mtmp, MINV_ALL, fbuf);
2945 You("%s no objects here.", verb);
2947 pline(Blind ? "
\82 \82È
\82½
\82Í
\89½
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D"
2948 : "
\82 \82È
\82½
\82Í
\89½
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
2953 if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen)
2955 There("is %s here.",
2957 pline("
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D",
2958 an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
2960 otmp = level.objects[u.ux][u.uy];
2961 dfeature = dfeature_at(u.ux, u.uy, fbuf2);
2963 if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
2965 if (dfeature && !strcmp(dfeature, "
\90\85\82½
\82Ü
\82è") && Underwater)
2969 boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
2972 if (dfeature && !strncmp(dfeature, "altar ", 6)) {
2974 if (dfeature && !strncmp(dfeature, "
\8dÕ
\92d", 4)) {
2975 /* don't say "altar" twice, dfeature has more info */
2977 You("try to feel what is here.");
2979 You("
\82±
\82±
\82É
\89½
\82ª
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
2982 const char *where = (Blind && !can_reach_floor(TRUE))
2983 ? "lying beneath you"
2984 : "lying here on the ",
2985 *onwhat = (Blind && !can_reach_floor(TRUE))
2987 : surface(u.ux, u.uy);
2989 You("try to feel what is %s%s.", drift ? "floating here" : where,
2990 drift ? "" : onwhat);
2993 You("
\89½
\82ª
\95\82\82¢
\82Ä
\82¢
\82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
2994 } else if (Blind && !can_reach_floor(TRUE)) {
2995 You("
\89½
\82ª
\91«
\89º
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D");
2997 You("
\89½
\82ª%s
\82Ì
\8fã
\82É
\82 \82é
\82Ì
\82©
\92²
\82×
\82æ
\82¤
\82Æ
\82µ
\82½
\81D", surface(u.ux, u.uy));
3001 if (dfeature && !drift && !strcmp(dfeature, surface(u.ux, u.uy)))
3002 dfeature = 0; /* ice already identified */
3003 if (!can_reach_floor(TRUE)) {
3005 pline("But you can't reach it!");
3007 pline("
\82µ
\82©
\82µ
\93Í
\82©
\82È
\82¢
\81I");
3014 Sprintf(fbuf, "There is %s here.", an(dfeature));
3016 Sprintf(fbuf, "
\82±
\82±
\82É
\82Í%s
\82ª
\82 \82é
\81D", an(dfeature));
3018 if (!otmp || is_lava(u.ux, u.uy)
3019 || (is_pool(u.ux, u.uy) && !Underwater)) {
3022 read_engr_at(u.ux, u.uy); /* Eric Backus */
3023 if (!skip_objects && (Blind || !dfeature))
3025 You("%s no objects here.", verb);
3028 "
\82È
\82É
\82à
\82È
\82¢
\82æ
\82¤
\82È
\8bC
\82ª
\82·
\82é
\81D" :
3029 "
\82È
\82É
\82à
\82Ý
\82Â
\82¯
\82ç
\82ê
\82È
\82©
\82Á
\82½
\81D");
3033 /* we know there is something here */
3038 read_engr_at(u.ux, u.uy); /* Eric Backus */
3039 if (obj_cnt == 1 && otmp->quan == 1L)
3040 There("is %s object here.", picked_some ? "another" : "an");
3043 There("are %s%s objects here.",
3049 picked_some ? " more" : "");
3051 pline("
\82±
\82±
\82É
\82Í%s%s
\82à
\82Ì
\82ª
\82 \82é
\81D",
3052 picked_some ? "
\82³
\82ç
\82É" : "",
3054 ? "
\82¢
\82
\82Â
\82©
\82Ì"
3055 : "
\82½
\82
\82³
\82ñ
\82Ì");
3057 for (; otmp; otmp = otmp->nexthere)
3058 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3065 corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
3066 poly_when_stoned(youmonst.data)
3068 : ", unfortunately");
3069 feel_cockatrice(otmp, FALSE);
3072 } else if (!otmp->nexthere) {
3073 /* only one object */
3076 read_engr_at(u.ux, u.uy); /* Eric Backus */
3078 You("%s here %s.", verb, doname_with_price(otmp));
3080 pline("%s%s
\81D", doname_with_price(otmp), verb);
3081 iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
3082 if (otmp->otyp == CORPSE)
3083 feel_cockatrice(otmp, FALSE);
3087 display_nhwindow(WIN_MESSAGE, FALSE);
3088 tmpwin = create_nhwindow(NHW_MENU);
3090 putstr(tmpwin, 0, fbuf);
3091 putstr(tmpwin, 0, "");
3094 Sprintf(buf, "%s that %s here:",
3095 picked_some ? "Other things" : "Things",
3096 Blind ? "you feel" : "are");
3098 Sprintf(buf, "%s
\82±
\82±
\82É
\82 \82é%s
\82à
\82Ì
\82Í
\81F",
3099 picked_some ? "
\91¼
\82É" : "",
3100 Blind ? "
\82ç
\82µ
\82¢" : "");
3102 putstr(tmpwin, 0, buf);
3103 for (; otmp; otmp = otmp->nexthere) {
3104 if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
3105 felt_cockatrice = TRUE;
3106 Sprintf(buf, "%s...", doname(otmp));
3107 putstr(tmpwin, 0, buf);
3110 putstr(tmpwin, 0, doname_with_price(otmp));
3112 display_nhwindow(tmpwin, TRUE);
3113 destroy_nhwindow(tmpwin);
3114 if (felt_cockatrice)
3115 feel_cockatrice(otmp, FALSE);
3116 read_engr_at(u.ux, u.uy); /* Eric Backus */
3121 /* the ':' command - explicitly look at what is here, including all objects */
3125 return look_here(0, FALSE);
3129 will_feel_cockatrice(otmp, force_touch)
3131 boolean force_touch;
3133 if ((Blind || force_touch) && !uarmg && !Stone_resistance
3134 && (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
3140 feel_cockatrice(otmp, force_touch)
3142 boolean force_touch;
3146 if (will_feel_cockatrice(otmp, force_touch)) {
3147 /* "the <cockatrice> corpse" */
3148 Strcpy(kbuf, corpse_xname(otmp, (const char *) 0, CXN_PFX_THE));
3150 if (poly_when_stoned(youmonst.data))
3152 You("touched %s with your bare %s.", kbuf,
3153 makeplural(body_part(HAND)));
3155 You("%s
\82Ì
\8e\80\91Ì
\82É
\91f%s
\82Å
\90G
\82Á
\82½
\81D", kbuf,
3160 pline("Touching %s is a fatal mistake...", kbuf);
3162 pline("%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82é
\82Ì
\82Í
\92v
\96½
\93I
\82È
\8aÔ
\88á
\82¢
\82¾
\81D
\81D
\81D", kbuf);
3163 /* normalize body shape here; hand, not body_part(HAND) */
3165 Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
3167 Sprintf(kbuf, "%s
\82Ì
\8e\80\91Ì
\82É
\90G
\82ê
\82Ä", killer_xname(otmp));
3168 /* will call polymon() for the poly_when_stoned() case */
3179 for (otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
3180 if (otmp != obj && merged(&obj, &otmp))
3185 /* returns TRUE if obj & otmp can be merged */
3188 register struct obj *otmp, *obj;
3190 int objnamelth = 0, otmpnamelth = 0;
3192 return FALSE; /* already the same object */
3193 if (obj->otyp != otmp->otyp)
3195 /* coins of the same kind will always merge */
3196 if (obj->oclass == COIN_CLASS)
3198 if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
3199 || obj->dknown != otmp->dknown
3200 || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
3201 || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed
3202 || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
3203 || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
3204 || obj->greased != otmp->greased || obj->oeroded != otmp->oeroded
3205 || obj->oeroded2 != otmp->oeroded2 || obj->bypass != otmp->bypass)
3208 if (obj->nomerge) /* explicitly marked to prevent merge */
3211 if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
3212 && (obj->oerodeproof != otmp->oerodeproof
3213 || obj->rknown != otmp->rknown))
3216 if (obj->oclass == FOOD_CLASS
3217 && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
3220 if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
3221 if (obj->corpsenm != otmp->corpsenm)
3225 /* hatching eggs don't merge; ditto for revivable corpses */
3226 if ((obj->otyp == EGG && (obj->timed || otmp->timed))
3227 || (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM
3228 && is_reviver(&mons[otmp->corpsenm])))
3231 /* allow candle merging only if their ages are close */
3232 /* see begin_burn() for a reference for the magic "25" */
3233 if (Is_candle(obj) && obj->age / 25 != otmp->age / 25)
3236 /* burning potions of oil never merge */
3237 if (obj->otyp == POT_OIL && obj->lamplit)
3240 /* don't merge surcharged item with base-cost item */
3241 if (obj->unpaid && !same_price(obj, otmp))
3244 /* if they have names, make sure they're the same */
3245 objnamelth = strlen(safe_oname(obj));
3246 otmpnamelth = strlen(safe_oname(otmp));
3247 if ((objnamelth != otmpnamelth
3248 && ((objnamelth && otmpnamelth) || obj->otyp == CORPSE))
3249 || (objnamelth && otmpnamelth
3250 && strncmp(ONAME(obj), ONAME(otmp), objnamelth)))
3253 /* for the moment, any additional information is incompatible */
3254 if (has_omonst(obj) || has_omid(obj) || has_olong(obj) || has_omonst(otmp)
3255 || has_omid(otmp) || has_olong(otmp))
3258 if (obj->oartifact != otmp->oartifact)
3261 if (obj->known == otmp->known || !objects[otmp->otyp].oc_uses_known) {
3262 return (boolean) objects[obj->otyp].oc_merge;
3267 /* the '$' command */
3271 /* the messages used to refer to "carrying gold", but that didn't
3272 take containers into account */
3273 long umoney = money_cnt(invent);
3276 Your("wallet is empty.");
3278 Your("
\8dà
\95z
\82Í
\8bó
\82Á
\82Û
\82¾
\81D");
3281 Your("wallet contains %ld %s.", umoney, currency(umoney));
3283 Your("
\8dà
\95z
\82É
\82Í%ld%s
\93ü
\82Á
\82Ä
\82¢
\82é
\81D", umoney, currency(umoney));
3284 shopper_financial_report();
3288 /* the ')' command */
3294 You("are empty %s.", body_part(HANDED));
3296 if(!uwep) You("%s
\82É
\95\90\8aí
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D", body_part(HAND));
3298 prinv((char *) 0, uwep, 0L);
3300 prinv((char *) 0, uswapwep, 0L);
3305 /* caller is responsible for checking !wearing_armor() */
3307 noarmor(report_uskin)
3308 boolean report_uskin;
3310 if (!uskin || !report_uskin) {
3312 You("are not wearing any armor.");
3314 You("
\8aZ
\82ð
\92\85\82Ä
\82¢
\82È
\82¢
\81D");
3316 char *p, *uskinname, buf[BUFSZ];
3318 uskinname = strcpy(buf, simpleonames(uskin));
3320 /* shorten "set of <color> dragon scales" to "<color> scales"
3321 and "<color> dragon scale mail" to "<color> scale mail" */
3322 if (!strncmpi(uskinname, "set of ", 7))
3324 if ((p = strstri(uskinname, " dragon ")) != 0)
3325 while ((p[1] = p[8]) != '\0')
3327 #else /*
\81u<
\90F>
\83h
\83\89\83S
\83\93\82Ì
\97Ø
\81v
\82ð
\81u<
\90F>
\82Ì
\97Ø
\81v
\82É
\82·
\82é*/
3328 if ((p = strstri(uskinname, "
\83h
\83\89\83S
\83\93\82Ì
\97Ø")) != 0)
3333 You("are not wearing armor but have %s embedded in your skin.",
3335 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",
3340 /* the '[' command */
3345 register int ct = 0;
3347 * Note: players sometimes get here by pressing a function key which
3348 * transmits ''ESC [ <something>'' rather than by pressing '[';
3349 * there's nothing we can--or should-do about that here.
3352 if (!wearing_armor()) {
3356 lets[ct++] = obj_to_let(uarmu);
3358 lets[ct++] = obj_to_let(uarm);
3360 lets[ct++] = obj_to_let(uarmc);
3362 lets[ct++] = obj_to_let(uarmh);
3364 lets[ct++] = obj_to_let(uarms);
3366 lets[ct++] = obj_to_let(uarmg);
3368 lets[ct++] = obj_to_let(uarmf);
3370 (void) display_inventory(lets, FALSE);
3375 /* the '=' command */
3379 if (!uleft && !uright)
3381 You("are not wearing any rings.");
3383 You("
\8ew
\97Ö
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
3386 register int ct = 0;
3389 lets[ct++] = obj_to_let(uleft);
3391 lets[ct++] = obj_to_let(uright);
3393 (void) display_inventory(lets, FALSE);
3398 /* the '"' command */
3404 You("are not wearing an amulet.");
3406 You("
\96\82\8f\9c\82¯
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82È
\82¢
\81D");
3408 prinv((char *) 0, uamul, 0L);
3416 if ((obj->owornmask & (W_TOOL | W_SADDLE)) != 0L)
3418 if (obj->oclass != TOOL_CLASS)
3420 return (boolean) (obj == uwep || obj->lamplit
3421 || (obj->otyp == LEASH && obj->leashmon));
3424 /* the '(' command */
3432 for (otmp = invent; otmp; otmp = otmp->nobj)
3433 if (tool_in_use(otmp))
3434 lets[ct++] = obj_to_let(otmp);
3438 You("are not using any tools.");
3440 You("
\8eg
\82¦
\82é
\93¹
\8bï
\82ð
\82à
\82Á
\82Ä
\82¢
\82È
\82¢
\81D");
3442 (void) display_inventory(lets, FALSE);
3446 /* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
3447 show inventory of all currently wielded, worn, or used objects */
3455 for (otmp = invent; otmp; otmp = otmp->nobj)
3456 if (is_worn(otmp) || tool_in_use(otmp))
3457 lets[ct++] = obj_to_let(otmp);
3461 You("are not wearing or wielding anything.");
3463 You("
\89½
\82à
\92\85\82Ä
\82¢
\82È
\82¢
\82µ
\81C
\91\95\94õ
\82µ
\82Ä
\82¢
\82È
\82¢
\81D");
3465 (void) display_inventory(lets, FALSE);
3470 * uses up an object that's on the floor, charging for it as necessary
3473 useupf(obj, numused)
3474 register struct obj *obj;
3477 register struct obj *otmp;
3478 boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
3480 /* burn_floor_objects() keeps an object pointer that it tries to
3481 * useupf() multiple times, so obj must survive if plural */
3482 if (obj->quan > numused)
3483 otmp = splitobj(obj, numused);
3486 if (costly_spot(otmp->ox, otmp->oy)) {
3487 if (index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
3488 addtobill(otmp, FALSE, FALSE, FALSE);
3490 (void) stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
3493 if (at_u && u.uundetected && hides_under(youmonst.data))
3494 (void) hideunder(&youmonst);
3498 * Conversion from a class to a string for printing.
3499 * This must match the object class order.
3501 STATIC_VAR NEARDATA const char *names[] = {
3503 0, "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", "Tools",
3504 "Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
3505 "Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
3507 0, "
\96
\82È
\95¨
\91Ì", "
\95\90\8aí", "
\8aZ", "
\8ew
\97Ö", "
\96\82\8f\9c\82¯", "
\93¹
\8bï",
3508 "
\90H
\97¿", "
\96ò", "
\8aª
\95¨", "
\96\82\96@
\8f\91", "
\8fñ", "
\8bà
\89Ý",
3509 "
\95ó
\90Î", "
\8aâ
\82Ü
\82½
\82Í
\92¤
\91\9c", "
\93S
\8b\85", "
\8d½", "
\93Å"
3513 static NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
3516 static NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
3518 static NEARDATA const char *oth_names[] = { "
\8bl
\82ß
\82ç
\82ê
\82½
\93¹
\8bï" };
3520 static NEARDATA char *invbuf = (char *) 0;
3521 static NEARDATA unsigned invbufsiz = 0;
3524 let_to_name(let, unpaid, showsym)
3526 boolean unpaid, showsym;
3528 const char *ocsymfmt = " ('%c')";
3529 const int invbuf_sympadding = 8; /* arbitrary */
3530 const char *class_name;
3532 int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
3536 class_name = names[oclass];
3537 else if ((pos = index(oth_symbols, let)) != 0)
3538 class_name = oth_names[pos - oth_symbols];
3540 class_name = names[0];
3543 len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "")
3545 len = strlen(class_name) + (unpaid ? sizeof "
\96¢
\95¥
\82¢
\82Ì" : sizeof "")
3546 + (oclass ? (strlen(ocsymfmt) + invbuf_sympadding) : 0);
3547 if (len > invbufsiz) {
3549 free((genericptr_t) invbuf);
3550 invbufsiz = len + 10; /* add slop to reduce incremental realloc */
3551 invbuf = (char *) alloc(invbufsiz);
3555 Strcat(strcpy(invbuf, "Unpaid "), class_name);
3557 Strcat(strcpy(invbuf, "
\96¢
\95¥
\82¢
\82Ì"), class_name);
3559 Strcpy(invbuf, class_name);
3560 if ((oclass != 0) && showsym) {
3561 char *bp = eos(invbuf);
3562 int mlen = invbuf_sympadding - strlen(class_name);
3563 while (--mlen > 0) {
3568 Sprintf(eos(invbuf), ocsymfmt, def_oc_syms[oclass].sym);
3573 /* release the static buffer used by let_to_name() */
3578 free((genericptr_t) invbuf), invbuf = (char *) 0;
3582 /* give consecutive letters to every item in inventory (for !fixinv mode);
3583 gold is always forced to '$' slot at head of list */
3588 struct obj *obj, *prevobj, *goldobj;
3590 /* first, remove [first instance of] gold from invent, if present */
3591 prevobj = goldobj = 0;
3592 for (obj = invent; obj; prevobj = obj, obj = obj->nobj)
3593 if (obj->oclass == COIN_CLASS) {
3596 prevobj->nobj = goldobj->nobj;
3598 invent = goldobj->nobj;
3601 /* second, re-letter the rest of the list */
3602 for (obj = invent, i = 0; obj; obj = obj->nobj, i++)
3604 (i < 26) ? ('a' + i) : (i < 52) ? ('A' + i - 26) : NOINVSYM;
3605 /* third, assign gold the "letter" '$' and re-insert it at head */
3607 goldobj->invlet = GOLD_SYM;
3608 goldobj->nobj = invent;
3618 * User specifies a 'from' slot for inventory stack to move,
3619 * then a 'to' slot for its destination. Open slots and those
3620 * filled by compatible stacks are listed as likely candidates
3621 * but user can pick any inventory letter (including 'from').
3622 * All compatible items found are gathered into the 'from'
3623 * stack as it is moved. If the 'to' slot isn't empty and
3624 * doesn't merge, then its stack is swapped to the 'from' slot.
3626 * If the user specifies a count when choosing the 'from' slot,
3627 * and that count is less than the full size of the stack,
3628 * then the stack will be split. The 'count' portion is moved
3629 * to the destination, and the only candidate for merging with
3630 * it is the stack already at the 'to' slot, if any. When the
3631 * destination is non-empty but won't merge, whatever is there
3632 * will be moved to an open slot; if there isn't any open slot
3633 * available, the adjustment attempt fails.
3635 * Splitting has one special case: if 'to' slot is non-empty
3636 * and is compatible with 'from' in all respects except for
3637 * user-assigned names, the 'count' portion being moved is
3638 * effectively renamed so that it will merge with 'to' stack.
3641 doorganize() /* inventory organizer by Del Lamb */
3643 struct obj *obj, *otmp, *splitting, *bumped;
3644 int ix, cur, trycnt;
3646 char alphabet[52 + 1], buf[52 + 1];
3648 char allowall[3]; /* { ALLOW_COUNT, ALL_CLASSES, 0 } */
3649 const char *adj_type;
3652 You("aren't carrying anything to adjust.");
3656 if (!flags.invlet_constant)
3658 /* get object the user wants to organize (the 'from' slot) */
3659 allowall[0] = ALLOW_COUNT;
3660 allowall[1] = ALL_CLASSES;
3662 if (!(obj = getobj(allowall, "adjust")))
3665 /* figure out whether user gave a split count to getobj() */
3666 splitting = bumped = 0;
3667 for (otmp = invent; otmp; otmp = otmp->nobj)
3668 if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
3669 if (otmp->invlet == obj->invlet)
3674 /* initialize the list with all lower and upper case letters */
3675 for (ix = 0, let = 'a'; let <= 'z';)
3676 alphabet[ix++] = let++;
3677 for (let = 'A'; let <= 'Z';)
3678 alphabet[ix++] = let++;
3679 alphabet[ix] = '\0';
3680 /* for floating inv letters, truncate list after the first open slot */
3681 if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
3682 alphabet[ix + (splitting ? 0 : 1)] = '\0';
3684 /* blank out all the letters currently in use in the inventory */
3685 /* except those that will be merged with the selected object */
3686 for (otmp = invent; otmp; otmp = otmp->nobj)
3687 if (otmp != obj && !mergable(otmp, obj)) {
3689 if (let >= 'a' && let <= 'z')
3690 alphabet[let - 'a'] = ' ';
3691 else if (let >= 'A' && let <= 'Z')
3692 alphabet[let - 'A' + 26] = ' ';
3695 /* compact the list by removing all the blanks */
3696 for (ix = cur = 0; alphabet[ix]; ix++)
3697 if (alphabet[ix] != ' ')
3698 buf[cur++] = alphabet[ix];
3699 if (!cur && obj->invlet == NOINVSYM)
3700 buf[cur++] = NOINVSYM;
3702 /* and by dashing runs of letters */
3706 /* get 'to' slot to use as destination */
3708 Sprintf(qbuf, "Adjust letter to what [%s]%s?", buf,
3709 invent ? " (? see used letters)" : "");
3711 Sprintf(qbuf, "
\82Ç
\82Ì
\95¶
\8e\9a\82É
\92²
\90®
\82µ
\82Ü
\82·
\82©[%s]%s
\81H", buf,
3712 invent ? " (?
\82Å
\8eg
\82Á
\82Ä
\82¢
\82é
\95¶
\8e\9a\82ð
\95\
\8e¦)" : "");
3714 for (trycnt = 1; ; ++trycnt) {
3715 let = yn_function(qbuf, (char *) 0, '\0');
3716 if (let == '?' || let == '*') {
3717 let = display_used_invlets(splitting ? obj->invlet : 0);
3723 if (index(quitchars, let)
3724 /* adjusting to same slot is meaningful since all
3725 compatible stacks get collected along the way,
3726 but splitting to same slot is not */
3727 || (splitting && let == obj->invlet)) {
3730 (void) merged(&splitting, &obj);
3734 if ((letter(let) && let != '@') || index(buf, let))
3735 break; /* got one */
3739 pline("Select an inventory slot letter."); /* else try again */
3741 pline("
\8e\9d\82¿
\95¨
\82Ì
\95¶
\8e\9a\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢
\81D");
3745 /* change the inventory and print the resulting item */
3747 adj_type = !splitting ? "Moving:" : "Splitting:";
3749 adj_type = !splitting ? "
\82ð
\88Ú
\93®
\82µ
\82½
\81D" : "
\82ð
\95ª
\8a\84\82µ
\82½
\81D";
3752 * don't use freeinv/addinv to avoid double-touching artifacts,
3753 * dousing lamps, losing luck, cursing loadstone, etc.
3755 extract_nobj(obj, &invent);
3757 for (otmp = invent; otmp;) {
3759 if (merged(&otmp, &obj)) {
3761 adj_type = "Merging:";
3763 adj_type = "
\82ð
\8d\87\82í
\82¹
\82½
\81D";
3766 extract_nobj(obj, &invent);
3767 continue; /* otmp has already been updated */
3768 } else if (otmp->invlet == let) {
3770 adj_type = "Swapping:";
3772 adj_type = "
\82ð
\8cð
\8a·
\82µ
\82½
\81D";
3773 otmp->invlet = obj->invlet;
3776 /* splitting: don't merge extra compatible stacks;
3777 if destination is compatible, do merge with it,
3778 otherwise bump whatever is there to an open slot */
3779 if (otmp->invlet == let) {
3783 olth = strlen(ONAME(obj));
3784 /* ugly hack: if these objects aren't going to merge
3785 solely because they have conflicting user-assigned
3786 names, strip off the name of the one being moved */
3787 if (olth && !obj->oartifact && !mergable(otmp, obj)) {
3788 char *holdname = ONAME(obj);
3789 ONAME(obj) = (char *) 0;
3790 /* restore name iff merging is still not possible */
3791 if (!mergable(otmp, obj)) {
3792 ONAME(obj) = holdname;
3793 holdname = (char *) 0;
3795 free((genericptr_t) holdname);
3798 if (merged(&otmp, &obj)) {
3800 extract_nobj(obj, &invent);
3801 } else if (inv_cnt(FALSE) >= 52) {
3802 (void) merged(&splitting, &obj); /* undo split */
3803 /* "knapsack cannot accommodate any more items" */
3804 Your("pack is too full.");
3808 extract_nobj(bumped, &invent);
3811 } /* found 'to' slot */
3816 /* inline addinv; insert loose object at beginning of inventory */
3819 obj->where = OBJ_INVENT;
3823 /* splitting the 'from' stack is causing an incompatible
3824 stack in the 'to' slot to be moved into an open one;
3825 we need to do another inline insertion to inventory */
3826 assigninvlet(bumped);
3827 bumped->nobj = invent;
3828 bumped->where = OBJ_INVENT;
3833 /* messages deferred until inventory has been fully reestablished */
3834 prinv(adj_type, obj, 0L);
3836 prinv("Moving:", bumped, 0L);
3838 clear_splitobjs(); /* reset splitobj context */
3843 /* common to display_minventory and display_cinventory */
3845 invdisp_nothing(hdr, txt)
3846 const char *hdr, *txt;
3850 menu_item *selected;
3853 win = create_nhwindow(NHW_MENU);
3855 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr,
3857 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
3858 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
3859 end_menu(win, (char *) 0);
3860 if (select_menu(win, PICK_NONE, &selected) > 0)
3861 free((genericptr_t) selected);
3862 destroy_nhwindow(win);
3866 /* query_objlist callback: return things that are worn or wielded */
3868 worn_wield_only(obj)
3872 /* check for things that *are* worn or wielded (only used for monsters,
3873 so we don't worry about excluding W_CHAIN, W_ARTI and the like) */
3874 return (boolean) (obj->owornmask != 0L);
3876 /* this used to check for things that *might* be worn or wielded,
3877 but that's not particularly interesting */
3878 if (is_weptool(obj) || is_wet_towel(obj) || obj->otyp == MEAT_RING)
3880 return (boolean) (obj->oclass == WEAPON_CLASS
3881 || obj->oclass == ARMOR_CLASS
3882 || obj->oclass == AMULET_CLASS
3883 || obj->oclass == RING_CLASS);
3888 * Display a monster's inventory.
3889 * Returns a pointer to the object from the monster's inventory selected
3890 * or NULL if nothing was selected.
3892 * By default, only worn and wielded items are displayed. The caller
3893 * can pick one. Modifier flags are:
3895 * MINV_NOLET - nothing selectable
3896 * MINV_ALL - display all inventory
3899 display_minventory(mon, dflags, title)
3900 register struct monst *mon;
3907 menu_item *selected = 0;
3908 int do_all = (dflags & MINV_ALL) != 0,
3909 incl_hero = (do_all && u.uswallow && mon == u.ustuck),
3910 have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero);
3913 Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
3914 do_all ? "possessions" : "armament");
3916 Sprintf(tmp, "%s
\82Ì%s
\81F", Monnam(mon),
3917 do_all ? "
\8e\9d\82¿
\95¨" : "
\91\95\94õ");
3920 if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
3921 /* Fool the 'weapon in hand' routine into
3922 * displaying 'weapon in claw', etc. properly.
3924 youmonst.data = mon->data;
3926 n = query_objlist(title ? title : tmp, mon->minvent,
3927 INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0),
3929 (dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE,
3930 do_all ? allow_all : worn_wield_only);
3935 invdisp_nothing(title ? title : tmp, "(none)");
3937 invdisp_nothing(title ? title : tmp, "(
\89½
\82à
\82È
\82¢)");
3942 ret = selected[0].item.a_obj;
3943 free((genericptr_t) selected);
3945 ret = (struct obj *) 0;
3950 * Display the contents of a container in inventory style.
3951 * Currently, this is only used for statues, via wand of probing.
3954 display_cinventory(obj)
3955 register struct obj *obj;
3960 menu_item *selected = 0;
3963 (void) safe_qbuf(qbuf, "Contents of ", ":", obj, doname, ansimpleoname,
3966 (void) safe_qbuf(qbuf, "", "
\82Ì
\92\86\90g
\81F", obj, doname, ansimpleoname,
3971 n = query_objlist(qbuf, obj->cobj, INVORDER_SORT, &selected,
3972 PICK_NONE, allow_all);
3975 invdisp_nothing(qbuf, "(empty)");
3977 invdisp_nothing(qbuf, "(
\8bó
\82Á
\82Û)");
3981 ret = selected[0].item.a_obj;
3982 free((genericptr_t) selected);
3984 ret = (struct obj *) 0;
3989 /* query objlist callback: return TRUE if obj is at given location */
3996 return (obj->ox == only.x && obj->oy == only.y);
4000 * Display a list of buried items in inventory style. Return a non-zero
4001 * value if there were items at that spot.
4003 * Currently, this is only used with a wand of probing zapped downwards.
4006 display_binventory(x, y, as_if_seen)
4011 menu_item *selected = 0;
4014 /* count # of objects here */
4015 for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
4016 if (obj->ox == x && obj->oy == y) {
4026 if (query_objlist("Things that are buried here:", level.buriedobjlist,
4028 if (query_objlist("
\82±
\82±
\82É
\96\84\82ß
\82ç
\82ê
\82Ä
\82¢
\82é
\82à
\82Ì
\81F", level.buriedobjlist,
4029 INVORDER_SORT, &selected, PICK_NONE, only_here) > 0)
4030 free((genericptr_t) selected);
4031 only.x = only.y = 0;