diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 3ca48f1af..e5b0417bf 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.228 $ $NHDT-Date: 1591017415 2020/06/01 13:16:55 $ +$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.229 $ $NHDT-Date: 1591178395 2020/06/03 09:59:55 $ General Fixes and Modified Features ----------------------------------- @@ -192,6 +192,8 @@ change mkclass() to usually honor (always honor for L class) the hell-only and (nor master lich there unless demilich gets a potion of gain level) thieving monster could be killed while hero was removing armor, triggering warning "stealarm(): dead monster stealing" when taking-off finished +petrifying a long worm and then reanimating it handled tail incorrectly; + with sanity_check On, X coordinate of head segment was reported as 0 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/include/hack.h b/include/hack.h index 4ea786b33..44ee8c4a5 100644 --- a/include/hack.h +++ b/include/hack.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 hack.h $NHDT-Date: 1580600495 2020/02/01 23:41:35 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.128 $ */ +/* NetHack 3.6 hack.h $NHDT-Date: 1591178395 2020/06/03 09:59:55 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.138 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Pasi Kallinen, 2017. */ /* NetHack may be freely redistributed. See license for details. */ @@ -305,10 +305,11 @@ typedef struct sortloot_item Loot; #define MM_EDOG 0x001000L /* add edog structure */ #define MM_ASLEEP 0x002000L /* monsters should be generated asleep */ #define MM_NOGRP 0x004000L /* suppress creation of monster groups */ +#define MM_NOTAIL 0x008000L /* if a long worm, don't give it a tail */ /* if more MM_ flag masks are added, skip or renumber the GP_ one(s) */ -#define GP_ALLOW_XY 0x008000L /* [actually used by enexto() to decide whether +#define GP_ALLOW_XY 0x010000L /* [actually used by enexto() to decide whether * to make an extra call to goodpos()] */ -#define GP_ALLOW_U 0x010000L /* don't reject hero's location */ +#define GP_ALLOW_U 0x020000L /* don't reject hero's location */ /* flags for make_corpse() and mkcorpstat() */ #define CORPSTAT_NONE 0x00 diff --git a/src/makemon.c b/src/makemon.c index 7ac6924c8..b325c64a7 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 makemon.c $NHDT-Date: 1590879611 2020/05/30 23:00:11 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.172 $ */ +/* NetHack 3.6 makemon.c $NHDT-Date: 1591178397 2020/06/03 09:59:57 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.173 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1124,10 +1124,11 @@ long mmflags; struct monst fakemon; coord cc; int mndx, mcham, ct, mitem; - boolean anymon = (!ptr); - boolean byyou = (x == u.ux && y == u.uy); - boolean allow_minvent = ((mmflags & NO_MINVENT) == 0); - boolean countbirth = ((mmflags & MM_NOCOUNTBIRTH) == 0); + boolean anymon = !ptr, + byyou = (x == u.ux && y == u.uy), + allow_minvent = ((mmflags & NO_MINVENT) == 0), + countbirth = ((mmflags & MM_NOCOUNTBIRTH) == 0), + allowtail = ((mmflags & MM_NOTAIL) == 0); unsigned gpflags = (mmflags & MM_IGNOREWATER) ? MM_IGNOREWATER : 0; fakemon = cg.zeromonst; @@ -1348,7 +1349,7 @@ long mmflags; mtmp->mpeaceful = mtmp->mtame = FALSE; } if (mndx == PM_LONG_WORM && (mtmp->wormno = get_wormno()) != 0) { - initworm(mtmp, rn2(5)); + initworm(mtmp, allowtail ? rn2(5) : 0); if (count_wsegs(mtmp)) place_worm_tail_randomly(mtmp, x, y); } diff --git a/src/mkobj.c b/src/mkobj.c index dc14c1a50..4ef6852f2 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mkobj.c $NHDT-Date: 1590870787 2020/05/30 20:33:07 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.179 $ */ +/* NetHack 3.6 mkobj.c $NHDT-Date: 1591178399 2020/06/03 09:59:59 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.180 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1597,6 +1597,9 @@ struct monst *mtmp; mtmp2->minvent = (struct obj *) 0; if (mtmp->mextra) copy_mextra(mtmp2, mtmp); + /* if mtmp is a long worm with segments, its saved traits will + be one without any segments */ + mtmp2->wormno = 0; } return obj; } diff --git a/src/worm.c b/src/worm.c index 3f173a134..dab10f926 100644 --- a/src/worm.c +++ b/src/worm.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 worm.c $NHDT-Date: 1580633722 2020/02/02 08:55:22 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.43 $ */ +/* NetHack 3.6 worm.c $NHDT-Date: 1591178400 2020/06/03 10:00:00 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.45 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -126,9 +126,9 @@ int wseg_count; } else { wtails[wnum] = wheads[wnum] = seg = newseg(); seg->nseg = (struct wseg *) 0; - seg->wx = worm->mx; - seg->wy = worm->my; } + seg->wx = worm->mx; + seg->wy = worm->my; wgrowtime[wnum] = 0L; } @@ -144,14 +144,13 @@ toss_wsegs(curr, display_update) struct wseg *curr; boolean display_update; { - struct wseg *seg; + struct wseg *nxtseg; while (curr) { - seg = curr->nseg; + nxtseg = curr->nseg; - /* remove from level.monsters[][] */ - - /* need to check curr->wx for genocided while migrating_mon */ + /* remove from level.monsters[][]; + need to check curr->wx for genocided while migrating_mon */ if (curr->wx) { remove_monster(curr->wx, curr->wy); @@ -162,7 +161,7 @@ boolean display_update; /* free memory used by the segment */ dealloc_seg(curr); - curr = seg; + curr = nxtseg; } } @@ -313,7 +312,6 @@ struct monst *worm; int wnum = worm->wormno; worm->wormno = 0; - /* This will also remove the real monster (ie 'w') from the its * position in level.monsters[][]. */ @@ -505,11 +503,9 @@ boolean use_detection_glyph; int what_tail = what_mon(PM_LONG_WORM_TAIL, newsym_rn2); while (curr != wheads[worm->wormno]) { - num = use_detection_glyph - ? detected_monnum_to_glyph(what_tail) - : (worm->mtame - ? petnum_to_glyph(what_tail) - : monnum_to_glyph(what_tail)); + num = use_detection_glyph ? detected_monnum_to_glyph(what_tail) + : worm->mtame ? petnum_to_glyph(what_tail) + : monnum_to_glyph(what_tail); show_glyph(curr->wx, curr->wy, num); curr = curr->nseg; } @@ -612,6 +608,7 @@ NHFILE *nhfp; * place_wsegs() * * Place the segments of the given worm. Called from restore.c + * and from replmon() in mon.c. * If oldworm is not NULL, assumes the oldworm segments are on map * in the same location as worm segments */ @@ -622,40 +619,63 @@ struct monst *worm, *oldworm; struct wseg *curr = wtails[worm->wormno]; while (curr != wheads[worm->wormno]) { - xchar x = curr->wx; - xchar y = curr->wy; + xchar x = curr->wx, y = curr->wy; + struct monst *mtmp = m_at(x, y); + + if (oldworm && mtmp == oldworm) + remove_monster(x, y); + else if (mtmp) + impossible("placing worm seg <%d,%d> over another mon", x, y); + else if (oldworm) + impossible("replacing worm seg <%d,%d> on empty spot", x, y); - if (oldworm) { - if (m_at(x,y) == oldworm) - remove_monster(x, y); - else - impossible("placing worm seg <%i,%i> over another mon", x, y); - } place_worm_seg(worm, x, y); curr = curr->nseg; } + /* head segment is co-located with worm itself so not placed on the map */ + curr->wx = worm->mx, curr->wy = worm->my; } +/* called from mon_sanity_check(mon.c) */ void sanity_check_worm(worm) struct monst *worm; { struct wseg *curr; + int wnum, x, y; - if (!worm) - panic("no worm!"); - if (!worm->wormno) - panic("not a worm?!"); + if (!worm) { + impossible("worm_sanity: null monster!"); + return; + } + /* note: wormno can't be less than 0 (unsigned bit field) and can't + be greater that MAX_NUM_WORMS - 1 (which uses all available bits) + so checking for 0 is all we can manage for wormno validation; + since caller has already done that, this is rather pointless... */ + if (!worm->wormno) { + impossible("worm_sanity: not a worm!"); + return; + } - curr = wtails[worm->wormno]; + wnum = worm->wormno; + if (!wtails[wnum] || !wheads[wnum]) { + impossible("wormno %d is set without proper tail", wnum); + return; + } + /* if worm is migrating, we can't check its segments against the map */ + if (!worm->mx) + return; + + curr = wtails[wnum]; + while (curr != wheads[wnum]) { + x = curr->wx, y = curr->wy; + if (!isok(x, y)) + impossible("worm seg not isok <%d,%d>", x, y); + else if (g.level.monsters[x][y] != worm) + impossible("mon (%s) at seg location is not worm (%s)", + fmt_ptr((genericptr_t) g.level.monsters[x][y]), + fmt_ptr((genericptr_t) worm)); - while (curr != wheads[worm->wormno]) { - if (curr->wx) { - if (!isok(curr->wx, curr->wy)) - panic("worm seg not isok"); - if (g.level.monsters[curr->wx][curr->wy] != worm) - panic("worm not at seg location"); - } curr = curr->nseg; } } diff --git a/src/zap.c b/src/zap.c index 73dc524a0..dfc15217d 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 zap.c $NHDT-Date: 1589491666 2020/05/14 21:27:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.340 $ */ +/* NetHack 3.6 zap.c $NHDT-Date: 1591178401 2020/06/03 10:00:01 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.341 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -586,6 +586,11 @@ boolean adjacentok; /* False: at obj's spot only, True: nearby is allowed */ return (struct monst *) 0; mtmp = makemon(mtmp2->data, cc->x, cc->y, (NO_MINVENT | MM_NOWAIT | MM_NOCOUNTBIRTH + /* in case mtmp2 is a long worm; saved traits for + long worm don't include tail segments so don't + give mtmp any; it will be given a new 'wormno' + though unless those are exhausted */ + | MM_NOTAIL | (adjacentok ? MM_ADJACENTOK : 0))); if (!mtmp) { /* mtmp2 is a copy of obj's object->oextra->omonst extension