more mimic-as-boulder (trunk only)

I started to add handling for doorways containing mimic-as-boulder
to doopen() and doclose() as was done for pick_lock(), but decided that
it was better just to prevent mimics from appearing as boulders at closed
door locations in the first place.  So the most recent pick_lock() change
and its fixes entry go away.

     This also fixes a post-3.4.3 bug.  On the top level of Sokoban I
discovered a boulder over a hole; probing reported it as a mimic with
0 hp.  The special level loading code moves mimic-as-boulder away from
trap spots by using place_monster() to put it on another spot, but it
was missing the corresponding remove_monster() to take it away from the
original location so left a stale pointer on the map.
This commit is contained in:
nethack.rankin
2011-01-05 01:28:36 +00:00
parent e379b245d4
commit 3b6c59c7fc
3 changed files with 34 additions and 21 deletions
+1 -3
View File
@@ -70,7 +70,7 @@ when blind and levitating > shouldn't say "stairs" if player has not seen them
a slow-moving monster hidden under a rotting corpse was not immediately a slow-moving monster hidden under a rotting corpse was not immediately
displayed when the corpse rotted away displayed when the corpse rotted away
mimic that ends up on the rogue level should not mimic a closed door mimic that ends up on the rogue level should not mimic a closed door
mimic should not mimic a boulder while on a pit or hole location mimic should not mimic a boulder while on a pit or hole or closed door
reviving invisible troll could appear visible until it moves reviving invisible troll could appear visible until it moves
adjust some of the shop repair messages adjust some of the shop repair messages
charge for reviving a shop owned corpse or reanimating a shop owned statue charge for reviving a shop owned corpse or reanimating a shop owned statue
@@ -342,8 +342,6 @@ when reading an unknown scroll and learning it, discovery of teleporation was
too late if hero happened to land on another scroll of teleportation too late if hero happened to land on another scroll of teleportation
using an unlocking tool on a closed door which was actually a mimic reported using an unlocking tool on a closed door which was actually a mimic reported
that there was no door to unlock instead of exposing the mimic that there was no door to unlock instead of exposing the mimic
using an unlocking tool on a boulder that was a mimic in a Sokoban doorway
successfully unlocked the underlying door without exposing mimic
Platform- and/or Interface-Specific Fixes Platform- and/or Interface-Specific Fixes
-11
View File
@@ -407,17 +407,6 @@ pick_lock(pick)
/* "The door actually was a <mimic>!" */ /* "The door actually was a <mimic>!" */
stumble_onto_mimic(mtmp); stumble_onto_mimic(mtmp);
return PICKLOCK_LEARNED_SOMETHING; return PICKLOCK_LEARNED_SOMETHING;
/* mimic-as-boulder on last Sokoban level */
} else if (mtmp && mtmp->m_ap_type == M_AP_OBJECT &&
mtmp->mappearance == BOULDER) {
if (Blind) /* by touch */
/* "Wait! That's a monster!" */
stumble_onto_mimic(mtmp);
else if (IS_DOOR(door->typ))
pline("That door is blocked.");
else
You("see no door there.");
return PICKLOCK_LEARNED_SOMETHING;
} }
if(!IS_DOOR(door->typ)) { if(!IS_DOOR(door->typ)) {
if (is_drawbridge_wall(cc.x,cc.y) >= 0) if (is_drawbridge_wall(cc.x,cc.y) >= 0)
+33 -7
View File
@@ -1,5 +1,4 @@
/* NetHack 3.5 sp_lev.c $Date$ $Revision$ */ /* NetHack 3.5 sp_lev.c $Date$ $Revision$ */
/* SCCS Id: @(#)sp_lev.c 3.5 2007/08/01 */
/* Copyright (c) 1989 by Jean-Christophe Collet */ /* Copyright (c) 1989 by Jean-Christophe Collet */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -30,6 +29,7 @@ STATIC_DCL void FDECL(get_room_loc, (schar *, schar *, struct mkroom *));
STATIC_DCL void FDECL(get_free_room_loc, (schar *, schar *, struct mkroom *)); STATIC_DCL void FDECL(get_free_room_loc, (schar *, schar *, struct mkroom *));
STATIC_DCL void FDECL(create_trap, (trap *, struct mkroom *)); STATIC_DCL void FDECL(create_trap, (trap *, struct mkroom *));
STATIC_DCL int FDECL(noncoalignment, (ALIGNTYP_P)); STATIC_DCL int FDECL(noncoalignment, (ALIGNTYP_P));
STATIC_DCL boolean FDECL(m_bad_boulder_spot, (int,int));
STATIC_DCL void FDECL(create_monster, (monster *, struct mkroom *)); STATIC_DCL void FDECL(create_monster, (monster *, struct mkroom *));
STATIC_DCL void FDECL(create_object, (object *, struct mkroom *)); STATIC_DCL void FDECL(create_object, (object *, struct mkroom *));
STATIC_DCL void FDECL(create_engraving, (engraving *,struct mkroom *)); STATIC_DCL void FDECL(create_engraving, (engraving *,struct mkroom *));
@@ -744,6 +744,26 @@ aligntyp alignment;
return(k ? -alignment : 0); return(k ? -alignment : 0);
} }
/* attempt to screen out locations where a mimic-as-boulder shouldn't occur */
STATIC_OVL boolean
m_bad_boulder_spot(x, y)
int x, y;
{
struct rm *lev;
/* avoid trap locations */
if (t_at(x, y)) return TRUE;
/* try to avoid locations which already have a boulder (this won't
actually work; we get called before objects have been placed...) */
if (sobj_at(BOULDER, x, y)) return TRUE;
/* avoid closed doors */
lev = &levl[x][y];
if (IS_DOOR(lev->typ) && (lev->doormask & (D_CLOSED | D_LOCKED)) != 0)
return TRUE;
/* spot is ok */
return FALSE;
}
STATIC_OVL void STATIC_OVL void
create_monster(m,croom) create_monster(m,croom)
monster *m; monster *m;
@@ -817,6 +837,7 @@ struct mkroom *croom;
else mtmp = makemon(pm, x, y, NO_MM_FLAGS); else mtmp = makemon(pm, x, y, NO_MM_FLAGS);
if (mtmp) { if (mtmp) {
x = mtmp->mx, y = mtmp->my; /* sanity precaution */
/* handle specific attributes for some special monsters */ /* handle specific attributes for some special monsters */
if (m->name.str) mtmp = christen_monst(mtmp, m->name.str); if (m->name.str) mtmp = christen_monst(mtmp, m->name.str);
@@ -862,21 +883,26 @@ struct mkroom *croom;
mtmp->m_ap_type = M_AP_OBJECT; mtmp->m_ap_type = M_AP_OBJECT;
mtmp->mappearance = i; mtmp->mappearance = i;
/* try to avoid placing mimic boulder on a trap */ /* try to avoid placing mimic boulder on a trap */
if (i == BOULDER && m->x < 0 && t_at(x, y)) { if (i == BOULDER && m->x < 0 &&
int k; m_bad_boulder_spot(x, y)) {
int retrylimit = 10;
for (k = 0; k < 10 && t_at(x, y); ++k) { remove_monster(x, y);
do {
x = m->x; x = m->x;
y = m->y; y = m->y;
if (croom) if (croom)
get_room_loc(&x, &y, croom); get_room_loc(&x, &y, croom);
else { else
get_location(&x, &y, DRY); get_location(&x, &y, DRY);
}
if (MON_AT(x,y) && enexto(&cc, x, y, pm)) if (MON_AT(x,y) && enexto(&cc, x, y, pm))
x = cc.x, y = cc.y; x = cc.x, y = cc.y;
} } while (m_bad_boulder_spot(x, y) &&
--retrylimit > 0);
place_monster(mtmp, x, y); place_monster(mtmp, x, y);
/* if we didn't find a good spot
then mimic something else */
if (!retrylimit) set_mimic_sym(mtmp);
} }
} }
break; break;