diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index c6faff6be..f6ffcc5a9 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1147,6 +1147,7 @@ prevent hug attacks and touch or engulf attacks for wrap, stick-to, and digestion damage from succeeding against unsolid targets (ghosts, vortices, a few others) wand of speed gives temporary speed, potion gives intrinsic +some monsters (riders, shopkeepers, priests, quest leader) can break boulders Fixes to 3.7.0-x General Problems Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index e12f290a2..730ee3424 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1711,6 +1711,8 @@ extern struct monst *find_pmmonst(int); extern int bee_eat_jelly(struct monst *, struct obj *); extern void monflee(struct monst *, int, boolean, boolean); extern void mon_yells(struct monst *, const char *); +extern boolean m_can_break_boulder(struct monst *); +extern void m_break_boulder(struct monst *, coordxy, coordxy); extern int dochug(struct monst *); extern boolean m_digweapon_check(struct monst *, coordxy, coordxy); extern int m_move(struct monst *, int); diff --git a/src/mon.c b/src/mon.c index 232abc976..c2e32f134 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1829,7 +1829,7 @@ mon_allowflags(struct monst* mtmp) allowflags |= ALLOW_SSM | ALLOW_SANCT; if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK | ALLOW_WALL); - if (throws_rocks(mtmp->data)) + if (throws_rocks(mtmp->data) || m_can_break_boulder(mtmp)) allowflags |= ALLOW_ROCK; if (can_tunnel) allowflags |= ALLOW_DIG; diff --git a/src/monmove.c b/src/monmove.c index f3b760a0d..f8f97c59d 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -104,6 +104,36 @@ mon_yells(struct monst* mon, const char* shout) } } +/* can monster mtmp break boulders? */ +boolean +m_can_break_boulder(struct monst *mtmp) +{ + return (is_rider(mtmp->data) + || (!mtmp->mspec_used + && (mtmp->isshk || mtmp->ispriest + || (mtmp->data->msound == MS_LEADER)))); +} + +/* monster mtmp breaks boulder at x,y */ +void +m_break_boulder(struct monst *mtmp, coordxy x, coordxy y) +{ + struct obj *otmp; + + if (m_can_break_boulder(mtmp) && ((otmp = sobj_at(BOULDER, x, y)) != 0)) { + if (!is_rider(mtmp->data)) { + if (!Deaf && (mdistu(mtmp) < 4*4)) + pline("%s mutters %s.", + Monnam(mtmp), + mtmp->ispriest ? "a prayer" : "an incantation"); + mtmp->mspec_used += rn1(20, 10); + } + if (cansee(x, y)) + pline_The("boulder falls apart."); + fracture_rock(otmp); + } +} + static void watch_on_duty(register struct monst* mtmp) { @@ -1536,6 +1566,11 @@ m_move(register struct monst* mtmp, register int after) if (!m_in_out_region(mtmp, nix, niy)) return MMOVE_DONE; + if ((info[chi] & ALLOW_ROCK) && m_can_break_boulder(mtmp)) { + (void) m_break_boulder(mtmp, nix, niy); + return MMOVE_DONE; + } + /* move a normal monster; for a long worm, remove_monster() and place_monster() only manipulate the head; they leave tail as-is */ remove_monster(omx, omy); diff --git a/src/priest.c b/src/priest.c index 8560d0c6b..00779be5c 100644 --- a/src/priest.c +++ b/src/priest.c @@ -101,7 +101,10 @@ move_special(struct monst *mtmp, boolean in_his_shop, schar appr, if (nix != omx || niy != omy) { - if (ninfo & ALLOW_M) { + if (ninfo & ALLOW_ROCK) { + m_break_boulder(mtmp, nix, niy); + return 1; + } else if (ninfo & ALLOW_M) { /* mtmp is deciding it would like to attack this turn. * Returns from m_move_aggress don't correspond to the same things * as this function should return, so we need to translate. */