From 448b7cc7b6d2496f6088441bf3008a655c066242 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Thu, 4 Jan 2007 06:15:25 +0000 Subject: [PATCH] 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 ? [: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. --- doc/fixes35.0 | 1 + src/invent.c | 38 ++++- src/pickup.c | 465 +++++++++++++++++++++++++++++++------------------- 3 files changed, 318 insertions(+), 186 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 2c43ea1de..aeb5014c9 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -274,6 +274,7 @@ the Amulet can be offered to Moloch javelins and spears now share the same weapon skill all stackable weapons are capable of being thrown/shot for multi-shot volleys worm teeth and crysknives have become stackable +improved container interface Platform- and/or Interface-Specific New Features diff --git a/src/invent.c b/src/invent.c index 14881c370..5d32f5df9 100644 --- a/src/invent.c +++ b/src/invent.c @@ -781,7 +781,9 @@ register const char *let,*word; register int foo = 0; register char *bp = buf; xchar allowcnt = 0; /* 0, 1 or 2 */ + struct obj *firstobj = invent; #ifndef GOLDOBJ + struct obj *u_gold = 0; boolean allowgold = FALSE; /* can't use gold because they don't have any */ #endif boolean usegold = FALSE; /* can't use gold because its illegal */ @@ -797,6 +799,13 @@ register const char *let,*word; #ifndef GOLDOBJ if(*let == COIN_CLASS) let++, 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 if(*let == COIN_CLASS) let++, usegold = TRUE; #endif @@ -835,7 +844,7 @@ register const char *let,*word; 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] || ap == &altlets[sizeof altlets - 1]) { /* we must have a huge number of NOINVSYM items somehow */ @@ -937,6 +946,7 @@ register const char *let,*word; || (!strcmp(word, "sacrifice") && /* (!astral && amulet) || (astral && !amulet) */ (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS))) + || (!strcmp(word, "stash") && !ck_bag(otmp)) ) { /* acceptable but not listed as likely candidate */ foo--; @@ -1032,7 +1042,11 @@ register const char *let,*word; #ifndef GOLDOBJ if(!(allowcnt == 2 && 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 } if(ilet == '?' || ilet == '*') { @@ -1424,14 +1438,17 @@ register int FDECL((*fn),(OBJ_P)), FDECL((*ckfn),(OBJ_P)); struct obj *otmp, *otmp2, *otmpo; register char sym, ilet; register int cnt = 0, dud = 0, tmp; - boolean takeoff, nodot, ident, ininv; - char qbuf[BUFSZ]; + boolean takeoff, nodot, ident, take_out, put_in, first, ininv; + char qbuf[QBUFSZ], qpfx[QBUFSZ]; takeoff = taking_off(word); ident = !strcmp(word, "identify"); + take_out = !strcmp(word, "take out"); + put_in = !strcmp(word, "put in"); nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || - ident || takeoff); + ident || takeoff || take_out || put_in); ininv = (*objchn == invent); + 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 @@ -1450,7 +1467,16 @@ nextclass: if (!allflag) { safeq_xprn_ctx.let = ilet; 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, ininv ? safeq_shortxprname : ansimpleoname, "item"); diff --git a/src/pickup.c b/src/pickup.c index 1991454dd..e24e3c12b 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -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. */ /* 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_DCL long FDECL(mbag_item_gone, (int,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(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 boolean FDECL(able_to_loot, (int,int,BOOLEAN_P)); 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); } +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 ? [: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 use_container(objp, held) struct obj **objp; @@ -2062,21 +2095,21 @@ int held; #ifndef GOLDOBJ struct obj *u_gold = (struct obj *)0; #endif - boolean one_by_one, allflag, quantum_cat = FALSE, - loot_out = FALSE, loot_in = FALSE; - char selection[MAXOCLASSES+1]; - char qbuf[BUFSZ], emptymsg[BUFSZ], pbuf[QBUFSZ]; - long loss = 0L; - int cnt = 0, used = 0, - menu_on_request; + boolean quantum_cat, cursed_mbag, + loot_out, loot_in, loot_in_first, stash_one, + inokay, outokay, outmaybe; + char c, emptymsg[BUFSZ], + qbuf[QBUFSZ], pbuf[QBUFSZ], xbuf[QBUFSZ]; + long loss; + int cnt, used = 0; emptymsg[0] = '\0'; if (nohands(youmonst.data)) { - You("have no hands!"); /* not `body_part(HAND)' */ - return 0; + You("have no hands!"); /* not `body_part(HAND)' */ + return 0; } else if (!freehand()) { - You("have no free %s.", body_part(HAND)); - return 0; + You("have no free %s.", body_part(HAND)); + return 0; } if (obj->olocked) { pline("%s locked.", Tobjnam(obj, "are")); @@ -2099,16 +2132,19 @@ int held; current_container = obj; /* for use by in/out_container */ /* from here on out, all early returns go through containerdone */ - if (obj->spe == 1) { - observe_quantum_cat(obj); + /* check for Schroedinger's Cat */ + quantum_cat = (current_container->spe == 1); /* "it's _now_ empty" */ + if (quantum_cat) { + observe_quantum_cat(current_container); used = 1; - quantum_cat = TRUE; /* for adjusting "it's empty" message */ } - /* Count the number of contained objects. Sometimes toss objects if */ - /* a cursed magic bag. */ - for (curr = obj->cobj; curr; curr = otmp) { + /* count the number of contained objects; + sometimes toss objects if a cursed magic bag */ + cursed_mbag = Is_mbag(current_container) && current_container->cursed; + cnt = 0, loss = 0L; + for (curr = current_container->cobj; curr; curr = otmp) { otmp = curr->nobj; - if (Is_mbag(obj) && obj->cursed && !rn2(13)) { + if (cursed_mbag && !rn2(13)) { obj_extract_self(curr); loss += mbag_item_gone(held, curr); used = 1; @@ -2116,170 +2152,159 @@ int held; cnt++; } } - - if (loss) /* magic bag lost some shop goods */ - You("owe %ld %s for lost merchandise.", loss, currency(loss)); - obj->owt = weight(obj); /* in case any items were lost */ - - if (!cnt) { - Sprintf(emptymsg, "%s is %sempty.", Ysimple_name2(obj), - quantum_cat ? "now " : ""); + if (cursed_mbag) { /* magic bag might have lost some contents */ + if (loss) + You("owe %ld %s for lost merchandise.", loss, currency(loss)); + current_container->owt = weight(current_container); } - - if (cnt || flags.menu_style == MENU_FULL) { - (void)safe_qbuf(qbuf, "Do you want to take something out of ", "?", - obj, yname, ysimple_name, "it"); - if (flags.menu_style != MENU_TRADITIONAL) { - if (flags.menu_style == MENU_FULL) { - int t; - char menuprompt[BUFSZ]; - boolean outokay = (cnt != 0), - inokay = (invent != 0); - + inokay = (invent != 0 && + !(invent == current_container && !current_container->nobj)); #ifndef GOLDOBJ - if (u.ugold) inokay = TRUE; + if (u.ugold) inokay = TRUE; #endif - if (!cnt) obj->cknown = 1; /* will be giving emptymsg */ + outokay = (cnt > 0); + if (!outokay) /* preformat the empty-container message */ + Sprintf(emptymsg, "%s is %sempty.", + Ysimple_name2(current_container), + quantum_cat ? "now " : ""); - if (!outokay && !inokay) { - pline("%s", emptymsg); - You("don't have anything to put in."); - goto containerdone; - } - menuprompt[0] = '\0'; - if (!cnt) Sprintf(menuprompt, "%s ", emptymsg); - Strcat(menuprompt, "Do what?"); - t = in_or_out_menu(menuprompt, current_container, - outokay, inokay); - if (t <= 0) { - used = 0; - goto containerdone; - } - loot_out = (t & 0x01) != 0; - loot_in = (t & 0x02) != 0; - } else { /* MENU_COMBINATION or MENU_PARTIAL */ - loot_out = (yn_function(qbuf, "ynq", 'n') == 'y'); - } - if (loot_out) { - add_valid_menu_class(0); /* reset */ - used |= menu_loot(0, FALSE) > 0; + /* + * What-to-do prompt's list of possible actions: + * always include the look-inside choice (':'); + * include the take-out choice ('o') if container + * has anything in it or if player doesn't yet know + * that it's empty (latter can change on subsequent + * iterations if player picks ':' response); + * include the put-in choices ('i','s') if hero + * carries any inventory (including gold); + * include do-both when 'o' is available, even if + * inventory is empty--taking out could alter that; + * include do-both-reversed when 'i' is available, + * even if container is empty--for similar reason; + * always include the quit choice ('q'). + * include the help choice (" or ?") if `cmdassist' + * run-time option is set; + * (Player can pick any of (o,i,b,r,s,?) even when + * they're not listed among the available actions.) + * + * Do what with ? [:oibrsq or ?] (q) + * or + * is empty. Do what with it? [:irsq or ?] + */ + for (;;) { /* repeats if '?' or ":' gets chosen */ + outmaybe = (outokay || !current_container->cknown); + if (!outmaybe) + (void)safe_qbuf(qbuf, (char *)0, + " is empty. Do what with it?", + current_container, + Yname2, Ysimple_name2, "This"); + else + (void)safe_qbuf(qbuf, "Do what with ", "?", + 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); } + } else { /* TRADITIONAL, COMBINATION, or PARTIAL */ + xbuf[0] = '\0'; /* list of extra acceptable responses */ + Strcpy(pbuf, ":"); /* look inside */ + Strcat(outmaybe ? pbuf : xbuf, "o"); /* take out */ + Strcat(inokay ? pbuf : xbuf, "i"); /* put in */ + Strcat(outmaybe ? pbuf : xbuf, "b"); /* both */ + Strcat(inokay ? pbuf : xbuf, "rs"); /* reversed, stash */ + Strcat(pbuf, "q"); /* quit */ + if (iflags.cmdassist) Strcat(pbuf, " or ?"); /* help */ + else Strcat(xbuf, "?"); + if (*xbuf) Strcat(strcat(pbuf, "\033"), xbuf); + c = yn_function(qbuf, pbuf, 'q'); + } /* FULL vs other modes */ + + if (c == '?') { + explain_container_prompt(); + } else if (c == ':') { /* note: will set obj->cknown */ + if (!current_container->cknown) used = 1; /* gaining info */ + container_contents(current_container, FALSE, FALSE, TRUE); + } else + break; + } /* loop until something other than '?' or ':' is picked */ + + if (c == 'q') /* [not strictly needed; falling through works] */ + goto containerdone; + loot_out = (c == 'o' || c == 'b' || c == 'r'); + loot_in = (c == 'i' || c == 'b' || c == 'r'); + loot_in_first = (c == 'r'); /* both, reversed */ + stash_one = (c == 's'); + + /* out-only or out before in */ + if (loot_out && !loot_in_first) { + if (!Has_contents(current_container)) { + pline("%s", emptymsg); /* is empty. */ + if (!current_container->cknown) used = 1; + current_container->cknown = 1; } else { - /* traditional code */ -ask_again2: - menu_on_request = 0; add_valid_menu_class(0); /* reset */ - Strcpy(pbuf, ":ynq"); - if (cnt) Strcat(pbuf, "m"); - switch (yn_function(qbuf, pbuf, 'n')) { - case ':': - 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; - } + if (flags.menu_style == MENU_TRADITIONAL) + used |= traditional_loot(FALSE); + else + used |= (menu_loot(0, FALSE) > 0); } - } else { - pline("%s", emptymsg); /* is empty. */ - obj->cknown = 1; } #ifndef GOLDOBJ - if (!invent && u.ugold == 0) { -#else - if (!invent) { -#endif - /* nothing to put in, but some feedback is necessary */ - You("don't have anything to put in."); - goto containerdone; + 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; } - if (flags.menu_style != MENU_FULL) { - Sprintf(qbuf, "Do you wish to put %s in?", something); - Strcpy(pbuf, ynqchars); - if (flags.menu_style == MENU_TRADITIONAL && invent && inv_cnt() > 0) - Strcat(pbuf, "m"); - switch (yn_function(qbuf, pbuf, 'n')) { - case 'y': - loot_in = TRUE; - break; - case 'n': - break; - case 'm': - add_valid_menu_class(0); /* reset */ - menu_on_request = -2; /* triggers ALL_CLASSES */ - used |= menu_loot(menu_on_request, TRUE) > 0; - break; - case 'q': - default: - goto containerdone; - } +#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 * putting things in an ice chest. */ if (loot_in) { -#ifndef GOLDOBJ - if (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 - 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"); + add_valid_menu_class(0); /* reset */ + if (flags.menu_style == MENU_TRADITIONAL) + used |= traditional_loot(TRUE); + else + used |= (menu_loot(0, TRUE) > 0); + } else if (stash_one) { + /* put one item into container */ + if ((otmp = getobj(stashable, "stash")) != 0) { + if (in_container(otmp)) { used = 1; - } else if (menu_on_request < 0) { - used |= menu_loot(menu_on_request, TRUE) > 0; + } else { + /* 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 if (u_gold && invent && invent->oclass == COIN_CLASS) { @@ -2292,19 +2317,74 @@ ask_again2: } #endif + /* out after in */ + if (loot_out && loot_in_first) { + if (!Has_contents(current_container)) { + pline("%s", emptymsg); /* 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: /* Not completely correct; if we put something in without knowing 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 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 */ current_container = 0; /* avoid hanging on to stale pointer */ 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 menu_loot(retry, put_in) int retry; @@ -2383,48 +2463,73 @@ boolean put_in; return n_looted; } -STATIC_OVL int +STATIC_OVL char in_or_out_menu(prompt, obj, outokay, inokay) const char *prompt; struct obj *obj; 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; anything any; menu_item *pick_list; char buf[BUFSZ]; int n; - const char *menuselector = flags.lootabc ? "abc" : "oib"; + const char *menuselector = flags.lootabc ? abc_chars : lootchars; any = zeroany; win = create_nhwindow(NHW_MENU); 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) { - any.a_int = 1; - Sprintf(buf,"Take %s out of %s", something, the(xname(obj))); - add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE, - buf, MENU_UNSELECTED); + any.a_int = 2; /* 'o' */ + Sprintf(buf, "take %s out", something); + add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE, + buf, MENU_UNSELECTED); } - menuselector++; if (inokay) { - any.a_int = 2; - Sprintf(buf,"Put %s into %s", something, the(xname(obj))); - add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE, buf, MENU_UNSELECTED); + any.a_int = 3; /* 'i' */ + Sprintf(buf, "put %s in", something); + add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE, + buf, MENU_UNSELECTED); } - menuselector++; - if (outokay && inokay) { - any.a_int = 3; - add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE, - "Both of the above", MENU_UNSELECTED); + if (outokay) { + any.a_int = 4; /* 'b' */ + Sprintf(buf, "%stake out, then put in", inokay ? "both; " : ""); + add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE, + 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); n = select_menu(win, PICK_ONE, &pick_list); destroy_nhwindow(win); if (n > 0) { n = pick_list[0].item.a_int; 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 }; -- 2.40.0