-/* NetHack 3.6 pickup.c $NHDT-Date: 1545785547 2018/12/26 00:52:27 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.222 $ */
+/* NetHack 3.6 pickup.c $NHDT-Date: 1576282488 2019/12/14 00:14:48 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.237 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* 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-2021 */
/* JNetHack may be freely redistributed. See license for details. */
/*
const char *where = 0;
char sym, oc_of_sym, *p;
- ask_again:
+ ask_again:
oclasses[oclassct = 0] = '\0';
*one_at_a_time = *everything = FALSE;
not_everything = filtered = FALSE;
? TRUE : FALSE)
: TRUE; /* catchall: no filters specified, so accept */
- if (Role_if(PM_PRIEST))
- obj->bknown = TRUE;
+ if (Role_if(PM_PRIEST) && !obj->bknown)
+ set_bknown(obj, 1);
/*
* There are three types of filters possible and the first and
if (!can_reach_floor(TRUE)) {
if ((multi && !context.run) || (autopickup && !flags.pickup)
|| ((ttmp = t_at(u.ux, u.uy)) != 0
- && uteetering_at_seen_pit(ttmp)))
+ && (uteetering_at_seen_pit(ttmp) || uescaped_shaft(ttmp))))
read_engr_at(u.ux, u.uy);
return 0;
}
#endif
}
- menu_pickup:
+ menu_pickup:
n_tried = n;
for (n_picked = i = 0; i < n; i++) {
res = pickup_object(pick_list[i].item.a_obj, pick_list[i].count,
break;
n_picked += res;
}
- end_query:
+ end_query:
; /* statement required after label */
}
return (n_tried > 0);
}
-boolean
-is_autopickup_exception(obj, grab)
+struct autopickup_exception *
+check_autopickup_exceptions(obj)
struct obj *obj;
-boolean grab; /* forced pickup, rather than forced leave behind? */
{
/*
* Does the text description of this match an exception?
*/
- struct autopickup_exception
- *ape = (grab) ? iflags.autopickup_exceptions[AP_GRAB]
- : iflags.autopickup_exceptions[AP_LEAVE];
+ struct autopickup_exception *ape = apelist;
if (ape) {
char *objdesc = makesingular(doname(obj));
- while (ape) {
- if (regex_match(objdesc, ape->regex))
- return TRUE;
+ while (ape && !regex_match(objdesc, ape->regex))
ape = ape->next;
- }
}
- return FALSE;
+ return ape;
}
boolean
struct obj *otmp;
boolean calc_costly;
{
+ struct autopickup_exception *ape;
static boolean costly = FALSE;
const char *otypes = flags.pickup_types;
boolean pickit;
/* check for pickup_types */
pickit = (!*otypes || index(otypes, otmp->oclass));
- /* check for "always pick up */
- if (!pickit)
- pickit = is_autopickup_exception(otmp, TRUE);
- /* then for "never pick up */
- if (pickit)
- pickit = !is_autopickup_exception(otmp, FALSE);
+
+ /* check for autopickup exceptions */
+ ape = check_autopickup_exceptions(otmp);
+ if (ape)
+ pickit = ape->grab;
+
/* pickup_thrown overrides pickup_types and exceptions */
if (!pickit)
pickit = (flags.pickup_thrown && otmp->was_thrown);
anything any;
boolean printed_type_name, first,
sorted = (qflags & INVORDER_SORT) != 0,
- engulfer = (qflags & INCLUDE_HERO) != 0;
+ engulfer = (qflags & INCLUDE_HERO) != 0,
+ engulfer_minvent;
unsigned sortflags;
Loot *sortedolist, *srtoli;
last = curr;
n++;
}
+ /* can't depend upon 'engulfer' because that's used to indicate whether
+ hero should be shown as an extra, fake item */
+ engulfer_minvent = (olist && olist->where == OBJ_MINVENT
+ && u.uswallow && olist->ocarry == u.ustuck);
+ if (engulfer_minvent && n == 1 && olist->owornmask != 0L) {
+ qflags &= ~AUTOSELECT_SINGLE;
+ }
if (engulfer) {
++n;
/* don't autoselect swallowed hero if it's the only choice */
&& will_feel_cockatrice(curr, FALSE)) {
destroy_nhwindow(win); /* stop the menu and revert */
(void) look_here(0, FALSE);
+ unsortloot(&sortedolist);
return 0;
}
if ((*allow)(curr)) {
/* fix up counts: -1 means no count used => pick all;
if fake_hero_object was picked, discard that choice */
for (i = k = 0, mi = *pick_list; i < n; i++, mi++) {
- if (mi->item.a_obj == &fake_hero_object)
+ curr = mi->item.a_obj;
+ if (curr == &fake_hero_object) {
+ /* this isn't actually possible; fake item representing
+ hero is only included for look here (':'), not pickup,
+ and that's PICK_NONE so we can't get here from there */
+/*JP
+ You_cant("pick yourself up!");
+*/
+ You_cant("\8e©\95ª\8e©\90g\82Í\8fE\82¦\82È\82¢\81I");
continue;
- if (mi->count == -1L || mi->count > mi->item.a_obj->quan)
- mi->count = mi->item.a_obj->quan;
+ }
+ if (engulfer_minvent && curr->owornmask != 0L) {
+/*JP
+ You_cant("pick %s up.", ysimple_name(curr));
+*/
+ You_cant("%s\82ð\8fE\82¦\82È\82¢\81D", ysimple_name(curr));
+ continue;
+ }
+ if (mi->count == -1L || mi->count > curr->quan)
+ mi->count = curr->quan;
if (k < i)
(*pick_list)[k] = *mi;
++k;
*pick_list = 0;
n = 0;
} else if (k < n) {
- /* other stuff plus fake_hero; last slot is now unused */
- (*pick_list)[k].item = zeroany;
- (*pick_list)[k].count = 0L;
- n = k;
+ /* other stuff plus fake_hero; last slot is now unused
+ (could be more than one if player tried to pick items
+ worn by engulfer) */
+ while (n > k) {
+ --n;
+ (*pick_list)[n].item = zeroany;
+ (*pick_list)[n].count = 0L;
+ }
}
} else if (n < 0) {
/* -1 is used for SIGNAL_NOMENU, so callers don't expect it
if (curr) {
*pick_list = (menu_item *) alloc(sizeof(menu_item));
(*pick_list)->item.a_int = curr->oclass;
- return 1;
+ n = 1;
} else {
debugpline0("query_category: no single object match");
+ n = 0;
}
- return 0;
+ /* early return is ok; there's no temp window yet */
+ return n;
}
win = create_nhwindow(NHW_MENU);
pack++;
if (invlet >= 'u') {
impossible("query_category: too many categories");
- return 0;
+ n = 0;
+ goto query_done;
}
} while (*pack);
}
end_menu(win, qstr);
n = select_menu(win, how, pick_list);
+ query_done:
destroy_nhwindow(win);
if (n < 0)
n = 0; /* caller's don't expect -1 */
for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
if (curr->oclass == *pack) {
if ((qflags & WORN_TYPES)
- && !(curr->owornmask & (W_ARMOR | W_ACCESSORY | W_WEAPON)))
+ && !(curr->owornmask & (W_ARMOR | W_ACCESSORY
+ | W_WEAPONS)))
continue;
if (!counted_category) {
ccount++;
/* [exception for gold coins will have to change
if silver/copper ones ever get implemented] */
&& inv_cnt(FALSE) >= 52 && !merge_choice(invent, obj)) {
-/*JP
- Your("knapsack cannot accommodate any more items.");
-*/
- Your("\83i\83b\83v\83U\83b\83N\82Í\82±\82ê\88È\8fã\83A\83C\83e\83\80\82ð\8bl\82ß\8d\9e\82ß\82È\82¢\81D");
+ /* if there is some gold here (and we haven't already skipped it),
+ we aren't limited by the 52 item limit for it, but caller and
+ "grandcaller" aren't prepared to skip stuff and then pickup
+ just gold, so the best we can do here is vary the message */
+#if 0 /*JP*/
+ Your("knapsack cannot accommodate any more items%s.",
+ /* floor follows by nexthere, otherwise container so by nobj */
+ nxtobj(obj, GOLD_PIECE, (boolean) (obj->where == OBJ_FLOOR))
+ ? " (except gold)" : "");
+#else
+ Your("\83i\83b\83v\83U\83b\83N\82Í%s\82±\82ê\88È\8fã\83A\83C\83e\83\80\82ð\8bl\82ß\8d\9e\82ß\82È\82¢\81D",
+ /* floor follows by nexthere, otherwise container so by nobj */
+ nxtobj(obj, GOLD_PIECE, (boolean) (obj->where == OBJ_FLOOR))
+ ? "(\8bà\89Ý\88È\8aO)" : "");
+#endif
result = -1; /* nothing lifted */
} else {
result = 1;
if (obj == uchain) { /* do not pick up attached chain */
return 0;
+ } else if (obj->where == OBJ_MINVENT && obj->owornmask != 0L
+ && u.uswallow && obj->ocarry == u.ustuck) {
+/*JP
+ You_cant("pick %s up.", ysimple_name(obj));
+*/
+ You_cant("%s\82ð\8fE\82¦\82È\82¢\81D", ysimple_name(obj));
+ return 0;
} else if (obj->oartifact && !touch_artifact(obj, &youmonst)) {
return 0;
} else if (obj->otyp == CORPSE) {
return FALSE;
}
-int
+STATIC_OVL int
do_loot_cont(cobjp, cindex, ccount)
struct obj **cobjp;
int cindex, ccount; /* index of this container (1..N), number of them (N) */
cobj->lknown = 1;
return 0;
}
- cobj->lknown = 1;
+ cobj->lknown = 1; /* floor container, so no need for update_inventory() */
if (cobj->otyp == BAG_OF_TRICKS) {
int tmp;
*/
pline("\83I\81[\83P\81[\81C\82±\82±\82É\98d\98G\82ð\92u\82¢\82Ä\82¨\82±\82¤\81D");
} else {
- /* find original coffers chest if present, otherwise use nearest one
- */
+ /* find original coffers chest if present, otherwise use nearest one */
otmp = 0;
for (coffers = fobj; coffers; coffers = coffers->nobj)
if (coffers->otyp == CHEST) {
#endif
return 0;
} else if ((obj->otyp == LOADSTONE) && obj->cursed) {
- obj->bknown = 1;
+ set_bknown(obj, 1);
/*JP
pline_The("stone%s won't leave your person.", plur(obj->quan));
*/
if (!u_handsy())
return 0;
+ if (!obj->lknown) { /* do this in advance */
+ obj->lknown = 1;
+ if (held)
+ update_inventory();
+ }
if (obj->olocked) {
/*JP
pline("%s locked.", Tobjnam(obj, "are"));
You("must put it down to unlock.");
*/
if (held) pline("\89º\82É\92u\82©\82È\82¢\82±\82Æ\82É\82Í\8c®\82ð\82Í\82¸\82¹\82È\82¢\81D");
- obj->lknown = 1;
return 0;
} else if (obj->otrapped) {
if (held)
You("open %s...", the(xname(obj)));
*/
You("%s\82ð\8aJ\82¯\82½\81D\81D\81D", the(xname(obj)));
- obj->lknown = 1;
(void) chest_trap(obj, HAND, FALSE);
/* even if the trap fails, you've used up this turn */
if (multi >= 0) { /* in case we didn't become paralyzed */
abort_looting = TRUE;
return 1;
}
- obj->lknown = 1;
current_container = obj; /* for use by in/out_container */
/*
* or
* <The/Your/Shk's container> is empty. Do what with it? [:irs nq or ?]
*/
- for (;;) { /* repeats iff '?' or ":' gets chosen */
+ for (;;) { /* repeats iff '?' or ':' gets chosen */
outmaybe = (outokay || !current_container->cknown);
if (!outmaybe)
#if 0 /*JP:T*/
if (iflags.cmdassist)
/* this unintentionally allows user to answer with 'o' or
'r'; fortunately, those are already valid choices here */
+#if 0 /*JP:T*/
Strcat(pbuf, " or ?"); /* help */
+#else
+ Strcat(pbuf, "\82Ü\82½\82Í?"); /* help */
+#endif
else
Strcat(xbuf, "?");
if (*xbuf)
}
}
-containerdone:
+ containerdone:
if (used) {
/* Not completely correct; if we put something in without knowing
whatever was already inside, now we suddenly do. That can't
/* caveat: this assumes that cknown, lknown, olocked, and otrapped
fields haven't been overloaded to mean something special for the
non-standard "container" horn of plenty */
- box->lknown = 1;
+ if (!box->lknown) {
+ box->lknown = 1;
+ if (carried(box))
+ update_inventory(); /* jumping the gun slightly; hope that's ok */
+ }
if (box->olocked) {
/*JP
pline("It's locked.");
if (held)
(void) encumber_msg();
}
+ if (carried(box)) /* box is now empty with cknown set */
+ update_inventory();
}
/*pickup.c*/