diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 1396e8c21..3afad9964 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -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 diff --git a/include/extern.h b/include/extern.h index 60aa32df4..e5370436a 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 *)); diff --git a/src/mthrowu.c b/src/mthrowu.c index 48b7af415..f258c9981 100644 --- a/src/mthrowu.c +++ b/src/mthrowu.c @@ -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 { + /* is guaranteed to eventually converge with */ + 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. diff --git a/src/priest.c b/src/priest.c index f791b01e0..1e60d104d 100644 --- a/src/priest.c +++ b/src/priest.c @@ -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)) {