B18009 animate figurine over water

>More worrying is the fact that applying a figurine over water lets
>the monster wait until its next move before it drowns (giving
>you time to teleport it to safety, or whatever) [...]
>Should there be a minliquid() check as part of make_familiar()?

Applying at the water location next to you was easy. But
applying it at your own location (triggering BY_YOU)  could
end up placing the figurine at the far side of the level if
there was lots of water.

Correcting that required the ability to pass a flag from
make_familiar to makemon() telling it to not rule out
water locations as good positions.  The flag had to
be passed on down to goodpos() and enexto().

The bulk of this patch is just adding an additional
argument to goodpos() in all of the callers.
This commit is contained in:
nethack.allison
2003-02-09 05:39:32 +00:00
parent fd22b557ed
commit c2c72d11e7
17 changed files with 58 additions and 35 deletions

View File

@@ -1704,12 +1704,13 @@ register struct obj *obj;
if (!figurine_location_checks(obj, &cc, FALSE)) return;
You("%s and it transforms.",
(u.dx||u.dy) ? "set the figurine beside you" :
(Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) ?
(Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ||
is_pool(cc.x, cc.y)) ?
"release the figurine" :
(u.dz < 0 ?
"toss the figurine into the air" :
"set the figurine on the ground"));
(void) make_familiar(obj, u.ux+u.dx, u.uy+u.dy, FALSE);
(void) make_familiar(obj, cc.x, cc.y, FALSE);
(void) stop_timer(FIG_TRANSFORM, (genericptr_t)obj);
useup(obj);
}

View File

@@ -81,7 +81,7 @@ boolean quietly;
}
}
mtmp = makemon(pm, x, y, MM_EDOG);
mtmp = makemon(pm, x, y, MM_EDOG|MM_IGNOREWATER);
if (otmp && !mtmp) { /* monster was genocided or square occupied */
if (!quietly)
pline_The("figurine writhes and then shatters into pieces!");
@@ -91,6 +91,9 @@ boolean quietly;
if (!mtmp) return (struct monst *)0;
if (is_pool(mtmp->mx, mtmp->my) && minliquid(mtmp))
return (struct monst *)0;
initedog(mtmp);
mtmp->msleeping = 0;
if (otmp) { /* figurine; resulting monster might not become a pet */

View File

@@ -760,16 +760,16 @@ newdogpos:
ny = sgn(omy - u.uy);
cc.x = u.ux + nx;
cc.y = u.uy + ny;
if (goodpos(cc.x, cc.y, mtmp)) goto dognext;
if (goodpos(cc.x, cc.y, mtmp, 0)) goto dognext;
i = xytod(nx, ny);
for (j = (i + 7)%8; j < (i + 1)%8; j++) {
dtoxy(&cc, j);
if (goodpos(cc.x, cc.y, mtmp)) goto dognext;
if (goodpos(cc.x, cc.y, mtmp, 0)) goto dognext;
}
for (j = (i + 6)%8; j < (i + 2)%8; j++) {
dtoxy(&cc, j);
if (goodpos(cc.x, cc.y, mtmp)) goto dognext;
if (goodpos(cc.x, cc.y, mtmp, 0)) goto dognext;
}
cc.x = mtmp->mx;
cc.y = mtmp->my;

View File

@@ -93,7 +93,7 @@ register boolean clumsy;
/* see if the monster has a place to move into */
mdx = mon->mx + u.dx;
mdy = mon->my + u.dy;
if(goodpos(mdx, mdy, mon)) {
if(goodpos(mdx, mdy, mon, 0)) {
pline("%s reels from the blow.", Monnam(mon));
if (m_in_out_region(mon, mdx, mdy)) {
remove_monster(mon->mx, mon->my);

View File

@@ -555,7 +555,7 @@ mhurtle_step(arg, x, y)
/* TODO: Treat walls, doors, iron bars, pools, lava, etc. specially
* rather than just stopping before.
*/
if (goodpos(x, y, mon) && m_in_out_region(mon, x, y)) {
if (goodpos(x, y, mon, 0) && m_in_out_region(mon, x, y)) {
remove_monster(mon->mx, mon->my);
newsym(mon->mx, mon->my);
place_monster(mon, x, y);

View File

@@ -1188,7 +1188,7 @@ struct engr *ep;
tx = rn1(COLNO-3,2);
ty = rn2(ROWNO);
} while (engr_at(tx, ty) ||
!goodpos(tx, ty, (struct monst *)0));
!goodpos(tx, ty, (struct monst *)0, 0));
ep->engr_x = tx;
ep->engr_y = ty;

View File

@@ -47,7 +47,7 @@ const char *msg;
/* this location might not be safe, if not, move revived monster */
if (revived) {
mtmp = m_at(x,y);
if (mtmp && !goodpos(x, y, mtmp) &&
if (mtmp && !goodpos(x, y, mtmp, 0) &&
enexto(&cc, x, y, mtmp->data)) {
rloc_to(mtmp, cc.x, cc.y);
}

View File

@@ -766,6 +766,7 @@ register int mmflags;
boolean byyou = (x == u.ux && y == u.uy);
boolean allow_minvent = ((mmflags & NO_MINVENT) == 0);
boolean countbirth = ((mmflags & MM_NOCOUNTBIRTH) == 0);
unsigned gpflags = (mmflags & MM_IGNOREWATER) ? MM_IGNOREWATER : 0;
uchar lim;
/* if caller wants random location, do it here */
@@ -777,12 +778,12 @@ register int mmflags;
do {
x = rn1(COLNO-3,2);
y = rn2(ROWNO);
} while(!goodpos(x, y, ptr ? &fakemon : (struct monst *)0) ||
} while(!goodpos(x, y, ptr ? &fakemon : (struct monst *)0, gpflags) ||
(!in_mklev && tryct++ < 50 && cansee(x, y)));
} else if (byyou && !in_mklev) {
coord bypos;
if(enexto(&bypos, u.ux, u.uy, ptr)) {
if(enexto_core(&bypos, u.ux, u.uy, ptr, gpflags)) {
x = bypos.x;
y = bypos.y;
} else
@@ -819,7 +820,7 @@ register int mmflags;
return((struct monst *) 0); /* no more monsters! */
}
fakemon.data = ptr; /* set up for goodpos */
} while(!goodpos(x, y, &fakemon) && tryct++ < 50);
} while(!goodpos(x, y, &fakemon, gpflags) && tryct++ < 50);
mndx = monsndx(ptr);
}
/* if it's unique, don't ever make it again */

View File

@@ -417,7 +417,7 @@ fixup_special()
croom = &rooms[0]; /* only one room on the medusa level */
for (tryct = rnd(4); tryct; tryct--) {
x = somex(croom); y = somey(croom);
if (goodpos(x, y, (struct monst *)0)) {
if (goodpos(x, y, (struct monst *)0, 0)) {
otmp = mk_tt_object(STATUE, x, y);
while (otmp && (poly_when_stoned(&mons[otmp->corpsenm]) ||
pm_resistance(&mons[otmp->corpsenm],MR_STONE))) {

View File

@@ -1919,7 +1919,7 @@ boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
newx = x;
newy = y;
if (!goodpos(newx, newy, mtmp)) {
if (!goodpos(newx, newy, mtmp, 0)) {
/* actually we have real problems if enexto ever fails.
* migrating_mons that need to be placed will cause
* no end of trouble.

View File

@@ -305,7 +305,7 @@ boolean special;
do {
x = rn1(COLNO-4, 2);
y = rnd(ROWNO-2);
} while(!goodpos(x, y, &fakemon) && tryct++ <= 50);
} while(!goodpos(x, y, &fakemon, 0) && tryct++ <= 50);
/* if pos not found in 50 tries, don't bother to continue */
if(tryct > 50) return;

View File

@@ -18,11 +18,13 @@ STATIC_DCL void FDECL(mvault_tele, (struct monst *));
* call it to generate new monster positions with fake monster structures.
*/
boolean
goodpos(x, y, mtmp)
goodpos(x, y, mtmp, gpflags)
int x,y;
struct monst *mtmp;
unsigned gpflags;
{
struct permonst *mdat = NULL;
boolean ignorewater = ((gpflags & MM_IGNOREWATER) != 0);
if (!isok(x, y)) return FALSE;
@@ -56,13 +58,13 @@ struct monst *mtmp;
return FALSE;
mdat = mtmp->data;
if (is_pool(x,y)) {
if (is_pool(x,y) && !ignorewater) {
if (mtmp == &youmonst)
return !!(HLevitation || Flying || Wwalking ||
Swimming || Amphibious);
else return (is_flyer(mdat) || is_swimmer(mdat) ||
is_clinger(mdat));
} else if (mdat->mlet == S_EEL && rn2(13)) {
} else if (mdat->mlet == S_EEL && rn2(13) && !ignorewater) {
return FALSE;
} else if (is_lava(x,y)) {
if (mtmp == &youmonst)
@@ -72,7 +74,10 @@ struct monst *mtmp;
}
if (passes_walls(mdat) && may_passwall(x,y)) return TRUE;
}
if (!ACCESSIBLE(levl[x][y].typ)) return FALSE;
if (!ACCESSIBLE(levl[x][y].typ)) {
if (!(is_pool(x,y) && ignorewater)) return FALSE;
}
if (closed_door(x, y) && (!mdat || !amorphous(mdat)))
return FALSE;
if (sobj_at(BOULDER, x, y) && (!mdat || !throws_rocks(mdat)))
@@ -93,6 +98,16 @@ enexto(cc, xx, yy, mdat)
coord *cc;
register xchar xx, yy;
struct permonst *mdat;
{
return enexto_core(cc, xx, yy, mdat, 0);
}
boolean
enexto_core(cc, xx, yy, mdat, entflags)
coord *cc;
register xchar xx, yy;
struct permonst *mdat;
unsigned entflags;
{
#define MAX_GOOD 15
coord good[MAX_GOOD], *good_ptr;
@@ -121,28 +136,28 @@ struct permonst *mdat;
ymax = min(ROWNO-1, yy+range);
for (x = xmin; x <= xmax; x++)
if (goodpos(x, ymin, &fakemon)) {
if (goodpos(x, ymin, &fakemon, entflags)) {
good_ptr->x = x;
good_ptr->y = ymin ;
/* beware of accessing beyond segment boundaries.. */
if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
}
for (x = xmin; x <= xmax; x++)
if (goodpos(x, ymax, &fakemon)) {
if (goodpos(x, ymax, &fakemon, entflags)) {
good_ptr->x = x;
good_ptr->y = ymax ;
/* beware of accessing beyond segment boundaries.. */
if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
}
for (y = ymin+1; y < ymax; y++)
if (goodpos(xmin, y, &fakemon)) {
if (goodpos(xmin, y, &fakemon, entflags)) {
good_ptr->x = xmin;
good_ptr-> y = y ;
/* beware of accessing beyond segment boundaries.. */
if (good_ptr++ == &good[MAX_GOOD-1]) goto full;
}
for (y = ymin+1; y < ymax; y++)
if (goodpos(xmax, y, &fakemon)) {
if (goodpos(xmax, y, &fakemon, entflags)) {
good_ptr->x = xmax;
good_ptr->y = y ;
/* beware of accessing beyond segment boundaries.. */
@@ -205,7 +220,7 @@ register int x, y;
boolean trapok;
{
if (!trapok && t_at(x, y)) return FALSE;
if (!goodpos(x, y, &youmonst)) return FALSE;
if (!goodpos(x, y, &youmonst, 0)) return FALSE;
if (!tele_jump_ok(u.ux, u.uy, x, y)) return FALSE;
if (!in_out_region(x, y)) return FALSE;
return TRUE;
@@ -826,7 +841,7 @@ struct monst *mtmp;
{
register int xx, yy;
if (!goodpos(x, y, mtmp)) return FALSE;
if (!goodpos(x, y, mtmp, 0)) return FALSE;
/*
* Check for restricted areas present in some special levels.
*
@@ -938,7 +953,7 @@ struct monst *mtmp; /* mx==0 implies migrating monster arrival */
/* if the wiz teleports away to heal, try the up staircase,
to block the player's escaping before he's healed
(deliberately use `goodpos' rather than `rloc_pos_ok' here) */
if (goodpos(x, y, mtmp))
if (goodpos(x, y, mtmp, 0))
goto found_xy;
}
@@ -947,14 +962,14 @@ struct monst *mtmp; /* mx==0 implies migrating monster arrival */
x = rn1(COLNO-3,2);
y = rn2(ROWNO);
if ((trycount < 500) ? rloc_pos_ok(x, y, mtmp)
: goodpos(x, y, mtmp))
: goodpos(x, y, mtmp, 0))
goto found_xy;
} while (++trycount < 1000);
/* last ditch attempt to find a good place */
for (x = 2; x < COLNO - 1; x++)
for (y = 0; y < ROWNO; y++)
if (goodpos(x, y, mtmp))
if (goodpos(x, y, mtmp, 0))
goto found_xy;
/* level either full of monsters or somehow faulty */
@@ -973,7 +988,7 @@ struct monst *mtmp;
coord c;
if (croom && somexy(croom, &c) &&
goodpos(c.x, c.y, mtmp)) {
goodpos(c.x, c.y, mtmp, 0)) {
rloc_to(mtmp, c.x, c.y);
return;
}
@@ -1114,7 +1129,7 @@ register struct obj *obj;
tx = rn1(COLNO-3,2);
ty = rn2(ROWNO);
if (!--try_limit) break;
} while (!goodpos(tx, ty, (struct monst *)0) ||
} while (!goodpos(tx, ty, (struct monst *)0, 0) ||
/* bug: this lacks provision for handling the Wizard's tower */
(restricted_fall &&
(!within_bounded_area(tx, ty, dndest.lx, dndest.ly,

View File

@@ -2737,7 +2737,7 @@ drown()
for (i = 0; i < 100; i++) {
x = rn1(3,u.ux - 1);
y = rn1(3,u.uy - 1);
if (goodpos(x, y, &youmonst)) {
if (goodpos(x, y, &youmonst, 0)) {
crawl_ok = TRUE;
goto crawl;
}
@@ -2745,7 +2745,7 @@ drown()
/* one more scan */
for (x = u.ux - 1; x <= u.ux + 1; x++)
for (y = u.uy - 1; y <= u.uy + 1; y++)
if (goodpos(x, y, &youmonst)) {
if (goodpos(x, y, &youmonst, 0)) {
crawl_ok = TRUE;
goto crawl;
}

View File

@@ -613,7 +613,7 @@ place_worm_tail_randomly(worm, x, y)
do {
random_dir(ox, oy, &nx, &ny);
} while (!goodpos(nx, ny, worm) && (tryct++ < 50));
} while (!goodpos(nx, ny, worm, 0) && (tryct++ < 50));
if (tryct < 50) {
place_worm_seg(worm, nx, ny);