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

This commit is contained in:
keni
2018-03-22 16:27:26 -04:00
18 changed files with 259 additions and 76 deletions

View File

@@ -166,7 +166,7 @@ const struct symdef defsyms[MAXPCHARS] = {
{ '<', "ladder up", C(CLR_BROWN) }, /* upladder */
{ '>', "ladder down", C(CLR_BROWN) }, /* dnladder */
{ '_', "altar", C(CLR_GRAY) }, /* altar */
{ '|', "grave", C(CLR_GRAY) }, /* grave */
{ '|', "grave", C(CLR_WHITE) }, /* grave */
{ '\\', "opulent throne", C(HI_GOLD) }, /* throne */
/*30*/ { '#', "sink", C(CLR_GRAY) }, /* sink */
{ '{', "fountain", C(CLR_BRIGHT_BLUE) }, /* fountain */

View File

@@ -1301,7 +1301,8 @@ int how;
for normal end of game, genocide doesn't either */
if (how <= GENOCIDED) {
dump_redirect(TRUE);
genl_outrip(0, how, endtime);
if (iflags.in_dumplog)
genl_outrip(0, how, endtime);
dump_redirect(FALSE);
}
#endif
@@ -1382,7 +1383,8 @@ int how;
artifact_score(invent, FALSE, endwin); /* list artifacts */
#ifdef DUMPLOG
dump_redirect(TRUE);
artifact_score(invent, FALSE, 0);
if (iflags.in_dumplog)
artifact_score(invent, FALSE, 0);
dump_redirect(FALSE);
#endif

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 lock.c $NHDT-Date: 1446955300 2015/11/08 04:01:40 $ $NHDT-Branch: master $:$NHDT-Revision: 1.67 $ */
/* NetHack 3.6 lock.c $NHDT-Date: 1521499715 2018/03/19 22:48:35 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -549,8 +549,13 @@ doforce()
for (otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere)
if (Is_box(otmp)) {
if (otmp->obroken || !otmp->olocked) {
There("is %s here, but its lock is already %s.", doname(otmp),
otmp->obroken ? "broken" : "unlocked");
/* force doname() to omit known "broken" or "unlocked"
prefix so that the message isn't worded redundantly;
since we're about to set lknown, there's no need to
remember and then reset its current value */
otmp->lknown = 0;
There("is %s here, but its lock is already %s.",
doname(otmp), otmp->obroken ? "broken" : "unlocked");
otmp->lknown = 1;
continue;
}
@@ -630,8 +635,9 @@ int x, y;
} else if (!get_adjacent_loc((char *) 0, (char *) 0, u.ux, u.uy, &cc))
return 0;
/* open at yourself/up/down */
if ((cc.x == u.ux) && (cc.y == u.uy))
return 0;
return doloot();
if (stumble_on_door_mimic(cc.x, cc.y))
return 1;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 objnam.c $NHDT-Date: 1471112245 2016/08/13 18:17:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.178 $ */
/* NetHack 3.6 objnam.c $NHDT-Date: 1521507553 2018/03/20 00:59:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.199 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -22,6 +22,7 @@ STATIC_DCL boolean FDECL(singplur_lookup, (char *, char *, BOOLEAN_P,
const char *const *));
STATIC_DCL char *FDECL(singplur_compound, (char *));
STATIC_DCL char *FDECL(xname_flags, (struct obj *, unsigned));
STATIC_DCL boolean FDECL(badman, (const char *, BOOLEAN_P));
struct Jitem {
int item;
@@ -2042,10 +2043,11 @@ static struct sing_plur one_off[] = {
{ "nemesis", "nemeses" },
{ "ovum", "ova" },
{ "ox", "oxen" },
{ "passerby", "passersby" },
{ "rtex", "rtices" }, /* vortex */
{ "tooth", "teeth" },
{ "serum", "sera" },
{ "staff", "staves" },
{ "tooth", "teeth" },
{ 0, 0 }
};
@@ -2054,19 +2056,18 @@ static const char *const as_is[] = {
"boots", "shoes", "gloves", "lenses", "scales",
"eyes", "gauntlets", "iron bars",
/* both singular and plural are spelled the same */
"deer", "elk", "fish", "tuna", "yaki",
"-hai", "krill", "manes", "moose", "ninja",
"sheep", "ronin", "roshi", "shito", "tengu",
"ki-rin", "Nazgul", "gunyoki", "piranha", "samurai",
"shuriken", 0,
"bison", "deer", "elk", "fish", "fowl",
"tuna", "yaki", "-hai", "krill", "manes",
"moose", "ninja", "sheep", "ronin", "roshi",
"shito", "tengu", "ki-rin", "Nazgul", "gunyoki",
"piranha", "samurai", "shuriken", 0,
/* Note: "fish" and "piranha" are collective plurals, suitable
for "wiped out all <foo>". For "3 <foo>", they should be
"fishes" and "piranhas" instead. We settle for collective
variant instead of attempting to support both. */
};
/* singularize/pluralize decisions common to both makesingular & makeplural
*/
/* singularize/pluralize decisions common to both makesingular & makeplural */
STATIC_OVL boolean
singplur_lookup(basestr, endstring, to_plural, alt_as_is)
char *basestr, *endstring; /* base string, pointer to eos(string) */
@@ -2090,16 +2091,35 @@ const char *const *alt_as_is; /* another set like as_is[] */
}
}
/* avoid false hit on one_off[].plur == "lice";
/* avoid false hit on one_off[].plur == "lice" or .sing == "goose";
if more of these turn up, one_off[] entries will need to flagged
as to which are whole words and which are matchable as suffices
then matching in the loop below will end up becoming more complex */
if (!strcmpi(basestr, "slice")
|| !strcmpi(basestr, "mongoose")) {
if (to_plural)
(void) strkitten(basestr, 's');
Strcasecpy(endstring, "s");
return TRUE;
}
/* skip "ox" -> "oxen" entry when pluralizing "<something>ox"
unless it is muskox */
if (to_plural && strlen(basestr) > 2 && !strcmpi(endstring - 2, "ox")
&& strcmpi(endstring - 6, "muskox")) {
/* "fox" -> "foxes" */
Strcasecpy(endstring, "es");
return TRUE;
}
if (to_plural) {
if (!strcmpi(endstring - 3, "man")
&& badman(basestr, to_plural)) {
Strcasecpy(endstring, "s");
return TRUE;
}
} else {
if (!strcmpi(endstring - 3, "men")
&& badman(basestr, to_plural))
return TRUE;
}
for (sp = one_off; sp->sing; sp++) {
/* check whether endstring already matches */
same = to_plural ? sp->plur : sp->sing;
@@ -2209,7 +2229,7 @@ const char *oldstr;
spot--;
while (spot > str && *spot == ' ')
spot--; /* Strip blanks from end */
*(spot + 1) = 0;
*(spot + 1) = '\0';
/* Now spot is the last character of the string */
len = strlen(str);
@@ -2224,7 +2244,6 @@ const char *oldstr;
{
static const char *const already_plural[] = {
"ae", /* algae, larvae, &c */
"men", /* also catches women, watchmen */
"matzot", 0,
};
@@ -2240,9 +2259,8 @@ const char *oldstr;
/* man/men ("Wiped out all cavemen.") */
if (len >= 3 && !strcmpi(spot - 2, "man")
/* exclude shamans and humans */
&& (len < 6 || strcmpi(spot - 5, "shaman"))
&& (len < 5 || strcmpi(spot - 4, "human"))) {
/* exclude shamans and humans etc */
&& !badman(str, TRUE)) {
Strcasecpy(spot - 1, "en");
goto bottom;
}
@@ -2417,7 +2435,8 @@ const char *oldstr;
} else { /* input doesn't end in 's' */
if (!BSTRCMPI(bp, p - 3, "men")) {
if (!BSTRCMPI(bp, p - 3, "men")
&& !badman(bp, FALSE)) {
Strcasecpy(p - 2, "an");
goto bottom;
}
@@ -2444,6 +2463,54 @@ bottom:
return bp;
}
boolean
badman(basestr, to_plural)
const char *basestr;
boolean to_plural; /* true => makeplural, false => makesingular */
{
int i, al;
char *endstr, *spot;
/* these are all the prefixes for *man that don't have a *men plural */
const char *no_men[] = {
"albu", "antihu", "anti", "ata", "auto", "bildungsro", "cai", "cay",
"ceru", "corner", "decu", "des", "dura", "fir", "hanu", "het",
"infrahu", "inhu", "nonhu", "otto", "out", "prehu", "protohu",
"subhu", "superhu", "talis", "unhu", "sha",
"hu", "un", "le", "re", "so", "to", "at", "a",
};
/* these are all the prefixes for *men that don't have a *man singular */
const char *no_man[] = {
"abdo", "acu", "agno", "ceru", "cogno", "cycla", "fleh", "grava",
"hegu", "preno", "sonar", "speci", "dai", "exa", "fla", "sta", "teg",
"tegu", "vela", "da", "hy", "lu", "no", "nu", "ra", "ru", "se", "vi", "ya",
"o", "a",
};
if (!basestr || strlen(basestr) < 4)
return FALSE;
endstr = eos((char *)basestr);
if (to_plural) {
for (i = 0; i < SIZE(no_men); i++) {
al = (int) strlen(no_men[i]);
spot = endstr - (al + 3);
if (!BSTRNCMPI(basestr, spot, no_men[i], al)
&& (spot == basestr || *(spot - 1) == ' '))
return TRUE;
}
} else {
for (i = 0; i < SIZE(no_man); i++) {
al = (int) strlen(no_man[i]);
spot = endstr - (al + 3);
if (!BSTRNCMPI(basestr, spot, no_man[i], al)
&& (spot == basestr || *(spot - 1) == ' '))
return TRUE;
}
}
return FALSE;
}
/* compare user string against object name string using fuzzy matching */
STATIC_OVL boolean
wishymatch(u_str, o_str, retry_inverted)
@@ -2603,6 +2670,8 @@ struct alt_spellings {
{ "grapnel", GRAPPLING_HOOK },
{ "grapple", GRAPPLING_HOOK },
{ "protection from shape shifters", RIN_PROTECTION_FROM_SHAPE_CHAN },
/* if we ever add other sizes, move this to o_ranges[] with "bag" */
{ "box", LARGE_BOX },
/* normally we wouldn't have to worry about unnecessary <space>, but
" stone" will get stripped off, preventing a wishymatch; that actually
lets "flint stone" be a match, so we also accept bogus "flintstone" */
@@ -2696,7 +2765,7 @@ struct obj *no_wish;
register struct obj *otmp;
int cnt, spe, spesgn, typ, very, rechrg;
int blessed, uncursed, iscursed, ispoisoned, isgreased;
int eroded, eroded2, erodeproof;
int eroded, eroded2, erodeproof, locked, unlocked, broken;
int halfeaten, mntmp, contents;
int islit, unlabeled, ishistoric, isdiluted, trapped;
int tmp, tinv, tvariety;
@@ -2722,9 +2791,11 @@ struct obj *no_wish;
char *un, *dn, *actualn, *origbp = bp;
const char *name = 0;
cnt = spe = spesgn = typ = very = rechrg = blessed = uncursed = iscursed =
ispoisoned = isgreased = eroded = eroded2 = erodeproof = halfeaten =
islit = unlabeled = ishistoric = isdiluted = trapped = 0;
cnt = spe = spesgn = typ = 0;
very = rechrg = blessed = uncursed = iscursed = ispoisoned =
isgreased = eroded = eroded2 = erodeproof = halfeaten =
islit = unlabeled = ishistoric = isdiluted = trapped =
locked = unlocked = broken = 0;
tvariety = RANDOM_TIN;
mntmp = NON_PM;
#define UNDEFINED 0
@@ -2812,6 +2883,13 @@ struct obj *no_wish;
trapped = 1;
} else if (!strncmpi(bp, "untrapped ", l = 10)) {
trapped = 2; /* not trapped */
/* locked, unlocked, broken: box/chest lock states */
} else if (!strncmpi(bp, "locked ", l = 7)) {
locked = 1, unlocked = broken = 0;
} else if (!strncmpi(bp, "unlocked ", l = 9)) {
unlocked = 1, locked = broken = 0;
} else if (!strncmpi(bp, "broken ", l = 7)) {
broken = 1, locked = unlocked = 0;
} else if (!strncmpi(bp, "greased ", l = 8)) {
isgreased = 1;
} else if (!strncmpi(bp, "very ", l = 5)) {
@@ -3217,7 +3295,10 @@ retry:
; /* avoid false hit on "* glass" */
} else if (!BSTRCMPI(bp, p - 6, " glass") || !strcmpi(bp, "glass")) {
register char *g = bp;
if (strstri(g, "broken"))
/* treat "broken glass" as a non-existent item; since "broken" is
also a chest/box prefix it might have been stripped off above */
if (broken || strstri(g, "broken"))
return (struct obj *) 0;
if (!strncmpi(g, "worthless ", 10))
g += 10;
@@ -3737,6 +3818,28 @@ typfnd:
if (Is_box(otmp) || typ == TIN)
otmp->otrapped = (trapped == 1);
}
/* empty for containers rather than for tins */
if (contents == EMPTY) {
if (otmp->otyp == BAG_OF_TRICKS || otmp->otyp == HORN_OF_PLENTY) {
if (otmp->spe > 0)
otmp->spe = 0;
} else if (Has_contents(otmp)) {
/* this assumes that artifacts can't be randomly generated
inside containers */
delete_contents(otmp);
otmp->owt = weight(otmp);
}
}
/* set locked/unlocked/broken */
if (Is_box(otmp)) {
if (locked) {
otmp->olocked = 1, otmp->obroken = 0;
} else if (unlocked) {
otmp->olocked = 0, otmp->obroken = 0;
} else if (broken) {
otmp->olocked = 0, otmp->obroken = 1;
}
}
if (isgreased)
otmp->greased = 1;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pline.c $NHDT-Date: 1519183957 2018/02/21 03:32:37 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.65 $ */
/* NetHack 3.6 pline.c $NHDT-Date: 1520964541 2018/03/13 18:09:01 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.66 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -96,6 +96,7 @@ void pline
VA_DECL(const char *, line)
#endif /* USE_STDARG | USE_VARARG */
{ /* start of vpline() or of nested block in USE_OLDARG's pline() */
static int in_pline = 0;
char pbuf[3 * BUFSZ];
int ln;
int msgtyp;
@@ -138,11 +139,14 @@ VA_DECL(const char *, line)
if ((pline_flags & SUPPRESS_HISTORY) == 0)
dumplogmsg(line);
#endif
if (!iflags.window_inited) {
/* use raw_print() if we're called too early (or perhaps too late
during shutdown) or if we're being called recursively (probably
via debugpline() in the interface code) */
if (in_pline++ || !iflags.window_inited) {
/* [we should probably be using raw_printf("\n%s", line) here] */
raw_print(line);
iflags.last_msg = PLNMSG_UNKNOWN;
return;
goto pline_done;
}
msgtyp = MSGTYP_NORMAL;
@@ -158,7 +162,7 @@ VA_DECL(const char *, line)
* doing so out of context and probably end up seeming silly.
* (Not an issue for no-repeat but matters for no-show.)
*/
return;
goto pline_done;
}
if (vision_full_recalc)
@@ -178,6 +182,10 @@ VA_DECL(const char *, line)
if (msgtyp == MSGTYP_STOP)
display_nhwindow(WIN_MESSAGE, TRUE); /* --more-- */
pline_done:
--in_pline;
return;
#if !(defined(USE_STDARG) || defined(USE_VARARGS))
/* provide closing brace for the nested block
which immediately follows USE_OLDARGS's VA_DECL() */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 polyself.c $NHDT-Date: 1513298347 2017/12/15 00:39:07 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.116 $ */
/* NetHack 3.6 polyself.c $NHDT-Date: 1520797126 2018/03/11 19:38:46 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.117 $ */
/* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
@@ -964,7 +964,7 @@ int alone;
{
struct obj *otmp;
const char *what, *which, *whichtoo;
boolean candropwep, candropswapwep;
boolean candropwep, candropswapwep, updateinv = TRUE;
if (uwep) {
/* !alone check below is currently superfluous but in the
@@ -989,17 +989,26 @@ int alone;
You("find you must %s %s %s!", what,
the_your[!!strncmp(which, "corpse", 6)], which);
}
/* if either uwep or wielded uswapwep is flagged as 'in_use'
then don't drop it or explicitly update inventory; leave
those actions to caller (or caller's caller, &c) */
if (u.twoweap) {
otmp = uswapwep;
uswapwepgone();
if (candropswapwep)
if (otmp->in_use)
updateinv = FALSE;
else if (candropswapwep)
dropx(otmp);
}
otmp = uwep;
uwepgone();
if (candropwep)
if (otmp->in_use)
updateinv = FALSE;
else if (candropwep)
dropx(otmp);
update_inventory();
if (updateinv)
update_inventory();
} else if (!could_twoweap(youmonst.data)) {
untwoweapon();
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 potion.c $NHDT-Date: 1502753790 2017/08/14 23:36:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.138 $ */
/* NetHack 3.6 potion.c $NHDT-Date: 1520797133 2018/03/11 19:38:53 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.144 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1563,6 +1563,11 @@ register struct obj *obj;
int i, ii, isdone, kn = 0;
boolean cureblind = FALSE;
/* potion of unholy water might be wielded; prevent
you_were() -> drop_weapon() from dropping it so that it
remains in inventory where our caller expects it to be */
obj->in_use = 1;
switch (obj->otyp) {
case POT_RESTORE_ABILITY:
case POT_GAIN_ABILITY:
@@ -1714,7 +1719,7 @@ register struct obj *obj;
break;
*/
}
/* note: no obfree() */
/* note: no obfree() -- that's our caller's responsibility */
if (obj->dknown) {
if (kn)
makeknown(obj->otyp);

View File

@@ -143,7 +143,7 @@ time_t when;
#ifdef DUMPLOG
if (tmpwin == 0)
dump_forward_putstr(0, 0, "Gave over:", TRUE);
dump_forward_putstr(0, 0, "Game over:", TRUE);
else
#endif
putstr(tmpwin, 0, "");

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 uhitm.c $NHDT-Date: 1520043553 2018/03/03 02:19:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.175 $ */
/* NetHack 3.6 uhitm.c $NHDT-Date: 1521684760 2018/03/22 02:12:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.176 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -513,14 +513,10 @@ struct attack *uattk; /* ... but we don't enforce that here; Null works ok */
u.dx, u.dy, u.dz);
return TRUE; /* target hasn't been killed */
}
clockwise = !clockwise; /* alternate */
/* adjust direction by two so that loop's increment (for clockwise)
or decrement (for counter-clockwise) will point at the spot next
to primary target */
if (clockwise)
i = (i + 6) % 8;
else
i = (i + 2) % 8;
i = (i + (clockwise ? 6 : 2)) % 8;
umort = u.umortality; /* used to detect life-saving */
/*
@@ -535,10 +531,8 @@ struct attack *uattk; /* ... but we don't enforce that here; Null works ok */
struct monst *mtmp;
int tx, ty, tmp, dieroll, mhit, attknum, armorpenalty;
if (clockwise)
i = (i + 1) % 8; /* ++i, wrap 8 to i=0 */
else
i = (i + 7) % 8; /* --i, wrap -1 to i=7 */
/* ++i, wrap 8 to i=0 /or/ --i, wrap -1 to i=7 */
i = (i + (clockwise ? 1 : 7)) % 8;
tx = x + xdir[i], ty = y + ydir[i]; /* current target location */
if (!isok(tx, ty))
@@ -563,6 +557,8 @@ struct attack *uattk; /* ... but we don't enforce that here; Null works ok */
if (!uwep || u.umortality > umort)
break;
}
/* set up for next time */
clockwise = !clockwise; /* alternate */
/* return False if primary target died, True otherwise; note: if 'target'
was nonNull upon entry then it's still nonNull even if *target died */
@@ -583,8 +579,8 @@ struct attack *uattk;
int dieroll = rnd(20);
int mhit = (tmp > dieroll || u.uswallow);
/* Cleaver attacks three spots, one on either side of 'mon';
it can't we part of dual-wielding but we guard against that anyway;
/* Cleaver attacks three spots, 'mon' and one on either side of 'mon';
it can't be part of dual-wielding but we guard against that anyway;
cleave return value reflects status of primary target ('mon') */
if (uwep && uwep->oartifact == ART_CLEAVER && !u.twoweap
&& !u.uswallow && !u.ustuck && !NODIAG(u.umonnum))