Exemple #1
0
static int stealarm (void) {
    struct monst *mtmp;
    struct obj *otmp;

    for(otmp = invent; otmp; otmp = otmp->nobj) {
        if(otmp->o_id == stealoid) {
            for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
                if(mtmp->m_id == stealmid) {
                    if(DEADMONSTER(mtmp)) impossible("stealarm(): dead monster stealing");
                    if(!dmgtype(mtmp->data, AD_SITM)) /* polymorphed */
                        goto botm;
                    if(otmp->unpaid)
                        subfrombill(otmp, shop_keeper(*u.ushops));
                    freeinv(otmp);
                    message_monster_object(MSG_M_STEALS_O, mtmp, otmp);
                    mpickobj(mtmp,otmp);     /* may free otmp */
                    /* Implies seduction, "you gladly hand over ..."
                       so we don't set mavenge bit here. */
                    monflee(mtmp, 0, false, false);
                    if (!tele_restrict(mtmp)) (void) rloc(mtmp, false);
                    break;
                }
            }
            break;
        }
    }
botm:   stealoid = 0;
        return 0;
}
Exemple #2
0
/* Charm snakes in range.  Note that the snakes are NOT tamed. */
static void
charm_snakes(int distance)
{
    struct monst *mtmp = level->monlist;
    int could_see_mon, was_peaceful;

    while (mtmp) {
        if (!DEADMONSTER(mtmp) && mtmp->data->mlet == S_SNAKE && mtmp->mcanmove
            && distu(mtmp->mx, mtmp->my) < distance) {
            was_peaceful = mtmp->mpeaceful;
            mtmp->mavenge = 0;
            could_see_mon = canspotmon(mtmp);
            mtmp->mundetected = 0;
            msethostility(mtmp, FALSE, FALSE); /* does a newsym() */
            if (canseemon(mtmp)) {
                if (!could_see_mon)
                    pline(msgc_youdiscover,
                          "You notice %s, swaying with the music.",
                          a_monnam(mtmp));
                else
                    pline(msgc_actionok,
                          "%s freezes, then sways with the music%s.",
                          Monnam(mtmp),
                          was_peaceful ? "" : ", and now seems quieter");
            }
        }
        mtmp = mtmp->nmon;
    }
}
Exemple #3
0
static int stealarm(void)
{
	struct monst *mtmp;
	struct obj *otmp;

	for (otmp = invent; otmp; otmp = otmp->nobj) {
	    if (otmp->o_id == stealoid) {
		for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
		    if (mtmp->m_id == stealmid) {
			if (DEADMONSTER(mtmp)) warning("stealarm(): dead monster stealing");
			if (!dmgtype(mtmp->data, AD_SITM)) /* polymorphed */
			    goto botm;
			if (otmp->unpaid)
			    subfrombill(otmp, shop_keeper(level, *u.ushops));
			freeinv(otmp);
			pline("%s steals %s!", Monnam(mtmp), doname(otmp));
			mpickobj(mtmp,otmp);	/* may free otmp */
			/* Implies seduction, "you gladly hand over ..."
			   so we don't set mavenge bit here. */
			monflee(mtmp, 0, FALSE, FALSE);
			if (!tele_restrict(mtmp)) rloc(level, mtmp, FALSE);
		        break;
		    }
		}
		break;
	    }
	}
botm:   stealoid = 0;
	return 0;
}
Exemple #4
0
/* all objects with their bypass bit set should now be reset to normal */
void clear_bypasses(void)
{
	struct obj *otmp, *nobj;
	struct monst *mtmp;

	for (otmp = level->objlist; otmp; otmp = nobj) {
	    nobj = otmp->nobj;
	    if (otmp->bypass) {
		otmp->bypass = 0;
		/* bypass will have inhibited any stacking, but since it's
		   used for polymorph handling, the objects here probably
		   have been transformed and won't be stacked in the usual
		   manner afterwards; so don't bother with this */
	    }
	}
	/* invent and mydogs chains shouldn't matter here */
	for (otmp = migrating_objs; otmp; otmp = otmp->nobj)
	    otmp->bypass = 0;
	for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
	    if (DEADMONSTER(mtmp)) continue;
	    for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
		otmp->bypass = 0;
	}
	for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
	    for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
		otmp->bypass = 0;
	}
	flags.bypasses = FALSE;
}
Exemple #5
0
/* drop one object taken from a (possibly dead) monster's inventory */
static void
mdrop_obj(struct monst *mon, struct obj *obj, boolean verbosely)
{
    int omx = mon->mx, omy = mon->my;

    if (obj->owornmask) {
        /* perform worn item handling if the monster is still alive */
        if (mon->mhp > 0) {
            mon->misc_worn_check &= ~obj->owornmask;
            update_mon_intrinsics(mon, obj, FALSE, TRUE);
            /* obj_no_longer_held(obj); -- done by place_object */
            if (obj->owornmask & W_WEP)
                setmnotwielded(mon, obj);
            /* don't charge for an owned saddle on dead steed */
        } else if (mon->mtame && (obj->owornmask & W_SADDLE) && !obj->unpaid &&
                   costly_spot(omx, omy)) {
            obj->no_charge = 1;
        }
        obj->owornmask = 0L;
    }
    if (!DEADMONSTER(mon) && obj->otyp == LOADSTONE && !obj->cursed)
        curse(obj);
    if (verbosely && cansee(omx, omy))
        pline("%s drops %s.", Monnam(mon), distant_name(obj, doname));
    if (!flooreffects(obj, omx, omy, "fall")) {
        place_object(obj, level, omx, omy);
        stackobj(obj);
    }
}
Exemple #6
0
int domindblast (void) {
    struct monst *mtmp, *nmon;

    if (u.uen < 10) {
        You("concentrate but lack the energy to maintain doing so.");
        return(0);
    }
    u.uen -= 10;

    You("concentrate.");
    pline("A wave of psychic energy pours out.");
    for(mtmp=fmon; mtmp; mtmp = nmon) {
        int u_sen;

        nmon = mtmp->nmon;
        if (DEADMONSTER(mtmp))
            continue;
        if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM)
            continue;
        if (mtmp->mpeaceful)
            continue;
        u_sen = telepathic(mtmp->data) && !mtmp->mcansee;
        if (u_sen || (telepathic(mtmp->data) && rn2(2)) || !rn2(10)) {
            You("lock in on %s %s.", "TODO: s_suffix(mon_nam(mtmp))",
                    u_sen ? "telepathy" :
                    telepathic(mtmp->data) ? "latent telepathy" :
                    "mind");
            mtmp->mhp -= rnd(15);
            if (mtmp->mhp <= 0)
                killed(mtmp);
        }
    }
    return 1;
}
Exemple #7
0
static struct monst * findgd(void) {
    struct monst *mtmp;

    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
        if (mtmp->isgd && !DEADMONSTER(mtmp) && on_level(&(EGD(mtmp)->gdlevel), &u.uz))
            return (mtmp);
    return ((struct monst *)0);
}
Exemple #8
0
/* record `last move time' for all monsters prior to level save so that
   mon_arrive() can catch up for lost time when they're restored later */
void update_mlstmv(void)
{
	struct monst *mon;

	/* monst->mlstmv used to be updated every time `monst' actually moved,
	   but that is no longer the case so we just do a blanket assignment */
	for (mon = level->monlist; mon; mon = mon->nmon)
	    if (!DEADMONSTER(mon)) mon->mlstmv = moves;
}
Exemple #9
0
/* extract a shopkeeper name for the given shop type */
static void nameshk (struct monst *shk, const char *const *nlp) {
    int i, trycnt, names_avail;
    const char *shname = 0;
    struct monst *mtmp;
    int name_wanted;
    s_level *sptr;

    if (nlp == shklight && In_mines(&u.uz)
            && (sptr = Is_special(&u.uz)) != 0 && sptr->flags.town) {
        /* special-case minetown lighting shk */
        shname = "Izchak";
        shk->female = false;
    } else {
        /* We want variation from game to game, without needing the save
           and restore support which would be necessary for randomization;
           try not to make too many assumptions about time_t's internals;
           use ledger_no rather than depth to keep mine town distinct. */
        int nseed = (int)((long)u.ubirthday / 257L);

        name_wanted = ledger_no(&u.uz) + (nseed % 13) - (nseed % 5);
        if (name_wanted < 0) name_wanted += (13 + 5);
        shk->female = name_wanted & 1;

        for (names_avail = 0; nlp[names_avail]; names_avail++)
            continue;

        for (trycnt = 0; trycnt < 50; trycnt++) {
            if (nlp == shktools) {
                shname = shktools[rn2(names_avail)];
                shk->female = (*shname == '_');
                if (shk->female) shname++;
            } else if (name_wanted < names_avail) {
                shname = nlp[name_wanted];
            } else if ((i = rn2(names_avail)) != 0) {
                shname = nlp[i - 1];
            } else if (nlp != shkgeneral) {
                nlp = shkgeneral;   /* try general names */
                for (names_avail = 0; nlp[names_avail]; names_avail++)
                    continue;
                continue;           /* next `trycnt' iteration */
            } else {
                shname = shk->female ? "Lucrezia" : "Dirk";
            }

            /* is name already in use on this level? */
            for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
                if (DEADMONSTER(mtmp) || (mtmp == shk) || !mtmp->isshk) continue;
                if (strcmp(ESHK(mtmp)->shknam, shname)) continue;
                break;
            }
            if (!mtmp) break;       /* new name */
        }
    }
    (void) strncpy(ESHK(shk)->shknam, shname, PL_NSIZ);
    ESHK(shk)->shknam[PL_NSIZ-1] = 0;
}
boolean
inside_gas_cloud(void *p1, void *p2)
{
    struct region *reg;
    struct monst *mtmp;
    long dam;

    reg = (struct region *)p1;
    dam = (long)reg->arg;
    if (p2 == NULL) {   /* This means *YOU* Bozo! */
        if (nonliving(youmonst.data) || u.uinvulnerable)
            return FALSE;
        /* If you will unblind next turn, extend the blindness so that you do
         * not get a "You can see again!" message immediately before being
         * blinded again. */
        if (!Blind || Blinded == 1)
            make_blinded(2L, FALSE);
        if (Breathless)
            return FALSE;
        if (!Poison_resistance) {
            pline("Something is burning your %s!", makeplural(body_part(LUNG)));
            pline("You cough and spit blood!");
            losehp(rnd(dam) + 5, killer_msg(DIED, "a gas cloud"));
            return FALSE;
        } else {
            pline("You cough!");
            return FALSE;
        }
    } else {    /* A monster is inside the cloud */
        mtmp = (struct monst *)p2;

        /* Non living and non breathing monsters are not concerned */
        if (!nonliving(mtmp->data) && !breathless(mtmp->data)) {
            if (cansee(mtmp->mx, mtmp->my))
                pline("%s coughs!", Monnam(mtmp));
            setmangry(mtmp);
            if (haseyes(mtmp->data) && mtmp->mcansee) {
                mtmp->mblinded = 1;
                mtmp->mcansee = 0;
            }
            if (resists_poison(mtmp))
                return FALSE;
            mtmp->mhp -= rnd(dam) + 5;
            if (mtmp->mhp <= 0) {
                if (heros_fault(reg))
                    killed(mtmp);
                else
                    monkilled(mtmp, "gas cloud", AD_DRST);
                if (DEADMONSTER(mtmp)) {   /* not lifesaved */
                    return TRUE;
                }
            }
        }
    }
    return FALSE;       /* Monster is still alive */
}
Exemple #11
0
static struct monst *
findgd(void)
{
    struct monst *mtmp;

    for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon)
        if (mtmp->isgd && !DEADMONSTER(mtmp) &&
            on_level(&(EGD(mtmp)->gdlevel), &u.uz))
            return mtmp;
    return NULL;
}
Exemple #12
0
/* Also, give hints about portal locations, if amulet is worn/wielded -dlc */
void
amulet()
{
	struct monst *mtmp;
	struct trap *ttmp;
	struct obj *amu;

#if 0		/* caller takes care of this check */
	if (!u.uhave.amulet)
		return;
#endif
	if ((((amu = uamul) != 0 && amu->otyp == AMULET_OF_YENDOR) ||
	     ((amu = uwep) != 0 && amu->otyp == AMULET_OF_YENDOR))
	    && !rn2(15)) {
	    for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
		if(ttmp->ttyp == MAGIC_PORTAL) {
		    int du = distu(ttmp->tx, ttmp->ty);
		    if (du <= 9)
/*JP
			pline("%s hot!", Tobjnam(amu, "feel"));
*/
			pline("%sは熱く感じた!", xname(amu));
		    else if (du <= 64)
/*JP
			pline("%s very warm.", Tobjnam(amu, "feel"));
*/
			pline("%sはとても暖かく感じた。", xname(amu));
		    else if (du <= 144)
/*JP
			pline("%s warm.", Tobjnam(amu, "feel"));
*/
			pline("%sは暖かく感じた。", xname(amu));
		    /* else, the amulet feels normal */
		    break;
		}
	    }
	}

	if (!flags.no_of_wizards)
		return;
	/* find Wizard, and wake him if necessary */
	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
	    if (!DEADMONSTER(mtmp) && mtmp->iswiz && mtmp->msleeping && !rn2(40)) {
		mtmp->msleeping = 0;
		if (distu(mtmp->mx,mtmp->my) > 2)
		    You(
/*JP
    "get the creepy feeling that somebody noticed your taking the Amulet."
*/
 "あなたが魔除けを持っていることが誰かに知られたと感じてぞくぞくした。"
		    );
		return;
	    }
}
Exemple #13
0
/*
 * When saving bones, find priests that aren't on their shrine level,
 * and remove them.   This avoids big problems when restoring bones.
 */
void
clearpriests(void)
{
    struct monst *mtmp, *mtmp2;

    for (mtmp = level->monlist; mtmp; mtmp = mtmp2) {
        mtmp2 = mtmp->nmon;
        if (!DEADMONSTER(mtmp) && mtmp->ispriest &&
            !on_level(&(CONST_EPRI(mtmp)->shrlevel), &u.uz))
            mongone(mtmp);
    }
}
Exemple #14
0
struct monst *
findpriest(char roomno)
{
    struct monst *mtmp;

    for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
        if (DEADMONSTER(mtmp))
            continue;
        if (mtmp->ispriest && (CONST_EPRI(mtmp)->shroom == roomno) &&
            histemple_at(mtmp, mtmp->mx, mtmp->my))
            return mtmp;
    }
    return NULL;
}
Exemple #15
0
/* Make monsters fall asleep.  Note that they may resist the spell. */
static void
put_monsters_to_sleep(int distance)
{
    struct monst *mtmp = level->monlist;

    while (mtmp) {
        if (!DEADMONSTER(mtmp) && distu(mtmp->mx, mtmp->my) < distance &&
            sleep_monst(&youmonst, mtmp, dice(10, 10), TOOL_CLASS)) {
            mtmp->msleeping = 1;        /* 10d10 turns + wake_nearby to rouse */
            slept_monst(mtmp);
        }
        mtmp = mtmp->nmon;
    }
}
Exemple #16
0
/* Wake every monster in range... */
void
awaken_monsters(struct monst *mon, int distance)
{
    struct monst *mtmp;
    int distm;

    for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
        if (DEADMONSTER(mtmp) || mon == mtmp)
            continue;

        distm = dist2(m_mx(mon), m_my(mon), mtmp->mx, mtmp->my);
        if (distm >= distance || mon == mtmp)
            continue;

        mtmp->msleeping = 0;
        mtmp->mcanmove = 1;
        mtmp->mfrozen = 0;

        /* May scare some monsters */
        if (distm >= distance / 3 ||
            resist(mon, mtmp, TOOL_CLASS, NOTELL, 0))
            continue;

        monflee(mtmp, 0, FALSE, TRUE);
    }

    /* affect the player */
    distm = dist2(m_mx(mon), m_my(mon), youmonst.mx, youmonst.my);
    if (distm >= distance || mon == &youmonst)
        return;

    cancel_helplessness(hm_unconscious,
                        "Surprised, you are jolted into full consciousness!");

    if (distm >= distance / 3)
        return;

    /* there is no real player scare effect, so make it work similar to potion
       ghosts, except only 2 turns. Until an actual player scared effect can
       be made, monsters utilizing the paralyzation "intelligently" isn't
       fair game -- it currently only happens if a monster is about to discover
       that a magical instrument horn is out of charges */
    if (mon != &youmonst) {
        pline(msgc_statusbad,
              "The loud noise frightens you momentarily and you are unable to move!");
        helpless(2, hr_afraid, "being frightened",
                 "You regain your composure.");
    }
}
Exemple #17
0
struct monst *find_mid(struct level *lev, unsigned nid, unsigned fmflags)
{
	struct monst *mtmp;

	if (!nid)
	    return &youmonst;
	if (fmflags & FM_FMON)
		for (mtmp = lev->monlist; mtmp; mtmp = mtmp->nmon)
		    if (!DEADMONSTER(mtmp) && mtmp->m_id == nid) return mtmp;
	if (fmflags & FM_MIGRATE)
		for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon)
	    	    if (mtmp->m_id == nid) return mtmp;
	if (fmflags & FM_MYDOGS)
		for (mtmp = mydogs; mtmp; mtmp = mtmp->nmon)
	    	    if (mtmp->m_id == nid) return mtmp;
	return NULL;
}
/*
 * This function is called every turn.
 * It makes the regions age, if necessary and calls the appropriate
 * callbacks when needed.
 */
void
run_regions(struct level *lev)
{
    int i, j, k;
    int f_indx;

    /* End of life ? */
    /* Do it backward because the array will be modified */
    for (i = lev->n_regions - 1; i >= 0; i--) {
        if (lev->regions[i]->ttl == 0) {
            if ((f_indx = lev->regions[i]->expire_f) == NO_CALLBACK ||
                (*callbacks[f_indx]) (lev->regions[i], 0))
                remove_region(lev->regions[i]);
        }
    }

    /* Process remaining lev->regions */
    for (i = 0; i < lev->n_regions; i++) {
        /* Make the region age */
        if (lev->regions[i]->ttl > 0)
            lev->regions[i]->ttl--;
        /* Check if player is inside region */
        f_indx = lev->regions[i]->inside_f;
        if (f_indx != NO_CALLBACK && hero_inside(lev->regions[i]))
            (void)(*callbacks[f_indx]) (lev->regions[i], 0);
        /* Check if any monster is inside region */
        if (f_indx != NO_CALLBACK) {
            for (j = 0; j < lev->regions[i]->n_monst; j++) {
                struct monst *mtmp =
                    find_mid(lev, lev->regions[i]->monsters[j], FM_FMON);

                if (!mtmp || DEADMONSTER(mtmp) ||
                    (*callbacks[f_indx]) (lev->regions[i], mtmp)) {
                    /* The monster died, remove it from list */
                    k = (lev->regions[i]->n_monst -= 1);
                    lev->regions[i]->monsters[j] = lev->regions[i]->monsters[k];
                    lev->regions[i]->monsters[k] = 0;
                    --j;        /* current slot has been reused; recheck it
                                   next */
                }
            }
        }
    }
}
Exemple #19
0
/* Assign a name to a monster, taken from a list of possible names.
   Note that shopkeepers are special and use nameshk instead, partly
   because it contains additional logic peculiar to them and also
   because their name is stored in ESHK because of reasons. */
static void
namemonsterfromlist(struct monst *mon, const char *const *nlist,
                    struct level *lev, boolean unique)
{
    int names_avail, tryct;
    const char *ourname;
    struct monst *mtmp;
    if (!mon) {
        if (wizard)
            impossible("Cannot name a non-existent monster.");
        return;
    }
    if (!nlist[0]) {
        if (wizard)
            impossible("No names available for the %s.", mon_nam(mon));
        return;
    }
    for (names_avail = 0; nlist[names_avail]; names_avail++)
        ;
    for (tryct = 0; tryct < 500; tryct++) {
        ourname = nlist[rn2(names_avail)];
        if (!unique) {
            christen_monst(mon, ourname);
            return;
        }
        for (mtmp = lev->monlist; mtmp; mtmp = mtmp->nmon) {
            if (DEADMONSTER(mtmp) || (mtmp == mon) ||
                !(mtmp->data->mlet == mon->data->mlet))
                continue;
            if (strcmp(NAME_MUTABLE(mtmp), ourname) != 0)
                continue;
            break;
        }
        if (!mtmp) {
            christen_monst(mon, ourname);
            return;
        } 
    }
    /* We're not going to name this monster. */
    if (wizard)
        pline("Failed to find %s name for the %s.",
              (unique ? "an unused" : "a"), mon_nam(mon));
}
Exemple #20
0
/* Calm nymphs in range. */
static void
calm_nymphs(int distance)
{
    struct monst *mtmp = level->monlist;

    while (mtmp) {
        if (!DEADMONSTER(mtmp) && mtmp->data->mlet == S_NYMPH && mtmp->mcanmove
            && distu(mtmp->mx, mtmp->my) < distance) {
            mtmp->msleeping = 0;
            msethostility(mtmp, FALSE, FALSE);
            mtmp->mavenge = 0;
            if (canseemon(mtmp))
                pline(msgc_actionok,
                      "%s listens cheerfully to the music, then seems quieter.",
                      Monnam(mtmp));
        }
        mtmp = mtmp->nmon;
    }
}
Exemple #21
0
/* Charm monsters in range. Note that they may resist the spell.  If swallowed,
   range is reduced to 0. */
static void
charm_monsters(int distance)
{
    struct monst *mtmp, *mtmp2;

    if (Engulfed) {
        if (!resist(&youmonst, u.ustuck, TOOL_CLASS, NOTELL, 0))
            tamedog(u.ustuck, NULL);
    } else {
        for (mtmp = level->monlist; mtmp; mtmp = mtmp2) {
            mtmp2 = mtmp->nmon;
            if (DEADMONSTER(mtmp))
                continue;

            if (distu(mtmp->mx, mtmp->my) <= distance) {
                if (!resist(&youmonst, mtmp, TOOL_CLASS, NOTELL, 0))
                    tamedog(mtmp, NULL);
            }
        }
    }

}
Exemple #22
0
void
place_monster(struct monst *mon, int x, int y)
{
    if (mon == u.usteed || DEADMONSTER(mon) ) {
        impossible("placing %s onto map?",
                   (mon == u.usteed) ? "steed" : "defunct monster");
        return;
    }
    mon->mx = x;
    mon->my = y;
    if (isok(x, y))
        mon->dlevel->monsters[x][y] = mon;
    else
        impossible("placing monster on invalid spot (%d,%d)", x, y);

    /* If a monster's moved to the location it believes the player to be on,
       it'll learn the player isn't there. */
    if (mon->mux == mon->mx && mon->muy == mon->my) {
        mon->mux = COLNO;
        mon->muy = ROWNO;
    }
}
Exemple #23
0
/* Awake only soldiers of the level. */
void
awaken_soldiers(struct monst *culprit)
{
    struct monst *mtmp;

    for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
        if (!DEADMONSTER(mtmp) && is_mercenary(mtmp->data) &&
            !mx_egd(mtmp)) {
            mtmp->mfrozen = 0;
            msethostility(mtmp, TRUE, FALSE);
            mtmp->mcanmove = 1;
            mtmp->msleeping = 0;
            if (canseemon(mtmp))
                pline(culprit == &youmonst ? msgc_actionok :
                      msgc_moncombatbad, "%s is now ready for battle!",
                      Monnam(mtmp));
            else
                pline_once(msgc_levelsound,
                           "You hear the rattle of battle gear being readied.");
        }
    }
}
Exemple #24
0
/*
 * Let's destroy the drawbridge located at x,y
 */
void
destroy_drawbridge(int x, int y)
{
    struct rm *loc1, *loc2;
    struct trap *t;
    struct obj *chain;
    int x2, y2, i;
    boolean e_inview;
    struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);

    loc1 = &level->locations[x][y];
    if (!IS_DRAWBRIDGE(loc1->typ))
        return;
    x2 = x;
    y2 = y;
    get_wall_for_db(&x2, &y2);
    loc2 = &level->locations[x2][y2];
    if ((loc1->drawbridgemask & DB_UNDER) == DB_MOAT ||
        (loc1->drawbridgemask & DB_UNDER) == DB_LAVA) {
        struct obj *otmp;
        boolean lava = (loc1->drawbridgemask & DB_UNDER) == DB_LAVA;

        if (loc1->typ == DRAWBRIDGE_UP) {
            if (cansee(x2, y2))
                pline("The portcullis of the drawbridge falls into the %s!",
                      lava ? "lava" : waterbody_name(x2, y2));
            else
                You_hear("a loud *SPLASH*!");
        } else {
            if (cansee(x, y))
                pline("The drawbridge collapses into the %s!",
                      lava ? "lava" : waterbody_name(x, y));
            else
                You_hear("a loud *SPLASH*!");
        }
        loc1->typ = lava ? LAVAPOOL : MOAT;
        loc1->drawbridgemask = 0;
        if ((otmp = sobj_at(BOULDER, level, x, y)) != 0) {
            obj_extract_self(otmp);
            flooreffects(otmp, x, y, "fall");
        }
    } else {
        if (cansee(x, y))
            pline("The drawbridge disintegrates!");
        else
            You_hear("a loud *CRASH*!");
        loc1->typ = ((loc1->drawbridgemask & DB_ICE) ? ICE : ROOM);
        loc1->icedpool = ((loc1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
    }
    wake_nearto(x, y, 500);
    loc2->typ = DOOR;
    loc2->doormask = D_NODOOR;
    if ((t = t_at(level, x, y)) != 0)
        deltrap(level, t);
    if ((t = t_at(level, x2, y2)) != 0)
        deltrap(level, t);
    del_engr_at(level, x, y);
    del_engr_at(level, x2, y2);
    for (i = rn2(6); i > 0; --i) {  /* scatter some debris */
        /* doesn't matter if we happen to pick <x,y2> or <x2,y>;
           since drawbridges are never placed diagonally, those
           pairings will always match one of <x,y> or <x2,y2> */
        chain = mksobj_at(IRON_CHAIN, level,
                          rn2(2) ? x : x2, rn2(2) ? y : y2,
                          TRUE, FALSE, rng_main);
        /* a force of 5 here would yield a radius of 2 for
           iron chain; anything less produces a radius of 1 */
        (void) scatter(chain->ox, chain->oy, 1, MAY_HIT, chain);
    }
    newsym(x, y);
    newsym(x2, y2);
    if (!does_block(level, x2, y2))
        unblock_point(x2, y2);  /* vision */
    if (Is_stronghold(&u.uz))
        u.uevent.uopened_dbridge = TRUE;

    set_entity(x2, y2, etmp2);  /* currently only automissers can be here */
    if (etmp2->edata) {
        e_inview = e_canseemon(etmp2);
        if (!automiss(etmp2)) {
            if (e_inview)
                pline("%s blown apart by flying debris.",
                      E_phrase(etmp2, "are"));
            e_died(etmp2, e_inview ? 3 : 2, CRUSHING,
                   killer_msg(CRUSHING, "an exploding drawbridge"));
        }       /* nothing which is vulnerable can survive this */
    }
    set_entity(x, y, etmp1);
    if (etmp1->edata) {
        e_inview = e_canseemon(etmp1);
        if (!e_missed(etmp1, TRUE)) {
            if (e_inview) {
                if (!is_u(etmp1) && Hallucination)
                    pline("%s into some heavy metal!", E_phrase(etmp1, "get"));
                else
                    pline("%s hit by a huge chunk of metal!",
                          E_phrase(etmp1, "are"));
            } else {
                if (!is_u(etmp1) && !is_pool(level, x, y))
                    You_hear("a crushing sound.");
            }
            e_died(etmp1, e_inview ? 3 : 2, CRUSHING,
                   killer_msg(CRUSHING, "a collapsing drawbridge"));
            /* if (loc1->typ == MOAT) do_entity(etmp1); */
        }
        if (is_u(etmp1))
            spoteffects(FALSE);
        else if (!DEADMONSTER(etmp1->emon))
            minliquid(etmp1->emon);
    }
}
Exemple #25
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;
}
Exemple #26
0
void dosounds(void)
{
    struct mkroom *sroom;
    int hallu, vx, vy;
    struct monst *mtmp;

    if (!flags.soundok || u.uswallow || Underwater) return;

    if (level->sounds && !rn2(level->sounds->freq)) {
	int idx = rn2(level->sounds->n_sounds);
	char *buf;
	struct lvl_sound_bite *snd = &level->sounds->sounds[idx];
	buf = string_subst(snd->msg);
	switch (snd->flags) {
	default:
	case LVLSND_HEARD:	You_hear(buf);			break;
	case LVLSND_PLINED:	pline(buf);			break;
	case LVLSND_VERBAL:	verbalize(buf);			break;
	case LVLSND_FELT:	pline("You feel %s", buf);	break;
	}
    }

    hallu = Hallucination ? 1 : 0;

    if (level->flags.nfountains && !rn2(400)) {
	static const char * const fountain_msg[4] = {
		"bubbling water.",
		"water falling on coins.",
		"the splashing of a naiad.",
		"a soda fountain!",
	};
	You_hear(fountain_msg[rn2(3)+hallu]);
    }

    if (level->flags.nsinks && !rn2(300)) {
	static const char * const sink_msg[3] = {
		"a slow drip.",
		"a gurgling noise.",
		"dishes being washed!",
	};
	You_hear(sink_msg[rn2(2)+hallu]);
    }

    if (level->flags.has_court && !rn2(200)) {
	static const char * const throne_msg[4] = {
		"the tones of courtly conversation.",
		"a sceptre pounded in judgment.",
		"Someone shouts \"Off with %s head!\"",
		"Queen Beruthiel's cats!",
	};
	for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
	    if (DEADMONSTER(mtmp)) continue;
	    if ((mtmp->msleeping ||
			is_lord(mtmp->data) || is_prince(mtmp->data)) &&
		!is_animal(mtmp->data) &&
		mon_in_room(mtmp, COURT)) {
		/* finding one is enough, at least for now */
		int which = rn2(3)+hallu;

		if (which != 2) You_hear(throne_msg[which]);
		else		pline(throne_msg[2], uhis());
		return;
	    }
	}
    }
    if (level->flags.has_garden && !rn2(200)) {
	static const char * const garden_msg[4] = {
		"crickets chirping.",
		"birds singing.",
		"grass growing!",
		"wind in the willows!",
	};
	You_hear(garden_msg[rn2(2) + 2 * hallu]);
	return;
    }
    if (level->flags.has_swamp && !rn2(200)) {
	static const char * const swamp_msg[3] = {
		"You hear mosquitoes!",
		"You smell marsh gas!",	/* so it's a smell...*/
		"You hear Donald Duck!",
	};
	pline(swamp_msg[rn2(2)+hallu]);
	return;
    }
    if (level->flags.has_vault && !rn2(200)) {
	if (!(sroom = search_special(level, VAULT))) {
	    /* strange ... */
	    level->flags.has_vault = 0;
	    return;
	}
	if (gd_sound())
	    switch (rn2(2)+hallu) {
		case 1: {
		    boolean gold_in_vault = FALSE;

		    for (vx = sroom->lx;vx <= sroom->hx; vx++)
			for (vy = sroom->ly; vy <= sroom->hy; vy++)
			    if (gold_at(level, vx, vy))
				gold_in_vault = TRUE;
		    if (vault_occupied(u.urooms) !=
			 (ROOM_INDEX(sroom) + ROOMOFFSET))
		    {
			if (gold_in_vault)
			    You_hear(!hallu ? "someone counting money." :
				"the quarterback calling the play.");
			else
			    You_hear("someone searching.");
			break;
		    }
		    /* fall into... (yes, even for hallucination) */
		}
		case 0:
		    You_hear("the footsteps of a guard on patrol.");
		    break;
		case 2:
		    You_hear("Ebenezer Scrooge!");
		    break;
	    }
	return;
    }
    if (level->flags.has_beehive && !rn2(200)) {
	for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
	    if (DEADMONSTER(mtmp)) continue;
	    if ((mtmp->data->mlet == S_ANT && is_flyer(mtmp->data)) &&
		mon_in_room(mtmp, BEEHIVE)) {
		switch (rn2(2)+hallu) {
		    case 0:
			You_hear("a low buzzing.");
			break;
		    case 1:
			You_hear("an angry drone.");
			break;
		    case 2:
			You_hear("bees in your %sbonnet!",
			    uarmh ? "" : "(nonexistent) ");
			break;
		}
		return;
	    }
	}
    }
    if (level->flags.has_lemurepit && !rn2(20)) {
	for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
	    if (DEADMONSTER(mtmp)) continue;
	    if (mtmp->data == &mons[PM_LEMURE] &&
		mon_in_room(mtmp, LEMUREPIT)) {
		if (hallu) {
		    switch (rn2(3)) {
			case 0:
			    You_hear("screams of lust!");
			    break;
			case 1:
			    You_hear("the crack of your mistress's whip!");
			    break;
			case 2:
			    You_hear("a weeping willow!");
			    break;
		    }
		} else {
		    switch (rn2(6)) {
			case 0:
			    You_hear("the crack of a barbed whip!");
			    break;
			case 1:
			    You_hear("the screams of tortured souls!");
			    break;
			case 2:
			    You_hear("a wail of eternal anguish!");
			    break;
			case 3:
			    You_hear("diabolical laughter!");
			    break;
			case 4:
			    You_hear("cries of repentance!");
			    break;
			case 5:
			    You_hear("futile pleas for mercy!");
			    break;
		    }
		}
		return;
	    }
	}
    }
    if (level->flags.has_morgue && !rn2(200)) {
	for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
	    if (DEADMONSTER(mtmp)) continue;
	    if (is_undead(mtmp->data) &&
		mon_in_room(mtmp, MORGUE)) {
		switch (rn2(2)+hallu) {
		    case 1:
			if (!strcmp(body_part(HAIR), "hair")) {
			    pline("The %s on the back of your %s stands up.",
				body_part(HAIR), body_part(NECK));
			    break;
			}
			/* fall through */
		    case 2:
			if (!strcmp(body_part(HAIR), "hair")) {
			    pline("The %s on your %s seems to stand up.",
				    body_part(HAIR), body_part(HEAD));
			    break;
			}
			/* fall through */
		    case 0:
			pline("You suddenly realize it is unnaturally quiet.");
			break;
		}
		return;
	    }
	}
    }
    if (level->flags.has_barracks && !rn2(200)) {
	static const char * const barracks_msg[4] = {
		"blades being honed.",
		"loud snoring.",
		"dice being thrown.",
		"General MacArthur!",
	};
	int count = 0;

	for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
	    if (DEADMONSTER(mtmp)) continue;
	    if (is_mercenary(mtmp->data) &&
		mon_in_room(mtmp, BARRACKS) &&
		/* sleeping implies not-yet-disturbed (usually) */
		(mtmp->msleeping || ++count > 5)) {
		You_hear(barracks_msg[rn2(3)+hallu]);
		return;
	    }
	}
    }
    if (level->flags.has_zoo && !rn2(200)) {
	static const char * const zoo_msg[3] = {
		"a sound reminiscent of an elephant stepping on a peanut.",
		"a sound reminiscent of a seal barking.",
		"Doctor Dolittle!",
	};
	for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
	    if (DEADMONSTER(mtmp)) continue;
	    if ((mtmp->msleeping || is_animal(mtmp->data)) &&
		    mon_in_room(mtmp, ZOO)) {
		You_hear(zoo_msg[rn2(2)+hallu]);
		return;
	    }
	}
    }
    if (level->flags.has_shop && !rn2(200)) {
	if (!(sroom = search_special(level, ANY_SHOP))) {
	    /* strange... */
	    level->flags.has_shop = 0;
	    return;
	}
	if (tended_shop(sroom) &&
		!strchr(u.ushops, ROOM_INDEX(sroom) + ROOMOFFSET)) {
	    static const char * const shop_msg[3] = {
		    "someone cursing shoplifters.",
		    "the chime of a cash register.",
		    "Neiman and Marcus arguing!",
	    };
	    You_hear(shop_msg[rn2(2)+hallu]);
	}
	return;
    }
    if (Is_oracle_level(&u.uz) && !rn2(400)) {
	/* make sure the Oracle is still here */
	for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon)
	    if (!DEADMONSTER(mtmp) && mtmp->data == &mons[PM_ORACLE])
		break;
	/* and don't produce silly effects when she's clearly visible */
	if (mtmp && (hallu || !canseemon(level, mtmp))) {
	    static const char * const ora_msg[5] = {
		    "a strange wind.",		/* Jupiter at Dodona */
		    "convulsive ravings.",	/* Apollo at Delphi */
		    "snoring snakes.",		/* AEsculapius at Epidaurus */
		    "someone say \"No more woodchucks!\"",
		    "a loud ZOT!"		/* both rec.humor.oracle */
	    };
	    You_hear(ora_msg[rn2(3)+hallu*2]);
	}
	return;
    }
    if (!Is_blackmarket(&u.uz) && at_dgn_entrance(&u.uz, "One-eyed Sam's Market") &&
	!rn2(200)) {
	static const char *blkmar_msg[3] = {
	    "You hear someone complaining about the prices.",
	    "Somebody whispers: \"Food rations? Only 900 zorkmids.\"",
	    "You feel like searching for more gold.",
	};
	pline(blkmar_msg[rn2(2)+hallu]);
    }
}
Exemple #27
0
/* look for gold, on the floor or in monsters' possession */
int gold_detect(struct obj *sobj, boolean *scr_known)
{
    struct obj *obj;
    struct monst *mtmp;
    int uw = u.uinwater;
    struct obj *temp;
    boolean stale;

    *scr_known = stale = clear_stale_map(COIN_CLASS, sobj->blessed ? GOLD : 0);

    /* look for gold carried by monsters (might be in a container) */
    for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
    	if (DEADMONSTER(mtmp)) continue;	/* probably not needed in this case but... */
	if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
	    *scr_known = TRUE;
	    goto outgoldmap;	/* skip further searching */
	} else for (obj = mtmp->minvent; obj; obj = obj->nobj)
	    if (sobj->blessed && o_material(obj, GOLD)) {
	    	*scr_known = TRUE;
	    	goto outgoldmap;
	    } else if (o_in(obj, COIN_CLASS)) {
		*scr_known = TRUE;
		goto outgoldmap;	/* skip further searching */
	    }
    }
    
    /* look for gold objects */
    for (obj = level->objlist; obj; obj = obj->nobj) {
	if (sobj->blessed && o_material(obj, GOLD)) {
	    *scr_known = TRUE;
	    if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap;
	} else if (o_in(obj, COIN_CLASS)) {
	    *scr_known = TRUE;
	    if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap;
	}
    }

    if (!*scr_known) {
	/* no gold found on floor or monster's inventory.
	   adjust message if you have gold in your inventory */
	char buf[BUFSZ];
	if (youmonst.data == &mons[PM_GOLD_GOLEM]) {
		sprintf(buf, "You feel like a million %s!", currency(2L));
	} else if (hidden_gold() || money_cnt(invent))
		strcpy(buf, "You feel worried about your future financial situation.");
	else
		strcpy(buf, "You feel materially poor.");
	strange_feeling(sobj, buf);
	return 1;
    }
    /* only under me - no separate display required */
    if (stale) doredraw();
    pline("You notice some gold between your %s.", makeplural(body_part(FOOT)));
    return 0;

outgoldmap:
    cls();

    u.uinwater = 0;
    /* Discover gold locations. */
    for (obj = level->objlist; obj; obj = obj->nobj) {
    	if (sobj->blessed && (temp = o_material(obj, GOLD))) {
	    if (temp != obj) {
		temp->ox = obj->ox;
		temp->oy = obj->oy;
	    }
	    map_object(temp,1);
	} else if ((temp = o_in(obj, COIN_CLASS))) {
	    if (temp != obj) {
		temp->ox = obj->ox;
		temp->oy = obj->oy;
	    }
	    map_object(temp,1);
	}
    }
    for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
    	if (DEADMONSTER(mtmp)) continue;	/* probably overkill here */
	if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) {
	    struct obj gold;

	    gold.otyp = GOLD_PIECE;
	    gold.ox = mtmp->mx;
	    gold.oy = mtmp->my;
	    map_object(&gold,1);
	} else for (obj = mtmp->minvent; obj; obj = obj->nobj)
	    if (sobj->blessed && (temp = o_material(obj, GOLD))) {
		temp->ox = mtmp->mx;
		temp->oy = mtmp->my;
		map_object(temp,1);
		break;
	    } else if ((temp = o_in(obj, COIN_CLASS))) {
		temp->ox = mtmp->mx;
		temp->oy = mtmp->my;
		map_object(temp,1);
		break;
	    }
    }
    
    newsym(u.ux,u.uy);
    pline("You feel very greedy, and sense gold!");
    exercise(A_WIS, TRUE);
    win_pause_output(P_MAP);
    doredraw();
    u.uinwater = uw;
    if (Underwater) under_water(2);
    if (u.uburied) under_ground(2);
    return 0;
}
Exemple #28
0
/*
 * Let's destroy the drawbridge located at x,y
 */
void
destroy_drawbridge(int x, int y)
{
    struct rm *loc1, *loc2;
    struct trap *t;
    int x2, y2;
    boolean e_inview;
    struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);

    loc1 = &level->locations[x][y];
    if (!IS_DRAWBRIDGE(loc1->typ))
        return;
    x2 = x;
    y2 = y;
    get_wall_for_db(&x2, &y2);
    loc2 = &level->locations[x2][y2];
    if ((loc1->drawbridgemask & DB_UNDER) == DB_MOAT ||
        (loc1->drawbridgemask & DB_UNDER) == DB_LAVA) {
        struct obj *otmp;
        boolean lava = (loc1->drawbridgemask & DB_UNDER) == DB_LAVA;

        if (loc1->typ == DRAWBRIDGE_UP) {
            if (cansee(x2, y2))
                pline("The portcullis of the drawbridge falls into the %s!",
                      lava ? "lava" : waterbody_name(x2, y2));
            else if (flags.soundok)
                You_hear("a loud *SPLASH*!");
        } else {
            if (cansee(x, y))
                pline("The drawbridge collapses into the %s!",
                      lava ? "lava" : waterbody_name(x, y));
            else if (flags.soundok)
                You_hear("a loud *SPLASH*!");
        }
        loc1->typ = lava ? LAVAPOOL : MOAT;
        loc1->drawbridgemask = 0;
        if ((otmp = sobj_at(BOULDER, level, x, y)) != 0) {
            obj_extract_self(otmp);
            flooreffects(otmp, x, y, "fall");
        }
    } else {
        if (cansee(x, y))
            pline("The drawbridge disintegrates!");
        else
            You_hear("a loud *CRASH*!");
        loc1->typ = ((loc1->drawbridgemask & DB_ICE) ? ICE : ROOM);
        loc1->icedpool = ((loc1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
    }
    wake_nearto(x, y, 500);
    loc2->typ = DOOR;
    loc2->doormask = D_NODOOR;
    if ((t = t_at(level, x, y)) != 0)
        deltrap(level, t);
    if ((t = t_at(level, x2, y2)) != 0)
        deltrap(level, t);
    newsym(x, y);
    newsym(x2, y2);
    if (!does_block(level, x2, y2))
        unblock_point(x2, y2);  /* vision */
    if (Is_stronghold(&u.uz))
        u.uevent.uopened_dbridge = TRUE;

    set_entity(x2, y2, etmp2);  /* currently only automissers can be here */
    if (etmp2->edata) {
        e_inview = e_canseemon(etmp2);
        if (!automiss(etmp2)) {
            if (e_inview)
                pline("%s blown apart by flying debris.",
                      E_phrase(etmp2, "are"));
            killer_format = KILLED_BY_AN;
            killer = "exploding drawbridge";
            e_died(etmp2, e_inview ? 3 : 2, CRUSHING);  /* no corpse */
        }       /* nothing which is vulnerable can survive this */
    }
    set_entity(x, y, etmp1);
    if (etmp1->edata) {
        e_inview = e_canseemon(etmp1);
        if (!e_missed(etmp1, TRUE)) {
            if (e_inview) {
                if (!is_u(etmp1) && Hallucination)
                    pline("%s into some heavy metal!", E_phrase(etmp1, "get"));
                else
                    pline("%s hit by a huge chunk of metal!",
                          E_phrase(etmp1, "are"));
            } else {
                if (flags.soundok && !is_u(etmp1) && !is_pool(level, x, y))
                    You_hear("a crushing sound.");
            }
            killer_format = KILLED_BY_AN;
            killer = "collapsing drawbridge";
            e_died(etmp1, e_inview ? 3 : 2, CRUSHING);  /* no corpse */
            /* if (loc1->typ == MOAT) do_entity(etmp1); */
        }
        if (is_u(etmp1))
            spoteffects(FALSE);
        else if (!DEADMONSTER(etmp1->emon))
            minliquid(etmp1->emon);
    }
}
Exemple #29
0
void
dosounds(void)
{
    struct mkroom *sroom;
    int hallu, vx, vy;
    struct monst *mtmp;

    if (!canhear() || Engulfed || Underwater)
        return;

    hallu = Hallucination ? 1 : 0;

    if (has_terrain(level, FOUNTAIN) && !rn2(400)) {
        static const char *const fountain_msg[4] = {
            "bubbling water.",
            "water falling on coins.",
            "the splashing of a naiad.",
            "a soda fountain!",
        };
        You_hear("%s", fountain_msg[rn2(3) + hallu]);
    }

    if (has_terrain(level, SINK) && !rn2(300)) {
        static const char *const sink_msg[3] = {
            "a slow drip.",
            "a gurgling noise.",
            "dishes being washed!",
        };
        You_hear("%s", sink_msg[rn2(2) + hallu]);
    }

    if (search_special(level, COURT) && !rn2(200)) {
        static const char *const throne_msg[4] = {
            "the tones of courtly conversation.",
            "a sceptre pounded in judgment.",
            "Someone shouts \"Off with %s head!\"",
            "Queen Beruthiel's cats!",
        };
        for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
            if (DEADMONSTER(mtmp))
                continue;
            if ((mtmp->msleeping || is_lord(mtmp->data) ||
                 is_prince(mtmp->data)) && !is_animal(mtmp->data) &&
                mon_in_room(mtmp, COURT)) {
                /* finding one is enough, at least for now */
                int which = rn2(3) + hallu;

                if (which != 2)
                    You_hear("%s", throne_msg[which]);
                else
                    pline(throne_msg[2], uhis());
                return;
            }
        }
    }
    if (search_special(level, SWAMP) && !rn2(200)) {
        static const char *const swamp_msg[3] = {
            "You hear mosquitoes!",
            "You smell marsh gas!",     /* so it's a smell... */
            "You hear Donald Duck!",
        };
        pline("%s", swamp_msg[rn2(2) + hallu]);
        return;
    }
    if ((sroom = search_special(level, VAULT)) && !rn2(200)) {
        if (gd_sound())
            switch (rn2(2) + hallu) {
            case 1:{
                    boolean gold_in_vault = FALSE;

                    for (vx = sroom->lx; vx <= sroom->hx; vx++)
                        for (vy = sroom->ly; vy <= sroom->hy; vy++)
                            if (gold_at(level, vx, vy))
                                gold_in_vault = TRUE;
                    if (vault_occupied(u.urooms) !=
                        (ROOM_INDEX(sroom) + ROOMOFFSET)) {
                        if (gold_in_vault)
                            You_hear(!hallu ? "someone counting money." :
                                     "the quarterback calling the play.");
                        else
                            You_hear("someone searching.");
                        break;
                    }
                    /* fall into... (yes, even for hallucination) */
                }
            case 0:
                You_hear("the footsteps of a guard on patrol.");
                break;
            case 2:
                You_hear("Ebenezer Scrooge!");
                break;
            }
        return;
    }
    if (search_special(level, BEEHIVE) && !rn2(200)) {
        for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
            if (DEADMONSTER(mtmp))
                continue;
            if ((mtmp->data->mlet == S_ANT && is_flyer(mtmp->data)) &&
                mon_in_room(mtmp, BEEHIVE)) {
                switch (rn2(2) + hallu) {
                case 0:
                    You_hear("a low buzzing.");
                    break;
                case 1:
                    You_hear("an angry drone.");
                    break;
                case 2:
                    You_hear("bees in your %sbonnet!",
                             uarmh ? "" : "(nonexistent) ");
                    break;
                }
                return;
            }
        }
    }
    if (search_special(level, MORGUE) && !rn2(200)) {
        for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
            if (DEADMONSTER(mtmp))
                continue;
            if (is_undead(mtmp->data) && mon_in_room(mtmp, MORGUE)) {
                switch (rn2(2) + hallu) {
                case 1:
                    if (!strcmp(body_part(HAIR), "hair")) {
                        pline("The %s on the back of your %s stands up.",
                              body_part(HAIR), body_part(NECK));
                        break;
                    }
                    /* fall through */
                case 2:
                    if (!strcmp(body_part(HAIR), "hair")) {
                        pline("The %s on your %s seems to stand up.",
                              body_part(HAIR), body_part(HEAD));
                        break;
                    }
                    /* fall through */
                case 0:
                    pline("You suddenly realize it is unnaturally quiet.");
                    break;
                }
                return;
            }
        }
    }
    if (search_special(level, BARRACKS) && !rn2(200)) {
        static const char *const barracks_msg[4] = {
            "blades being honed.",
            "loud snoring.",
            "dice being thrown.",
            "General MacArthur!",
        };
        int count = 0;

        for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
            if (DEADMONSTER(mtmp))
                continue;
            if (is_mercenary(mtmp->data) && mon_in_room(mtmp, BARRACKS) &&
                /* sleeping implies not-yet-disturbed (usually) */
                (mtmp->msleeping || ++count > 5)) {
                You_hear("%s", barracks_msg[rn2(3) + hallu]);
                return;
            }
        }
    }
    if (search_special(level, ZOO) && !rn2(200)) {
        static const char *const zoo_msg[3] = {
            "a sound reminiscent of an elephant stepping on a peanut.",
            "a sound reminiscent of a seal barking.",
            "Doctor Dolittle!",
        };
        for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon) {
            if (DEADMONSTER(mtmp))
                continue;
            if ((mtmp->msleeping || is_animal(mtmp->data)) &&
                mon_in_room(mtmp, ZOO)) {
                You_hear("%s", zoo_msg[rn2(2) + hallu]);
                return;
            }
        }
    }
    if ((sroom = search_special(level, ANY_SHOP)) && !rn2(200)) {
        if (tended_shop(sroom) &&
            !strchr(u.ushops, ROOM_INDEX(sroom) + ROOMOFFSET)) {
            static const char *const shop_msg[3] = {
                "someone cursing shoplifters.",
                "the chime of a cash register.",
                "Neiman and Marcus arguing!",
            };
            You_hear("%s", shop_msg[rn2(2) + hallu]);
        }
        return;
    }
    if (search_special(level, DELPHI) && !rn2(400)) {
        /* make sure the Oracle is still here */
        for (mtmp = level->monlist; mtmp; mtmp = mtmp->nmon)
            if (!DEADMONSTER(mtmp) && mtmp->data == &mons[PM_POTTER])
                break;
        /* and don't produce silly effects when he's clearly visible */
        if (mtmp && (hallu || !canseemon(mtmp))) {
            static const char *const ora_msg[5] = {
                "political commentary.",
                "convulsive ravings about WLAN controllers.",
                "an Adirondack woodsman.",
                "someone ask you for your punchcards.", /* if(hallucinating) */
                "loud praise for Netgear devices." /* if(hallucinating) */
            };
            You_hear("%s", ora_msg[rn2(3) + hallu * 2]);
        }
        return;
    }
}
Exemple #30
0
/* special effects for The Book of the Dead */
void
deadbook(struct obj *book2, boolean invoked)
{
    struct monst *mtmp, *mtmp2;
    coord mm;

    if (!invoked)
        pline("You turn the pages of the Book of the Dead...");
    makeknown(SPE_BOOK_OF_THE_DEAD);
    /* KMH -- Need ->known to avoid "_a_ Book of the Dead" */
    book2->known = 1;
    if (invocation_pos(&u.uz, u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
        struct obj *otmp;
        boolean arti1_primed = FALSE, arti2_primed = FALSE, arti_cursed = FALSE;

        if (invoked) {
            if (Blind)
                You_hear("a crisp flicker...");
            else
                pline("The Book of the Dead opens of its own accord...");
        }

        if (book2->cursed) {
            if (invoked) {
                if (Hallucination)
                    You_hear("gratuitous bleeping.");
                else
                    You_hear("a mumbled curse.");
            } else
                pline("The runes appear scrambled.  You can't read them!");
            return;
        }

        if (!Uhave_bell || !Uhave_menorah) {
            pline("A chill runs down your %s.", body_part(SPINE));
            if (!Uhave_bell) {
                if (Hallucination)
                    pline("You feel like a tuning fork!");
                else
                    You_hear("a faint chime...");
            }
            if (!Uhave_menorah) {
                if (Hallucination) {
                    pline("Nosferatu giggles.");
                } else if (mvitals[PM_DOPPELGANGER].mvflags & G_GENOD) {
                    /* suggestion by b_jonas: can't talk about doppelgangers
                       if they don't exist */
                    if (Uhave_bell)
                        pline("Nothing seems to happen.");
                    /* otherwise no message, we already printed one. */
                } else {
                    pline("Vlad's doppelganger is amused.");
                }
            }
            return;
        }

        for (otmp = invent; otmp; otmp = otmp->nobj) {
            if (otmp->otyp == CANDELABRUM_OF_INVOCATION && otmp->spe == 7 &&
                otmp->lamplit) {
                if (!otmp->cursed)
                    arti1_primed = TRUE;
                else
                    arti_cursed = TRUE;
            }
            if (otmp->otyp == BELL_OF_OPENING && (moves - otmp->age) < 5L) {
                /* you rang it recently */
                if (!otmp->cursed)
                    arti2_primed = TRUE;
                else
                    arti_cursed = TRUE;
            }
        }

        if (arti_cursed) {
            pline("The invocation fails!");
            if (Hallucination)
                pline("At least one of your heirlooms is in a tizzy!");
            else
                pline("At least one of your artifacts is cursed...");
        } else if (arti1_primed && arti2_primed) {
            unsigned soon = (unsigned)dice(2, 6); /* time til next intervene */

            /* successful invocation */
            mkinvokearea();
            u.uevent.invoked = 1;
            historic_event(FALSE, TRUE, "performed the invocation.");
            /* in case you haven't killed the Wizard yet, behave as if you just
               did */
            u.uevent.udemigod = 1;      /* wizdead() */
            if (!u.udg_cnt || u.udg_cnt > soon)
                u.udg_cnt = soon;
        } else {        /* at least one artifact not prepared properly */
            pline("You have a feeling that something is amiss...");
            goto raise_dead;
        }
        return;
    }

    /* when not an invocation situation */
    if (invoked) {
        pline("Nothing happens.");
        return;
    }

    if (book2->cursed) {
    raise_dead:

        if (Hallucination)
            You_hear("Michael Jackson dancing!");
        else
            pline("You raised the dead!");
        /* first maybe place a dangerous adversary; don't bother with
           MM_CREATEMONSTER, that's mostly used to ensure that consistent
           species of monsters generate */
        if (!rn2(3) &&
            ((mtmp = makemon(&mons[PM_MASTER_LICH], level, u.ux, u.uy,
                             NO_MINVENT)) != 0 ||
             (mtmp = makemon(&mons[PM_NALFESHNEE], level, u.ux, u.uy,
                             NO_MINVENT)) != 0)) {
            msethostility(mtmp, TRUE, TRUE);
        }
        /* next handle the effect on things you're carrying */
        unturn_dead(&youmonst);
        /* last place some monsters around you */
        mm.x = u.ux;
        mm.y = u.uy;
        mkundead(level, &mm, TRUE, NO_MINVENT);
    } else if (book2->blessed) {
        for (mtmp = level->monlist; mtmp; mtmp = mtmp2) {
            mtmp2 = mtmp->nmon; /* tamedog() changes chain */
            if (DEADMONSTER(mtmp))
                continue;

            if (is_undead(mtmp->data) && cansee(mtmp->mx, mtmp->my)) {
                msethostility(mtmp, FALSE, FALSE); /* TODO: reset alignment? */
                if (sgn(mtmp->data->maligntyp) == sgn(u.ualign.type)
                    && distu(mtmp->mx, mtmp->my) < 4)
                    if (mtmp->mtame) {
                        if (mtmp->mtame < 20)
                            mtmp->mtame++;
                    } else
                        tamedog(mtmp, NULL);
                else
                    monflee(mtmp, 0, FALSE, TRUE);
            }
        }
    } else {
        switch (rn2(3)) {
        case 0:
            pline("Your ancestors are annoyed with you!");
            break;
        case 1:
            pline("The headstones in the cemetery begin to move!");
            break;
        default:
            pline("Oh my!  Your name appears in the book!");
        }
    }
    return;
}