diff --git a/doc/fixes34.4 b/doc/fixes34.4 index e2cda30c0..2e0c416fc 100644 --- a/doc/fixes34.4 +++ b/doc/fixes34.4 @@ -263,6 +263,7 @@ try harder to keep dragged chain between ball and hero fireproof containers should not burn in lava fix invalid pointer dereference after applying a wielded cream pie avoid drowned in a drowning and burned by burning if life-saving is inadequate +hidden monsters who change levels come out of hiding in the process Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 585159854..ea4cd3193 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1247,7 +1247,7 @@ E void NDECL(dmonsfree); E int FDECL(mcalcmove, (struct monst*)); E void NDECL(mcalcdistress); E void FDECL(replmon, (struct monst *,struct monst *)); -E void FDECL(relmon, (struct monst *)); +E void FDECL(relmon, (struct monst *,struct monst **)); E struct obj *FDECL(mlifesaver, (struct monst *)); E boolean FDECL(corpse_chance,(struct monst *,struct monst *,BOOLEAN_P)); E void FDECL(mondead, (struct monst *)); diff --git a/src/dog.c b/src/dog.c index 037c12659..cc7e81ead 100644 --- a/src/dog.c +++ b/src/dog.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dog.c 3.5 2006/06/11 */ +/* SCCS Id: @(#)dog.c 3.5 2006/10/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -604,13 +604,10 @@ boolean pets_only; /* true for ascension or final escape */ obj->no_charge = 0; } - relmon(mtmp); - newsym(mtmp->mx,mtmp->my); + relmon(mtmp, &mydogs); /* move it from map to mydogs */ mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */ mtmp->wormno = num_segs; mtmp->mlstmv = monstermoves; - mtmp->nmon = mydogs; - mydogs = mtmp; } else if (mtmp->iswiz) { /* we want to be able to find him when his next resurrection chance comes up, but have him resume his present location @@ -660,10 +657,7 @@ migrate_to_level(mtmp, tolev, xyloc, cc) mtmp->mtame--; m_unleash(mtmp, TRUE); } - relmon(mtmp); - mtmp->nmon = migrating_mons; - migrating_mons = mtmp; - newsym(mtmp->mx,mtmp->my); + relmon(mtmp, &migrating_mons); /* move it from map to migrating_mons */ new_lev.dnum = ledger_to_dnum((xchar)tolev); new_lev.dlevel = ledger_to_dlev((xchar)tolev); diff --git a/src/mon.c b/src/mon.c index 0642fcc67..b205d1f26 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mon.c 3.5 2006/09/06 */ +/* SCCS Id: @(#)mon.c 3.5 2006/10/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1297,7 +1297,7 @@ register struct monst *mtmp, *mtmp2; mtmp->minvent = 0; /* remove the old monster from the map and from `fmon' list */ - relmon(mtmp); + relmon(mtmp, (struct monst **)0); /* finish adding its replacement */ #ifdef STEED @@ -1326,22 +1326,48 @@ register struct monst *mtmp, *mtmp2; dealloc_monst(mtmp); } -/* release mon from display and monster list */ +/* release mon from the display and the map's monster list, + maybe transfer it to one of the other monster lists */ void -relmon(mon) +relmon(mon, monst_list) register struct monst *mon; +struct monst **monst_list; /* &migrating_mons or &mydogs or null */ { register struct monst *mtmp; + boolean unhide = (monst_list != 0); + int mx = mon->mx, my = mon->my; - if (fmon == (struct monst *)0) panic ("relmon: no fmon available."); + if (!fmon) panic("relmon: no fmon available."); - remove_monster(mon->mx, mon->my); + if (unhide) { + /* can't remain hidden across level changes (exception: wizard + clone can continue imitating some other monster form); also, + might be imitating a boulder so need line-of-sight unblocking */ + mon->mundetected = 0; + if (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER) + seemimic(mon); + } - if(mon == fmon) fmon = fmon->nmon; - else { - for(mtmp = fmon; mtmp && mtmp->nmon != mon; mtmp = mtmp->nmon) ; - if(mtmp) mtmp->nmon = mon->nmon; - else panic("relmon: mon not in list."); + remove_monster(mx, my); + + if (mon == fmon) { + fmon = fmon->nmon; + } else { + for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) + if (mtmp->nmon == mon) break; + + if (mtmp) mtmp->nmon = mon->nmon; + else panic("relmon: mon not in list."); + } + + if (unhide) { + newsym(mx, my); + /* insert into mydogs or migrating_mons */ + mon->nmon = *monst_list; + *monst_list = mon; + } else { + /* orphan has no next monster */ + mon->nmon = 0; } }