Пример #1
0
/*
 * Close the drawbridge located at x,y.
 * Returns TRUE if the drawbridge was closed, FALSE otherwise.
 */
boolean close_drawbridge(int x, int y)
{
	struct rm *loc1, *loc2;
	struct monst *m;
	struct trap *t;
	int x2, y2;

	loc1 = &level->locations[x][y];
	if (loc1->typ != DRAWBRIDGE_DOWN) return FALSE;
	/* A huge monster will block the drawbridge. */
	if ((m = m_at(level, x, y)) && hugemonst(m->data)) {
	    pline("%s blocks the drawbridge with %s weight!",
		  canseemon(level, m) ? Amonnam(m) : "Something",
		  canseemon(level, m) ? mhis(level, m) : "its");
	    return FALSE;
	}
	if (rn2(5) == 0) {
	    pline("The mechanism seems to have something stuck in it and won't close.");
	    return FALSE;
	}
	x2 = x; y2 = y;
	get_wall_for_db(&x2,&y2);
	if (cansee(x,y) || cansee(x2,y2))
		pline("You see a drawbridge %s up!",
		    (((u.ux == x || u.uy == y) && !Underwater) ||
		     distu(x2,y2) < distu(x,y)) ? "coming" : "going");
	loc1->typ = DRAWBRIDGE_UP;
	loc2 = &level->locations[x2][y2];
	loc2->typ = DBWALL;
	switch (loc1->drawbridgemask & DB_DIR) {
		case DB_NORTH:
		case DB_SOUTH:
			loc2->horizontal = TRUE;
			break;
		case DB_WEST:
		case DB_EAST:
			loc2->horizontal = FALSE;
			break;
	}
	loc2->wall_info = W_NONDIGGABLE;
	set_entity(x, y, &(occupants[0]));
	set_entity(x2, y2, &(occupants[1]));
	do_entity(&(occupants[0]));		/* Do set_entity after first */
	set_entity(x2, y2, &(occupants[1]));	/* do_entity for worm tail */
	do_entity(&(occupants[1]));
	if (OBJ_AT(x, y) && flags.soundok)
	    You_hear("smashing and crushing.");
	revive_nasty(x,y,NULL);
	revive_nasty(x2,y2,NULL);
	delallobj(x, y);
	delallobj(x2, y2);
	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);
	block_point(x2,y2);	/* vision */
	return TRUE;
}
Пример #2
0
/* returns 1 if it won't attack. */
int
demon_talk(struct monst *mtmp)
{
    long cash, demand, offer;

    if (uwep && uwep->oartifact == ART_EXCALIBUR) {
        pline("%s looks very angry.", Amonnam(mtmp));
        msethostility(mtmp, TRUE, TRUE);
        return 0;
    }

    /* Slight advantage given. */
    if (is_dprince(mtmp->data) && mtmp->minvis) {
        mtmp->minvis = mtmp->perminvis = 0;
        if (!Blind)
            pline("%s appears before you.", Amonnam(mtmp));
        newsym(mtmp->mx, mtmp->my);
    }
    if (youmonst.data->mlet == S_DEMON) {       /* Won't blackmail their own. */
        pline("%s says, \"Good hunting, %s.\"", Amonnam(mtmp),
              u.ufemale ? "Sister" : "Brother");
        if (!tele_restrict(mtmp))
            rloc(mtmp, TRUE);
        return 1;
    }
    cash = money_cnt(invent);
    /* don't bother with a custom RNG here, too much unpredictability is
       involved */
    demand = (cash * (rnd(80) + 20 * Athome)) /
        (100 * (1 + (sgn(u.ualign.type) == sgn(mtmp->data->maligntyp))));

    if (!demand) {      /* you have no gold */
        msethostility(mtmp, TRUE, TRUE);
        return 0;
    } else {
        /* make sure that the demand is unmeetable if the monster has the
           Amulet, preventing monster from being satisified and removed from
           the game (along with said Amulet...) */
        if (mon_has_amulet(mtmp))
            demand = cash + (long)rn1(1000, 40);

        pline("%s demands %ld %s for safe passage.", Amonnam(mtmp), demand,
              currency(demand));

        if ((offer = bribe(mtmp)) >= demand) {
            pline("%s vanishes, laughing about cowardly %s.", Amonnam(mtmp),
                  makeplural(mortal_or_creature(youmonst.data, FALSE)));
        } else if (offer > 0L && (long)rnd(40) > (demand - offer)) {
            pline("%s scowls at you menacingly, then vanishes.", Amonnam(mtmp));
        } else {
            pline("%s gets angry...", Amonnam(mtmp));
            msethostility(mtmp, TRUE, TRUE);
            return 0;
        }
    }
    mongone(mtmp);
    return 1;
}
Пример #3
0
void
summon_minion(aligntyp alignment, boolean talk)
{
    struct monst *mon;
    int mnum;

    switch ((int)alignment) {
    case A_LAWFUL:
        mnum = lminion();
        break;
    case A_NEUTRAL:
        mnum = PM_AIR_ELEMENTAL + rn2(4);
        break;
    case A_CHAOTIC:
    case A_NONE:
        mnum = ndemon(&u.uz, alignment);
        break;
    default:
        impossible("unaligned player?");
        mnum = ndemon(&u.uz, A_NONE);
        break;
    }
    if (mnum == NON_PM) {
        mon = 0;
    } else if (mons[mnum].pxtyp == MX_NONE) {
        const struct permonst *pm = &mons[mnum];

        mon = makemon(pm, level, u.ux, u.uy, MM_EMIN);
        if (mon) {
            mon->isminion = TRUE;
            EMIN(mon)->min_align = alignment;
        }
    } else if (roamer_type(&mons[mnum])) {
        mon = makemon(&mons[mnum], level, u.ux, u.uy, NO_MM_FLAGS);
        if (mon) {
            mon->isminion = TRUE;
            EPRI(mon)->shralign = alignment;
        }
    } else
        mon = makemon(&mons[mnum], level, u.ux, u.uy, NO_MM_FLAGS);
    if (mon) {
        if (talk) {
            pline("The voice of %s booms:", align_gname(alignment));
            verbalize("Thou shalt pay for thy indiscretion!");
            if (!Blind)
                pline("%s appears before you.", Amonnam(mon));
        }
        mon->mpeaceful = FALSE;
        /* don't call set_malign(); player was naughty */
    }
}
Пример #4
0
static int domonnoise(struct monst *mtmp)
{
    const char *pline_msg = 0,	/* Monnam(mtmp) will be prepended */
			*verbl_msg = 0;	/* verbalize() */
    const struct permonst *ptr = mtmp->data;
    char verbuf[BUFSZ];

    /* presumably nearness and sleep checks have already been made */
    if (!flags.soundok) return 0;
    if (is_silent(ptr)) return 0;

    /* Make sure its your role's quest quardian; adjust if not */
    if (ptr->msound == MS_GUARDIAN && ptr != &pm_guardian) {
	int mndx = monsndx(ptr);
	ptr = &mons[genus(mndx,1)];
    }

    /* be sure to do this before talking; the monster might teleport away, in
     * which case we want to check its pre-teleport position
     */
    if (!canspotmon(level, mtmp))
	map_invisible(mtmp->mx, mtmp->my);

    switch (ptr->msound) {
	case MS_ORACLE:
	    return doconsult(mtmp);
	case MS_PRIEST:
	    priest_talk(mtmp);
	    break;
	case MS_LEADER:
	case MS_NEMESIS:
	case MS_GUARDIAN:
	    quest_chat(mtmp);
	    break;
	case MS_SELL: /* pitch, pay, total */
	    shk_chat(mtmp);
	    break;
	case MS_VAMPIRE:
	    {
	    /* vampire messages are varied by tameness, peacefulness, and time of night */
		boolean isnight = night();
		boolean kindred = maybe_polyd(u.umonnum == PM_VAMPIRE ||
					      u.umonnum == PM_VAMPIRE_LORD,
					      Race_if(PM_VAMPIRE));
		boolean nightchild = (Upolyd && (u.umonnum == PM_WOLF ||
				       u.umonnum == PM_WINTER_WOLF ||
				       u.umonnum == PM_WINTER_WOLF_CUB));
		const char *racenoun = (flags.female && urace.individual.f) ?
					urace.individual.f : (urace.individual.m) ?
					urace.individual.m : urace.noun;

		if (mtmp->mtame) {
			if (kindred) {
				sprintf(verbuf, "Good %s to you Master%s",
					isnight ? "evening" : "day",
					isnight ? "!" : ".  Why do we not rest?");
				verbl_msg = verbuf;
		    	} else {
		    	    sprintf(verbuf,"%s%s",
				nightchild ? "Child of the night, " : "",
				midnight() ?
					"I can stand this craving no longer!" :
				isnight ?
					"I beg you, help me satisfy this growing craving!" :
					"I find myself growing a little weary.");
				verbl_msg = verbuf;
			}
		} else if (mtmp->mpeaceful) {
			if (kindred && isnight) {
				sprintf(verbuf, "Good feeding %s!",
	    				flags.female ? "sister" : "brother");
				verbl_msg = verbuf;
 			} else if (nightchild && isnight) {
				sprintf(verbuf,
				    "How nice to hear you, child of the night!");
				verbl_msg = verbuf;
	    		} else
		    		verbl_msg = "I only drink... potions.";
    	        } else {
			int vampindex;
	    		static const char * const vampmsg[] = {
			       /* These first two (0 and 1) are specially handled below */
	    			"I vant to suck your %s!",
	    			"I vill come after %s without regret!",
		    	       /* other famous vampire quotes can follow here if desired */
	    		};
			if (kindred)
			    verbl_msg = "This is my hunting ground that you dare to prowl!";
			else if (youmonst.data == &mons[PM_SILVER_DRAGON] ||
				 youmonst.data == &mons[PM_BABY_SILVER_DRAGON]) {
			    /* Silver dragons are silver in color, not made of silver */
			    sprintf(verbuf, "%s! Your silver sheen does not frighten me!",
					youmonst.data == &mons[PM_SILVER_DRAGON] ?
					"Fool" : "Young Fool");
			    verbl_msg = verbuf; 
			} else {
			    vampindex = rn2(SIZE(vampmsg));
			    if (vampindex == 0) {
				sprintf(verbuf, vampmsg[vampindex], body_part(BLOOD));
	    			verbl_msg = verbuf;
			    } else if (vampindex == 1) {
				sprintf(verbuf, vampmsg[vampindex],
					Upolyd ? an(mons_mname(&mons[u.umonnum])) : an(racenoun));
	    			verbl_msg = verbuf;
		    	    } else
			    	verbl_msg = vampmsg[vampindex];
			}
	        }
	    }
	    break;
	case MS_WERE:
	    if (flags.moonphase == FULL_MOON && (night() ^ !rn2(13))) {
		pline("%s throws back %s head and lets out a blood curdling %s!",
		      Monnam(mtmp), mhis(level, mtmp),
		      ptr == &mons[PM_HUMAN_WERERAT] ? "shriek" : "howl");
		wake_nearto(mtmp->mx, mtmp->my, 11*11);
	    } else
		pline_msg =
		     "whispers inaudibly.  All you can make out is \"moon\".";
	    break;
	case MS_BARK:
	    if (flags.moonphase == FULL_MOON && night()) {
		pline_msg = "howls.";
	    } else if (mtmp->mpeaceful) {
		if (mtmp->mtame &&
			(mtmp->mconf || mtmp->mflee || mtmp->mtrapped ||
			 moves > EDOG(mtmp)->hungrytime || mtmp->mtame < 5))
		    pline_msg = "whines.";
		else if (mtmp->mtame && EDOG(mtmp)->hungrytime > moves + 1000)
		    pline_msg = "yips.";
		else {
		    if (mtmp->data != &mons[PM_DINGO])	/* dingos do not actually bark */
			    pline_msg = "barks.";
		}
	    } else {
		pline_msg = "growls.";
	    }
	    break;
	case MS_MEW:
	    if (mtmp->mtame) {
		if (mtmp->mconf || mtmp->mflee || mtmp->mtrapped ||
			mtmp->mtame < 5)
		    pline_msg = "yowls.";
		else if (moves > EDOG(mtmp)->hungrytime)
		    pline_msg = "meows.";
		else if (EDOG(mtmp)->hungrytime > moves + 1000)
		    pline_msg = "purrs.";
		else
		    pline_msg = "mews.";
		break;
	    } /* else FALLTHRU */
	case MS_GROWL:
	    if (mtmp->mtame &&
		(mtmp->data == &mons[PM_MONKEY] ||
		 mtmp->data == &mons[PM_APE] ||
		 mtmp->data == &mons[PM_CARNIVOROUS_APE])) {
		if (mtmp->mconf || mtmp->mflee || mtmp->mtrapped ||
		    moves > EDOG(mtmp)->hungrytime || mtmp->mtame < 5) {
		    pline_msg = "shrieks.";
		    wake_nearto(mtmp->mx, mtmp->my, 8*8);
		} else if (EDOG(mtmp)->hungrytime > moves + 1000) {
		    pline_msg = "chatters.";
		} else {
		    pline_msg = "hoots.";
		}
	    } else {
		pline_msg = mtmp->mpeaceful ? "snarls." : "growls!";
	    }
	    break;
	case MS_ROAR:
	    pline_msg = mtmp->mpeaceful ? "snarls." : "roars!";
	    break;
	case MS_SQEEK:
	    pline_msg = "squeaks.";
	    break;
	case MS_SQAWK:
	    if (ptr == &mons[PM_RAVEN] && !mtmp->mpeaceful)
	    	verbl_msg = "Nevermore!";
	    else
	    	pline_msg = "squawks.";
	    break;
	case MS_HISS:
	    if (!mtmp->mpeaceful)
		pline_msg = "hisses!";
	    else return 0;	/* no sound */
	    break;
	case MS_BUZZ:
	    pline_msg = mtmp->mpeaceful ? "drones." : "buzzes angrily.";
	    break;
	case MS_GRUNT:
	    pline_msg = "grunts.";
	    break;
	case MS_NEIGH:
	    if (mtmp->mtame < 5)
		pline_msg = "neighs.";
	    else if (moves > EDOG(mtmp)->hungrytime)
		pline_msg = "whinnies.";
	    else
		pline_msg = "whickers.";
	    break;
	case MS_WAIL:
	    pline_msg = "wails mournfully.";
	    break;
	case MS_GURGLE:
	    pline_msg = "gurgles.";
	    break;
	case MS_BURBLE:
	    pline_msg = "burbles.";
	    break;
	case MS_SHRIEK:
	    pline_msg = "shrieks.";
	    aggravate();
	    break;
	case MS_IMITATE:
	    pline_msg = "imitates you.";
	    break;
	case MS_BONES:
	    pline("%s rattles noisily.", Monnam(mtmp));
	    pline("You freeze for a moment.");
	    nomul(-2, "scared by rattling");
	    break;
	case MS_LAUGH:
	    {
		static const char * const laugh_msg[4] = {
		    "giggles.", "chuckles.", "snickers.", "laughs.",
		};
		pline_msg = laugh_msg[rn2(4)];
	    }
	    break;
	case MS_MUMBLE:
	    pline_msg = "mumbles incomprehensibly.";
	    break;
	case MS_DJINNI:
	    if (mtmp->mtame) {
		verbl_msg = "Sorry, I'm all out of wishes.";
	    } else if (mtmp->mpeaceful) {
		if (ptr == &mons[PM_WATER_DEMON])
		    pline_msg = "gurgles.";
		else
		    verbl_msg = "I'm free!";
	    } else verbl_msg = "This will teach you not to disturb me!";
	    break;
	case MS_BOAST:	/* giants */
	    if (!mtmp->mpeaceful) {
		switch (rn2(4)) {
		case 0: pline("%s boasts about %s gem collection.",
			      Monnam(mtmp), mhis(level, mtmp));
			break;
		case 1: pline_msg = "complains about a diet of mutton.";
			break;
	       default: pline_msg = "shouts \"Fee Fie Foe Foo!\" and guffaws.";
			wake_nearto(mtmp->mx, mtmp->my, 7*7);
			break;
		}
		break;
	    }
	    /* else FALLTHRU */
	case MS_HUMANOID:
	    if (!mtmp->mpeaceful) {
		if (In_endgame(&u.uz) && is_mplayer(ptr)) {
		    mplayer_talk(mtmp);
		    break;
		} else return 0;	/* no sound */
	    }
	    /* Generic peaceful humanoid behaviour. */
	    if (mtmp->mflee)
		pline_msg = "wants nothing to do with you.";
	    else if (mtmp->mhp < mtmp->mhpmax/4)
		pline_msg = "moans.";
	    else if (mtmp->mconf || mtmp->mstun)
		verbl_msg = !rn2(3) ? "Huh?" : rn2(2) ? "What?" : "Eh?";
	    else if (!mtmp->mcansee)
		verbl_msg = "I can't see!";
	    else if (mtmp->mtrapped) {
		struct trap *t = t_at(level, mtmp->mx, mtmp->my);

		if (t) t->tseen = 1;
		verbl_msg = "I'm trapped!";
	    } else if (mtmp->mhp < mtmp->mhpmax/2)
		pline_msg = "asks for a potion of healing.";
	    else if (mtmp->mtame && !mtmp->isminion &&
						moves > EDOG(mtmp)->hungrytime)
		verbl_msg = "I'm hungry.";
	    /* Specific monsters' interests */
	    else if (is_elf(ptr))
		pline_msg = "curses orcs.";
	    else if (is_dwarf(ptr))
		pline_msg = "talks about mining.";
	    else if (likes_magic(ptr))
		pline_msg = "talks about spellcraft.";
	    else if (ptr->mlet == S_CENTAUR)
		pline_msg = "discusses hunting.";
	    else switch (monsndx(ptr)) {
		case PM_HOBBIT:
		    pline_msg = (mtmp->mhpmax - mtmp->mhp >= 10) ?
				"complains about unpleasant dungeon conditions."
				: "asks you about the One Ring.";
		    break;
		case PM_ARCHEOLOGIST:
    pline_msg = "describes a recent article in \"Spelunker Today\" magazine.";
		    break;
		case PM_TOURIST:
		    verbl_msg = "Aloha.";
		    break;
		default:
		    pline_msg = "discusses dungeon exploration.";
		    break;
	    }
	    break;
	case MS_SEDUCE:
	    if (ptr->mlet != S_NYMPH && flags.seduce_enabled &&
		could_seduce(mtmp, &youmonst, NULL) == 1) {
			doseduce(mtmp);
			break;
	    }
	    
	    switch ((poly_gender() != (int) mtmp->female) ? rn2(3) : 0)
	    {
		case 2:
			verbl_msg = "Hello, sailor.";
			break;
		case 1:
			pline_msg = "comes on to you.";
			break;
		default:
			pline_msg = "cajoles you.";
	    }
	    break;
	case MS_ARREST:
	    if (mtmp->mpeaceful)
		verbalize("Just the facts, %s.",
		      flags.female ? "Ma'am" : "Sir");
	    else {
		static const char * const arrest_msg[3] = {
		    "Anything you say can be used against you.",
		    "You're under arrest!",
		    "Stop in the name of the Law!",
		};
		verbl_msg = arrest_msg[rn2(3)];
	    }
	    break;
	case MS_BRIBE:
	    if (monsndx(ptr) == PM_PRISON_GUARD) {
		long gdemand = 500 * u.ulevel;
		long goffer = 0;

		if (!mtmp->mpeaceful && !mtmp->mtame) {
		    pline("%s demands %ld %s to avoid re-arrest.",
			  Amonnam(mtmp), gdemand, currency(gdemand));
		    if ((goffer = bribe(mtmp)) >= gdemand) {
			verbl_msg = "Good.  Now beat it, scum!";
			mtmp->mpeaceful = 1;
			set_malign(mtmp);
		    } else {
			verbalize("I said %ld!", gdemand);
			mtmp->mspec_used = 1000;
		    }
		} else {
		    verbl_msg = "Out of my way, scum!"; /* still a jerk */
		}
		break;
	    } else if (mtmp->mpeaceful && !mtmp->mtame) {
		demon_talk(mtmp);
		break;
	    }
	    /* fall through */
	case MS_CUSS:
	    if (!mtmp->mpeaceful)
		cuss(mtmp);
	    break;
	case MS_SPELL:
	    /* deliberately vague, since it's not actually casting any spell */
	    pline_msg = "seems to mutter a cantrip.";
	    break;
	case MS_NURSE:
	    if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
		verbl_msg = "Put that weapon away before you hurt someone!";
	    else if (uarmc || uarm || uarmh || uarms || uarmg || uarmf)
		verbl_msg = Role_if (PM_HEALER) ?
			  "Doc, I can't help you unless you cooperate." :
			  "Please undress so I can examine you.";
	    else if (uarmu)
		verbl_msg = "Take off your shirt, please.";
	    else
		verbl_msg = "Relax, this won't hurt a bit.";
	    break;
	case MS_GUARD:
	    if (money_cnt(invent))
		verbl_msg = "Please drop that gold and follow me.";
	    else
		verbl_msg = "Please follow me.";
	    break;
	case MS_SOLDIER:
	    {
		static const char * const soldier_foe_msg[3] = {
		    "Resistance is useless!",
		    "You're dog meat!",
		    "Surrender!",
		},		  * const soldier_pax_msg[3] = {
		    "What lousy pay we're getting here!",
		    "The food's not fit for Orcs!",
		    "My feet hurt, I've been on them all day!",
		};
		verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)]
					    : soldier_foe_msg[rn2(3)];
	    }
	    break;
	case MS_RIDER:
	    if (ptr == &mons[PM_DEATH] && !rn2(10))
		pline_msg = "is busy reading a copy of Sandman #8.";
	    else
		verbl_msg = (ptr == &mons[PM_DEATH]) ?
			 "WHO DO YOU THINK YOU ARE, WAR?" :
			 "Who do you think you are, War?";
	    break;
    }

    if (pline_msg) pline("%s %s", Monnam(mtmp), pline_msg);
    else if (verbl_msg) verbalize(verbl_msg);
    return 1;
}
Пример #5
0
// returns 1 when something was stolen
// (or at least, when N should flee now)
// avoid stealing the object stealoid
int steal(struct monst *mtmp)
{
    struct obj *otmp;
    int tmp;
    int named = 0;

    if (!invent) {
	if (Blind)
	    pline("Somebody tries to rob you, but finds nothing to steal.");
	else
	    pline("%s tries to rob you, but she finds nothing to steal!", Monnam(mtmp));
	return 1;	       // let her flee
    }
    tmp = 0;
    for (otmp = invent; otmp; otmp = otmp->nobj)
	if (otmp != uarm2)
	    tmp += ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1);
    tmp = rn2(tmp);
    for (otmp = invent; otmp; otmp = otmp->nobj)
	if (otmp != uarm2)
	    if ((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1))
		< 0)
		break;
    if (!otmp) {
	impossible("Steal fails!");
	return 0;
    }
    if (otmp->o_id == stealoid)
	return 0;
    if ((otmp->owornmask & (W_ARMOR | W_RING))) {
	switch (otmp->olet) {
	    case RING_SYM:
		ringoff(otmp);
		break;
	    case ARMOR_SYM:
		if (multi < 0 || otmp == uarms) {
		    setworn((struct obj *) 0, otmp->owornmask & W_ARMOR);
		    break;
		}
		{
		    int curssv = otmp->cursed;
		    otmp->cursed = 0;
		    stop_occupation();
		    pline("%s seduces you and %s off your %s.", Amonnam(mtmp, Blind ? "gentle" : "beautiful"), otmp->cursed ? "helps you to take" : "you start taking", (otmp == uarmg) ? "gloves" : (otmp == uarmh) ? "helmet" : "armor");
		    named++;
		    (void) armoroff(otmp);
		    otmp->cursed = curssv;
		    if (multi < 0) {
			// multi = 0;
			// nomovemsg = 0;
			// afternmv = 0;
			stealoid = otmp->o_id;
			stealmid = mtmp->m_id;
			afternmv = stealarm;
			return 0;
		    }
		    break;
		}
	    default:
		impossible("Tried to steal a strange worn thing.");
	}
    } else if (otmp == uwep)
	setuwep((struct obj *) 0);
    if (otmp->olet == CHAIN_SYM) {
	impossible("How come you are carrying that chain?");
    }
    if (Punished && otmp == uball) {
	Punished = 0;
	freeobj(uchain);
	free((char *) uchain);
	uchain = (struct obj *) 0;
	uball->spe = 0;
	uball = (struct obj *) 0;	// superfluous
    }
    freeinv(otmp);
    pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp));
    mpickobj(mtmp, otmp);
    return multi < 0 ? 0 : 1;
}
Пример #6
0
/* Generate earthquake :-) of desired force. That is: create random chasms
   (pits). Currently assumes that the player created it (you'll need to change
   at least messages, angering, and kill credit if you generalize it). */
static void
do_earthquake(int force)
{
    int x, y;
    struct monst *mtmp;
    struct obj *otmp;
    struct trap *chasm, *oldtrap;
    int start_x, start_y, end_x, end_y;

    start_x = youmonst.mx - (force * 2);
    start_y = youmonst.my - (force * 2);
    end_x = youmonst.mx + (force * 2);
    end_y = youmonst.my + (force * 2);
    if (start_x < 0)
        start_x = 0;
    if (start_y < 0)
        start_y = 0;
    if (end_x >= COLNO)
        end_x = COLNO - 1;
    if (end_y >= ROWNO)
        end_y = ROWNO - 1;
    for (x = start_x; x <= end_x; x++)
        for (y = start_y; y <= end_y; y++) {
            if ((mtmp = m_at(level, x, y)) != 0) {
                wakeup(mtmp, FALSE);  /* peaceful monster will become hostile */
                if (mtmp->mundetected && is_hider(mtmp->data)) {
                    mtmp->mundetected = 0;
                    if (cansee(x, y))
                        pline(msgc_youdiscover, "%s is shaken loose from %s!",
                              Amonnam(mtmp), mtmp->data == &mons[PM_TRAPPER] ?
                              "its hiding place" : the(ceiling(youmonst.mx, youmonst.my)));
                    else
                        You_hear(msgc_levelsound, "a thumping sound.");
                    if (x == youmonst.mx && y == youmonst.my &&
                        mtmp->data != &mons[PM_TRAPPER])
                        pline(msgc_moncombatgood,
                              "You easily dodge the falling %s.",
                              mon_nam(mtmp));
                    newsym(x, y);
                }
            }
            if (!rn2(14 - force))
                switch (level->locations[x][y].typ) {
                case FOUNTAIN: /* Make the fountain disappear */
                    if (cansee(x, y))
                        pline(msgc_consequence,
                              "The fountain falls into a chasm.");
                    goto do_pit;
                case SINK:
                    if (cansee(x, y))
                        pline(msgc_consequence,
                              "The kitchen sink falls into a chasm.");
                    goto do_pit;
                case ALTAR:
                    if (level->locations[x][y].altarmask & AM_SANCTUM)
                        break;

                    if (cansee(x, y))
                        pline(msgc_consequence,
                              "The altar falls into a chasm.");
                    goto do_pit;
                case GRAVE:
                    if (cansee(x, y))
                        pline(msgc_consequence,
                              "The headstone topples into a chasm.");
                    goto do_pit;
                case THRONE:
                    if (cansee(x, y))
                        pline(msgc_consequence,
                              "The throne falls into a chasm.");
                    /* Falls into next case */
                case ROOM:
                case CORR:     /* Try to make a pit */
                    /* Pits, spiked pits, holes, trapdoors, vibrating squares,
                       magic portals are immune.  A bear trap will leave the
                       trap in the pit.  It would be kind of cool to make
                       landmines detonate, but that's more trouble than it's
                       worth. */
                    if ((oldtrap = t_at(level, x, y))) {
                        if (oldtrap->ttyp == PIT || oldtrap->ttyp == SPIKED_PIT
                            || oldtrap->ttyp == HOLE ||
                            oldtrap->ttyp == TRAPDOOR ||
                            oldtrap->ttyp == VIBRATING_SQUARE ||
                            oldtrap->ttyp == MAGIC_PORTAL)
                            break;

                        if (oldtrap->ttyp == BEAR_TRAP) {
                            if (mtmp)
                                mtmp->mtrapped = 0;
                            cnv_trap_obj(level, BEARTRAP, 1, oldtrap);
                        }
                    }

                do_pit:
                    chasm = maketrap(level, x, y, PIT, rng_main);
                    if (!chasm)
                        break;  /* no pit if portal at that location */
                    chasm->tseen = 1;

                    level->locations[x][y].doormask = 0;

                    mtmp = m_at(level, x, y);

                    if ((otmp = sobj_at(BOULDER, level, x, y)) != 0) {
                        if (cansee(x, y))
                            pline(msgc_consequence,
                                  "KADOOM! The boulder falls into a chasm%s!",
                                  ((x == youmonst.mx) &&
                                   (y == youmonst.my)) ? " below you" : "");
                        if (mtmp)
                            mtmp->mtrapped = 0;
                        obj_extract_self(otmp);
                        flooreffects(otmp, x, y, "");
                        break;
                    }

                    /* We have to check whether monsters or player falls in a
                       chasm... */

                    if (mtmp) {
                        if (!flying(mtmp) && !levitates(mtmp) &&
                            !is_clinger(mtmp->data)) {
                            mtmp->mtrapped = 1;
                            if (cansee(x, y))
                                pline(combat_msgc(&youmonst, mtmp, cr_hit),
                                      "%s falls into a chasm!", Monnam(mtmp));
                            else if (humanoid(mtmp->data))
                                You_hear(msgc_levelsound, "a scream!");
                            mselftouch(mtmp, "Falling, ", &youmonst);
                            if (!DEADMONSTER(mtmp))
                                if ((mtmp->mhp -= rnd(6)) <= 0) {
                                    if (!cansee(x, y))
                                        pline(msgc_kill, "It is destroyed!");
                                    else {
                                        pline(msgc_petfatal, "You destroy %s!",
                                              mtmp->mtame ?
                                              x_monnam(mtmp, ARTICLE_THE,
                                                       "poor", mx_name(mtmp) ?
                                                       SUPPRESS_SADDLE : 0,
                                                       FALSE) : mon_nam(mtmp));
                                    }
                                    xkilled(mtmp, 0);
                                }
                        }
                    } else if (!u.utrap && x == youmonst.mx && y == youmonst.my) {
                        if (Levitation || Flying || is_clinger(youmonst.data)) {
                            pline(msgc_noconsequence,
                                  "A chasm opens up under you!");
                            pline(msgc_noconsequence, "You don't fall in!");
                        } else {
                            pline(msgc_badidea, "You fall into a chasm!");
                            u.utrap = rn1(6, 2);
                            u.utraptype = TT_PIT;
                            turnstate.vision_full_recalc = TRUE;
                            losehp(rnd(6), "fell into a chasm");
                            selftouch("Falling, you",
                                      "falling into a chasm while wielding");
                        }
                    } else
                        newsym(x, y);
                    break;
                case DOOR:     /* Make the door collapse */
                    if (level->locations[x][y].doormask == D_NODOOR)
                        goto do_pit;
                    if (cansee(x, y))
                        pline(msgc_consequence, "The door collapses.");
                    if (*in_rooms(level, x, y, SHOPBASE))
                        add_damage(x, y, 0L);
                    level->locations[x][y].doormask = D_NODOOR;
                    unblock_point(x, y);
                    newsym(x, y);
                    break;
                }
        }
}
Пример #7
0
/*
 * mhitu: monster hits you
 *	  returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise
 */
bool
mhitu(struct monst *mtmp)
{
	struct permonst *mdat = mtmp->data;
	int tmp, ctmp;

	nomul(0);

	/* If swallowed, can only be affected by hissers and by u.ustuck */
	if (u.uswallow) {
		if (mtmp != u.ustuck) {
			if (mdat->mlet == 'c' && !rn2(13)) {
				pline("Outside, you hear %s's hissing!",
				      monnam(mtmp));
				pline("%s gets turned to stone!",
				      Monnam(u.ustuck));
				pline("And the same fate befalls you.");
				done_in_by(mtmp);
				/* "notreached": not return(1); */
			}
			return (0);
		}
		switch (mdat->mlet) {	/* now mtmp == u.ustuck */
		case ',':
			youswld(mtmp, (u.uac > 0) ? u.uac + 4 : 4,
				5, "The trapper");
			break;
		case '\'':
			youswld(mtmp, rnd(6), 7, "The lurker above");
			break;
		case 'P':
			youswld(mtmp, d(2, 4), 12, "The purple worm");
			break;
		default:
			/* This is not impossible! */
			pline("The mysterious monster totally digests you.");
			u.uhp = 0;
		}
		if (u.uhp < 1)
			done_in_by(mtmp);
		return (0);
	}

	if (mdat->mlet == 'c' && Stoned)
		return (0);

	/* make eels visible the moment they hit/miss us */
	if (mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx, mtmp->my)) {
		mtmp->minvis = 0;
		pmon(mtmp);
	}
	if (!strchr("1&DuxynNF", mdat->mlet))
		tmp = hitu(mtmp, d(mdat->damn, mdat->damd));
	else
		tmp = 0;
	if (strchr(UNDEAD, mdat->mlet) && midnight())
		tmp += hitu(mtmp, d(mdat->damn, mdat->damd));

	ctmp = tmp && !mtmp->mcan &&
	    (!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50));
	switch (mdat->mlet) {
	case '1':
		if (wiz_hit(mtmp))	/* he disappeared */
			return (1);
		break;
	case '&':
		if (!mtmp->cham && !mtmp->mcan && !rn2(13)) {
			makemon(PM_DEMON, u.ux, u.uy);
		} else {
			hitu(mtmp, d(2, 6));
			hitu(mtmp, d(2, 6));
			hitu(mtmp, rnd(3));
			hitu(mtmp, rnd(3));
			hitu(mtmp, rn1(4, 2));
		}
		break;
	case ',':
		if (tmp)
			justswld(mtmp, "The trapper");
		break;
	case '\'':
		if (tmp)
			justswld(mtmp, "The lurker above");
		break;
	case ';':
		if (ctmp) {
			if (!u.ustuck && !rn2(10)) {
				pline("%s swings itself around you!",
				      Monnam(mtmp));
				u.ustuck = mtmp;
			} else if (u.ustuck == mtmp &&
				   levl[mtmp->mx][mtmp->my].typ == POOL) {
				pline("%s drowns you ...", Monnam(mtmp));
				done("drowned");
			}
		}
		break;
	case 'A':
		if (ctmp && rn2(2)) {
			if (Poison_resistance)
				pline("The sting doesn't seem to affect you.");
			else {
				pline("You feel weaker!");
				losestr(1);
			}
		}
		break;
	case 'C':
		hitu(mtmp, rnd(6));
		break;
	case 'c':
		if (!rn2(5)) {
			pline("You hear %s's hissing!", monnam(mtmp));
			if (ctmp || !rn2(20) || (flags.moonphase == NEW_MOON
			    && !carrying(DEAD_LIZARD)))
				Stoned = 5;
		}
		break;
	case 'D':
		if (rn2(6) || mtmp->mcan) {
			hitu(mtmp, d(3, 10));
			hitu(mtmp, rnd(8));
			hitu(mtmp, rnd(8));
			break;
		}
		kludge("%s breathes fire!", "The dragon");
		buzz(-1, mtmp->mx, mtmp->my, u.ux - mtmp->mx, u.uy - mtmp->my);
		break;
	case 'd':
		hitu(mtmp, d(2, (flags.moonphase == FULL_MOON) ? 3 : 4));
		break;
	case 'e':
		hitu(mtmp, d(3, 6));
		break;
	case 'F':
		if (mtmp->mcan)
			break;
		kludge("%s explodes!", "The freezing sphere");
		if (Cold_resistance)
			pline("You don't seem affected by it.");
		else {
			xchar dn;
			if (17 - (u.ulevel / 2) > rnd(20)) {
				pline("You get blasted!");
				dn = 6;
			} else {
				pline("You duck the blast...");
				dn = 3;
			}
			losehp_m(d(dn, 6), mtmp);
		}
		mondead(mtmp);
		return (1);
	case 'g':
		if (ctmp && multi >= 0 && !rn2(3)) {
			kludge("You are frozen by %ss juices", "the cube'");
			nomul(-rnd(10));
		}
		break;
	case 'h':
		if (ctmp && multi >= 0 && !rn2(5)) {
			nomul(-rnd(10));
			kludge("You are put to sleep by %ss bite!",
			       "the homunculus'");
		}
		break;
	case 'j':
		tmp = hitu(mtmp, rnd(3));
		tmp &= hitu(mtmp, rnd(3));
		if (tmp) {
			hitu(mtmp, rnd(4));
			hitu(mtmp, rnd(4));
		}
		break;
	case 'k':
		if ((hitu(mtmp, rnd(4)) || !rn2(3)) && ctmp)
			poisoned("bee's sting", mdat->mname);
		break;
	case 'L':
		if (tmp)
			stealgold(mtmp);
		break;
	case 'N':
		if (mtmp->mcan && !Blind) {
			pline("%s tries to seduce you, but you seem not interested.",
			    Amonnam(mtmp, "plain"));
			if (rn2(3))
				rloc(mtmp);
		} else if (steal(mtmp)) {
			rloc(mtmp);
			mtmp->mflee = 1;
		}
		break;
	case 'n':
		if (!uwep && !uarm && !uarmh && !uarms && !uarmg) {
			pline("%s hits! (I hope you don't mind)",
			      Monnam(mtmp));
			u.uhp += rnd(7);
			if (!rn2(7))
				u.uhpmax++;
			if (u.uhp > u.uhpmax)
				u.uhp = u.uhpmax;
			flags.botl = 1;
			if (!rn2(50))
				rloc(mtmp);
		} else {
			hitu(mtmp, d(2, 6));
			hitu(mtmp, d(2, 6));
		}
		break;
	case 'o':
		tmp = hitu(mtmp, rnd(6));
		if (hitu(mtmp, rnd(6)) && tmp &&	/* hits with both paws */
		    !u.ustuck && rn2(2)) {
			u.ustuck = mtmp;
			kludge("%s has grabbed you!", "The owlbear");
			u.uhp -= d(2, 8);
		} else if (u.ustuck == mtmp) {
			u.uhp -= d(2, 8);
			pline("You are being crushed.");
		}
		break;
	case 'P':
		if (ctmp && !rn2(4))
			justswld(mtmp, "The purple worm");
		else
			hitu(mtmp, d(2, 4));
		break;
	case 'Q':
		hitu(mtmp, rnd(2));
		hitu(mtmp, rnd(2));
		break;
	case 'R':
		if (tmp && uarmh && !uarmh->rustfree &&
		    (int)uarmh->spe >= -1) {
			pline("Your helmet rusts!");
			uarmh->spe--;
		} else if (ctmp && uarm && !uarm->rustfree &&	/* Mike Newton */
		    uarm->otyp < STUDDED_LEATHER_ARMOR &&
		    (int)uarm->spe >= -1) {
			pline("Your armor rusts!");
			uarm->spe--;
		}
		break;
	case 'S':
		if (ctmp && !rn2(8))
			poisoned("snake's bite", mdat->mname);
		break;
	case 's':
		if (tmp && !rn2(8))
			poisoned("scorpion's sting", mdat->mname);
		hitu(mtmp, rnd(8));
		hitu(mtmp, rnd(8));
		break;
	case 'T':
		hitu(mtmp, rnd(6));
		hitu(mtmp, rnd(6));
		break;
	case 't':
		if (!rn2(5))
			rloc(mtmp);
		break;
	case 'u':
		mtmp->mflee = 1;
		break;
	case 'U':
		hitu(mtmp, d(3, 4));
		hitu(mtmp, d(3, 4));
		break;
	case 'v':
		if (ctmp && !u.ustuck)
			u.ustuck = mtmp;
		break;
	case 'V':
		if (tmp)
			u.uhp -= 4;
		if (ctmp)
			losexp();
		break;
	case 'W':
		if (ctmp)
			losexp();
		break;
#ifndef NOWORM
	case 'w':
		if (tmp)
			wormhit(mtmp);
#endif /* NOWORM */
		break;
	case 'X':
		hitu(mtmp, rnd(5));
		hitu(mtmp, rnd(5));
		hitu(mtmp, rnd(5));
		break;
	case 'x':
		{
			long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
			pline("%s pricks in your %s leg!",
			    Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left");
			set_wounded_legs(side, rnd(50));
			losehp_m(2, mtmp);
			break;
		}
	case 'y':
		if (mtmp->mcan)
			break;
		mondead(mtmp);
		if (!Blind) {
			pline("You are blinded by a blast of light!");
			Blind = d(4, 12);
			seeoff(0);
		}
		return (1);
	case 'Y':
		hitu(mtmp, rnd(6));
		break;
	}
	if (u.uhp < 1)
		done_in_by(mtmp);
	return (0);
}