From e5263b5ff0ad4e21397db7495b0ec7c67395d619 Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 30 Jul 2016 14:53:00 -0700 Subject: [PATCH 01/11] fix #H4460 - tribute typos in /Thud!/ Passage 2: DELIBERATEDLY -> DELIBERATELY Passage 6: vengence -> vengeance --- dat/tribute | 4 ++-- doc/fixes36.1 | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dat/tribute b/dat/tribute index ef2b776cd..e1ea7590b 100644 --- a/dat/tribute +++ b/dat/tribute @@ -6759,7 +6759,7 @@ pretty good sigh. IT APPEARS THAT THE BUTLER DID IT. IT IS A MADE-UP STORY. VERY STRANGE. ALL ONE NEEDS TO DO IS TURN TO THE LAST PAGE AND THE ANSWER IS THERE. WHAT, THEREFORE, IS THE POINT OF -DELIBERATEDLY NOT KNOWING? +DELIBERATELY NOT KNOWING? It sounded like gibberish to Vimes, so he ignored it. Some of the aches had gone, although his head still hammered. There was an empty feeling @@ -6815,7 +6815,7 @@ favor. "I have been know to have the occasional 'little flutter,' sir." "Given, then, a contest between an invisible and very powerful quasidemonic -/thing/ of pure vengence on the one hand, and the commander on the other, +/thing/ of pure vengeance on the one hand, and the commander on the other, where would you wager, say... one dollar?" "I wouldn't, sir. That looks like one that would go to the judges." diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 8b63f9015..c4198661a 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -29,6 +29,7 @@ negative intrinsic protection shouldn't confer MC=1, "you are warded" (not possible from divine protection but is possible from eating rings) make a slight adjustment to the quickmimic() sense wording fix typo in passage 1 of The Colour of Magic +fix typos in passages 2 and 6 of Thud! falling asleep when reading dull spellbook ignored sleep resistance getpos() complaint about invalid movement keystroke didn't describe meta-chars accurately From 2160dee4caa4446db4685ec9b32dcaadf588fc55 Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 30 Jul 2016 19:08:25 -0700 Subject: [PATCH 02/11] lint suppression botl.c - unused argument in #if STATUS_HILITES code. mkmaze.c - "clang version 7.3.0 (clang-703.0.31)", or whatever version of gcc it's based on, warns that ''#define register /*empty*/'' hides a keyword. '-Wkeyword-macro' isn't mentioned in the recent gcc manual I checked, but it is being enabled by specifying '-pedantic' (rather than -Wall or -W) to the preprocessor. It could be turned off via '-Wno-keyword-macro' but this removes all mkmaze.c's register references instead. (Sean wanted that, and this might be why....) --- src/botl.c | 13 +++++---- src/mkmaze.c | 82 +++++++++++++++++++++++++--------------------------- 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/botl.c b/src/botl.c index fd1880cf5..8fc6ab521 100644 --- a/src/botl.c +++ b/src/botl.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 botl.c $NHDT-Date: 1452660188 2016/01/13 04:43:08 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.70 $ */ +/* NetHack 3.6 botl.c $NHDT-Date: 1469930895 2016/07/31 02:08:15 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.75 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1311,17 +1311,18 @@ boolean from_configfile; /* Now finally, we notify the window port */ if (!from_configfile) status_threshold(idx, status_hilites[idx].anytype, - status_hilites[idx].threshold, - status_hilites[idx].behavior, - status_hilites[idx].coloridx[0], - status_hilites[idx].coloridx[1]); + status_hilites[idx].threshold, + status_hilites[idx].behavior, + status_hilites[idx].coloridx[0], + status_hilites[idx].coloridx[1]); return TRUE; } +/*ARGUSED*/ void status_notify_windowport(all) -boolean all; +boolean all UNUSED; { int idx; anything it; diff --git a/src/mkmaze.c b/src/mkmaze.c index b3dc88f3e..8497f1c7e 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mkmaze.c $NHDT-Date: 1461571093 2016/04/25 07:58:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.47 $ */ +/* NetHack 3.6 mkmaze.c $NHDT-Date: 1469930897 2016/07/31 02:08:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.50 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -41,7 +41,7 @@ STATIC_OVL int iswall(x, y) int x, y; { - register int type; + int type; if (!isok(x, y)) return 0; @@ -126,7 +126,7 @@ wall_cleanup(x1, y1, x2, y2) int x1, y1, x2, y2; { uchar type; - register int x, y; + int x, y; struct rm *lev; /* sanity check on incoming variables */ @@ -158,7 +158,7 @@ fix_wall_spines(x1, y1, x2, y2) int x1, y1, x2, y2; { uchar type; - register int x,y; + int x, y; struct rm *lev; int FDECL((*loc_f), (int, int)); int bits; @@ -226,7 +226,7 @@ int x1, y1, x2, y2; STATIC_OVL boolean okay(x, y, dir) int x, y; -register int dir; +int dir; { mz_move(x, y, dir); mz_move(x, y, dir); @@ -460,9 +460,9 @@ static boolean was_waterlevel; /* ugh... this shouldn't be needed */ void fixup_special() { - register lev_region *r = lregions; + lev_region *r = lregions; struct d_level lev; - register int x, y; + int x, y; struct mkroom *croom; boolean added_branch = FALSE; @@ -600,7 +600,7 @@ fixup_special() create_secret_door(croom, W_ANY); } else if (on_level(&u.uz, &orcus_level)) { - register struct monst *mtmp, *mtmp2; + struct monst *mtmp, *mtmp2; /* it's a ghost town, get rid of shopkeepers */ for (mtmp = fmon; mtmp; mtmp = mtmp2) { @@ -620,7 +620,7 @@ fixup_special() void makemaz(s) -register const char *s; +const char *s; { int x, y; char protofile[20]; @@ -839,7 +839,7 @@ walkfrom(x, y, typ) int x, y; schar typ; { - register int q, a, dir; + int q, a, dir; int dirs[4]; if (!typ) { @@ -887,7 +887,8 @@ coord *cc; && levl[cc->x][cc->y].typ != (level.flags.corrmaze ? CORR : ROOM)); if (cpt >= 100) { - register int x, y; + int x, y; + /* last try */ for (x = 0; x < (x_maze_max >> 1) - 1; x++) for (y = 0; y < (y_maze_max >> 1) - 1; y++) { @@ -915,9 +916,9 @@ coord *cc; void bound_digging() { - register int x, y; - register unsigned typ; - register struct rm *lev; + int x, y; + unsigned typ; + struct rm *lev; boolean found, nonwall; int xmin, xmax, ymin, ymax; @@ -1024,8 +1025,10 @@ fumaroles() for (n = rn2(3) + 2; n; n--) { xchar x = rn1(COLNO - 4, 3); xchar y = rn1(ROWNO - 4, 3); + if (levl[x][y].typ == LAVAPOOL) { NhRegion *r = create_gas_cloud(x, y, 4 + rn2(5), rn1(10, 5)); + clear_heros_fault(r); snd = TRUE; if (distu(x, y) < 15) @@ -1043,11 +1046,6 @@ fumaroles() * other source files, but they are all so nicely encapsulated here. */ -#ifdef DEBUG -/* to ease the work of debuggers at this stage */ -#define register -#endif - #define CONS_OBJ 0 #define CONS_MON 1 #define CONS_HERO 2 @@ -1071,8 +1069,8 @@ void movebubbles() { static boolean up; - register struct bubble *b; - register int x, y, i, j; + struct bubble *b; + int x, y, i, j; struct trap *btrap; static const struct rm water_pos = { cmap_to_glyph(S_water), WATER, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -1194,7 +1192,7 @@ movebubbles() */ up = !up; for (b = up ? bbubbles : ebubbles; b; b = up ? b->next : b->prev) { - register int rx = rn2(3), ry = rn2(3); + int rx = rn2(3), ry = rn2(3); mv_bubble(b, b->dx + 1 - (!b->dx ? rx : (rx ? 1 : 0)), b->dy + 1 - (!b->dy ? ry : (ry ? 1 : 0)), FALSE); @@ -1210,8 +1208,8 @@ movebubbles() void water_friction() { - register int x, y, dx, dy; - register boolean eff = FALSE; + int x, y, dx, dy; + boolean eff = FALSE; if (Swimming && rn2(4)) return; /* natural swimmers have advantage */ @@ -1245,7 +1243,7 @@ void save_waterlevel(fd, mode) int fd, mode; { - register struct bubble *b; + struct bubble *b; if (!Is_waterlevel(&u.uz) && !Is_airlevel(&u.uz)) return; @@ -1268,11 +1266,10 @@ int fd, mode; void restore_waterlevel(fd) -register int fd; +int fd; { - register struct bubble *b = (struct bubble *) 0, *btmp; - register int i; - int n; + struct bubble *b = (struct bubble *) 0, *btmp; + int i, n; if (!Is_waterlevel(&u.uz) && !Is_airlevel(&u.uz)) return; @@ -1305,7 +1302,7 @@ const char * waterbody_name(x, y) xchar x, y; { - register struct rm *lev; + struct rm *lev; schar ltyp; if (!isok(x, y)) @@ -1344,10 +1341,10 @@ set_wportal() STATIC_OVL void setup_waterlevel() { - register int x, y; - register int xskip, yskip; - register int water_glyph = cmap_to_glyph(S_water); - register int air_glyph = cmap_to_glyph(S_air); + int x, y; + int xskip, yskip; + int water_glyph = cmap_to_glyph(S_water), + air_glyph = cmap_to_glyph(S_air); /* ouch, hardcoded... */ @@ -1380,7 +1377,7 @@ setup_waterlevel() STATIC_OVL void unsetup_waterlevel() { - register struct bubble *b, *bb; + struct bubble *b, *bb; /* free bubbles */ @@ -1393,7 +1390,7 @@ unsetup_waterlevel() STATIC_OVL void mk_bubble(x, y, n) -register int x, y, n; +int x, y, n; { /* * These bit masks make visually pleasing bubbles on a normal aspect @@ -1402,14 +1399,15 @@ register int x, y, n; * in situ, either. The first two elements tell the dimensions of * the bubble's bounding box. */ - static uchar bm2[] = { 2, 1, 0x3 }, bm3[] = { 3, 2, 0x7, 0x7 }, + static uchar bm2[] = { 2, 1, 0x3 }, + bm3[] = { 3, 2, 0x7, 0x7 }, bm4[] = { 4, 3, 0x6, 0xf, 0x6 }, bm5[] = { 5, 3, 0xe, 0x1f, 0xe }, bm6[] = { 6, 4, 0x1e, 0x3f, 0x3f, 0x1e }, bm7[] = { 7, 4, 0x3e, 0x7f, 0x7f, 0x3e }, bm8[] = { 8, 4, 0x7e, 0xff, 0xff, 0x7e }, *bmask[] = { bm2, bm3, bm4, bm5, bm6, bm7, bm8 }; - register struct bubble *b; + struct bubble *b; if (x >= bxmax || y >= bymax) return; @@ -1455,11 +1453,11 @@ register int x, y, n; */ STATIC_OVL void mv_bubble(b, dx, dy, ini) -register struct bubble *b; -register int dx, dy; -register boolean ini; +struct bubble *b; +int dx, dy; +boolean ini; { - register int x, y, i, j, colli = 0; + int x, y, i, j, colli = 0; struct container *cons, *ctemp; /* clouds move slowly */ From bde2aa5ea2a549d741d2e3863405bfe2f144d53e Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 3 Aug 2016 01:17:43 -0700 Subject: [PATCH 03/11] lev_comp shifts of negative values Apparently the compiler for OSX 10.11 + Xcode 7.3.1 is defaulting to C99 (or C11?) because it is enabling a gcc warning that is included by -Wextra (newer name for obscure -W) for C99 or later. lev_comp.y:2276:20: warning: shifting a negative signed value is undefined [-Wshift-negative-value] (yyval.i) = SP_OBJ_PACK(-1, (yyvsp[(1) - (1)].i)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../include/sp_lev.h:248:33: note: expanded from macro 'SP_OBJ_PACK' \#define SP_OBJ_PACK(o, c) (((o) << 8) + ((char) (c))) \ ~~~ ^ SP_MONST_PACK() and SP_OBJ_PACK() are both called with -1, and SP_MAPCHAR_PACK() is called with either -1 or -2. The revised macros add 10 when encoding and subtract it when decoding so that they can handle -1 through -10 without shifting negative values. There were also several bitwise ANDs that the bulk reformatting misclassified as casts of hardcoded addresses. --- include/sp_lev.h | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/include/sp_lev.h b/include/sp_lev.h index 6c42d9aff..78ace02ab 100644 --- a/include/sp_lev.h +++ b/include/sp_lev.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 sp_lev.h $NHDT-Date: 1432512780 2015/05/25 00:13:00 $ $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */ +/* NetHack 3.6 sp_lev.h $NHDT-Date: 1470212260 2016/08/03 08:17:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.17 $ */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -228,28 +228,31 @@ enum opcode_defs { #define SP_COORD_X(l) (l & 0xff) #define SP_COORD_Y(l) ((l >> 16) & 0xff) -#define SP_COORD_PACK(x, y) (((x) &0xff) + (((y) &0xff) << 16)) +#define SP_COORD_PACK(x, y) (((x) & 0xff) + (((y) & 0xff) << 16)) #define SP_COORD_PACK_RANDOM(f) (SP_COORD_IS_RANDOM | (f)) #define SP_REGION_X1(l) (l & 0xff) #define SP_REGION_Y1(l) ((l >> 8) & 0xff) #define SP_REGION_X2(l) ((l >> 16) & 0xff) #define SP_REGION_Y2(l) ((l >> 24) & 0xff) -#define SP_REGION_PACK(x1, y1, x2, y2) \ - (((x1) &0xff) + (((y1) &0xff) << 8) + (((x2) &0xff) << 16) \ - + (((y2) &0xff) << 24)) +#define SP_REGION_PACK(x1, y1, x2, y2) \ + (((x1) & 0xff) + (((y1) & 0xff) << 8) + (((x2) & 0xff) << 16) \ + + (((y2) & 0xff) << 24)) -#define SP_MONST_CLASS(l) (l & 0xff) -#define SP_MONST_PM(l) ((l >> 8) & 0xffff) -#define SP_MONST_PACK(m, c) (((m) << 8) + ((char) (c))) +/* permonst index, object index, and lit value might be negative; + * add 10 to accept -1 through -9 while forcing non-negative for bit shift + */ +#define SP_MONST_CLASS(l) ((l) & 0xff) +#define SP_MONST_PM(l) ((((l) >> 8) & 0xffff) - 10) +#define SP_MONST_PACK(pm, cls) (((10 + (pm)) << 8) | ((cls) & 0xff)) -#define SP_OBJ_CLASS(l) (l & 0xff) -#define SP_OBJ_TYP(l) ((l >> 8) & 0xffff) -#define SP_OBJ_PACK(o, c) (((o) << 8) + ((char) (c))) +#define SP_OBJ_CLASS(l) ((l) & 0xff) +#define SP_OBJ_TYP(l) ((((l) >> 8) & 0xffff) - 10) +#define SP_OBJ_PACK(ob, cls) (((10 + (ob)) << 8) | ((cls) & 0xff)) -#define SP_MAPCHAR_TYP(l) (l & 0xff) -#define SP_MAPCHAR_LIT(l) ((l >> 8) & 0xff) -#define SP_MAPCHAR_PACK(typ, lit) (((lit) << 8) + ((char) (typ))) +#define SP_MAPCHAR_TYP(l) ((l) & 0xff) +#define SP_MAPCHAR_LIT(l) ((((l) >> 8) & 0xffff) - 10) +#define SP_MAPCHAR_PACK(typ, lit) (((10 + (lit)) << 8) | ((typ) & 0xff)) struct opvar { xchar spovartyp; /* one of SPOVAR_foo */ From b49830f4c14c761b8e826c0e5ce0c61f4d9b8ca4 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 3 Aug 2016 17:59:10 -0700 Subject: [PATCH 04/11] fix #H4462 - grammar in corpse eating message "The the Wizard of Yendor corpse tastes terrible." "The" was supplied when formatting the sentence, "the" when formatting the corpse object. Same applied to several other monsters, those flagged as unique and without personal name (Oracle, Cyclops, others). This also changes the corpse eating message to not always specify the taste as "terrible" when the eater is omnivorous. It also makes corpses (and tins) of unique monsters be wishable in wizard mode. I had killed the Wizard at least half a dozen times without a corpse being left, so used wishing instead. Later retries did finally leave one--lack of corpse turned out to just be by chance. --- doc/fixes36.1 | 3 +++ src/eat.c | 33 ++++++++++++++++++++++----------- src/objnam.c | 6 +++--- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index c4198661a..ee67cc371 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -323,6 +323,9 @@ clarify that shape-shifted vampires revert to vampire form when petrified or digested; when back in 'V' form, they're vulnerable to such damage when poly'd into an engulfer which does digestion damage, a kill resulting in a level gain gave "welcome to level N+1" before "you digest " +any corpse eaten by omnivorous hero always tasted "terrible" +eating the corpse of a unique non-named monster (Wizard of Yendor, Oracle, + Chromatic Dragon, others) gave "The the tastes ..." Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/src/eat.c b/src/eat.c index 52e29def5..ff5390496 100644 --- a/src/eat.c +++ b/src/eat.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 eat.c $NHDT-Date: 1467028559 2016/06/27 11:55:59 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.171 $ */ +/* NetHack 3.6 eat.c $NHDT-Date: 1470272344 2016/08/04 00:59:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.172 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1662,22 +1662,33 @@ struct obj *otmp; } else if (mnum == PM_FLOATING_EYE && u.umonnum == PM_RAVEN) { You("peck the eyeball with delight."); } else { - /* [is this right? omnivores end up always disliking the taste] */ - boolean yummy = vegan(&mons[mnum]) - ? (!carnivorous(youmonst.data) - && herbivorous(youmonst.data)) - : (carnivorous(youmonst.data) - && !herbivorous(youmonst.data)); + /* yummy is always False for omnivores, palatable always True */ + boolean yummy = (vegan(&mons[mnum]) + ? (!carnivorous(youmonst.data) + && herbivorous(youmonst.data)) + : (carnivorous(youmonst.data) + && !herbivorous(youmonst.data))), + palatable = (vegetarian(&mons[mnum]) + ? herbivorous(youmonst.data) + : carnivorous(youmonst.data)); + const char *pmxnam = food_xname(otmp, FALSE); + if (!strncmpi(pmxnam, "the ", 4)) + pmxnam += 4; pline("%s%s %s!", type_is_pname(&mons[mnum]) - ? "" : the_unique_pm(&mons[mnum]) ? "The " : "This ", - food_xname(otmp, FALSE), + ? "" : the_unique_pm(&mons[mnum]) ? "The " : "This ", + pmxnam, + /* tiger reference is to TV ads for "Frosted Flakes", + breakfast cereal targeted at kids by "Tony the tiger" */ Hallucination ? (yummy ? ((u.umonnum == PM_TIGER) ? "is gr-r-reat" : "is gnarly") - : "is grody") - : (yummy ? "is delicious" : "tastes terrible")); + : palatable ? "is copacetic" + : "is grody") + : (yummy ? "tastes delicious" + : palatable ? "tastes okay" + : "tastes terrible")); } return retcode; diff --git a/src/objnam.c b/src/objnam.c index 24e444056..90f36a67f 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 objnam.c $NHDT-Date: 1462067746 2016/05/01 01:55:46 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.169 $ */ +/* NetHack 3.6 objnam.c $NHDT-Date: 1470272345 2016/08/04 00:59:05 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.177 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -3448,14 +3448,14 @@ typfnd: otmp->spe = 0; /* No spinach */ if (dead_species(mntmp, FALSE)) { otmp->corpsenm = NON_PM; /* it's empty */ - } else if (!(mons[mntmp].geno & G_UNIQ) + } else if ((!(mons[mntmp].geno & G_UNIQ) || wizard) && !(mvitals[mntmp].mvflags & G_NOCORPSE) && mons[mntmp].cnutrit != 0) { otmp->corpsenm = mntmp; } break; case CORPSE: - if (!(mons[mntmp].geno & G_UNIQ) + if ((!(mons[mntmp].geno & G_UNIQ) || wizard) && !(mvitals[mntmp].mvflags & G_NOCORPSE)) { if (mons[mntmp].msound == MS_GUARDIAN) mntmp = genus(mntmp, 1); From e03c14eeae10c4a49f933120722ac9329689d99a Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 3 Aug 2016 18:51:55 -0700 Subject: [PATCH 05/11] dungeon overview when escaping the dungeon Noticed while testing something. Final disclosure of dungeon overview showed "Level 1: <- You were here", which looked a bit odd when the game ended by climbing the stairs to escape the dungeon. Change the annotation when escaping to be "<- You left from here". 'Here' will usually be level 1, but not always. --- doc/fixes36.1 | 2 ++ src/dungeon.c | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index ee67cc371..cbf74c283 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -326,6 +326,8 @@ when poly'd into an engulfer which does digestion damage, a kill resulting in any corpse eaten by omnivorous hero always tasted "terrible" eating the corpse of a unique non-named monster (Wizard of Yendor, Oracle, Chromatic Dragon, others) gave "The the tastes ..." +when escaping the dungeon, change "you were here" annotation in dungeon + overview to "you left from here" Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/src/dungeon.c b/src/dungeon.c index 8a93b5e5c..78dd19d6c 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dungeon.c $NHDT-Date: 1462486971 2016/05/05 22:22:51 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.73 $ */ +/* NetHack 3.6 dungeon.c $NHDT-Date: 1470275509 2016/08/04 01:51:49 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.76 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2864,7 +2864,9 @@ boolean printdun; Sprintf(eos(buf), " \"%s\"", mptr->custom); if (on_level(&u.uz, &mptr->lev)) Sprintf(eos(buf), " <- You %s here.", - (!final || (final == 1 && how == ASCENDED)) ? "are" : "were"); + (!final || (final == 1 && how == ASCENDED)) ? "are" + : (final == 1 && how == ESCAPED) ? "left from" + : "were"); putstr(win, !final ? ATR_BOLD : 0, buf); if (mptr->flags.forgot) From 694b32cae267134598465ce3d3483483a9dac848 Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 4 Aug 2016 17:42:26 -0700 Subject: [PATCH 06/11] option parsing crash: 'playmode' without value Reported directly to devteam, specifying the playmode option without appending a value caused a segfault during options parsing. The argument passed to string_for_opt() ought to have been False for "not optional" to trigger a "bad syntax" message, but even then the playmode parsing needs to check for Null to prevent the crash. "Bad syntax" is awfully vague. In cases like this, we can be more precise. Now it will say "Missing value" instead. --- doc/fixes36.1 | 1 + src/options.c | 48 +++++++++++++++++++++++++++--------------------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index cbf74c283..d6031ea65 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -328,6 +328,7 @@ eating the corpse of a unique non-named monster (Wizard of Yendor, Oracle, Chromatic Dragon, others) gave "The the tastes ..." when escaping the dungeon, change "you were here" annotation in dungeon overview to "you left from here" +option parsing will crash if 'playmode' option is present without a value Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/src/options.c b/src/options.c index 1245c276b..4edc94fe0 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1461102048 2016/04/19 21:40:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.268 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1470357737 2016/08/05 00:42:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.279 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -500,6 +500,7 @@ static boolean initial, from_file; STATIC_DCL void FDECL(nmcpy, (char *, const char *, int)); STATIC_DCL void FDECL(escapes, (const char *, char *)); STATIC_DCL void FDECL(rejectoption, (const char *)); +STATIC_DCL void FDECL(badoptmsg, (const char *, const char *)); STATIC_DCL void FDECL(badoption, (const char *)); STATIC_DCL char *FDECL(string_for_opt, (char *, BOOLEAN_P)); STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *, BOOLEAN_P)); @@ -927,40 +928,43 @@ const char *optname; } STATIC_OVL void -badoption(opts) +badoptmsg(opts, reason) const char *opts; +const char *reason; /* "Bad syntax" or "Missing value" */ { + const char *linesplit = ""; + if (!initial) { if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1)) option_help(); else - pline("Bad syntax: %s. Enter \"?g\" for help.", opts); + pline("%s: %s. Enter \"?g\" for help.", reason, opts); return; - } #ifdef MAC - else + } else { return; #endif + } +#ifdef WIN32 + linesplit = "\n"; +#endif if (from_file) - raw_printf("Bad syntax in OPTIONS in %s: %s%s.\n", configfile, -#ifdef WIN32 - "\n", -#else - "", -#endif - opts); + raw_printf("%s in OPTIONS in %s: %s%s.\n", + reason, configfile, linesplit, opts); else - raw_printf("Bad syntax in NETHACKOPTIONS: %s%s.\n", -#ifdef WIN32 - "\n", -#else - "", -#endif - opts); + raw_printf("%s in NETHACKOPTIONS: %s%s.\n", + reason, linesplit, opts); wait_synch(); } +STATIC_OVL void +badoption(opts) +const char *opts; +{ + badoptmsg(opts, "Bad syntax"); +} + STATIC_OVL char * string_for_opt(opts, val_optional) char *opts; @@ -975,7 +979,7 @@ boolean val_optional; if (!colon || !*++colon) { if (!val_optional) - badoption(opts); + badoptmsg(opts, "Missing value"); return (char *) 0; } return colon; @@ -2700,7 +2704,9 @@ boolean tinitial, tfrom_file; bad_negation(fullname, FALSE); if (duplicate || negated) return; - op = string_for_opt(opts, TRUE); + op = string_for_opt(opts, FALSE); + if (!op) + return; if (!strncmpi(op, "normal", 6) || !strcmpi(op, "play")) { wizard = discover = FALSE; } else if (!strncmpi(op, "explore", 6) From 7f8e8293f96e5d31aea8ef914e12db7b4c1f29e3 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 5 Aug 2016 19:17:47 -0700 Subject: [PATCH 07/11] fix #H4468 - [no-]autopickup in shop Autopickup for pickup_types is disabled for unpaid shop goods, but always-pick-up autopickup_exception still picked things up, as did pickup_thrown for thrown objects. Now they'll only work in shops for no_charge items (dropped by hero and shk didn't want, or hero declined to sell). costly_spot() was being recalculated for every item which passed pickup_types. This changes autopickup to check it once for a given autopickup operation and cache the result. [Whenever the hero moves, a room entry check is performed. That ought to be extended to cache costly_spot() for in iflags or u.] --- doc/fixes36.1 | 2 ++ src/pickup.c | 48 +++++++++++++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index d6031ea65..610cb43cb 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -346,6 +346,8 @@ fix for long lines in config file (28-Jan-2016) made 'O' command's 'list' and message types, and autopickup exceptions subject to buffer overflow when picking a destination for #jump, '$' to show valid dest. is more accurate enchant armor gave "your pair of boots/gloves glow", should have been "glows" +when autopickup is overridden in a shop, always-pick-up exceptions and + pickup_thrown still picked unpaid items up Platform- and/or Interface-Specific Fixes diff --git a/src/pickup.c b/src/pickup.c index 0f8b5b5d4..4b42be708 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pickup.c $NHDT-Date: 1461919368 2016/04/29 08:42:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.177 $ */ +/* NetHack 3.6 pickup.c $NHDT-Date: 1470449858 2016/08/06 02:17:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.184 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -21,7 +21,7 @@ STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *)); #if 0 /* not used */ STATIC_DCL boolean FDECL(allow_cat_no_uchain, (struct obj *)); #endif -STATIC_DCL boolean FDECL(autopick_testobj, (struct obj *)); +STATIC_DCL boolean FDECL(autopick_testobj, (struct obj *, BOOLEAN_P)); STATIC_DCL int FDECL(autopick, (struct obj *, int, menu_item **)); STATIC_DCL int FDECL(count_categories, (struct obj *, int)); STATIC_DCL long FDECL(carry_count, (struct obj *, struct obj *, long, @@ -685,30 +685,42 @@ boolean grab; /* forced pickup, rather than forced leave behind? */ /* * Does the text description of this match an exception? */ - char *objdesc = makesingular(doname(obj)); struct autopickup_exception *ape = (grab) ? iflags.autopickup_exceptions[AP_GRAB] : iflags.autopickup_exceptions[AP_LEAVE]; - while (ape) { - if (regex_match(objdesc, ape->regex)) - return TRUE; - ape = ape->next; + if (ape) { + char *objdesc = makesingular(doname(obj)); + + while (ape) { + if (regex_match(objdesc, ape->regex)) + return TRUE; + ape = ape->next; + } } return FALSE; } -boolean -autopick_testobj(otmp) +STATIC_OVL boolean +autopick_testobj(otmp, calc_costly) struct obj *otmp; +boolean calc_costly; { + static boolean costly = FALSE; const char *otypes = flags.pickup_types; - /* pick if in pickup_types and not unpaid item in shop */ - boolean pickit = ((!*otypes || index(otypes, otmp->oclass)) - && !(otmp->where == OBJ_FLOOR - && !otmp->no_charge - && isok(otmp->ox, otmp->oy) - && costly_spot(otmp->ox, otmp->oy))); + boolean pickit; + + /* calculate 'costly' just once for a given autopickup operation */ + if (calc_costly) + costly = (otmp->where == OBJ_FLOOR + && costly_spot(otmp->ox, otmp->oy)); + + /* first check: reject if an unpaid item in a shop */ + if (costly && !otmp->no_charge) + return FALSE; + + /* check for pickup_types */ + pickit = (!*otypes || index(otypes, otmp->oclass)); /* check for "always pick up */ if (!pickit) pickit = is_autopickup_exception(otmp, TRUE); @@ -737,17 +749,19 @@ menu_item **pick_list; /* list of objects and counts to pick up */ menu_item *pi; /* pick item */ struct obj *curr; int n; + boolean check_costly = TRUE; /* first count the number of eligible items */ for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) { - if (autopick_testobj(curr)) + if (autopick_testobj(curr, check_costly)) ++n; + check_costly = FALSE; /* only need to check once per autopickup */ } if (n) { *pick_list = pi = (menu_item *) alloc(sizeof (menu_item) * n); for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) { - if (autopick_testobj(curr)) { + if (autopick_testobj(curr, FALSE)) { pi[n].item.a_obj = curr; pi[n].count = curr->quan; n++; From 62fd7962713f629543be062aa9d95379d32a7796 Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 6 Aug 2016 19:30:44 -0700 Subject: [PATCH 08/11] fix #H4472 & #H4473 - incorrect total_tiles_used The value calculated for total_tiles_used never got adjusted for displaying statues-as-monsters. The most common configuration(s) using tiles don't care, but the combination of X11 plus USE_XPM needs an accurate value there. --- doc/fixes36.1 | 4 ++++ win/share/tilemap.c | 11 ++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 610cb43cb..d1bf9973a 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -353,6 +353,8 @@ when autopickup is overridden in a shop, always-pick-up exceptions and Platform- and/or Interface-Specific Fixes ----------------------------------------- tiles: wrinkled spellbook had a spurious brown pixel on far right edge of tile +tiles: when statues are displayed as corresponding monsters, total_tiles_used + in generated src/tile.c had incorrect value tty: M-N gave "Unknown command 'M-" with "'." finishing the sentence on the line below it, leaving bogus '.' displayed on the top row of the map tty: specifying all four of role, race, gender, and alignment still prompted @@ -399,6 +401,8 @@ X11: make the extended command menu be easier to use and look a little nicer X11: make the getline text entry widget display a bigger text entry area X11: color didn't work when the map was displayed as text rather than tiles X11: use grayscale monster tiles for statues +X11/USE_XPM: [post-3.6.0 issue] the 'tiles' bug of incorrect total_tiles_used + for STATUES_LOOK_LIKE_MONSTERS broke XPM manipulation of tiles data General New Features diff --git a/win/share/tilemap.c b/win/share/tilemap.c index cae25fdfb..a14d9203e 100644 --- a/win/share/tilemap.c +++ b/win/share/tilemap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 tilemap.c $NHDT-Date: 1465163425 2016/06/05 21:50:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.30 $ */ +/* NetHack 3.6 tilemap.c $NHDT-Date: 1470537037 2016/08/07 02:30:37 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.32 $ */ /* NetHack may be freely redistributed. See license for details. */ /* @@ -464,8 +464,11 @@ FILE *ofp; fprintf(ofp, "%s\n", epilog[i]); } - fprintf(ofp, "\nint total_tiles_used = %d;\n", start); lastothtile = start - 1; +#ifdef STATUES_LOOK_LIKE_MONSTERS + start = laststatuetile + 1; +#endif + fprintf(ofp, "\nint total_tiles_used = %d;\n", start); } int @@ -500,7 +503,9 @@ main() fprintf(ofp, "\n#define MAXMONTILE %d\n", lastmontile); fprintf(ofp, "#define MAXOBJTILE %d\n", lastobjtile); fprintf(ofp, "#define MAXOTHTILE %d\n", lastothtile); - +#ifdef STATUES_LOOK_LIKE_MONSTERS + fprintf(ofp, "/* #define MAXSTATUETILE %d */\n", laststatuetile); +#endif fprintf(ofp, "\n/*tile.c*/\n"); fclose(ofp); From a72d19b9056bfbe3bff7f13c426606381f765a69 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 10 Aug 2016 02:04:09 -0700 Subject: [PATCH 09/11] fix #H4475 - shop message about disenchanted item drain_item() always assumed player was responsible, so called costly_alteration() to adjust shop price of disenchanted item. If it was unpaid and the effect was caused by a disenchanter attack rather than by the hero, the feedback was nonsensical. This also lets a disenchanter hit worn rings, amulet, or blindfold if no armor gets targetted. Amulets, blindfolds, and most rings have no charge to be drained, but several types of rings do. --- doc/fixes36.1 | 2 ++ include/extern.h | 4 ++-- src/mhitm.c | 4 ++-- src/mhitu.c | 28 +++++++++++++++++++++++++--- src/uhitm.c | 10 +++++----- src/zap.c | 21 ++++++++++++++------- 6 files changed, 50 insertions(+), 19 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index d1bf9973a..d827071ae 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -329,6 +329,8 @@ eating the corpse of a unique non-named monster (Wizard of Yendor, Oracle, when escaping the dungeon, change "you were here" annotation in dungeon overview to "you left from here" option parsing will crash if 'playmode' option is present without a value +any item drained of enchantment was blamed on the player as far as shop + billing was concerned, even if caused by disenchanter attack Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 4781d1b9c..086543287 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1461967848 2016/04/29 22:10:48 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.558 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1470819839 2016/08/10 09:03:59 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.569 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2771,7 +2771,7 @@ E struct monst *FDECL(montraits, (struct obj *, coord *)); E struct monst *FDECL(revive, (struct obj *, BOOLEAN_P)); E int FDECL(unturn_dead, (struct monst *)); E void FDECL(cancel_item, (struct obj *)); -E boolean FDECL(drain_item, (struct obj *)); +E boolean FDECL(drain_item, (struct obj *, BOOLEAN_P)); E struct obj *FDECL(poly_obj, (struct obj *, int)); E boolean FDECL(obj_resists, (struct obj *, int, int)); E boolean FDECL(obj_shudders, (struct obj *)); diff --git a/src/mhitm.c b/src/mhitm.c index e92b6e287..9836136a1 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mhitm.c $NHDT-Date: 1456992461 2016/03/03 08:07:41 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.86 $ */ +/* NetHack 3.6 mhitm.c $NHDT-Date: 1470819842 2016/08/10 09:04:02 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.92 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1524,7 +1524,7 @@ int mdead; goto assess_dmg; case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ if (mhit && !mdef->mcan && otmp) { - (void) drain_item(otmp); + (void) drain_item(otmp, FALSE); /* No message */ } break; diff --git a/src/mhitu.c b/src/mhitu.c index e07718fda..1cdd7bce7 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mhitu.c $NHDT-Date: 1456992469 2016/03/03 08:07:49 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.136 $ */ +/* NetHack 3.6 mhitu.c $NHDT-Date: 1470819843 2016/08/10 09:04:03 $ $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. */ @@ -1597,7 +1597,27 @@ register struct attack *mattk; if (uncancelled) { struct obj *obj = some_armor(&youmonst); - if (drain_item(obj)) { + if (!obj) { + /* some rings are susceptible; + amulets and blindfolds aren't (at present) */ + switch (rn2(5)) { + case 0: + break; + case 1: + obj = uright; + break; + case 2: + obj = uleft; + break; + case 3: + obj = uamul; + break; + case 4: + obj = ublindf; + break; + } + } + if (drain_item(obj, FALSE)) { pline("%s less effective.", Yobjnam2(obj, "seem")); } } @@ -2691,7 +2711,9 @@ register struct attack *mattk; } case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ if (otmp) { - (void) drain_item(otmp); + /* by_you==True: passive counterattack to hero's action + is hero's fault */ + (void) drain_item(otmp, TRUE); /* No message */ } return 1; diff --git a/src/uhitm.c b/src/uhitm.c index 1217b5b48..832390694 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 uhitm.c $NHDT-Date: 1460103141 2016/04/08 08:12:21 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.156 $ */ +/* NetHack 3.6 uhitm.c $NHDT-Date: 1470819843 2016/08/10 09:04:03 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.164 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2537,12 +2537,12 @@ boolean wep_was_destroyed; */ void passive_obj(mon, obj, mattk) -register struct monst *mon; -register struct obj *obj; /* null means pick uwep, uswapwep or uarmg */ +struct monst *mon; +struct obj *obj; /* null means pick uwep, uswapwep or uarmg */ struct attack *mattk; /* null means we find one internally */ { struct permonst *ptr = mon->data; - register int i; + int i; /* if caller hasn't specified an object, use uwep, uswapwep or uarmg */ if (!obj) { @@ -2589,7 +2589,7 @@ struct attack *mattk; /* null means we find one internally */ break; case AD_ENCH: if (!mon->mcan) { - if (drain_item(obj) && carried(obj) + if (drain_item(obj, TRUE) && carried(obj) && (obj->known || obj->oclass == ARMOR_CLASS)) { pline("%s less effective.", Yobjnam2(obj, "seem")); } diff --git a/src/zap.c b/src/zap.c index ea246aabb..927bcb1dc 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 zap.c $NHDT-Date: 1464163779 2016/05/25 08:09:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.258 $ */ +/* NetHack 3.6 zap.c $NHDT-Date: 1470819844 2016/08/10 09:04:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.263 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1062,8 +1062,9 @@ register struct obj *obj; * possibly carried by you or a monster */ boolean -drain_item(obj) -register struct obj *obj; +drain_item(obj, by_you) +struct obj *obj; +boolean by_you; { boolean u_ring; @@ -1078,7 +1079,8 @@ register struct obj *obj; return FALSE; /* Charge for the cost of the object */ - costly_alteration(obj, COST_DRAIN); + if (by_you) + costly_alteration(obj, COST_DRAIN); /* Drain the object and any implied effects */ obj->spe--; @@ -1110,6 +1112,10 @@ register struct obj *obj; if ((obj->owornmask & W_RING) && u_ring) u.udaminc--; break; + case RIN_PROTECTION: + if (u_ring) + context.botl = 1; /* bot() will recalc u.uac */ + break; case HELM_OF_BRILLIANCE: if ((obj->owornmask & W_ARMH) && (obj == uarmh)) { ABON(A_INT)--; @@ -1123,10 +1129,11 @@ register struct obj *obj; context.botl = 1; } break; - case RIN_PROTECTION: - context.botl = 1; + default: break; } + if (context.botl) + bot(); if (carried(obj)) update_inventory(); return TRUE; @@ -1935,7 +1942,7 @@ struct obj *obj, *otmp; #endif break; case SPE_DRAIN_LIFE: - (void) drain_item(obj); + (void) drain_item(obj, TRUE); break; case WAN_TELEPORTATION: case SPE_TELEPORT_AWAY: From b848f2732d0ea801bf38873c201d65e6fde7feb3 Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 11 Aug 2016 18:53:52 -0700 Subject: [PATCH 10/11] fix #H4476 - monster class via member of class Blessed genocide of "titans" wiped out all quadrupeds because "titan" is a prefix of "titanothere". After class letters and class descriptions have been rejected, Have name_to_monclass() resort to name_to_mon() instead of doing its own less detailed name matching. --- doc/fixes36.1 | 3 +++ src/mondata.c | 18 +++++++----------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index d827071ae..b574d4816 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -331,6 +331,9 @@ when escaping the dungeon, change "you were here" annotation in dungeon option parsing will crash if 'playmode' option is present without a value any item drained of enchantment was blamed on the player as far as shop billing was concerned, even if caused by disenchanter attack +if user supplied a specific monster name when asked to choose a monster class, + first prefix match was picked rather than best match ("titan" yielded + S_quadruped due to being preceded by "titanothere" in mons[]) Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/src/mondata.c b/src/mondata.c index 0e924f3fc..a9d054f4c 100644 --- a/src/mondata.c +++ b/src/mondata.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mondata.c $NHDT-Date: 1446604115 2015/11/04 02:28:35 $ $NHDT-Branch: master $:$NHDT-Revision: 1.58 $ */ +/* NetHack 3.6 mondata.c $NHDT-Date: 1470966820 2016/08/12 01:53:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.61 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -855,16 +855,12 @@ int *mndx_p; if ((p = strstri(x, in_str)) != 0 && (p == x || *(p - 1) == ' ')) return i; } - /* check individual species names; not as thorough as mon_to_name() - but our caller can call that directly if desired */ - for (i = LOW_PM; i < NUMMONS; i++) { - x = mons[i].mname; - if ((p = strstri(x, in_str)) != 0 - && (p == x || *(p - 1) == ' ')) { - if (mndx_p) - *mndx_p = i; - return mons[i].mlet; - } + /* check individual species names */ + i = name_to_mon(in_str); + if (i != NON_PM) { + if (mndx_p) + *mndx_p = i; + return mons[i].mlet; } } return 0; From a16000d80a293ce14f37da16240da71834e0168d Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 13 Aug 2016 11:17:32 -0700 Subject: [PATCH 11/11] fix #H4482 - "a some corpses" farlook was changed (end of December) to use doname instead of xname to yield more info for items which had already been seen up close, but it gave away info about ones which hadn't. So doname was changed (end of April) to use "some" instead of precise quantity (when the quantity is greater than 1) for the latter, but that doesn't work well with corpse_xname() when the hero is blind, yielding "a some corpses". While testing the first fix attempt, I noticed that pickup gave "you can only lift some of the some corpses". This fix is far from perfect. farlook can still say "some s" but lookhere and pickup always say "N s". Picking up a stack while blind will show "N s" in inventory display, but dropping it while still blind will revert to "some s" for farlook. --- doc/fixes36.1 | 4 +++ include/extern.h | 3 +- src/objnam.c | 75 +++++++++++++++++++++++++++++++++--------------- src/pager.c | 4 +-- 4 files changed, 60 insertions(+), 26 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index b574d4816..96aba09c7 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -345,6 +345,10 @@ rings covered by non-cursed gloves not listed as 'R' candidates in baalz_fixup, move any monster away from the two fake pool spots switching farlook from xname to doname was giving away information for items located via object detection (quantity of detected gold) +changing doname to use "some" instead of precise quantity when an item's + dknown flag is not set could result in blind hero getting + "There is a some jackal corpses here. Eat one?" and + "You can only lift some of the some jackal corpses. Continue?" catch up win/Qt/qt_win.cpp on 18-Dec-2015 change to formatkiller() fix for long lines in config file (28-Jan-2016) made 'O' command's 'list' and 'remove' menu choices in interactive handling for menu colorings, diff --git a/include/extern.h b/include/extern.h index 086543287..c5ff34441 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1470819839 2016/08/10 09:03:59 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.569 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1471112244 2016/08/13 18:17:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.570 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1606,6 +1606,7 @@ E boolean FDECL(the_unique_pm, (struct permonst *)); E boolean FDECL(erosion_matters, (struct obj *)); E char *FDECL(doname, (struct obj *)); E char *FDECL(doname_with_price, (struct obj *)); +E char *FDECL(doname_vague_quan, (struct obj *)); E boolean FDECL(not_fully_identified, (struct obj *)); E char *FDECL(corpse_xname, (struct obj *, const char *, unsigned)); E char *FDECL(cxname, (struct obj *)); diff --git a/src/objnam.c b/src/objnam.c index 90f36a67f..d395ea747 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 objnam.c $NHDT-Date: 1470272345 2016/08/04 00:59:05 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.177 $ */ +/* NetHack 3.6 objnam.c $NHDT-Date: 1471112245 2016/08/13 18:17:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.178 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -17,6 +17,7 @@ STATIC_DCL char *NDECL(nextobuf); STATIC_DCL void FDECL(releaseobuf, (char *)); STATIC_DCL char *FDECL(minimal_xname, (struct obj *)); STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *)); +STATIC_DCL char *FDECL(doname_base, (struct obj *obj, unsigned)); STATIC_DCL boolean FDECL(singplur_lookup, (char *, char *, BOOLEAN_P, const char *const *)); STATIC_DCL char *FDECL(singplur_compound, (char *)); @@ -580,7 +581,7 @@ unsigned cxn_flags; /* bitmask of CXN_xxx values */ brown potion -- if oc_name_known not set potion of object detection -- if discovered */ -static char * +STATIC_OVL char * minimal_xname(obj) struct obj *obj; { @@ -756,12 +757,17 @@ struct obj *obj; return FALSE; } -static char * -doname_base(obj, with_price) -register struct obj *obj; -boolean with_price; +#define DONAME_WITH_PRICE 1 +#define DONAME_VAGUE_QUAN 2 + +STATIC_OVL char * +doname_base(obj, doname_flags) +struct obj *obj; +unsigned doname_flags; { - boolean ispoisoned = FALSE; + boolean ispoisoned = FALSE, + with_price = (doname_flags & DONAME_WITH_PRICE) != 0, + vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0; boolean known, dknown, cknown, bknown, lknown; int omndx = obj->corpsenm; char prefix[PREFIX]; @@ -792,7 +798,7 @@ boolean with_price; } if (obj->quan != 1L) { - if (dknown) + if (dknown || !vague_quan) Sprintf(prefix, "%ld ", obj->quan); else Strcpy(prefix, "some "); @@ -816,11 +822,11 @@ boolean with_price; making the prefix be redundant; note that 'known' flag isn't set when emptiness gets discovered because then charging magic would yield known number of new charges) */ - && (obj->otyp == BAG_OF_TRICKS + && ((obj->otyp == BAG_OF_TRICKS) ? (obj->spe == 0 && !obj->known) /* not bag of tricks: empty if container which has no contents */ - : (Is_container(obj) || obj->otyp == STATUE) - && !Has_contents(obj))) + : ((Is_container(obj) || obj->otyp == STATUE) + && !Has_contents(obj)))) Strcat(prefix, "empty "); if (bknown && obj->oclass != COIN_CLASS @@ -872,11 +878,9 @@ boolean with_price; Strcat(prefix, "greased "); if (cknown && Has_contents(obj)) { - /* we count all objects (obj->quantity); perhaps we should - count separate stacks instead (or even introduce a user - preference option to choose between the two alternatives) - since it's somewhat odd so see "containing 1002 items" - when there are 2 scrolls plus 1000 gold pieces */ + /* we count the number of separate stacks, which corresponds + to the number of inventory slots needed to be able to take + everything out if no merges occur */ long itemcount = count_contents(obj, FALSE, FALSE, TRUE); Sprintf(eos(bp), " containing %ld item%s", itemcount, @@ -960,8 +964,13 @@ boolean with_price; if (obj->oeaten) Strcat(prefix, "partly eaten "); if (obj->otyp == CORPSE) { - Sprintf(prefix, "%s ", - corpse_xname(obj, prefix, CXN_ARTICLE | CXN_NOCORPSE)); + /* (quan == 1) => want corpse_xname() to supply article, + (quan != 1) => already have count or "some" as prefix; + "corpse" is already in the buffer returned by xname() */ + unsigned cxarg = (((obj->quan != 1L) ? 0 : CXN_ARTICLE) + | CXN_NOCORPSE); + + Sprintf(prefix, "%s ", corpse_xname(obj, prefix, cxarg)); } else if (obj->otyp == EGG) { #if 0 /* corpses don't tell if they're stale either */ if (known && stale_egg(obj)) @@ -1074,23 +1083,43 @@ boolean with_price; char * doname(obj) -register struct obj *obj; +struct obj *obj; { - return doname_base(obj, FALSE); + return doname_base(obj, (unsigned) 0); } /* Name of object including price. */ char * doname_with_price(obj) -register struct obj *obj; +struct obj *obj; { - return doname_base(obj, TRUE); + return doname_base(obj, DONAME_WITH_PRICE); +} + +/* "some" instead of precise quantity if obj->dknown not set */ +char * +doname_vague_quan(obj) +struct obj *obj; +{ + /* Used by farlook. + * If it hasn't been seen up close and quantity is more than one, + * use "some" instead of the quantity: "some gold pieces" rather + * than "25 gold pieces". This is suboptimal, to put it mildly, + * because lookhere and pickup report the precise amount. + * Picking the item up while blind also shows the precise amount + * for inventory display, then dropping it while still blind leaves + * obj->dknown unset so the count reverts to "some" for farlook. + * + * TODO: add obj->qknown flag for 'quantity known' on stackable + * items; it could overlay obj->cknown since no containers stack. + */ + return doname_base(obj, DONAME_VAGUE_QUAN); } /* used from invent.c */ boolean not_fully_identified(otmp) -register struct obj *otmp; +struct obj *otmp; { /* gold doesn't have any interesting attributes [yet?] */ if (otmp->oclass == COIN_CLASS) diff --git a/src/pager.c b/src/pager.c index b00c425a9..de932073d 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pager.c $NHDT-Date: 1466638086 2016/06/22 23:28:06 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.111 $ */ +/* NetHack 3.6 pager.c $NHDT-Date: 1471112245 2016/08/13 18:17:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.112 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -203,7 +203,7 @@ int x, y, glyph; if (otmp) { Strcpy(buf, (otmp->otyp != STRANGE_OBJECT) - ? distant_name(otmp, doname) + ? distant_name(otmp, doname_vague_quan) : obj_descr[STRANGE_OBJECT].oc_name); if (fakeobj) dealloc_obj(otmp), otmp = 0;