-/* NetHack 3.6 invent.c $NHDT-Date: 1447576348 2015/11/15 08:32:28 $ $NHDT-Branch: master $:$NHDT-Revision: 1.179 $ */
+/* NetHack 3.6 invent.c $NHDT-Date: 1555196229 2019/04/13 22:57:09 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.253 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
+/* JNetHack Copyright */
+/* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019 */
+/* JNetHack may be freely redistributed. See license for details. */
+
#include "hack.h"
+#ifndef C /* same as cmd.c */
+#define C(c) (0x1f & (c))
+#endif
+
#define NOINVSYM '#'
#define CONTAINED_SYM '>' /* designator for inside a container */
+#define HANDS_SYM '-'
-STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (struct obj *, struct obj *));
+STATIC_DCL void FDECL(loot_classify, (Loot *, struct obj *));
+STATIC_DCL char *FDECL(loot_xname, (struct obj *));
+STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (const genericptr,
+ const genericptr));
STATIC_DCL void NDECL(reorder_invent);
-STATIC_DCL boolean FDECL(mergable, (struct obj *, struct obj *));
STATIC_DCL void FDECL(noarmor, (BOOLEAN_P));
STATIC_DCL void FDECL(invdisp_nothing, (const char *, const char *));
STATIC_DCL boolean FDECL(worn_wield_only, (struct obj *));
STATIC_DCL boolean FDECL(only_here, (struct obj *));
STATIC_DCL void FDECL(compactify, (char *));
-STATIC_DCL boolean FDECL(splittable, (struct obj *));
STATIC_DCL boolean FDECL(taking_off, (const char *));
STATIC_DCL boolean FDECL(putting_on, (const char *));
-STATIC_PTR int FDECL(ckunpaid, (struct obj *));
STATIC_PTR int FDECL(ckvalidcat, (struct obj *));
+STATIC_PTR int FDECL(ckunpaid, (struct obj *));
STATIC_PTR char *FDECL(safeq_xprname, (struct obj *));
STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
-STATIC_DCL char FDECL(display_pickinv, (const char *, BOOLEAN_P, long *));
+STATIC_DCL char FDECL(display_pickinv, (const char *, const char *,
+ const char *, BOOLEAN_P, long *));
STATIC_DCL char FDECL(display_used_invlets, (CHAR_P));
-STATIC_DCL void FDECL(tally_BUCX,
- (struct obj *, int *, int *, int *, int *, int *));
STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
STATIC_DCL void NDECL(dounpaid);
STATIC_DCL struct obj *FDECL(find_unpaid, (struct obj *, struct obj **));
*/
static char venom_inv[] = { VENOM_CLASS, 0 }; /* (constant) */
-STATIC_OVL int CFDECLSPEC
-sortloot_cmp(obj1, obj2)
-struct obj *obj1;
-struct obj *obj2;
+/* sortloot() classification; called at most once [per sort] for each object */
+STATIC_OVL void
+loot_classify(sort_item, obj)
+Loot *sort_item;
+struct obj *obj;
{
- int val1 = 0;
- int val2 = 0;
+ /* we may eventually make this a settable option to always use
+ with sortloot instead of only when the 'sortpack' option isn't
+ set; it is similar to sortpack's inv_order but items most
+ likely to be picked up are moved to the front */
+ static char def_srt_order[MAXOCLASSES] = {
+ COIN_CLASS, AMULET_CLASS, RING_CLASS, WAND_CLASS, POTION_CLASS,
+ SCROLL_CLASS, SPBOOK_CLASS, GEM_CLASS, FOOD_CLASS, TOOL_CLASS,
+ WEAPON_CLASS, ARMOR_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0,
+ };
+ static char armcat[8];
+ const char *classorder;
+ char *p;
+ int k, otyp = obj->otyp, oclass = obj->oclass;
+ boolean seen, discovered = objects[otyp].oc_name_known ? TRUE : FALSE;
+
+ /*
+ * For the value types assigned by this classification, sortloot()
+ * will put lower valued ones before higher valued ones.
+ */
+ if (!Blind)
+ obj->dknown = 1; /* xname(obj) does this; we want it sooner */
+ seen = obj->dknown ? TRUE : FALSE,
+ /* class order */
+ classorder = flags.sortpack ? flags.inv_order : def_srt_order;
+ p = index(classorder, oclass);
+ if (p)
+ k = 1 + (int) (p - classorder);
+ else
+ k = 1 + (int) strlen(classorder) + (oclass != VENOM_CLASS);
+ sort_item->orderclass = (xchar) k;
+ /* subclass designation; only a few classes have subclasses
+ and the non-armor ones we use are fairly arbitrary */
+ switch (oclass) {
+ case ARMOR_CLASS:
+ if (!armcat[7]) {
+ /* one-time init; we use a different order than the subclass
+ values defined by objclass.h */
+ armcat[ARM_HELM] = 1; /* [2] */
+ armcat[ARM_GLOVES] = 2; /* [3] */
+ armcat[ARM_BOOTS] = 3; /* [4] */
+ armcat[ARM_SHIELD] = 4; /* [1] */
+ armcat[ARM_CLOAK] = 5; /* [5] */
+ armcat[ARM_SHIRT] = 6; /* [6] */
+ armcat[ARM_SUIT] = 7; /* [0] */
+ armcat[7] = 8; /* sanity protection */
+ }
+ k = objects[otyp].oc_armcat;
+ /* oc_armcat overloads oc_subtyp which is an 'schar' so guard
+ against somebody assigning something unexpected to it */
+ if (k < 0 || k >= 7)
+ k = 7;
+ k = armcat[k];
+ break;
+ case WEAPON_CLASS:
+ /* for weapons, group by ammo (arrows, bolts), launcher (bows),
+ missile (darts, boomerangs), stackable (daggers, knives, spears),
+ 'other' (swords, axes, &c), polearms */
+ k = objects[otyp].oc_skill;
+ k = (k < 0) ? ((k >= -P_CROSSBOW && k <= -P_BOW) ? 1 : 3)
+ : ((k >= P_BOW && k <= P_CROSSBOW) ? 2
+ : (k == P_SPEAR || k == P_DAGGER || k == P_KNIFE) ? 4
+ : !is_pole(obj) ? 5 : 6);
+ break;
+ case TOOL_CLASS:
+ if (seen && discovered
+ && (otyp == BAG_OF_TRICKS || otyp == HORN_OF_PLENTY))
+ k = 2; /* known pseudo-container */
+ else if (Is_container(obj))
+ k = 1; /* regular container or unknown bag of tricks */
+ else
+ switch (otyp) {
+ case WOODEN_FLUTE:
+ case MAGIC_FLUTE:
+ case TOOLED_HORN:
+ case FROST_HORN:
+ case FIRE_HORN:
+ case WOODEN_HARP:
+ case MAGIC_HARP:
+ case BUGLE:
+ case LEATHER_DRUM:
+ case DRUM_OF_EARTHQUAKE:
+ case HORN_OF_PLENTY: /* not a musical instrument */
+ k = 3; /* instrument or unknown horn of plenty */
+ default:
+ k = 4; /* 'other' tool */
+ }
+ break;
+ case FOOD_CLASS:
+ /* [what about separating "partly eaten" within each group?] */
+ switch (otyp) {
+ case SLIME_MOLD:
+ k = 1;
+ break;
+ default:
+ /* [maybe separate one-bite foods from rations and such?] */
+ k = obj->globby ? 6 : 2;
+ break;
+ case TIN:
+ k = 3;
+ break;
+ case EGG:
+ k = 4;
+ break;
+ case CORPSE:
+ k = 5;
+ break;
+ }
+ break;
+ case GEM_CLASS:
+ /*
+ * Normally subclass takes priority over discovery status, but
+ * that would give away information for gems (assuming we'll
+ * group them as valuable gems, next glass, then gray stones,
+ * and finally rocks once they're all fully identified).
+ *
+ * Order:
+ * 1) unseen gems and glass ("gem")
+ * 2) seen but undiscovered gems and glass ("blue gem"),
+ * 3) discovered gems ("sapphire"),
+ * 4) discovered glass ("worthless pieced of blue glass"),
+ * 5) unseen gray stones and rocks ("stone"),
+ * 6) seen but undiscovered gray stones ("gray stone"),
+ * 7) discovered gray stones ("touchstone"),
+ * 8) seen rocks ("rock").
+ */
+ switch (objects[obj->otyp].oc_material) {
+ case GEMSTONE:
+ k = !seen ? 1 : !discovered ? 2 : 3;
+ break;
+ case GLASS:
+ k = !seen ? 1 : !discovered ? 2 : 4;
+ break;
+ default: /* MINERAL */
+ k = !seen ? 5 : (obj->otyp != ROCK) ? (!discovered ? 6 : 7) : 8;
+ break;
+ }
+ break;
+ default:
+ /* other classes don't have subclasses; we assign a nonzero
+ value because sortloot() uses 0 to mean 'not yet classified' */
+ k = 1; /* any non-zero would do */
+ break;
+ }
+ sort_item->subclass = (xchar) k;
+ /* discovery status */
+ k = !seen ? 1 /* unseen */
+ : (discovered || !OBJ_DESCR(objects[otyp])) ? 4
+ : (objects[otyp].oc_uname) ? 3 /* named (partially discovered) */
+ : 2; /* undiscovered */
+ sort_item->disco = (xchar) k;
+}
- /* Sort object names in lexicographical order, ignoring quantity. */
- int name_cmp = strcmpi(cxname_singular(obj1), cxname_singular(obj2));
+/* sortloot() formatting routine; for alphabetizing, not shown to user */
+STATIC_OVL char *
+loot_xname(obj)
+struct obj *obj;
+{
+ struct obj saveo;
+ boolean save_debug;
+ char *res, *save_oname;
- if (name_cmp != 0) {
- return name_cmp;
+ /*
+ * Deal with things that xname() includes as a prefix. We don't
+ * want such because they change alphabetical ordering. First,
+ * remember 'obj's current settings.
+ */
+ saveo.odiluted = obj->odiluted;
+ saveo.blessed = obj->blessed, saveo.cursed = obj->cursed;
+ saveo.spe = obj->spe;
+ saveo.owt = obj->owt;
+ save_oname = has_oname(obj) ? ONAME(obj) : 0;
+ save_debug = flags.debug;
+ /* suppress "diluted" for potions and "holy/unholy" for water;
+ sortloot() will deal with them using other criteria than name */
+ if (obj->oclass == POTION_CLASS) {
+ obj->odiluted = 0;
+ if (obj->otyp == POT_WATER)
+ obj->blessed = 0, obj->cursed = 0;
+ }
+ /* make "wet towel" and "moist towel" format as "towel" so that all
+ three group together */
+ if (obj->otyp == TOWEL)
+ obj->spe = 0;
+ /* group "<size> glob of <foo>" by <foo> rather than by <size> */
+ if (obj->globby)
+ obj->owt = 200; /* 200: weight of combined glob from ten creatures
+ (five or fewer is "small", more than fifteen is
+ "large", in between has no prefix) */
+ /* suppress user-assigned name */
+ if (save_oname && !obj->oartifact)
+ ONAME(obj) = 0;
+ /* avoid wizard mode formatting variations */
+ if (wizard) { /* flags.debug */
+ /* paranoia: before toggling off wizard mode, guard against a
+ panic in xname() producing a normal mode panic save file */
+ program_state.something_worth_saving = 0;
+ flags.debug = FALSE;
}
- /* Sort by BUC. Map blessed to 4, uncursed to 2, cursed to 1, and unknown
- * to 0. */
- val1 = obj1->bknown
- ? (obj1->blessed << 2)
- + ((!obj1->blessed && !obj1->cursed) << 1) + obj1->cursed
- : 0;
- val2 = obj2->bknown
- ? (obj2->blessed << 2)
- + ((!obj2->blessed && !obj2->cursed) << 1) + obj2->cursed
- : 0;
- if (val1 != val2) {
- return val2 - val1; /* Because bigger is better. */
+ res = cxname_singular(obj);
+
+ if (save_debug) {
+ flags.debug = TRUE;
+ program_state.something_worth_saving = 1;
+ }
+ /* restore the object */
+ if (obj->oclass == POTION_CLASS) {
+ obj->odiluted = saveo.odiluted;
+ if (obj->otyp == POT_WATER)
+ obj->blessed = saveo.blessed, obj->cursed = saveo.cursed;
+ }
+ if (obj->otyp == TOWEL) {
+ obj->spe = saveo.spe;
+ /* give "towel" a suffix that will force wet ones to come first,
+ moist ones next, and dry ones last regardless of whether
+ they've been flagged as having spe known */
+ Strcat(res, is_wet_towel(obj) ? ((obj->spe >= 3) ? "x" : "y") : "z");
+ }
+ if (obj->globby) {
+ obj->owt = saveo.owt;
+ /* we've suppressed the size prefix (above); there normally won't
+ be more than one of a given creature type because they coalesce,
+ but globs with different bless/curse state won't merge so it is
+ feasible to have multiple at the same location; add a suffix to
+ get such sorted by size (small first) */
+ Strcat(res, (obj->owt <= 100) ? "a"
+ : (obj->owt <= 300) ? "b"
+ : (obj->owt <= 500) ? "c"
+ : "d");
}
+ if (save_oname && !obj->oartifact)
+ ONAME(obj) = save_oname;
- /* Sort by greasing. This will put the objects in degreasing order. */
+ return res;
+}
+
+/* set by sortloot() for use by sortloot_cmp(); reset by sortloot when done */
+static unsigned sortlootmode = 0;
+
+/* qsort comparison routine for sortloot() */
+STATIC_OVL int CFDECLSPEC
+sortloot_cmp(vptr1, vptr2)
+const genericptr vptr1;
+const genericptr vptr2;
+{
+ struct sortloot_item *sli1 = (struct sortloot_item *) vptr1,
+ *sli2 = (struct sortloot_item *) vptr2;
+ struct obj *obj1 = sli1->obj,
+ *obj2 = sli2->obj;
+ char *nam1, *nam2;
+ int val1, val2, c, namcmp;
+
+ /* order by object class unless we're doing by-invlet without sortpack */
+ if ((sortlootmode & (SORTLOOT_PACK | SORTLOOT_INVLET))
+ != SORTLOOT_INVLET) {
+ /* Classify each object at most once no matter how many
+ comparisons it is involved in. */
+ if (!sli1->orderclass)
+ loot_classify(sli1, obj1);
+ if (!sli2->orderclass)
+ loot_classify(sli2, obj2);
+
+ /* Sort by class. */
+ val1 = sli1->orderclass;
+ val2 = sli2->orderclass;
+ if (val1 != val2)
+ return (int) (val1 - val2);
+
+ /* skip sub-classes when ordering by sortpack+invlet */
+ if ((sortlootmode & SORTLOOT_INVLET) == 0) {
+ /* Class matches; sort by subclass. */
+ val1 = sli1->subclass;
+ val2 = sli2->subclass;
+ if (val1 != val2)
+ return val1 - val2;
+
+ /* Class and subclass match; sort by discovery status:
+ * first unseen, then seen but not named or discovered,
+ * then named, lastly discovered.
+ * 1) potion
+ * 2) pink potion
+ * 3) dark green potion called confusion
+ * 4) potion of healing
+ * Multiple entries within each group will be put into
+ * alphabetical order below.
+ */
+ val1 = sli1->disco;
+ val2 = sli2->disco;
+ if (val1 != val2)
+ return val1 - val2;
+ }
+ }
+
+ /* order by assigned inventory letter */
+ if ((sortlootmode & SORTLOOT_INVLET) != 0) {
+ c = obj1->invlet;
+ val1 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
+ : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
+ : (c == '$') ? 1
+ : (c == '#') ? 1 + 52 + 1
+ : 1 + 52 + 1 + 1; /* none of the above */
+ c = obj2->invlet;
+ val2 = ('a' <= c && c <= 'z') ? (c - 'a' + 2)
+ : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
+ : (c == '$') ? 1
+ : (c == '#') ? 1 + 52 + 1
+ : 1 + 52 + 1 + 1; /* none of the above */
+ if (val1 != val2)
+ return val1 - val2;
+ }
+
+ if ((sortlootmode & SORTLOOT_LOOT) == 0)
+ goto tiebreak;
+
+ /*
+ * Sort object names in lexicographical order, ignoring quantity.
+ *
+ * Each obj gets formatted at most once (per sort) no matter how many
+ * comparisons it gets subjected to.
+ */
+ nam1 = sli1->str;
+ if (!nam1)
+ nam1 = sli1->str = dupstr(loot_xname(obj1));
+ nam2 = sli2->str;
+ if (!nam2)
+ nam2 = sli2->str = dupstr(loot_xname(obj2));
+ if ((namcmp = strcmpi(nam1, nam2)) != 0)
+ return namcmp;
+
+ /* Sort by BUCX. */
+ val1 = obj1->bknown ? (obj1->blessed ? 3 : !obj1->cursed ? 2 : 1) : 0;
+ val2 = obj2->bknown ? (obj2->blessed ? 3 : !obj2->cursed ? 2 : 1) : 0;
+ if (val1 != val2)
+ return val2 - val1; /* bigger is better */
+
+ /* Sort by greasing. This will put the objects in degreasing order. */
val1 = obj1->greased;
val2 = obj2->greased;
- if (val1 != val2) {
- return val2 - val1; /* Because bigger is better. */
- }
+ if (val1 != val2)
+ return val2 - val1; /* bigger is better */
- /* Sort by erosion. The effective amount is what matters. */
+ /* Sort by erosion. The effective amount is what matters. */
val1 = greatest_erosion(obj1);
val2 = greatest_erosion(obj2);
- if (val1 != val2) {
- return val1 - val2; /* Because bigger is WORSE. */
- }
+ if (val1 != val2)
+ return val1 - val2; /* bigger is WORSE */
- /* Sort by erodeproofing. Map known-invulnerable to 1, and both
- * known-vulnerable and unknown-vulnerability to 0, because that's how
- * they're displayed. */
+ /* Sort by erodeproofing. Map known-invulnerable to 1, and both
+ known-vulnerable and unknown-vulnerability to 0, because that's
+ how they're displayed. */
val1 = obj1->rknown && obj1->oerodeproof;
val2 = obj2->rknown && obj2->oerodeproof;
- if (val1 != val2) {
- return val2 - val1; /* Because bigger is better. */
+ if (val1 != val2)
+ return val2 - val1; /* bigger is better */
+
+ /* Sort by enchantment. Map unknown to -1000, which is comfortably
+ below the range of obj->spe. oc_uses_known means that obj->known
+ matters, which usually indirectly means that obj->spe is relevant.
+ Lots of objects use obj->spe for some other purpose (see obj.h). */
+ if (objects[obj1->otyp].oc_uses_known
+ /* exclude eggs (laid by you) and tins (homemade, pureed, &c) */
+ && obj1->oclass != FOOD_CLASS) {
+ val1 = obj1->known ? obj1->spe : -1000;
+ val2 = obj2->known ? obj2->spe : -1000;
+ if (val1 != val2)
+ return val2 - val1; /* bigger is better */
}
- /* Sort by enchantment. Map unknown to -1000, which is comfortably below
- * the range of ->spe. */
- val1 = obj1->known ? obj1->spe : -1000;
- val2 = obj2->known ? obj2->spe : -1000;
- if (val1 != val2) {
- return val2 - val1; /* Because bigger is better. */
- }
+ tiebreak:
+ /* They're identical, as far as we're concerned. We want
+ to force a deterministic order, and do so by producing a
+ stable sort: maintain the original order of equal items. */
+ return (sli1->indx - sli2->indx);
+}
- /* They're identical, as far as we're concerned,
- but we want to force a determistic order between them. */
- return (obj1->o_id > obj2->o_id) ? 1 : -1;
+/*
+ * sortloot() - the story so far...
+ *
+ * The original implementation constructed and returned an array
+ * of pointers to objects in the requested order. Callers had to
+ * count the number of objects, allocate the array, pass one
+ * object at a time to the routine which populates it, traverse
+ * the objects via stepping through the array, then free the
+ * array. The ordering process used a basic insertion sort which
+ * is fine for short lists but inefficient for long ones.
+ *
+ * 3.6.0 (and continuing with 3.6.1) changed all that so that
+ * sortloot was self-contained as far as callers were concerned.
+ * It reordered the linked list into the requested order and then
+ * normal list traversal was used to process it. It also switched
+ * to qsort() on the assumption that the C library implementation
+ * put some effort into sorting efficiently. It also checked
+ * whether the list was already sorted as it got ready to do the
+ * sorting, so re-examining inventory or a pile of objects without
+ * having changed anything would gobble up less CPU than a full
+ * sort. But it had at least two problems (aside from the ordinary
+ * complement of bugs):
+ * 1) some players wanted to get the original order back when they
+ * changed the 'sortloot' option back to 'none', but the list
+ * reordering made that infeasible;
+ * 2) object identification giving the 'ID whole pack' result
+ * would call makeknown() on each newly ID'd object, that would
+ * call update_inventory() to update the persistent inventory
+ * window if one existed, the interface would call the inventory
+ * display routine which would call sortloot() which might change
+ * the order of the list being traversed by the identify code,
+ * possibly skipping the ID of some objects. That could have been
+ * avoided by suppressing 'perm_invent' during identification
+ * (fragile) or by avoiding sortloot() during inventory display
+ * (more robust).
+ *
+ * 3.6.2 reverts to the temporary array of ordered obj pointers
+ * but has sortloot() do the counting and allocation. Callers
+ * need to use array traversal instead of linked list traversal
+ * and need to free the temporary array when done. And the
+ * array contains 'struct sortloot_item' (aka 'Loot') entries
+ * instead of simple 'struct obj *' entries.
+ */
+Loot *
+sortloot(olist, mode, by_nexthere, filterfunc)
+struct obj **olist; /* previous version might have changed *olist, we don't */
+unsigned mode; /* flags for sortloot_cmp() */
+boolean by_nexthere; /* T: traverse via obj->nexthere, F: via obj->nobj */
+boolean FDECL((*filterfunc), (OBJ_P));
+{
+ Loot *sliarray;
+ struct obj *o;
+ unsigned n, i;
+ boolean augment_filter;
+
+ for (n = 0, o = *olist; o; o = by_nexthere ? o->nexthere : o->nobj)
+ ++n;
+ /* note: if there is a filter function, this might overallocate */
+ sliarray = (Loot *) alloc((n + 1) * sizeof *sliarray);
+
+ /* the 'keep cockatrice corpses' flag is overloaded with sort mode */
+ augment_filter = (mode & SORTLOOT_PETRIFY) ? TRUE : FALSE;
+ mode &= ~SORTLOOT_PETRIFY; /* remove flag, leaving mode */
+ /* populate aliarray[0..n-1] */
+ for (i = 0, o = *olist; o; o = by_nexthere ? o->nexthere : o->nobj) {
+ if (filterfunc && !(*filterfunc)(o)
+ /* caller may be asking us to override filterfunc (in order
+ to do a cockatrice corpse touch check during pickup even
+ if/when the filter rejects food class) */
+ && (!augment_filter || o->otyp != CORPSE
+ || !touch_petrifies(&mons[o->corpsenm])))
+ continue;
+ sliarray[i].obj = o, sliarray[i].indx = (int) i;
+ sliarray[i].str = (char *) 0;
+ sliarray[i].orderclass = sliarray[i].subclass = sliarray[i].disco = 0;
+ ++i;
+ }
+ n = i;
+ /* add a terminator so that we don't have to pass 'n' back to caller */
+ sliarray[n].obj = (struct obj *) 0, sliarray[n].indx = -1;
+ sliarray[n].str = (char *) 0;
+ sliarray[n].orderclass = sliarray[n].subclass = sliarray[n].disco = 0;
+
+ /* do the sort; if no sorting is requested, we'll just return
+ a sortloot_item array reflecting the current ordering */
+ if (mode && n > 1) {
+ sortlootmode = mode; /* extra input for sortloot_cmp() */
+ qsort((genericptr_t) sliarray, n, sizeof *sliarray, sortloot_cmp);
+ sortlootmode = 0; /* reset static mode flags */
+ /* if sortloot_cmp formatted any objects, discard their strings now */
+ for (i = 0; i < n; ++i)
+ if (sliarray[i].str)
+ free((genericptr_t) sliarray[i].str), sliarray[i].str = 0;
+ }
+ return sliarray;
}
-struct obj **
-objarr_init(n)
-int n;
+/* sortloot() callers should use this to free up memory it allocates */
+void
+unsortloot(loot_array_p)
+Loot **loot_array_p;
{
- return (struct obj **) alloc(n * sizeof(struct obj *));
+ if (*loot_array_p)
+ free((genericptr_t) *loot_array_p), *loot_array_p = (Loot *) 0;
}
+#if 0 /* 3.6.0 'revamp' */
void
-objarr_set(otmp, idx, oarray, dosort)
-struct obj *otmp;
-int idx;
-struct obj **oarray;
-boolean dosort;
-{
- if (dosort) {
- int j;
- for (j = idx; j; j--) {
- if (sortloot_cmp(otmp, oarray[j - 1]) > 0)
- break;
- oarray[j] = oarray[j - 1];
+sortloot(olist, mode, by_nexthere)
+struct obj **olist;
+unsigned mode; /* flags for sortloot_cmp() */
+boolean by_nexthere; /* T: traverse via obj->nexthere, F: via obj->nobj */
+{
+ struct sortloot_item *sliarray, osli, nsli;
+ struct obj *o, **nxt_p;
+ unsigned n, i;
+ boolean already_sorted = TRUE;
+
+ sortlootmode = mode; /* extra input for sortloot_cmp() */
+ for (n = osli.indx = 0, osli.obj = *olist; (o = osli.obj) != 0;
+ osli = nsli) {
+ nsli.obj = by_nexthere ? o->nexthere : o->nobj;
+ nsli.indx = (int) ++n;
+ if (nsli.obj && already_sorted
+ && sortloot_cmp((genericptr_t) &osli, (genericptr_t) &nsli) > 0)
+ already_sorted = FALSE;
+ }
+ if (n > 1 && !already_sorted) {
+ sliarray = (struct sortloot_item *) alloc(n * sizeof *sliarray);
+ for (i = 0, o = *olist; o;
+ ++i, o = by_nexthere ? o->nexthere : o->nobj)
+ sliarray[i].obj = o, sliarray[i].indx = (int) i;
+
+ qsort((genericptr_t) sliarray, n, sizeof *sliarray, sortloot_cmp);
+ for (i = 0; i < n; ++i) {
+ o = sliarray[i].obj;
+ nxt_p = by_nexthere ? &(o->nexthere) : &(o->nobj);
+ *nxt_p = (i < n - 1) ? sliarray[i + 1].obj : (struct obj *) 0;
}
- oarray[j] = otmp;
- } else {
- oarray[idx] = otmp;
+ *olist = sliarray[0].obj;
+ free((genericptr_t) sliarray);
}
+ sortlootmode = 0;
}
+#endif /*0*/
void
assigninvlet(otmp)
*
* Don't do the age manipulation if lit. We would need
* to stop the burn on both items, then merge the age,
- * then restart the burn.
+ * then restart the burn. Glob ages are averaged in the
+ * absorb routine, which uses weight rather than quantity
+ * to adjust for proportion (glob quantity is always 1).
*/
- if (!obj->lamplit)
+ if (!obj->lamplit && !obj->globby)
otmp->age = ((otmp->age * otmp->quan) + (obj->age * obj->quan))
/ (otmp->quan + obj->quan);
otmp->quan += obj->quan;
/* temporary special case for gold objects!!!! */
if (otmp->oclass == COIN_CLASS)
- otmp->owt = weight(otmp);
+ otmp->owt = weight(otmp), otmp->bknown = 0;
/* and puddings!!!1!!one! */
else if (!Is_pudding(otmp))
otmp->owt += obj->owt;
#endif /*0*/
}
- /* handle puddings a bit differently; absorption will
- * free the other object automatically so we can just
- * return out from here. */
- if (Is_pudding(obj)) {
+ /* handle puddings a bit differently; absorption will free the
+ other object automatically so we can just return out from here */
+ if (obj->globby) {
pudding_merge_message(otmp, obj);
obj_absorb(potmp, pobj);
return 1;
}
set_artifact_intrinsic(obj, 1, W_ART);
}
- if (obj->otyp == LUCKSTONE && obj->record_achieve_special) {
+
+ /* "special achievements" aren't discoverable during play, they
+ end up being recorded in XLOGFILE at end of game, nowhere else;
+ record_achieve_special overloads corpsenm which is ordinarily
+ initialized to NON_PM (-1) rather than to 0; any special prize
+ must never be a corpse, egg, tin, figurine, or statue because
+ their use of obj->corpsenm for monster type would conflict,
+ nor be a leash (corpsenm overloaded for m_id of leashed
+ monster) or a novel (corpsenm overloaded for novel index) */
+ if (is_mines_prize(obj)) {
u.uachieve.mines_luckstone = 1;
- obj->record_achieve_special = 0;
- } else if ((obj->otyp == AMULET_OF_REFLECTION
- || obj->otyp == BAG_OF_HOLDING)
- && obj->record_achieve_special) {
+ obj->record_achieve_special = NON_PM;
+ obj->nomerge = 0;
+ } else if (is_soko_prize(obj)) {
u.uachieve.finish_sokoban = 1;
- obj->record_achieve_special = 0;
+ obj->record_achieve_special = NON_PM;
+ obj->nomerge = 0;
}
}
{
struct obj *otmp, *prev;
int saved_otyp = (int) obj->otyp; /* for panic */
+ boolean obj_was_thrown;
if (obj->where != OBJ_FREE)
panic("addinv: obj not free");
obj->no_charge = 0; /* should not be set in hero's invent */
if (Has_contents(obj))
picked_container(obj); /* clear no_charge */
+ obj_was_thrown = obj->was_thrown;
obj->was_thrown = 0; /* not meaningful for invent */
addinv_core1(obj);
}
obj->where = OBJ_INVENT;
-added:
+ /* fill empty quiver if obj was thrown */
+ if (flags.pickup_thrown && !uquiver && obj_was_thrown
+ /* if Mjollnir is thrown and fails to return, we want to
+ auto-pick it when we move to its spot, but not into quiver;
+ aklyses behave like Mjollnir when thrown while wielded, but
+ we lack sufficient information here make them exceptions */
+ && obj->oartifact != ART_MJOLLNIR
+ && (throwing_weapon(obj) || is_ammo(obj)))
+ setuqwep(obj);
+ added:
addinv_core2(obj);
carry_obj_effects(obj); /* carrying affects the obj */
update_inventory();
carry_obj_effects(obj)
struct obj *obj;
{
- /* Cursed figurines can spontaneously transform
- when carried. */
+ /* Cursed figurines can spontaneously transform when carried. */
if (obj->otyp == FIGURINE) {
if (obj->cursed && obj->corpsenm != NON_PM
&& !dead_species(obj->corpsenm, TRUE)) {
}
}
if (Fumbling) {
- if (drop_fmt)
- pline(drop_fmt, drop_arg);
- dropy(obj);
+ obj->nomerge = 1;
+ obj = addinv(obj); /* dropping expects obj to be in invent */
+ goto drop_it;
} else {
long oquan = obj->quan;
int prev_encumbr = near_capacity(); /* before addinv() */
obj = addinv(obj);
if (inv_cnt(FALSE) > 52 || ((obj->otyp != LOADSTONE || !obj->cursed)
&& near_capacity() > prev_encumbr)) {
- if (drop_fmt)
- pline(drop_fmt, drop_arg);
/* undo any merge which took place */
if (obj->quan > oquan)
obj = splitobj(obj, oquan);
- dropx(obj);
+ goto drop_it;
} else {
if (flags.autoquiver && !uquiver && !obj->owornmask
&& (is_missile(obj) || ammo_and_launcher(obj, uwep)
}
}
return obj;
+
+ drop_it:
+ if (drop_fmt)
+ pline(drop_fmt, drop_arg);
+ obj->nomerge = 0;
+ if (can_reach_floor(TRUE)) {
+ dropx(obj);
+ } else {
+ freeinv(obj);
+ hitfloor(obj, FALSE);
+ }
+ return (struct obj *) 0; /* might be gone */
}
/* useup() all of an item regardless of its quantity */
* http://concord.wikia.com/wiki/List_of_Fictional_Currencies
*/
static const char *const currencies[] = {
+#if 0 /*JP*/
"Altarian Dollar", /* The Hitchhiker's Guide to the Galaxy */
"Ankh-Morpork Dollar", /* Discworld */
"auric", /* The Domination of Draka */
"Triganic Pu", /* The Hitchhiker's Guide to the Galaxy */
"woolong", /* Cowboy Bebop */
"zorkmid", /* Zork, NetHack */
+#else
+ "\83A\83\8b\83^\83C\83\8b\81E\83h\83\8b", /* The Hitchhiker's Guide to the Galaxy */
+ "\83A\83\93\83N\83\82\83\8b\83|\81[\83N\81E\83h\83\8b", /* Discworld */
+ "\83\86\81[\83\8a\83b\83N", /* The Domination of Draka */
+ "\83o\83b\83J\83]\83C\83h", /* Space Quest */
+ "\83T\81[\83{\83]\83C\83h", /* Starslip */
+ "\83N\83\8c\83W\83b\83g\81E\83`\83b\83g", /* Deus Ex */
+ "\83L\83\85\81[\83r\83b\83g", /* Battlestar Galactica */
+ "\83t\83\8c\83j\83A\83\93\81E\83s\83b\83u\83\8b\81E\83r\81[\83h", /* The Hitchhiker's Guide to the Galaxy */
+ "\83t\83\8c\83b\83c\83@", /* Jules Verne */
+ "\92é\8d\91\83N\83\8c\83W\83b\83g", /* Star Wars */
+ "\8d\81\8d`\8c\8e\83h\83\8b", /* The Moon is a Harsh Mistress */
+ "\83R\83\93\83o\83b\83N", /* Snow Crash */
+ "\83i\81[\83i\83C\83g", /* System Shock 2 */
+ "\83N\83@\83g\83\8d", /* Star Trek, Sim City */
+ "\83V\83\82\83\8c\83I\83\93", /* Sim City */
+ "\83\\83\89\83\8a", /* Spaceballs */
+ "\83X\83y\81[\83X\83o\83b\83N", /* Spaceballs */
+ "\83X\83|\83A\83o\83b\83N", /* Spore */
+ "\83g\83\89\83C\83K\83j\83b\83N\81E\83v\81[", /* The Hitchhiker's Guide to the Galaxy */
+ "\83E\81[\83\8d\83\93", /* Cowboy Bebop */
+ "\83S\81[\83\8b\83h", /* Zork, NetHack */
+#endif
};
const char *
{
const char *res;
+#if 0 /*JP*/
res = Hallucination ? currencies[rn2(SIZE(currencies))] : "zorkmid";
if (amount != 1L)
res = makeplural(res);
+#else
+ res = Hallucination ? currencies[rn2(SIZE(currencies))] : "\83S\81[\83\8b\83h";
+#endif
return res;
}
return FALSE;
}
-/* 3.6.0 tribute */
+/* 3.6 tribute */
struct obj *
u_have_novel()
{
}
/* some objects shouldn't be split when count given to getobj or askchain */
-STATIC_OVL boolean
+boolean
splittable(obj)
struct obj *obj;
{
!!!! test if gold can be used in unusual ways (eaten etc.)
!!!! may be able to remove "usegold"
*/
+/*JP
+** word \82É\82Í\89p\8cê\82Å\93®\8e\8c\82ª\93ü\82é\81D
+**
+** \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
+** \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
+**
+*/
struct obj *
getobj(let, word)
register const char *let, *word;
{
register struct obj *otmp;
- register char ilet;
+ register char ilet = 0;
char buf[BUFSZ], qbuf[QBUFSZ];
char lets[BUFSZ], altlets[BUFSZ], *ap;
register int foo = 0;
register char *bp = buf;
xchar allowcnt = 0; /* 0, 1 or 2 */
- struct obj *firstobj = invent;
boolean usegold = FALSE; /* can't use gold because its illegal */
boolean allowall = FALSE;
boolean allownone = FALSE;
boolean useboulder = FALSE;
xchar foox = 0;
- long cnt, prevcnt;
- boolean prezero;
+ long cnt;
+ boolean cntgiven = FALSE;
+ boolean msggiven = FALSE;
+ boolean oneloop = FALSE;
long dummymask;
+ Loot *sortedinvent, *srtinv;
+
+#if 1 /*JP*/
+ const char *jword;
+ const char *joshi;
+ const char *what;
+ struct trans_verb *tv = trans_verb(word);
+
+ jword = tv->jp;
+ what = tv->what;
+ joshi = tv->particle;
+#endif
if (*let == ALLOW_COUNT)
let++, allowcnt = 1;
if (*let == COIN_CLASS)
useboulder = TRUE;
if (allownone)
- *bp++ = '-';
- if (bp > buf && bp[-1] == '-')
- *bp++ = ' ';
+ *bp++ = HANDS_SYM, *bp++ = ' '; /* '-' */
ap = altlets;
if (!flags.invlet_constant)
reassign();
- for (otmp = firstobj; otmp; otmp = otmp->nobj) {
+ /* force invent to be in invlet order before collecting candidate
+ inventory letters */
+ sortedinvent = sortloot(&invent, SORTLOOT_INVLET, FALSE,
+ (boolean FDECL((*), (OBJ_P))) 0);
+
+ for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
if (&bp[foo] == &buf[sizeof buf - 1]
|| ap == &altlets[sizeof altlets - 1]) {
/* we must have a huge number of NOINVSYM items somehow */
|| (usegold && otmp->invlet == GOLD_SYM)
|| (useboulder && otmp->otyp == BOULDER)) {
register int otyp = otmp->otyp;
- bp[foo++] = otmp->invlet;
+ bp[foo++] = otmp->invlet;
/* clang-format off */
/* *INDENT-OFF* */
/* ugly check: remove inappropriate things */
|| (!strcmp(word, "wield")
&& (otmp->owornmask & W_WEP))
#endif
- || (!strcmp(word, "ready") /* exclude if wielded */
- && (otmp == uwep || (otmp == uswapwep && u.twoweap)))
+ || (!strcmp(word, "ready") /* exclude when wielded... */
+ && ((otmp == uwep || (otmp == uswapwep && u.twoweap))
+ && otmp->quan == 1L)) /* ...unless more than one */
|| ((!strcmp(word, "dip") || !strcmp(word, "grease"))
&& inaccessible_equipment(otmp, (const char *) 0, FALSE))
) {
&& (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown
|| !objects[HORN_OF_PLENTY].oc_name_known))
|| (!strcmp(word, "charge") && !is_chargeable(otmp))
+ || (!strcmp(word, "open") && otyp != TIN)
|| (!strcmp(word, "call") && !objtyp_is_callable(otyp))
+ || (!strcmp(word, "adjust") && otmp->oclass == COIN_CLASS
+ && !usegold)
) {
foo--;
}
&& (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
/* suppress container being stashed into */
|| (!strcmp(word, "stash") && !ck_bag(otmp))
- /* worn armor or accessory covered by cursed worn armor */
+ /* worn armor (shirt, suit) covered by worn armor (suit, cloak)
+ or accessory (ring) covered by cursed worn armor (gloves) */
|| (taking_off(word)
- && inaccessible_equipment(otmp, (const char *) 0, TRUE))
+ && inaccessible_equipment(otmp, (const char *) 0,
+ (boolean) (otmp->oclass == RING_CLASS)))
+ || (!strcmp(word, "write on")
+ && (!(otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER)
+ || !otmp->dknown || !objects[otyp].oc_name_known))
) {
/* acceptable but not listed as likely candidate */
foo--;
allowall = usegold = TRUE;
}
}
+ unsortloot(&sortedinvent);
bp[foo] = 0;
if (foo == 0 && bp > buf && bp[-1] == ' ')
*ap = '\0';
if (!foo && !allowall && !allownone) {
+/*JP
You("don't have anything %sto %s.", foox ? "else " : "", word);
+*/
+ You("%s%s\82à\82Ì\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81D", foox ? "\91¼\82É" : "", jconj(jword, "\82ê\82é"));
return (struct obj *) 0;
+ } else if (!strcmp(word, "write on")) { /* ugly check for magic marker */
+ /* we wanted all scrolls and books in altlets[], but that came with
+ 'allowall' which we don't want since it prevents "silly thing"
+ result if anything other than scroll or spellbook is chosen */
+ allowall = FALSE;
}
for (;;) {
cnt = 0;
- if (allowcnt == 2)
- allowcnt = 1; /* abort previous count */
- prezero = FALSE;
- if (!buf[0]) {
- Sprintf(qbuf, "What do you want to %s? [*]", word);
- } else {
- Sprintf(qbuf, "What do you want to %s? [%s or ?*]", word, buf);
- }
+ cntgiven = FALSE;
+/*JP
+ Sprintf(qbuf, "What do you want to %s?", word);
+*/
+ Sprintf(qbuf, "%s%s%s\82©\81H", what, joshi, jpolite(jword));
if (in_doagain)
ilet = readchar();
- else
+ else if (iflags.force_invmenu) {
+ /* don't overwrite a possible quitchars */
+ if (!oneloop)
+ ilet = *let ? '?' : '*';
+ if (!msggiven)
+ putmsghistory(qbuf, FALSE);
+ msggiven = TRUE;
+ oneloop = TRUE;
+ } else {
+ if (!buf[0])
+ Strcat(qbuf, " [*]");
+ else
+ Sprintf(eos(qbuf), " [%s or ?*]", buf);
ilet = yn_function(qbuf, (char *) 0, '\0');
- if (digit(ilet) && !allowcnt) {
- pline("No count allowed with this command.");
- continue;
}
- if (ilet == '0')
- prezero = TRUE;
- while (digit(ilet)) {
- if (ilet != '?' && ilet != '*')
- savech(ilet);
- /* accumulate unless cnt has overflowed */
- if (allowcnt < 3) {
- prevcnt = cnt;
- cnt = 10L * cnt + (long) (ilet - '0');
- /* signal presence of cnt */
- allowcnt = (cnt >= prevcnt) ? 2 : 3;
+ if (digit(ilet)) {
+ long tmpcnt = 0;
+
+ if (!allowcnt) {
+/*JP
+ pline("No count allowed with this command.");
+*/
+ pline("\82±\82Ì\83R\83}\83\93\83h\82É\90\94\8e\9a\82Í\82Â\82©\82¦\82È\82¢\81D");
+ continue;
+ }
+ ilet = get_count(NULL, ilet, LARGEST_INT, &tmpcnt, TRUE);
+ if (tmpcnt) {
+ cnt = tmpcnt;
+ cntgiven = TRUE;
}
- ilet = readchar();
- }
- if (allowcnt == 3) {
- /* overflow detected; force cnt to be invalid */
- cnt = -1L;
- allowcnt = 2;
}
if (index(quitchars, ilet)) {
if (flags.verbose)
pline1(Never_mind);
return (struct obj *) 0;
}
- if (ilet == '-') {
+ if (ilet == HANDS_SYM) { /* '-' */
if (!allownone) {
+#if 0 /*JP*/
char *suf = (char *) 0;
strcpy(buf, word);
bp = buf;
You("mime %s something%s%s.", ing_suffix(bp), suf ? " " : "",
suf ? suf : "");
+#else
+ You("\89½\82©\82ð%s\82Ó\82è\82ð\82µ\82½\81D", bp);
+#endif
}
- return (allownone ? &zeroobj : (struct obj *) 0);
+ return (allownone ? (struct obj *) &zeroobj : (struct obj *) 0);
}
+ redo_menu:
/* since gold is now kept in inventory, we need to do processing for
select-from-invent before checking whether gold has been picked */
if (ilet == '?' || ilet == '*') {
char *allowed_choices = (ilet == '?') ? lets : (char *) 0;
long ctmp = 0;
+ char menuquery[QBUFSZ];
+
+ menuquery[0] = qbuf[0] = '\0';
+ if (iflags.force_invmenu)
+ Sprintf(menuquery, "What do you want to %s?", word);
+ if (!strcmp(word, "grease"))
+ Sprintf(qbuf, "your %s", makeplural(body_part(FINGER)));
+ else if (!strcmp(word, "write with"))
+ Sprintf(qbuf, "your %s", body_part(FINGERTIP));
+ else if (!strcmp(word, "wield"))
+ Sprintf(qbuf, "your %s %s%s", uarmg ? "gloved" : "bare",
+ makeplural(body_part(HAND)),
+ !uwep ? " (wielded)" : "");
+ else if (!strcmp(word, "ready"))
+ Sprintf(qbuf, "empty quiver%s",
+ !uquiver ? " (nothing readied)" : "");
if (ilet == '?' && !*lets && *altlets)
allowed_choices = altlets;
- ilet = display_pickinv(allowed_choices, TRUE,
- allowcnt ? &ctmp : (long *) 0);
+ ilet = display_pickinv(allowed_choices, *qbuf ? qbuf : (char *) 0,
+ menuquery,
+ TRUE, allowcnt ? &ctmp : (long *) 0);
if (!ilet)
continue;
- if (allowcnt && ctmp >= 0) {
- cnt = ctmp;
- if (!cnt)
- prezero = TRUE;
- allowcnt = 2;
- }
+ if (ilet == HANDS_SYM)
+ return (struct obj *) &zeroobj; /* cast away 'const' */
if (ilet == '\033') {
if (flags.verbose)
pline1(Never_mind);
return (struct obj *) 0;
}
+ if (ilet == '*')
+ goto redo_menu;
+ if (allowcnt && ctmp >= 0) {
+ cnt = ctmp;
+ cntgiven = TRUE;
+ }
/* they typed a letter (not a space) at the prompt */
}
/* find the item which was picked */
than one invent slot of gold and picking the non-'$' one */
|| (otmp && otmp->oclass == COIN_CLASS)) {
if (!usegold) {
+/*JP
You("cannot %s gold.", word);
+*/
+ You("\8bà\89Ý%s%s\82±\82Æ\82Í\82Å\82«\82È\82¢\81D", joshi, jword);
return (struct obj *) 0;
}
/* Historic note: early Nethack had a bug which was
* to your money supply. The LRS is the tax bureau
* from Larn.
*/
- if (allowcnt == 2 && cnt <= 0) {
- if (cnt < 0 || !prezero)
+ if (cntgiven && cnt <= 0) {
+ if (cnt < 0)
pline_The(
+/*JP
"LRS would be very interested to know you have that much.");
+*/
+ "\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");
return (struct obj *) 0;
}
}
- if (allowcnt == 2 && !strcmp(word, "throw")) {
+ if (cntgiven && !strcmp(word, "throw")) {
/* permit counts for throwing gold, but don't accept
* counts for other things since the throw code will
* split off a single item anyway */
- if (ilet != def_oc_syms[COIN_CLASS].sym
- && !(otmp && otmp->oclass == COIN_CLASS))
- allowcnt = 1;
- if (cnt == 0 && prezero)
+ if (cnt == 0)
return (struct obj *) 0;
- if (cnt > 1) {
+ if (cnt > 1 && (ilet != def_oc_syms[COIN_CLASS].sym
+ && !(otmp && otmp->oclass == COIN_CLASS))) {
+/*JP
You("can only throw one item at a time.");
+*/
+ You("\93¯\8e\9e\82É\82½\82\82³\82ñ\82Ì\82à\82Ì\82ð\93\8a\82°\82ç\82ê\82È\82¢\81D");
continue;
}
}
that's been moved above so that otmp can be checked earlier] */
/* verify the chosen object */
if (!otmp) {
+/*JP
You("don't have that object.");
+*/
+ You("\82»\82ñ\82È\82à\82Ì\82Í\8e\9d\82Á\82Ä\82¢\82È\82¢\81D");
if (in_doagain)
return (struct obj *) 0;
continue;
} else if (cnt < 0 || otmp->quan < cnt) {
+/*JP
You("don't have that many! You have only %ld.", otmp->quan);
+*/
+ 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);
if (in_doagain)
return (struct obj *) 0;
continue;
}
if (!allowall && let && !index(let, otmp->oclass)
&& !(usegold && otmp->oclass == COIN_CLASS)) {
+#if 0 /*JP*/
silly_thing(word, otmp);
+#else
+ silly_thing(jword, otmp);
+#endif
return (struct obj *) 0;
}
- if (allowcnt == 2) { /* cnt given */
+ if (cntgiven) {
if (cnt == 0)
return (struct obj *) 0;
if (cnt != otmp->quan) {
#if 1 /* 'P','R' vs 'W','T' handling is obsolete */
nhUse(otmp);
#else
- const char *s1, *s2, *s3, *what;
+ const char *s1, *s2, *s3;
int ocls = otmp->oclass, otyp = otmp->otyp;
s1 = s2 = s3 = 0;
/* check for attempted use of accessory commands ('P','R') on armor
and for corresponding armor commands ('W','T') on accessories */
if (ocls == ARMOR_CLASS) {
+#if 0 /*JP*/
if (!strcmp(word, "put on"))
s1 = "W", s2 = "wear", s3 = "";
else if (!strcmp(word, "remove"))
s1 = "T", s2 = "take", s3 = " off";
+#else
+ if (!strcmp(word, "\90g\82É\82Â\82¯\82é"))
+ s1 = "W", s2 = "\90g\82É\82Â\82¯\82é", s3 = "";
+ else if (!strcmp(word, "\82Í\82¸\82·"))
+ s1 = "T", s2 = "\82Í\82¸\82·", s3 = "";
+#endif
} else if ((ocls == RING_CLASS || otyp == MEAT_RING)
|| ocls == AMULET_CLASS
|| (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
+#if 0 /*JP*/
if (!strcmp(word, "wear"))
s1 = "P", s2 = "put", s3 = " on";
else if (!strcmp(word, "take off"))
s1 = "R", s2 = "remove", s3 = "";
+#else
+ if (!strcmp(word, "\90g\82É\82Â\82¯\82é"))
+ s1 = "P", s2 = "\90g\82É\82Â\82¯\82é", s3 = "";
+ else if (!strcmp(word, "\82Í\82¸\82·"))
+ s1 = "R", s2 = "\82Í\82¸\82·", s3 = "";
+#endif
}
- if (s1) {
- what = "that";
- /* quantity for armor and accessory objects is always 1,
- but some things should be referred to as plural */
- if (otyp == LENSES || is_gloves(otmp) || is_boots(otmp))
- what = "those";
- pline("Use the '%s' command to %s %s%s.", s1, s2, what, s3);
- } else
+ if (s1)
+#if 0 /*JP*/
+ pline("Use the '%s' command to %s %s%s.", s1, s2,
+ !(is_plural(otmp) || pair_of(otmp)) ? "that" : "those", s3);
+#else
+ pline("\82»\82ê\82ð%s\82É\82Í'%s'\83R\83}\83\93\83h\82ð\8eg\82¤\82±\82Æ\81D", s2, s1);
+#endif
+ else
#endif
pline(silly_thing_to, word);
}
RING_CLASS, AMULET_CLASS,
TOOL_CLASS, 0 };
-/* interactive version of getobj - used for Drop, Identify and */
-/* Takeoff (A). Return the number of times fn was called successfully */
-/* If combo is TRUE, we just use this to get a category list */
+/* Interactive version of getobj - used for Drop, Identify, and Takeoff (A).
+ Return the number of times fn was called successfully.
+ If combo is TRUE, we just use this to get a category list. */
+/*JP CHECK: 3.6.0 \82Ì\8cÄ\82Ñ\8fo\82µ\8c³
+do.c:962: || (result = ggetobj("drop", drop, 0, FALSE, (unsigned *) 0)) < -1)
+do.c:1009: i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
+do_wear.c:2955: || (result = ggetobj("take off", select_off, 0, FALSE,
+do_wear.c:3007: if (ggetobj("take off", select_off, 0, TRUE, (unsigned *) 0) == -2)
+invent.c:2014: n = ggetobj("identify", identify, id_limit, FALSE,
+*/
int
ggetobj(word, fn, mx, combo, resultflags)
const char *word;
unsigned *resultflags;
{
int FDECL((*ckfn), (OBJ_P)) = (int FDECL((*), (OBJ_P))) 0;
- boolean FDECL((*filter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
+ boolean FDECL((*ofilter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
boolean takeoff, ident, allflag, m_seen;
int itemcount;
int oletct, iletct, unpaid, oc_of_sym;
- char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 5];
+ char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 10];
char extra_removeables[3 + 1]; /* uwep,uswapwep,uquiver */
- char buf[BUFSZ], qbuf[QBUFSZ];
+ char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ];
+#if 1 /*JP*/
+ const char *joshi = "\82ð";
+ const char *jword;
+
+ const struct trans_verb *tv = trans_verb(word);
+ jword = tv->jp;
+ joshi = tv->particle;
+#endif
- if (resultflags)
- *resultflags = 0;
- takeoff = ident = allflag = m_seen = FALSE;
if (!invent) {
+/*JP
You("have nothing to %s.", word);
+*/
+ You("%s\82à\82Ì\82Í\8e\9d\82Á\82Ä\82¢\82È\82¢\81D", jcan(jword));
+ if (resultflags)
+ *resultflags = ALL_FINISHED;
return 0;
}
+ if (resultflags)
+ *resultflags = 0;
+ takeoff = ident = allflag = m_seen = FALSE;
add_valid_menu_class(0); /* reset */
if (taking_off(word)) {
takeoff = TRUE;
- filter = is_worn;
+ ofilter = is_worn;
} else if (!strcmp(word, "identify")) {
ident = TRUE;
- filter = not_fully_identified;
+ ofilter = not_fully_identified;
}
- iletct = collect_obj_classes(ilets, invent, FALSE, filter, &itemcount);
+ iletct = collect_obj_classes(ilets, invent, FALSE, ofilter, &itemcount);
unpaid = count_unpaid(invent);
if (ident && !iletct) {
return -1; /* no further identifications */
- } else if (!takeoff && (unpaid || invent)) {
+ } else if (invent) {
ilets[iletct++] = ' ';
if (unpaid)
ilets[iletct++] = 'u';
- if (count_buc(invent, BUC_BLESSED))
+ if (count_buc(invent, BUC_BLESSED, ofilter))
ilets[iletct++] = 'B';
- if (count_buc(invent, BUC_UNCURSED))
+ if (count_buc(invent, BUC_UNCURSED, ofilter))
ilets[iletct++] = 'U';
- if (count_buc(invent, BUC_CURSED))
+ if (count_buc(invent, BUC_CURSED, ofilter))
ilets[iletct++] = 'C';
- if (count_buc(invent, BUC_UNKNOWN))
+ if (count_buc(invent, BUC_UNKNOWN, ofilter))
ilets[iletct++] = 'X';
- if (invent)
- ilets[iletct++] = 'a';
- } else if (takeoff && invent) {
- ilets[iletct++] = ' ';
+ ilets[iletct++] = 'a';
}
ilets[iletct++] = 'i';
if (!combo)
ilets[iletct] = '\0';
for (;;) {
- Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]", word,
- ilets);
+#if 0 /*JP*/
+ Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]",
+ word, ilets);
+#else
+ Sprintf(qbuf,"\82Ç\82Ì\8eí\97Þ\82Ì\82à\82Ì%s%s\82©\81H[%s]", joshi,
+ jpolite(jword), ilets);
+#endif
getlin(qbuf, buf);
if (buf[0] == '\033')
return 0;
if (index(buf, 'i')) {
- if (display_inventory((char *) 0, TRUE) == '\033')
+ char ailets[1+26+26+1+5+1]; /* $ + a-z + A-Z + # + slop + \0 */
+ struct obj *otmp;
+
+ /* applicable inventory letters; if empty, show entire invent */
+ ailets[0] = '\0';
+ if (ofilter)
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ /* index() check: limit overflow items to one '#' */
+ if ((*ofilter)(otmp) && !index(ailets, otmp->invlet))
+ (void) strkitten(ailets, otmp->invlet);
+ if (display_inventory(ailets, TRUE) == '\033')
return 0;
} else
break;
if (index(extra_removeables, oc_of_sym)) {
; /* skip rest of takeoff checks */
} else if (!index(removeables, oc_of_sym)) {
+/*JP
pline("Not applicable.");
+*/
+ pline("\82»\82ê\82Í\82Å\82«\82È\82¢\81D");
return 0;
} else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
noarmor(FALSE);
return 0;
} else if (oc_of_sym == WEAPON_CLASS && !uwep && !uswapwep
&& !uquiver) {
+/*JP
You("are not wielding anything.");
+*/
+ You("\89½\82à\91\95\94õ\82µ\82Ä\82¢\82È\82¢\81D");
return 0;
} else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
+/*JP
You("are not wearing rings.");
+*/
+ You("\8ew\97Ö\82ð\90g\82É\82Â\82¯\82Ä\82¢\82È\82¢\81D");
return 0;
} else if (oc_of_sym == AMULET_CLASS && !uamul) {
+/*JP
You("are not wearing an amulet.");
+*/
+ You("\96\82\8f\9c\82¯\82ð\90g\82É\82Â\82¯\82Ä\82¢\82È\82¢\81D");
return 0;
} else if (oc_of_sym == TOOL_CLASS && !ublindf) {
+/*JP
You("are not wearing a blindfold.");
+*/
+ You("\96Ú\89B\82µ\82ð\82µ\82Ä\82¢\82È\82¢\81D");
return 0;
}
}
} else if (sym == 'a') {
allflag = TRUE;
} else if (sym == 'A') {
- /* same as the default */;
+ ; /* same as the default */
} else if (sym == 'u') {
add_valid_menu_class('u');
ckfn = ckunpaid;
- } else if (sym == 'B') {
- add_valid_menu_class('B');
- ckfn = ckvalidcat;
- } else if (sym == 'U') {
- add_valid_menu_class('U');
- ckfn = ckvalidcat;
- } else if (sym == 'C') {
- add_valid_menu_class('C');
- ckfn = ckvalidcat;
- } else if (sym == 'X') {
- add_valid_menu_class('X');
+ } else if (index("BUCX", sym)) {
+ add_valid_menu_class(sym); /* 'B','U','C',or 'X' */
ckfn = ckvalidcat;
} else if (sym == 'm') {
m_seen = TRUE;
} else if (oc_of_sym == MAXOCLASSES) {
+/*JP
You("don't have any %c's.", sym);
+*/
+ You("%c\82É\91®\82·\82é\95¨\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81D", sym);
} else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */
if (!index(olets, oc_of_sym)) {
add_valid_menu_class(oc_of_sym);
}
if (m_seen) {
- return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3;
+ return (allflag
+ || (!oletct && ckfn != ckunpaid && ckfn != ckvalidcat))
+ ? -2 : -3;
} else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) {
return 0;
#if 0
* Walk through the chain starting at objchn and ask for all objects
* with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
* whether the action in question (i.e., fn) has to be performed.
- * If allflag then no questions are asked. Max gives the max nr of
- * objects to be treated. Return the number of objects treated.
+ * If allflag then no questions are asked. Mx gives the max number
+ * of objects to be treated. Return the number of objects treated.
*/
+/*JP CHECK: 3.6.2 \82Å\82Ì\8cÄ\82Ñ\8fo\82µ\8c³
+invent.c:2228: int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
+pickup.c:3208: if (askchain(objlist, (one_by_one ? (char *) 0 : selection), allflag,
+ word\82É\82Í\93®\8e\8c\82ª\89p\8cê\82Å\93ü\82é\81B
+*/
int
askchain(objchn, olets, allflag, fn, ckfn, mx, word)
-struct obj **objchn;
-register int allflag, mx;
-register const char *olets, *word; /* olets is an Obj Class char array */
-register int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
+struct obj **objchn; /* *objchn might change */
+int allflag, mx;
+const char *olets, *word; /* olets is an Obj Class char array */
+int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
{
struct obj *otmp, *otmpo;
register char sym, ilet;
- register int cnt = 0, dud = 0, tmp;
- boolean takeoff, nodot, ident, take_out, put_in, first, ininv;
+ int cnt = 0, dud = 0, tmp;
+ boolean takeoff, nodot, ident, take_out, put_in, first, ininv, bycat;
char qbuf[QBUFSZ], qpfx[QBUFSZ];
+ Loot *sortedchn = 0;
takeoff = taking_off(word);
ident = !strcmp(word, "identify");
nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
|| takeoff || take_out || put_in);
ininv = (*objchn == invent);
+ bycat = (menu_class_present('u')
+ || menu_class_present('B') || menu_class_present('U')
+ || menu_class_present('C') || menu_class_present('X'));
+
+ /* someday maybe we'll sort by 'olets' too (temporarily replace
+ flags.packorder and pass SORTLOOT_PACK), but not yet... */
+ sortedchn = sortloot(objchn, SORTLOOT_INVLET, FALSE,
+ (boolean FDECL((*), (OBJ_P))) 0);
+
first = TRUE;
-/* Changed so the askchain is interrogated in the order specified.
- * For example, if a person specifies =/ then first all rings will be
- * asked about followed by all wands -dgk
- */
-nextclass:
+ /*
+ * Interrogate in the object class order specified.
+ * For example, if a person specifies =/ then first all rings
+ * will be asked about followed by all wands. -dgk
+ */
+ nextclass:
ilet = 'a' - 1;
if (*objchn && (*objchn)->oclass == COIN_CLASS)
ilet--; /* extra iteration */
* track of which list elements have already been processed.
*/
bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */
- while ((otmp = nxt_unbypassed_obj(*objchn)) != 0) {
+ while ((otmp = nxt_unbypassed_loot(sortedchn, *objchn)) != 0) {
if (ilet == 'z')
ilet = 'A';
+ else if (ilet == 'Z')
+ ilet = NOINVSYM; /* '#' */
else
ilet++;
if (olets && *olets && otmp->oclass != *olets)
continue;
if (ckfn && !(*ckfn)(otmp))
continue;
+ if (bycat && !ckvalidcat(otmp))
+ continue;
if (!allflag) {
safeq_xprn_ctx.let = ilet;
safeq_xprn_ctx.dot = !nodot;
Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
first = FALSE;
}
- (void) safe_qbuf(
- qbuf, qpfx, "?", otmp, ininv ? safeq_xprname : doname,
- ininv ? safeq_shortxprname : ansimpleoname, "item");
+#if 0 /*JP*/
+ (void) safe_qbuf(qbuf, qpfx, "?", otmp,
+ ininv ? safeq_xprname : doname,
+ ininv ? safeq_shortxprname : ansimpleoname,
+ "item");
+#else
+ (void) safe_qbuf(qbuf, qpfx, "\81H", otmp,
+ ininv ? safeq_xprname : doname,
+ ininv ? safeq_shortxprname : ansimpleoname,
+ "\83A\83C\83e\83\80");
+#endif
sym = (takeoff || ident || otmp->quan < 2L) ? nyaq(qbuf)
: nyNaq(qbuf);
} else
to 'none' or 'all'. 2 special cases: cursed loadstones and
welded weapons (eg, multiple daggers) will remain as merged
unit; done to avoid splitting an object that won't be
- droppable (even if we're picking up rather than dropping).
- */
- if (!yn_number)
+ droppable (even if we're picking up rather than dropping). */
+ if (!yn_number) {
sym = 'n';
- else {
+ } else {
sym = 'y';
if (yn_number < otmp->quan && splittable(otmp))
otmp = splitobj(otmp, yn_number);
switch (sym) {
case 'a':
allflag = 1;
+ /*FALLTHRU*/
case 'y':
tmp = (*fn)(otmp);
if (tmp < 0) {
cnt += tmp;
if (--mx == 0)
goto ret;
+ /*FALLTHRU*/
case 'n':
if (nodot)
dud++;
}
if (olets && *olets && *++olets)
goto nextclass;
+
if (!takeoff && (dud || cnt))
+/*JP
pline("That was all.");
+*/
+ pline("\82±\82ê\82Å\91S\95\94\82¾\81D");
else if (!dud && !cnt)
+/*JP
pline("No applicable objects.");
-ret:
+*/
+ pline("\82»\82ê\82Í\82Å\82«\82È\82¢\81D");
+ ret:
+ unsortloot(&sortedchn);
bypass_objlist(*objchn, FALSE);
return cnt;
}
/* assumptions: id_limit > 0 and at least one unID'd item is present */
while (id_limit) {
+#if 0 /*JP:T*/
Sprintf(buf, "What would you like to identify %s?",
first ? "first" : "next");
- n = query_objlist(buf, invent, SIGNAL_NOMENU | SIGNAL_ESCAPE
- | USE_INVLET | INVORDER_SORT,
+#else
+ Sprintf(buf, "\82Ç\82ê\82ð%s\82É\8e¯\95Ê\82µ\82Ü\82·\82©\81H",
+ first ? "\8dÅ\8f\89" : "\8e\9f");
+#endif
+ n = query_objlist(buf, &invent, (SIGNAL_NOMENU | SIGNAL_ESCAPE
+ | USE_INVLET | INVORDER_SORT),
&pick_list, PICK_ANY, not_fully_identified);
if (n > 0) {
} else if (n == -2) { /* player used ESC to quit menu */
break;
} else if (n == -1) { /* no eligible items found */
+/*JP
pline("That was all.");
+*/
+ pline("\82±\82ê\82Å\91S\95\94\82¾\81D");
break;
} else if (!--tryct) { /* stop re-prompting */
pline1(thats_enough_tries);
break;
} else { /* try again */
+/*JP
pline("Choose an item; use ESC to decline.");
+*/
+ pline("\83A\83C\83e\83\80\82ð\91I\82ñ\82Å\82\82¾\82³\82¢;\82â\82ß\82é\82È\82çESC\81D");
}
}
}
+/* count the unidentified items */
+int
+count_unidentified(objchn)
+struct obj *objchn;
+{
+ int unid_cnt = 0;
+ struct obj *obj;
+
+ for (obj = objchn; obj; obj = obj->nobj)
+ if (not_fully_identified(obj))
+ ++unid_cnt;
+ return unid_cnt;
+}
/* dialog with user to identify a given number of items; 0 means all */
void
int id_limit;
boolean learning_id; /* true if we just read unknown identify scroll */
{
- struct obj *obj, *the_obj;
- int n, unid_cnt;
-
- unid_cnt = 0;
- the_obj = 0; /* if unid_cnt ends up 1, this will be it */
- for (obj = invent; obj; obj = obj->nobj)
- if (not_fully_identified(obj))
- ++unid_cnt, the_obj = obj;
+ struct obj *obj;
+ int n, unid_cnt = count_unidentified(invent);
if (!unid_cnt) {
+#if 0 /*JP:T*/
You("have already identified all %sof your possessions.",
learning_id ? "the rest " : "");
+#else
+ You("%s\91S\82Ä\82Ì\8f\8a\97L\95¨\82ð\8e¯\95Ê\82µ\82Ä\82µ\82Ü\82Á\82Ä\82¢\82é\81D",
+ learning_id ? "\8ec\82è" : "");
+#endif
} else if (!id_limit || id_limit >= unid_cnt) {
/* identify everything */
- if (unid_cnt == 1) {
- (void) identify(the_obj);
- } else {
- /* TODO: use fully_identify_obj and cornline/menu/whatever here
- */
- for (obj = invent; obj; obj = obj->nobj)
- if (not_fully_identified(obj))
- (void) identify(obj);
+ /* TODO: use fully_identify_obj and cornline/menu/whatever here */
+ for (obj = invent; obj; obj = obj->nobj) {
+ if (not_fully_identified(obj)) {
+ (void) identify(obj);
+ if (unid_cnt == 1)
+ break;
+ }
}
} else {
/* identify up to `id_limit' items */
{
if (!prefix)
prefix = "";
+#if 0 /*JP*/
pline("%s%s%s", prefix, *prefix ? " " : "",
xprname(obj, (char *) 0, obj_to_let(obj), TRUE, 0L, quan));
+#else
+ pline("%s%s",
+ xprname(obj, (char *)0, obj_to_let(obj), *prefix ? FALSE : TRUE, 0L, quan),
+ prefix);
+#endif
}
char *
#else
static char li[BUFSZ];
#endif
- boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM;
+ boolean use_invlet = (flags.invlet_constant
+ && let != CONTAINED_SYM && let != HANDS_SYM);
long savequan = 0;
if (quan && obj) {
savequan = obj->quan;
obj->quan = quan;
}
-
/*
* If let is:
+ * - Then obj == null and 'txt' refers to hands or fingers.
* * Then obj == null and we are printing a total amount.
* > Then the object is contained and doesn't have an inventory letter.
*/
if (cost != 0 || let == '*') {
/* if dot is true, we're doing Iu, otherwise Ix */
- Sprintf(li, "%c - %-45s %6ld %s",
+#if 0 /*JP*/
+ Sprintf(li,
+ iflags.menu_tab_sep ? "%c - %s\t%6ld %s"
+ : "%c - %-45s %6ld %s",
+ (dot && use_invlet ? obj->invlet : let),
+ (txt ? txt : doname(obj)), cost, currency(cost));
+#else
+ Sprintf(li,
+ iflags.menu_tab_sep ? "%c - %s\t%6ld%s"
+ : "%c - %-45s %6ld%s",
(dot && use_invlet ? obj->invlet : let),
(txt ? txt : doname(obj)), cost, currency(cost));
+#endif
} else {
/* ordinary inventory display or pickup message */
Sprintf(li, "%c - %s%s", (use_invlet ? obj->invlet : let),
+/*JP
(txt ? txt : doname(obj)), (dot ? "." : ""));
+*/
+ (txt ? txt : doname(obj)), (dot ? "\81D" : ""));
}
if (savequan)
obj->quan = savequan;
* any count returned from the menu selection is placed here.
*/
STATIC_OVL char
-display_pickinv(lets, want_reply, out_cnt)
+display_pickinv(lets, xtra_choice, query, want_reply, out_cnt)
register const char *lets;
+const char *xtra_choice; /* "fingers", pick hands rather than an object */
+const char *query;
boolean want_reply;
long *out_cnt;
{
- struct obj *otmp;
+/*JP
+ static const char not_carrying_anything[] = "Not carrying anything";
+*/
+ static const char not_carrying_anything[] = "\89½\82à\8e\9d\82Á\82Ä\82¢\82È\82¢";
+ struct obj *otmp, wizid_fakeobj;
char ilet, ret;
char *invlet = flags.inv_order;
- int i, n, classcount;
+ int n, classcount;
winid win; /* windows being used */
anything any;
menu_item *selected;
- struct obj **oarray;
+ unsigned sortflags;
+ Loot *sortedinvent, *srtinv;
+ boolean wizid = FALSE;
- if (flags.perm_invent && lets && *lets) {
+ if (lets && !*lets)
+ lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
+
+ if (iflags.perm_invent && (lets || xtra_choice)) {
/* partial inventory in perm_invent setting; don't operate on
full inventory window, use an alternate one instead; create
the first time needed and keep it for re-use as needed later */
* don't know at this level if its up or not. This may not be
* an issue if empty checks are done before hand and the call
* to here is short circuited away.
+ *
+ * 2: our count here is only to distinguish between 0 and 1 and
+ * more than 1; for the last one, we don't need a precise number.
+ * For perm_invent update we force 'more than 1'.
*/
- if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
- pline("Not carrying anything.");
+ n = (iflags.perm_invent && !lets && !want_reply) ? 2
+ : lets ? (int) strlen(lets)
+ : !invent ? 0 : !invent->nobj ? 1 : 2;
+ /* for xtra_choice, there's another 'item' not included in initial 'n';
+ for !lets (full invent) and for override_ID (wizard mode identify),
+ skip message_menu handling of single item even if item count was 1 */
+ if (xtra_choice || (n == 1 && (!lets || iflags.override_ID)))
+ ++n;
+
+ if (n == 0) {
+/*JP
+ pline("%s.", not_carrying_anything);
+*/
+ pline("%s\81D", not_carrying_anything);
return 0;
}
if (!flags.invlet_constant)
reassign();
- if (lets && strlen(lets) == 1 && !iflags.override_ID) {
+ if (n == 1 && !iflags.force_invmenu) {
/* when only one item of interest, use pline instead of menus;
we actually use a fake message-line menu in order to allow
the user to perform selection at the --More-- prompt for tty */
ret = '\0';
- for (otmp = invent; otmp; otmp = otmp->nobj) {
- if (otmp->invlet == lets[0]) {
- ret = message_menu(
- lets[0], want_reply ? PICK_ONE : PICK_NONE,
- xprname(otmp, (char *) 0, lets[0], TRUE, 0L, 0L));
- if (out_cnt)
- *out_cnt = -1L; /* select all */
- break;
- }
+ if (xtra_choice) {
+ /* xtra_choice is "bare hands" (wield), "fingertip" (Engrave),
+ "nothing" (ready Quiver), or "fingers" (apply grease) */
+ ret = message_menu(HANDS_SYM, PICK_ONE,
+ xprname((struct obj *) 0, xtra_choice,
+ HANDS_SYM, TRUE, 0L, 0L)); /* '-' */
+ } else {
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if (!lets || otmp->invlet == lets[0])
+ break;
+ if (otmp)
+ ret = message_menu(otmp->invlet,
+ want_reply ? PICK_ONE : PICK_NONE,
+ xprname(otmp, (char *) 0, lets[0],
+ TRUE, 0L, 0L));
}
+ if (out_cnt)
+ *out_cnt = -1L; /* select all */
return ret;
}
- /* count the number of items */
- for (n = 0, otmp = invent; otmp; otmp = otmp->nobj)
- if (!lets || !*lets || index(lets, otmp->invlet))
- n++;
-
- oarray = objarr_init(n);
-
- /* Add objects to the array */
- i = 0;
- for (otmp = invent; otmp; otmp = otmp->nobj)
- if (!lets || !*lets || index(lets, otmp->invlet)) {
- objarr_set(otmp, i++, oarray, (flags.sortloot == 'f'));
- }
+ sortflags = (flags.sortloot == 'f') ? SORTLOOT_LOOT : SORTLOOT_INVLET;
+ if (flags.sortpack)
+ sortflags |= SORTLOOT_PACK;
+ sortedinvent = sortloot(&invent, sortflags, FALSE,
+ (boolean FDECL((*), (OBJ_P))) 0);
start_menu(win);
any = zeroany;
if (wizard && iflags.override_ID) {
- char prompt[BUFSZ];
- any.a_char = -1;
- /* wiz_identify stuffed the wiz_identify cmd character
- into iflags.override_ID */
- Sprintf(prompt, "Debug Identify (%s to permanently identify)",
- visctrl(iflags.override_ID));
- add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
- prompt, MENU_UNSELECTED);
- }
-nextclass:
+ int unid_cnt;
+ char prompt[QBUFSZ];
+
+ unid_cnt = count_unidentified(invent);
+ Sprintf(prompt, "Debug Identify"); /* 'title' rather than 'prompt' */
+ if (unid_cnt)
+ Sprintf(eos(prompt),
+ " -- unidentified or partially identified item%s",
+ plur(unid_cnt));
+ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, prompt, MENU_UNSELECTED);
+ if (!unid_cnt) {
+ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
+ "(all items are permanently identified already)",
+ MENU_UNSELECTED);
+ } else {
+ any.a_obj = &wizid_fakeobj;
+ Sprintf(prompt, "select %s to permanently identify",
+ (unid_cnt == 1) ? "it": "any or all of them");
+ /* wiz_identify stuffed the wiz_identify command character (^I)
+ into iflags.override_ID for our use as an accelerator;
+ it could be ambiguous if player has assigned a letter to
+ the #wizidentify command */
+ if (unid_cnt > 1)
+ Sprintf(eos(prompt), " (%s for all)",
+ visctrl(iflags.override_ID));
+ add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
+ prompt, MENU_UNSELECTED);
+ wizid = TRUE;
+ }
+ } else if (xtra_choice) {
+ /* wizard override ID and xtra_choice are mutually exclusive */
+ if (flags.sortpack)
+ add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+ "Miscellaneous", MENU_UNSELECTED);
+ any.a_char = HANDS_SYM; /* '-' */
+ add_menu(win, NO_GLYPH, &any, HANDS_SYM, 0, ATR_NONE,
+ xtra_choice, MENU_UNSELECTED);
+ }
+ nextclass:
classcount = 0;
- any = zeroany; /* set all bits to zero */
- for (i = 0; i < n; i++) {
- otmp = oarray[i];
- ilet = otmp->invlet;
- any = zeroany; /* zero */
+ for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
+ if (lets && !index(lets, otmp->invlet))
+ continue;
if (!flags.sortpack || otmp->oclass == *invlet) {
+ if (wizid && !not_fully_identified(otmp))
+ continue;
+ any = zeroany; /* all bits zero */
+ ilet = otmp->invlet;
if (flags.sortpack && !classcount) {
add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
let_to_name(*invlet, FALSE,
MENU_UNSELECTED);
classcount++;
}
- any.a_char = ilet;
- add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE,
- doname(otmp), MENU_UNSELECTED);
+ if (wizid)
+ any.a_obj = otmp;
+ else
+ any.a_char = ilet;
+ add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng), &any, ilet,
+ wizid ? def_oc_syms[(int) otmp->oclass].sym : 0,
+ ATR_NONE, doname(otmp), MENU_UNSELECTED);
}
}
if (flags.sortpack) {
goto nextclass;
}
}
- free(oarray);
- end_menu(win, (char *) 0);
+ if (iflags.force_invmenu && lets && want_reply) {
+ any = zeroany;
+#if 0 /*JP*/
+ add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+ "Special", MENU_UNSELECTED);
+#else
+ add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+ "\93Á\8eê", MENU_UNSELECTED);
+#endif
+ any.a_char = '*';
+#if 0 /*JP*/
+ add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
+ "(list everything)", MENU_UNSELECTED);
+#else
+ add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE,
+ "(\91S\82Ä\82Ì\88ê\97\97)", MENU_UNSELECTED);
+#endif
+ }
+ unsortloot(&sortedinvent);
+ /* for permanent inventory where we intend to show everything but
+ nothing has been listed (because there isn't anyhing to list;
+ recognized via any.a_char still being zero; the n==0 case above
+ gets skipped for perm_invent), put something into the menu */
+ if (iflags.perm_invent && !lets && !any.a_char) {
+ any = zeroany;
+ add_menu(win, NO_GLYPH, &any, 0, 0, 0,
+ not_carrying_anything, MENU_UNSELECTED);
+ want_reply = FALSE;
+ }
+ end_menu(win, query && *query ? query : (char *) 0);
- n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
+ n = select_menu(win,
+ wizid ? PICK_ANY : want_reply ? PICK_ONE : PICK_NONE,
+ &selected);
if (n > 0) {
- ret = selected[0].item.a_char;
- if (out_cnt)
- *out_cnt = selected[0].count;
+ if (wizid) {
+ int i;
+
+ ret = '\0';
+ for (i = 0; i < n; ++i) {
+ otmp = selected[i].item.a_obj;
+ if (otmp == &wizid_fakeobj) {
+ identify_pack(0, FALSE);
+ } else {
+ if (not_fully_identified(otmp))
+ (void) identify(otmp);
+ }
+ }
+ } else {
+ ret = selected[0].item.a_char;
+ if (out_cnt)
+ *out_cnt = selected[0].count;
+ }
free((genericptr_t) selected);
} else
ret = !n ? '\0' : '\033'; /* cancelled */
const char *lets;
boolean want_reply;
{
- return display_pickinv(lets, want_reply, (long *) 0);
+ return display_pickinv(lets, (char *) 0, (char *) 0,
+ want_reply, (long *) 0);
}
/*
classcount++;
}
any.a_char = ilet;
- add_menu(win, obj_to_glyph(otmp), &any, ilet, 0, ATR_NONE,
+ add_menu(win, obj_to_glyph(otmp, rn2_on_display_rng),
+ &any, ilet, 0, ATR_NONE,
doname(otmp), MENU_UNSELECTED);
}
}
}
end_menu(win, "Inventory letters used:");
- n = select_menu(win, PICK_NONE, &selected);
+ n = select_menu(win, PICK_ONE, &selected);
if (n > 0) {
ret = selected[0].item.a_char;
free((genericptr_t) selected);
* at some point: bknown is forced for priest[ess], like in xname().
*/
int
-count_buc(list, type)
+count_buc(list, type, filterfunc)
struct obj *list;
int type;
+boolean FDECL((*filterfunc), (OBJ_P));
{
int count = 0;
for (; list; list = list->nobj) {
- /* coins are "none of the above" as far as BUCX filtering goes */
- if (list->oclass == COIN_CLASS)
- continue;
/* priests always know bless/curse state */
if (Role_if(PM_PRIEST))
- list->bknown = 1;
+ list->bknown = (list->oclass != COIN_CLASS);
+ /* some actions exclude some or most items */
+ if (filterfunc && !(*filterfunc)(list))
+ continue;
+ /* coins are either uncursed or unknown based upon option setting */
+ if (list->oclass == COIN_CLASS) {
+ if (type == (iflags.goldX ? BUC_UNKNOWN : BUC_UNCURSED))
+ ++count;
+ continue;
+ }
/* check whether this object matches the requested type */
if (!list->bknown
? (type == BUC_UNKNOWN)
/* similar to count_buc(), but tallies all states at once
rather than looking for a specific type */
-STATIC_OVL void
-tally_BUCX(list, bcp, ucp, ccp, xcp, ocp)
+void
+tally_BUCX(list, by_nexthere, bcp, ucp, ccp, xcp, ocp)
struct obj *list;
+boolean by_nexthere;
int *bcp, *ucp, *ccp, *xcp, *ocp;
{
+ /* Future extensions:
+ * Skip current_container when list is invent, uchain when
+ * first object of list is located on the floor. 'ocp' will then
+ * have a function again (it was a counter for having skipped gold,
+ * but that's not skipped anymore).
+ */
*bcp = *ucp = *ccp = *xcp = *ocp = 0;
- for (; list; list = list->nobj) {
+ for ( ; list; list = (by_nexthere ? list->nexthere : list->nobj)) {
+ /* priests always know bless/curse state */
+ if (Role_if(PM_PRIEST))
+ list->bknown = (list->oclass != COIN_CLASS);
+ /* coins are either uncursed or unknown based upon option setting */
if (list->oclass == COIN_CLASS) {
- ++(*ocp); /* "other" */
+ if (iflags.goldX)
+ ++(*xcp);
+ else
+ ++(*ucp);
continue;
}
- /* priests always know bless/curse state */
- if (Role_if(PM_PRIEST))
- list->bknown = 1;
-
+ /* ordinary items */
if (!list->bknown)
++(*xcp);
else if (list->blessed)
}
}
+/* count everything inside a container, or just shop-owned items inside */
long
count_contents(container, nested, quantity, everything)
struct obj *container;
quantity, /* count all vs count separate stacks */
everything; /* all objects vs only unpaid objects */
{
- struct obj *otmp;
+ struct obj *otmp, *topc;
+ boolean shoppy = FALSE;
long count = 0L;
+ if (!everything) {
+ for (topc = container; topc->where == OBJ_CONTAINED;
+ topc = topc->ocontainer)
+ continue;
+ if (topc->where == OBJ_FLOOR) {
+ xchar x, y;
+
+ (void) get_obj_location(topc, &x, &y, CONTAINED_TOO);
+ shoppy = costly_spot(x, y);
+ }
+ }
for (otmp = container->cobj; otmp; otmp = otmp->nobj) {
if (nested && Has_contents(otmp))
count += count_contents(otmp, nested, quantity, everything);
- if (everything || otmp->unpaid)
+ if (everything || otmp->unpaid || (shoppy && !otmp->no_charge))
count += quantity ? otmp->quan : 1L;
}
return count;
dounpaid()
{
winid win;
- struct obj *otmp, *marker;
+ struct obj *otmp, *marker, *contnr;
register char ilet;
char *invlet = flags.inv_order;
int classcount, count, num_so_far;
long cost, totcost;
count = count_unpaid(invent);
+ otmp = marker = contnr = (struct obj *) 0;
if (count == 1) {
- marker = (struct obj *) 0;
otmp = find_unpaid(invent, &marker);
+ contnr = unknwn_contnr_contents(otmp);
+ }
+ if (otmp && !contnr) {
+ /* 1 item; use pline instead of popup menu */
cost = unpaid_cost(otmp, FALSE);
iflags.suppress_price++; /* suppress "(unpaid)" suffix */
pline1(xprname(otmp, distant_name(otmp, doname),
- carried(otmp) ? otmp->invlet : CONTAINED_SYM, TRUE,
- cost, 0L));
+ carried(otmp) ? otmp->invlet : CONTAINED_SYM,
+ TRUE, cost, 0L));
iflags.suppress_price--;
return;
}
char contbuf[BUFSZ];
/* Shopkeeper knows what to charge for contents */
+/*JP
Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
+*/
+ Sprintf(contbuf, "%s\82Ì\92\86\90g", xname(otmp));
putstr(win, 0,
xprname((struct obj *) 0, contbuf, CONTAINED_SYM,
TRUE, contcost, 0L));
}
putstr(win, 0, "");
+#if 0 /*JP*/
putstr(win, 0,
xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
+#else
+ putstr(win, 0,
+ xprname((struct obj *) 0, "\8d\87\8cv\81F", '*', FALSE, totcost, 0L));
+#endif
display_nhwindow(win, FALSE);
destroy_nhwindow(win);
}
{
boolean res = (obj->oclass == this_type);
- if (obj->oclass != COIN_CLASS) {
+ if (obj->oclass == COIN_CLASS) {
+ /* if filtering by bless/curse state, gold is classified as
+ either unknown or uncursed based on user option setting */
+ if (this_type && index("BUCX", this_type))
+ res = (this_type == (iflags.goldX ? 'X' : 'U'));
+ } else {
switch (this_type) {
case 'B':
res = (obj->bknown && obj->blessed);
boolean billx = *u.ushops && doinvbill(0);
menu_item *pick_list;
boolean traditional = TRUE;
+/*JP
const char *prompt = "What type of object do you want an inventory of?";
+*/
+ const char *prompt = "\82Ç\82Ì\8eí\97Þ\82Ì\8e\9d\82¿\95¨\82ð\8c©\82Ü\82·\82©\81H";
if (!invent && !billx) {
+/*JP
You("aren't carrying anything.");
+*/
+ You("\82»\82Ì\8eí\97Þ\82Ì\95¨\82Í\89½\82à\8e\9d\82Á\82Ä\82¢\82È\82¢\81D");
return 0;
}
unpaid_count = count_unpaid(invent);
- tally_BUCX(invent, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
+ tally_BUCX(invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
if (flags.menu_style != MENU_TRADITIONAL) {
if (flags.menu_style == MENU_FULL
/* collect a list of classes of objects carried, for use as a prompt
*/
types[0] = 0;
- class_count =
- collect_obj_classes(types, invent, FALSE,
- (boolean FDECL((*), (OBJ_P))) 0, &itemcount);
+ class_count = collect_obj_classes(types, invent, FALSE,
+ (boolean FDECL((*), (OBJ_P))) 0,
+ &itemcount);
if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
types[class_count++] = ' ';
if (unpaid_count)
if (billx)
(void) doinvbill(1);
else
+#if 0 /*JP*/
pline("No used-up objects%s.",
unpaid_count ? " on your shopping bill" : "");
+#else
+ pline("\8eg\82Á\82Ä\82µ\82Ü\82Á\82½\95¨\82Í%s\82È\82¢\81D",
+ unpaid_count ? "\8f¤\93X\82Ì\90¿\8b\81\8f\91\82É\82Í" : "");
+#endif
return 0;
}
if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
if (unpaid_count)
dounpaid();
else
+/*JP
You("are not carrying any unpaid objects.");
+*/
+ You("\96¢\95¥\82¢\82Ì\83A\83C\83e\83\80\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81D");
return 0;
}
if (traditional) {
return doprgold();
if (index(types, c) > index(types, '\033')) {
/* '> ESC' => hidden choice, something known not to be carried */
- const char *which = 0;
+ const char *before = "", *after = "";
switch (c) {
case 'B':
- which = "known to be blessed";
+/*JP
+ before = "known to be blessed ";
+*/
+ before = "\8fj\95\9f\82³\82ê\82Ä\82¢\82é\82Æ\82í\82©\82Á\82Ä\82¢\82é";
break;
case 'U':
- which = "known to be uncursed";
+/*JP
+ before = "known to be uncursed ";
+*/
+ before = "\8eô\82í\82ê\82Ä\82¢\82È\82¢\82Æ\82í\82©\82Á\82Ä\82¢\82é";
break;
case 'C':
- which = "known to be cursed";
+/*JP
+ before = "known to be cursed ";
+*/
+ before = "\8eô\82í\82ê\82Ä\82¢\82é\82Æ\82í\82©\82Á\82Ä\82¢\82é";
break;
case 'X':
- You(
- "have no objects whose blessed/uncursed/cursed status is unknown.");
+/*JP
+ after = " whose blessed/uncursed/cursed status is unknown";
+*/
+ after = "\8fj\95\9f\81^\8eô\82¢\82ª\82í\82©\82ç\82È\82¢";
break; /* better phrasing is desirable */
default:
- which = "such";
+ /* 'c' is an object class, because we've already handled
+ all the non-class letters which were put into 'types[]';
+ could/should move object class names[] array from below
+ to somewhere above so that we can access it here (via
+ lcase(strcpy(classnamebuf, names[(int) c]))), but the
+ game-play value of doing so is low... */
+/*JP
+ before = "such ";
+*/
+ before = "\82»\82Ì\82æ\82¤\82È";
break;
}
- if (which)
- You("have no %s objects.", which);
+/*JP
+ You("have no %sobjects%s.", before, after);
+*/
+ You("%s%s\82à\82Ì\82Í\89½\82à\8e\9d\82Á\82Ä\82¢\82È\82¢\81D", before, after);
return 0;
}
this_type = oclass;
}
- if (query_objlist((char *) 0, invent,
- (flags.invlet_constant ? USE_INVLET : 0)
- | INVORDER_SORT,
+ if (query_objlist((char *) 0, &invent,
+ ((flags.invlet_constant ? USE_INVLET : 0)
+ | INVORDER_SORT),
&pick_list, PICK_NONE, this_type_only) > 0)
free((genericptr_t) pick_list);
return 0;
cmap = S_vodoor;
break; /* "open door" */
case D_BROKEN:
+/*JP
dfeature = "broken door";
+*/
+ dfeature = "\89ó\82ê\82½\94à";
break;
default:
cmap = S_vcdoor;
}
/* override door description for open drawbridge */
if (is_drawbridge_wall(x, y) >= 0)
+/*JP
dfeature = "open drawbridge portcullis", cmap = -1;
+*/
+ dfeature = "\8d~\82è\82Ä\82¢\82é\92µ\82Ë\8b´", cmap = -1;
} else if (IS_FOUNTAIN(ltyp))
cmap = S_fountain; /* "fountain" */
else if (IS_THRONE(ltyp))
else if (is_ice(x, y))
cmap = S_ice; /* "ice" */
else if (is_pool(x, y))
+/*JP
dfeature = "pool of water";
+*/
+ dfeature = "\90\85\82½\82Ü\82è";
else if (IS_SINK(ltyp))
cmap = S_sink; /* "sink" */
else if (IS_ALTAR(ltyp)) {
+#if 0 /*JP*/
Sprintf(altbuf, "%saltar to %s (%s)",
((lev->altarmask & AM_SHRINE)
&& (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
: "",
a_gname(),
align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
+#else
+ Sprintf(altbuf, "%s%s\82Ì\8dÕ\92d(%s)",
+ ((lev->altarmask & AM_SHRINE)
+ && (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
+ ? "\8d\82\88Ê\82Ì"
+ : "",
+ a_gname(),
+ align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
+#endif
dfeature = altbuf;
} else if ((x == xupstair && y == yupstair)
|| (x == sstairs.sx && y == sstairs.sy && sstairs.up))
else if (ltyp == TREE)
cmap = S_tree; /* "tree" */
else if (ltyp == IRONBARS)
+/*JP
dfeature = "set of iron bars";
+*/
+ dfeature = "\93S\82Ì\96_";
if (cmap >= 0)
dfeature = defsyms[cmap].explanation;
{
struct obj *otmp;
struct trap *trap;
+#if 0 /*JP:C*/
const char *verb = Blind ? "feel" : "see";
+#else
+ const char *verb = Blind ? "\82ª\82 \82é\82æ\82¤\82È\8bC\82ª\82µ\82½" : "\82ð\82Ý\82Â\82¯\82½";
+#endif
const char *dfeature = (char *) 0;
char fbuf[BUFSZ], fbuf2[BUFSZ];
winid tmpwin;
skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
if (u.uswallow && u.ustuck) {
struct monst *mtmp = u.ustuck;
+
+#if 0 /*JP:T*/
Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
mbodypart(mtmp, STOMACH));
+#else
+ Sprintf(fbuf, "%s\82Ì%s\82Ì\92\86\90g", mon_nam(mtmp),
+ mbodypart(mtmp, STOMACH));
+#endif
+#if 0 /*JP*//*\8cê\8f\87\82ª\88á\82¤\82Ì\82Å\91f\92¼\82É*/
/* Skip "Contents of " by using fbuf index 12 */
You("%s to %s what is lying in %s.", Blind ? "try" : "look around",
verb, &fbuf[12]);
+#else
+ You("%s\82Ì%s\82É\89½\82ª\82 \82é\82©%s\81D",
+ mon_nam(mtmp), mbodypart(mtmp, STOMACH),
+ Blind ? "\82³\82®\82Á\82½" : "\8c©\89ñ\82µ\82½");
+#endif
otmp = mtmp->minvent;
if (otmp) {
for (; otmp; otmp = otmp->nobj) {
if (otmp->otyp == CORPSE)
feel_cockatrice(otmp, FALSE);
}
+#if 0 /*JP*/
if (Blind)
Strcpy(fbuf, "You feel");
Strcat(fbuf, ":");
- (void) display_minventory(mtmp, MINV_ALL, fbuf);
+#else
+ Sprintf(fbuf, "\82±\82±\82É\82 \82é%s\82à\82Ì\82Í\81F", Blind ? "\82ç\82µ\82¢" : "");
+#endif
+ (void) display_minventory(mtmp, MINV_ALL | PICK_NONE, fbuf);
} else {
+#if 0 /*JP*/
You("%s no objects here.", verb);
+#else
+ pline(Blind ? "\82 \82È\82½\82Í\89½\82à\82È\82¢\82æ\82¤\82È\8bC\82ª\82µ\82½\81D"
+ : "\82 \82È\82½\82Í\89½\82à\82Ý\82Â\82¯\82ç\82ê\82È\82©\82Á\82½\81D");
+#endif
}
return !!Blind;
}
if (!skip_objects && (trap = t_at(u.ux, u.uy)) && trap->tseen)
+/*JP
There("is %s here.",
+*/
+ pline("\82±\82±\82É\82Í%s\82ª\82 \82é\81D",
an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
otmp = level.objects[u.ux][u.uy];
dfeature = dfeature_at(u.ux, u.uy, fbuf2);
+/*JP
if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
+*/
+ if (dfeature && !strcmp(dfeature, "\90\85\82½\82Ü\82è") && Underwater)
dfeature = 0;
if (Blind) {
boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
+/*JP
if (dfeature && !strncmp(dfeature, "altar ", 6)) {
+*/
+ if (dfeature && !strncmp(dfeature, "\8dÕ\92d", 4)) {
/* don't say "altar" twice, dfeature has more info */
+/*JP
You("try to feel what is here.");
+*/
+ You("\82±\82±\82É\89½\82ª\82 \82é\82Ì\82©\92²\82×\82æ\82¤\82Æ\82µ\82½\81D");
} else {
+#if 0 /*JP*/
const char *where = (Blind && !can_reach_floor(TRUE))
? "lying beneath you"
: "lying here on the ",
You("try to feel what is %s%s.", drift ? "floating here" : where,
drift ? "" : onwhat);
+#else
+ if (drift) {
+ You("\89½\82ª\95\82\82¢\82Ä\82¢\82é\82Ì\82©\92²\82×\82æ\82¤\82Æ\82µ\82½\81D");
+ } else if (Blind && !can_reach_floor(TRUE)) {
+ You("\89½\82ª\91«\89º\82É\82 \82é\82Ì\82©\92²\82×\82æ\82¤\82Æ\82µ\82½\81D");
+ } else {
+ You("\89½\82ª%s\82Ì\8fã\82É\82 \82é\82Ì\82©\92²\82×\82æ\82¤\82Æ\82µ\82½\81D", surface(u.ux, u.uy));
+ }
+#endif
}
if (dfeature && !drift && !strcmp(dfeature, surface(u.ux, u.uy)))
dfeature = 0; /* ice already identified */
if (!can_reach_floor(TRUE)) {
+/*JP
pline("But you can't reach it!");
+*/
+ pline("\82µ\82©\82µ\93Í\82©\82È\82¢\81I");
return 0;
}
}
if (dfeature)
+/*JP
Sprintf(fbuf, "There is %s here.", an(dfeature));
+*/
+ Sprintf(fbuf, "\82±\82±\82É\82Í%s\82ª\82 \82é\81D", an(dfeature));
if (!otmp || is_lava(u.ux, u.uy)
|| (is_pool(u.ux, u.uy) && !Underwater)) {
pline1(fbuf);
read_engr_at(u.ux, u.uy); /* Eric Backus */
if (!skip_objects && (Blind || !dfeature))
+#if 0 /*JP:C*/
You("%s no objects here.", verb);
+#else
+ pline(Blind ?
+ "\82È\82É\82à\82È\82¢\82æ\82¤\82È\8bC\82ª\82·\82é\81D" :
+ "\82È\82É\82à\82Ý\82Â\82¯\82ç\82ê\82È\82©\82Á\82½\81D");
+#endif
return !!Blind;
}
/* we know there is something here */
pline1(fbuf);
read_engr_at(u.ux, u.uy); /* Eric Backus */
if (obj_cnt == 1 && otmp->quan == 1L)
+/*JP
There("is %s object here.", picked_some ? "another" : "an");
+*/
+ There("\82±\82±\82É\82Í%s\88ê\82Â\82à\82Ì\82ª\82 \82é\81D", picked_some ? "\82à\82¤" : "");
else
+#if 0 /*JP*/
There("are %s%s objects here.",
(obj_cnt < 5)
? "a few"
? "several"
: "many",
picked_some ? " more" : "");
+#else
+ pline("\82±\82±\82É\82Í%s%s\82à\82Ì\82ª\82 \82é\81D",
+ picked_some ? "\82³\82ç\82É" : "",
+ (obj_cnt < 10)
+ ? "\82¢\82\82Â\82©\82Ì"
+ : "\82½\82\82³\82ñ\82Ì");
+#endif
for (; otmp; otmp = otmp->nexthere)
if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
+#if 0 /*JP*//*"It's (corpse_name), unfortunately"*/
pline("%s %s%s.",
(obj_cnt > 1)
? "Including"
poly_when_stoned(youmonst.data)
? ""
: ", unfortunately");
+#else
+ pline("%s%s%s\81D",
+ poly_when_stoned(youmonst.data)
+ ? ""
+ : "\8ec\94O\82È\82ª\82ç",
+ corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
+ (obj_cnt > 1)
+ ? "\82ð\8aÜ\82ñ\82Å\82¢\82é"
+ : "\82¾");
+#endif
feel_cockatrice(otmp, FALSE);
break;
}
if (dfeature)
pline1(fbuf);
read_engr_at(u.ux, u.uy); /* Eric Backus */
+/*JP
You("%s here %s.", verb, doname_with_price(otmp));
+*/
+ pline("%s%s\81D", doname_with_price(otmp), verb);
iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
if (otmp->otyp == CORPSE)
feel_cockatrice(otmp, FALSE);
putstr(tmpwin, 0, fbuf);
putstr(tmpwin, 0, "");
}
+#if 0 /*JP*/
Sprintf(buf, "%s that %s here:",
picked_some ? "Other things" : "Things",
Blind ? "you feel" : "are");
+#else
+ Sprintf(buf, "%s\82±\82±\82É\82 \82é%s\82à\82Ì\82Í\81F",
+ picked_some ? "\91¼\82É" : "",
+ Blind ? "\82ç\82µ\82¢" : "");
+#endif
putstr(tmpwin, 0, buf);
for (; otmp; otmp = otmp->nexthere) {
if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
felt_cockatrice = TRUE;
+/*JP
Sprintf(buf, "%s...", doname(otmp));
+*/
+ Sprintf(buf, "%s\81D\81D\81D", doname(otmp));
putstr(tmpwin, 0, buf);
break;
}
int
dolook()
{
- return look_here(0, FALSE);
+ int res;
+
+ /* don't let
+ MSGTYPE={norep,noshow} "You see here"
+ interfere with feedback from the look-here command */
+ hide_unhide_msgtypes(TRUE, MSGTYP_MASK_REP_SHOW);
+ res = look_here(0, FALSE);
+ /* restore normal msgtype handling */
+ hide_unhide_msgtypes(FALSE, MSGTYP_MASK_REP_SHOW);
+ return res;
}
boolean
Strcpy(kbuf, corpse_xname(otmp, (const char *) 0, CXN_PFX_THE));
if (poly_when_stoned(youmonst.data))
+#if 0 /*JP*/
You("touched %s with your bare %s.", kbuf,
makeplural(body_part(HAND)));
+#else
+ You("%s\82Ì\8e\80\91Ì\82É\91f%s\82Å\90G\82Á\82½\81D", kbuf,
+ body_part(HAND));
+#endif
else
+/*JP
pline("Touching %s is a fatal mistake...", kbuf);
+*/
+ pline("%s\82Ì\8e\80\91Ì\82É\90G\82ê\82é\82Ì\82Í\92v\96½\93I\82È\8aÔ\88á\82¢\82¾\81D\81D\81D", kbuf);
/* normalize body shape here; hand, not body_part(HAND) */
+/*JP
Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
+*/
+ Sprintf(kbuf, "%s\82Ì\8e\80\91Ì\82É\90G\82ê\82Ä", killer_xname(otmp));
/* will call polymon() for the poly_when_stoned() case */
instapetrify(kbuf);
}
return;
}
-/* returns TRUE if obj & otmp can be merged */
-STATIC_OVL boolean
+/* returns TRUE if obj & otmp can be merged; used in invent.c and mkobj.c */
+boolean
mergable(otmp, obj)
register struct obj *otmp, *obj;
{
int objnamelth = 0, otmpnamelth = 0;
- if (obj == otmp)
- return FALSE; /* already the same object */
- if (obj->otyp != otmp->otyp)
+
+ /* fail if already the same object, if different types, if either is
+ explicitly marked to prevent merge, or if not mergable in general */
+ if (obj == otmp || obj->otyp != otmp->otyp
+ || obj->nomerge || otmp->nomerge || !objects[obj->otyp].oc_merge)
return FALSE;
+
/* coins of the same kind will always merge */
if (obj->oclass == COIN_CLASS)
return TRUE;
+
if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
- || obj->dknown != otmp->dknown
- || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
|| obj->cursed != otmp->cursed || obj->blessed != otmp->blessed
|| obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
|| obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
- || obj->greased != otmp->greased || obj->oeroded != otmp->oeroded
- || obj->oeroded2 != otmp->oeroded2 || obj->bypass != otmp->bypass)
+ || obj->bypass != otmp->bypass)
return FALSE;
- if (obj->nomerge) /* explicitly marked to prevent merge */
+ if (obj->globby)
+ return TRUE;
+ /* Checks beyond this point either aren't applicable to globs
+ * or don't inhibit their merger.
+ */
+
+ if (obj->oclass == FOOD_CLASS
+ && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
+ return FALSE;
+
+ if (obj->dknown != otmp->dknown
+ || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST))
+ || obj->oeroded != otmp->oeroded || obj->oeroded2 != otmp->oeroded2
+ || obj->greased != otmp->greased)
return FALSE;
if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
|| obj->rknown != otmp->rknown))
return FALSE;
- if (obj->oclass == FOOD_CLASS
- && (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
- return FALSE;
-
if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
if (obj->corpsenm != otmp->corpsenm)
return FALSE;
/* the messages used to refer to "carrying gold", but that didn't
take containers into account */
long umoney = money_cnt(invent);
+
if (!umoney)
+/*JP
Your("wallet is empty.");
+*/
+ Your("\8dà\95z\82Í\8bó\82Á\82Û\82¾\81D");
else
+/*JP
Your("wallet contains %ld %s.", umoney, currency(umoney));
+*/
+ Your("\8dà\95z\82É\82Í%ld%s\93ü\82Á\82Ä\82¢\82é\81D", umoney, currency(umoney));
shopper_financial_report();
return 0;
}
doprwep()
{
if (!uwep) {
+/*JP
You("are empty %s.", body_part(HANDED));
+*/
+ if(!uwep) You("%s\82É\95\90\8aí\82ð\82à\82Á\82Ä\82¢\82È\82¢\81D", body_part(HAND));
} else {
prinv((char *) 0, uwep, 0L);
if (u.twoweap)
boolean report_uskin;
{
if (!uskin || !report_uskin) {
+/*JP
You("are not wearing any armor.");
+*/
+ You("\8aZ\82ð\92\85\82Ä\82¢\82È\82¢\81D");
} else {
char *p, *uskinname, buf[BUFSZ];
uskinname = strcpy(buf, simpleonames(uskin));
+#if 0 /*JP*/
/* shorten "set of <color> dragon scales" to "<color> scales"
and "<color> dragon scale mail" to "<color> scale mail" */
if (!strncmpi(uskinname, "set of ", 7))
if ((p = strstri(uskinname, " dragon ")) != 0)
while ((p[1] = p[8]) != '\0')
++p;
+#else /*\81u<\90F>\83h\83\89\83S\83\93\82Ì\97Ø\81v\82ð\81u<\90F>\82Ì\97Ø\81v\82É\82·\82é*/
+ if ((p = strstri(uskinname, "\83h\83\89\83S\83\93\82Ì\97Ø")) != 0)
+ strcpy(p, "\97Ø");
+#endif
+/*JP
You("are not wearing armor but have %s embedded in your skin.",
+*/
+ 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",
uskinname);
}
}
doprring()
{
if (!uleft && !uright)
+/*JP
You("are not wearing any rings.");
+*/
+ You("\8ew\97Ö\82ð\90g\82É\82Â\82¯\82Ä\82¢\82È\82¢\81D");
else {
char lets[3];
register int ct = 0;
dopramulet()
{
if (!uamul)
+/*JP
You("are not wearing an amulet.");
+*/
+ You("\96\82\8f\9c\82¯\82ð\90g\82É\82Â\82¯\82Ä\82¢\82È\82¢\81D");
else
prinv((char *) 0, uamul, 0L);
return 0;
lets[ct++] = obj_to_let(otmp);
lets[ct] = '\0';
if (!ct)
+/*JP
You("are not using any tools.");
+*/
+ You("\8eg\82¦\82é\93¹\8bï\82ð\82à\82Á\82Ä\82¢\82È\82¢\81D");
else
(void) display_inventory(lets, FALSE);
return 0;
lets[ct++] = obj_to_let(otmp);
lets[ct] = '\0';
if (!ct)
+/*JP
You("are not wearing or wielding anything.");
+*/
+ You("\89½\82à\92\85\82Ä\82¢\82È\82¢\82µ\81C\91\95\94õ\82µ\82Ä\82¢\82È\82¢\81D");
else
(void) display_inventory(lets, FALSE);
return 0;
* This must match the object class order.
*/
STATIC_VAR NEARDATA const char *names[] = {
+#if 0 /*JP*/
0, "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", "Tools",
"Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
"Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
+#else
+ 0, "\96\82È\95¨\91Ì", "\95\90\8aí", "\8aZ", "\8ew\97Ö", "\96\82\8f\9c\82¯", "\93¹\8bï",
+ "\90H\97¿", "\96ò", "\8aª\95¨", "\96\82\96@\8f\91", "\8fñ", "\8bà\89Ý",
+ "\95ó\90Î", "\8aâ\82Ü\82½\82Í\92¤\91\9c", "\93S\8b\85", "\8d½", "\93Å"
+#endif
};
+STATIC_VAR NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
+/*JP
+STATIC_VAR NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
+*/
+STATIC_VAR NEARDATA const char *oth_names[] = { "\8bl\82ß\82ç\82ê\82½\93¹\8bï" };
-static NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
-
-static NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
-
-static NEARDATA char *invbuf = (char *) 0;
-static NEARDATA unsigned invbufsiz = 0;
+STATIC_VAR NEARDATA char *invbuf = (char *) 0;
+STATIC_VAR NEARDATA unsigned invbufsiz = 0;
char *
let_to_name(let, unpaid, showsym)
else
class_name = names[0];
+/*JP
len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "")
+*/
+ len = strlen(class_name) + (unpaid ? sizeof "\96¢\95¥\82¢\82Ì" : sizeof "")
+ (oclass ? (strlen(ocsymfmt) + invbuf_sympadding) : 0);
if (len > invbufsiz) {
if (invbuf)
invbuf = (char *) alloc(invbufsiz);
}
if (unpaid)
+/*JP
Strcat(strcpy(invbuf, "Unpaid "), class_name);
+*/
+ Strcat(strcpy(invbuf, "\96¢\95¥\82¢\82Ì"), class_name);
else
Strcpy(invbuf, class_name);
if ((oclass != 0) && showsym) {
* then a 'to' slot for its destination. Open slots and those
* filled by compatible stacks are listed as likely candidates
* but user can pick any inventory letter (including 'from').
- * All compatible items found are gathered into the 'from'
- * stack as it is moved. If the 'to' slot isn't empty and
- * doesn't merge, then its stack is swapped to the 'from' slot.
*
+ * to == from, 'from' has a name
+ * All compatible items (same name or no name) are gathered
+ * into the 'from' stack. No count is allowed.
+ * to == from, 'from' does not have a name
+ * All compatible items without a name are gathered into the
+ * 'from' stack. No count is allowed. Compatible stacks with
+ * names are left as-is.
+ * to != from, no count
+ * Move 'from' to 'to'. If 'to' is not empty, merge 'from'
+ * into it if possible, otherwise swap it with the 'from' slot.
+ * to != from, count given
* If the user specifies a count when choosing the 'from' slot,
* and that count is less than the full size of the stack,
* then the stack will be split. The 'count' portion is moved
* will be moved to an open slot; if there isn't any open slot
* available, the adjustment attempt fails.
*
- * Splitting has one special case: if 'to' slot is non-empty
- * and is compatible with 'from' in all respects except for
- * user-assigned names, the 'count' portion being moved is
- * effectively renamed so that it will merge with 'to' stack.
+ * To minimize merging for 'from == to', unnamed stacks will
+ * merge with named 'from' but named ones won't merge with
+ * unnamed 'from'. Otherwise attempting to collect all unnamed
+ * stacks would lump the first compatible named stack with them
+ * and give them its name.
+ *
+ * To maximize merging for 'from != to', compatible stacks will
+ * merge when either lacks a name (or they already have the same
+ * name). When no count is given and one stack has a name and
+ * the other doesn't, the merged result will have that name.
+ * However, when splitting results in a merger, the name of the
+ * destination overrides that of the source, even if destination
+ * is unnamed and source is named.
*/
int
doorganize() /* inventory organizer by Del Lamb */
{
struct obj *obj, *otmp, *splitting, *bumped;
- int ix, cur, trycnt;
+ int ix, cur, trycnt, goldstacks;
char let;
- char alphabet[52 + 1], buf[52 + 1];
+#define GOLD_INDX 0
+#define GOLD_OFFSET 1
+#define OVRFLW_INDX (GOLD_OFFSET + 52) /* past gold and 2*26 letters */
+ char lets[1 + 52 + 1 + 1]; /* room for '$a-zA-Z#\0' */
char qbuf[QBUFSZ];
- char allowall[3]; /* { ALLOW_COUNT, ALL_CLASSES, 0 } */
+ char allowall[4]; /* { ALLOW_COUNT, ALL_CLASSES, 0, 0 } */
+ char *objname, *otmpname;
const char *adj_type;
+ boolean ever_mind = FALSE, collect;
if (!invent) {
+/*JP
You("aren't carrying anything to adjust.");
+*/
+ You("\8f\87\8f\98\82ð\95Ï\82¦\82é\82à\82Ì\82ð\89½\82à\8e\9d\82Á\82Ä\82¢\82È\82¢\81D");
return 0;
}
allowall[0] = ALLOW_COUNT;
allowall[1] = ALL_CLASSES;
allowall[2] = '\0';
+ for (goldstacks = 0, otmp = invent; otmp; otmp = otmp->nobj) {
+ /* gold should never end up in a letter slot, nor should two '$'
+ slots occur, but if they ever do, allow #adjust to handle them
+ (in the past, things like this have happened, usually due to
+ bknown being erroneously set on one stack, clear on another;
+ object merger isn't fooled by that anymore) */
+ if (otmp->oclass == COIN_CLASS
+ && (otmp->invlet != GOLD_SYM || ++goldstacks > 1)) {
+ allowall[1] = COIN_CLASS;
+ allowall[2] = ALL_CLASSES;
+ allowall[3] = '\0';
+ break;
+ }
+ }
if (!(obj = getobj(allowall, "adjust")))
return 0;
}
/* initialize the list with all lower and upper case letters */
- for (ix = 0, let = 'a'; let <= 'z';)
- alphabet[ix++] = let++;
+ lets[GOLD_INDX] = (obj->oclass == COIN_CLASS) ? GOLD_SYM : ' ';
+ for (ix = GOLD_OFFSET, let = 'a'; let <= 'z';)
+ lets[ix++] = let++;
for (let = 'A'; let <= 'Z';)
- alphabet[ix++] = let++;
- alphabet[ix] = '\0';
+ lets[ix++] = let++;
+ lets[OVRFLW_INDX] = ' ';
+ lets[sizeof lets - 1] = '\0';
/* for floating inv letters, truncate list after the first open slot */
if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
- alphabet[ix + (splitting ? 0 : 1)] = '\0';
+ lets[ix + (splitting ? 0 : 1)] = '\0';
- /* blank out all the letters currently in use in the inventory */
- /* except those that will be merged with the selected object */
+ /* blank out all the letters currently in use in the inventory
+ except those that will be merged with the selected object */
for (otmp = invent; otmp; otmp = otmp->nobj)
if (otmp != obj && !mergable(otmp, obj)) {
let = otmp->invlet;
if (let >= 'a' && let <= 'z')
- alphabet[let - 'a'] = ' ';
+ lets[GOLD_OFFSET + let - 'a'] = ' ';
else if (let >= 'A' && let <= 'Z')
- alphabet[let - 'A' + 26] = ' ';
+ lets[GOLD_OFFSET + let - 'A' + 26] = ' ';
+ /* overflow defaults to off, but it we find a stack using that
+ slot, switch to on -- the opposite of normal invlet handling */
+ else if (let == NOINVSYM)
+ lets[OVRFLW_INDX] = NOINVSYM;
}
/* compact the list by removing all the blanks */
- for (ix = cur = 0; alphabet[ix]; ix++)
- if (alphabet[ix] != ' ')
- buf[cur++] = alphabet[ix];
- if (!cur && obj->invlet == NOINVSYM)
- buf[cur++] = NOINVSYM;
- buf[cur] = '\0';
+ for (ix = cur = 0; lets[ix]; ix++)
+ if (lets[ix] != ' ' && cur++ < ix)
+ lets[cur - 1] = lets[ix];
+ lets[cur] = '\0';
/* and by dashing runs of letters */
if (cur > 5)
- compactify(buf);
+ compactify(lets);
/* get 'to' slot to use as destination */
- Sprintf(qbuf, "Adjust letter to what [%s]%s?", buf,
+#if 0 /*JP:T*/
+ Sprintf(qbuf, "Adjust letter to what [%s]%s?", lets,
invent ? " (? see used letters)" : "");
+#else
+ Sprintf(qbuf, "\82Ç\82Ì\95¶\8e\9a\82É\92²\90®\82µ\82Ü\82·\82©[%s]%s\81H", lets,
+ invent ? " (? \82Å\8eg\82Á\82Ä\82¢\82é\95¶\8e\9a\82ð\95\\8e¦)" : "");
+#endif
for (trycnt = 1; ; ++trycnt) {
let = yn_function(qbuf, (char *) 0, '\0');
if (let == '?' || let == '*') {
compatible stacks get collected along the way,
but splitting to same slot is not */
|| (splitting && let == obj->invlet)) {
- noadjust:
+ noadjust:
if (splitting)
(void) merged(&splitting, &obj);
- pline1(Never_mind);
+ if (!ever_mind)
+ pline1(Never_mind);
return 0;
+ } else if (let == GOLD_SYM && obj->oclass != COIN_CLASS) {
+#if 0 /*JP*/
+ pline("Only gold coins may be moved into the '%c' slot.",
+ GOLD_SYM);
+#else
+ pline("'%c'\82É\82Å\82«\82é\82Ì\82Í\8bà\89Ý\82¾\82¯\81D",
+ GOLD_SYM);
+#endif
+ ever_mind = TRUE;
+ goto noadjust;
}
- if ((letter(let) && let != '@') || index(buf, let))
+ /* letter() classifies '@' as one; compactify() can put '-' in lets;
+ the only thing of interest that index() might find is '$' or '#'
+ since letter() catches everything else that we put into lets[] */
+ if ((letter(let) && let != '@') || (index(lets, let) && let != '-'))
break; /* got one */
if (trycnt == 5)
goto noadjust;
+#if 0 /*JP*/
pline("Select an inventory slot letter."); /* else try again */
+#else
+ pline("\8e\9d\82¿\95¨\82Ì\95¶\8e\9a\82ð\91I\82ñ\82Å\82\82¾\82³\82¢\81D");
+#endif
}
+ collect = (let == obj->invlet);
/* change the inventory and print the resulting item */
- adj_type = !splitting ? "Moving:" : "Splitting:";
+/*JP
+ adj_type = collect ? "Collecting" : !splitting ? "Moving:" : "Splitting:";
+*/
+ adj_type = collect ? "\82ð\8fW\82ß\82½\81D" : !splitting ? "\82ð\88Ú\93®\82µ\82½\81D" : "\82ð\95ª\8a\84\82µ\82½\81D";
/*
* don't use freeinv/addinv to avoid double-touching artifacts,
extract_nobj(obj, &invent);
for (otmp = invent; otmp;) {
- if (!splitting) {
- if (merged(&otmp, &obj)) {
+ /* it's tempting to pull this outside the loop, but merged() could
+ free ONAME(obj) [via obfree()] and replace it with ONAME(otmp) */
+ objname = has_oname(obj) ? ONAME(obj) : (char *) 0;
+
+ if (collect) {
+ /* Collecting: #adjust an inventory stack into its same slot;
+ keep it there and merge other compatible stacks into it.
+ Traditional inventory behavior is to merge unnamed stacks
+ with compatible named ones; we only want that if it is
+ the 'from' stack (obj) with a name and candidate (otmp)
+ without one, not unnamed 'from' with named candidate. */
+ otmpname = has_oname(otmp) ? ONAME(otmp) : (char *) 0;
+ if ((!otmpname || (objname && !strcmp(objname, otmpname)))
+ && merged(&otmp, &obj)) {
+/*JP
adj_type = "Merging:";
+*/
+ adj_type = "\82ð\8d\87\82í\82¹\82½\81D";
obj = otmp;
otmp = otmp->nobj;
extract_nobj(obj, &invent);
continue; /* otmp has already been updated */
- } else if (otmp->invlet == let) {
+ }
+ } else if (otmp->invlet == let) {
+ /* Moving or splitting: don't merge extra compatible stacks.
+ Found 'otmp' in destination slot; merge if compatible,
+ otherwise bump whatever is there to an open slot. */
+ if (!splitting) {
+/*JP
adj_type = "Swapping:";
+*/
+ adj_type = "\82ð\8cð\8a·\82µ\82½\81D";
otmp->invlet = obj->invlet;
- }
- } else {
- /* splitting: don't merge extra compatible stacks;
- if destination is compatible, do merge with it,
- otherwise bump whatever is there to an open slot */
- if (otmp->invlet == let) {
- int olth = 0;
-
- if (has_oname(obj))
- olth = strlen(ONAME(obj));
- /* ugly hack: if these objects aren't going to merge
- solely because they have conflicting user-assigned
- names, strip off the name of the one being moved */
- if (olth && !obj->oartifact && !mergable(otmp, obj)) {
- char *holdname = ONAME(obj);
+ } else {
+ /* strip 'from' name if it has one */
+ if (objname && !obj->oartifact)
ONAME(obj) = (char *) 0;
- /* restore name iff merging is still not possible */
- if (!mergable(otmp, obj)) {
- ONAME(obj) = holdname;
- holdname = (char *) 0;
- } else
- free((genericptr_t) holdname);
+ if (!mergable(otmp, obj)) {
+ /* won't merge; put 'from' name back */
+ if (objname)
+ ONAME(obj) = objname;
+ } else {
+ /* will merge; discard 'from' name */
+ if (objname)
+ free((genericptr_t) objname), objname = 0;
}
if (merged(&otmp, &obj)) {
+/*JP
+ adj_type = "Splitting and merging:";
+*/
+ adj_type = "\82ð\95ª\8a\84\82µ\82Ä\8d\87\82í\82¹\82½\81D";
obj = otmp;
extract_nobj(obj, &invent);
} else if (inv_cnt(FALSE) >= 52) {
(void) merged(&splitting, &obj); /* undo split */
/* "knapsack cannot accommodate any more items" */
+/*JP
Your("pack is too full.");
+*/
+ Your("\8e\9d\82¿\95¨\82Í\88ê\94t\82¾\81D");
return 0;
} else {
bumped = otmp;
extract_nobj(bumped, &invent);
}
- break;
- } /* found 'to' slot */
- } /* splitting */
+ } /* moving vs splitting */
+ break; /* not collecting and found 'to' slot */
+ } /* collect */
otmp = otmp->nobj;
}
/* messages deferred until inventory has been fully reestablished */
prinv(adj_type, obj, 0L);
if (bumped)
+/*JP
prinv("Moving:", bumped, 0L);
+*/
+ prinv("\88Ú\93®:", bumped, 0L);
if (splitting)
clear_splitobjs(); /* reset splitobj context */
update_inventory();
* By default, only worn and wielded items are displayed. The caller
* can pick one. Modifier flags are:
*
- * MINV_NOLET - nothing selectable
- * MINV_ALL - display all inventory
+ * PICK_NONE, PICK_ONE - standard menu control
+ * PICK_ANY - allowed, but we only return a single object
+ * MINV_NOLET - nothing selectable
+ * MINV_ALL - display all inventory
*/
struct obj *
display_minventory(mon, dflags, title)
menu_item *selected = 0;
int do_all = (dflags & MINV_ALL) != 0,
incl_hero = (do_all && u.uswallow && mon == u.ustuck),
- have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero);
+ have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
+ pickings = (dflags & MINV_PICKMASK);
+#if 0 /*JP*/
Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
do_all ? "possessions" : "armament");
+#else
+ Sprintf(tmp, "%s\82Ì%s\81F", Monnam(mon),
+ do_all ? "\8e\9d\82¿\95¨" : "\91\95\94õ");
+#endif
if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
/* Fool the 'weapon in hand' routine into
* displaying 'weapon in claw', etc. properly.
*/
youmonst.data = mon->data;
+ /* in case inside a shop, don't append "for sale" prices */
+ iflags.suppress_price++;
- n = query_objlist(title ? title : tmp, mon->minvent,
- INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0),
- &selected,
- (dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE,
+ n = query_objlist(title ? title : tmp, &(mon->minvent),
+ (INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0)),
+ &selected, pickings,
do_all ? allow_all : worn_wield_only);
- set_uasmon();
+ iflags.suppress_price--;
+ /* was 'set_uasmon();' but that potentially has side-effects */
+ youmonst.data = &mons[u.umonnum]; /* most basic part of set_uasmon */
} else {
+/*JP
invdisp_nothing(title ? title : tmp, "(none)");
+*/
+ invdisp_nothing(title ? title : tmp, "(\89½\82à\82È\82¢)");
n = 0;
}
int n;
menu_item *selected = 0;
+#if 0 /*JP*/
(void) safe_qbuf(qbuf, "Contents of ", ":", obj, doname, ansimpleoname,
"that");
+#else
+ (void) safe_qbuf(qbuf, "", "\82Ì\92\86\90g\81F", obj, doname, ansimpleoname,
+ "\82»");
+#endif
if (obj->cobj) {
- n = query_objlist(qbuf, obj->cobj, INVORDER_SORT, &selected,
- PICK_NONE, allow_all);
+ n = query_objlist(qbuf, &(obj->cobj), INVORDER_SORT,
+ &selected, PICK_NONE, allow_all);
} else {
+/*JP
invdisp_nothing(qbuf, "(empty)");
+*/
+ invdisp_nothing(qbuf, "(\8bó\82Á\82Û)");
n = 0;
}
if (n > 0) {
if (n) {
only.x = x;
only.y = y;
- if (query_objlist("Things that are buried here:", level.buriedobjlist,
- INVORDER_SORT, &selected, PICK_NONE, only_here) > 0)
+/*JP
+ if (query_objlist("Things that are buried here:",
+*/
+ if (query_objlist("\82±\82±\82É\96\84\82ß\82ç\82ê\82Ä\82¢\82é\82à\82Ì\81F",
+ &level.buriedobjlist, INVORDER_SORT,
+ &selected, PICK_NONE, only_here) > 0)
free((genericptr_t) selected);
only.x = only.y = 0;
}