streamlined container interface (trunk only)
Reduce the number of questions issued when applying or looting a
container, and offer the opportunity to put things inside before taking
things out. Instead of "Do you want to take something out? [:ynq]",
followed by "Do you want to put something in? [ynq]", this gives just one
prompt; the result is similar to menustyle:full where you start out by
choosing between out, in, and both. There are now two additional choices:
reversed, for both in the opposite order, and stash, to put a single item
inside. Prompt phrasing is rather clumsy; I wanted to keep it short:
"Do what with <the container>? [:oibrsq or ?]", where picking '?' pops
up a brief help window. Inappropriate choices (like 'o'and 'b' when
container is empty) are suppressed from the prompt but still acceptable as
input; " or ?" is suppressed if the cmdassist option has been toggled off,
but entering '?' still works to get help.
Menu mode wouldn't allow 'b' when inventory was empty, despite the
fact that first taking things out might change that. Now 'b' is a viable
choice if the container isn't empty, and the new 'r' is a vialble choice
when inventory isn't empty even if the container is.
This commit is contained in:
@@ -274,6 +274,7 @@ the Amulet can be offered to Moloch
|
|||||||
javelins and spears now share the same weapon skill
|
javelins and spears now share the same weapon skill
|
||||||
all stackable weapons are capable of being thrown/shot for multi-shot volleys
|
all stackable weapons are capable of being thrown/shot for multi-shot volleys
|
||||||
worm teeth and crysknives have become stackable
|
worm teeth and crysknives have become stackable
|
||||||
|
improved container interface
|
||||||
|
|
||||||
|
|
||||||
Platform- and/or Interface-Specific New Features
|
Platform- and/or Interface-Specific New Features
|
||||||
|
|||||||
+32
-6
@@ -781,7 +781,9 @@ register const char *let,*word;
|
|||||||
register int foo = 0;
|
register int foo = 0;
|
||||||
register char *bp = buf;
|
register char *bp = buf;
|
||||||
xchar allowcnt = 0; /* 0, 1 or 2 */
|
xchar allowcnt = 0; /* 0, 1 or 2 */
|
||||||
|
struct obj *firstobj = invent;
|
||||||
#ifndef GOLDOBJ
|
#ifndef GOLDOBJ
|
||||||
|
struct obj *u_gold = 0;
|
||||||
boolean allowgold = FALSE; /* can't use gold because they don't have any */
|
boolean allowgold = FALSE; /* can't use gold because they don't have any */
|
||||||
#endif
|
#endif
|
||||||
boolean usegold = FALSE; /* can't use gold because its illegal */
|
boolean usegold = FALSE; /* can't use gold because its illegal */
|
||||||
@@ -797,6 +799,13 @@ register const char *let,*word;
|
|||||||
#ifndef GOLDOBJ
|
#ifndef GOLDOBJ
|
||||||
if(*let == COIN_CLASS) let++,
|
if(*let == COIN_CLASS) let++,
|
||||||
usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE);
|
usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE);
|
||||||
|
if (firstobj && firstobj->oclass == COIN_CLASS) {
|
||||||
|
/* gold has been inserted into inventory; skip it during
|
||||||
|
inventory letter collection */
|
||||||
|
u_gold = firstobj;
|
||||||
|
firstobj = u_gold->nobj;
|
||||||
|
allowgold = usegold;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if(*let == COIN_CLASS) let++, usegold = TRUE;
|
if(*let == COIN_CLASS) let++, usegold = TRUE;
|
||||||
#endif
|
#endif
|
||||||
@@ -835,7 +844,7 @@ register const char *let,*word;
|
|||||||
|
|
||||||
if (!flags.invlet_constant) reassign();
|
if (!flags.invlet_constant) reassign();
|
||||||
|
|
||||||
for (otmp = invent; otmp; otmp = otmp->nobj) {
|
for (otmp = firstobj; otmp; otmp = otmp->nobj) {
|
||||||
if (&bp[foo] == &buf[sizeof buf - 1] ||
|
if (&bp[foo] == &buf[sizeof buf - 1] ||
|
||||||
ap == &altlets[sizeof altlets - 1]) {
|
ap == &altlets[sizeof altlets - 1]) {
|
||||||
/* we must have a huge number of NOINVSYM items somehow */
|
/* we must have a huge number of NOINVSYM items somehow */
|
||||||
@@ -937,6 +946,7 @@ register const char *let,*word;
|
|||||||
|| (!strcmp(word, "sacrifice") &&
|
|| (!strcmp(word, "sacrifice") &&
|
||||||
/* (!astral && amulet) || (astral && !amulet) */
|
/* (!astral && amulet) || (astral && !amulet) */
|
||||||
(!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
|
(!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
|
||||||
|
|| (!strcmp(word, "stash") && !ck_bag(otmp))
|
||||||
) {
|
) {
|
||||||
/* acceptable but not listed as likely candidate */
|
/* acceptable but not listed as likely candidate */
|
||||||
foo--;
|
foo--;
|
||||||
@@ -1032,7 +1042,11 @@ register const char *let,*word;
|
|||||||
#ifndef GOLDOBJ
|
#ifndef GOLDOBJ
|
||||||
if(!(allowcnt == 2 && cnt < u.ugold))
|
if(!(allowcnt == 2 && cnt < u.ugold))
|
||||||
cnt = u.ugold;
|
cnt = u.ugold;
|
||||||
return(mkgoldobj(cnt));
|
if (!u_gold)
|
||||||
|
u_gold = mkgoldobj(cnt);
|
||||||
|
else if (cnt < u_gold->quan)
|
||||||
|
u_gold = splitobj(u_gold, cnt);
|
||||||
|
return u_gold;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if(ilet == '?' || ilet == '*') {
|
if(ilet == '?' || ilet == '*') {
|
||||||
@@ -1424,14 +1438,17 @@ register int FDECL((*fn),(OBJ_P)), FDECL((*ckfn),(OBJ_P));
|
|||||||
struct obj *otmp, *otmp2, *otmpo;
|
struct obj *otmp, *otmp2, *otmpo;
|
||||||
register char sym, ilet;
|
register char sym, ilet;
|
||||||
register int cnt = 0, dud = 0, tmp;
|
register int cnt = 0, dud = 0, tmp;
|
||||||
boolean takeoff, nodot, ident, ininv;
|
boolean takeoff, nodot, ident, take_out, put_in, first, ininv;
|
||||||
char qbuf[BUFSZ];
|
char qbuf[QBUFSZ], qpfx[QBUFSZ];
|
||||||
|
|
||||||
takeoff = taking_off(word);
|
takeoff = taking_off(word);
|
||||||
ident = !strcmp(word, "identify");
|
ident = !strcmp(word, "identify");
|
||||||
|
take_out = !strcmp(word, "take out");
|
||||||
|
put_in = !strcmp(word, "put in");
|
||||||
nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") ||
|
nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") ||
|
||||||
ident || takeoff);
|
ident || takeoff || take_out || put_in);
|
||||||
ininv = (*objchn == invent);
|
ininv = (*objchn == invent);
|
||||||
|
first = TRUE;
|
||||||
/* Changed so the askchain is interrogated in the order specified.
|
/* Changed so the askchain is interrogated in the order specified.
|
||||||
* For example, if a person specifies =/ then first all rings will be
|
* For example, if a person specifies =/ then first all rings will be
|
||||||
* asked about followed by all wands -dgk
|
* asked about followed by all wands -dgk
|
||||||
@@ -1450,7 +1467,16 @@ nextclass:
|
|||||||
if (!allflag) {
|
if (!allflag) {
|
||||||
safeq_xprn_ctx.let = ilet;
|
safeq_xprn_ctx.let = ilet;
|
||||||
safeq_xprn_ctx.dot = !nodot;
|
safeq_xprn_ctx.dot = !nodot;
|
||||||
(void)safe_qbuf(qbuf, (char *)0, "?",
|
*qpfx = '\0';
|
||||||
|
if (first) {
|
||||||
|
/* traditional_loot() skips prompting when only one
|
||||||
|
class of objects is involved, so prefix the first
|
||||||
|
object being queried here with an explanation why */
|
||||||
|
if (take_out || put_in)
|
||||||
|
Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
|
||||||
|
first = FALSE;
|
||||||
|
}
|
||||||
|
(void)safe_qbuf(qbuf, qpfx, "?",
|
||||||
otmp, ininv ? safeq_xprname : doname,
|
otmp, ininv ? safeq_xprname : doname,
|
||||||
ininv ? safeq_shortxprname : ansimpleoname,
|
ininv ? safeq_shortxprname : ansimpleoname,
|
||||||
"item");
|
"item");
|
||||||
|
|||||||
+291
-186
@@ -1,4 +1,4 @@
|
|||||||
/* SCCS Id: @(#)pickup.c 3.5 2006/10/16 */
|
/* SCCS Id: @(#)pickup.c 3.5 2007/01/02 */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -33,8 +33,11 @@ STATIC_PTR int FDECL(in_container,(struct obj *));
|
|||||||
STATIC_PTR int FDECL(out_container,(struct obj *));
|
STATIC_PTR int FDECL(out_container,(struct obj *));
|
||||||
STATIC_DCL long FDECL(mbag_item_gone, (int,struct obj *));
|
STATIC_DCL long FDECL(mbag_item_gone, (int,struct obj *));
|
||||||
STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
|
STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
|
||||||
|
STATIC_DCL void NDECL(explain_container_prompt);
|
||||||
|
STATIC_DCL int FDECL(traditional_loot, (BOOLEAN_P));
|
||||||
STATIC_DCL int FDECL(menu_loot, (int,BOOLEAN_P));
|
STATIC_DCL int FDECL(menu_loot, (int,BOOLEAN_P));
|
||||||
STATIC_DCL int FDECL(in_or_out_menu, (const char *,struct obj *, BOOLEAN_P, BOOLEAN_P));
|
STATIC_DCL char FDECL(in_or_out_menu, (const char *,struct obj *,
|
||||||
|
BOOLEAN_P,BOOLEAN_P));
|
||||||
STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
|
STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
|
||||||
STATIC_DCL boolean FDECL(able_to_loot, (int,int,BOOLEAN_P));
|
STATIC_DCL boolean FDECL(able_to_loot, (int,int,BOOLEAN_P));
|
||||||
STATIC_DCL boolean FDECL(mon_beside, (int, int));
|
STATIC_DCL boolean FDECL(mon_beside, (int, int));
|
||||||
@@ -2053,6 +2056,36 @@ int FDECL((*fn), (OBJ_P));
|
|||||||
return ((fn == in_container || fn == out_container) && !current_container);
|
return ((fn == in_container || fn == out_container) && !current_container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC_OVL void
|
||||||
|
explain_container_prompt()
|
||||||
|
{
|
||||||
|
static const char * const explaintext[] = {
|
||||||
|
"Container actions:",
|
||||||
|
"",
|
||||||
|
" : -- Look: examine contents",
|
||||||
|
" o -- Out: take things out",
|
||||||
|
" i -- In: put things in",
|
||||||
|
" b -- Both: first take things out, then put things in",
|
||||||
|
" r -- Reversed: put things in, then take things out",
|
||||||
|
" s -- Stash: put one item in",
|
||||||
|
" q -- Quit: do nothing",
|
||||||
|
" ? -- Help: display this text.",
|
||||||
|
"",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
const char * const *txtpp;
|
||||||
|
winid win;
|
||||||
|
|
||||||
|
/* "Do what with <container>? [:oibrsq or ?] (q)" */
|
||||||
|
if ((win = create_nhwindow(NHW_TEXT)) != WIN_ERR) {
|
||||||
|
for (txtpp = explaintext; *txtpp; ++txtpp) putstr(win, 0, *txtpp);
|
||||||
|
display_nhwindow(win, FALSE);
|
||||||
|
destroy_nhwindow(win);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char stashable[] = { ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, 0 };
|
||||||
|
|
||||||
int
|
int
|
||||||
use_container(objp, held)
|
use_container(objp, held)
|
||||||
struct obj **objp;
|
struct obj **objp;
|
||||||
@@ -2062,21 +2095,21 @@ int held;
|
|||||||
#ifndef GOLDOBJ
|
#ifndef GOLDOBJ
|
||||||
struct obj *u_gold = (struct obj *)0;
|
struct obj *u_gold = (struct obj *)0;
|
||||||
#endif
|
#endif
|
||||||
boolean one_by_one, allflag, quantum_cat = FALSE,
|
boolean quantum_cat, cursed_mbag,
|
||||||
loot_out = FALSE, loot_in = FALSE;
|
loot_out, loot_in, loot_in_first, stash_one,
|
||||||
char selection[MAXOCLASSES+1];
|
inokay, outokay, outmaybe;
|
||||||
char qbuf[BUFSZ], emptymsg[BUFSZ], pbuf[QBUFSZ];
|
char c, emptymsg[BUFSZ],
|
||||||
long loss = 0L;
|
qbuf[QBUFSZ], pbuf[QBUFSZ], xbuf[QBUFSZ];
|
||||||
int cnt = 0, used = 0,
|
long loss;
|
||||||
menu_on_request;
|
int cnt, used = 0;
|
||||||
|
|
||||||
emptymsg[0] = '\0';
|
emptymsg[0] = '\0';
|
||||||
if (nohands(youmonst.data)) {
|
if (nohands(youmonst.data)) {
|
||||||
You("have no hands!"); /* not `body_part(HAND)' */
|
You("have no hands!"); /* not `body_part(HAND)' */
|
||||||
return 0;
|
return 0;
|
||||||
} else if (!freehand()) {
|
} else if (!freehand()) {
|
||||||
You("have no free %s.", body_part(HAND));
|
You("have no free %s.", body_part(HAND));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (obj->olocked) {
|
if (obj->olocked) {
|
||||||
pline("%s locked.", Tobjnam(obj, "are"));
|
pline("%s locked.", Tobjnam(obj, "are"));
|
||||||
@@ -2099,16 +2132,19 @@ int held;
|
|||||||
current_container = obj; /* for use by in/out_container */
|
current_container = obj; /* for use by in/out_container */
|
||||||
/* from here on out, all early returns go through containerdone */
|
/* from here on out, all early returns go through containerdone */
|
||||||
|
|
||||||
if (obj->spe == 1) {
|
/* check for Schroedinger's Cat */
|
||||||
observe_quantum_cat(obj);
|
quantum_cat = (current_container->spe == 1); /* "it's _now_ empty" */
|
||||||
|
if (quantum_cat) {
|
||||||
|
observe_quantum_cat(current_container);
|
||||||
used = 1;
|
used = 1;
|
||||||
quantum_cat = TRUE; /* for adjusting "it's empty" message */
|
|
||||||
}
|
}
|
||||||
/* Count the number of contained objects. Sometimes toss objects if */
|
/* count the number of contained objects;
|
||||||
/* a cursed magic bag. */
|
sometimes toss objects if a cursed magic bag */
|
||||||
for (curr = obj->cobj; curr; curr = otmp) {
|
cursed_mbag = Is_mbag(current_container) && current_container->cursed;
|
||||||
|
cnt = 0, loss = 0L;
|
||||||
|
for (curr = current_container->cobj; curr; curr = otmp) {
|
||||||
otmp = curr->nobj;
|
otmp = curr->nobj;
|
||||||
if (Is_mbag(obj) && obj->cursed && !rn2(13)) {
|
if (cursed_mbag && !rn2(13)) {
|
||||||
obj_extract_self(curr);
|
obj_extract_self(curr);
|
||||||
loss += mbag_item_gone(held, curr);
|
loss += mbag_item_gone(held, curr);
|
||||||
used = 1;
|
used = 1;
|
||||||
@@ -2116,170 +2152,159 @@ int held;
|
|||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cursed_mbag) { /* magic bag might have lost some contents */
|
||||||
if (loss) /* magic bag lost some shop goods */
|
if (loss)
|
||||||
You("owe %ld %s for lost merchandise.", loss, currency(loss));
|
You("owe %ld %s for lost merchandise.", loss, currency(loss));
|
||||||
obj->owt = weight(obj); /* in case any items were lost */
|
current_container->owt = weight(current_container);
|
||||||
|
}
|
||||||
if (!cnt) {
|
inokay = (invent != 0 &&
|
||||||
Sprintf(emptymsg, "%s is %sempty.", Ysimple_name2(obj),
|
!(invent == current_container && !current_container->nobj));
|
||||||
|
#ifndef GOLDOBJ
|
||||||
|
if (u.ugold) inokay = TRUE;
|
||||||
|
#endif
|
||||||
|
outokay = (cnt > 0);
|
||||||
|
if (!outokay) /* preformat the empty-container message */
|
||||||
|
Sprintf(emptymsg, "%s is %sempty.",
|
||||||
|
Ysimple_name2(current_container),
|
||||||
quantum_cat ? "now " : "");
|
quantum_cat ? "now " : "");
|
||||||
}
|
|
||||||
|
|
||||||
if (cnt || flags.menu_style == MENU_FULL) {
|
/*
|
||||||
(void)safe_qbuf(qbuf, "Do you want to take something out of ", "?",
|
* What-to-do prompt's list of possible actions:
|
||||||
obj, yname, ysimple_name, "it");
|
* always include the look-inside choice (':');
|
||||||
if (flags.menu_style != MENU_TRADITIONAL) {
|
* include the take-out choice ('o') if container
|
||||||
if (flags.menu_style == MENU_FULL) {
|
* has anything in it or if player doesn't yet know
|
||||||
int t;
|
* that it's empty (latter can change on subsequent
|
||||||
char menuprompt[BUFSZ];
|
* iterations if player picks ':' response);
|
||||||
boolean outokay = (cnt != 0),
|
* include the put-in choices ('i','s') if hero
|
||||||
inokay = (invent != 0);
|
* carries any inventory (including gold);
|
||||||
|
* include do-both when 'o' is available, even if
|
||||||
#ifndef GOLDOBJ
|
* inventory is empty--taking out could alter that;
|
||||||
if (u.ugold) inokay = TRUE;
|
* include do-both-reversed when 'i' is available,
|
||||||
#endif
|
* even if container is empty--for similar reason;
|
||||||
if (!cnt) obj->cknown = 1; /* will be giving emptymsg */
|
* always include the quit choice ('q').
|
||||||
|
* include the help choice (" or ?") if `cmdassist'
|
||||||
if (!outokay && !inokay) {
|
* run-time option is set;
|
||||||
pline("%s", emptymsg);
|
* (Player can pick any of (o,i,b,r,s,?) even when
|
||||||
You("don't have anything to put in.");
|
* they're not listed among the available actions.)
|
||||||
goto containerdone;
|
*
|
||||||
}
|
* Do what with <the/your/Shk's container>? [:oibrsq or ?] (q)
|
||||||
menuprompt[0] = '\0';
|
* or
|
||||||
if (!cnt) Sprintf(menuprompt, "%s ", emptymsg);
|
* <The/Your/Shk's container> is empty. Do what with it? [:irsq or ?]
|
||||||
Strcat(menuprompt, "Do what?");
|
*/
|
||||||
t = in_or_out_menu(menuprompt, current_container,
|
for (;;) { /* repeats if '?' or ":' gets chosen */
|
||||||
outokay, inokay);
|
outmaybe = (outokay || !current_container->cknown);
|
||||||
if (t <= 0) {
|
if (!outmaybe)
|
||||||
used = 0;
|
(void)safe_qbuf(qbuf, (char *)0,
|
||||||
goto containerdone;
|
" is empty. Do what with it?",
|
||||||
}
|
current_container,
|
||||||
loot_out = (t & 0x01) != 0;
|
Yname2, Ysimple_name2, "This");
|
||||||
loot_in = (t & 0x02) != 0;
|
else
|
||||||
} else { /* MENU_COMBINATION or MENU_PARTIAL */
|
(void)safe_qbuf(qbuf, "Do what with ", "?",
|
||||||
loot_out = (yn_function(qbuf, "ynq", 'n') == 'y');
|
current_container, yname, ysimple_name, "it");
|
||||||
|
/* ask player about what to do with this container */
|
||||||
|
if (flags.menu_style == MENU_FULL) {
|
||||||
|
if (!inokay && !outmaybe) {
|
||||||
|
/* nothing to take out, nothing to put in;
|
||||||
|
trying to do both will yield proper feedback */
|
||||||
|
c = 'b';
|
||||||
|
} else {
|
||||||
|
c = in_or_out_menu(qbuf, current_container,
|
||||||
|
outmaybe, inokay);
|
||||||
}
|
}
|
||||||
if (loot_out) {
|
} else { /* TRADITIONAL, COMBINATION, or PARTIAL */
|
||||||
add_valid_menu_class(0); /* reset */
|
xbuf[0] = '\0'; /* list of extra acceptable responses */
|
||||||
used |= menu_loot(0, FALSE) > 0;
|
Strcpy(pbuf, ":"); /* look inside */
|
||||||
}
|
Strcat(outmaybe ? pbuf : xbuf, "o"); /* take out */
|
||||||
} else {
|
Strcat(inokay ? pbuf : xbuf, "i"); /* put in */
|
||||||
/* traditional code */
|
Strcat(outmaybe ? pbuf : xbuf, "b"); /* both */
|
||||||
ask_again2:
|
Strcat(inokay ? pbuf : xbuf, "rs"); /* reversed, stash */
|
||||||
menu_on_request = 0;
|
Strcat(pbuf, "q"); /* quit */
|
||||||
add_valid_menu_class(0); /* reset */
|
if (iflags.cmdassist) Strcat(pbuf, " or ?"); /* help */
|
||||||
Strcpy(pbuf, ":ynq");
|
else Strcat(xbuf, "?");
|
||||||
if (cnt) Strcat(pbuf, "m");
|
if (*xbuf) Strcat(strcat(pbuf, "\033"), xbuf);
|
||||||
switch (yn_function(qbuf, pbuf, 'n')) {
|
c = yn_function(qbuf, pbuf, 'q');
|
||||||
case ':':
|
} /* FULL vs other modes */
|
||||||
container_contents(current_container, FALSE, FALSE, TRUE);
|
|
||||||
goto ask_again2;
|
|
||||||
case 'y':
|
|
||||||
if (query_classes(selection, &one_by_one, &allflag,
|
|
||||||
"take out", current_container->cobj,
|
|
||||||
FALSE,
|
|
||||||
#ifndef GOLDOBJ
|
|
||||||
FALSE,
|
|
||||||
#endif
|
|
||||||
&menu_on_request)) {
|
|
||||||
if (askchain((struct obj **)¤t_container->cobj,
|
|
||||||
(one_by_one ? (char *)0 : selection),
|
|
||||||
allflag, out_container,
|
|
||||||
(int FDECL((*),(OBJ_P)))0,
|
|
||||||
0, "nodot"))
|
|
||||||
used = 1;
|
|
||||||
} else if (menu_on_request < 0) {
|
|
||||||
used |= menu_loot(menu_on_request, FALSE) > 0;
|
|
||||||
}
|
|
||||||
/*FALLTHRU*/
|
|
||||||
case 'n':
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
menu_on_request = -2; /* triggers ALL_CLASSES */
|
|
||||||
used |= menu_loot(menu_on_request, FALSE) > 0;
|
|
||||||
break;
|
|
||||||
case 'q':
|
|
||||||
default:
|
|
||||||
goto containerdone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pline("%s", emptymsg); /* <whatever> is empty. */
|
|
||||||
obj->cknown = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef GOLDOBJ
|
if (c == '?') {
|
||||||
if (!invent && u.ugold == 0) {
|
explain_container_prompt();
|
||||||
#else
|
} else if (c == ':') { /* note: will set obj->cknown */
|
||||||
if (!invent) {
|
if (!current_container->cknown) used = 1; /* gaining info */
|
||||||
#endif
|
container_contents(current_container, FALSE, FALSE, TRUE);
|
||||||
/* nothing to put in, but some feedback is necessary */
|
} else
|
||||||
You("don't have anything to put in.");
|
break;
|
||||||
|
} /* loop until something other than '?' or ':' is picked */
|
||||||
|
|
||||||
|
if (c == 'q') /* [not strictly needed; falling through works] */
|
||||||
goto containerdone;
|
goto containerdone;
|
||||||
}
|
loot_out = (c == 'o' || c == 'b' || c == 'r');
|
||||||
if (flags.menu_style != MENU_FULL) {
|
loot_in = (c == 'i' || c == 'b' || c == 'r');
|
||||||
Sprintf(qbuf, "Do you wish to put %s in?", something);
|
loot_in_first = (c == 'r'); /* both, reversed */
|
||||||
Strcpy(pbuf, ynqchars);
|
stash_one = (c == 's');
|
||||||
if (flags.menu_style == MENU_TRADITIONAL && invent && inv_cnt() > 0)
|
|
||||||
Strcat(pbuf, "m");
|
/* out-only or out before in */
|
||||||
switch (yn_function(qbuf, pbuf, 'n')) {
|
if (loot_out && !loot_in_first) {
|
||||||
case 'y':
|
if (!Has_contents(current_container)) {
|
||||||
loot_in = TRUE;
|
pline("%s", emptymsg); /* <whatever> is empty. */
|
||||||
break;
|
if (!current_container->cknown) used = 1;
|
||||||
case 'n':
|
current_container->cknown = 1;
|
||||||
break;
|
} else {
|
||||||
case 'm':
|
add_valid_menu_class(0); /* reset */
|
||||||
add_valid_menu_class(0); /* reset */
|
if (flags.menu_style == MENU_TRADITIONAL)
|
||||||
menu_on_request = -2; /* triggers ALL_CLASSES */
|
used |= traditional_loot(FALSE);
|
||||||
used |= menu_loot(menu_on_request, TRUE) > 0;
|
else
|
||||||
break;
|
used |= (menu_loot(0, FALSE) > 0);
|
||||||
case 'q':
|
|
||||||
default:
|
|
||||||
goto containerdone;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef GOLDOBJ
|
||||||
|
if ((loot_in ||stash_one) && u.ugold) {
|
||||||
|
/*
|
||||||
|
* Hack: gold is not in the inventory, so make a gold object
|
||||||
|
* and put it at the head of the inventory list.
|
||||||
|
*/
|
||||||
|
u_gold = mkgoldobj(u.ugold); /* removes from u.ugold */
|
||||||
|
u_gold->in_use = TRUE;
|
||||||
|
u.ugold = u_gold->quan; /* put the gold back */
|
||||||
|
assigninvlet(u_gold); /* might end up as NOINVSYM */
|
||||||
|
u_gold->nobj = invent;
|
||||||
|
invent = u_gold;
|
||||||
|
u_gold->where = OBJ_INVENT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if ((loot_in || stash_one) &&
|
||||||
|
(!invent || (invent == current_container && !invent->nobj))) {
|
||||||
|
You("don't have anything%s to %s.",
|
||||||
|
invent ? " else" : "", stash_one ? "stash" : "put in");
|
||||||
|
loot_in = stash_one = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gone: being nice about only selecting food if we know we are
|
* Gone: being nice about only selecting food if we know we are
|
||||||
* putting things in an ice chest.
|
* putting things in an ice chest.
|
||||||
*/
|
*/
|
||||||
if (loot_in) {
|
if (loot_in) {
|
||||||
#ifndef GOLDOBJ
|
add_valid_menu_class(0); /* reset */
|
||||||
if (u.ugold) {
|
if (flags.menu_style == MENU_TRADITIONAL)
|
||||||
/*
|
used |= traditional_loot(TRUE);
|
||||||
* Hack: gold is not in the inventory, so make a gold object
|
else
|
||||||
* and put it at the head of the inventory list.
|
used |= (menu_loot(0, TRUE) > 0);
|
||||||
*/
|
} else if (stash_one) {
|
||||||
u_gold = mkgoldobj(u.ugold); /* removes from u.ugold */
|
/* put one item into container */
|
||||||
u_gold->in_use = TRUE;
|
if ((otmp = getobj(stashable, "stash")) != 0) {
|
||||||
u.ugold = u_gold->quan; /* put the gold back */
|
if (in_container(otmp)) {
|
||||||
assigninvlet(u_gold); /* might end up as NOINVSYM */
|
|
||||||
u_gold->nobj = invent;
|
|
||||||
invent = u_gold;
|
|
||||||
u_gold->where = OBJ_INVENT;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
add_valid_menu_class(0); /* reset */
|
|
||||||
if (flags.menu_style != MENU_TRADITIONAL) {
|
|
||||||
used |= menu_loot(0, TRUE) > 0;
|
|
||||||
} else {
|
|
||||||
/* traditional code */
|
|
||||||
menu_on_request = 0;
|
|
||||||
if (query_classes(selection, &one_by_one, &allflag, "put in",
|
|
||||||
invent, FALSE,
|
|
||||||
#ifndef GOLDOBJ
|
|
||||||
(u.ugold != 0L),
|
|
||||||
#endif
|
|
||||||
&menu_on_request)) {
|
|
||||||
(void) askchain((struct obj **)&invent,
|
|
||||||
(one_by_one ? (char *)0 : selection), allflag,
|
|
||||||
in_container, ck_bag, 0, "nodot");
|
|
||||||
used = 1;
|
used = 1;
|
||||||
} else if (menu_on_request < 0) {
|
} else {
|
||||||
used |= menu_loot(menu_on_request, TRUE) > 0;
|
/* couldn't put selected item into container for some
|
||||||
|
reason; might need to undo splitobj() */
|
||||||
|
for (curr = invent; curr; curr = curr->nobj)
|
||||||
|
if (curr->nobj == otmp) break;
|
||||||
|
if (curr && curr->invlet == otmp->invlet)
|
||||||
|
(void)merged(&curr, &otmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* putting something in might have triggered magic bag explosion */
|
||||||
|
if (!current_container) loot_out = FALSE;
|
||||||
|
|
||||||
#ifndef GOLDOBJ
|
#ifndef GOLDOBJ
|
||||||
if (u_gold && invent && invent->oclass == COIN_CLASS) {
|
if (u_gold && invent && invent->oclass == COIN_CLASS) {
|
||||||
@@ -2292,19 +2317,74 @@ ask_again2:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* out after in */
|
||||||
|
if (loot_out && loot_in_first) {
|
||||||
|
if (!Has_contents(current_container)) {
|
||||||
|
pline("%s", emptymsg); /* <whatever> is empty. */
|
||||||
|
if (!current_container->cknown) used = 1;
|
||||||
|
current_container->cknown = 1;
|
||||||
|
} else {
|
||||||
|
add_valid_menu_class(0); /* reset */
|
||||||
|
if (flags.menu_style == MENU_TRADITIONAL)
|
||||||
|
used |= traditional_loot(FALSE);
|
||||||
|
else
|
||||||
|
used |= (menu_loot(0, FALSE) > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
containerdone:
|
containerdone:
|
||||||
/* Not completely correct; if we put something in without knowing
|
/* Not completely correct; if we put something in without knowing
|
||||||
whatever was already inside, now we suddenly do. That can't be
|
whatever was already inside, now we suddenly do. That can't be
|
||||||
helped unless we want to track things item by item and then deal
|
helped unless we want to track things item by item and then deal
|
||||||
with containers whose contents are "partly known". */
|
with containers whose contents are "partly known". */
|
||||||
if (used) obj->cknown = 1;
|
if (used && current_container) current_container->cknown = 1;
|
||||||
|
|
||||||
*objp = current_container; /* might have become null */
|
*objp = current_container; /* might have become null */
|
||||||
current_container = 0; /* avoid hanging on to stale pointer */
|
current_container = 0; /* avoid hanging on to stale pointer */
|
||||||
return used;
|
return used;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loot current_container (take things out, put things in), using a menu. */
|
/* loot current_container (take things out or put things in), by prompting */
|
||||||
|
STATIC_OVL int
|
||||||
|
traditional_loot(put_in)
|
||||||
|
boolean put_in;
|
||||||
|
{
|
||||||
|
int FDECL((*actionfunc), (OBJ_P)),
|
||||||
|
FDECL((*checkfunc), (OBJ_P));
|
||||||
|
struct obj **objlist;
|
||||||
|
char selection[MAXOCLASSES+1];
|
||||||
|
const char *action;
|
||||||
|
boolean one_by_one, allflag;
|
||||||
|
int used = 0, menu_on_request = 0;
|
||||||
|
|
||||||
|
if (put_in) {
|
||||||
|
action = "put in";
|
||||||
|
objlist = &invent;
|
||||||
|
actionfunc = in_container;
|
||||||
|
checkfunc = ck_bag;
|
||||||
|
} else {
|
||||||
|
action = "take out";
|
||||||
|
objlist = &(current_container->cobj);
|
||||||
|
actionfunc = out_container;
|
||||||
|
checkfunc = (int FDECL((*), (OBJ_P)))0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query_classes(selection, &one_by_one, &allflag,
|
||||||
|
action, *objlist, FALSE,
|
||||||
|
#ifndef GOLDOBJ
|
||||||
|
put_in ? (boolean)(u.ugold != 0L) : FALSE,
|
||||||
|
#endif
|
||||||
|
&menu_on_request)) {
|
||||||
|
if (askchain(objlist, (one_by_one ? (char *)0 : selection),
|
||||||
|
allflag, actionfunc, checkfunc, 0, action))
|
||||||
|
used = 1;
|
||||||
|
} else if (menu_on_request < 0) {
|
||||||
|
used = (menu_loot(menu_on_request, put_in) > 0);
|
||||||
|
}
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* loot current_container (take things out or put things in), using a menu */
|
||||||
STATIC_OVL int
|
STATIC_OVL int
|
||||||
menu_loot(retry, put_in)
|
menu_loot(retry, put_in)
|
||||||
int retry;
|
int retry;
|
||||||
@@ -2383,48 +2463,73 @@ boolean put_in;
|
|||||||
return n_looted;
|
return n_looted;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC_OVL int
|
STATIC_OVL char
|
||||||
in_or_out_menu(prompt, obj, outokay, inokay)
|
in_or_out_menu(prompt, obj, outokay, inokay)
|
||||||
const char *prompt;
|
const char *prompt;
|
||||||
struct obj *obj;
|
struct obj *obj;
|
||||||
boolean outokay, inokay;
|
boolean outokay, inokay;
|
||||||
{
|
{
|
||||||
|
/* underscore is not a choice; it's used to skip element [0] */
|
||||||
|
static const char lootchars[] = "_:oibrsq",
|
||||||
|
abc_chars[] = "_:abcdeq";
|
||||||
winid win;
|
winid win;
|
||||||
anything any;
|
anything any;
|
||||||
menu_item *pick_list;
|
menu_item *pick_list;
|
||||||
char buf[BUFSZ];
|
char buf[BUFSZ];
|
||||||
int n;
|
int n;
|
||||||
const char *menuselector = flags.lootabc ? "abc" : "oib";
|
const char *menuselector = flags.lootabc ? abc_chars : lootchars;
|
||||||
|
|
||||||
any = zeroany;
|
any = zeroany;
|
||||||
win = create_nhwindow(NHW_MENU);
|
win = create_nhwindow(NHW_MENU);
|
||||||
start_menu(win);
|
start_menu(win);
|
||||||
|
|
||||||
|
any.a_int = 1; /* ':' */
|
||||||
|
Sprintf(buf, "Look inside %s", thesimpleoname(obj));
|
||||||
|
add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
|
||||||
|
buf, MENU_UNSELECTED);
|
||||||
if (outokay) {
|
if (outokay) {
|
||||||
any.a_int = 1;
|
any.a_int = 2; /* 'o' */
|
||||||
Sprintf(buf,"Take %s out of %s", something, the(xname(obj)));
|
Sprintf(buf, "take %s out", something);
|
||||||
add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE,
|
add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
|
||||||
buf, MENU_UNSELECTED);
|
buf, MENU_UNSELECTED);
|
||||||
}
|
}
|
||||||
menuselector++;
|
|
||||||
if (inokay) {
|
if (inokay) {
|
||||||
any.a_int = 2;
|
any.a_int = 3; /* 'i' */
|
||||||
Sprintf(buf,"Put %s into %s", something, the(xname(obj)));
|
Sprintf(buf, "put %s in", something);
|
||||||
add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE, buf, MENU_UNSELECTED);
|
add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
|
||||||
|
buf, MENU_UNSELECTED);
|
||||||
}
|
}
|
||||||
menuselector++;
|
if (outokay) {
|
||||||
if (outokay && inokay) {
|
any.a_int = 4; /* 'b' */
|
||||||
any.a_int = 3;
|
Sprintf(buf, "%stake out, then put in", inokay ? "both; " : "");
|
||||||
add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE,
|
add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
|
||||||
"Both of the above", MENU_UNSELECTED);
|
buf, MENU_UNSELECTED);
|
||||||
}
|
}
|
||||||
|
if (inokay) {
|
||||||
|
any.a_int = 5; /* 'r' */
|
||||||
|
Sprintf(buf, "%sput in, then take out",
|
||||||
|
outokay ? "both reversed; " : "");
|
||||||
|
add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
|
||||||
|
buf, MENU_UNSELECTED);
|
||||||
|
any.a_int = 6; /* 's' */
|
||||||
|
Sprintf(buf, "stash one item into %s", thesimpleoname(obj));
|
||||||
|
add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
|
||||||
|
buf, MENU_UNSELECTED);
|
||||||
|
}
|
||||||
|
any.a_int = 7; /* 'q' */
|
||||||
|
Strcpy(buf, "do nothing");
|
||||||
|
add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
|
||||||
|
buf, MENU_SELECTED);
|
||||||
|
|
||||||
end_menu(win, prompt);
|
end_menu(win, prompt);
|
||||||
n = select_menu(win, PICK_ONE, &pick_list);
|
n = select_menu(win, PICK_ONE, &pick_list);
|
||||||
destroy_nhwindow(win);
|
destroy_nhwindow(win);
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
n = pick_list[0].item.a_int;
|
n = pick_list[0].item.a_int;
|
||||||
free((genericptr_t) pick_list);
|
free((genericptr_t) pick_list);
|
||||||
|
return lootchars[n]; /* :,o,i,b,r,s,q */
|
||||||
}
|
}
|
||||||
return n;
|
return 'q'; /* quit */
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char tippables[] = { ALL_CLASSES, TOOL_CLASS, 0 };
|
static const char tippables[] = { ALL_CLASSES, TOOL_CLASS, 0 };
|
||||||
|
|||||||
Reference in New Issue
Block a user