From 480e682454dec0772391f48df4cfdf3f6102a28f Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 2 Jan 2019 13:42:45 -0800 Subject: [PATCH] create_particular long worm tail vs mkclass Similar to ^G of 'I' triggering impossible "mkclass found no class 35 monsters", using a leading substring of "long worm tail" (other than "l" and "long worm") would trigger impossible "mkclass found no class 59 monsters and kill the fuzzer when it escalates impossible to panic. Tighten up the substring matching. ^G of '~' wasn't affected; it deliberately creates a long worm rather than the tail of one. But it was possible to ask for "long worm tail" as a specific monster type and then override the switch to long worm when prompted about whether to force the originally specified critter. I've added a check to prevent that opportunity to override even though a tail without a head seemed to be harmless. --- doc/fixes36.2 | 12 +++++++----- src/mondata.c | 16 +++++++++++----- src/read.c | 9 +++++++-- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index fe8568a2d..320d6288e 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.219 $ $NHDT-Date: 1546212616 2018/12/30 23:30:16 $ +$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.220 $ $NHDT-Date: 1546465283 2019/01/02 21:41:23 $ This fixes36.2 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.1 in April 2018. Please note, however, @@ -360,10 +360,12 @@ when built with STATUS_HILITES enabled (the default), gold on status line was missing '$' prefix for symset:Blank wizard mode ^G, creating a monster of class 'I' yielded impossible "mkclass found no class 35 monsters" -in some unknown circumstance, examining something on the map could match bogus - monster class #0 and trigger impossible "Alphabet soup: 'an("")'." - (fix avoids the warning but underlying cause is a mystery; noticed - with the fuzzer, which swaps symbol sets in and out at random) +wizard mode ^G, creating a monster via class name using "lo" through "long wor" + or "long worm t" through "long worm tail" yielded impossible "mkclass + found no class 59 monsters" (class '~' creates a long worm as intended) +if bouldersym bug (via 'O', above) put a ('\0') on the map, examining + that spot matched placeholder monster class #0 and triggered impossible + "Alphabet soup: 'an("")'." tty: turn off an optimization that is the suspected cause of Windows reported partial status lines following level changes tty: ensure that current status fields are always copied to prior status diff --git a/src/mondata.c b/src/mondata.c index 62dea9a10..9feeeae4e 100644 --- a/src/mondata.c +++ b/src/mondata.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mondata.c $NHDT-Date: 1543545188 2018/11/30 02:33:08 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.69 $ */ +/* NetHack 3.6 mondata.c $NHDT-Date: 1546465283 2019/01/02 21:41:23 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.70 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -781,11 +781,12 @@ const char *in_str; } for (len = 0, i = LOW_PM; i < NUMMONS; i++) { - register int m_i_len = strlen(mons[i].mname); + register int m_i_len = (int) strlen(mons[i].mname); if (m_i_len > len && !strncmpi(mons[i].mname, str, m_i_len)) { if (m_i_len == slen) { - return i; /* exact match */ + mntmp = i; + break; /* exact match */ } else if (slen > m_i_len && (str[m_i_len] == ' ' || !strcmpi(&str[m_i_len], "s") @@ -841,7 +842,7 @@ int *mndx_p; { 0, NON_PM } }; const char *p, *x; - int i; + int i, len; if (mndx_p) *mndx_p = NON_PM; /* haven't [yet] matched a specific type */ @@ -863,6 +864,8 @@ int *mndx_p; return i; } else { /* multiple characters */ + if (!strcmpi(in_str, "long")) /* not enough to match "long worm" */ + return 0; /* avoid false whole-word match with "long worm tail" */ in_str = makesingular(in_str); /* check for special cases */ for (i = 0; falsematch[i]; i++) @@ -878,9 +881,12 @@ int *mndx_p; return mons[i].mlet; } /* check monster class descriptions */ + len = (int) strlen(in_str); for (i = 1; i < MAXMCLASSES; i++) { x = def_monsyms[i].explain; - if ((p = strstri(x, in_str)) != 0 && (p == x || *(p - 1) == ' ')) + if ((p = strstri(x, in_str)) != 0 && (p == x || *(p - 1) == ' ') + && ((int) strlen(p) >= len + && (p[len] == '\0' || p[len] == ' '))) return i; } /* check individual species names */ diff --git a/src/read.c b/src/read.c index a52a0317b..562b52bf1 100644 --- a/src/read.c +++ b/src/read.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 read.c $NHDT-Date: 1546053040 2018/12/29 03:10:40 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.163 $ */ +/* NetHack 3.6 read.c $NHDT-Date: 1546465285 2019/01/02 21:41:25 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.164 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2498,6 +2498,10 @@ struct _create_particular_data *d; d->which = PM_STALKER; d->monclass = MAXMCLASSES; return TRUE; + } else if (d->monclass == S_WORM_TAIL) { /* empty monster class */ + d->which = PM_LONG_WORM; + d->monclass = MAXMCLASSES; + return TRUE; } else if (d->monclass > 0) { d->which = urole.malenum; /* reset from NON_PM */ return TRUE; @@ -2516,7 +2520,8 @@ struct _create_particular_data *d; if (!d->randmonst) { firstchoice = d->which; - if (cant_revive(&d->which, FALSE, (struct obj *) 0)) { + if (cant_revive(&d->which, FALSE, (struct obj *) 0) + && firstchoice != PM_LONG_WORM_TAIL) { /* wizard mode can override handling of special monsters */ char buf[BUFSZ]; -- 2.40.0