Merge remote-tracking branch 'origin/NetHack-3.6.0'

This commit is contained in:
keni
2017-06-28 17:45:49 -04:00
19 changed files with 626 additions and 316 deletions

129
src/cmd.c
View File

@@ -621,13 +621,29 @@ wiz_identify(VOID_ARGS)
STATIC_PTR int
wiz_makemap(VOID_ARGS)
{
/* FIXME: doesn't handle riding */
if (wizard) {
struct monst *mtmp;
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
if (mtmp->isshk)
setpaid(mtmp);
if (Punished) {
ballrelease(FALSE);
unplacebc();
}
check_special_room(TRUE);
dmonsfree();
savelev(-1, ledger_no(&u.uz), FREE_SAVE);
mklev();
reglyph_darkroom();
vision_reset();
vision_full_recalc = 1;
cls();
(void) safe_teleds(TRUE);
if (Punished) {
unplacebc();
placebc();
}
docrt();
flush_screen(1);
}
@@ -1141,41 +1157,94 @@ STATIC_PTR int
wiz_intrinsic(VOID_ARGS)
{
if (wizard) {
extern const char *const propertynames[]; /* timeout.c */
static const char wizintrinsic[] = "#wizintrinsic";
static const char fmt[] = "You are%s %s.";
winid win;
anything any;
int i, n, accelerator;
char buf[BUFSZ];
int i, n, p, amt, typ;
long oldtimeout, newtimeout;
const char *propname;
menu_item *pick_list = (menu_item *) 0;
static const char *const intrinsics[] = {
"deafness",
};
win = create_nhwindow(NHW_MENU);
start_menu(win);
accelerator = 0;
for (i = 0; i < SIZE(intrinsics); ++i) {
accelerator = intrinsics[i][0];
any.a_int = i + 1;
add_menu(win, NO_GLYPH, &any, accelerator, 0,
ATR_NONE, intrinsics[i], FALSE);
for (i = 1; (propname = propertynames[i]) != 0; ++i) {
if (i == HALLUC_RES) {
/* Grayswandir vs hallucination; ought to be redone to
use u.uprops[HALLUC].blocked instead of being treated
as a separate property; letting in be manually toggled
even only in wizard mode would be asking for trouble... */
continue;
}
any.a_int = i;
add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, propname, FALSE);
}
end_menu(win, "Which intrinsic?");
n = select_menu(win, PICK_ONE, &pick_list);
end_menu(win, "Which intrinsics?");
n = select_menu(win, PICK_ANY, &pick_list);
destroy_nhwindow(win);
if (n >= 1) {
i = pick_list[0].item.a_int-1;
free((genericptr_t) pick_list);
} else {
return 0;
}
amt = 30; /* TODO: prompt for duration */
for (i = 0; i < n; ++i) {
p = pick_list[i].item.a_int;
oldtimeout = u.uprops[p].intrinsic & TIMEOUT;
newtimeout = oldtimeout + (long) amt;
switch (p) {
case SICK:
case SLIMED:
case STONED:
if (oldtimeout > 0L && newtimeout > oldtimeout)
newtimeout = oldtimeout;
break;
}
if (!strcmp(intrinsics[i], "deafness")) {
You("go deaf.");
incr_itimeout(&HDeaf, 30);
context.botl = TRUE;
switch (p) {
case BLINDED:
make_blinded(newtimeout, TRUE);
break;
case CONFUSION:
make_confused(newtimeout, TRUE);
break;
case DEAF:
make_deaf(newtimeout, TRUE);
break;
case HALLUC:
make_hallucinated(newtimeout, TRUE, 0L);
break;
case SICK:
typ = !rn2(2) ? SICK_VOMITABLE : SICK_NONVOMITABLE;
make_sick(newtimeout, wizintrinsic, TRUE, typ);
break;
case SLIMED:
Sprintf(buf, fmt,
!Slimed ? "" : " still", "turning into slime");
make_slimed(newtimeout, buf);
break;
case STONED:
Sprintf(buf, fmt,
!Stoned ? "" : " still", "turning into stone");
make_stoned(newtimeout, buf, KILLED_BY, wizintrinsic);
break;
case STUNNED:
make_stunned(newtimeout, TRUE);
break;
case VOMITING:
Sprintf(buf, fmt, !Vomiting ? "" : " still", "vomiting");
make_vomiting(newtimeout, FALSE);
pline1(buf);
break;
default:
pline("Timeout for %s %s %d.", propertynames[p],
oldtimeout ? "increased by" : "set to", amt);
incr_itimeout(&u.uprops[p].intrinsic, amt);
break;
}
context.botl = 1; /* probably not necessary... */
}
if (n >= 1)
free((genericptr_t) pick_list);
} else
pline("Unavailable command '%s'.",
visctrl((int) cmd_from_func(wiz_intrinsic)));
@@ -2814,7 +2883,7 @@ struct ext_func_tab extcmdlist[] = {
{ '\\', "known", "show what object types have been discovered",
dodiscovered, IFBURIED | GENERALCMD },
{ '`', "knownclass", "show discovered types for one class of objects",
doclassdisco, IFBURIED|GENERALCMD },
doclassdisco, IFBURIED | GENERALCMD },
{ '\0', "levelchange", "change experience level",
wiz_level_change, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '\0', "lightsources", "show mobile light sources",
@@ -2835,11 +2904,11 @@ struct ext_func_tab extcmdlist[] = {
dosacrifice, AUTOCOMPLETE },
{ 'o', "open", "open a door", doopen },
{ 'O', "options", "show option settings, possibly change them",
doset, IFBURIED|GENERALCMD },
doset, IFBURIED | GENERALCMD },
{ C('o'), "overview", "show a summary of the explored dungeon",
dooverview, IFBURIED|AUTOCOMPLETE },
dooverview, IFBURIED | AUTOCOMPLETE },
{ '\0', "panic", "test panic routine (fatal to game)",
wiz_panic, IFBURIED|AUTOCOMPLETE|WIZMODECMD },
wiz_panic, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ 'p', "pay", "pay your shopping bill", dopay },
{ ',', "pickup", "pick up things at the current location", dopickup },
{ '\0', "polyself", "polymorph self",
@@ -2851,7 +2920,7 @@ struct ext_func_tab extcmdlist[] = {
{ M('p'), "pray", "pray to the gods for help",
dopray, IFBURIED | AUTOCOMPLETE },
{ C('p'), "prevmsg", "view recent game messages",
doprev_message, IFBURIED|GENERALCMD },
doprev_message, IFBURIED | GENERALCMD },
{ 'P', "puton", "put on an accessory (ring, amulet, etc)", doputon },
{ 'q', "quaff", "quaff (drink) something", dodrink },
{ M('q'), "quit", "exit without saving current game",
@@ -2900,7 +2969,7 @@ struct ext_func_tab extcmdlist[] = {
{ '\0', "terrain", "show map without obstructions",
doterrain, IFBURIED | AUTOCOMPLETE },
{ 't', "throw", "throw something", dothrow },
{ '\0', "timeout", "look at timeout queue",
{ '\0', "timeout", "look at timeout queue and hero's timed intrinsics",
wiz_timeout_queue, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ M('T'), "tip", "empty a container", dotip, AUTOCOMPLETE },
{ '_', "travel", "travel to a specific location on the map", dotravel },

View File

@@ -2541,8 +2541,9 @@ int retry;
} else if (flags.menu_style == MENU_FULL) {
all_worn_categories = FALSE;
n = query_category("What type of things do you want to take off?",
invent, WORN_TYPES | ALL_TYPES, &pick_list,
PICK_ANY);
invent, (WORN_TYPES | ALL_TYPES
| UNPAID_TYPES | BUCX_TYPES),
&pick_list, PICK_ANY);
if (!n)
return 0;
for (i = 0; i < n; i++) {
@@ -2553,10 +2554,17 @@ int retry;
}
free((genericptr_t) pick_list);
} else if (flags.menu_style == MENU_COMBINATION) {
all_worn_categories = FALSE;
if (ggetobj("take off", select_off, 0, TRUE, (unsigned *) 0) == -2)
all_worn_categories = TRUE;
unsigned ggofeedback = 0;
i = ggetobj("take off", select_off, 0, TRUE, &ggofeedback);
if (ggofeedback & ALL_FINISHED)
return 0;
all_worn_categories = (i == -2);
}
if (menu_class_present('u')
|| menu_class_present('B') || menu_class_present('U')
|| menu_class_present('C') || menu_class_present('X'))
all_worn_categories = FALSE;
n = query_objlist("What do you want to take off?", &invent,
(SIGNAL_NOMENU | USE_INVLET | INVORDER_SORT),

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 invent.c $NHDT-Date: 1472809075 2016/09/02 09:37:55 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.210 $ */
/* NetHack 3.6 invent.c $NHDT-Date: 1498078873 2017/06/21 21:01:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.214 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -25,8 +25,6 @@ STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
STATIC_DCL char FDECL(display_pickinv, (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 **));
@@ -1560,7 +1558,7 @@ unsigned *resultflags;
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];
@@ -1587,22 +1585,19 @@ unsigned *resultflags;
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)
@@ -1680,21 +1675,12 @@ unsigned *resultflags;
} 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;
@@ -1751,7 +1737,7 @@ 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;
boolean takeoff, nodot, ident, take_out, put_in, first, ininv, bycat;
char qbuf[QBUFSZ], qpfx[QBUFSZ];
takeoff = taking_off(word);
@@ -1761,6 +1747,8 @@ int FDECL((*fn), (OBJ_P)), FDECL((*ckfn), (OBJ_P));
nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident
|| takeoff || take_out || put_in);
ininv = (*objchn == invent);
bycat = (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... */
@@ -1792,6 +1780,8 @@ nextclass:
while ((otmp = nxt_unbypassed_obj(*objchn)) != 0) {
if (ilet == 'z')
ilet = 'A';
else if (ilet == 'Z')
ilet = NOINVSYM; /* '#' */
else
ilet++;
if (olets && *olets && otmp->oclass != *olets)
@@ -1802,6 +1792,8 @@ nextclass:
continue;
if (ckfn && !(*ckfn)(otmp))
continue;
if (bycat && !ckvalidcat(otmp))
continue;
if (!allflag) {
safeq_xprn_ctx.let = ilet;
safeq_xprn_ctx.dot = !nodot;
@@ -2405,20 +2397,27 @@ struct obj *list;
* 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)
@@ -2432,21 +2431,32 @@ int type;
/* 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) {
if (list->oclass == COIN_CLASS) {
++(*ocp); /* "other" */
continue;
}
for ( ; list; list = (by_nexthere ? list->nexthere : list->nobj)) {
/* priests always know bless/curse state */
if (Role_if(PM_PRIEST))
list->bknown = 1;
list->bknown = (list->oclass != COIN_CLASS);
/* coins are either uncursed or unknown based upon option setting */
if (list->oclass == COIN_CLASS) {
if (iflags.goldX)
++(*xcp);
else
++(*ucp);
continue;
}
/* ordinary items */
if (!list->bknown)
++(*xcp);
else if (list->blessed)
@@ -2583,7 +2593,12 @@ struct obj *obj;
{
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);
@@ -2623,7 +2638,7 @@ dotypeinv()
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
@@ -2651,9 +2666,9 @@ dotypeinv()
/* 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)
@@ -2733,28 +2748,32 @@ dotypeinv()
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";
before = "known to be blessed ";
break;
case 'U':
which = "known to be uncursed";
before = "known to be uncursed ";
break;
case 'C':
which = "known to be cursed";
before = "known to be cursed ";
break;
case 'X':
You(
"have no objects whose blessed/uncursed/cursed status is unknown.");
after = " whose blessed/uncursed/cursed status is unknown";
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... */
before = "such ";
break;
}
if (which)
You("have no %s objects.", which);
You("have no %sobjects%s.", before, after);
return 0;
}
this_type = oclass;
@@ -3368,13 +3387,11 @@ STATIC_VAR NEARDATA const char *names[] = {
"Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
"Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
};
STATIC_VAR NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
STATIC_VAR NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
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)

View File

@@ -93,6 +93,8 @@ mon_sanity_check()
else if (level.monsters[x][y] != mtmp)
impossible("mon (%s) at <%d,%d> is not there!",
fmt_ptr((genericptr_t) mtmp), x, y);
else if (mtmp->wormno)
sanity_check_worm(mtmp);
}
for (x = 0; x < COLNO; x++)

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 options.c $NHDT-Date: 1470357737 2016/08/05 00:42:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.279 $ */
/* NetHack 3.6 options.c $NHDT-Date: 1498078876 2017/06/21 21:01:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.288 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -126,6 +126,7 @@ static struct Bool_Opt {
{ "flush", (boolean *) 0, FALSE, SET_IN_FILE },
#endif
{ "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE },
{ "goldX", &iflags.goldX, FALSE, SET_IN_GAME },
{ "help", &flags.help, TRUE, SET_IN_GAME },
{ "hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME }, /*WC*/
{ "hilite_pile", &iflags.hilite_pile, FALSE, SET_IN_GAME },
@@ -265,7 +266,7 @@ static struct Comp_Opt {
{ "altkeyhandler", "alternate key handler", 20, DISP_IN_GAME },
#ifdef BACKWARD_COMPAT
{ "boulder", "deprecated (use S_boulder in sym file instead)", 1,
SET_IN_FILE },
SET_IN_GAME },
#endif
{ "catname", "the name of your (first) cat (e.g., catname:Tabby)",
PL_PSIZ, DISP_IN_GAME },
@@ -2441,8 +2442,12 @@ boolean tinitial, tfrom_file;
*/
iflags.bouldersym = (uchar) opts[0];
}
if (!initial)
/* for 'initial', update_bouldersym() is done in initoptions_finish(),
after all symset options have been processed */
if (!initial) {
update_bouldersym();
need_redraw = TRUE;
}
return;
}
#endif
@@ -2585,7 +2590,7 @@ boolean tinitial, tfrom_file;
op = pp + 1;
else
break; /* no next token */
} /* for(;;) */
} /* for(;;) */
}
return;
}
@@ -3497,7 +3502,8 @@ char* bindings;
}
/* parse a single binding: first split around : */
if (! (bind = index(bindings, ':'))) return; /* it's not a binding */
if (! (bind = index(bindings, ':')))
return; /* it's not a binding */
*bind++ = 0;
/* read the key to be bound */
@@ -4691,7 +4697,8 @@ boolean setinitial, setfromfile;
}
sl = sl->next;
}
Sprintf(buf, "Select %ssymbol set:", rogueflag ? "rogue level " : "");
Sprintf(buf, "Select %ssymbol set:",
rogueflag ? "rogue level " : "");
end_menu(tmpwin, buf);
if (select_menu(tmpwin, PICK_ONE, &symset_pick) > 0) {
chosen = symset_pick->item.a_int - 2;
@@ -5335,7 +5342,8 @@ register char *opts;
if ((op = index(opts, ',')) != 0) {
*op++ = 0;
if (!parsesymbols(op)) return FALSE;
if (!parsesymbols(op))
return FALSE;
}
/* S_sample:string */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pickup.c $NHDT-Date: 1470449858 2016/08/06 02:17:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.184 $ */
/* NetHack 3.6 pickup.c $NHDT-Date: 1498078877 2017/06/21 21:01:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.185 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -149,45 +149,54 @@ struct obj *objs;
boolean here;
int *menu_on_demand;
{
char ilets[30], inbuf[BUFSZ]; /* FIXME: hardcoded ilets[] length */
char ilets[36], inbuf[BUFSZ]; /* FIXME: hardcoded ilets[] length */
int iletct, oclassct;
boolean not_everything;
boolean not_everything, filtered;
char qbuf[QBUFSZ];
boolean m_seen;
int itemcount;
int itemcount, bcnt, ucnt, ccnt, xcnt, ocnt;
oclasses[oclassct = 0] = '\0';
*one_at_a_time = *everything = m_seen = FALSE;
if (menu_on_demand)
*menu_on_demand = 0;
iletct = collect_obj_classes(ilets, objs, here,
(boolean FDECL((*), (OBJ_P))) 0, &itemcount);
if (iletct == 0) {
if (iletct == 0)
return FALSE;
} else if (iletct == 1) {
if (iletct == 1) {
oclasses[0] = def_char_to_objclass(ilets[0]);
oclasses[1] = '\0';
if (itemcount && menu_on_demand) {
ilets[iletct++] = 'm';
*menu_on_demand = 0;
ilets[iletct] = '\0';
}
} else { /* more than one choice available */
const char *where = 0;
char sym, oc_of_sym, *p;
/* additional choices */
ilets[iletct++] = ' ';
ilets[iletct++] = 'a';
ilets[iletct++] = 'A';
ilets[iletct++] = (objs == invent ? 'i' : ':');
if (menu_on_demand) {
ilets[iletct++] = 'm';
*menu_on_demand = 0;
}
ilets[iletct] = '\0';
}
if (itemcount && menu_on_demand)
ilets[iletct++] = 'm';
tally_BUCX(objs, here, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt);
if (bcnt)
ilets[iletct++] = 'B';
if (ucnt)
ilets[iletct++] = 'U';
if (ccnt)
ilets[iletct++] = 'C';
if (xcnt)
ilets[iletct++] = 'X';
ilets[iletct] = '\0';
if (iletct > 1) {
const char *where = 0;
char sym, oc_of_sym, *p;
ask_again:
oclasses[oclassct = 0] = '\0';
*one_at_a_time = *everything = FALSE;
not_everything = FALSE;
not_everything = filtered = FALSE;
Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]", action,
ilets);
getlin(qbuf, inbuf);
@@ -213,6 +222,9 @@ int *menu_on_demand;
goto ask_again;
} else if (sym == 'm') {
m_seen = TRUE;
} else if (index("BUCX", sym)) {
add_valid_menu_class(sym); /* 'B','U','C',or 'X' */
filtered = TRUE;
} else {
oc_of_sym = def_char_to_objclass(sym);
if (index(ilets, sym)) {
@@ -230,9 +242,11 @@ int *menu_on_demand;
not_everything = TRUE;
}
}
}
} /* for p:sym in inbuf */
if (m_seen && menu_on_demand) {
*menu_on_demand = (*everything || !oclassct) ? -2 : -3;
*menu_on_demand = (((*everything || !oclassct) && !filtered)
? -2 : -3);
return FALSE;
}
if (!oclassct && (!*everything || not_everything)) {
@@ -325,6 +339,14 @@ struct obj *obj;
static char valid_menu_classes[MAXOCLASSES + 1 + 4 + 1];
static boolean class_filter, bucx_filter, shop_filter;
/* check valid_menu_classes[] for an entry; also used by askchain() */
boolean
menu_class_present(c)
int c;
{
return (c && index(valid_menu_classes, c)) ? TRUE : FALSE;
}
void
add_valid_menu_class(c)
int c;
@@ -334,7 +356,7 @@ int c;
if (c == 0) { /* reset */
vmc_count = 0;
class_filter = bucx_filter = shop_filter = FALSE;
} else {
} else if (!menu_class_present(c)) {
valid_menu_classes[vmc_count++] = (char) c;
/* categorize the new class */
switch (c) {
@@ -376,9 +398,21 @@ boolean
allow_category(obj)
struct obj *obj;
{
/* unpaid and BUC checks don't apply to coins */
/* For coins, if any class filter is specified, accept if coins
* are included regardless of whether either unpaid or BUC-status
* is also specified since player has explicitly requested coins.
* If no class filtering is specified but bless/curse state is,
* coins are either unknown or uncursed based on an option setting.
*/
if (obj->oclass == COIN_CLASS)
return index(valid_menu_classes, COIN_CLASS) ? TRUE : FALSE;
return class_filter
? (index(valid_menu_classes, COIN_CLASS) ? TRUE : FALSE)
: shop_filter /* coins are never unpaid, but check anyway */
? (obj->unpaid ? TRUE : FALSE)
: bucx_filter
? (index(valid_menu_classes, iflags.goldX ? 'X' : 'U')
? TRUE : FALSE)
: TRUE; /* catchall: no filters specified, so accept */
if (Role_if(PM_PRIEST))
obj->bknown = TRUE;
@@ -429,7 +463,7 @@ allow_cat_no_uchain(obj)
struct obj *obj;
{
if (obj != uchain
&& ((index(valid_menu_classes,'u') && obj->unpaid)
&& ((index(valid_menu_classes, 'u') && obj->unpaid)
|| index(valid_menu_classes, obj->oclass)))
return TRUE;
return FALSE;
@@ -441,8 +475,7 @@ boolean
is_worn_by_type(otmp)
register struct obj *otmp;
{
return (boolean) (!!(otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_WEAPON))
&& index(valid_menu_classes, otmp->oclass) != 0);
return (is_worn(otmp) && allow_category(otmp)) ? TRUE : FALSE;
}
/*
@@ -574,8 +607,8 @@ int what; /* should be a long */
/* old style interface */
int ct = 0;
long lcount;
boolean all_of_a_type, selective;
char oclasses[MAXOCLASSES];
boolean all_of_a_type, selective, bycat;
char oclasses[MAXOCLASSES + 10]; /* +10: room for B,U,C,X plus slop */
struct obj *obj, *obj2;
oclasses[0] = '\0'; /* types to consider (empty for all) */
@@ -604,7 +637,7 @@ int what; /* should be a long */
(traverse_how & BY_NEXTHERE) ? TRUE : FALSE,
&via_menu)) {
if (!via_menu)
return 0;
goto pickupdone;
if (selective)
traverse_how |= INVORDER_SORT;
n = query_objlist("Pick up what?", objchain_p, traverse_how,
@@ -614,10 +647,14 @@ int what; /* should be a long */
goto menu_pickup;
}
}
bycat = (menu_class_present('B') || menu_class_present('U')
|| menu_class_present('C') || menu_class_present('X'));
for (obj = *objchain_p; obj; obj = obj2) {
obj2 = FOLLOW(obj, traverse_how);
if (!selective && oclasses[0] && !index(oclasses, obj->oclass))
if (bycat ? !allow_category(obj)
: (!selective && oclasses[0]
&& !index(oclasses, obj->oclass)))
continue;
lcount = -1L;
@@ -674,6 +711,8 @@ int what; /* should be a long */
if (autopickup)
check_here(n_picked > 0);
}
pickupdone:
add_valid_menu_class(0); /* reset */
return (n_tried > 0);
}
@@ -969,6 +1008,7 @@ int how; /* type of query */
boolean collected_type_name;
char invlet;
int ccount;
boolean FDECL((*ofilter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
boolean do_unpaid = FALSE;
boolean do_blessed = FALSE, do_cursed = FALSE, do_uncursed = FALSE,
do_buc_unknown = FALSE;
@@ -979,19 +1019,21 @@ int how; /* type of query */
return 0;
if ((qflags & UNPAID_TYPES) && count_unpaid(olist))
do_unpaid = TRUE;
if ((qflags & BUC_BLESSED) && count_buc(olist, BUC_BLESSED)) {
if (qflags & WORN_TYPES)
ofilter = is_worn;
if ((qflags & BUC_BLESSED) && count_buc(olist, BUC_BLESSED, ofilter)) {
do_blessed = TRUE;
num_buc_types++;
}
if ((qflags & BUC_CURSED) && count_buc(olist, BUC_CURSED)) {
if ((qflags & BUC_CURSED) && count_buc(olist, BUC_CURSED, ofilter)) {
do_cursed = TRUE;
num_buc_types++;
}
if ((qflags & BUC_UNCURSED) && count_buc(olist, BUC_UNCURSED)) {
if ((qflags & BUC_UNCURSED) && count_buc(olist, BUC_UNCURSED, ofilter)) {
do_uncursed = TRUE;
num_buc_types++;
}
if ((qflags & BUC_UNKNOWN) && count_buc(olist, BUC_UNKNOWN)) {
if ((qflags & BUC_UNKNOWN) && count_buc(olist, BUC_UNKNOWN, ofilter)) {
do_buc_unknown = TRUE;
num_buc_types++;
}
@@ -1001,8 +1043,7 @@ int how; /* type of query */
if (ccount == 1 && !do_unpaid && num_buc_types <= 1
&& !(qflags & BILLED_TYPES)) {
for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
if ((qflags & WORN_TYPES)
&& !(curr->owornmask & (W_ARMOR | W_ACCESSORY | W_WEAPON)))
if (ofilter && !(*ofilter)(curr))
continue;
break;
}
@@ -1033,8 +1074,7 @@ int how; /* type of query */
collected_type_name = FALSE;
for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
if (curr->oclass == *pack) {
if ((qflags & WORN_TYPES)
&& !(curr->owornmask & (W_ARMOR | W_ACCESSORY | W_WEAPON)))
if (ofilter && !(*ofilter)(curr))
continue;
if (!collected_type_name) {
any = zeroany;
@@ -1081,7 +1121,9 @@ int how; /* type of query */
: "Auto-select every item",
MENU_UNSELECTED);
}
/* items with b/u/c/unknown if there are any */
/* items with b/u/c/unknown if there are any;
this cluster of menu entries is in alphabetical order,
reversing the usual sequence of 'U' and 'C' in BUCX */
if (do_blessed) {
invlet = 'B';
any = zeroany;
@@ -1108,7 +1150,7 @@ int how; /* type of query */
any = zeroany;
any.a_int = 'X';
add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
"Items of unknown B/C/U status", MENU_UNSELECTED);
"Items of unknown Bless/Curse status", MENU_UNSELECTED);
}
end_menu(win, qstr);
n = select_menu(win, how, pick_list);
@@ -2116,6 +2158,11 @@ register struct obj *obj;
return (current_container ? 1 : -1);
}
/* askchain() filter used by in_container();
* returns True if the container is intact and 'obj' isn't it, False if
* container is gone (magic bag explosion) or 'obj' is the container itself;
* also used by getobj() when picking a single item to stash
*/
int
ck_bag(obj)
struct obj *obj;
@@ -2490,6 +2537,7 @@ boolean more_containers; /* True iff #loot multiple and this isn't last one */
used |= traditional_loot(FALSE);
else
used |= (menu_loot(0, FALSE) > 0);
add_valid_menu_class(0);
}
}
@@ -2510,6 +2558,7 @@ boolean more_containers; /* True iff #loot multiple and this isn't last one */
used |= traditional_loot(TRUE);
else
used |= (menu_loot(0, TRUE) > 0);
add_valid_menu_class(0);
} else if (stash_one) {
/* put one item into container */
if ((otmp = getobj(stashable, "stash")) != 0) {
@@ -2539,6 +2588,7 @@ boolean more_containers; /* True iff #loot multiple and this isn't last one */
used |= traditional_loot(FALSE);
else
used |= (menu_loot(0, FALSE) > 0);
add_valid_menu_class(0);
}
}
@@ -2568,7 +2618,7 @@ boolean put_in;
{
int FDECL((*actionfunc), (OBJ_P)), FDECL((*checkfunc), (OBJ_P));
struct obj **objlist;
char selection[MAXOCLASSES + 1];
char selection[MAXOCLASSES + 10]; /* +10: room for B,U,C,X plus slop */
const char *action;
boolean one_by_one, allflag;
int used = 0, menu_on_request = 0;
@@ -2616,7 +2666,7 @@ boolean put_in;
} else if (flags.menu_style == MENU_FULL) {
all_categories = FALSE;
Sprintf(buf, "%s what type of objects?", action);
mflags = (ALL_TYPES | BUC_ALLBKNOWN | BUC_UNKNOWN);
mflags = (ALL_TYPES | BUCX_TYPES);
if (put_in)
mflags |= CHOOSE_ALL;
n = query_category(buf, put_in ? invent : current_container->cobj,

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 polyself.c $NHDT-Date: 1457572516 2016/03/10 01:15:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.108 $ */
/* NetHack 3.6 polyself.c $NHDT-Date: 1497485548 2017/06/15 00:12:28 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.112 $ */
/* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
@@ -366,9 +366,11 @@ newman()
newuhs(FALSE);
polyman("feel like a new %s!",
/* use saved gender we're about to revert to, not current */
(u.mfemale && urace.individual.f)
((Upolyd ? u.mfemale : flags.female) && urace.individual.f)
? urace.individual.f
: (urace.individual.m) ? urace.individual.m : urace.noun);
: (urace.individual.m)
? urace.individual.m
: urace.noun);
if (Slimed) {
Your("body transforms, but there is still slime on you.");
make_slimed(10L, (const char *) 0);

View File

@@ -29,7 +29,6 @@ STATIC_VAR const char and_its_contents[] = " and its contents";
STATIC_VAR const char the_contents_of[] = "the contents of ";
STATIC_DCL void FDECL(append_honorific, (char *));
STATIC_DCL void FDECL(setpaid, (struct monst *));
STATIC_DCL long FDECL(addupbill, (struct monst *));
STATIC_DCL void FDECL(pacify_shk, (struct monst *));
STATIC_DCL struct bill_x *FDECL(onbill, (struct obj *, struct monst *,
@@ -286,7 +285,7 @@ struct obj *list;
}
/* either you paid or left the shop or the shopkeeper died */
STATIC_OVL void
void
setpaid(shkp)
register struct monst *shkp;
{

View File

@@ -15,6 +15,45 @@ STATIC_DCL void FDECL(see_lamp_flicker, (struct obj *, const char *));
STATIC_DCL void FDECL(lantern_message, (struct obj *));
STATIC_DCL void FDECL(cleanup_burn, (ANY_P *, long));
/* the order of these must match their numerical sequence in prop.h
because the property number is inferred from the array index;
used by wizard mode #timeout and #wizintrinsic */
const char *const propertynames[] = {
"0: not used",
/* Resistances */
/* 1..2 */ "fire resistance", "cold resistance",
/* 3..4 */ "sleep resistance", "disintegration resistance",
/* 5..6 */ "shock resistance", "poison resistance",
/* 7..8 */ "acid resistance", "stoning resistance",
/* 9..10 */ "drain resistance", "sickness resistance",
/* 11..12 */ "invulnerable", "magic resistance",
/* Troubles */
/* 13..16 */ "stunned", "confused", "blinded", "deafness",
/* 17..20 */ "fatally sick", "petrifying", "strangling", "vomiting",
/* 21..22 */ "slippery fingers", "becoming slime",
/* 23..24 */ "hallucinating", "halluicination resistance",
/* 25..28 */ "fumbling", "wounded legs", "sleepy", "voracious hunger",
/* Vision and senses */
/* 29..30 */ "see invisible", "telepathic",
/* 31..33 */ "warning", "warn:monster", "warn:undead",
/* 34..37 */ "searching", "clairvoyant", "infravision", "monster detection",
/* Appearance and behavior */
/* 38..41 */ "adorned (+/-Cha)", "invisible", "displaced", "stealthy",
/* 42..43 */ "monster aggrevation", "conflict",
/* Transportation */
/* 44..46 */ "jumping", "teleporting", "teleport control",
/* 47..49 */ "levitating", "flying", "water walking",
/* 50..52 */ "swimming", "magical breathing", "pass thru walls",
/* Physical attributes */
/* 53..55 */ "slow digestion", "half spell damage", "half physical damage",
/* 56..58 */ "HP regeneration", "energy regeneration", "extra protection",
/* 59 */ "protection from shape changers",
/* 60..62 */ "polymorphing", "polymorph control", "unchanging",
/* 63..66 */ "fast", "reflecting", "free action", "fixed abilites",
/* 67 */ "life will be saved",
0 /* sentinel */
};
/* He is being petrified - dialogue by inmet!tower */
static NEARDATA const char *const stoned_texts[] = {
"You are slowing down.", /* 5 */
@@ -57,6 +96,9 @@ stoned_dialogue()
multi_reason = "getting stoned";
nomovemsg = You_can_move_again; /* not unconscious */
break;
case 2:
if ((HDeaf & TIMEOUT) > 0L && (HDeaf & TIMEOUT) < 5L)
set_itimeout(&HDeaf, 5L); /* avoid Hear_again at tail end */
default:
break;
}
@@ -179,8 +221,9 @@ levitation_dialogue()
if (((HLevitation & TIMEOUT) % 2L) && i > 0L && i <= SIZE(levi_texts)) {
const char *s = levi_texts[SIZE(levi_texts) - i];
if (index(s, '%')) {
boolean danger = is_pool_or_lava(u.ux, u.uy)
&& !Is_waterlevel(&u.uz);
boolean danger = (is_pool_or_lava(u.ux, u.uy)
&& !Is_waterlevel(&u.uz));
pline(s, danger ? "over" : "in",
danger ? surface(u.ux, u.uy) : "air");
} else
@@ -225,6 +268,8 @@ slime_dialogue()
if (multi > 0)
nomul(0);
}
if (i == 2L && (HDeaf & TIMEOUT) > 0L && (HDeaf & TIMEOUT) < 5L)
set_itimeout(&HDeaf, 5L); /* avoid Hear_again at tail end */
exercise(A_DEX, FALSE);
}
@@ -1473,7 +1518,7 @@ timer_element *base;
char buf[BUFSZ];
if (!base) {
putstr(win, 0, "<empty>");
putstr(win, 0, " <empty>");
} else {
putstr(win, 0, "timeout id kind call");
for (curr = base; curr; curr = curr->next) {
@@ -1492,31 +1537,14 @@ timer_element *base;
}
}
static boolean print_prop_header = TRUE;
void
print_prop(win, text, prop)
winid win;
const char *text;
long prop;
{
char buf[BUFSZ];
if (prop & TIMEOUT) {
if (print_prop_header) {
putstr(win, 0, "");
putstr(win, 0, "Properties:");
putstr(win, 0, "");
print_prop_header = FALSE;
}
Sprintf(buf, " %10s: %ld", text, (prop & TIMEOUT));
putstr(win, 0, buf);
}
}
int
wiz_timeout_queue()
{
winid win;
char buf[BUFSZ];
const char *propname;
long intrinsic;
int i, count, longestlen, ln;
win = create_nhwindow(NHW_MENU); /* corner text window */
if (win == WIN_ERR)
@@ -1529,13 +1557,38 @@ wiz_timeout_queue()
putstr(win, 0, "");
print_queue(win, timer_base);
print_prop_header = TRUE;
print_prop(win, "Levitation", HLevitation);
print_prop(win, "Stoned", Stoned);
print_prop(win, "Vomiting", Vomiting);
print_prop(win, "Strangled", Strangled);
print_prop(win, "Slimed", Slimed);
/* Timed properies:
* check every one; the majority can't obtain temporary timeouts in
* normal play but those can be forced via the #wizintrinsic command.
*/
count = longestlen = 0;
for (i = 1; (propname = propertynames[i]) != 0; ++i) { /* [0] not used */
intrinsic = u.uprops[i].intrinsic;
if (intrinsic & TIMEOUT) {
++count;
if ((ln = (int) strlen(propname)) > longestlen)
longestlen = ln;
}
}
putstr(win, 0, "");
if (!count) {
putstr(win, 0, "No timed properties.");
} else {
putstr(win, 0, "Timed properties:");
putstr(win, 0, "");
for (i = 1; (propname = propertynames[i]) != 0; ++i) {
intrinsic = u.uprops[i].intrinsic;
if (intrinsic & TIMEOUT) {
/* timeout value can be up to 16777215 (0x00ffffff) but
width of 4 digits should result in values lining up
almost all the time (if/when they don't, it won't
look nice but the information will still be accurate) */
Sprintf(buf, " %*s %4ld", -longestlen, propname,
(intrinsic & TIMEOUT));
putstr(win, 0, buf);
}
}
}
display_nhwindow(win, FALSE);
destroy_nhwindow(win);
@@ -1551,6 +1604,7 @@ timer_sanity_check()
for (curr = timer_base; curr; curr = curr->next)
if (curr->kind == TIMER_OBJECT) {
struct obj *obj = curr->arg.a_obj;
if (obj->timed == 0) {
pline("timer sanity: untimed obj %s, timer %ld",
fmt_ptr((genericptr_t) obj), curr->tid);

View File

@@ -569,6 +569,28 @@ struct monst *worm;
}
}
void
sanity_check_worm(worm)
struct monst *worm;
{
struct wseg *curr;
if (!worm)
panic("no worm!");
if (!worm->wormno)
panic("not a worm?!");
curr = wtails[worm->wormno];
while (curr != wheads[worm->wormno]) {
if (!isok(curr->wx, curr->wy))
panic("worm seg not isok");
if (level.monsters[curr->wx][curr->wy] != worm)
panic("worm not at seg location");
curr = curr->nseg;
}
}
/*
* remove_worm()
*