From cf89253358a86372c41e1c7c55b240ceea64524a Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 11 Dec 2018 01:27:20 -0800 Subject: [PATCH 1/4] an() bit --- src/objnam.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objnam.c b/src/objnam.c index ce828c355..6a805852d 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 objnam.c $NHDT-Date: 1544492043 2018/12/11 01:34:03 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.229 $ */ +/* NetHack 3.6 objnam.c $NHDT-Date: 1544520422 2018/12/11 09:27:02 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.230 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1220,7 +1220,7 @@ unsigned doname_flags; Strcpy(tmpbuf, prefix + 2); /* set prefix[] to "", "a ", or "an " */ (void) just_an(prefix, *tmpbuf ? tmpbuf : bp); - /* apprend remainder of original prefix */ + /* append remainder of original prefix */ Strcat(prefix, tmpbuf); } @@ -1629,7 +1629,7 @@ const char *str; impossible("Alphabet soup: 'an(%s)'.", str ? "\"\"" : ""); return strcpy(buf, "an []"); } - just_an(buf, str); + (void) just_an(buf, str); return strcat(buf, str); } From ce7c9d5077aff263b59f7e8d59eb7339793a88b9 Mon Sep 17 00:00:00 2001 From: Bart House Date: Tue, 11 Dec 2018 20:52:07 -0800 Subject: [PATCH 2/4] Terminal font when not fitting to screen. Consolas for fit to screen. --- win/win32/mhmap.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/win/win32/mhmap.c b/win/win32/mhmap.c index 75155a73f..b883cd7bd 100644 --- a/win/win32/mhmap.c +++ b/win/win32/mhmap.c @@ -15,7 +15,8 @@ #include "color.h" #include "patchlevel.h" -#define NHMAP_FONT_NAME TEXT("Courier New") +#define NHMAP_FONT_NAME TEXT("Terminal") +#define NHMAP_TTFONT_NAME TEXT("Consolas") #define MAXWINDOWTEXT 255 #define CURSOR_BLINK_INTERVAL 1000 // milliseconds @@ -182,24 +183,38 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) LOGFONT lgfnt; ZeroMemory(&lgfnt, sizeof(lgfnt)); - lgfnt.lfHeight = -data->yBackTile; // height of font - lgfnt.lfWidth = 0; // average character width + if (data->bFitToScreenMode) { + lgfnt.lfHeight = -data->yBackTile; // height of font + lgfnt.lfWidth = 0; // average character width + } else { + lgfnt.lfHeight = -data->yBackTile; // height of font + lgfnt.lfWidth = -data->xBackTile; // average character width + } lgfnt.lfEscapement = 0; // angle of escapement lgfnt.lfOrientation = 0; // base-line orientation angle - lgfnt.lfWeight = FW_SEMIBOLD; // font weight + lgfnt.lfWeight = FW_NORMAL; // font weight lgfnt.lfItalic = FALSE; // italic attribute option lgfnt.lfUnderline = FALSE; // underline attribute option lgfnt.lfStrikeOut = FALSE; // strikeout attribute option lgfnt.lfCharSet = mswin_charset(); // character set identifier lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS; // output precision lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision - lgfnt.lfQuality = NONANTIALIASED_QUALITY; // output quality + if (data->bFitToScreenMode) { + lgfnt.lfQuality = ANTIALIASED_QUALITY; // output quality + } else { + lgfnt.lfQuality = NONANTIALIASED_QUALITY; // output quality + } if (iflags.wc_font_map && *iflags.wc_font_map) { lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family NH_A2W(iflags.wc_font_map, lgfnt.lfFaceName, LF_FACESIZE); } else { - lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family - NH_A2W(NHMAP_FONT_NAME, lgfnt.lfFaceName, LF_FACESIZE); + if (!data->bFitToScreenMode) { + lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family + NH_A2W(NHMAP_FONT_NAME, lgfnt.lfFaceName, LF_FACESIZE); + } else { + lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family + NH_A2W(NHMAP_TTFONT_NAME, lgfnt.lfFaceName, LF_FACESIZE); + } } TEXTMETRIC textMetrics; @@ -216,6 +231,9 @@ mswin_map_stretch(HWND hWnd, LPSIZE map_size, BOOL redraw) GetTextMetrics(data->backBufferDC, &textMetrics); + if (!data->bFitToScreenMode) + break; + if ((textMetrics.tmHeight > data->yBackTile || textMetrics.tmAveCharWidth > data->xBackTile) && lgfnt.lfHeight < -MIN_FONT_HEIGHT) { From 9952049a752b6e310791740814cf3aea78d2951e Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 12 Dec 2018 01:54:33 -0800 Subject: [PATCH 3/4] fix #H7677 - guard placed twice at <0,0> "Placing monster over another?" warning was triggered for vault guard by an earlier change which made m_detach() stop removing monsters at <0,*> from level.monsters[][]. So one guard would replace another at <0,0> for however many guards were created, and memory for all but the last one would be lost. This involved a lot of flailing about and the patch includes various things would could have been discarded. One or two extended monster sanity checks are included, plus a couple of debugpline()'s for tracking guard movement. --- doc/fixes36.2 | 1 + src/mon.c | 29 +++++++++++---- src/steed.c | 8 +++- src/vault.c | 101 ++++++++++++++++++++++++++++++-------------------- 4 files changed, 90 insertions(+), 49 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 9e6b004bb..51e6bfa69 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -293,6 +293,7 @@ changing Sting's description to be "(weapon in hand) (light blue aura)" was fix bit-use collision between WC2_TERM_SIZE and WC2_RESET_STATUS in include/winprocs.h following a recent merge fix foxen pluralization again after underflow remedy reintroduced the problem +fix "placing monster over another?" warning for vault guards 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/mon.c b/src/mon.c index a22db1a1a..74edcccd7 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1543455827 2018/11/29 01:43:47 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.272 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1544608467 2018/12/12 09:54:27 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.273 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -48,8 +48,6 @@ struct monst *mtmp; boolean chk_geno; const char *msg; { - if (DEADMONSTER(mtmp)) - return; if (mtmp->data < &mons[LOW_PM] || mtmp->data >= &mons[NUMMONS]) { impossible("illegal mon data %s; mnum=%d (%s)", fmt_ptr((genericptr_t) mtmp->data), mtmp->mnum, msg); @@ -61,6 +59,13 @@ const char *msg; mtmp->mnum, mndx, msg); mtmp->mnum = mndx; } + if (DEADMONSTER(mtmp)) { + /* bad if not fmons list or if not vault guard */ + if (strcmp(msg, "fmon") || !mtmp->isgd) + impossible("dead monster on %s; %s at <%d,%d>", + msg, mons[mndx].mname, mtmp->mx, mtmp->my); + return; + } if (chk_geno && (mvitals[mndx].mvflags & G_GENOD) != 0) impossible("genocided %s in play (%s)", mons[mndx].mname, msg); } @@ -85,8 +90,9 @@ mon_sanity_check() for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { sanity_check_single_mon(mtmp, TRUE, "fmon"); - if (DEADMONSTER(mtmp)) + if (DEADMONSTER(mtmp) && !mtmp->isgd) continue; + x = mtmp->mx, y = mtmp->my; if (!isok(x, y) && !(mtmp->isgd && x == 0 && y == 0)) { impossible("mon (%s) claims to be at <%d,%d>?", @@ -713,10 +719,17 @@ movemon() break; } nmtmp = mtmp->nmon; - /* one dead monster needs to perform a move after death: - vault guard whose temporary corridor is still on the map */ - if (mtmp->isgd && !mtmp->mx && DEADMONSTER(mtmp)) + /* one dead monster needs to perform a move after death: vault + guard whose temporary corridor is still on the map; live + guards who have led the hero back to civilization get moved + off the map too; gd_move() decides whether the temporary + corridor can be removed and guard discarded (via clearing + mon->isgd flag so that dmonsfree() will get rid of mon) */ + if (mtmp->isgd && !mtmp->mx) { + /* parked at <0,0>; eventually isgd should get set to false */ (void) gd_move(mtmp); + continue; + } if (DEADMONSTER(mtmp)) continue; @@ -1766,7 +1779,7 @@ struct permonst *mptr; /* reflects mtmp->data _prior_ to mtmp's death */ mtmp->mtrapped = 0; mtmp->mhp = 0; /* simplify some tests: force mhp to 0 */ relobj(mtmp, 0, FALSE); - if (onmap) { + if (onmap || mtmp == level.monsters[0][0]) { if (mtmp->wormno) remove_worm(mtmp); else diff --git a/src/steed.c b/src/steed.c index 65e5ebbae..9eaf8f4c0 100644 --- a/src/steed.c +++ b/src/steed.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 steed.c $NHDT-Date: 1543543362 2018/11/30 02:02:42 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.59 $ */ +/* NetHack 3.6 steed.c $NHDT-Date: 1544608468 2018/12/12 09:54:28 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.60 $ */ /* Copyright (c) Kevin Hugo, 1998-1999. */ /* NetHack may be freely redistributed. See license for details. */ @@ -742,6 +742,12 @@ place_monster(mon, x, y) struct monst *mon; int x, y; { + /* normal map bounds are <1..COLNO-1,0..ROWNO-1> but sometimes + vault guards (either living or dead) are parked at <0,0> */ + if (!isok(x, y) && (x != 0 || y != 0 || !mon->isgd)) { + impossible("trying to place monster at <%d,%d>", x, y); + x = y = 0; + } if (mon == u.usteed /* special case is for convoluted vault guard handling */ || (DEADMONSTER(mon) && !(mon->isgd && x == 0 && y == 0))) { diff --git a/src/vault.c b/src/vault.c index 7e47577e2..0e811d117 100644 --- a/src/vault.c +++ b/src/vault.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 vault.c $NHDT-Date: 1542765368 2018/11/21 01:56:08 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.55 $ */ +/* NetHack 3.6 vault.c $NHDT-Date: 1544608469 2018/12/12 09:54:29 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.57 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -10,6 +10,7 @@ STATIC_DCL struct monst *NDECL(findgd); STATIC_DCL boolean FDECL(clear_fcorr, (struct monst *, BOOLEAN_P)); STATIC_DCL void FDECL(blackout, (int, int)); STATIC_DCL void FDECL(restfakecorr, (struct monst *)); +STATIC_DCL void FDECL(parkguard, (struct monst *)); STATIC_DCL boolean FDECL(in_fcorridor, (struct monst *, int, int)); STATIC_DCL void FDECL(move_gold, (struct obj *, int)); STATIC_DCL void FDECL(wallify_vault, (struct monst *)); @@ -22,8 +23,8 @@ struct monst *mtmp; if (!mtmp->mextra) mtmp->mextra = newmextra(); if (!EGD(mtmp)) { - EGD(mtmp) = (struct egd *) alloc(sizeof(struct egd)); - (void) memset((genericptr_t) EGD(mtmp), 0, sizeof(struct egd)); + EGD(mtmp) = (struct egd *) alloc(sizeof (struct egd)); + (void) memset((genericptr_t) EGD(mtmp), 0, sizeof (struct egd)); } } @@ -38,6 +39,9 @@ struct monst *mtmp; mtmp->isgd = 0; } +/* try to remove the temporary corridor (from vault to rest of map) being + maintained by guard 'grd'; if guard is still in it, removal will fail, + to be tried again later */ STATIC_OVL boolean clear_fcorr(grd, forceshow) struct monst *grd; @@ -53,10 +57,14 @@ boolean forceshow; if (!on_level(&egrd->gdlevel, &u.uz)) return TRUE; + /* note: guard remains on 'fmons' list (alive or dead, at off-map + coordinate <0,0>), until temporary corridor from vault back to + civilization has been removed */ while ((fcbeg = egrd->fcbeg) < egrd->fcend) { fcx = egrd->fakecorr[fcbeg].fx; fcy = egrd->fakecorr[fcbeg].fy; - if ((DEADMONSTER(grd) || !in_fcorridor(grd, u.ux, u.uy)) && egrd->gddone) + if ((DEADMONSTER(grd) || !in_fcorridor(grd, u.ux, u.uy)) + && egrd->gddone) forceshow = TRUE; if ((u.ux == fcx && u.uy == fcy && !DEADMONSTER(grd)) || (!forceshow && couldsee(fcx, fcy)) @@ -137,6 +145,26 @@ struct monst *grd; } } +/* move guard--dead to alive--to <0,0> until temporary corridor is removed */ +STATIC_OVL void +parkguard(grd) +struct monst *grd; +{ + /* either guard is dead or will now be treated as if so; + monster traversal loops should skip it */ + if (grd == context.polearm.hitmon) + context.polearm.hitmon = 0; + if (grd->mx) { + remove_monster(grd->mx, grd->my); + newsym(grd->mx, grd->my); + place_monster(grd, 0, 0); + /* [grd->mx,my just got set to 0,0 by place_monster(), so this + just sets EGD(grd)->ogx,ogy to 0,0 too; is that what we want?] */ + EGD(grd)->ogx = grd->mx; + EGD(grd)->ogy = grd->my; + } +} + /* called in mon.c */ boolean grddead(grd) @@ -147,16 +175,8 @@ struct monst *grd; if (!dispose) { /* destroy guard's gold; drop any other inventory */ relobj(grd, 0, FALSE); - /* guard is dead; monster traversal loops should skip it */ grd->mhp = 0; - if (grd == context.polearm.hitmon) - context.polearm.hitmon = 0; - /* see comment by newpos in gd_move() */ - remove_monster(grd->mx, grd->my); - newsym(grd->mx, grd->my); - place_monster(grd, 0, 0); - EGD(grd)->ogx = grd->mx; - EGD(grd)->ogy = grd->my; + parkguard(grd); dispose = clear_fcorr(grd, TRUE); } if (dispose) @@ -226,13 +246,12 @@ invault() u.uinvault = 0; return; } - vaultroom -= ROOMOFFSET; guard = findgd(); if (++u.uinvault % VAULT_GUARD_TIME == 0 && !guard) { /* if time ok and no guard now. */ - char buf[BUFSZ] = DUMMY; + char buf[BUFSZ]; register int x, y, dd, gx, gy; int lx = 0, ly = 0; long umoney; @@ -387,6 +406,7 @@ invault() nomul(0); unmul((char *) 0); } + buf[0] = '\0'; trycount = 5; do { getlin(Deaf ? "You are required to supply your name. -" @@ -401,7 +421,7 @@ invault() } if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos") - || !strcmpi(buf, "Creosote")) { + || !strcmpi(buf, "Creosote")) { /* Discworld */ if (!mvitals[PM_CROESUS].died) { if (Deaf) { if (!Blind) @@ -468,9 +488,9 @@ invault() EGD(guard)->fcbeg = 0; EGD(guard)->fakecorr[0].fx = x; EGD(guard)->fakecorr[0].fy = y; - if (IS_WALL(levl[x][y].typ)) + if (IS_WALL(levl[x][y].typ)) { EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ; - else { /* the initial guard location is a dug door */ + } else { /* the initial guard location is a dug door */ int vlt = EGD(guard)->vroom; xchar lowx = rooms[vlt].lx, hix = rooms[vlt].hx; xchar lowy = rooms[vlt].ly, hiy = rooms[vlt].hy; @@ -603,27 +623,29 @@ register struct monst *grd; int x, y, nx, ny, m, n; int dx, dy, gx, gy, fci; uchar typ; + struct rm *crm; struct fakecorridor *fcp; register struct egd *egrd = EGD(grd); - struct rm *crm; - boolean goldincorridor = FALSE, - u_in_vault = vault_occupied(u.urooms) ? TRUE : FALSE, - grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT) ? TRUE : FALSE; - boolean disappear_msg_seen = FALSE, semi_dead = (DEADMONSTER(grd)); - long umoney = money_cnt(invent); - register boolean u_carry_gold = ((umoney + hidden_gold()) > 0L); - boolean see_guard, newspot = FALSE; + long umoney = 0L; + boolean goldincorridor = FALSE, u_in_vault = FALSE, grd_in_vault = FALSE, + disappear_msg_seen = FALSE, semi_dead = DEADMONSTER(grd), + u_carry_gold = FALSE, newspot = FALSE, see_guard; if (!on_level(&(egrd->gdlevel), &u.uz)) return -1; nx = ny = m = n = 0; + if (semi_dead || !grd->mx || egrd->gddone) { + egrd->gddone = 1; + goto cleanup; + } + debugpline1("gd_move: %s guard", grd->mpeaceful ? "peaceful" : "hostile"); + + u_in_vault = vault_occupied(u.urooms) ? TRUE : FALSE; + grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT) ? TRUE : FALSE; if (!u_in_vault && !grd_in_vault) wallify_vault(grd); + if (!grd->mpeaceful) { - if (semi_dead) { - egrd->gddone = 1; - goto newpos; - } if (!u_in_vault && (grd_in_vault || (in_fcorridor(grd, grd->mx, grd->my) && !in_fcorridor(grd, u.ux, u.uy)))) { @@ -647,6 +669,9 @@ register struct monst *grd; grd->mpeaceful = 0; return -1; } + + umoney = money_cnt(invent); + u_carry_gold = umoney > 0L || hidden_gold() > 0L; if (egrd->fcend == 1) { if (u_in_vault && (u_carry_gold || um_dist(grd->mx, grd->my, 1))) { if (egrd->warncnt == 3 && !Deaf) @@ -696,7 +721,6 @@ register struct monst *grd; } else { if (!Deaf) verbalize("Well, begone."); - wallify_vault(grd); egrd->gddone = 1; goto cleanup; } @@ -881,7 +905,7 @@ proceed: fcp->fy = ny; fcp->ftyp = typ; newpos: - gd_mv_monaway(grd, nx,ny); + gd_mv_monaway(grd, nx, ny); if (egrd->gddone) { /* The following is a kludge. We need to keep */ /* the guard around in order to be able to make */ @@ -893,17 +917,14 @@ newpos: /* At the end of the process, the guard is killed */ /* in restfakecorr(). */ cleanup: - x = grd->mx; - y = grd->my; - + x = grd->mx, y = grd->my; see_guard = canspotmon(grd); + parkguard(grd); /* move to <0,0> */ wallify_vault(grd); - remove_monster(grd->mx, grd->my); - newsym(grd->mx, grd->my); - place_monster(grd, 0, 0); - egrd->ogx = grd->mx; - egrd->ogy = grd->my; restfakecorr(grd); + debugpline2("gd_move: %scleanup%s", + grd->isgd ? "" : "final ", + grd->isgd ? " attempt" : ""); if (!semi_dead && (in_fcorridor(grd, u.ux, u.uy) || cansee(x, y))) { if (!disappear_msg_seen && see_guard) pline("Suddenly, %s disappears.", noit_mon_nam(grd)); From fdec3704fd51e546fb588e8dcea7bbb228cff11d Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 12 Dec 2018 15:42:46 -0800 Subject: [PATCH 4/4] mon_sanity_check tweak A change I included with the vault guard fix was triggering fuzzer panics about dead monsters on the fmons list. I'm not quite sure why; I couldn't reproduce it interactively. [Perhaps caused by hero killing a monster and then getting another move before monsters get their turn, but trying to do that still didn't trip the dead monster sanity check.] Suppress that check so that the fuzzer can run amok. Also, a waiting-to-exit vault guard could move extra times, uselessly since ''hero hasn't left temporary corridor yet'' is why he's waiting, if there were any monsters fast enough to get extra moves before the hero's next turn. --- src/mon.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mon.c b/src/mon.c index 74edcccd7..de037e42b 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1544608467 2018/12/12 09:54:27 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.273 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1544658160 2018/12/12 23:42:40 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.274 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -60,10 +60,12 @@ const char *msg; mtmp->mnum = mndx; } if (DEADMONSTER(mtmp)) { +#if 0 /* bad if not fmons list or if not vault guard */ if (strcmp(msg, "fmon") || !mtmp->isgd) impossible("dead monster on %s; %s at <%d,%d>", msg, mons[mndx].mname, mtmp->mx, mtmp->my); +#endif return; } if (chk_geno && (mvitals[mndx].mvflags & G_GENOD) != 0) @@ -89,6 +91,7 @@ mon_sanity_check() struct monst *mtmp, *m; for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { + /* dead monsters should still have sane data */ sanity_check_single_mon(mtmp, TRUE, "fmon"); if (DEADMONSTER(mtmp) && !mtmp->isgd) continue; @@ -727,7 +730,10 @@ movemon() mon->isgd flag so that dmonsfree() will get rid of mon) */ if (mtmp->isgd && !mtmp->mx) { /* parked at <0,0>; eventually isgd should get set to false */ - (void) gd_move(mtmp); + if (monstermoves > mtmp->mlstmv) { + (void) gd_move(mtmp); + mtmp->mlstmv = monstermoves; + } continue; } if (DEADMONSTER(mtmp))