diff --git a/include/extern.h b/include/extern.h index 502035219..ee0a4dc75 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1559,6 +1559,7 @@ extern void mon_to_stone(struct monst *); extern void m_into_limbo(struct monst *); extern void migrate_mon(struct monst *, coordxy, coordxy); extern void mnexto(struct monst *, unsigned); +extern void deal_with_overcrowding(struct monst *); extern void maybe_mnexto(struct monst *); extern int mnearto(struct monst *, coordxy, coordxy, boolean, unsigned); extern void m_respond(struct monst *); @@ -1571,7 +1572,9 @@ extern void seemimic(struct monst *); extern void normal_shape(struct monst *); extern void iter_mons(void (*)(struct monst *)); extern struct monst *get_iter_mons(boolean (*)(struct monst *)); -extern struct monst *get_iter_mons_xy(boolean (*)(struct monst *, coordxy, coordxy), coordxy, coordxy); +extern struct monst *get_iter_mons_xy(boolean (*)(struct monst *, + coordxy, coordxy), + coordxy, coordxy); extern void rescham(void); extern void restartcham(void); extern void restore_cham(struct monst *); diff --git a/src/mhitm.c b/src/mhitm.c index 7bdd48495..a51dc9db5 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -719,7 +719,8 @@ engulf_target(struct monst *magr, struct monst *mdef) int dx, dy; /* can't swallow something that's too big */ - if (mdef->data->msize >= MZ_HUGE) + if (mdef->data->msize >= MZ_HUGE + || (magr->data->msize < mdef->data->msize && !is_whirly(magr->data))) return FALSE; /* can't (move to) swallow if trapped. TODO: could do some? */ diff --git a/src/mhitu.c b/src/mhitu.c index 3e9a13b7a..d7f3ced28 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1151,16 +1151,17 @@ gulpmu(struct monst *mtmp, struct attack *mattk) place_monster(mtmp, u.ux, u.uy); set_ustuck(mtmp); newsym(mtmp->mx, mtmp->my); - if (is_animal(mtmp->data) && u.usteed) { + /* 3.7: dismount for all engulfers, not just for purple worms */ + if (u.usteed) { char buf[BUFSZ]; - /* Too many quirks presently if hero and steed - * are swallowed. Pretend purple worms don't - * like horses for now :-) - */ Strcpy(buf, mon_nam(u.usteed)); - urgent_pline("%s lunges forward and plucks you off %s!", - Monnam(mtmp), buf); + urgent_pline("%s %s forward and plucks you off %s!", + Some_Monnam(mtmp), + is_animal(mtmp->data) ? "lunges" + : amorphous(mtmp->data) ? "oozes" + : "surges", + buf); dismount_steed(DISMOUNT_ENGULFED); } else { urgent_pline("%s engulfs you!", Monnam(mtmp)); @@ -1184,7 +1185,11 @@ gulpmu(struct monst *mtmp, struct attack *mattk) if (touch_petrifies(g.youmonst.data) && !resists_ston(mtmp)) { /* put the attacker back where it started; - the resulting statue will end up there */ + the resulting statue will end up there + [note: if poly'd hero could ride or non-poly'd hero could + acquire touch_petrifies() capability somehow, this code + would need to deal with possibility of steed having taken + engulfer's previous spot when hero was forcibly dismounted] */ remove_monster(mtmp->mx, mtmp->my); /* u.ux,u.uy */ place_monster(mtmp, omx, omy); minstapetrify(mtmp, TRUE); diff --git a/src/mon.c b/src/mon.c index 2e253a7d5..dd4c9a0af 100644 --- a/src/mon.c +++ b/src/mon.c @@ -20,7 +20,6 @@ static void m_detach(struct monst *, struct permonst *); static void set_mon_min_mhpmax(struct monst *, int); static void lifesaved_monster(struct monst *); static boolean ok_to_obliterate(struct monst *); -static void deal_with_overcrowding(struct monst *); static void m_restartcham(struct monst *); static boolean restrap(struct monst *); static int pick_animal(void); @@ -3444,7 +3443,7 @@ elemental_clog(struct monst *mon) /* make monster mtmp next to you (if possible); might place monst on far side of a wall or boulder */ void -mnexto(struct monst* mtmp, unsigned int rlocflags) +mnexto(struct monst *mtmp, unsigned int rlocflags) { coord mm; @@ -3463,8 +3462,8 @@ mnexto(struct monst* mtmp, unsigned int rlocflags) return; } -static void -deal_with_overcrowding(struct monst* mtmp) +void +deal_with_overcrowding(struct monst *mtmp) { if (In_endgame(&u.uz)) { debugpline1("overcrowding: elemental_clog on %s", m_monnam(mtmp)); @@ -3477,7 +3476,7 @@ deal_with_overcrowding(struct monst* mtmp) /* like mnexto() but requires destination to be directly accessible */ void -maybe_mnexto(struct monst* mtmp) +maybe_mnexto(struct monst *mtmp) { coord mm; struct permonst *ptr = mtmp->data; diff --git a/src/monmove.c b/src/monmove.c index 2a280f806..9608fdb52 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -218,9 +218,10 @@ onscary(coordxy x, coordxy y, struct monst* mtmp) /* regenerate lost hit points */ void -mon_regen(struct monst* mon, boolean digest_meal) +mon_regen(struct monst *mon, boolean digest_meal) { - if (mon->mhp < mon->mhpmax && (g.moves % 20 == 0 || regenerates(mon->data))) + if (mon->mhp < mon->mhpmax + && (g.moves % 20 == 0 || regenerates(mon->data))) mon->mhp++; if (mon->mspec_used) mon->mspec_used--; @@ -238,7 +239,7 @@ mon_regen(struct monst* mon, boolean digest_meal) * jolted awake. */ static int -disturb(register struct monst* mtmp) +disturb(register struct monst *mtmp) { /* * + Ettins are hard to surprise. @@ -273,7 +274,7 @@ disturb(register struct monst* mtmp) /* ungrab/expel held/swallowed hero */ static void -release_hero(struct monst* mon) +release_hero(struct monst *mon) { if (mon == u.ustuck) { if (u.uswallow) { @@ -416,7 +417,9 @@ monflee( } static void -distfleeck(register struct monst* mtmp, int* inrange, int* nearby, int* scared) +distfleeck( + struct monst *mtmp, + int *inrange, int *nearby, int *scared) /* output */ { int seescaryx, seescaryy; boolean sawscary = FALSE, bravegremlin = (rn2(5) == 0); @@ -1123,12 +1126,22 @@ m_move(register struct monst* mtmp, register int after) /* likewise for shopkeeper, guard, or priest */ if (mtmp->isshk || mtmp->isgd || mtmp->ispriest) { - int xm = mtmp->isshk ? shk_move(mtmp) : (mtmp->isgd ? gd_move(mtmp) : pri_move(mtmp)); + int xm = mtmp->isshk ? shk_move(mtmp) + : mtmp->isgd ? gd_move(mtmp) + : pri_move(mtmp); + switch (xm) { - case -2: return MMOVE_DIED; - case -1: mmoved = MMOVE_NOTHING; break; /* shk follow hero outside shop */ - case 0: mmoved = MMOVE_NOTHING; goto postmov; - case 1: mmoved = MMOVE_MOVED; goto postmov; + case -2: + return MMOVE_DIED; + case -1: + mmoved = MMOVE_NOTHING; /* shk follow hero outside shop */ + break; + case 0: + mmoved = MMOVE_NOTHING; + goto postmov; + case 1: + mmoved = MMOVE_MOVED; + goto postmov; default: impossible("unknown shk/gd/pri_move return value (%i)", xm); mmoved = MMOVE_NOTHING; goto postmov; @@ -1343,10 +1356,10 @@ m_move(register struct monst* mtmp, register int after) niy = omy; flag = mon_allowflags(mtmp); { - register int i, j, nx, ny, nearer; + int i, j, nx, ny, nearer; int jcnt, cnt; int ndist, nidist; - register coord *mtrk; + coord *mtrk; coord poss[9]; cnt = mfndpos(mtmp, poss, info, flag); diff --git a/src/steed.c b/src/steed.c index e9848c42e..515d35819 100644 --- a/src/steed.c +++ b/src/steed.c @@ -589,11 +589,13 @@ dismount_steed( (void) enexto(&steedcc, u.ux, u.uy, &mons[PM_GHOST]); } if (!m_at(steedcc.x, steedcc.y)) { - if (mtmp->mhp < 1) - mtmp->mhp = 0; /* make sure it isn't negative */ - mtmp->mhp++; /* force at least one hit point, possibly resurrecting */ + if (mtmp->mhp < 1) /* make sure it isn't negative so that */ + mtmp->mhp = 0; /* ++mhp produces a positive value */ + mtmp->mhp++; /* force at least one hit point, possibly resurrecting + * to avoid impossible("placing defunct monst on map") */ place_monster(mtmp, steedcc.x, steedcc.y); - mtmp->mhp--; /* take the extra hit point away: cancel resurrection */ + mtmp->mhp--; /* take the extra hit point away: cancel resurrection + * if former steed has died */ } else { impossible("Dismounting: can't place former steed on map."); } @@ -610,7 +612,9 @@ dismount_steed( return; } - /* Set hero's and/or steed's positions. Try moving the hero first. */ + /* Set hero's and/or steed's positions. Usually try moving the + hero first. Note: for DISMOUNT_ENGULFED, caller hasn't set + u.uswallow yet but has set u.ustuck. */ if (!u.uswallow && !u.ustuck && have_spot) { struct permonst *mdat = mtmp->data; @@ -673,8 +677,9 @@ dismount_steed( rloc_to(mtmp, cc.x, cc.y); /* Player stays put */ - /* Otherwise, kill the steed. */ + /* Otherwise, steed goes bye-bye. */ } else { +#if 1 /* original there's-no-room handling */ if (reason == DISMOUNT_BYCHOICE) { /* [un]#ride: hero gets credit/blame for killing steed */ killed(mtmp); @@ -684,6 +689,18 @@ dismount_steed( damage type is just "neither AD_DGST nor -AD_RBRE" */ monkilled(mtmp, "", -AD_PHYS); } +#else + /* Can't use this [yet?] because it violates monmove()'s + * assumption that a moving monster (engulfer) can't cause + * another monster (steed) to be removed from the fmon list. + * That other monster (steed) might be cached as the next one + * to move. + */ + /* migrate back to this level if hero leaves and returns + or to next level if it is happening in the endgame */ + mdrop_special_objs(mtmp); + deal_with_overcrowding(mtmp); +#endif } } /* !DEADMONST(mtmp) */