-/* SCCS Id: @(#)mhitm.c 3.5 2007/02/07 */
+/* SCCS Id: @(#)mhitm.c 3.5 2007/04/02 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
#ifdef BARGETHROUGH
/*
- * mattackm() and mdisplacem() below both return a result bitfield:
- *
- * --------- aggressor died
- * / ------- defender died
- * / / ----- defender was hit
- * / / /
- * x x x
- *
- * 0x4 MM_AGR_DIED
- * 0x2 MM_DEF_DIED
- * 0x1 MM_HIT
- * 0x0 MM_MISS
- *
- */
-
-/*
- * mdisplacem() -- a monster moves another monster out of the way.
+ * mdisplacem() -- attacker moves defender out of the way;
+ * returns same results as mattackm().
*/
int
mdisplacem(magr, mdef, quietly)
boolean quietly;
{
struct permonst *pa, *pd;
- struct monst *mon; /* displaced monster */
- int tx = mdef->mx, ty = mdef->my; /* destination */
- int fx = magr->mx, fy = magr->my; /* current location */
- boolean struck = FALSE;
-
- pa = magr->data; pd = mdef->data;
+ int tx, ty, fx, fy;
+
+ /* sanity checks; could matter if we unexpectedly get a long worm */
+ if (!magr || !mdef || magr == mdef) return MM_MISS;
+ pa = magr->data, pd =mdef->data;
+ tx = mdef->mx, ty = mdef->my; /* destination */
+ fx = magr->mx, fy = magr->my; /* current location */
+ if (m_at(fx, fy) != magr || m_at(tx, ty) != mdef) return MM_MISS;
/* The 1 in 7 failure below matches the chance in attack()
* for pet displacement.
&& magr->my != mdef->my)
return(MM_MISS);
-
- /* undetected monsters become un-hidden if they are displaced */
- if (mdef->mundetected)
- mdef->mundetected = 0;
+ /* undetected monster becomes un-hidden if it is displaced */
+ if (mdef->mundetected) mdef->mundetected = 0;
+ if (mdef->m_ap_type && mdef->m_ap_type != M_AP_MONSTER) seemimic(mdef);
+ /* wake up the displaced defender */
+ mdef->msleeping = 0;
+ mdef->mstrategy &= ~STRAT_WAITMASK;
+ finish_meating(mdef);
/*
* Set up the visibility of action.
*/
vis = (canspotmon(magr) && canspotmon(mdef));
-
if (touch_petrifies(pd) && !resists_ston(magr)) {
if (which_armor(magr, W_ARMG) != 0) {
if (poly_when_stoned(pa)) {
if (!quietly && canspotmon(magr))
pline("%s turns to stone!", Monnam(magr));
monstone(magr);
- if (magr->mhp > 0) return 0;
+ if (magr->mhp > 0)
+ return MM_HIT; /* lifesaved */
else if (magr->mtame && !vis)
You(brief_feeling, "peculiarly sad");
return MM_AGR_DIED;
}
}
- if (m_at(fx, fy) == magr)
- remove_monster(fx, fy); /* pick up from orig position */
- if ((mon = m_at(tx, ty)) == mdef) {
- if (!quietly && (vis))
- pline("%s moves %s out of %s way!",
- Monnam(magr), mon_nam(mdef),
- is_rider(pa) ? "the" : mhis(magr));
- remove_monster(tx, ty);
- }
- place_monster(magr,tx,ty); /* put magr down */
-
- /* Restore original mon */
- if (mon) {
- if ((mon->mx != tx) || (mon->my != ty))
- place_worm_seg(mon, fx, fy);
- else
- place_monster(mon, fx, fy);
- struck = TRUE;
- } else
- remove_monster(fx, fy); /* shouldn't happen */
- newsym(fx,fy); /* see it */
- newsym(tx,ty); /* all happen */
+ remove_monster(fx, fy); /* pick up from orig position */
+ remove_monster(tx, ty);
+ place_monster(magr, tx, ty); /* put down at target spot */
+ place_monster(mdef, fx, fy);
+ if (vis && !quietly)
+ pline("%s moves %s out of %s way!",
+ Monnam(magr), mon_nam(mdef),
+ is_rider(pa) ? "the" : mhis(magr));
+ newsym(fx, fy); /* see it */
+ newsym(tx, ty); /* all happen */
flush_screen(0); /* make sure it shows up */
- /*
- * Wake up the displaced defender.
- */
- mdef->msleeping = 0;
-
- return(struck ? MM_HIT : MM_MISS);
+ return MM_HIT;
}
#endif /* BARGETHROUGH */
/*
* mattackm() -- a monster attacks another monster.
-#ifndef BARGETHROUGH
*
* --------- aggressor died
* / ------- defender died
* 0x1 MM_HIT
* 0x0 MM_MISS
*
-#endif
* Each successive attack has a lower probability of hitting. Some rely on the
* success of previous attacks. ** this doen't seem to be implemented -dl **
*
}
if (vis) pline("%s turns to stone!", Monnam(magr));
monstone(magr);
- if (magr->mhp > 0) return 0;
+ if (magr->mhp > 0)
+ return MM_HIT; /* lifesaved */
else if (magr->mtame && !vis)
You(brief_feeling, "peculiarly sad");
return MM_AGR_DIED;
struct monst *magr, /* monster that is currently deciding where to move */
*mdef; /* another monster which is next to it */
{
- struct permonst *pa = magr->data;
- struct permonst *pd = mdef->data;
- if ((pa->mflags3 & M3_DISPLACES) &&
- !is_longworm(pd) && /* no displacing longworms */
- !mdef->mtrapped && /* complex to do right */
- (is_rider(pa) || /* riders can move anything */
- pa->msize >= pd->msize)) /* same or smaller only */
+ struct permonst *pa = magr->data,
+ *pd = mdef->data;
+
+ /* if attacker can't barge through, there's nothing to do;
+ or if defender can barge through too, don't let attacker
+ do so, otherwise they might just end up swapping places
+ again when defender gets its chance to move */
+ if ((pa->mflags3 & M3_DISPLACES) != 0 &&
+ (pd->mflags3 & M3_DISPLACES) == 0 &&
+ /* no displacing trapped monsters or multi-location longworms */
+ !mdef->mtrapped && (!mdef->wormno || !count_wsegs(mdef)) &&
+ /* riders can move anything; others, same size or smaller only */
+ (is_rider(pa) || pa->msize >= pd->msize))
return ALLOW_MDISP;
return 0L;
}
/* Is the square close enough for the monster to move or attack into? */
{
register int distance = dist2(mon->mx, mon->my, x, y);
+
if (distance==2 && mon->data==&mons[PM_GRID_BUG]) return 0;
return((boolean)(distance < 3));
}