Esempio n. 1
0
/* Some spells are useless under some circumstances. */
static boolean spell_would_be_useless(struct monst *mtmp, unsigned int adtyp,
				      int spellnum)
{
    /* Some spells don't require the player to really be there and can be cast
     * by the monster when you're invisible, yet still shouldn't be cast when
     * the monster doesn't even think you're there.
     * This check isn't quite right because it always uses your real position.
     * We really want something like "if the monster could see mux, muy".
     */
    boolean mcouldseeu = couldsee(mtmp->mx, mtmp->my);

    if (adtyp == AD_SPEL) {
	/* aggravate monsters, etc. won't be cast by peaceful monsters */
	if (mtmp->mpeaceful && (spellnum == MGC_AGGRAVATION ||
		spellnum == MGC_SUMMON_MONS || spellnum == MGC_CLONE_WIZ))
	    return TRUE;
	/* haste self when already fast */
	if (mtmp->permspeed == MFAST && spellnum == MGC_HASTE_SELF)
	    return TRUE;
	/* invisibility when already invisible */
	if ((mtmp->minvis || mtmp->invis_blkd) && spellnum == MGC_DISAPPEAR)
	    return TRUE;
	/* peaceful monster won't cast invisibility if you can't see invisible,
	   same as when monsters drink potions of invisibility.  This doesn't
	   really make a lot of sense, but lets the player avoid hitting
	   peaceful monsters by mistake */
	if (mtmp->mpeaceful && !See_invisible && spellnum == MGC_DISAPPEAR)
	    return TRUE;
	/* healing when already healed */
	if (mtmp->mhp == mtmp->mhpmax && spellnum == MGC_CURE_SELF)
	    return TRUE;
	/* don't summon monsters if it doesn't think you're around */
	if (!mcouldseeu && (spellnum == MGC_SUMMON_MONS ||
		(!mtmp->iswiz && spellnum == MGC_CLONE_WIZ)))
	    return TRUE;
	if ((!mtmp->iswiz || flags.no_of_wizards > 1)
						&& spellnum == MGC_CLONE_WIZ)
	    return TRUE;
    } else if (adtyp == AD_CLRC) {
	/* summon insects/sticks to snakes won't be cast by peaceful monsters */
	if (mtmp->mpeaceful && spellnum == CLC_INSECTS)
	    return TRUE;
	/* healing when already healed */
	if (mtmp->mhp == mtmp->mhpmax && spellnum == CLC_CURE_SELF)
	    return TRUE;
	/* don't summon insects if it doesn't think you're around */
	if (!mcouldseeu && spellnum == CLC_INSECTS)
	    return TRUE;
	/* blindness spell on blinded player */
	if (Blinded && spellnum == CLC_BLIND_YOU)
	    return TRUE;
    }
    return FALSE;
}
Esempio n. 2
0
static bool clear_fcorr(struct monst *grd, bool forceshow) {
    int fcx, fcy, fcbeg;
    struct monst *mtmp;

    if (!on_level(&(EGD(grd)->gdlevel), &u.uz))
        return true;

    while ((fcbeg = EGD(grd)->fcbeg) < EGD(grd)->fcend) {
        fcx = EGD(grd)->fakecorr[fcbeg].fx;
        fcy = EGD(grd)->fakecorr[fcbeg].fy;
        if ((grd->mhp <= 0 || !in_fcorridor(grd, u.ux, u.uy)) &&
        EGD(grd)->gddone)
            forceshow = true;
        if ((u.ux == fcx && u.uy == fcy && grd->mhp > 0) || (!forceshow && couldsee(fcx, fcy)) || (Punished && !carried(uball) && uball->ox == fcx && uball->oy == fcy))
            return false;

        if ((mtmp = m_at(fcx, fcy)) != 0) {
            if (mtmp->isgd)
                return (false);
            else if (!in_fcorridor(grd, u.ux, u.uy)) {
                if (mtmp->mtame)
                    yelp(mtmp);
                (void)rloc(mtmp, false);
            }
        }
        levl[fcx][fcy].typ = EGD(grd)->fakecorr[fcbeg].ftyp;
        map_location(fcx, fcy, 1); /* bypass vision */
        if (!ACCESSIBLE(levl[fcx][fcy].typ))
            block_point(fcx, fcy);
        EGD(grd)->fcbeg++;
    }
    if (grd->mhp <= 0) {
        pline_The("corridor disappears.");
        if (IS_ROCK(levl[u.ux][u.uy].typ))
            You("are encased in rock.");
    }
    return (true);
}
Esempio n. 3
0
/* feedback when frustrated monster couldn't cast a spell */
static void cursetxt(struct monst *mtmp, boolean undirected)
{
	if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my)) {
	    const char *point_msg;  /* spellcasting monsters are impolite */

	    if (undirected)
		point_msg = "all around, then curses";
	    else if ((Invis && !perceives(mtmp->data) &&
			(mtmp->mux != u.ux || mtmp->muy != u.uy)) ||
		    (youmonst.m_ap_type == M_AP_OBJECT &&
			youmonst.mappearance == STRANGE_OBJECT) ||
		    u.uundetected)
		point_msg = "and curses in your general direction";
	    else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy))
		point_msg = "and curses at your displaced image";
	    else
		point_msg = "at you, then curses";

	    pline("%s points %s.", Monnam(mtmp), point_msg);
	} else if (!(moves % 4) || !rn2(4)) {
	    if (flags.soundok) Norep("You hear a mumbled curse.");
	}
}
Esempio n. 4
0
int dogaze(void)
{
	struct monst *mtmp;
	int looked = 0;
	char qbuf[QBUFSZ];
	int i;
	uchar adtyp = 0;

	for (i = 0; i < NATTK; i++) {
	    if (youmonst.data->mattk[i].aatyp == AT_GAZE) {
		adtyp = youmonst.data->mattk[i].adtyp;
		break;
	    }
	}
	if (adtyp != AD_CONF && adtyp != AD_FIRE) {
	    impossible("gaze attack %d?", adtyp);
	    return 0;
	}


	if (Blind) {
	    pline("You can't see anything to gaze at.");
	    return 0;
	}
	if (u.uen < 15) {
	    pline("You lack the energy to use your special gaze!");
	    return 0;
	}
	u.uen -= 15;
	iflags.botl = 1;

	for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
	    if (DEADMONSTER(mtmp)) continue;
	    if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my)) {
		looked++;
		if (Invis && !perceives(mtmp->data))
		    pline("%s seems not to notice your gaze.", Monnam(mtmp));
		else if (mtmp->minvis && !See_invisible)
		    pline("You can't see where to gaze at %s.", Monnam(mtmp));
		else if (mtmp->m_ap_type == M_AP_FURNITURE
			|| mtmp->m_ap_type == M_AP_OBJECT) {
		    looked--;
		    continue;
		} else if (flags.safe_dog && !Confusion && !Hallucination
		  && mtmp->mtame) {
		    pline("You avoid gazing at %s.", y_monnam(mtmp));
		} else {
		    if (flags.confirm && mtmp->mpeaceful && !Confusion
							&& !Hallucination) {
			sprintf(qbuf, "Really %s %s?",
			    (adtyp == AD_CONF) ? "confuse" : "attack",
			    mon_nam(mtmp));
			if (yn(qbuf) != 'y') continue;
			setmangry(mtmp);
		    }
		    if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleeping ||
				    !mtmp->mcansee || !haseyes(mtmp->data)) {
			looked--;
			continue;
		    }
		    /* No reflection check for consistency with when a monster
		     * gazes at *you*--only medusa gaze gets reflected then.
		     */
		    if (adtyp == AD_CONF) {
			if (!mtmp->mconf)
			    pline("Your gaze confuses %s!", mon_nam(mtmp));
			else
			    pline("%s is getting more and more confused.",
							Monnam(mtmp));
			mtmp->mconf = 1;
		    } else if (adtyp == AD_FIRE) {
			int dmg = dice(2,6);
			pline("You attack %s with a fiery gaze!", mon_nam(mtmp));
			if (resists_fire(mtmp)) {
			    pline("The fire doesn't burn %s!", mon_nam(mtmp));
			    dmg = 0;
			}
			if ((int) u.ulevel > rn2(20))
			    destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
			if ((int) u.ulevel > rn2(20))
			    destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
			if ((int) u.ulevel > rn2(25))
			    destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
			if (dmg && !DEADMONSTER(mtmp)) mtmp->mhp -= dmg;
			if (mtmp->mhp <= 0) killed(mtmp);
		    }
		    /* For consistency with passive() in uhitm.c, this only
		     * affects you if the monster is still alive.
		     */
		    if (!DEADMONSTER(mtmp) &&
			  (mtmp->data==&mons[PM_FLOATING_EYE]) && !mtmp->mcan) {
			if (!Free_action) {
			    pline("You are frozen by %s gaze!",
					     s_suffix(mon_nam(mtmp)));
			    nomul((u.ulevel > 6 || rn2(4)) ?
				    -dice((int)mtmp->m_lev+1,
					    (int)mtmp->data->mattk[0].damd)
				    : -200, "frozen by a monster's gaze");
			    return 1;
			} else
			    pline("You stiffen momentarily under %s gaze.",
				    s_suffix(mon_nam(mtmp)));
		    }
		    /* Technically this one shouldn't affect you at all because
		     * the Medusa gaze is an active monster attack that only
		     * works on the monster's turn, but for it to *not* have an
		     * effect would be too weird.
		     */
		    if (!DEADMONSTER(mtmp) &&
			    (mtmp->data == &mons[PM_MEDUSA]) && !mtmp->mcan) {
			pline(
			 "Gazing at the awake %s is not a very good idea.",
			    l_monnam(mtmp));
			/* as if gazing at a sleeping anything is fruitful... */
			pline("You turn to stone...");
			killer_format = KILLED_BY;
			killer = "deliberately meeting Medusa's gaze";
			done(STONING);
		    }
		}
	    }
	}
	if (!looked) pline("You gaze at no place in particular.");
	return 1;
}
Esempio n. 5
0
/*
 * Pick coordinates for a starting position for the mail daemon.  Called
 * from newmail() and newphone().
 */
STATIC_OVL boolean
md_start(coord *startp)
{
    coord testcc;	/* scratch coordinates */
    int row;		/* current row we are checking */
    int lax;		/* if TRUE, pick a position in sight. */
    int dd;		/* distance to current point */
    int max_distance;	/* max distance found so far */

    /*
     * If blind and not telepathic, then it doesn't matter what we pick ---
     * the hero is not going to see it anyway.  So pick a nearby position.
     */
    if (Blind && !Blind_telepat) {
        if (!enexto(startp, u.ux, u.uy, (struct permonst *) 0))
            return FALSE;	/* no good posiitons */
        return TRUE;
    }

    /*
     * Arrive at an up or down stairwell if it is in line of sight from the
     * hero.
     */
    if (couldsee(upstair.sx, upstair.sy)) {
        startp->x = upstair.sx;
        startp->y = upstair.sy;
        return TRUE;
    }
    if (couldsee(dnstair.sx, dnstair.sy)) {
        startp->x = dnstair.sx;
        startp->y = dnstair.sy;
        return TRUE;
    }

    /*
     * Try to pick a location out of sight next to the farthest position away
     * from the hero.  If this fails, try again, just picking the farthest
     * position that could be seen.  What we really ought to be doing is
     * finding a path from a stairwell...
     *
     * The arrays viz_rmin[] and viz_rmax[] are set even when blind.  These
     * are the LOS limits for each row.
     */
    lax = 0;	/* be picky */
    max_distance = -1;
retry:
    for (row = 0; row < ROWNO; row++) {
        if (viz_rmin[row] < viz_rmax[row]) {
            /* There are valid positions on this row. */
            dd = distu(viz_rmin[row],row);
            if (dd > max_distance) {
                if (lax) {
                    max_distance = dd;
                    startp->y = row;
                    startp->x = viz_rmin[row];

                } else if (enexto(&testcc, (xchar)viz_rmin[row], row,
                                  (struct permonst *) 0) &&
                           !cansee(testcc.x, testcc.y) &&
                           couldsee(testcc.x, testcc.y)) {
                    max_distance = dd;
                    *startp = testcc;
                }
            }
            dd = distu(viz_rmax[row],row);
            if (dd > max_distance) {
                if (lax) {
                    max_distance = dd;
                    startp->y = row;
                    startp->x = viz_rmax[row];

                } else if (enexto(&testcc, (xchar)viz_rmax[row], row,
                                  (struct permonst *) 0) &&
                           !cansee(testcc.x,testcc.y) &&
                           couldsee(testcc.x, testcc.y)) {

                    max_distance = dd;
                    *startp = testcc;
                }
            }
        }
    }

    if (max_distance < 0) {
        if (!lax) {
            lax = 1;		/* just find a position */
            goto retry;
        }
        return FALSE;
    }

    return TRUE;
}
Esempio n. 6
0
/* Is a monster willing to fire with a compass beam in a given direction?

   Returns TRUE and sets *mdef to a monster if there's a monster it wants to
   target (and no monster it doesn't want to attack). *mdef can be &youmonst.

   If mdef is non-NULL, also set the tbx/tby globals for backwards compatibility
   (clobbered on a *mdef == NULL return, appropriately otherwise). TODO: get rid
   of these, they're really spaghetti.

   Returns TRUE and sets *mdef to NULL if there's no reason it wants to fire
   in that direction, but no reason it dislikes firing in that direction
   either.

   Returns FALSE if the monster refuses to fire in that direction. In this
   case, *mdef will be a monster that we don't want to target (possibly
   &youmonst).
   
   helpful determines whether or not a beam gives a positive effect */
boolean
m_beam_ok(struct monst *magr, int dx, int dy, struct monst **mdef, boolean helpful)
{
    int x = magr->mx;
    int y = magr->my;
    int i;
    struct monst *mat;

    if (mdef)
        *mdef = NULL;

    for (i = 0; i < BOLT_LIM; i++) {
        x += dx;
        y += dy;

        /* Will the beam stop at this point? As usual, assume that monsters have
           perfect knowledge of the level layout. */
        if (!isok(x, y) || !ZAP_POS(level->locations[x][y].typ) ||
            closed_door(level, x, y))
            break;

        /* Will the monster think that the beam will hit the player? Does it
           care? Hostiles like to attack the player; peacefuls don't want to.
           Pets have perfect knowledge of their master's location even if they
           can't sense their master. Confused monsters can't aim a beam at the
           player (or to avoid the player); no monster can hit an engulfed
           player with a beam. */
        if ((x == magr->mux && y == magr->muy && msensem(magr, &youmonst)) ||
            (magr->mtame && x == u.ux && y == u.uy)) {
            if (!Engulfed && !magr->mconf) {
                if (mdef) {
                    *mdef = &youmonst;
                    tbx = x - magr->mx;
                    tby = y - magr->my;
                }

                if (!Conflict) {
                    if ((!helpful && magr->mpeaceful) ||
                        (helpful && !magr->mpeaceful))
                    return FALSE;
                }
            }
        }

        mat = m_at(level, x, y);

        /* special case: make sure we don't hit the quest leader with stray
           beams, as it can make the game unwinnable; do this regardless of LOS
           or hostility or Conflict or confusion or anything like that */
        if (mat && mat->data->msound == MS_LEADER && !helpful) {
            if (mdef)
                *mdef = mat;
            return FALSE;
        }

        /* Confused monsters aren't trying to target anything in particular,
           because they don't have full control of their actions. Monsters won't
           intentionally aim at or to avoid a monster they can't see (apart from
           the above MS_LEADER case). */
        if (mat && (msensem(magr, mat) & ~MSENSE_ITEMMIMIC) && !magr->mconf) {
            /* Note: the couldsee() here is an LOE check and has nothing to
               do with vision; it determines conflict radius */
            if (Conflict && !resist(magr, RING_CLASS, 0, 0) &&
                couldsee(magr->mx, magr->my) &&
                distu(magr->mx, magr->my) <= BOLT_LIM * BOLT_LIM) {
                /* we're conflicted, anything is a valid target */
                if (mdef) {
                    *mdef = mat;
                    tbx = x - magr->mx;
                    tby = y - magr->my;
                }
            } else if (mm_aggression(magr, mat) & ALLOW_M && !helpful) {
                /* we want to target this monster */
                if (mdef) {
                    *mdef = mat;
                    tbx = x - magr->mx;
                    tby = y - magr->my;
                }
            } else if (!helpful && (magr->mpeaceful || mat->mpeaceful)) {
                /* we don't want to attack this monster; peacefuls (including
                   pets) should avoid collateral damage; also handles the
                   pet_attacks_up_to_difficulty checks; symmetrised so that
                   hostiles won't attack pets who won't attack them */
                if (mdef)
                    *mdef = mat;
                return FALSE;
            } else if (helpful &&
                       ((magr->mpeaceful && mat->mpeaceful) ||
                        (!magr->mpeaceful && !mat->mpeaceful))) {
                /* helpful beam, hostile-hostile or peaceful/tame-peaceful/tame
                   is OK; the peaceful checks aren't redundant with above since
                   pet_attacks_up_to_difficulty is a thing */
                if (mdef) {
                    *mdef = mat;
                    tbx = x - magr->mx;
                    tby = y - magr->my;
                }
            }
        }
    }

    return TRUE;
}
Esempio n. 7
0
/* monster attempts ranged weapon attack against a square */
void
thrwmq(struct monst *mtmp, int xdef, int ydef)
{
    struct obj *otmp, *mwep;
    schar skill;
    int multishot;
    const char *onm;

    /* Rearranged beginning so monsters can use polearms not in a line */
    if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
        mtmp->weapon_check = NEED_RANGED_WEAPON;
        /* mon_wield_item resets weapon_check as appropriate */
        if (mon_wield_item(mtmp) != 0)
            return;
    }

    /* Pick a weapon */
    otmp = select_rwep(mtmp);
    if (!otmp)
        return;

    if (is_pole(otmp)) {
        int dam, hitv;

        if (otmp != MON_WEP(mtmp))
            return;  /* polearm must be wielded */

        /* TODO: LOE function between two arbitrary points. */
        if (dist2(mtmp->mx, mtmp->my, xdef, ydef) > POLE_LIM ||
            (xdef == u.ux && ydef == u.uy && !couldsee(mtmp->mx, mtmp->my)))
            return;     /* Out of range, or intervening wall */

        if (mon_visible(mtmp)) {
            onm = singular(otmp, xname);
            pline("%s thrusts %s.", Monnam(mtmp),
                  obj_is_pname(otmp) ? the(onm) : an(onm));
        }

        if (xdef == u.ux && ydef == u.uy) {

            dam = dmgval(otmp, &youmonst);
            hitv = 3 - distmin(u.ux, u.uy, mtmp->mx, mtmp->my);
            if (hitv < -4)
                hitv = -4;
            if (bigmonst(youmonst.data))
                hitv++;
            hitv += 8 + otmp->spe;
            if (objects[otmp->otyp].oc_class == WEAPON_CLASS ||
                objects[otmp->otyp].oc_class == VENOM_CLASS)
                hitv += objects[otmp->otyp].oc_hitbon;
            if (dam < 1)
                dam = 1;

            thitu(hitv, dam, otmp, NULL);
            action_interrupted();

        } else if (MON_AT(level, xdef, ydef))
            (void)ohitmon(m_at(level, xdef, ydef), otmp, 0, FALSE);
        else if (mon_visible(mtmp))
            pline("But it misses wildly.");

        return;
    }

    if (!qlined_up(mtmp, xdef, ydef, FALSE, FALSE) ||
        !ai_use_at_range(BOLT_LIM - distmin(mtmp->mx, mtmp->my, xdef, ydef)))
        return;

    skill = objects[otmp->otyp].oc_skill;
    mwep = MON_WEP(mtmp);       /* wielded weapon */

    /* Multishot calculations */
    multishot = 1;
    if ((ammo_and_launcher(otmp, mwep) || skill == P_DAGGER || skill == -P_DART
         || skill == -P_SHURIKEN) && !mtmp->mconf) {
        /* Assumes lords are skilled, princes are expert */
        if (is_prince(mtmp->data))
            multishot += 2;
        else if (is_lord(mtmp->data))
            multishot++;

        switch (monsndx(mtmp->data)) {
        case PM_RANGER:
            multishot++;
            break;
        case PM_ROGUE:
            if (skill == P_DAGGER)
                multishot++;
            break;
        case PM_NINJA:
        case PM_SAMURAI:
            if (otmp->otyp == YA && mwep && mwep->otyp == YUMI)
                multishot++;
            break;
        default:
            break;
        }
        /* racial bonus */
        if ((is_elf(mtmp->data) && otmp->otyp == ELVEN_ARROW && mwep &&
             mwep->otyp == ELVEN_BOW) || (is_orc(mtmp->data) &&
                                          otmp->otyp == ORCISH_ARROW && mwep &&
                                          mwep->otyp == ORCISH_BOW))
            multishot++;

        if ((long)multishot > otmp->quan)
            multishot = (int)otmp->quan;
        if (multishot < 1)
            multishot = 1;
        else
            multishot = rnd(multishot);
    }

    if (mon_visible(mtmp)) {
        if (multishot > 1) {
            /* "N arrows"; multishot > 1 implies otmp->quan > 1, so xname()'s
               result will already be pluralized */
            onm = msgprintf("%d %s", multishot, xname(otmp));
        } else {
            /* "an arrow" */
            onm = singular(otmp, xname);
            onm = obj_is_pname(otmp) ? the(onm) : an(onm);
        }
        m_shot.s = ammo_and_launcher(otmp, mwep) ? TRUE : FALSE;
        pline("%s %s %s!", Monnam(mtmp), m_shot.s ? "shoots" : "throws", onm);
        m_shot.o = otmp->otyp;
    } else {
        m_shot.o = STRANGE_OBJECT;      /* don't give multishot feedback */
    }

    m_shot.n = multishot;
    for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) {
        m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
                distmin(mtmp->mx, mtmp->my, xdef, ydef), otmp, TRUE);
        /* conceptually all N missiles are in flight at once, but
           if mtmp gets killed (shot kills adjacent gas spore and
           triggers explosion, perhaps), inventory will be dropped
           and otmp might go away via merging into another stack;
           if we then use it, we could cause undefined behavior */
        if (mtmp->mhp <= 0 && m_shot.i < m_shot.n) {
            /* cancel pending shots (ought to give a message here since
               we gave one above about throwing/shooting N missiles) */
            break;  /* endmultishot(FALSE); */
        }
    }
    m_shot.n = m_shot.i = 0;
    m_shot.o = STRANGE_OBJECT;
    m_shot.s = FALSE;

    action_interrupted();
}
Esempio n. 8
0
static boolean
clear_fcorr(struct monst *grd, boolean forceshow)
{
    int fcx, fcy, fcbeg, oldtyp;
    struct monst *mtmp;
    boolean showmsg = FALSE;

    if (!on_level(&(EGD(grd)->gdlevel), &u.uz))
        return TRUE;

    while ((fcbeg = EGD(grd)->fcbeg) < EGD(grd)->fcend) {
        fcx = EGD(grd)->fakecorr[fcbeg].fx;
        fcy = EGD(grd)->fakecorr[fcbeg].fy;
        if ((grd->mhp <= 0 || !in_fcorridor(grd, u.ux, u.uy)) &&
            EGD(grd)->gddone)
            forceshow = TRUE;
        if ((u.ux == fcx && u.uy == fcy && grd->mhp > 0)
            || (!forceshow && couldsee(fcx, fcy)))
            return FALSE;

        if ((Punished && !carried(uball)
             && uball->ox == fcx && uball->oy == fcy)) {
            unplacebc();
            placebc();
        }

        if ((mtmp = m_at(level, fcx, fcy)) != 0) {
            if (mtmp->isgd)
                return FALSE;
            else if (!in_fcorridor(grd, u.ux, u.uy)) {
                if (mtmp->mtame)
                    yelp(mtmp);
                rloc(mtmp, FALSE);
            }
        }
        oldtyp = level->locations[fcx][fcy].typ;
        level->locations[fcx][fcy].typ = EGD(grd)->fakecorr[fcbeg].ftyp;
        if (!ACCESSIBLE(level->locations[fcx][fcy].typ) && ACCESSIBLE(oldtyp)) {
            struct trap *t = t_at(level, fcx, fcy);

            if (couldsee(fcx, fcy))
                showmsg = TRUE;
            if (t)
                deltrap(level, t);
            level->locations[fcx][fcy].lit = FALSE;
            block_point(fcx, fcy);
        }
        map_location(fcx, fcy, 1, FALSE);      /* bypass vision */
        EGD(grd)->fcbeg++;
    }
    if (grd->mhp <= 0) {
        if (showmsg) {
            if (!Blind)
                pline("The corridor disappears.");
            else
                pline("You feel claustrophobic.");
        }
        if (IS_ROCK(level->locations[u.ux][u.uy].typ))
            pline("You are encased in rock.");
    }
    return TRUE;
}
Esempio n. 9
0
int dogaze(void) {
        struct monst *mtmp;
        int looked = 0;
        char qbuf[QBUFSZ];
        int i;
        unsigned char adtyp = 0;

        for (i = 0; i < NATTK; i++) {
            if(youmonst.data->mattk[i].aatyp == AT_GAZE) {
                adtyp = youmonst.data->mattk[i].adtyp;
                break;
            }
        }
        if (adtyp != AD_CONF && adtyp != AD_FIRE) {
            impossible("gaze attack %d?", adtyp);
            return 0;
        }


        if (Blind()) {
            You_cant("see anything to gaze at.");
            return 0;
        }
        if (u.uen < 15) {
            You("lack the energy to use your special gaze!");
            return(0);
        }
        u.uen -= 15;

        for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
            if (DEADMONSTER(mtmp)) continue;
            if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my)) {
                looked++;
                if (Invis && !perceives(mtmp->data)) {
                    message_monster(MSG_M_SEEMS_NOT_NOTICE_GAZE, mtmp);
                } else if (mtmp->minvis && !See_invisible()) {
                    message_monster(MSG_YOU_CANT_SEE_WHERE_GAZE_M, mtmp);
                } else if (mtmp->m_ap_type == M_AP_FURNITURE || mtmp->m_ap_type == M_AP_OBJECT) {
                    looked--;
                    continue;
                } else if (flags.safe_dog && !Confusion() && !Hallucination() && mtmp->mtame) {
                    message_monster(MSG_YOU_AVOID_GAZING_AT_M, mtmp);
                } else {
                    if (flags.confirm && mtmp->mpeaceful && !Confusion()
                                                        && !Hallucination()) {
                        sprintf(qbuf, "Really %s %s?",
                            (adtyp == AD_CONF) ? "confuse" : "attack", "TODO: mon_nam(mtmp)");
                        if (yn(qbuf) != 'y') continue;
                        setmangry(mtmp);
                    }
                    if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleeping ||
                                    !mtmp->mcansee || !haseyes(mtmp->data))
                    {
                        looked--;
                        continue;
                    }
                    /* No reflection check for consistency with when a monster
                     * gazes at *you*--only medusa gaze gets reflected then.
                     */
                    if (adtyp == AD_CONF) {
                        if (!mtmp->mconf) {
                            message_monster(MSG_GAZE_CONFUSES_M, mtmp);
                        } else {
                            message_monster(MSG_M_GETTING_MORE_CONFUSED, mtmp);
                        }
                        mtmp->mconf = 1;
                    } else if (adtyp == AD_FIRE) {
                        int dmg = d(2,6);
                        message_monster(MSG_ATTACK_M_WITH_FIERY_GAZE, mtmp);
                        if (resists_fire(mtmp)) {
                            message_monster(MSG_FIRE_DOES_NOT_BURN_M, mtmp);
                            dmg = 0;
                        }
                        if((int) u.ulevel > rn2(20))
                            (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
                        if((int) u.ulevel > rn2(20))
                            (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
                        if((int) u.ulevel > rn2(25))
                            (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
                        if (dmg && !DEADMONSTER(mtmp)) mtmp->mhp -= dmg;
                        if (mtmp->mhp <= 0) killed(mtmp);
                    }
                    /* For consistency with passive() in uhitm.c, this only
                     * affects you if the monster is still alive.
                     */
                    if (!DEADMONSTER(mtmp) &&
                          (mtmp->data==&mons[PM_FLOATING_EYE]) && !mtmp->mcan) {
                        if (!Free_action) {
                            message_monster(MSG_YOU_ARE_FROZEN_BY_M_GAZE, mtmp);
                            nomul((u.ulevel > 6 || rn2(4)) ?
                                    -d((int)mtmp->m_lev+1,
                                            (int)mtmp->data->mattk[0].damd)
                                    : -200);
                            return 1;
                        } else {
                            message_monster(MSG_STIFFEN_MOMENTARILY_UNDER_M_GAZE, mtmp);
                        }
                    }
                    /* Technically this one shouldn't affect you at all because
                     * the Medusa gaze is an active monster attack that only
                     * works on the monster's turn, but for it to *not* have an
                     * effect would be too weird.
                     */
                    if (!DEADMONSTER(mtmp) && (mtmp->data == &mons[PM_MEDUSA]) && !mtmp->mcan) {
                        message_monster(MSG_GAZING_AT_AWAKE_MEDUSA_BAD_IDEA, mtmp);
                        /* as if gazing at a sleeping anything is fruitful... */
                        You("turn to stone...");
                        killer = killed_by_const(KM_DELIBERATELY_MEETING_MEDUSA_GAZE);
                        done(KM_STONING);
                    }
                }
            }
        }
        if (!looked) You("gaze at no place in particular.");
        return 1;
}