monster ranged attacks (trunk only)

Newsgroup posts mention "boulder forts" from time to time, where the
player surrounds the hero with boulders in order to prevent the majority
of monsters from being able to attack.  Since the hero can shoot or throw
or zap over/around/through boulders, monsters ought to be able to do so
too.  This makes the test for whether a monster is lined up properly for
its ranged attacks try harder when the original line-of-sight check fails.
If there aren't any terrain obstacles found, it allows a chance to attack
based on the number of locations in the path that contain any boulders.
Giants and any monster carrying a boulder-destroying wand of striking get
to ignore boulders, overriding the random chance.
This commit is contained in:
nethack.rankin
2006-12-28 02:45:38 +00:00
parent 4b3b8b4047
commit f411d303ea
4 changed files with 30 additions and 9 deletions

View File

@@ -182,6 +182,7 @@ allow corpses on floor to be offered at high altars
allow hero to attempt to offer the Amulet at ordinary altars
shooting range for crossbow isn't affected by strength; multi-shot volley is
right-handed boomerang throw travels counterclockwise
monsters can use ranged attacks over/around boulders, same as hero
Platform- and/or Interface-Specific Fixes

View File

@@ -1421,7 +1421,7 @@ E int FDECL(ohitmon, (struct monst *,struct obj *,int,BOOLEAN_P));
E void FDECL(thrwmu, (struct monst *));
E int FDECL(spitmu, (struct monst *,struct attack *));
E int FDECL(breamu, (struct monst *,struct attack *));
E boolean FDECL(linedup, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P));
E boolean FDECL(linedup, (XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P,int));
E boolean FDECL(lined_up, (struct monst *));
E struct obj *FDECL(m_carrying, (struct monst *,int));
E void FDECL(m_useupall, (struct monst *,struct obj *));

View File

@@ -708,9 +708,12 @@ breamu(mtmp, mattk) /* monster breathes at you (ranged) */
}
boolean
linedup(ax, ay, bx, by)
linedup(ax, ay, bx, by, boulderhandling)
register xchar ax, ay, bx, by;
int boulderhandling; /* 0=block, 1=ignore, 2=conditionally block */
{
int dx, dy, boulderspots;
tbx = ax - bx; /* These two values are set for use */
tby = ay - by; /* after successful return. */
@@ -720,8 +723,22 @@ register xchar ax, ay, bx, by;
if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
&& distmin(tbx, tby, 0, 0) < BOLT_LIM) {
if(ax == u.ux && ay == u.uy) return((boolean)(couldsee(bx,by)));
else if(clear_path(ax,ay,bx,by)) return TRUE;
if ((ax == u.ux && ay == u.uy) ? (boolean)couldsee(bx, by) :
clear_path(ax, ay, bx, by)) return TRUE;
/* don't have line of sight, but might still be lined up
if that lack of sight is due solely to boulders */
if (boulderhandling == 0) return FALSE;
dx = sgn(ax - bx), dy = sgn(ay - by);
boulderspots = 0;
do {
/* <bx,by> is guaranteed to eventually converge with <ax,ay> */
bx += dx, by += dy;
if (IS_ROCK(levl[bx][by].typ) || closed_door(bx, by))
return FALSE;
if (sobj_at(BOULDER, bx, by)) ++boulderspots;
} while (bx != ax && by != ay);
/* reached target position without encountering obstacle */
if (boulderhandling == 1 || rn2(2 + boulderspots) < 2) return TRUE;
}
return FALSE;
}
@@ -730,7 +747,11 @@ boolean
lined_up(mtmp) /* is mtmp in position to use ranged attack? */
register struct monst *mtmp;
{
return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my));
boolean ignore_boulders = (throws_rocks(mtmp->data) ||
m_carrying(mtmp, WAN_STRIKING));
return linedup(mtmp->mux, mtmp->muy, mtmp->mx, mtmp->my,
ignore_boulders ? 1 : 2);
}
/* Check if a monster is carrying a particular item.

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)priest.c 3.5 2006/05/26 */
/* SCCS Id: @(#)priest.c 3.5 2006/12/27 */
/* Copyright (c) Izchak Miller, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */
@@ -710,9 +710,8 @@ struct monst *priest;
ay = y = EPRI(priest)->shrpos.y;
troom = &rooms[roomno - ROOMOFFSET];
if((u.ux == x && u.uy == y) || !linedup(u.ux, u.uy, x, y)) {
if ((u.ux == x && u.uy == y) || !linedup(u.ux, u.uy, x, y, 1)) {
if(IS_DOOR(levl[u.ux][u.uy].typ)) {
if(u.ux == troom->lx - 1) {
x = troom->hx;
y = u.uy;
@@ -734,7 +733,7 @@ struct monst *priest;
default: x = troom->hx; y = u.uy; break;
}
}
if(!linedup(u.ux, u.uy, x, y)) return;
if (!linedup(u.ux, u.uy, x, y, 1)) return;
}
switch(rn2(3)) {