unhiding during level change

From the newsgroup:  if a pet was hiding under an object next to you
when you changed levels, it could arrive hidden at the destination if there
was something available to hide under there too, and sometimes you'd start
the new level with a hidden monster glyph at its location.  I was able to
reproduce that once with current trunk code, but while trying to figure
out what is actually happening I've been unable to make it happen again.
However, it doesn't make sense for a monster to be able to remain in hiding
during the level change in the first place, so this patch prevents that.
(I'd still like to know how/why map_invisible() is sometimes getting called.
[The test character was a level 1 tourist without auto-search capability.]
I'm reasonably sure that it won't happen any more once this fix in place.)

     This also brings adjacent pets out of hiding when they accompany you
during ascension or dungeon escape, but it seems that that wasn't actually
necessary.  The end of game disclosure already lists such by name rather
than as "it", contrary to my expectations.  (I had forgotten that end-of-
game forces true names so that blindness and hallucination don't interfere
with disclosure; obviously that ends up handling hidden monsters too.)
This commit is contained in:
nethack.rankin
2006-10-22 02:53:31 +00:00
parent 4169a3a308
commit 6b371a7042
4 changed files with 42 additions and 21 deletions

View File

@@ -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

View File

@@ -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 *));

View File

@@ -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);

View File

@@ -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;
}
}