From 200cc21fb3a31452c4448fa835ca595fcabfc488 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Wed, 19 Apr 2023 14:37:51 +0300 Subject: [PATCH] Allow some monsters to break boulders ... if the boulder is in a position they want to move to. Shopkeepers, priests, and the quest leader can break one boulder and then need to take several turns before being able to break another. Riders can break a boulder every turn. --- doc/fixes3-7-0.txt | 1 + include/extern.h | 2 ++ src/mon.c | 2 +- src/monmove.c | 35 +++++++++++++++++++++++++++++++++++ src/priest.c | 5 ++++- 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index c6faff6be4..f6ffcc5a91 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 e12f290a21..730ee3424e 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 232abc9763..c2e32f1341 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 f3b760a0db..f8f97c59df 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 8560d0c6b4..00779be5c0 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. */