-/* 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 $ */
+/* NetHack 3.6 invent.c $NHDT-Date: 1575245062 2019/12/02 00:04:22 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.267 $ */
/* 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 */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020 */
/* JNetHack may be freely redistributed. See license for details. */
#include "hack.h"
case DRUM_OF_EARTHQUAKE:
case HORN_OF_PLENTY: /* not a musical instrument */
k = 3; /* instrument or unknown horn of plenty */
+ break;
default:
k = 4; /* 'other' tool */
+ break;
}
break;
case FOOD_CLASS:
* (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
+ * As of 3.6.2: revert to the temporary array of ordered obj pointers
+ * but have 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
otmp->age = ((otmp->age * otmp->quan) + (obj->age * obj->quan))
/ (otmp->quan + obj->quan);
- otmp->quan += obj->quan;
+ if (!otmp->globby)
+ otmp->quan += obj->quan;
/* temporary special case for gold objects!!!! */
if (otmp->oclass == COIN_CLASS)
otmp->owt = weight(otmp), otmp->bknown = 0;
* http://concord.wikia.com/wiki/List_of_Fictional_Currencies
*/
static const char *const currencies[] = {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
"Altarian Dollar", /* The Hitchhiker's Guide to the Galaxy */
"Ankh-Morpork Dollar", /* Discworld */
"auric", /* The Domination of Draka */
{
const char *res;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
res = Hallucination ? currencies[rn2(SIZE(currencies))] : "zorkmid";
if (amount != 1L)
res = makeplural(res);
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)));
+ Sprintf(qbuf, "your %s", fingers_or_gloves(FALSE));
else if (!strcmp(word, "write with"))
Sprintf(qbuf, "your %s", body_part(FINGERTIP));
else if (!strcmp(word, "wield"))
is_worn(otmp)
struct obj *otmp;
{
- return (otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_SADDLE | W_WEAPON))
+ return (otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_SADDLE | W_WEAPONS))
? TRUE
: FALSE;
}
ilets[iletct] = '\0';
for (;;) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]",
word, ilets);
#else
Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
first = FALSE;
}
-#if 0 /*JP*/
+#if 0 /*JP:T*/
(void) safe_qbuf(qbuf, qpfx, "?", otmp,
ininv ? safeq_xprname : doname,
ininv ? safeq_shortxprname : ansimpleoname,
update_inventory();
}
+/* persistent inventory window is maintained by interface code;
+ 'update_inventory' used to be a macro for
+ (*windowprocs.win_update_inventory) but the restore hackery
+ was getting out of hand; this is now a central call point */
+void
+update_inventory()
+{
+ if (restoring)
+ return;
+
+ /*
+ * Ought to check (windowprocs.wincap2 & WC2_PERM_INVENT) here....
+ *
+ * We currently don't skip this call when iflags.perm_invent is False
+ * because curses uses that to disable a previous perm_invent window
+ * (after toggle via 'O'; perhaps the options code should handle that).
+ */
+ (*windowprocs.win_update_inventory)();
+}
+
/* should of course only be called for things in invent */
STATIC_OVL char
obj_to_let(obj)
*/
if (cost != 0 || let == '*') {
/* if dot is true, we're doing Iu, otherwise Ix */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Sprintf(li,
iflags.menu_tab_sep ? "%c - %s\t%6ld %s"
: "%c - %-45s %6ld %s",
menu_item *selected;
unsigned sortflags;
Loot *sortedinvent, *srtinv;
- boolean wizid = FALSE;
+ boolean wizid = (wizard && iflags.override_ID), gotsomething = FALSE;
if (lets && !*lets)
lets = 0; /* simplify tests: (lets) instead of (lets && *lets) */
- if (iflags.perm_invent && (lets || xtra_choice)) {
+ if (iflags.perm_invent && (lets || xtra_choice || wizid)) {
/* 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 */
add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
"(all items are permanently identified already)",
MENU_UNSELECTED);
+ gotsomething = TRUE;
} else {
any.a_obj = &wizid_fakeobj;
Sprintf(prompt, "select %s to permanently identify",
/* 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 */
+ the #wizidentify command, so include it as a group accelator
+ but use '_' as the primary selector */
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;
+ gotsomething = TRUE;
}
} else if (xtra_choice) {
/* wizard override ID and xtra_choice are mutually exclusive */
any.a_char = HANDS_SYM; /* '-' */
add_menu(win, NO_GLYPH, &any, HANDS_SYM, 0, ATR_NONE,
xtra_choice, MENU_UNSELECTED);
+ gotsomething = TRUE;
}
nextclass:
classcount = 0;
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);
+ gotsomething = TRUE;
}
}
if (flags.sortpack) {
}
if (iflags.force_invmenu && lets && want_reply) {
any = zeroany;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
"Special", MENU_UNSELECTED);
#else
"\93Á\8eê", MENU_UNSELECTED);
#endif
any.a_char = '*';
-#if 0 /*JP*/
+#if 0 /*JP:T*/
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
+ gotsomething = TRUE;
}
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) {
+ the n==0 case above gets skipped for perm_invent), put something
+ into the menu */
+ if (iflags.perm_invent && !lets && !gotsomething) {
any = zeroany;
add_menu(win, NO_GLYPH, &any, 0, 0, 0,
not_carrying_anything, MENU_UNSELECTED);
if (wizid) {
int i;
+ /* identifying items will update perm_invent, calling this
+ routine recursively, and we don't want the nested call
+ to filter on unID'd items */
+ iflags.override_ID = 0;
ret = '\0';
for (i = 0; i < n; ++i) {
otmp = selected[i].item.a_obj;
/* count everything inside a container, or just shop-owned items inside */
long
-count_contents(container, nested, quantity, everything)
+count_contents(container, nested, quantity, everything, newdrop)
struct obj *container;
boolean nested, /* include contents of any nested containers */
quantity, /* count all vs count separate stacks */
- everything; /* all objects vs only unpaid objects */
+ everything, /* all objects vs only unpaid objects */
+ newdrop; /* on floor, but hero-owned items haven't been marked
+ * no_charge yet and shop-owned items are still marked
+ * unpaid -- used when asking the player whether to sell */
{
struct obj *otmp, *topc;
boolean shoppy = FALSE;
long count = 0L;
- if (!everything) {
+ if (!everything && !newdrop) {
+ xchar x, y;
+
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);
+ if (topc->where == OBJ_FLOOR && get_obj_location(topc, &x, &y, 0))
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);
+ count += count_contents(otmp, nested, quantity, everything,
+ newdrop);
if (everything || otmp->unpaid || (shoppy && !otmp->no_charge))
count += quantity ? otmp->quan : 1L;
}
}
putstr(win, 0, "");
-#if 0 /*JP*/
+#if 0 /*JP:T*/
putstr(win, 0,
xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
#else
if (billx)
(void) doinvbill(1);
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("No used-up objects%s.",
unpaid_count ? " on your shopping bill" : "");
#else
/*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);
+ You("%s%s\82à\82Ì\82Í\89½\82à\8e\9d\82Á\82Ä\82¢\82È\82¢\81D", before, after);
return 0;
}
this_type = oclass;
else if (IS_SINK(ltyp))
cmap = S_sink; /* "sink" */
else if (IS_ALTAR(ltyp)) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Sprintf(altbuf, "%saltar to %s (%s)",
((lev->altarmask & AM_SHRINE)
&& (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)))
if (u.uswallow && u.ustuck) {
struct monst *mtmp = u.ustuck;
+ /*
+ * FIXME?
+ * Engulfer's inventory can include worn items (specific case is
+ * Juiblex being created with an amulet as random defensive item)
+ * which will be flagged as "(being worn)". This code includes
+ * such a worn item under the header "Contents of <mon>'s stomach",
+ * a nifty trick for how/where to wear stuff. The situation is
+ * rare enough to turn a blind eye.
+ *
+ * 3.6.3: Pickup has been changed to decline to pick up a worn
+ * item from inside an engulfer, but if player tries, it just
+ * says "you can't" without giving a reason why (which would be
+ * something along the lines of "because it's worn on the outside
+ * so is unreachable from in here...").
+ */
#if 0 /*JP:T*/
Sprintf(fbuf, "Contents of %s %s", s_suffix(mon_nam(mtmp)),
mbodypart(mtmp, STOMACH));
*/
There("\82±\82±\82É\82Í%s\88ê\82Â\82à\82Ì\82ª\82 \82é\81D", picked_some ? "\82à\82¤" : "");
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
There("are %s%s objects here.",
(obj_cnt < 5)
? "a few"
putstr(tmpwin, 0, fbuf);
putstr(tmpwin, 0, "");
}
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Sprintf(buf, "%s that %s here:",
picked_some ? "Other things" : "Things",
Blind ? "you feel" : "are");
Strcpy(kbuf, corpse_xname(otmp, (const char *) 0, CXN_PFX_THE));
if (poly_when_stoned(youmonst.data))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("touched %s with your bare %s.", kbuf,
makeplural(body_part(HAND)));
#else
if (obj->oclass == COIN_CLASS)
return TRUE;
- if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
- || 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->bypass != otmp->bypass)
+ if (obj->bypass != otmp->bypass
+ || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed)
return FALSE;
if (obj->globby)
* or don't inhibit their merger.
*/
+ if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
+ || obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
+ || obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit)
+ return FALSE;
+
if (obj->oclass == FOOD_CLASS
&& (obj->oeaten != otmp->oeaten || obj->orotten != otmp->orotten))
return FALSE;
* This must match the object class order.
*/
STATIC_VAR NEARDATA const char *names[] = {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
0, "Illegal objects", "Weapons", "Armor", "Rings", "Amulets", "Tools",
"Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
"Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
const char *adj_type;
boolean ever_mind = FALSE, collect;
- if (!invent) {
-/*JP
- You("aren't carrying anything to adjust.");
-*/
+ /* when no invent, or just gold in '$' slot, there's nothing to adjust */
+ if (!invent || (invent->oclass == COIN_CLASS
+ && invent->invlet == GOLD_SYM && !invent->nobj)) {
+#if 0 /*JP:T*/
+ You("aren't carrying anything %s.",
+ !invent ? "to adjust" : "adjustable");
+#else
You("\8f\87\8f\98\82ð\95Ï\82¦\82é\82à\82Ì\82ð\89½\82à\8e\9d\82Á\82Ä\82¢\82È\82¢\81D");
+#endif
return 0;
}
pline1(Never_mind);
return 0;
} else if (let == GOLD_SYM && obj->oclass != COIN_CLASS) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("Only gold coins may be moved into the '%c' slot.",
GOLD_SYM);
#else
break; /* got one */
if (trycnt == 5)
goto noadjust;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
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");
have_inv = (mon->minvent != 0), have_any = (have_inv || incl_hero),
pickings = (dflags & MINV_PICKMASK);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Sprintf(tmp, "%s %s:", s_suffix(noit_Monnam(mon)),
do_all ? "possessions" : "armament");
#else
int n;
menu_item *selected = 0;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
(void) safe_qbuf(qbuf, "Contents of ", ":", obj, doname, ansimpleoname,
"that");
#else