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 *);
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 *);
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? */
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));
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);
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);
/* 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;
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));
/* 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;
/* 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--;
* jolted awake.
*/
static int
-disturb(register struct monst* mtmp)
+disturb(register struct monst *mtmp)
{
/*
* + Ettins are hard to surprise.
/* ungrab/expel held/swallowed hero */
static void
-release_hero(struct monst* mon)
+release_hero(struct monst *mon)
{
if (mon == u.ustuck) {
if (u.uswallow) {
}
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);
/* 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;
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);
(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.");
}
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;
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);
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) */