示例#1
0
void rehumanize(void)
{
	/* You can't revert back while unchanging */
	if (Unchanging && (u.mh < 1)) {
		killer_format = NO_KILLER_PREFIX;
		killer = "killed while stuck in creature form";
		done(DIED);
	}

	if (emits_light(youmonst.data))
	    del_light_source(level, LS_MONSTER, &youmonst);
	polyman("You return to %s form!", urace.adj);

	if (u.uhp < 1) {
	    char kbuf[256];

	    sprintf(kbuf, "reverting to unhealthy %s form", urace.adj);
	    killer_format = KILLED_BY;
	    killer = kbuf;
	    done(DIED);
	}
	if (!uarmg) selftouch("No longer petrify-resistant, you");
	nomul(0, NULL);

	iflags.botl = 1;
	vision_full_recalc = 1;
	encumber_msg();
}
示例#2
0
void rehumanize (void) {
    /* You can't revert back while unchanging */
    if (Unchanging && (u.mh < 1)) {
        killer = killed_by_const(KM_WHILE_STUCK_IN_CREATURE_FORM);
        done(DIED);
    }

    if (emits_light(youmonst.data))
        del_light_source(LS_MONSTER, (void *)&youmonst);
    polyman("return to %s form!", urace.adj);

    if (u.uhp < 1) {
        char kbuf[256];

        sprintf(kbuf, "reverting to unhealthy %s form", urace.adj);
        fprintf(stderr, "TODO killer = %s\n", kbuf);
        done(DIED);
    }
    if (!uarmg) selftouch("No longer petrify-resistant, you");
    nomul(0);

    vision_full_recalc = 1;
    (void) encumber_msg();
}
示例#3
0
void polyself(boolean forcecontrol)
{
	char buf[BUFSZ];
	int old_light, new_light;
	int mntmp = NON_PM;
	int tries=0;
	boolean draconian = (uarm &&
				uarm->otyp >= GRAY_DRAGON_SCALE_MAIL &&
				uarm->otyp <= YELLOW_DRAGON_SCALES);
	boolean iswere = (u.ulycn >= LOW_PM || is_were(youmonst.data));
	boolean isvamp = (youmonst.data->mlet == S_VAMPIRE || u.umonnum == PM_VAMPIRE_BAT);
	boolean was_floating = (Levitation || Flying);

        if (!Polymorph_control && !forcecontrol && !draconian && !iswere && !isvamp) {
	    if (rn2(20) > ACURR(A_CON)) {
		pline("You shudder for a moment.");
		losehp(rnd(30), "system shock", KILLED_BY_AN);
		exercise(A_CON, FALSE);
		return;
	    }
	}
	old_light = Upolyd ? emits_light(youmonst.data) : 0;

	if (Polymorph_control || forcecontrol) {
		do {
			getlin("Become what kind of monster? [type the name]",
				buf);
			mntmp = name_to_mon(buf);
			if (mntmp < LOW_PM)
				pline("I've never heard of such monsters.");
			/* Note:  humans are illegal as monsters, but an
			 * illegal monster forces newman(), which is what we
			 * want if they specified a human.... */
			else if (!polyok(&mons[mntmp]) && !your_race(&mons[mntmp]))
				pline("You cannot polymorph into that.");
			else break;
		} while (++tries < 5);
		if (tries==5) pline("That's enough tries!");
		/* allow skin merging, even when polymorph is controlled */
		if (draconian &&
		    (mntmp == armor_to_dragon(uarm->otyp) || tries == 5))
		    goto do_merge;
	} else if (draconian || iswere || isvamp) {
		/* special changes that don't require polyok() */
		if (draconian) {
		    do_merge:
			mntmp = armor_to_dragon(uarm->otyp);
			if (!(mvitals[mntmp].mvflags & G_GENOD)) {
				/* allow G_EXTINCT */
				pline("You merge with your scaly armor.");
				uskin = uarm;
				uarm = NULL;
				/* save/restore hack */
				uskin->owornmask |= I_SPECIAL;
			}
		} else if (iswere) {
			if (is_were(youmonst.data))
				mntmp = PM_HUMAN; /* Illegal; force newman() */
			else
				mntmp = u.ulycn;
		} else {
			if (youmonst.data->mlet == S_VAMPIRE)
				mntmp = PM_VAMPIRE_BAT;
			else
				mntmp = PM_VAMPIRE;
		}
		/* if polymon fails, "you feel" message has been given
		   so don't follow up with another polymon or newman */
		if (mntmp == PM_HUMAN) newman();	/* werecritter */
		else polymon(mntmp);
		goto made_change;    /* maybe not, but this is right anyway */
	}

	if (mntmp < LOW_PM) {
		tries = 0;
		do {
			/* randomly pick an "ordinary" monster */
			mntmp = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
		} while ((!polyok(&mons[mntmp]) || is_placeholder(&mons[mntmp]))
				&& tries++ < 200);
	}

	/* The below polyok() fails either if everything is genocided, or if
	 * we deliberately chose something illegal to force newman().
	 */
	if (!polyok(&mons[mntmp]) || !rn2(5) || your_race(&mons[mntmp]))
		newman();
	else if (!polymon(mntmp)) return;

	if (!uarmg) selftouch("No longer petrify-resistant, you");

 made_change:
	new_light = Upolyd ? emits_light(youmonst.data) : 0;
	if (old_light != new_light) {
	    if (old_light)
		del_light_source(level, LS_MONSTER, &youmonst);
	    if (new_light == 1) ++new_light;  /* otherwise it's undetectable */
	    if (new_light)
		new_light_source(level, u.ux, u.uy, new_light,
				 LS_MONSTER, &youmonst);
	}
	if (is_pool(level, u.ux,u.uy) && was_floating && !(Levitation || Flying) &&
		!breathless(youmonst.data) && !amphibious(youmonst.data) &&
		!Swimming) drown();
}
示例#4
0
int
doread()
{
	struct obj *scroll;
	boolean confused = (Confusion != 0);
	boolean known = FALSE;

	scroll = getobj("?", "read");
	if(!scroll) return(0);
	if(!scroll->dknown && Blind) {
	    pline("Being blind, you cannot read the formula on the scroll.");
	    return(0);
	}
	if(Blind)
	  pline("As you pronounce the formula on it, the scroll disappears.");
	else
	  pline("As you read the scroll, it disappears.");
	if(confused)
	  pline("Being confused, you mispronounce the magic words ... ");

	switch(scroll->otyp) {
#ifdef MAIL
	case SCR_MAIL:
		readmail(/* scroll */);
		break;
#endif /* MAIL */
	case SCR_ENCHANT_ARMOR:
	    {	struct obj *otmp = some_armor();
		if(!otmp) {
			strange_feeling(scroll,"Your skin glows then fades.");
			return(1);
		}
		if(confused) {
			pline("Your %s glows silver for a moment.",
				objects[otmp->otyp].oc_name);
			otmp->rustfree = 1;
			break;
		}
		if(otmp->spe > 3 && rn2(otmp->spe)) {
	pline("Your %s glows violently green for a while, then evaporates.",
			objects[otmp->otyp].oc_name);
			useup(otmp);
			break;
		}
		pline("Your %s glows green for a moment.",
			objects[otmp->otyp].oc_name);
		otmp->cursed = 0;
		otmp->spe++;
		break;
	    }
	case SCR_DESTROY_ARMOR:
		if(confused) {
			struct obj *otmp = some_armor();
			if(!otmp) {
				strange_feeling(scroll,"Your bones itch.");
				return(1);
			}
			pline("Your %s glows purple for a moment.",
				objects[otmp->otyp].oc_name);
			otmp->rustfree = 0;
			break;
		}
		if(uarm) {
		    pline("Your armor turns to dust and falls to the floor!");
		    useup(uarm);
		} else if(uarmh) {
		    pline("Your helmet turns to dust and is blown away!");
		    useup(uarmh);
		} else if(uarmg) {
			pline("Your gloves vanish!");
			useup(uarmg);
			selftouch("You");
		} else {
			strange_feeling(scroll,"Your skin itches.");
			return(1);
		}
		break;
	case SCR_CONFUSE_MONSTER:
		if(confused) {
			pline("Your hands begin to glow purple.");
			Confusion += rnd(100);
		} else {
			pline("Your hands begin to glow blue.");
			u.umconf = 1;
		}
		break;
	case SCR_SCARE_MONSTER:
	    {	int ct = 0;
		struct monst *mtmp;

		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
			if(cansee(mtmp->mx,mtmp->my)) {
				if(confused)
					mtmp->mflee = mtmp->mfroz =
					mtmp->msleep = 0;
				else
					mtmp->mflee = 1;
				ct++;
			}
		if(!ct) {
		    if(confused)
			pline("You hear sad wailing in the distance.");
		    else
			pline("You hear maniacal laughter in the distance.");
		}
		break;
	    }
	case SCR_BLANK_PAPER:
		if(confused)
		    pline("You see strange patterns on this scroll.");
		else
		    pline("This scroll seems to be blank.");
		break;
	case SCR_REMOVE_CURSE:
	    {	struct obj *obj;
		if(confused)
		  pline("You feel like you need some help.");
		else
		  pline("You feel like someone is helping you.");
		for(obj = invent; obj ; obj = obj->nobj)
			if(obj->owornmask)
				obj->cursed = confused;
		if(Punished && !confused) {
			Punished = 0;
			freeobj(uchain);
			unpobj(uchain);
			free(uchain);
			uball->spe = 0;
			uball->owornmask &= ~W_BALL;
			uchain = uball = (struct obj *) 0;
		}
		break;
	    }
	case SCR_CREATE_MONSTER:
	    {	int cnt = 1;

		if(!rn2(73)) cnt += rnd(4);
		if(confused) cnt += 12;
		while(cnt--)
		    (void) makemon(confused ? PM_ACID_BLOB :
			(struct permonst *) 0, u.ux, u.uy);
		break;
	    }
	case SCR_ENCHANT_WEAPON:
		if(uwep && confused) {
			pline("Your %s glows silver for a moment.",
				objects[uwep->otyp].oc_name);
			uwep->rustfree = 1;
		} else
			if(!chwepon(scroll, 1))		/* tests for !uwep */
				return(1);
		break;
	case SCR_DAMAGE_WEAPON:
		if(uwep && confused) {
			pline("Your %s glows purple for a moment.",
				objects[uwep->otyp].oc_name);
			uwep->rustfree = 0;
		} else
			if(!chwepon(scroll, -1))	/* tests for !uwep */
				return(1);
		break;
	case SCR_TAMING:
	    {	int i,j;
		int bd = confused ? 5 : 1;
		struct monst *mtmp;

		for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++)
		if ((mtmp = m_at(u.ux+i, u.uy+j)))
			(void) tamedog(mtmp, NULL);
		break;
	    }
	case SCR_GENOCIDE:
	    {	extern char genocided[], fut_geno[];
		char buf[BUFSZ];
		struct monst *mtmp, *mtmp2;

		pline("You have found a scroll of genocide!");
		known = TRUE;
		if(confused)
			*buf = u.usym;
		else do {
	    pline("What monster do you want to genocide (Type the letter)? ");
			getlin(buf);
		} while(strlen(buf) != 1 || !monstersym(*buf));
		if(!strchr(fut_geno, *buf))
			charcat(fut_geno, *buf);
		if(!strchr(genocided, *buf))
			charcat(genocided, *buf);
		else {
			pline("Such monsters do not exist in this world.");
			break;
		}
		for(mtmp = fmon; mtmp; mtmp = mtmp2){
			mtmp2 = mtmp->nmon;
			if(mtmp->data->mlet == *buf)
				mondead(mtmp);
		}
		pline("Wiped out all %c's.", *buf);
		if(*buf == u.usym) {
			killer = "scroll of genocide";
			u.uhp = -1;
		}
		break;
		}
	case SCR_LIGHT:
		if(!Blind) known = TRUE;
		litroom(!confused);
		break;
	case SCR_TELEPORTATION:
		if(confused)
			level_tele();
		else {
#ifdef QUEST
			int oux = u.ux, ouy = u.uy;
			tele();
			if(dist(oux, ouy) > 100) known = TRUE;
#else /* QUEST */
			int uroom = inroom(u.ux, u.uy);
			tele();
			if(uroom != inroom(u.ux, u.uy)) known = TRUE;
#endif /* QUEST */
		}
		break;
	case SCR_GOLD_DETECTION:
	    /* Unfortunately this code has become slightly less elegant,
	       now that gold and traps no longer are of the same type. */
	    if(confused) {
		struct trap *ttmp;

		if(!ftrap) {
			strange_feeling(scroll, "Your toes stop itching.");
			return(1);
		} else {
			for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
				if(ttmp->tx != u.ux || ttmp->ty != u.uy)
					goto outtrapmap;
			/* only under me - no separate display required */
			pline("Your toes itch!");
			break;
		outtrapmap:
			cls();
			for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
				at(ttmp->tx, ttmp->ty, '$');
			prme();
			pline("You feel very greedy!");
		}
	    } else {
		struct gold *gtmp;

		if(!fgold) {
			strange_feeling(scroll, "You feel materially poor.");
			return(1);
		} else {
			known = TRUE;
			for(gtmp = fgold; gtmp; gtmp = gtmp->ngold)
				if(gtmp->gx != u.ux || gtmp->gy != u.uy)
					goto outgoldmap;
			/* only under me - no separate display required */
			pline("You notice some gold between your feet.");
			break;
		outgoldmap:
			cls();
			for(gtmp = fgold; gtmp; gtmp = gtmp->ngold)
				at(gtmp->gx, gtmp->gy, '$');
			prme();
			pline("You feel very greedy, and sense gold!");
		}
	    }
		/* common sequel */
		more();
		docrt();
		break;
	case SCR_FOOD_DETECTION:
	    {	int ct = 0, ctu = 0;
		struct obj *obj;
		char foodsym = confused ? POTION_SYM : FOOD_SYM;

		for(obj = fobj; obj; obj = obj->nobj)
			if(obj->olet == FOOD_SYM) {
				if(obj->ox == u.ux && obj->oy == u.uy) ctu++;
				else ct++;
			}
		if(!ct && !ctu) {
			strange_feeling(scroll,"Your nose twitches.");
			return(1);
		} else if(!ct) {
			known = TRUE;
			pline("You smell %s close nearby.",
				confused ? "something" : "food");
			
		} else {
			known = TRUE;
			cls();
			for(obj = fobj; obj; obj = obj->nobj)
			    if(obj->olet == foodsym)
				at(obj->ox, obj->oy, FOOD_SYM);
			prme();
			pline("Your nose tingles and you smell %s!",
				confused ? "something" : "food");
			more();
			docrt();
		}
		break;
	    }
	case SCR_IDENTIFY:
		/* known = TRUE; */
		if(confused)
			pline("You identify this as an identify scroll.");
		else
			pline("This is an identify scroll.");
		useup(scroll);
		objects[SCR_IDENTIFY].oc_name_known = 1;
		if(!confused)
		    while(
			!ggetobj("identify", identify, rn2(5) ? 1 : rn2(5))
			&& invent
		    );
		return(1);
	case SCR_MAGIC_MAPPING:
	    {	struct rm *lev;
		int num, zx, zy;

		known = TRUE;
		pline("On this scroll %s a map!",
			confused ? "was" : "is");
		for(zy = 0; zy < ROWNO; zy++)
			for(zx = 0; zx < COLNO; zx++) {
				if(confused && rn2(7)) continue;
				lev = &(levl[zx][zy]);
				if((num = lev->typ) == 0)
					continue;
				if(num == SCORR) {
					lev->typ = CORR;
					lev->scrsym = CORR_SYM;
				} else
				if(num == SDOOR) {
					lev->typ = DOOR;
					lev->scrsym = '+';
					/* do sth in doors ? */
				} else if(lev->seen) continue;
#ifndef QUEST
				if(num != ROOM)
#endif /* QUEST */
				{
				  lev->seen = lev->new = 1;
				  if(lev->scrsym == ' ' || !lev->scrsym)
				    newsym(zx,zy);
				  else
				    on_scr(zx,zy);
				}
			}
		break;
	    }
	case SCR_AMNESIA:
	    {	int zx, zy;

		known = TRUE;
		for(zx = 0; zx < COLNO; zx++) for(zy = 0; zy < ROWNO; zy++)
		    if(!confused || rn2(7))
			if(!cansee(zx,zy))
			    levl[zx][zy].seen = 0;
		docrt();
		pline("Thinking of Maud you forget everything else.");
		break;
	    }
	case SCR_FIRE:
	    {	int num;
		struct monst *mtmp;

		known = TRUE;
		if(confused) {
		    pline("The scroll catches fire and you burn your hands.");
		    losehp(1, "scroll of fire");
		} else {
		    pline("The scroll erupts in a tower of flame!");
		    if(Fire_resistance)
			pline("You are uninjured.");
		    else {
			num = rnd(6);
			u.uhpmax -= num;
			losehp(num, "scroll of fire");
		    }
		}
		num = (2*num + 1)/3;
		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
		    if(dist(mtmp->mx,mtmp->my) < 3) {
			mtmp->mhp -= num;
			if(strchr("FY", mtmp->data->mlet))
			    mtmp->mhp -= 3*num;	/* this might well kill 'F's */
			if(mtmp->mhp < 1) {
			    killed(mtmp);
			    break;		/* primitive */
			}
		    }
		}
		break;
	    }
	case SCR_PUNISHMENT:
		known = TRUE;
		if(confused) {
			pline("You feel guilty.");
			break;
		}
		pline("You are being punished for your misbehaviour!");
		if(Punished){
			pline("Your iron ball gets heavier.");
			uball->owt += 15;
			break;
		}
		Punished = INTRINSIC;
		setworn(mkobj_at(CHAIN_SYM, u.ux, u.uy), W_CHAIN);
		setworn(mkobj_at(BALL_SYM, u.ux, u.uy), W_BALL);
		uball->spe = 1;		/* special ball (see save) */
		break;
	default:
		impossible("What weird language is this written in? (%u)",
			scroll->otyp);
	}
示例#5
0
文件: hack.do.c 项目: lattera/openbsd
void
goto_level(int newlevel, boolean at_stairs)
{
	int fd;
	boolean up = (newlevel < dlevel);

	if(newlevel <= 0) done("escaped");    /* in fact < 0 is impossible */
	if(newlevel > MAXLEVEL) newlevel = MAXLEVEL;	/* strange ... */
	if(newlevel == dlevel) return;	      /* this can happen */

	glo(dlevel);
	fd = creat(lock, FMASK);
	if(fd < 0) {
		/*
		 * This is not quite impossible: e.g., we may have
		 * exceeded our quota. If that is the case then we
		 * cannot leave this level, and cannot save either.
		 * Another possibility is that the directory was not
		 * writable.
		 */
		pline("A mysterious force prevents you from going %s.",
			up ? "up" : "down");
		return;
	}

	if(Punished) unplacebc();
	u.utrap = 0;				/* needed in level_tele */
	u.ustuck = 0;				/* idem */
	keepdogs();
	seeoff(1);
	if(u.uswallow)				/* idem */
		u.uswldtim = u.uswallow = 0;
	flags.nscrinh = 1;
	u.ux = FAR;				/* hack */
	(void) inshop();			/* probably was a trapdoor */

	savelev(fd,dlevel);
	(void) close(fd);

	dlevel = newlevel;
	if(maxdlevel < dlevel)
		maxdlevel = dlevel;
	glo(dlevel);

	if(!level_exists[(int)dlevel])
		mklev();
	else {
		extern int hackpid;

		if((fd = open(lock, O_RDONLY)) < 0) {
			pline("Cannot open %s .", lock);
			pline("Probably someone removed it.");
			done("tricked");
		}
		getlev(fd, hackpid, dlevel);
		(void) close(fd);
	}

	if(at_stairs) {
	    if(up) {
		u.ux = xdnstair;
		u.uy = ydnstair;
		if(!u.ux) {		/* entering a maze from below? */
		    u.ux = xupstair;	/* this will confuse the player! */
		    u.uy = yupstair;
		}
		if(Punished && !Levitation){
			pline("With great effort you climb the stairs.");
			placebc(1);
		}
	    } else {
		u.ux = xupstair;
		u.uy = yupstair;
		if(inv_weight() + 5 > 0 || Punished){
			pline("You fall down the stairs.");	/* %% */
			losehp(rnd(3), "fall");
			if(Punished) {
			    if(uwep != uball && rn2(3)){
				pline("... and are hit by the iron ball.");
				losehp(rnd(20), "iron ball");
			    }
			    placebc(1);
			}
			selftouch("Falling, you");
		}
	    }
	    { struct monst *mtmp = m_at(u.ux, u.uy);
	      if(mtmp)
		mnexto(mtmp);
	    }
	} else {	/* trapdoor or level_tele */
	    do {
		u.ux = rnd(COLNO-1);
		u.uy = rn2(ROWNO);
	    } while(levl[(int)u.ux][(int)u.uy].typ != ROOM ||
			m_at(u.ux,u.uy));
	    if(Punished){
		if(uwep != uball && !up /* %% */ && rn2(5)){
			pline("The iron ball falls on your head.");
			losehp(rnd(25), "iron ball");
		}
		placebc(1);
	    }
	    selftouch("Falling, you");
	}
	(void) inshop();
	initrack();

	losedogs();
	{ struct monst *mtmp;
	  if ((mtmp = m_at(u.ux, u.uy)))
		  mnexto(mtmp);	/* riv05!a3 */
	}
	flags.nscrinh = 0;
	setsee();
	seeobjs();	/* make old cadavers disappear - riv05!a3 */
	docrt();
	pickup(1);
	read_engr_at(u.ux,u.uy);
}
示例#6
0
文件: music.c 项目: FredrIQ/fiqhack
/* 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
void do_trap(trap_t *trap) // was dotrap
{
  Short ttype = get_trap_type(trap->trap_info);

  nomul(0);
  if (get_trap_seen(trap->trap_info) && !rund(5) && ttype != PIT) {
    StrPrintF(ScratchBuffer, "You escape a%s.", traps[ttype]);
    message(ScratchBuffer);
  } else {
    trap->trap_info |= SEEN_TRAP;
    switch(ttype) {
    case SLP_GAS_TRAP:
      message("A cloud of gas puts you to sleep!");
      nomul(-rnd(25));
      break;
    case BEAR_TRAP:
      if (Levitation) {
	message("You float over a bear trap.");
	break;
      }
      you.utrap = 4 + rund(4);
      you.utraptype = TT_BEARTRAP;
      message("A bear trap closes on your foot!");
      break;
    case PIERC:
      deltrap(trap);
      if (makemon(PM_PIERCER, you.ux, you.uy)) {
	message("A piercer suddenly drops from the ceiling!");
	if (uarmh)
	  message("Its blow glances off your helmet.");
	else
	  thing_hit_you(3, dice(4,6), "falling piercer");
      }
      break;
    case ARROW_TRAP:
      message("An arrow shoots out at you!");
      if (!thing_hit_you(8, rnd(6), "arrow")){
	mksobj_at(ARROW, you.ux, you.uy);
	fobj->quantity = 1;
      }
      break;
    case TRAPDOOR:
      if (!xdnstair) {
	message("A trap door in the ceiling opens and a rock falls on your head!");
	if (uarmh) message("Fortunately, you are wearing a helmet!");
	losehp((uarmh ? 2 : dice(2,10)), "falling rock");
	mksobj_at(ROCK, you.ux, you.uy);
	fobj->quantity = 1;
	stackobj(fobj);
	if (Invisible) newsym(you.ux, you.uy);
      } else {
	Short newlevel = dlevel + 1;
	while (!rund(4) && newlevel < 29)
	  newlevel++;
	message("A trap door opens up under you!");
	if (Levitation || you.ustuck) {
	  message("For some reason you don't fall in.");
	  break;
	}

	goto_level(newlevel, false);
      }
      break;
    case DART_TRAP:
      message("A little dart shoots out at you!");
      if (thing_hit_you(7, rnd(3), "little dart")) {
	if (!rund(6))
	  poisoned("dart", "poison dart");
      } else {
	mksobj_at(DART, you.ux, you.uy);
	fobj->quantity = 1;
      }
      break;
    case TELEP_TRAP:
      map_mode_teleport = TELE_TRAP;
      if (get_trap_once(trap->trap_info)) {
	deltrap(trap);
	newsym(you.ux,you.uy);
	vtele();
      } else {
	newsym(you.ux,you.uy);
	tele();
      }
      break;
    case PIT:
      if (Levitation) {
	message("A pit opens up under you!");
	message("You don't fall in!");
	break;
      }
      message("You fall into a pit!");
      you.utrap = rund(6) + 2;
      you.utraptype = TT_PIT;
      losehp(rnd(6),"fall into a pit");
      selftouch("Falling, you");
      break;
    default:
      StrPrintF(ScratchBuffer, "BUG: You hit a trap with info=%u",
		trap->trap_info);
      message(ScratchBuffer);
    }
  }
}