Beispiel #1
0
/**
 * Drain stats at random
 *
 * \param num is the number of points to drain
 * \param sustain is whether sustains will prevent draining
 * \param perma is whether the drains are permanent
 */
static void drain_stats(int num, bool sustain, bool perma)
{
	int i, k = 0;
	const char *act = NULL;

	for (i = 0; i < num; i++) {
		switch (randint1(6)) {
			case 1: k = A_STR; act = "strong"; break;
			case 2: k = A_INT; act = "bright"; break;
			case 3: k = A_WIS; act = "wise"; break;
			case 4: k = A_DEX; act = "agile"; break;
			case 5: k = A_CON; act = "hale"; break;
			case 6: k = A_CHR; act = "beautiful"; break;
		}

		if (sustain)
			do_dec_stat(k, perma);
		else {
			msg("You're not as %s as you used to be...", act);
			player_stat_dec(p_ptr, k, perma);
		}
	}

	return;
}
Beispiel #2
0
bool fear_set_p(int v)
{
    int old_lvl, new_lvl;
    bool notice = FALSE;

    /* Hack -- Force good values */
    v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;

    if (p_ptr->is_dead) return FALSE;

    old_lvl = _get_level(p_ptr->afraid);
    new_lvl = _get_level(v);

    if (new_lvl > old_lvl)
    {
        msg_format("You feel <color:%c>%s</color>.", _get_level_color(new_lvl), _get_level_name(new_lvl));
        if (old_lvl <= FEAR_SCARED && one_in_(6) && !fear_save_p(v/5))
            do_dec_stat(A_CHR);
        if (p_ptr->special_defense & KATA_MASK)
        {
            msg_print("Your posture gets loose.");
            p_ptr->special_defense &= ~KATA_MASK;
            p_ptr->update |= PU_BONUS;
            p_ptr->update |= PU_MONSTERS;
            p_ptr->redraw |= PR_STATE;
            p_ptr->redraw |= PR_STATUS;
            p_ptr->action = ACTION_NONE;
        }
        notice = TRUE;
        p_ptr->counter = FALSE;
        virtue_add(VIRTUE_VALOUR, -1);
    }
    else if (new_lvl < old_lvl)
    {
        if (new_lvl == FEAR_BOLD)
            msg_print("Your fears finally subside.");
        else
        {
            msg_format("You are no longer %s, but you still feel %s.",
                        _get_level_name(old_lvl), _get_level_name(new_lvl));
        }
        notice = TRUE;
    }

    p_ptr->afraid = v;
    p_ptr->redraw |= PR_EFFECTS;
    if (!notice) return FALSE;
    if (disturb_state) disturb(0, 0);
    handle_stuff();
    return TRUE;
}
Beispiel #3
0
/*
 * Do an effect, given an object.
 * Boost is the extent to which skill surpasses difficulty, used as % boost. It
 * ranges from 0 to 138.
 */
bool effect_do(effect_type effect, bool *ident, bool aware, int dir, int beam,
	int boost)
{
	int py = p_ptr->py;
	int px = p_ptr->px;
	int dam, chance, dur;

	if (effect < 1 || effect > EF_MAX)
	{
		msg("Bad effect passed to do_effect().  Please report this bug.");
		return FALSE;
	}

	switch (effect)
	{
		case EF_POISON:
		{
			inc_timed(TMD_POISONED, damroll(2, 7) + 10, TRUE, TRUE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_BLIND:
		{
			inc_timed(TMD_BLIND, damroll(4, 25) + 75, TRUE, TRUE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_SCARE:
		{
			inc_timed(TMD_AFRAID, randint0(10) + 10, TRUE, TRUE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_CONFUSE:
		{
			inc_timed(TMD_CONFUSED, damroll(4, 5) + 10, TRUE, TRUE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_HALLUC:
		{
			inc_timed(TMD_IMAGE, randint0(250) + 250, TRUE, TRUE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_PARALYZE:
		{
			inc_timed(TMD_PARALYZED, randint0(5) + 5, TRUE, TRUE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_SLOW:
		{
			if (inc_timed(TMD_SLOW, randint1(25) + 15, TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_CURE_POISON:
		{
			if (clear_timed(TMD_POISONED, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_CURE_BLINDNESS:
		{
			if (clear_timed(TMD_BLIND, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_CURE_PARANOIA:
		{
			if (clear_timed(TMD_AFRAID, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_CURE_CONFUSION:
		{
			if (clear_timed(TMD_CONFUSED, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_CURE_MIND:
		{
			if (clear_timed(TMD_CONFUSED, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_AFRAID, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_IMAGE, TRUE)) *ident = TRUE;
			if (!of_has(p_ptr->state.flags, OF_RES_CONFU) &&
				inc_timed(TMD_OPP_CONF, damroll(4, 10), TRUE, TRUE))
			    	*ident = TRUE;
			return TRUE;
		}

		case EF_CURE_BODY:
		{
			if (clear_timed(TMD_STUN, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CUT, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_POISONED, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_BLIND, TRUE)) *ident = TRUE;
			return TRUE;
		}


		case EF_CURE_LIGHT:
		{
			if (hp_player(20)) *ident = TRUE;
			if (clear_timed(TMD_BLIND, TRUE)) *ident = TRUE;
			if (dec_timed(TMD_CUT, 20, TRUE)) *ident = TRUE;
			if (dec_timed(TMD_CONFUSED, 20, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_CURE_SERIOUS:
		{
			if (hp_player(40)) *ident = TRUE;
			if (clear_timed(TMD_CUT, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_BLIND, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CONFUSED, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_CURE_CRITICAL:
		{
			if (hp_player(60)) *ident = TRUE;
			if (clear_timed(TMD_BLIND, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CONFUSED, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_POISONED, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_STUN, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CUT, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_AMNESIA, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_CURE_FULL:
		{
			int amt = (p_ptr->mhp * 35) / 100;
			if (amt < 300) amt = 300;

			if (hp_player(amt)) *ident = TRUE;
			if (clear_timed(TMD_BLIND, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CONFUSED, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_POISONED, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_STUN, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CUT, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_AMNESIA, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_CURE_FULL2:
		{
			if (hp_player(1200)) *ident = TRUE;
			if (clear_timed(TMD_BLIND, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CONFUSED, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_POISONED, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_STUN, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CUT, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_AMNESIA, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_CURE_TEMP:
		{
			if (clear_timed(TMD_BLIND, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_POISONED, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CONFUSED, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_STUN, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CUT, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_HEAL1:
		{
			if (hp_player(500)) *ident = TRUE;
			if (clear_timed(TMD_CUT, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_HEAL2:
		{
			if (hp_player(1000)) *ident = TRUE;
			if (clear_timed(TMD_CUT, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_HEAL3:
		{
			if (hp_player(500)) *ident = TRUE;
			if (clear_timed(TMD_STUN, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CUT, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_GAIN_EXP:
		{
			if (p_ptr->exp < PY_MAX_EXP)
			{
				msg("You feel more experienced.");
				player_exp_gain(p_ptr, 100000L);
				*ident = TRUE;
			}
			return TRUE;
		}

		case EF_LOSE_EXP:
		{
			if (!check_state(OF_HOLD_LIFE, p_ptr->state.flags) && (p_ptr->exp > 0))
			{
				msg("You feel your memories fade.");
				player_exp_lose(p_ptr, p_ptr->exp / 4, FALSE);
				*ident = TRUE;
			}
			*ident = TRUE;
			wieldeds_notice_flag(OF_HOLD_LIFE);
			return TRUE;
		}

		case EF_RESTORE_EXP:
		{
			if (restore_level()) *ident = TRUE;
			return TRUE;
		}

		case EF_RESTORE_MANA:
		{
			if (p_ptr->csp < p_ptr->msp)
			{
				p_ptr->csp = p_ptr->msp;
				p_ptr->csp_frac = 0;
				msg("Your feel your head clear.");
				p_ptr->redraw |= (PR_MANA);
				*ident = TRUE;
			}
			return TRUE;
		}

		case EF_GAIN_STR:
		case EF_GAIN_INT:
		case EF_GAIN_WIS:
		case EF_GAIN_DEX:
		case EF_GAIN_CON:
		case EF_GAIN_CHR:
		{
			int stat = effect - EF_GAIN_STR;
			if (do_inc_stat(stat)) *ident = TRUE;
			return TRUE;
		}

		case EF_GAIN_ALL:
		{
			if (do_inc_stat(A_STR)) *ident = TRUE;
			if (do_inc_stat(A_INT)) *ident = TRUE;
			if (do_inc_stat(A_WIS)) *ident = TRUE;
			if (do_inc_stat(A_DEX)) *ident = TRUE;
			if (do_inc_stat(A_CON)) *ident = TRUE;
			if (do_inc_stat(A_CHR)) *ident = TRUE;
			return TRUE;
		}

		case EF_BRAWN:
		{
			/* Pick a random stat to decrease other than strength */
			int stat = randint0(A_MAX-1) + 1;

			if (do_dec_stat(stat, TRUE))
			{
				do_inc_stat(A_STR);
				*ident = TRUE;
			}

			return TRUE;
		}

		case EF_INTELLECT:
		{
			/* Pick a random stat to decrease other than intelligence */
			int stat = randint0(A_MAX-1);
			if (stat >= A_INT) stat++;

			if (do_dec_stat(stat, TRUE))
			{
				do_inc_stat(A_INT);
				*ident = TRUE;
			}

			return TRUE;
		}

		case EF_CONTEMPLATION:
		{
			/* Pick a random stat to decrease other than wisdom */
			int stat = randint0(A_MAX-1);
			if (stat >= A_WIS) stat++;

			if (do_dec_stat(stat, TRUE))
			{
				do_inc_stat(A_WIS);
				*ident = TRUE;
			}

			return TRUE;
		}

		case EF_TOUGHNESS:
		{
			/* Pick a random stat to decrease other than constitution */
			int stat = randint0(A_MAX-1);
			if (stat >= A_CON) stat++;

			if (do_dec_stat(stat, TRUE))
			{
				do_inc_stat(A_CON);
				*ident = TRUE;
			}

			return TRUE;
		}

		case EF_NIMBLENESS:
		{
			/* Pick a random stat to decrease other than dexterity */
			int stat = randint0(A_MAX-1);
			if (stat >= A_DEX) stat++;

			if (do_dec_stat(stat, TRUE))
			{
				do_inc_stat(A_DEX);
				*ident = TRUE;
			}

			return TRUE;
		}

		case EF_PLEASING:
		{
			/* Pick a random stat to decrease other than charisma */
			int stat = randint0(A_MAX-1);

			if (do_dec_stat(stat, TRUE))
			{
				do_inc_stat(A_CHR);
				*ident = TRUE;
			}

			return TRUE;
		}

		case EF_LOSE_STR:
		case EF_LOSE_INT:
		case EF_LOSE_WIS:
		case EF_LOSE_DEX:
		case EF_LOSE_CON:
		case EF_LOSE_CHR:
		{
			int stat = effect - EF_LOSE_STR;

			take_hit(damroll(5, 5), "stat drain");
			(void)do_dec_stat(stat, FALSE);
			*ident = TRUE;

			return TRUE;
		}

		case EF_LOSE_CON2:
		{
			take_hit(damroll(10, 10), "poisonous food");
			(void)do_dec_stat(A_CON, FALSE);
			*ident = TRUE;

			return TRUE;
		}

		case EF_RESTORE_STR:
		case EF_RESTORE_INT:
		case EF_RESTORE_WIS:
		case EF_RESTORE_DEX:
		case EF_RESTORE_CON:
		case EF_RESTORE_CHR:
		{
			int stat = effect - EF_RESTORE_STR;
			if (do_res_stat(stat)) *ident = TRUE;
			return TRUE;
		}

		case EF_CURE_NONORLYBIG:
		{
			msg("You feel life flow through your body!");
			restore_level();
			(void)clear_timed(TMD_POISONED, TRUE);
			(void)clear_timed(TMD_BLIND, TRUE);
			(void)clear_timed(TMD_CONFUSED, TRUE);
			(void)clear_timed(TMD_IMAGE, TRUE);
			(void)clear_timed(TMD_STUN, TRUE);
			(void)clear_timed(TMD_CUT, TRUE);
			(void)clear_timed(TMD_AMNESIA, TRUE);

			if (do_res_stat(A_STR)) *ident = TRUE;
			if (do_res_stat(A_INT)) *ident = TRUE;
			if (do_res_stat(A_WIS)) *ident = TRUE;
			if (do_res_stat(A_DEX)) *ident = TRUE;
			if (do_res_stat(A_CON)) *ident = TRUE;
			if (do_res_stat(A_CHR)) *ident = TRUE;

			/* Recalculate max. hitpoints */
			update_stuff();

			hp_player(5000);

			*ident = TRUE;
			return TRUE;
		}

		case EF_RESTORE_ALL:
		{
			/* Life, above, also gives these effects */
			if (do_res_stat(A_STR)) *ident = TRUE;
			if (do_res_stat(A_INT)) *ident = TRUE;
			if (do_res_stat(A_WIS)) *ident = TRUE;
			if (do_res_stat(A_DEX)) *ident = TRUE;
			if (do_res_stat(A_CON)) *ident = TRUE;
			if (do_res_stat(A_CHR)) *ident = TRUE;
			return TRUE;
		}

		case EF_RESTORE_ST_LEV:
		{
			if (restore_level()) *ident = TRUE;
			if (do_res_stat(A_STR)) *ident = TRUE;
			if (do_res_stat(A_INT)) *ident = TRUE;
			if (do_res_stat(A_WIS)) *ident = TRUE;
			if (do_res_stat(A_DEX)) *ident = TRUE;
			if (do_res_stat(A_CON)) *ident = TRUE;
			if (do_res_stat(A_CHR)) *ident = TRUE;
			return TRUE;
		}

		case EF_TMD_INFRA:
		{
			if (inc_timed(TMD_SINFRA, 100 + damroll(4, 25), TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_TMD_SINVIS:
		{
			if (clear_timed(TMD_BLIND, TRUE)) *ident = TRUE;
			if (inc_timed(TMD_SINVIS, 12 + damroll(2, 6), TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_TMD_ESP:
		{
			if (clear_timed(TMD_BLIND, TRUE)) *ident = TRUE;
			if (inc_timed(TMD_TELEPATHY, 12 + damroll(6, 6), TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}


		case EF_ENLIGHTENMENT:
		{
			msg("An image of your surroundings forms in your mind...");
			wiz_light();
			*ident = TRUE;
			return TRUE;
		}


		case EF_ENLIGHTENMENT2:
		{
			msg("You begin to feel more enlightened...");
			message_flush();
			wiz_light();
			(void)do_inc_stat(A_INT);
			(void)do_inc_stat(A_WIS);
			(void)detect_traps(TRUE);
			(void)detect_doorstairs(TRUE);
			(void)detect_treasure(TRUE);
			identify_pack();
			*ident = TRUE;
			return TRUE;
		}

		case EF_HERO:
		{
			dur = randint1(25) + 25;
			if (hp_player(10)) *ident = TRUE;
			if (clear_timed(TMD_AFRAID, TRUE)) *ident = TRUE;
			if (inc_timed(TMD_BOLD, dur, TRUE, TRUE)) *ident = TRUE;
			if (inc_timed(TMD_HERO, dur, TRUE, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_SHERO:
		{
			dur = randint1(25) + 25;
			if (hp_player(30)) *ident = TRUE;
			if (clear_timed(TMD_AFRAID, TRUE)) *ident = TRUE;
			if (inc_timed(TMD_BOLD, dur, TRUE, TRUE)) *ident = TRUE;
			if (inc_timed(TMD_SHERO, dur, TRUE, TRUE)) *ident = TRUE;
			return TRUE;
		}


		case EF_RESIST_ACID:
		{
			if (inc_timed(TMD_OPP_ACID, randint1(10) + 10, TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_RESIST_ELEC:
		{
			if (inc_timed(TMD_OPP_ELEC, randint1(10) + 10, TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_RESIST_FIRE:
		{
			if (inc_timed(TMD_OPP_FIRE, randint1(10) + 10, TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_RESIST_COLD:
		{
			if (inc_timed(TMD_OPP_COLD, randint1(10) + 10, TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_RESIST_POIS:
		{
			if (inc_timed(TMD_OPP_POIS, randint1(10) + 10, TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_RESIST_ALL:
		{
			if (inc_timed(TMD_OPP_ACID, randint1(20) + 20, TRUE, TRUE))
				*ident = TRUE;
			if (inc_timed(TMD_OPP_ELEC, randint1(20) + 20, TRUE, TRUE))
				*ident = TRUE;
			if (inc_timed(TMD_OPP_FIRE, randint1(20) + 20, TRUE, TRUE))
				*ident = TRUE;
			if (inc_timed(TMD_OPP_COLD, randint1(20) + 20, TRUE, TRUE))
				*ident = TRUE;
			if (inc_timed(TMD_OPP_POIS, randint1(20) + 20, TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_DETECT_TREASURE:
		{
			if (detect_treasure(aware)) *ident = TRUE;
			return TRUE;
		}

		case EF_DETECT_TRAP:
		{
			if (detect_traps(aware)) *ident = TRUE;
			return TRUE;
		}

		case EF_DETECT_DOORSTAIR:
		{
			if (detect_doorstairs(aware)) *ident = TRUE;
			return TRUE;
		}

		case EF_DETECT_INVIS:
		{
			if (detect_monsters_invis(aware)) *ident = TRUE;
			return TRUE;
		}

		case EF_DETECT_EVIL:
		{
			if (detect_monsters_evil(aware)) *ident = TRUE;
			return TRUE;
		}

		case EF_DETECT_ALL:
		{
			if (detect_all(aware)) *ident = TRUE;
			return TRUE;
		}

		case EF_ENCHANT_TOHIT:
		{
			*ident = TRUE;
			return enchant_spell(1, 0, 0);
		}

		case EF_ENCHANT_TODAM:
		{
			*ident = TRUE;
			return enchant_spell(0, 1, 0);
		}

		case EF_ENCHANT_WEAPON:
		{
			*ident = TRUE;
			return enchant_spell(randint1(3), randint1(3), 0);
		}

		case EF_ENCHANT_ARMOR:
		{
			*ident = TRUE;
			return enchant_spell(0, 0, 1);
		}

		case EF_ENCHANT_ARMOR2:
		{
			*ident = TRUE;
			return enchant_spell(0, 0, randint1(3) + 2);
		}

		case EF_RESTORE_ITEM:
		{
			*ident = TRUE;
			return restore_item();
		}

		case EF_IDENTIFY:
		{
			*ident = TRUE;
			if (!ident_spell()) return FALSE;
			return TRUE;
		}

		case EF_REMOVE_CURSE:
		{
			if (remove_curse())
			{
				if (!p_ptr->timed[TMD_BLIND])
					msg("The air around your body glows blue for a moment...");
				else
					msg("You feel as if someone is watching over you.");

				*ident = TRUE;
			}
			return TRUE;
		}

		case EF_REMOVE_CURSE2:
		{
			remove_all_curse();
			*ident = TRUE;
			return TRUE;
		}

		case EF_LIGHT:
		{
			if (light_area(damroll(2, 8), 2)) *ident = TRUE;
			return TRUE;
		}

		case EF_SUMMON_MON:
		{
			int i;
			sound(MSG_SUM_MONSTER);

			for (i = 0; i < randint1(3); i++)
			{
				if (summon_specific(py, px, p_ptr->depth, 0, 1))
					*ident = TRUE;
			}
			return TRUE;
		}

		case EF_SUMMON_UNDEAD:
		{
			int i;
			sound(MSG_SUM_UNDEAD);

			for (i = 0; i < randint1(3); i++)
			{
				if (summon_specific(py, px, p_ptr->depth,
					S_UNDEAD, 1))
					*ident = TRUE;
			}
			return TRUE;
		}

		case EF_TELE_PHASE:
		{
			teleport_player(10);
			*ident = TRUE;
			return TRUE;
		}

		case EF_TELE_LONG:
		{
			teleport_player(100);
			*ident = TRUE;
			return TRUE;
		}

		case EF_TELE_LEVEL:
		{
			(void)teleport_player_level();
			*ident = TRUE;
			return TRUE;
		}

		case EF_CONFUSING:
		{
			if (p_ptr->confusing == 0)
			{
				msg("Your hands begin to glow.");
				p_ptr->confusing = TRUE;
				*ident = TRUE;
			}
			return TRUE;
		}

		case EF_MAPPING:
		{
			map_area();
			*ident = TRUE;
			return TRUE;
		}

		case EF_RUNE:
		{
			warding_glyph();
			*ident = TRUE;
			return TRUE;
		}

		case EF_ACQUIRE:
		{
			acquirement(py, px, p_ptr->depth, 1, TRUE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_ACQUIRE2:
		{
			acquirement(py, px, p_ptr->depth, randint1(2) + 1,
				TRUE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_ANNOY_MON:
		{
			msg("There is a high pitched humming noise.");
			aggravate_monsters(0);
			*ident = TRUE;
			return TRUE;
		}

		case EF_CREATE_TRAP:
		{
			/* Hack -- no traps in the town */
			if (p_ptr->depth == 0)
				return TRUE;

			trap_creation();
			msg("You hear a low-pitched whistling sound.");
			*ident = TRUE;
			return TRUE;
		}

		case EF_DESTROY_TDOORS:
		{
			if (destroy_doors_touch()) *ident = TRUE;
			return TRUE;
		}

		case EF_RECHARGE:
		{
			*ident = TRUE;
			if (!recharge(60)) return FALSE;
			return TRUE;
		}

		case EF_BANISHMENT:
		{
			*ident = TRUE;
			if (!banishment()) return FALSE;
			return TRUE;
		}

		case EF_DARKNESS:
		{
			if (!check_state(OF_RES_DARK, p_ptr->state.flags))
				(void)inc_timed(TMD_BLIND, 3 + randint1(5), TRUE, TRUE);
			unlight_area(10, 3);
			wieldeds_notice_flag(OF_RES_DARK);
			*ident = TRUE;
			return TRUE;
		}

		case EF_PROTEVIL:
		{
			if (inc_timed(TMD_PROTEVIL, randint1(25) + 3 *
				p_ptr->lev, TRUE, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_SATISFY:
		{
			if (set_food(PY_FOOD_MAX - 1)) *ident = TRUE;
			return TRUE;
		}

		case EF_CURSE_WEAPON:
		{
			if (curse_weapon()) *ident = TRUE;
			return TRUE;
		}

		case EF_CURSE_ARMOR:
		{
			if (curse_armor()) *ident = TRUE;
			return TRUE;
		}

		case EF_BLESSING:
		{
			if (inc_timed(TMD_BLESSED, randint1(12) + 6, TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_BLESSING2:
		{
			if (inc_timed(TMD_BLESSED, randint1(24) + 12, TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_BLESSING3:
		{
			if (inc_timed(TMD_BLESSED, randint1(48) + 24, TRUE, TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_RECALL:
		{
			set_recall();
			*ident = TRUE;
			return TRUE;
		}

		case EF_DEEP_DESCENT:
		{
			int i, target_depth = p_ptr->depth;
			
			/* Calculate target depth */
			for (i = 2; i > 0; i--) {
				if (is_quest(target_depth)) break;
				if (target_depth >= MAX_DEPTH - 1) break;
				
				target_depth++;
			}

			if (target_depth > p_ptr->depth) {
				msgt(MSG_TPLEVEL, "You sink through the floor...");
				dungeon_change_level(target_depth);
				*ident = TRUE;
				return TRUE;
			} else {
				msgt(MSG_TPLEVEL, "You sense a malevolent presence blocking passage to the levels below.");
				*ident = TRUE;
				return FALSE;
			}
		}

		case EF_LOSHASTE:
		{
			if (speed_monsters()) *ident = TRUE;
			return TRUE;
		}

		case EF_LOSSLEEP:
		{
			if (sleep_monsters(aware)) *ident = TRUE;
			return TRUE;
		}

		case EF_LOSSLOW:
		{
			if (slow_monsters()) *ident = TRUE;
			return TRUE;
		}

		case EF_LOSCONF:
		{
			if (confuse_monsters(aware)) *ident = TRUE;
			return TRUE;
		}

		case EF_LOSKILL:
		{
			(void)mass_banishment();
			*ident = TRUE;
			return TRUE;
		}

		case EF_EARTHQUAKES:
		{
			earthquake(py, px, 10);
			*ident = TRUE;
			return TRUE;
		}

		case EF_DESTRUCTION2:
		{
			destroy_area(py, px, 15, TRUE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_ILLUMINATION:
		{
			if (light_area(damroll(2, 15), 3)) *ident = TRUE;
			return TRUE;
		}

		case EF_CLAIRVOYANCE:
		{
			*ident = TRUE;
			wiz_light();
			(void)detect_traps(TRUE);
			(void)detect_doorstairs(TRUE);
			return TRUE;
		}

		case EF_PROBING:
		{
			*ident = probing();
			return TRUE;
		}

		case EF_STONE_TO_MUD:
		{
			if (wall_to_mud(dir)) *ident = TRUE;
			return TRUE;
		}

		case EF_CONFUSE2:
		{
			*ident = TRUE;
			confuse_monster(dir, 20, aware);
			return TRUE;
		}

		case EF_BIZARRE:
		{
			*ident = TRUE;
			ring_of_power(dir);
			return TRUE;
		}

		case EF_STAR_BALL:
		{
			int i;
			*ident = TRUE;
			for (i = 0; i < 8; i++) fire_ball(GF_ELEC, ddd[i],
				(150 * (100 + boost) / 100), 3);
			return TRUE;
		}

		case EF_RAGE_BLESS_RESIST:
		{
			dur = randint1(50) + 50;
			*ident = TRUE;
			(void)hp_player(30);
			(void)clear_timed(TMD_AFRAID, TRUE);
			(void)inc_timed(TMD_BOLD, dur, TRUE, TRUE);
			(void)inc_timed(TMD_SHERO, dur, TRUE, TRUE);
			(void)inc_timed(TMD_BLESSED, randint1(50) + 50, TRUE, TRUE);
			(void)inc_timed(TMD_OPP_ACID, randint1(50) + 50, TRUE, TRUE);
			(void)inc_timed(TMD_OPP_ELEC, randint1(50) + 50, TRUE, TRUE);
			(void)inc_timed(TMD_OPP_FIRE, randint1(50) + 50, TRUE, TRUE);
			(void)inc_timed(TMD_OPP_COLD, randint1(50) + 50, TRUE, TRUE);
			(void)inc_timed(TMD_OPP_POIS, randint1(50) + 50, TRUE, TRUE);
			return TRUE;
		}

		case EF_SLEEPII:
		{
			*ident = TRUE;
			sleep_monsters_touch(aware);
			return TRUE;
		}

		case EF_RESTORE_LIFE:
		{
			*ident = TRUE;
			restore_level();
			return TRUE;
		}

		case EF_MISSILE:
		{
			*ident = TRUE;
			dam = damroll(3, 4) * (100 + boost) / 100;
			fire_bolt_or_beam(beam, GF_MISSILE, dir, dam);
			return TRUE;
		}

		case EF_DISPEL_EVIL:
		{
			*ident = TRUE;
			dam = p_ptr->lev * 5 * (100 + boost) / 100;
			dispel_evil(dam);
			return TRUE;
		}

		case EF_DISPEL_EVIL60:
		{
			dam = 60 * (100 + boost) / 100;
			if (dispel_evil(dam)) *ident = TRUE;
			return TRUE;
		}

		case EF_DISPEL_UNDEAD:
		{
			dam = 60 * (100 + boost) / 100;
			if (dispel_undead(dam)) *ident = TRUE;
			return TRUE;
		}

		case EF_DISPEL_ALL:
		{
			dam = 120 * (100 + boost) / 100;
			if (dispel_monsters(dam)) *ident = TRUE;
			return TRUE;
		}

		case EF_HASTE:
		{
			if (!p_ptr->timed[TMD_FAST])
			{
				if (set_timed(TMD_FAST, damroll(2, 10) + 20, TRUE)) *ident = TRUE;
			}
			else
			{
				(void)inc_timed(TMD_FAST, 5, TRUE, TRUE);
			}

			return TRUE;
		}

		case EF_HASTE1:
		{
			if (!p_ptr->timed[TMD_FAST])
			{
				if (set_timed(TMD_FAST, randint1(20) + 20, TRUE)) *ident = TRUE;
			}
			else
			{
				(void)inc_timed(TMD_FAST, 5, TRUE, TRUE);
			}

			return TRUE;
		}

		case EF_HASTE2:
		{
			if (!p_ptr->timed[TMD_FAST])
			{
				if (set_timed(TMD_FAST, randint1(75) + 75, TRUE)) *ident = TRUE;
			}
			else
			{
				(void)inc_timed(TMD_FAST, 5, TRUE, TRUE);
			}

			return TRUE;
		}


		case EF_FIRE_BOLT:
		{
			*ident = TRUE;
			dam = damroll(9, 8) * (100 + boost) / 100;
			fire_bolt(GF_FIRE, dir, dam);
			return TRUE;
		}

		case EF_FIRE_BOLT2:
		{
			dam = damroll(12, 8) * (100 + boost) / 100;
			fire_bolt_or_beam(beam, GF_FIRE, dir, dam);
			*ident = TRUE;
			return TRUE;
		}

		case EF_FIRE_BOLT3:
		{
			dam = damroll(16, 8) * (100 + boost) / 100;
			fire_bolt_or_beam(beam, GF_FIRE, dir, dam);
			*ident = TRUE;
			return TRUE;
		}

		case EF_FIRE_BOLT72:
		{
			dam = 72 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_FIRE, dir, dam, 2);
			return TRUE;
		}

		case EF_FIRE_BALL:
		{
			dam = 144 * (100 + boost) / 100;
			fire_ball(GF_FIRE, dir, dam, 2);
			*ident = TRUE;
			return TRUE;
		}

		case EF_FIRE_BALL2:
		{
			dam = 120 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_FIRE, dir, dam, 3);
			return TRUE;
		}

		case EF_FIRE_BALL200:
		{
			dam = 200 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_FIRE, dir, dam, 3);
			return TRUE;
		}

		case EF_COLD_BOLT:
		{
			dam = damroll(6, 8) * (100 + boost) / 100;
			*ident = TRUE;
			fire_bolt_or_beam(beam, GF_COLD, dir, dam);
			return TRUE;
		}

		case EF_COLD_BOLT2:
		{
			dam = damroll(12, 8) * (100 + boost) / 100;
			*ident = TRUE;
			fire_bolt(GF_COLD, dir, dam);
			return TRUE;
		}

		case EF_COLD_BALL2:
		{
			dam = 200 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_COLD, dir, dam, 3);
			return TRUE;
		}

		case EF_COLD_BALL50:
		{
			dam = 50 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_COLD, dir, dam, 2);
			return TRUE;
		}

		case EF_COLD_BALL100:
		{
			dam = 100 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_COLD, dir, dam, 2);
			return TRUE;
		}

		case EF_COLD_BALL160:
		{
			dam = 160 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_COLD, dir, dam, 3);
			return TRUE;
		}

		case EF_ACID_BOLT:
		{
			dam = damroll(5, 8) * (100 + boost) / 100;
			*ident = TRUE;
			fire_bolt(GF_ACID, dir, dam);
			return TRUE;
		}

		case EF_ACID_BOLT2:
		{
			dam = damroll(10, 8) * (100 + boost) / 100;
			fire_bolt_or_beam(beam, GF_ACID, dir, dam);
			*ident = TRUE;
			return TRUE;
		}

		case EF_ACID_BOLT3:
		{
			dam = damroll(12, 8) * (100 + boost) / 100;
			fire_bolt_or_beam(beam, GF_ACID, dir, dam);
			*ident = TRUE;
			return TRUE;
		}

		case EF_ACID_BALL:
		{
			dam = 120 * (100 + boost) / 100;
			fire_ball(GF_ACID, dir, dam, 2);
			*ident = TRUE;
			return TRUE;
		}

		case EF_ELEC_BOLT:
		{
			dam = damroll(6, 6) * (100 + boost) / 100;
			*ident = TRUE;
			fire_beam(GF_ELEC, dir, dam);
			return TRUE;
		}

		case EF_ELEC_BALL:
		{
			dam = 64 * (100 + boost) / 100;
			fire_ball(GF_ELEC, dir, dam, 2);
			*ident = TRUE;
			return TRUE;
		}

		case EF_ELEC_BALL2:
		{
			dam = 250 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_ELEC, dir, dam, 3);
			return TRUE;
		}


		case EF_ARROW:
		{
			dam = 150 * (100 + boost) / 100;
			*ident = TRUE;
			fire_bolt(GF_ARROW, dir, dam);
			return TRUE;
		}

		case EF_REM_FEAR_POIS:
		{
			*ident = TRUE;
			(void)clear_timed(TMD_AFRAID, TRUE);
			(void)clear_timed(TMD_POISONED, TRUE);
			return TRUE;
		}

		case EF_STINKING_CLOUD:
		{
			dam = 12 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_POIS, dir, dam, 3);
			return TRUE;
		}


		case EF_DRAIN_LIFE1:
		{
			dam = 90 * (100 + boost) / 100;
			if (drain_life(dir, dam)) *ident = TRUE;
			return TRUE;
		}

		case EF_DRAIN_LIFE2:
		{
			dam = 120 * (100 + boost) / 100;
			if (drain_life(dir, dam)) *ident = TRUE;
			return TRUE;
		}

		case EF_DRAIN_LIFE3:
		{
			dam = 150 * (100 + boost) / 100;
			if (drain_life(dir, dam)) *ident = TRUE;
			return TRUE;
		}

		case EF_DRAIN_LIFE4:
		{
			dam = 250 * (100 + boost) / 100;
			if (drain_life(dir, dam)) *ident = TRUE;
			return TRUE;
		}

		case EF_FIREBRAND:
		{
			*ident = TRUE;
			if (!brand_bolts()) return FALSE;
			return TRUE;
		}

		case EF_MANA_BOLT:
		{
			dam = damroll(12, 8) * (100 + boost) / 100;
			fire_bolt(GF_MANA, dir, dam);
			*ident = TRUE;
			return TRUE;
		}

		case EF_MON_HEAL:
		{
			if (heal_monster(dir)) *ident = TRUE;
			return TRUE;
		}

		case EF_MON_HASTE:
		{
			if (speed_monster(dir)) *ident = TRUE;
			return TRUE;
		}

		case EF_MON_SLOW:
		{
			if (slow_monster(dir)) *ident = TRUE;
			return TRUE;
		}

		case EF_MON_CONFUSE:
		{
			if (confuse_monster(dir, 10, aware)) *ident = TRUE;
			return TRUE;
		}

		case EF_MON_SLEEP:
		{
			if (sleep_monster(dir, aware)) *ident = TRUE;
			return TRUE;
		}

		case EF_MON_CLONE:
		{
			if (clone_monster(dir)) *ident = TRUE;
			return TRUE;
		}

		case EF_MON_SCARE:
		{
			if (fear_monster(dir, 10, aware)) *ident = TRUE;
			return TRUE;
		}

		case EF_LIGHT_LINE:
		{
			msg("A line of shimmering blue light appears.");
			light_line(dir);
			*ident = TRUE;
			return TRUE;
		}

		case EF_TELE_OTHER:
		{
			if (teleport_monster(dir)) *ident = TRUE;
			return TRUE;
		}

		case EF_DISARMING:
		{
			if (disarm_trap(dir)) *ident = TRUE;
			return TRUE;
		}

		case EF_TDOOR_DEST:
		{
			if (destroy_door(dir)) *ident = TRUE;
			return TRUE;
		}

		case EF_POLYMORPH:
		{
			if (poly_monster(dir)) *ident = TRUE;
			return TRUE;
		}

		case EF_STARLIGHT:
		{
			int i;
			if (!p_ptr->timed[TMD_BLIND])
				msg("Light shoots in all directions!");
			for (i = 0; i < 8; i++) light_line(ddd[i]);
			*ident = TRUE;
			return TRUE;
		}

		case EF_STARLIGHT2:
		{
			int k;
			for (k = 0; k < 8; k++) strong_light_line(ddd[k]);
			*ident = TRUE;
			return TRUE;
		}

		case EF_BERSERKER:
		{
			dur = randint1(50) + 50;
			if (inc_timed(TMD_BOLD, dur, TRUE, TRUE)) *ident = TRUE;
			if (inc_timed(TMD_SHERO, dur, TRUE, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_WONDER:
		{
			if (effect_wonder(dir, randint1(100) + p_ptr->lev / 5,
				beam)) *ident = TRUE;
			return TRUE;
		}

		case EF_WAND_BREATH:
		{
			/* table of random ball effects and their damages */
			const int breath_types[] = {
				GF_ACID, 200,
				GF_ELEC, 160,
				GF_FIRE, 200,
				GF_COLD, 160,
				GF_POIS, 120
			};
			/* pick a random (type, damage) tuple in the table */
			int which = 2 * randint0(sizeof(breath_types) / (2 * sizeof(int)));
			fire_ball(breath_types[which], dir, breath_types[which + 1], 3);
			*ident = TRUE;
			return TRUE;
		}

		case EF_STAFF_MAGI:
		{
			if (do_res_stat(A_INT)) *ident = TRUE;
			if (p_ptr->csp < p_ptr->msp)
			{
				p_ptr->csp = p_ptr->msp;
				p_ptr->csp_frac = 0;
				*ident = TRUE;
				msg("Your feel your head clear.");
				p_ptr->redraw |= (PR_MANA);
			}
			return TRUE;
		}

		case EF_STAFF_HOLY:
		{
			dam = 120 * (100 + boost) / 100;
			if (dispel_evil(dam)) *ident = TRUE;
			if (inc_timed(TMD_PROTEVIL, randint1(25) + 3 *
				p_ptr->lev, TRUE, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_POISONED, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_AFRAID, TRUE)) *ident = TRUE;
			if (hp_player(50)) *ident = TRUE;
			if (clear_timed(TMD_STUN, TRUE)) *ident = TRUE;
			if (clear_timed(TMD_CUT, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_DRINK_BREATH:
		{
			const int breath_types[] =
			{
				GF_FIRE, 80,
				GF_COLD, 80,
			};

			int which = 2 * randint0(N_ELEMENTS(breath_types) / 2);
			fire_ball(breath_types[which], dir, breath_types[which + 1], 2);
			*ident = TRUE;
			return TRUE;
		}

		case EF_DRINK_GOOD:
		{
			msg("You feel less thirsty.");
			*ident = TRUE;
			return TRUE;
		}

		case EF_DRINK_DEATH:
		{
			msg("A feeling of Death flows through your body.");
			take_hit(5000, "a potion of Death");
			*ident = TRUE;
			return TRUE;
		}

		case EF_DRINK_RUIN:
		{
			msg("Your nerves and muscles feel weak and lifeless!");
			take_hit(damroll(10, 10), "a potion of Ruination");
			player_stat_dec(p_ptr, A_DEX, TRUE);
			player_stat_dec(p_ptr, A_WIS, TRUE);
			player_stat_dec(p_ptr, A_CON, TRUE);
			player_stat_dec(p_ptr, A_STR, TRUE);
			player_stat_dec(p_ptr, A_CHR, TRUE);
			player_stat_dec(p_ptr, A_INT, TRUE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_DRINK_DETONATE:
		{
			msg("Massive explosions rupture your body!");
			take_hit(damroll(50, 20), "a potion of Detonation");
			(void)inc_timed(TMD_STUN, 75, TRUE, TRUE);
			(void)inc_timed(TMD_CUT, 5000, TRUE, TRUE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_DRINK_SALT:
		{
			msg("The potion makes you vomit!");
			(void)set_food(PY_FOOD_STARVE - 1);
			(void)clear_timed(TMD_POISONED, TRUE);
			(void)inc_timed(TMD_PARALYZED, 4, TRUE, FALSE);
			*ident = TRUE;
			return TRUE;
		}

		case EF_FOOD_GOOD:
		{
			msg("That tastes good.");
			*ident = TRUE;
			return TRUE;
		}

		case EF_FOOD_WAYBREAD:
		{
			msg("That tastes good.");
			(void)clear_timed(TMD_POISONED, TRUE);
			(void)hp_player(damroll(4, 8));
			*ident = TRUE;
			return TRUE;
		}

		case EF_SHROOM_EMERGENCY:
		{
			(void)set_timed(TMD_IMAGE, rand_spread(250, 50), TRUE);
			(void)set_timed(TMD_OPP_FIRE, rand_spread(30, 10), TRUE);
			(void)set_timed(TMD_OPP_COLD, rand_spread(30, 10), TRUE);
			(void)hp_player(200);
			*ident = TRUE;
			return TRUE;
		}

		case EF_SHROOM_TERROR:
		{
			if (set_timed(TMD_TERROR, rand_spread(100, 20), TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_SHROOM_STONE:
		{
			if (set_timed(TMD_STONESKIN, rand_spread(80, 20), TRUE))
				*ident = TRUE;
			return TRUE;
		}

		case EF_SHROOM_DEBILITY:
		{
			int stat = one_in_(2) ? A_STR : A_CON;

			if (p_ptr->csp < p_ptr->msp)
			{
				p_ptr->csp = p_ptr->msp;
				p_ptr->csp_frac = 0;
				msg("Your feel your head clear.");
				p_ptr->redraw |= (PR_MANA);
				*ident = TRUE;
			}

			(void)do_dec_stat(stat, FALSE);

			*ident = TRUE;
			return TRUE;
		}

		case EF_SHROOM_SPRINTING:
		{
			if (inc_timed(TMD_SPRINT, 100, TRUE, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_SHROOM_PURGING:
		{
			(void)set_food(PY_FOOD_FAINT - 1);
			if (do_res_stat(A_STR)) *ident = TRUE;
			if (do_res_stat(A_CON)) *ident = TRUE;
			if (clear_timed(TMD_POISONED, TRUE)) *ident = TRUE;
			return TRUE;
		}

		case EF_RING_ACID:
		{
			dam = 70 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_ACID, dir, dam, 2);
			inc_timed(TMD_OPP_ACID, randint1(20) + 20, TRUE, TRUE);
			return TRUE;
		}

		case EF_RING_FLAMES:
		{
			dam = 80 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_FIRE, dir, dam, 2);
			inc_timed(TMD_OPP_FIRE, randint1(20) + 20, TRUE, TRUE);
			return TRUE;
		}

		case EF_RING_ICE:
		{
			dam = 75 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_COLD, dir, dam, 2);
			inc_timed(TMD_OPP_COLD, randint1(20) + 20, TRUE, TRUE);
			return TRUE;
		}

		case EF_RING_LIGHTNING:
		{
			dam = 85 * (100 + boost) / 100;
			*ident = TRUE;
			fire_ball(GF_ELEC, dir, dam, 2);
			inc_timed(TMD_OPP_ELEC, randint1(20) + 20, TRUE, TRUE);
			return TRUE;
		}

		case EF_DRAGON_BLUE:
		{
			dam = 100 * (100 + boost) / 100;
			msgt(MSG_BR_ELEC, "You breathe lightning.");
			fire_ball(GF_ELEC, dir, dam, 2);
			return TRUE;
		}

		case EF_DRAGON_GREEN:
		{
			dam = 150 * (100 + boost) / 100;
			msgt(MSG_BR_GAS, "You breathe poison gas.");
			fire_ball(GF_POIS, dir, dam, 2);
			return TRUE;
		}

		case EF_DRAGON_RED:
		{
			dam = 200 * (100 + boost) / 100;
			msgt(MSG_BR_FIRE, "You breathe fire.");
			fire_ball(GF_FIRE, dir, dam, 2);
			return TRUE;
		}

		case EF_DRAGON_MULTIHUED:
		{
			static const struct
			{
				int msg_sound;
				const char *msg;
				int typ;
			} mh[] =
			{
				{ MSG_BR_ELEC,  "lightning",  GF_ELEC },
				{ MSG_BR_FROST, "frost",      GF_COLD },
				{ MSG_BR_ACID,  "acid",       GF_ACID },
				{ MSG_BR_GAS,   "poison gas", GF_POIS },
				{ MSG_BR_FIRE,  "fire",       GF_FIRE }
			};

			int chance = randint0(5);
			dam = 250 * (100 + boost) / 100;
			msgt(mh[chance].msg_sound, "You breathe %s.", mh[chance].msg);
			fire_ball(mh[chance].typ, dir, dam, 2);
			return TRUE;
		}

		case EF_DRAGON_BRONZE:
		{
			dam = 120 * (100 + boost) / 100;
			msgt(MSG_BR_CONF, "You breathe confusion.");
			fire_ball(GF_CONFU, dir, dam, 2);
			return TRUE;
		}

		case EF_DRAGON_GOLD:
		{
			dam = 130 * (100 + boost) / 100;
			msgt(MSG_BR_SOUND, "You breathe sound.");
			fire_ball(GF_SOUND, dir, dam, 2);
			return TRUE;
		}

		case EF_DRAGON_CHAOS:
		{
			dam = 220 * (100 + boost) / 100;
			chance = randint0(2);
			msgt((chance == 1 ? MSG_BR_CHAOS : MSG_BR_DISEN),
					"You breathe %s.",
					((chance == 1 ? "chaos" : "disenchantment")));
			fire_ball((chance == 1 ? GF_CHAOS : GF_DISEN),
			          dir, dam, 2);
			return TRUE;
		}

		case EF_DRAGON_LAW:
		{
			dam = 230 * (100 + boost) / 100;
			chance = randint0(2);
			msgt((chance == 1 ? MSG_BR_SOUND : MSG_BR_SHARDS), "You breathe %s.",
			           ((chance == 1 ? "sound" : "shards")));
			fire_ball((chance == 1 ? GF_SOUND : GF_SHARD),
			          dir, dam, 2);
			return TRUE;
		}

		case EF_DRAGON_BALANCE:
		{
			dam = 250 * (100 + boost) / 100;
			chance = randint0(4);
			msg("You breathe %s.",
			           ((chance == 1) ? "chaos" :
			            ((chance == 2) ? "disenchantment" :
			             ((chance == 3) ? "sound" : "shards"))));
			fire_ball(((chance == 1) ? GF_CHAOS :
			           ((chance == 2) ? GF_DISEN :
			            ((chance == 3) ? GF_SOUND : GF_SHARD))),
			          dir, dam, 2);
			return TRUE;
		}

		case EF_DRAGON_SHINING:
		{
			dam = 200 * (100 + boost) / 100;
			chance = randint0(2);
			msgt((chance == 0 ? MSG_BR_LIGHT : MSG_BR_DARK), "You breathe %s.",
			        ((chance == 0 ? "light" : "darkness")));
			fire_ball((chance == 0 ? GF_LIGHT : GF_DARK), dir, dam,
				2);
			return TRUE;
		}

		case EF_DRAGON_POWER:
		{
			dam = 300 * (100 + boost) / 100;
			msgt(MSG_BR_ELEMENTS, "You breathe the elements.");
			fire_ball(GF_MISSILE, dir, dam, 2);
			return TRUE;
		}

		case EF_TRAP_DOOR:
		{
			msg("You fall through a trap door!");
			if (check_state(OF_FEATHER, p_ptr->state.flags)) {
				msg("You float gently down to the next level.");
			} else {
				take_hit(damroll(2, 8), "a trap");
			}
			wieldeds_notice_flag(OF_FEATHER);

			dungeon_change_level(p_ptr->depth + 1);
			return TRUE;
		}

		case EF_TRAP_PIT:
		{
			msg("You fall into a pit!");
			if (check_state(OF_FEATHER, p_ptr->state.flags)) {
				msg("You float gently to the bottom of the pit.");
			} else {
				take_hit(damroll(2, 6), "a trap");
			}
			wieldeds_notice_flag(OF_FEATHER);
			return TRUE;
		}

		case EF_TRAP_PIT_SPIKES:
		{
			msg("You fall into a spiked pit!");

			if (check_state(OF_FEATHER, p_ptr->state.flags)) {
				msg("You float gently to the floor of the pit.");
				msg("You carefully avoid touching the spikes.");
			} else {
				int dam = damroll(2, 6);

				/* Extra spike damage */
				if (one_in_(2)) {
					msg("You are impaled!");
					dam *= 2;
					(void)inc_timed(TMD_CUT, randint1(dam), TRUE, TRUE);
				}

				take_hit(dam, "a trap");
			}
			wieldeds_notice_flag(OF_FEATHER);
			return TRUE;
		}

		case EF_TRAP_PIT_POISON:
		{
			msg("You fall into a spiked pit!");

			if (check_state(OF_FEATHER, p_ptr->state.flags)) {
				msg("You float gently to the floor of the pit.");
				msg("You carefully avoid touching the spikes.");
			} else {
				int dam = damroll(2, 6);

				/* Extra spike damage */
				if (one_in_(2)) {
					msg("You are impaled on poisonous spikes!");
					(void)inc_timed(TMD_CUT, randint1(dam * 2), TRUE, TRUE);
					(void)inc_timed(TMD_POISONED, randint1(dam * 4), TRUE, TRUE);
				}

				take_hit(dam, "a trap");
			}
			wieldeds_notice_flag(OF_FEATHER);
			return TRUE;
		}

		case EF_TRAP_RUNE_SUMMON:
		{
			int i;
			int num = 2 + randint1(3);

			msgt(MSG_SUM_MONSTER, "You are enveloped in a cloud of smoke!");

			/* Remove trap */
			cave->info[py][px] &= ~(CAVE_MARK);
			cave_set_feat(cave, py, px, FEAT_FLOOR);

			for (i = 0; i < num; i++)
				(void)summon_specific(py, px, p_ptr->depth, 0, 1);

			break;
		}

		case EF_TRAP_RUNE_TELEPORT:
		{
			msg("You hit a teleport trap!");
			teleport_player(100);
			return TRUE;		
		}

		case EF_TRAP_SPOT_FIRE:
		{
			int dam;

			msg("You are enveloped in flames!");
			dam = damroll(4, 6);
			dam = adjust_dam(GF_FIRE, dam, RANDOMISE,
					check_for_resist(GF_FIRE, p_ptr->state.flags, TRUE));
			if (dam) {
				take_hit(dam, "a fire trap");
				inven_damage(GF_FIRE, MIN(dam * 5, 300));
			}
			return TRUE;
		}

		case EF_TRAP_SPOT_ACID:
		{
			int dam;

			msg("You are splashed with acid!");
			dam = damroll(4, 6);
			dam = adjust_dam(GF_ACID, dam, RANDOMISE,
					check_for_resist(GF_ACID, p_ptr->state.flags, TRUE));
			if (dam) {
				take_hit(dam, "an acid trap");
				inven_damage(GF_ACID, MIN(dam * 5, 300));
			}
			return TRUE;
		}

		case EF_TRAP_DART_SLOW:
		{
			if (trap_check_hit(125)) {
				msg("A small dart hits you!");
				take_hit(damroll(1, 4), "a trap");
				(void)inc_timed(TMD_SLOW, randint0(20) + 20, TRUE, FALSE);
			} else {
				msg("A small dart barely misses you.");
			}
			return TRUE;
		}

		case EF_TRAP_DART_LOSE_STR:
		{
			if (trap_check_hit(125)) {
				msg("A small dart hits you!");
				take_hit(damroll(1, 4), "a trap");
				(void)do_dec_stat(A_STR, FALSE);
			} else {
				msg("A small dart barely misses you.");
			}
			return TRUE;
		}

		case EF_TRAP_DART_LOSE_DEX:
		{
			if (trap_check_hit(125)) {
				msg("A small dart hits you!");
				take_hit(damroll(1, 4), "a trap");
				(void)do_dec_stat(A_DEX, FALSE);
			} else {
				msg("A small dart barely misses you.");
			}
			return TRUE;
		}

		case EF_TRAP_DART_LOSE_CON:
		{
			if (trap_check_hit(125)) {
				msg("A small dart hits you!");
				take_hit(damroll(1, 4), "a trap");
				(void)do_dec_stat(A_CON, FALSE);
			} else {
				msg("A small dart barely misses you.");
			}
			return TRUE;
		}

		case EF_TRAP_GAS_BLIND:
		{
			msg("You are surrounded by a black gas!");
			(void)inc_timed(TMD_BLIND, randint0(50) + 25, TRUE, TRUE);
			return TRUE;
		}

		case EF_TRAP_GAS_CONFUSE:
		{
			msg("You are surrounded by a gas of scintillating colors!");
			(void)inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE, TRUE);
			return TRUE;
		}

		case EF_TRAP_GAS_POISON:
		{
			msg("You are surrounded by a pungent green gas!");
			(void)inc_timed(TMD_POISONED, randint0(20) + 10, TRUE, TRUE);
			return TRUE;
		}

		case EF_TRAP_GAS_SLEEP:
		{
			msg("You are surrounded by a strange white mist!");
			(void)inc_timed(TMD_PARALYZED, randint0(10) + 5, TRUE, TRUE);
			return TRUE;
		}


		case EF_XXX:
		case EF_MAX:
			break;
	}

	/* Not used */
	msg("Effect not handled.");
	return FALSE;
}
Beispiel #4
0
/*
 * Chests have traps too.
 *
 * Exploding chest destroys contents (and traps).
 * Note that the chest itself is never destroyed.
 */
static void chest_trap(int y, int x, s16b o_idx)
{
	int i, trap;

	object_type *o_ptr = object_byid(o_idx);


	/* Ignore disarmed chests */
	if (o_ptr->pval[DEFAULT_PVAL] <= 0) return;

	/* Obtain the traps */
	trap = chest_traps[o_ptr->pval[DEFAULT_PVAL]];

	/* Lose strength */
	if (trap & (CHEST_LOSE_STR))
	{
		msg("A small needle has pricked you!");
		take_hit(p_ptr, damroll(1, 4), "a poison needle");
		(void)do_dec_stat(A_STR, FALSE);
	}

	/* Lose constitution */
	if (trap & (CHEST_LOSE_CON))
	{
		msg("A small needle has pricked you!");
		take_hit(p_ptr, damroll(1, 4), "a poison needle");
		(void)do_dec_stat(A_CON, FALSE);
	}

	/* Poison */
	if (trap & (CHEST_POISON))
	{
		msg("A puff of green gas surrounds you!");
		(void)player_inc_timed(p_ptr, TMD_POISONED, 10 + randint1(20), TRUE, TRUE);
	}

	/* Paralyze */
	if (trap & (CHEST_PARALYZE))
	{
		msg("A puff of yellow gas surrounds you!");
		(void)player_inc_timed(p_ptr, TMD_PARALYZED, 10 + randint1(20), TRUE, TRUE);
	}

	/* Summon monsters */
	if (trap & (CHEST_SUMMON))
	{
		int num = 2 + randint1(3);
		msg("You are enveloped in a cloud of smoke!");
		sound(MSG_SUM_MONSTER);
		for (i = 0; i < num; i++)
		{
			(void)summon_specific(y, x, p_ptr->depth, 0, 1);
		}
	}

	/* Explode */
	if (trap & (CHEST_EXPLODE))
	{
		msg("There is a sudden explosion!");
		msg("Everything inside the chest is destroyed!");
		o_ptr->pval[DEFAULT_PVAL] = 0;
		take_hit(p_ptr, damroll(5, 8), "an exploding chest");
	}
}
Beispiel #5
0
static bool quaff_potion(object_type *o_ptr, bool *ident)
{
	/* Analyze the potion */
	switch (o_ptr->sval)
	{
		case SV_POTION_WATER:
		case SV_POTION_APPLE_JUICE:
		case SV_POTION_SLIME_MOLD:
		{
			msg_print("You feel less thirsty.");
			*ident = TRUE;
			break;
		}

		case SV_POTION_SLOWNESS:
		{
			if (set_slow(p_ptr->slow + randint(25) + 15)) *ident = TRUE;
			break;
		}

		case SV_POTION_SALT_WATER:
		{
			msg_print("The potion makes you vomit!");
			(void)set_food(PY_FOOD_STARVE - 1);
			(void)set_poisoned(0);
			(void)set_paralyzed(p_ptr->paralyzed + 4);
			*ident = TRUE;
			break;
		}

		case SV_POTION_POISON:
		{
			if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
			{
				if (set_poisoned(p_ptr->poisoned + rand_int(15) + 10))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_POTION_BLINDNESS:
		{
			if (!p_ptr->resist_blind)
			{
				if (set_blind(p_ptr->blind + rand_int(100) + 100))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_POTION_CONFUSION:
		{
			if (!p_ptr->resist_confu)
			{
				if (set_confused(p_ptr->confused + rand_int(20) + 15))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_POTION_SLEEP:
		{
			if (!p_ptr->free_act)
			{
				if (set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_POTION_LOSE_MEMORIES:
		{
			if (!p_ptr->hold_life && (p_ptr->exp > 0))
			{
				msg_print("You feel your memories fade.");
				lose_exp(p_ptr->exp / 4);
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_RUINATION:
		{
			msg_print("Your nerves and muscles feel weak and lifeless!");
			take_hit(damroll(10, 10), "a potion of Ruination");
			(void)dec_stat(A_DEX, 25, TRUE);
			(void)dec_stat(A_WIS, 25, TRUE);
			(void)dec_stat(A_CON, 25, TRUE);
			(void)dec_stat(A_STR, 25, TRUE);
			(void)dec_stat(A_CHR, 25, TRUE);
			(void)dec_stat(A_INT, 25, TRUE);
			*ident = TRUE;
			break;
		}

		case SV_POTION_DEC_STR:
		{
			if (do_dec_stat(A_STR)) *ident = TRUE;
			break;
		}

		case SV_POTION_DEC_INT:
		{
			if (do_dec_stat(A_INT)) *ident = TRUE;
			break;
		}

		case SV_POTION_DEC_WIS:
		{
			if (do_dec_stat(A_WIS)) *ident = TRUE;
			break;
		}

		case SV_POTION_DEC_DEX:
		{
			if (do_dec_stat(A_DEX)) *ident = TRUE;
			break;
		}

		case SV_POTION_DEC_CON:
		{
			if (do_dec_stat(A_CON)) *ident = TRUE;
			break;
		}

		case SV_POTION_DEC_CHR:
		{
			if (do_dec_stat(A_CHR)) *ident = TRUE;
			break;
		}

		case SV_POTION_DETONATIONS:
		{
			msg_print("Massive explosions rupture your body!");
			take_hit(damroll(50, 20), "a potion of Detonation");
			(void)set_stun(p_ptr->stun + 75);
			(void)set_cut(p_ptr->cut + 5000);
			*ident = TRUE;
			break;
		}

		case SV_POTION_DEATH:
		{
			msg_print("A feeling of Death flows through your body.");
			take_hit(5000, "a potion of Death");
			*ident = TRUE;
			break;
		}

		case SV_POTION_INFRAVISION:
		{
			if (set_tim_infra(p_ptr->tim_infra + 100 + randint(100)))
			{
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_DETECT_INVIS:
		{
			if (set_tim_invis(p_ptr->tim_invis + 12 + randint(12)))
			{
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_SLOW_POISON:
		{
			if (set_poisoned(p_ptr->poisoned / 2)) *ident = TRUE;
			break;
		}

		case SV_POTION_CURE_POISON:
		{
			if (set_poisoned(0)) *ident = TRUE;
			break;
		}

		case SV_POTION_BOLDNESS:
		{
			if (set_afraid(0)) *ident = TRUE;
			break;
		}

		case SV_POTION_SPEED:
		{
			if (!p_ptr->fast)
			{
				if (set_fast(randint(25) + 15)) *ident = TRUE;
			}
			else
			{
				(void)set_fast(p_ptr->fast + 5);
			}
			break;
		}

		case SV_POTION_RESIST_HEAT:
		{
			if (set_oppose_fire(p_ptr->oppose_fire + randint(10) + 10))
			{
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_RESIST_COLD:
		{
			if (set_oppose_cold(p_ptr->oppose_cold + randint(10) + 10))
			{
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_HEROISM:
		{
			if (hp_player(10)) *ident = TRUE;
			if (set_afraid(0)) *ident = TRUE;
			if (set_hero(p_ptr->hero + randint(25) + 25)) *ident = TRUE;
			break;
		}

		case SV_POTION_BERSERK_STRENGTH:
		{
			if (hp_player(30)) *ident = TRUE;
			if (set_afraid(0)) *ident = TRUE;
			if (set_shero(p_ptr->shero + randint(25) + 25)) *ident = TRUE;
			break;
		}

		case SV_POTION_CURE_LIGHT:
		{
			if (hp_player(damroll(2, 8))) *ident = TRUE;
			if (set_blind(0)) *ident = TRUE;
			if (set_cut(p_ptr->cut - 10)) *ident = TRUE;
			break;
		}

		case SV_POTION_CURE_SERIOUS:
		{
			if (hp_player(damroll(4, 8))) *ident = TRUE;
			if (set_blind(0)) *ident = TRUE;
			if (set_confused(0)) *ident = TRUE;
			if (set_cut((p_ptr->cut / 2) - 50)) *ident = TRUE;
			break;
		}

		case SV_POTION_CURE_CRITICAL:
		{
			if (hp_player(damroll(6, 8))) *ident = TRUE;
			if (set_blind(0)) *ident = TRUE;
			if (set_confused(0)) *ident = TRUE;
			if (set_poisoned(0)) *ident = TRUE;
			if (set_stun(0)) *ident = TRUE;
			if (set_cut(0)) *ident = TRUE;
			break;
		}

		case SV_POTION_HEALING:
		{
			if (hp_player(300)) *ident = TRUE;
			if (set_blind(0)) *ident = TRUE;
			if (set_confused(0)) *ident = TRUE;
			if (set_poisoned(0)) *ident = TRUE;
			if (set_stun(0)) *ident = TRUE;
			if (set_cut(0)) *ident = TRUE;
			break;
		}

		case SV_POTION_STAR_HEALING:
		{
			if (hp_player(1200)) *ident = TRUE;
			if (set_blind(0)) *ident = TRUE;
			if (set_confused(0)) *ident = TRUE;
			if (set_poisoned(0)) *ident = TRUE;
			if (set_stun(0)) *ident = TRUE;
			if (set_cut(0)) *ident = TRUE;
			break;
		}

		case SV_POTION_LIFE:
		{
			msg_print("You feel life flow through your body!");
			restore_level();
			(void)set_poisoned(0);
			(void)set_blind(0);
			(void)set_confused(0);
			(void)set_image(0);
			(void)set_stun(0);
			(void)set_cut(0);
			(void)do_res_stat(A_STR);
			(void)do_res_stat(A_CON);
			(void)do_res_stat(A_DEX);
			(void)do_res_stat(A_WIS);
			(void)do_res_stat(A_INT);
			(void)do_res_stat(A_CHR);

			/* Recalculate max. hitpoints */
			update_stuff();

			hp_player(5000);

			*ident = TRUE;
			break;
		}

		case SV_POTION_RESTORE_MANA:
		{
			if (p_ptr->csp < p_ptr->msp)
			{
				p_ptr->csp = p_ptr->msp;
				p_ptr->csp_frac = 0;
				msg_print("Your feel your head clear.");
				p_ptr->redraw |= (PR_MANA);
				p_ptr->window |= (PW_PLAYER_0 | PW_PLAYER_1);
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_RESTORE_EXP:
		{
			if (restore_level()) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_STR:
		{
			if (do_res_stat(A_STR)) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_INT:
		{
			if (do_res_stat(A_INT)) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_WIS:
		{
			if (do_res_stat(A_WIS)) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_DEX:
		{
			if (do_res_stat(A_DEX)) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_CON:
		{
			if (do_res_stat(A_CON)) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_CHR:
		{
			if (do_res_stat(A_CHR)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_STR:
		{
			if (do_inc_stat(A_STR)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_INT:
		{
			if (do_inc_stat(A_INT)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_WIS:
		{
			if (do_inc_stat(A_WIS)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_DEX:
		{
			if (do_inc_stat(A_DEX)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_CON:
		{
			if (do_inc_stat(A_CON)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_CHR:
		{
			if (do_inc_stat(A_CHR)) *ident = TRUE;
			break;
		}

		case SV_POTION_AUGMENTATION:
		{
			if (do_inc_stat(A_STR)) *ident = TRUE;
			if (do_inc_stat(A_INT)) *ident = TRUE;
			if (do_inc_stat(A_WIS)) *ident = TRUE;
			if (do_inc_stat(A_DEX)) *ident = TRUE;
			if (do_inc_stat(A_CON)) *ident = TRUE;
			if (do_inc_stat(A_CHR)) *ident = TRUE;
			break;
		}

		case SV_POTION_ENLIGHTENMENT:
		{
			msg_print("An image of your surroundings forms in your mind...");
			wiz_lite();
			*ident = TRUE;
			break;
		}

		case SV_POTION_STAR_ENLIGHTENMENT:
		{
			msg_print("You begin to feel more enlightened...");
			message_flush();
			wiz_lite();
			(void)do_inc_stat(A_INT);
			(void)do_inc_stat(A_WIS);
			(void)detect_traps();
			(void)detect_doors();
			(void)detect_stairs();
			(void)detect_treasure();
			(void)detect_objects_gold();
			(void)detect_objects_normal();
			identify_pack();
			self_knowledge();
			*ident = TRUE;
			break;
		}

		case SV_POTION_SELF_KNOWLEDGE:
		{
			msg_print("You begin to know yourself a little better...");
			message_flush();
			self_knowledge();
			*ident = TRUE;
			break;
		}

		case SV_POTION_EXPERIENCE:
		{
			if (p_ptr->exp < PY_MAX_EXP)
			{
				s32b ee = (p_ptr->exp / 2) + 10;
				if (ee > 100000L) ee = 100000L;
				msg_print("You feel more experienced.");
				gain_exp(ee);
				*ident = TRUE;
			}
			break;
		}
	}

	return (TRUE);
}
Beispiel #6
0
static bool eat_food(object_type *o_ptr, bool *ident)
{
	/* Analyze the food */
	switch (o_ptr->sval)
	{
		case SV_FOOD_POISON:
		{
			if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
			{
				if (set_poisoned(p_ptr->poisoned + rand_int(10) + 10))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_FOOD_BLINDNESS:
		{
			if (!p_ptr->resist_blind)
			{
				if (set_blind(p_ptr->blind + rand_int(200) + 200))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_FOOD_PARANOIA:
		{
			if (!p_ptr->resist_fear)
			{
				if (set_afraid(p_ptr->afraid + rand_int(10) + 10))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_FOOD_CONFUSION:
		{
			if (!p_ptr->resist_confu)
			{
				if (set_confused(p_ptr->confused + rand_int(10) + 10))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_FOOD_HALLUCINATION:
		{
			if (!p_ptr->resist_chaos)
			{
				if (set_image(p_ptr->image + rand_int(250) + 250))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_FOOD_PARALYSIS:
		{
			if (!p_ptr->free_act)
			{
				if (set_paralyzed(p_ptr->paralyzed + rand_int(10) + 10))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_FOOD_WEAKNESS:
		{
			take_hit(damroll(6, 6), "poisonous food");
			(void)do_dec_stat(A_STR);
			*ident = TRUE;
			break;
		}

		case SV_FOOD_SICKNESS:
		{
			take_hit(damroll(6, 6), "poisonous food");
			(void)do_dec_stat(A_CON);
			*ident = TRUE;
			break;
		}

		case SV_FOOD_STUPIDITY:
		{
			take_hit(damroll(8, 8), "poisonous food");
			(void)do_dec_stat(A_INT);
			*ident = TRUE;
			break;
		}

		case SV_FOOD_NAIVETY:
		{
			take_hit(damroll(8, 8), "poisonous food");
			(void)do_dec_stat(A_WIS);
			*ident = TRUE;
			break;
		}

		case SV_FOOD_UNHEALTH:
		{
			take_hit(damroll(10, 10), "poisonous food");
			(void)do_dec_stat(A_CON);
			*ident = TRUE;
			break;
		}

		case SV_FOOD_DISEASE:
		{
			take_hit(damroll(10, 10), "poisonous food");
			(void)do_dec_stat(A_STR);
			*ident = TRUE;
			break;
		}

		case SV_FOOD_CURE_POISON:
		{
			if (set_poisoned(0)) *ident = TRUE;
			break;
		}

		case SV_FOOD_CURE_BLINDNESS:
		{
			if (set_blind(0)) *ident = TRUE;
			break;
		}

		case SV_FOOD_CURE_PARANOIA:
		{
			if (set_afraid(0)) *ident = TRUE;
			break;
		}

		case SV_FOOD_CURE_CONFUSION:
		{
			if (set_confused(0)) *ident = TRUE;
			break;
		}

		case SV_FOOD_CURE_SERIOUS:
		{
			if (hp_player(damroll(4, 8))) *ident = TRUE;
			break;
		}

		case SV_FOOD_RESTORE_STR:
		{
			if (do_res_stat(A_STR)) *ident = TRUE;
			break;
		}

		case SV_FOOD_RESTORE_CON:
		{
			if (do_res_stat(A_CON)) *ident = TRUE;
			break;
		}

		case SV_FOOD_RESTORING:
		{
			if (do_res_stat(A_STR)) *ident = TRUE;
			if (do_res_stat(A_INT)) *ident = TRUE;
			if (do_res_stat(A_WIS)) *ident = TRUE;
			if (do_res_stat(A_DEX)) *ident = TRUE;
			if (do_res_stat(A_CON)) *ident = TRUE;
			if (do_res_stat(A_CHR)) *ident = TRUE;
			break;
		}


		case SV_FOOD_RATION:
		case SV_FOOD_BISCUIT:
		case SV_FOOD_JERKY:
		case SV_FOOD_SLIME_MOLD:
		{
			msg_print("That tastes good.");
			*ident = TRUE;
			break;
		}

		case SV_FOOD_WAYBREAD:
		{
			msg_print("That tastes good.");
			(void)set_poisoned(0);
			(void)hp_player(damroll(4, 8));
			*ident = TRUE;
			break;
		}

		case SV_FOOD_PINT_OF_ALE:
		case SV_FOOD_PINT_OF_WINE:
		{
			msg_print("That tastes good.");
			*ident = TRUE;
			break;
		}
	}

	/* Food can feed the player */
	(void)set_food(p_ptr->food + o_ptr->pval);

	return (TRUE);
}
Beispiel #7
0
/*
 * Attack the player via physical attacks.
 */
bool make_attack_normal(int m_idx)
{
	monster_type *m_ptr = &mon_list[m_idx];

	monster_race *r_ptr = &r_info[m_ptr->r_idx];

	monster_lore *l_ptr = &l_list[m_ptr->r_idx];

	int ap_cnt;

	int i, k, tmp, ac, rlev;
	int do_cut, do_stun;

	s32b gold;

	object_type *o_ptr;

	char o_name[80];

	char m_name[80];

	char ddesc[80];

	bool blinked;


	/* Not allowed to attack */
	if (r_ptr->flags1 & (RF1_NEVER_BLOW)) return (FALSE);


	/* Total armor */
	ac = p_ptr->ac + p_ptr->to_a;

	/* Extract the effective monster level */
	rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);


	/* Get the monster name (or "it") */
	monster_desc(m_name, sizeof(m_name), m_ptr, 0);

	/* Get the "died from" information (i.e. "a kobold") */
	monster_desc(ddesc, sizeof(ddesc), m_ptr, 0x88);


	/* Assume no blink */
	blinked = FALSE;

	/* Scan through all blows */
	for (ap_cnt = 0; ap_cnt < MONSTER_BLOW_MAX; ap_cnt++)
	{
		bool visible = FALSE;
		bool obvious = FALSE;

		int power = 0;
		int damage = 0;

		cptr act = NULL;

		/* Extract the attack infomation */
		int effect = r_ptr->blow[ap_cnt].effect;
		int method = r_ptr->blow[ap_cnt].method;
		int d_dice = r_ptr->blow[ap_cnt].d_dice;
		int d_side = r_ptr->blow[ap_cnt].d_side;


		/* Hack -- no more attacks */
		if (!method) break;


		/* Handle "leaving" */
		if (p_ptr->leaving) break;


		/* Extract visibility (before blink) */
		if (m_ptr->ml) visible = TRUE;



		/* Extract the attack "power" */
		switch (effect)
		{
			case RBE_HURT:      power = 60; break;
			case RBE_POISON:    power =  5; break;
			case RBE_UN_BONUS:  power = 20; break;
			case RBE_UN_POWER:  power = 15; break;
			case RBE_EAT_GOLD:  power =  5; break;
			case RBE_EAT_ITEM:  power =  5; break;
			case RBE_EAT_FOOD:  power =  5; break;
			case RBE_EAT_LITE:  power =  5; break;
			case RBE_ACID:      power =  0; break;
			case RBE_ELEC:      power = 10; break;
			case RBE_FIRE:      power = 10; break;
			case RBE_COLD:      power = 10; break;
			case RBE_BLIND:     power =  2; break;
			case RBE_CONFUSE:   power = 10; break;
			case RBE_TERRIFY:   power = 10; break;
			case RBE_PARALYZE:  power =  2; break;
			case RBE_LOSE_STR:  power =  0; break;
			case RBE_LOSE_DEX:  power =  0; break;
			case RBE_LOSE_CON:  power =  0; break;
			case RBE_LOSE_INT:  power =  0; break;
			case RBE_LOSE_WIS:  power =  0; break;
			case RBE_LOSE_CHR:  power =  0; break;
			case RBE_LOSE_ALL:  power =  2; break;
			case RBE_SHATTER:   power = 60; break;
			case RBE_EXP_10:    power =  5; break;
			case RBE_EXP_20:    power =  5; break;
			case RBE_EXP_40:    power =  5; break;
			case RBE_EXP_80:    power =  5; break;
			case RBE_HALLU:     power = 10; break;
		}


		/* Monster hits player */
		if (!effect || check_hit(power, rlev))
		{
			/* Always disturbing */
			disturb(1, 0);


			/* Hack -- Apply "protection from evil" */
			if ((p_ptr->protevil > 0) &&
			    (r_ptr->flags3 & (RF3_EVIL)) &&
			    (p_ptr->lev >= rlev) &&
			    ((rand_int(100) + p_ptr->lev) > 50))
			{
				/* Remember the Evil-ness */
				if (m_ptr->ml)
				{
					l_ptr->flags3 |= (RF3_EVIL);
				}

				/* Message */
				msg_format("%^s is repelled.", m_name);

				/* Hack -- Next attack */
				continue;
			}


			/* Assume no cut or stun */
			do_cut = do_stun = 0;

			/* Describe the attack method */
			switch (method)
			{
				case RBM_HIT:
				{
					act = "hits you.";
					do_cut = do_stun = 1;
					break;
				}

				case RBM_TOUCH:
				{
					act = "touches you.";
					break;
				}

				case RBM_PUNCH:
				{
					act = "punches you.";
					do_stun = 1;
					break;
				}

				case RBM_KICK:
				{
					act = "kicks you.";
					do_stun = 1;
					break;
				}

				case RBM_CLAW:
				{
					act = "claws you.";
					do_cut = 1;
					break;
				}

				case RBM_BITE:
				{
					act = "bites you.";
					do_cut = 1;
					break;
				}

				case RBM_STING:
				{
					act = "stings you.";
					break;
				}

				case RBM_XXX1:
				{
					act = "XXX1's you.";
					break;
				}

				case RBM_BUTT:
				{
					act = "butts you.";
					do_stun = 1;
					break;
				}

				case RBM_CRUSH:
				{
					act = "crushes you.";
					do_stun = 1;
					break;
				}

				case RBM_ENGULF:
				{
					act = "engulfs you.";
					break;
				}

				case RBM_XXX2:
				{
					act = "XXX2's you.";
					break;
				}

				case RBM_CRAWL:
				{
					act = "crawls on you.";
					break;
				}

				case RBM_DROOL:
				{
					act = "drools on you.";
					break;
				}

				case RBM_SPIT:
				{
					act = "spits on you.";
					break;
				}

				case RBM_XXX3:
				{
					act = "XXX3's on you.";
					break;
				}

				case RBM_GAZE:
				{
					act = "gazes at you.";
					break;
				}

				case RBM_WAIL:
				{
					act = "wails at you.";
					break;
				}

				case RBM_SPORE:
				{
					act = "releases spores at you.";
					break;
				}

				case RBM_XXX4:
				{
					act = "projects XXX4's at you.";
					break;
				}

				case RBM_BEG:
				{
					act = "begs you for money.";
					break;
				}

				case RBM_INSULT:
				{
					act = desc_insult[rand_int(MAX_DESC_INSULT)];
					break;
				}

				case RBM_MOAN:
				{
					act = desc_moan[rand_int(MAX_DESC_MOAN)];
					break;
				}

				case RBM_XXX5:
				{
					act = "XXX5's you.";
					break;
				}
			}

			/* Message */
			if (act) msg_format("%^s %s", m_name, act);


			/* Hack -- assume all attacks are obvious */
			obvious = TRUE;

			/* Roll out the damage */
			damage = damroll(d_dice, d_side);

			/* Apply appropriate damage */
			switch (effect)
			{
				case 0:
				{
					/* Hack -- Assume obvious */
					obvious = TRUE;

					/* Hack -- No damage */
					damage = 0;

					break;
				}

				case RBE_HURT:
				{
					/* Obvious */
					obvious = TRUE;

					/* Hack -- Player armor reduces total damage */
					damage -= (damage * ((ac < 150) ? ac : 150) / 250);

					/* Take damage */
					take_hit(damage, ddesc);

					break;
				}

				case RBE_POISON:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Take "poison" effect */
					if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
					{
						if (set_poisoned(p_ptr->poisoned + randint(rlev) + 5))
						{
							obvious = TRUE;
						}
					}

					/* Learn about the player */
					update_smart_learn(m_idx, DRS_RES_POIS);

					break;
				}

				case RBE_UN_BONUS:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Allow complete resist */
					if (!p_ptr->resist_disen)
					{
						/* Apply disenchantment */
						if (apply_disenchant(0)) obvious = TRUE;
					}

					/* Learn about the player */
					update_smart_learn(m_idx, DRS_RES_DISEN);

					break;
				}

				case RBE_UN_POWER:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Find an item */
					for (k = 0; k < 10; k++)
					{
						/* Pick an item */
						i = rand_int(INVEN_PACK);

						/* Obtain the item */
						o_ptr = &inventory[i];

						/* Skip non-objects */
						if (!o_ptr->k_idx) continue;

						/* Drain charged wands/staffs */
						if (((o_ptr->tval == TV_STAFF) ||
						     (o_ptr->tval == TV_WAND)) &&
						    (o_ptr->pval > 0))
						{
							/* Calculate healed hitpoints */
							int heal = rlev * o_ptr->pval * o_ptr->number;

							/* Don't heal more than max hp */
							heal = MIN(heal, m_ptr->maxhp - m_ptr->hp);

							/* Message */
							msg_print("Energy drains from your pack!");

							/* Obvious */
							obvious = TRUE;

							/* Heal */
							m_ptr->hp += heal;

							/* Redraw (later) if needed */
							if (p_ptr->health_who == m_idx)
								p_ptr->redraw |= (PR_HEALTH);

							/* Uncharge */
							o_ptr->pval = 0;

							/* Combine / Reorder the pack */
							p_ptr->notice |= (PN_COMBINE | PN_REORDER);

							/* Window stuff */
							p_ptr->window |= (PW_INVEN);

							/* Done */
							break;
						}
					}

					break;
				}

				case RBE_EAT_GOLD:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Obvious */
					obvious = TRUE;

					/* Saving throw (unless paralyzed) based on dex and level */
					if (!p_ptr->paralyzed &&
					    (rand_int(100) < (adj_dex_safe[p_ptr->stat_ind[A_DEX]] +
					                      p_ptr->lev)))
					{
						/* Saving throw message */
						msg_print("You quickly protect your money pouch!");

						/* Occasional blink anyway */
						if (rand_int(3)) blinked = TRUE;
					}

					/* Eat gold */
					else
					{
						gold = (p_ptr->au / 10) + randint(25);
						if (gold < 2) gold = 2;
						if (gold > 5000) gold = (p_ptr->au / 20) + randint(3000);
						if (gold > p_ptr->au) gold = p_ptr->au;
						p_ptr->au -= gold;
						if (gold <= 0)
						{
							msg_print("Nothing was stolen.");
						}
						else if (p_ptr->au)
						{
							msg_print("Your purse feels lighter.");
							msg_format("%ld coins were stolen!", (long)gold);
						}
						else
						{
							msg_print("Your purse feels lighter.");
							msg_print("All of your coins were stolen!");
						}

						/* Redraw gold */
						p_ptr->redraw |= (PR_GOLD);

						/* Window stuff */
						p_ptr->window |= (PW_PLAYER_0 | PW_PLAYER_1);

						/* Blink away */
						blinked = TRUE;
					}

					break;
				}

				case RBE_EAT_ITEM:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Saving throw (unless paralyzed) based on dex and level */
					if (!p_ptr->paralyzed &&
					    (rand_int(100) < (adj_dex_safe[p_ptr->stat_ind[A_DEX]] +
					                      p_ptr->lev)))
					{
						/* Saving throw message */
						msg_print("You grab hold of your backpack!");

						/* Occasional "blink" anyway */
						blinked = TRUE;

						/* Obvious */
						obvious = TRUE;

						/* Done */
						break;
					}

					/* Find an item */
					for (k = 0; k < 10; k++)
					{
						object_type *i_ptr;
						object_type object_type_body;

						/* Pick an item */
						i = rand_int(INVEN_PACK);

						/* Obtain the item */
						o_ptr = &inventory[i];

						/* Skip non-objects */
						if (!o_ptr->k_idx) continue;

						/* Skip artifacts */
						if (artifact_p(o_ptr)) continue;

						/* Get a description */
						object_desc(o_name, sizeof(o_name), o_ptr, FALSE, 3);

						/* Message */
						msg_format("%sour %s (%c) was stolen!",
						           ((o_ptr->number > 1) ? "One of y" : "Y"),
						           o_name, index_to_label(i));

						/* Get local object */
						i_ptr = &object_type_body;

						/* Obtain local object */
						object_copy(i_ptr, o_ptr);

						/* Modify number */
						i_ptr->number = 1;

						/* Carry the object */
						(void)monster_carry(m_idx, i_ptr);

						/* Steal the items */
						inven_item_increase(i, -1);
						inven_item_optimize(i);

						/* Obvious */
						obvious = TRUE;

						/* Blink away */
						blinked = TRUE;

						/* Done */
						break;
					}

					break;
				}

				case RBE_EAT_FOOD:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Steal some food */
					for (k = 0; k < 10; k++)
					{
						/* Pick an item from the pack */
						i = rand_int(INVEN_PACK);

						/* Get the item */
						o_ptr = &inventory[i];

						/* Skip non-objects */
						if (!o_ptr->k_idx) continue;

						/* Skip non-food objects */
						if (o_ptr->tval != TV_FOOD) continue;

						/* Get a description */
						object_desc(o_name, sizeof(o_name), o_ptr, FALSE, 0);

						/* Message */
						msg_format("%sour %s (%c) was eaten!",
						           ((o_ptr->number > 1) ? "One of y" : "Y"),
						           o_name, index_to_label(i));

						/* Steal the items */
						inven_item_increase(i, -1);
						inven_item_optimize(i);

						/* Obvious */
						obvious = TRUE;

						/* Done */
						break;
					}

					break;
				}

				case RBE_EAT_LITE:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Get the lite */
					o_ptr = &inventory[INVEN_LITE];

					/* Drain fuel */
					if ((o_ptr->pval > 0) && (!artifact_p(o_ptr)))
					{
						/* Reduce fuel */
						o_ptr->pval -= (250 + randint(250));
						if (o_ptr->pval < 1) o_ptr->pval = 1;

						/* Notice */
						if (!p_ptr->blind)
						{
							msg_print("Your light dims.");
							obvious = TRUE;
						}

						/* Window stuff */
						p_ptr->window |= (PW_EQUIP);
					}

					break;
				}

				case RBE_ACID:
				{
					/* Obvious */
					obvious = TRUE;

					/* Message */
					msg_print("You are covered in acid!");

					/* Special damage */
					acid_dam(damage, ddesc);

					/* Learn about the player */
					update_smart_learn(m_idx, DRS_RES_ACID);

					break;
				}

				case RBE_ELEC:
				{
					/* Obvious */
					obvious = TRUE;

					/* Message */
					msg_print("You are struck by electricity!");

					/* Take damage (special) */
					elec_dam(damage, ddesc);

					/* Learn about the player */
					update_smart_learn(m_idx, DRS_RES_ELEC);

					break;
				}

				case RBE_FIRE:
				{
					/* Obvious */
					obvious = TRUE;

					/* Message */
					msg_print("You are enveloped in flames!");

					/* Take damage (special) */
					fire_dam(damage, ddesc);

					/* Learn about the player */
					update_smart_learn(m_idx, DRS_RES_FIRE);

					break;
				}

				case RBE_COLD:
				{
					/* Obvious */
					obvious = TRUE;

					/* Message */
					msg_print("You are covered with frost!");

					/* Take damage (special) */
					cold_dam(damage, ddesc);

					/* Learn about the player */
					update_smart_learn(m_idx, DRS_RES_COLD);

					break;
				}

				case RBE_BLIND:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Increase "blind" */
					if (!p_ptr->resist_blind)
					{
						if (set_blind(p_ptr->blind + 10 + randint(rlev)))
						{
							obvious = TRUE;
						}
					}

					/* Learn about the player */
					update_smart_learn(m_idx, DRS_RES_BLIND);

					break;
				}

				case RBE_CONFUSE:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Increase "confused" */
					if (!p_ptr->resist_confu)
					{
						if (set_confused(p_ptr->confused + 3 + randint(rlev)))
						{
							obvious = TRUE;
						}
					}

					/* Learn about the player */
					update_smart_learn(m_idx, DRS_RES_CONFU);

					break;
				}

				case RBE_TERRIFY:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Increase "afraid" */
					if (p_ptr->resist_fear)
					{
						msg_print("You stand your ground!");
						obvious = TRUE;
					}
					else if (rand_int(100) < p_ptr->skill_sav)
					{
						msg_print("You stand your ground!");
						obvious = TRUE;
					}
					else
					{
						if (set_afraid(p_ptr->afraid + 3 + randint(rlev)))
						{
							obvious = TRUE;
						}
					}

					/* Learn about the player */
					update_smart_learn(m_idx, DRS_RES_FEAR);

					break;
				}

				case RBE_PARALYZE:
				{
					/* Hack -- Prevent perma-paralysis via damage */
					if (p_ptr->paralyzed && (damage < 1)) damage = 1;

					/* Take damage */
					take_hit(damage, ddesc);

					/* Increase "paralyzed" */
					if (p_ptr->free_act)
					{
						msg_print("You are unaffected!");
						obvious = TRUE;
					}
					else if (rand_int(100) < p_ptr->skill_sav)
					{
						msg_print("You resist the effects!");
						obvious = TRUE;
					}
					else
					{
						if (set_paralyzed(p_ptr->paralyzed + 3 + randint(rlev)))
						{
							obvious = TRUE;
						}
					}

					/* Learn about the player */
					update_smart_learn(m_idx, DRS_FREE);

					break;
				}

				case RBE_LOSE_STR:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Damage (stat) */
					if (do_dec_stat(A_STR)) obvious = TRUE;

					break;
				}

				case RBE_LOSE_INT:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Damage (stat) */
					if (do_dec_stat(A_INT)) obvious = TRUE;

					break;
				}

				case RBE_LOSE_WIS:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Damage (stat) */
					if (do_dec_stat(A_WIS)) obvious = TRUE;

					break;
				}

				case RBE_LOSE_DEX:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Damage (stat) */
					if (do_dec_stat(A_DEX)) obvious = TRUE;

					break;
				}

				case RBE_LOSE_CON:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Damage (stat) */
					if (do_dec_stat(A_CON)) obvious = TRUE;

					break;
				}

				case RBE_LOSE_CHR:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Damage (stat) */
					if (do_dec_stat(A_CHR)) obvious = TRUE;

					break;
				}

				case RBE_LOSE_ALL:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Damage (stats) */
					if (do_dec_stat(A_STR)) obvious = TRUE;
					if (do_dec_stat(A_DEX)) obvious = TRUE;
					if (do_dec_stat(A_CON)) obvious = TRUE;
					if (do_dec_stat(A_INT)) obvious = TRUE;
					if (do_dec_stat(A_WIS)) obvious = TRUE;
					if (do_dec_stat(A_CHR)) obvious = TRUE;

					break;
				}

				case RBE_SHATTER:
				{
					/* Obvious */
					obvious = TRUE;

					/* Hack -- Reduce damage based on the player armor class */
					damage -= (damage * ((ac < 150) ? ac : 150) / 250);

					/* Take damage */
					take_hit(damage, ddesc);

					/* Radius 8 earthquake centered at the monster */
					if (damage > 23) earthquake(m_ptr->fy, m_ptr->fx, 8);

					break;
				}

				case RBE_EXP_10:
				{
					/* Obvious */
					obvious = TRUE;

					/* Take damage */
					take_hit(damage, ddesc);

					if (p_ptr->hold_life && (rand_int(100) < 95))
					{
						msg_print("You keep hold of your life force!");
					}
					else
					{
						s32b d = damroll(10, 6) + (p_ptr->exp/100) * MON_DRAIN_LIFE;
						if (p_ptr->hold_life)
						{
							msg_print("You feel your life slipping away!");
							lose_exp(d/10);
						}
						else
						{
							msg_print("You feel your life draining away!");
							lose_exp(d);
						}
					}
					break;
				}

				case RBE_EXP_20:
				{
					/* Obvious */
					obvious = TRUE;

					/* Take damage */
					take_hit(damage, ddesc);

					if (p_ptr->hold_life && (rand_int(100) < 90))
					{
						msg_print("You keep hold of your life force!");
					}
					else
					{
						s32b d = damroll(20, 6) + (p_ptr->exp / 100) * MON_DRAIN_LIFE;

						if (p_ptr->hold_life)
						{
							msg_print("You feel your life slipping away!");
							lose_exp(d / 10);
						}
						else
						{
							msg_print("You feel your life draining away!");
							lose_exp(d);
						}
					}
					break;
				}

				case RBE_EXP_40:
				{
					/* Obvious */
					obvious = TRUE;

					/* Take damage */
					take_hit(damage, ddesc);

					if (p_ptr->hold_life && (rand_int(100) < 75))
					{
						msg_print("You keep hold of your life force!");
					}
					else
					{
						s32b d = damroll(40, 6) + (p_ptr->exp / 100) * MON_DRAIN_LIFE;

						if (p_ptr->hold_life)
						{
							msg_print("You feel your life slipping away!");
							lose_exp(d / 10);
						}
						else
						{
							msg_print("You feel your life draining away!");
							lose_exp(d);
						}
					}
					break;
				}

				case RBE_EXP_80:
				{
					/* Obvious */
					obvious = TRUE;

					/* Take damage */
					take_hit(damage, ddesc);

					if (p_ptr->hold_life && (rand_int(100) < 50))
					{
						msg_print("You keep hold of your life force!");
					}
					else
					{
						s32b d = damroll(80, 6) + (p_ptr->exp / 100) * MON_DRAIN_LIFE;

						if (p_ptr->hold_life)
						{
							msg_print("You feel your life slipping away!");
							lose_exp(d / 10);
						}
						else
						{
							msg_print("You feel your life draining away!");
							lose_exp(d);
						}
					}
					break;
				}

				case RBE_HALLU:
				{
					/* Take damage */
					take_hit(damage, ddesc);

					/* Increase "image" */
					if (!p_ptr->resist_chaos)
					{
						if (set_image(p_ptr->image + 3 + randint(rlev / 2)))
						{
							obvious = TRUE;
						}
					}

					/* Learn about the player */
					update_smart_learn(m_idx, DRS_RES_CHAOS);

					break;
				}
			}


			/* Hack -- only one of cut or stun */
			if (do_cut && do_stun)
			{
				/* Cancel cut */
				if (rand_int(100) < 50)
				{
					do_cut = 0;
				}

				/* Cancel stun */
				else
				{
					do_stun = 0;
				}
			}

			/* Handle cut */
			if (do_cut)
			{
				int k;

				/* Critical hit (zero if non-critical) */
				tmp = monster_critical(d_dice, d_side, damage);

				/* Roll for damage */
				switch (tmp)
				{
					case 0: k = 0; break;
					case 1: k = randint(5); break;
					case 2: k = randint(5) + 5; break;
					case 3: k = randint(20) + 20; break;
					case 4: k = randint(50) + 50; break;
					case 5: k = randint(100) + 100; break;
					case 6: k = 300; break;
					default: k = 500; break;
				}

				/* Apply the cut */
				if (k) (void)set_cut(p_ptr->cut + k);
			}

			/* Handle stun */
			if (do_stun)
			{
				int k;

				/* Critical hit (zero if non-critical) */
				tmp = monster_critical(d_dice, d_side, damage);

				/* Roll for damage */
				switch (tmp)
				{
					case 0: k = 0; break;
					case 1: k = randint(5); break;
					case 2: k = randint(10) + 10; break;
					case 3: k = randint(20) + 20; break;
					case 4: k = randint(30) + 30; break;
					case 5: k = randint(40) + 40; break;
					case 6: k = 100; break;
					default: k = 200; break;
				}

				/* Apply the stun */
				if (k) (void)set_stun(p_ptr->stun + k);
			}
		}

		/* Monster missed player */
		else
		{
			/* Analyze failed attacks */
			switch (method)
			{
				case RBM_HIT:
				case RBM_TOUCH:
				case RBM_PUNCH:
				case RBM_KICK:
				case RBM_CLAW:
				case RBM_BITE:
				case RBM_STING:
				case RBM_XXX1:
				case RBM_BUTT:
				case RBM_CRUSH:
				case RBM_ENGULF:
				case RBM_XXX2:

				/* Visible monsters */
				if (m_ptr->ml)
				{
					/* Disturbing */
					disturb(1, 0);

					/* Message */
					msg_format("%^s misses you.", m_name);
				}

				break;
			}
		}


		/* Analyze "visible" monsters only */
		if (visible)
		{
			/* Count "obvious" attacks (and ones that cause damage) */
			if (obvious || damage || (l_ptr->blows[ap_cnt] > 10))
			{
				/* Count attacks of this type */
				if (l_ptr->blows[ap_cnt] < MAX_UCHAR)
				{
					l_ptr->blows[ap_cnt]++;
				}
			}
		}
	}


	/* Blink away */
	if (blinked)
	{
		msg_print("There is a puff of smoke!");
		teleport_away(m_idx, MAX_SIGHT * 2 + 5);
	}


	/* Always notice cause of death */
	if (p_ptr->is_dead && (l_ptr->deaths < MAX_SHORT))
	{
		l_ptr->deaths++;
	}


	/* Assume we attacked */
	return (TRUE);
}
Beispiel #8
0
/*
 * Chests have traps too.
 *
 * Exploding chest destroys contents (and traps).
 * Note that the chest itself is never destroyed.
 */
static void chest_trap(int y, int x, s16b o_idx)
{
	int i, trap;

	object_type *o_ptr = &o_list[o_idx];


	/* Ignore disarmed chests */
	if (o_ptr->pval <= 0) return;

	/* Obtain the traps */
	trap = chest_traps[o_ptr->pval];

	/* Lose strength */
	if (trap & (CHEST_LOSE_STR))
	{
		msg_print("A small needle has pricked you!");
		take_hit(damroll(1, 4), "a poison needle");
		(void)do_dec_stat(A_STR, FALSE);
	}

	/* Lose constitution */
	if (trap & (CHEST_LOSE_CON))
	{
		msg_print("A small needle has pricked you!");
		take_hit(damroll(1, 4), "a poison needle");
		(void)do_dec_stat(A_CON, FALSE);
	}

	/* Poison */
	if (trap & (CHEST_POISON))
	{
		msg_print("A puff of green gas surrounds you!");
		if (!(p_ptr->state.resist_pois ||  p_ptr->timed[TMD_OPP_POIS] || p_ptr->state.immune_pois ))
			(void)inc_timed(TMD_POISONED, 10 + randint1(20), TRUE);
		else if (p_ptr->state.resist_pois || p_ptr->state.immune_pois)
			wieldeds_notice_flag(OF_RES_POIS);
	}

	/* Paralyze */
	if (trap & (CHEST_PARALYZE))
	{
		msg_print("A puff of yellow gas surrounds you!");
		if (!p_ptr->state.free_act)
			(void)inc_timed(TMD_PARALYZED, 10 + randint1(20), TRUE);
		else
			wieldeds_notice_flag(OF_FREE_ACT);
	}

	/* Summon monsters */
	if (trap & (CHEST_SUMMON))
	{
		int num = 2 + randint1(3);
		msg_print("You are enveloped in a cloud of smoke!");
		sound(MSG_SUM_MONSTER);
		for (i = 0; i < num; i++)
		{
			(void)summon_specific(y, x, p_ptr->depth, 0, 1);
		}
	}

	/* Explode */
	if (trap & (CHEST_EXPLODE))
	{
		msg_print("There is a sudden explosion!");
		msg_print("Everything inside the chest is destroyed!");
		o_ptr->pval = 0;
		take_hit(damroll(5, 8), "an exploding chest");
	}
}
Beispiel #9
0
static void do_cmd_eat_food_aux(int item)
{
    int ident, lev;
    object_type *o_ptr;

    if (music_singing_any()) bard_stop_singing();
    if (hex_spelling_any()) stop_hex_spell_all();
    warlock_stop_singing();

    /* Get the item (in the pack) */
    if (item >= 0)
    {
        o_ptr = &inventory[item];
    }

    /* Get the item (on the floor) */
    else
    {
        o_ptr = &o_list[0 - item];
    }

    if (object_is_mushroom(o_ptr) && o_ptr->art_name && o_ptr->timeout)
    {
        msg_print("Your mushroom is still charging.");
        return;
    }

    /* Sound */
    sound(SOUND_EAT);

    /* Take a turn */
    energy_use = 100;

    /* Identity not known yet */
    ident = FALSE;

    /* Object level */
    lev = k_info[o_ptr->k_idx].level;

    if (o_ptr->tval == TV_FOOD)
    {
        /* Analyze the food */
        switch (o_ptr->sval)
        {
            case SV_FOOD_POISON:
            {
                if (!res_save_default(RES_POIS))
                {
                    if (set_poisoned(p_ptr->poisoned + randint0(10) + 10, FALSE))
                        ident = TRUE;
                }
                break;
            }

            case SV_FOOD_BLINDNESS:
            {
                if (!res_save_default(RES_BLIND))
                {
                    if (set_blind(p_ptr->blind + randint0(200) + 200, FALSE))
                        ident = TRUE;
                }
                break;
            }

            case SV_FOOD_PARANOIA:
            {
                if (!fear_save_p(fear_threat_level()))
                    ident = fear_add_p(FEAR_SCARED);
                break;
            }

            case SV_FOOD_CONFUSION:
            {
                if (!res_save_default(RES_CONF))
                {
                    if (set_confused(p_ptr->confused + randint0(10) + 10, FALSE))
                        ident = TRUE;
                }
                break;
            }

            case SV_FOOD_HALLUCINATION:
            {
                if (!res_save_default(RES_CHAOS))
                {
                    if (set_image(p_ptr->image + randint0(25) + 25, FALSE))
                        ident = TRUE;
                }
                break;
            }

            case SV_FOOD_PARALYSIS:
            {
                if (!p_ptr->free_act)
                {
                    if (set_paralyzed(randint1(4), FALSE))
                    {
                        ident = TRUE;
                    }
                }
                break;
            }

            case SV_FOOD_WEAKNESS:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(6, 6), "poisonous food", -1);
                (void)do_dec_stat(A_STR);
                ident = TRUE;
                break;
            }

            case SV_FOOD_SICKNESS:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(6, 6), "poisonous food", -1);
                (void)do_dec_stat(A_CON);
                ident = TRUE;
                break;
            }

            case SV_FOOD_STUPIDITY:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(8, 8), "poisonous food", -1);
                (void)do_dec_stat(A_INT);
                ident = TRUE;
                break;
            }

            case SV_FOOD_NAIVETY:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(8, 8), "poisonous food", -1);
                (void)do_dec_stat(A_WIS);
                ident = TRUE;
                break;
            }

            case SV_FOOD_UNHEALTH:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(10, 10), "poisonous food", -1);
                (void)do_dec_stat(A_CON);
                ident = TRUE;
                break;
            }

            case SV_FOOD_DISEASE:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(10, 10), "poisonous food", -1);
                (void)do_dec_stat(A_STR);
                ident = TRUE;
                break;
            }

            case SV_FOOD_CURE_POISON:
            {
                if (set_poisoned(0, TRUE)) ident = TRUE;
                break;
            }

            case SV_FOOD_CURE_BLINDNESS:
            {
                if (set_blind(0, TRUE)) ident = TRUE;
                break;
            }

            case SV_FOOD_CURE_PARANOIA:
            {
                if (p_ptr->afraid)
                {
                    fear_clear_p();
                    ident = TRUE;
                }
                break;
            }

            case SV_FOOD_CURE_CONFUSION:
            {
                if (set_confused(0, TRUE)) ident = TRUE;
                break;
            }

            case SV_FOOD_CURE_SERIOUS:
            {
                if (hp_player(damroll(6, 8))) ident = TRUE;
                if (set_cut((p_ptr->cut / 2) - 50, TRUE)) ident = TRUE;
                break;
            }

            case SV_FOOD_RESTORE_STR:
            {
                if (do_res_stat(A_STR)) ident = TRUE;
                break;
            }

            case SV_FOOD_RESTORE_CON:
            {
                if (do_res_stat(A_CON)) ident = TRUE;
                break;
            }

            case SV_FOOD_RESTORING:
            {
                if (do_res_stat(A_STR)) ident = TRUE;
                if (do_res_stat(A_INT)) ident = TRUE;
                if (do_res_stat(A_WIS)) ident = TRUE;
                if (do_res_stat(A_DEX)) ident = TRUE;
                if (do_res_stat(A_CON)) ident = TRUE;
                if (do_res_stat(A_CHR)) ident = TRUE;
                break;
            }
            case SV_FOOD_RATION:
            case SV_FOOD_BISCUIT:
            case SV_FOOD_JERKY:
            case SV_FOOD_SLIME_MOLD:
            {
                msg_print("That tastes good.");
                ident = TRUE;
                break;
            }
            case SV_FOOD_AMBROSIA:
            {
                msg_print("That tastes divine!");
                set_poisoned(0, TRUE);
                hp_player(damroll(15, 15));
                do_res_stat(A_STR);
                do_res_stat(A_INT);
                do_res_stat(A_WIS);
                do_res_stat(A_DEX);
                do_res_stat(A_CON);
                do_res_stat(A_CHR);
                restore_level();
                ident = TRUE;
                break;
            }

            case SV_FOOD_WAYBREAD:
            {
                msg_print("That tastes good.");
                (void)set_poisoned(0, TRUE);
                (void)hp_player(damroll(4, 8));
                ident = TRUE;
                break;
            }

            case SV_FOOD_PINT_OF_ALE:
            case SV_FOOD_PINT_OF_WINE:
            {
                msg_print("That tastes good.");
                ident = TRUE;
                break;
            }
        }
    }

    if (prace_is_(RACE_SNOTLING) && object_is_mushroom(o_ptr))
    {
        int lev = k_info[o_ptr->k_idx].level;
        int dur = lev + randint1(lev);
        set_fast(p_ptr->fast + dur, FALSE);
        set_shield(p_ptr->shield + dur, FALSE);
        set_hero(p_ptr->hero + dur, FALSE);
        set_tim_building_up(p_ptr->tim_building_up + dur, FALSE);
    }

    /* Combine / Reorder the pack (later) */
    p_ptr->notice |= (PN_COMBINE | PN_REORDER);

    if (!(object_is_aware(o_ptr)))
    {
        virtue_add(VIRTUE_KNOWLEDGE, -1);
        virtue_add(VIRTUE_PATIENCE, -1);
        virtue_add(VIRTUE_CHANCE, 1);
    }

    /* We have tried it */
    if (o_ptr->tval == TV_FOOD) object_tried(o_ptr);

    stats_on_use(o_ptr, 1);

    /* The player is now aware of the object */
    if (ident && !object_is_aware(o_ptr))
    {
        object_aware(o_ptr);
        stats_on_notice(o_ptr, 1);
        gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);
    }
static void do_cmd_eat_food_aux(obj_ptr obj)
{
    int  lev = k_info[obj->k_idx].level;
    bool ident = FALSE;

    if (music_singing_any()) bard_stop_singing();
    if (hex_spelling_any()) stop_hex_spell_all();
    warlock_stop_singing();

    if (object_is_mushroom(obj) && obj->art_name && obj->timeout)
    {
        msg_print("Your mushroom is still charging.");
        return;
    }

    sound(SOUND_EAT);
    energy_use = 100;
    ident = FALSE;

    /* Food may have effects */
    if (obj->tval == TV_FOOD)
    {
        switch (obj->sval)
        {
            case SV_FOOD_POISON:
            {
                if (!res_save_default(RES_POIS))
                {
                    if (set_poisoned(p_ptr->poisoned + randint0(10) + 10, FALSE))
                        ident = TRUE;
                }
                break;
            }

            case SV_FOOD_BLINDNESS:
            {
                if (!res_save_default(RES_BLIND))
                {
                    if (set_blind(p_ptr->blind + randint0(200) + 200, FALSE))
                        ident = TRUE;
                }
                break;
            }

            case SV_FOOD_PARANOIA:
            {
                if (!fear_save_p(fear_threat_level()))
                    ident = fear_add_p(FEAR_SCARED);
                break;
            }

            case SV_FOOD_CONFUSION:
            {
                if (!res_save_default(RES_CONF))
                {
                    if (set_confused(p_ptr->confused + randint0(10) + 10, FALSE))
                        ident = TRUE;
                }
                break;
            }

            case SV_FOOD_HALLUCINATION:
            {
                if (!res_save_default(RES_CHAOS))
                {
                    if (set_image(p_ptr->image + randint0(25) + 25, FALSE))
                        ident = TRUE;
                }
                break;
            }

            case SV_FOOD_PARALYSIS:
            {
                if (!p_ptr->free_act)
                {
                    if (set_paralyzed(randint1(4), FALSE))
                    {
                        ident = TRUE;
                    }
                }
                else equip_learn_flag(OF_FREE_ACT);
                break;
            }

            case SV_FOOD_WEAKNESS:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(6, 6), "poisonous food", -1);
                do_dec_stat(A_STR);
                ident = TRUE;
                break;
            }

            case SV_FOOD_SICKNESS:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(6, 6), "poisonous food", -1);
                do_dec_stat(A_CON);
                ident = TRUE;
                break;
            }

            case SV_FOOD_STUPIDITY:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(8, 8), "poisonous food", -1);
                do_dec_stat(A_INT);
                ident = TRUE;
                break;
            }

            case SV_FOOD_NAIVETY:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(8, 8), "poisonous food", -1);
                do_dec_stat(A_WIS);
                ident = TRUE;
                break;
            }

            case SV_FOOD_UNHEALTH:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(10, 10), "poisonous food", -1);
                do_dec_stat(A_CON);
                ident = TRUE;
                break;
            }

            case SV_FOOD_DISEASE:
            {
                take_hit(DAMAGE_NOESCAPE, damroll(10, 10), "poisonous food", -1);
                do_dec_stat(A_STR);
                ident = TRUE;
                break;
            }

            case SV_FOOD_CURE_POISON:
            {
                if (set_poisoned(0, TRUE)) ident = TRUE;
                break;
            }

            case SV_FOOD_CURE_BLINDNESS:
            {
                if (set_blind(0, TRUE)) ident = TRUE;
                break;
            }

            case SV_FOOD_CURE_PARANOIA:
            {
                if (p_ptr->afraid)
                {
                    fear_clear_p();
                    ident = TRUE;
                }
                break;
            }

            case SV_FOOD_CURE_CONFUSION:
            {
                if (set_confused(0, TRUE)) ident = TRUE;
                break;
            }

            case SV_FOOD_CURE_SERIOUS:
            {
                if (hp_player(damroll(6, 8))) ident = TRUE;
                if (set_cut((p_ptr->cut / 2) - 50, TRUE)) ident = TRUE;
                break;
            }

            case SV_FOOD_RESTORE_STR:
            {
                if (do_res_stat(A_STR)) ident = TRUE;
                break;
            }

            case SV_FOOD_RESTORE_CON:
            {
                if (do_res_stat(A_CON)) ident = TRUE;
                break;
            }

            case SV_FOOD_RESTORING:
            {
                if (do_res_stat(A_STR)) ident = TRUE;
                if (do_res_stat(A_INT)) ident = TRUE;
                if (do_res_stat(A_WIS)) ident = TRUE;
                if (do_res_stat(A_DEX)) ident = TRUE;
                if (do_res_stat(A_CON)) ident = TRUE;
                if (do_res_stat(A_CHR)) ident = TRUE;
                break;
            }
            case SV_FOOD_RATION:
            case SV_FOOD_BISCUIT:
            case SV_FOOD_JERKY:
            case SV_FOOD_SLIME_MOLD:
            {
                msg_print("That tastes good.");
                ident = TRUE;
                break;
            }
            case SV_FOOD_AMBROSIA:
            {
                msg_print("That tastes divine!");
                set_poisoned(0, TRUE);
                hp_player(damroll(15, 15));
                do_res_stat(A_STR);
                do_res_stat(A_INT);
                do_res_stat(A_WIS);
                do_res_stat(A_DEX);
                do_res_stat(A_CON);
                do_res_stat(A_CHR);
                restore_level();
                ident = TRUE;
                break;
            }

            case SV_FOOD_WAYBREAD:
            {
                msg_print("That tastes good.");
                set_poisoned(0, TRUE);
                hp_player(damroll(4, 8));
                ident = TRUE;
                break;
            }

            case SV_FOOD_PINT_OF_ALE:
            case SV_FOOD_PINT_OF_WINE:
            {
                msg_print("That tastes good.");
                ident = TRUE;
                break;
            }
        }
    }

    if (prace_is_(RACE_SNOTLING) && object_is_mushroom(obj))
    {
        int dur = lev + randint1(lev);
        set_fast(p_ptr->fast + dur, FALSE);
        set_shield(p_ptr->shield + dur, FALSE);
        set_hero(p_ptr->hero + dur, FALSE);
        set_tim_building_up(p_ptr->tim_building_up + dur, FALSE);
    }

    if (!object_is_aware(obj))
    {
        virtue_add(VIRTUE_KNOWLEDGE, -1);
        virtue_add(VIRTUE_PATIENCE, -1);
        virtue_add(VIRTUE_CHANCE, 1);
    }

    /* We have tried it */
    if (obj->tval == TV_FOOD) object_tried(obj);

    stats_on_use(obj, 1);

    /* The player is now aware of the object */
    if (ident && !object_is_aware(obj))
    {
        object_aware(obj);
        stats_on_notice(obj, 1);
        gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);
        p_ptr->notice |= PN_OPTIMIZE_PACK;
    }
Beispiel #11
0
/**
 * Handle player hitting a real trap.  Rewritten in Oangband to allow a
 * greater variety of traps, with effects controlled by dungeon level.
 * To allow a trap to choose one of a variety of effects consistantly,
 * the quick RNG is often used, and xy coordinates input as a seed value.
 */
extern void hit_trap(int y, int x)
{
    int i, j, k, num;
    int dam = 0;

    int nastyness, selection;

    feature_type *f_ptr = &f_info[cave_feat[y][x]];

    cptr name = f_ptr->name;

    /* Use the "simple" RNG to insure that traps are consistant. */
    Rand_quick = TRUE;

    /* Use the coordinates of the trap to seed the RNG. */
    Rand_value = y * x;

    /* Disturb the player */
    disturb(0, 0);

    /* Analyze XXX XXX XXX */
    switch (cave_feat[y][x]) {
    /* trap door. */
    case FEAT_TRAP_HEAD + 0x00:
    {
        Rand_quick = FALSE;

        /* Paranoia -NRM- */
        if (((stage_map[p_ptr->stage][STAGE_TYPE] == CAVE)
                || (stage_map[p_ptr->stage][STAGE_TYPE] == VALLEY))
                && (!stage_map[p_ptr->stage][DOWN])) {
            cave_info[y][x] &= ~(CAVE_MARK);
            cave_set_feat(y, x, FEAT_FLOOR);
            msg_print("The trap fails!");
            break;
        }


        msg_print("You fall through a trap door!");
        if (p_ptr->state.ffall) {
            notice_obj(OF_FEATHER, 0);
            msg_print("You float gently down to the next level.");
        } else {
            dam = damroll(2, 8);
            take_hit(dam, name);
        }
        /* Remember where we came from */
        p_ptr->last_stage = p_ptr->stage;

        if (!stage_map[p_ptr->stage][DOWN]) {
            /* Set the ways forward and back */
            stage_map[255][UP] = p_ptr->stage;
            stage_map[p_ptr->stage][DOWN] = 255;
            stage_map[255][DEPTH] = p_ptr->depth + 1;
        }

        /* New stage */
        p_ptr->stage = stage_map[p_ptr->stage][DOWN];

        /* New depth */
        p_ptr->depth = stage_map[p_ptr->stage][DEPTH];

        /* Leaving */
        p_ptr->leaving = TRUE;

        Rand_quick = TRUE;

        break;
    }

    /* pits. */
    case FEAT_TRAP_HEAD + 0x01:
    {
        /* determine how dangerous the trap is allowed to be. */
        nastyness = randint1(p_ptr->depth);
        if (randint1(20) == 1)
            nastyness += 20;
        else if (randint1(5) == 1)
            nastyness += 10;

        /* Player is now in pit. */
        monster_swap(p_ptr->py, p_ptr->px, y, x);

        /* Center on player. */
        y = p_ptr->py;
        x = p_ptr->px;

        /* pit of daggers. */
        if ((nastyness > 80) && (randint1(3) != 3)) {
            msg_print("You fall into a pit of daggers!");

            if (p_ptr->state.ffall) {
                notice_obj(OF_FEATHER, 0);
                msg_print("You float gently to the floor of the pit.");
                msg_print("You carefully avoid setting off the daggers.");
            }

            else {
                /* a trap of morgul. */
                if (randint1(6) == 1) {
                    Rand_quick = FALSE;


                    msg_print
                    ("A single coldly gleaming dagger pierces you deeply!");
                    msg_print
                    ("You feel a deadly chill slowly withering your soul.");

                    /* activate the Black Breath. */
                    p_ptr->black_breath = TRUE;

                    /* lots of damage. */
                    dam = damroll(20, 15);

                    /* undead may be attracted. */
                    if (randint1(2) == 1) {
                        msg_print
                        ("Undead suddenly appear and call you to them!");

                        k = randint1(3) + 2;
                        for (i = 0; i < k; i++) {
                            summon_specific(y, x, FALSE, p_ptr->depth,
                                            SUMMON_UNDEAD);
                        }
                    }

                    /* morgul-traps are one-time only. */
                    cave_info[y][x] &= ~(CAVE_MARK);
                    cave_set_feat(y, x, FEAT_FLOOR);

                    Rand_quick = TRUE;
                }

                else {
                    Rand_quick = FALSE;

                    /* activate the ordinary daggers. */
                    msg_print("Daggers pierce you everywhere!");

                    k = randint1(10) + 5;
                    for (i = 0; i < k; i++) {
                        dam += damroll(3, 4);
                    }

                    Rand_quick = TRUE;
                }

                /* cut the player. */
                (void) inc_timed(TMD_CUT, randint1(dam), TRUE);

                /* Take the damage. */
                take_hit(dam, name);
            }
        }

        /* poisoned spiked pit. */
        else if ((nastyness > 55) && (randint1(3) != 3)) {
            msg_print("You fall into a spiked pit!");

            if (p_ptr->state.ffall) {
                notice_obj(OF_FEATHER, 0);
                msg_print("You float gently to the floor of the pit.");
                msg_print("You carefully avoid touching the spikes.");
            }

            else {
                Rand_quick = FALSE;

                /* Base damage */
                dam = damroll(2, 6);

                /* Extra spike damage */
                if (randint0(100) < 85) {
                    bool was_poisoned;

                    msg_print("You are impaled on poisonous spikes!");

                    dam = dam * (randint1(6) + 3);
                    (void) inc_timed(TMD_CUT, randint1(dam), TRUE);

                    was_poisoned = pois_hit(dam);

                    if (!was_poisoned)
                        msg_print("The poison does not affect you!");
                }

                /* Take the damage */
                take_hit(dam, name);

                Rand_quick = TRUE;
            }
        }

        /* spiked pit. */
        else if ((nastyness > 30) && (randint1(3) != 3)) {
            msg_print("You fall into a spiked pit!");

            if (p_ptr->state.ffall) {
                notice_obj(OF_FEATHER, 0);
                msg_print("You float gently to the floor of the pit.");
                msg_print("You carefully avoid touching the spikes.");
            }

            else {
                Rand_quick = FALSE;

                /* Base damage */
                dam = damroll(2, 6);

                /* Extra spike damage */
                if (randint0(100) < 85) {
                    msg_print("You are impaled!");

                    dam = dam * (2 + randint1(4));
                    (void) inc_timed(TMD_CUT, randint1(dam), TRUE);
                }

                /* Take the damage */
                take_hit(dam, name);

                Rand_quick = TRUE;
            }
        }

        /* ordinary pit in all other cases. */
        else {
            msg_print("You fall into a pit!");
            if (p_ptr->state.ffall) {
                notice_obj(OF_FEATHER, 0);
                msg_print("You float gently to the bottom of the pit.");
            } else {
                Rand_quick = FALSE;

                dam = damroll(2, 6);
                take_hit(dam, name);

                Rand_quick = TRUE;
            }
        }

        break;
    }

    /* stat-reducing dart traps. */
    case FEAT_TRAP_HEAD + 0x02:
    {
        /* decide if the dart hits. */
        if (check_trap_hit(50 + p_ptr->depth)) {
            /* select a stat to drain. */
            selection = randint0(6);

            Rand_quick = FALSE;

            msg_print("A small dart hits you!");
            dam = damroll(1, 4);
            take_hit(dam, name);

            /* Determine how dangerous the trap is allowed to be. */
            nastyness = randint1(p_ptr->depth);

            /* decide how much to drain the stat by. */
            if ((nastyness > 50) && (randint1(3) == 1)) {
                num = randint1(4);
            } else
                num = 1;

            /* drain the stat. */
            for (i = 0; i < num; i++) {
                (void) do_dec_stat(selection);
            }

            Rand_quick = TRUE;
        } else {
            msg_print("A small dart barely misses you.");
        }
        break;
    }

    /* discolored spots. */
    case FEAT_TRAP_HEAD + 0x03:
    {
        /* determine how dangerous the trap is allowed to be. */
        nastyness = randint1(p_ptr->depth);
        if (randint1(5) == 1)
            nastyness += 10;

        /* pick a elemental attack type. */
        selection = randint1(4);


        /* electicity trap. */
        if (selection == 1) {
            if ((nastyness >= 50) && (randint1(2) == 1)) {
                Rand_quick = FALSE;

                msg_print("You are struck by lightning!");
                dam = damroll(6, 30);

                Rand_quick = TRUE;
            } else {
                Rand_quick = FALSE;

                msg_print("You get zapped!");
                dam = damroll(4, 8);

                Rand_quick = TRUE;
            }
            Rand_quick = FALSE;
            elec_dam(dam, "an electricity trap");
            Rand_quick = TRUE;

        }

        /* frost trap. */
        if (selection == 2) {
            if ((nastyness >= 50) && (randint1(2) == 1)) {
                Rand_quick = FALSE;

                msg_print("You are lost within a blizzard!");
                dam = damroll(6, 30);

                Rand_quick = TRUE;
            } else {
                Rand_quick = FALSE;

                msg_print("You are coated in frost!");
                dam = damroll(4, 8);

                Rand_quick = TRUE;
            }
            Rand_quick = FALSE;
            cold_dam(dam, "a frost trap");
            Rand_quick = TRUE;
        }

        /* fire trap. */
        if (selection == 3) {
            if ((nastyness >= 50) && (randint1(2) == 1)) {
                Rand_quick = FALSE;

                msg_print("You are enveloped in a column of fire!");
                dam = damroll(6, 30);

                Rand_quick = TRUE;
            } else {
                Rand_quick = FALSE;

                msg_print("You are surrounded by flames!");
                dam = damroll(4, 8);

                Rand_quick = TRUE;
            }
            Rand_quick = FALSE;
            fire_dam(dam, "a fire trap");
            Rand_quick = TRUE;
        }

        /* acid trap. */
        if (selection == 4) {
            if ((nastyness >= 50) && (randint1(2) == 1)) {
                Rand_quick = FALSE;

                msg_print("A cauldron of acid is tipped over your head!");
                dam = damroll(6, 30);

                Rand_quick = TRUE;
            } else {
                Rand_quick = FALSE;

                msg_print("You are splashed with acid!");
                dam = damroll(4, 8);

                Rand_quick = TRUE;
            }
            Rand_quick = FALSE;
            acid_dam(dam, "an acid trap");
            Rand_quick = TRUE;
        }

        break;
    }

    /* gas traps. */
    case FEAT_TRAP_HEAD + 0x04:
    {
        selection = randint1(4);

        /* blinding trap. */
        if (selection == 1) {
            msg_print("You are surrounded by a black gas!");
            if (!p_ptr->state.no_blind) {
                Rand_quick = FALSE;

                (void) inc_timed(TMD_BLIND, randint0(30) + 15, TRUE);

                Rand_quick = TRUE;
            }
        } else
            notice_obj(OF_SEEING, 0);

        /* confusing trap. */
        if (selection == 2) {
            msg_print
            ("You are surrounded by a gas of scintillating colors!");
            if (!p_resist_good(P_RES_CONFU)) {
                Rand_quick = FALSE;

                (void) inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE);

                Rand_quick = TRUE;
            } else
                notice_other(IF_RES_CONFU, 0);
        }

        /* poisoning trap. */
        if (selection == 3) {
            msg_print("You are surrounded by a pungent green gas!");

            Rand_quick = FALSE;

            pois_hit(25);

            Rand_quick = TRUE;
        }

        /* sleeping trap. */
        if (selection == 4) {
            msg_print("You are surrounded by a strange white mist!");
            if (!p_ptr->state.free_act) {
                (void) inc_timed(TMD_PARALYZED, randint0(10) + 5, TRUE);
            } else
                notice_obj(OF_FREE_ACT, 0);
        }

        break;
    }

    /* summoning traps. */
    case FEAT_TRAP_HEAD + 0x05:
    {
        sound(MSG_SUM_MONSTER);
        /* sometimes summon thieves. */
        if ((p_ptr->depth > 8) && (randint1(5) == 1)) {
            msg_print("You have aroused a den of thieves!");

            Rand_quick = FALSE;

            num = 2 + randint1(3);
            for (i = 0; i < num; i++) {
                (void) summon_specific(y, x, FALSE, p_ptr->depth,
                                       SUMMON_THIEF);
            }

            Rand_quick = TRUE;
        }

        /* sometimes summon a nasty unique. */
        else if (randint1(8) == 1) {
            msg_print("You are enveloped in a cloud of smoke!");

            Rand_quick = FALSE;

            (void) summon_specific(y, x, FALSE, p_ptr->depth + 5,
                                   SUMMON_UNIQUE);

            Rand_quick = TRUE;
        }

        /* otherwise, the ordinary summon monsters. */
        else {
            msg_print("You are enveloped in a cloud of smoke!");

            Rand_quick = FALSE;

            num = 2 + randint1(3);
            for (i = 0; i < num; i++) {
                (void) summon_specific(y, x, FALSE, p_ptr->depth, 0);
            }

            Rand_quick = TRUE;
        }

        /* these are all one-time traps. */
        cave_info[y][x] &= ~(CAVE_MARK);
        cave_set_feat(y, x, FEAT_FLOOR);

        break;
    }

    /* dungeon alteration traps. */
    case FEAT_TRAP_HEAD + 0x06:
    {
        /* determine how dangerous the trap is allowed to be. */
        nastyness = randint1(p_ptr->depth);
        if (randint1(5) == 1)
            nastyness += 10;

        /* make room for alterations. */
        cave_info[y][x] &= ~(CAVE_MARK);
        cave_set_feat(y, x, FEAT_FLOOR);

        /* Everything truely random from here on. */
        Rand_quick = FALSE;

        /* dungeon destruction trap. */
        if ((nastyness > 60) && (randint1(12) == 1)) {
            msg_print
            ("A ear-splitting howl shatters your mind as the dungeon is smashed by hammer blows!");

            (void) destroy_level(FALSE);

            /* the player is hard-hit. */
            (void) inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE);
            (void) inc_timed(TMD_BLIND, randint0(30) + 15, TRUE);
            (void) inc_timed(TMD_STUN, randint1(50) + 50, TRUE);
            dam = damroll(15, 15);
            take_hit(dam, name);
        }

        /* earthquake trap. */
        else if ((nastyness > 20) && (randint1(4) == 1)) {
            msg_print("A tremor shakes the earth around you");
            earthquake(y, x, 10, FALSE);
        }

        /* falling rock trap. */
        else if ((nastyness > 4) && (randint1(2) == 1)) {
            msg_print("A rock falls on your head.");
            dam = damroll(2, 10);
            take_hit(dam, name);

            (void) inc_timed(TMD_STUN, randint1(10) + 10, TRUE);
        }

        /* a few pebbles. */
        else {
            msg_print("A bunch of pebbles rain down on you.");
            dam = damroll(1, 8);
            take_hit(dam, name);
        }

        Rand_quick = TRUE;

        break;
    }

    /* various char and equipment-alteration traps, lumped together to
     * avoid any one effect being too common (some of them can be rather
     * nasty). */
    case FEAT_TRAP_HEAD + 0x07:
    {
        /* determine how dangerous the trap is allowed to be. */
        nastyness = randint0(100);

        /* these are all one-time traps. */
        cave_info[y][x] &= ~(CAVE_MARK);
        cave_set_feat(y, x, FEAT_FLOOR);

        /* Everything truely random from here on. */
        Rand_quick = FALSE;

        /* trap of drain wands. */
        if (nastyness < 15) {
            /* Hold the object information. */
            object_type *o_ptr;

            /* Find an item */
            for (i = 0; i < 20; i++) {
                /* Pick an item */
                i = randint0(INVEN_PACK - p_ptr->pack_size_reduce);

                /* Obtain the item */
                o_ptr = &p_ptr->inventory[i];

                /* use "num" to decide if a item can be uncharged.  By
                 * default, assume it can't. */
                num = 0;

                /* Skip non-objects */
                if (!o_ptr->k_idx)
                    continue;

                /* Drain charged wands/staffs/rods */
                if ((o_ptr->tval == TV_STAFF) || (o_ptr->tval == TV_WAND)
                        || (o_ptr->tval == TV_ROD)) {
                    /* case of charged wands/staffs. */
                    if (((o_ptr->tval == TV_STAFF)
                            || (o_ptr->tval == TV_WAND)) && (o_ptr->pval))
                        num = 1;

                    /* case of charged rods. */
                    if ((o_ptr->tval == TV_ROD)
                            && (o_ptr->timeout < randcalc(o_ptr->time, 0,
                                                          MINIMISE)))
                        num = 1;


                    if (num == 1) {
                        /* Message */
                        msg_print("Energy drains from your pack!");

                        /* Uncharge */
                        if ((o_ptr->tval == TV_STAFF)
                                || (o_ptr->tval == TV_WAND))
                            o_ptr->pval = 0;

                        if (o_ptr->tval == TV_ROD)
                            o_ptr->timeout = randcalc(o_ptr->time, 0, RANDOMISE) * o_ptr->number * 2;


                        /* Combine / Reorder the pack */
                        p_ptr->notice |= (PN_COMBINE | PN_REORDER);

                        /* not more than one inventory slot effected. */
                        break;
                    } else
                        continue;
                }
            }
        }

        /* trap of forgetting. */
        else if (nastyness < 35) {
            if (check_save(100)) {
                msg_print("You hang on to your memories!");
            } else if (lose_all_info()) {
                msg_print("Your memories fade away.");
            }
        }

        /* trap of alter reality. */
        else if (nastyness < 50) {
            if (OPT(adult_ironman))
                msg_print("Nothing happens.");
            else {
                msg_print("The world changes!");

                /* Leaving */
                p_ptr->leaving = TRUE;
            }
        }

        /* trap of remold player. */
        else if (nastyness < 75) {
            int max1, cur1, max2, cur2, ii, jj;

            msg_print("You feel yourself being twisted by wild magic!");

            if (check_save(100)) {
                msg_print("You resist the effects!");
            } else {
                msg_print("Your body starts to scramble...");

                /* Pick a pair of stats */
                ii = randint0(6);
                for (jj = ii; jj == ii; jj = randint0(6))	/* loop */
                    ;

                max1 = p_ptr->stat_max[ii];
                cur1 = p_ptr->stat_cur[ii];
                max2 = p_ptr->stat_max[jj];
                cur2 = p_ptr->stat_cur[jj];

                p_ptr->stat_max[ii] = max2;
                p_ptr->stat_cur[ii] = cur2;
                p_ptr->stat_max[jj] = max1;
                p_ptr->stat_cur[jj] = cur1;

                p_ptr->update |= (PU_BONUS);
            }
        }

        /* time ball trap. */
        else if (nastyness < 90) {
            msg_print("You feel time itself assault you!");

            /* Target the player with a radius 0 ball attack. */
            fire_meteor(0, GF_TIME, p_ptr->py, p_ptr->px, 75, 0, TRUE);
        }

        /* trap of bugs gone berserk. */
        else {
            /* explain what the dickens is going on. */
            msg_print("GRUESOME Gnawing Bugs leap out at you!");

            if (!p_resist_good(P_RES_CONFU)) {
                (void) inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE);
            } else
                notice_other(IF_RES_CONFU, 0);

            if (!p_resist_good(P_RES_CHAOS)) {
                (void) inc_timed(TMD_IMAGE, randint1(40), TRUE);
            } else
                notice_other(IF_RES_CHAOS, 0);

            /* XXX (hard coded) summon 3-6 bugs. */
            k = randint1(4) + 2;
            for (i = 0; i < k; ++i) {
                /* Look for a location */
                for (j = 0; j < 20; ++j) {
                    /* Pick a (scattered) distance. */
                    int d = (j / 10) + randint1(3);

                    /* Pick a location */
                    scatter(&y, &x, y, x, d, 0);

                    /* Require passable terrain */
                    if (!cave_passable_bold(y, x))
                        continue;

                    /* Hack -- no summon on glyph of warding */
                    if (cave_feat[y][x] == FEAT_RUNE_PROTECT)
                        continue;

                    /* Okay */
                    break;
                }

                /* Attempt to place the awake bug */
                place_monster_aux(y, x, 453, FALSE, TRUE);
            }

            /* herald the arrival of bugs. */
            msg_print("AAAAAAAHHHH! THEY'RE EVERYWHERE!");
        }

        Rand_quick = TRUE;

        break;
    }

    /* teleport trap */
    case FEAT_TRAP_HEAD + 0x08:
    {
        if (stage_map[p_ptr->stage][STAGE_TYPE] >= CAVE)
            msg_print("You teleport across the dungeon.");
        else
            msg_print("You teleport across the wilderness.");

        Rand_quick = FALSE;

        teleport_player(250, FALSE);

        Rand_quick = TRUE;

        break;
    }

    /* murder holes. */
    case FEAT_TRAP_HEAD + 0x09:
    {
        /* hold the object info. */
        object_type *o_ptr;
        object_type object_type_body;

        /* hold the missile type and name. */
        int sval = 0;
        int tval = 0;
        cptr missile_name = "";



        /* Determine the missile type and base damage. */
        if (randint1(3) == 1) {
            if (p_ptr->depth < 40) {
                missile_name = "shot";
                dam = damroll(2, 3);
                tval = TV_SHOT;
                sval = SV_AMMO_NORMAL;
            } else {
                missile_name = "seeker shot";
                dam = damroll(3, 7);
                tval = TV_SHOT;
                sval = SV_AMMO_HEAVY;
            }
        }

        else if (randint1(2) == 1) {
            if (p_ptr->depth < 55) {
                missile_name = "arrow";
                dam = damroll(2, 4);
                tval = TV_ARROW;
                sval = SV_AMMO_NORMAL;
            } else {
                missile_name = "seeker arrow";
                dam = damroll(3, 9);
                tval = TV_ARROW;
                sval = SV_AMMO_HEAVY;
            }
        }

        else {
            if (p_ptr->depth < 65) {
                missile_name = "bolt";
                dam = damroll(2, 5);
                tval = TV_BOLT;
                sval = SV_AMMO_NORMAL;
            } else {
                missile_name = "seeker bolt";
                dam = damroll(3, 11);
                tval = TV_BOLT;
                sval = SV_AMMO_HEAVY;
            }
        }

        /* determine if the missile hits. */
        if (check_trap_hit(75 + p_ptr->depth)) {
            msg_format("A %s hits you from above.", missile_name);

            Rand_quick = FALSE;

            /* critical hits. */
            if (randint1(2) == 1) {
                msg_print("It was well-aimed!");
                dam *= 1 + randint1(2);
            }
            if (randint1(2) == 1) {
                msg_print("It gouges you!");
                dam = 3 * dam / 2;

                /* cut the player. */
                (void) inc_timed(TMD_CUT, randint1(dam), TRUE);
            }

            Rand_quick = TRUE;

            take_hit(dam, name);
        }

        /* Explain what just happened. */
        else
            msg_format("A %s wizzes by your head.", missile_name);

        /* these will eventually run out of ammo. */

        Rand_quick = FALSE;

        if (randint0(8) == 0) {
            cave_info[y][x] &= ~(CAVE_MARK);
            cave_set_feat(y, x, FEAT_FLOOR);
        }

        Rand_quick = TRUE;

        /* Get local object */
        o_ptr = &object_type_body;

        /* Make a missile, identify it, and drop it near the player. */
        object_prep(o_ptr, lookup_kind(tval, sval), MINIMISE);
        object_aware(o_ptr);
        object_known(o_ptr);
        drop_near(o_ptr, -1, y, x, TRUE);

        break;
    }

    /* falling tree branch */
    case FEAT_TRAP_HEAD + 0x0A:
    {
        /* determine if the missile hits. */
        if (check_trap_hit(75 + p_ptr->depth)) {
            /* Take damage */
            dam = damroll(3, 5);
            msg_print("A branch hits you from above.");

            Rand_quick = FALSE;

            /* critical hits. */
            if (randint1(2) == 1) {
                msg_print("It was heavy!");
                dam = 3 * dam / 2;

                /* stun the player. */
                (void) inc_timed(TMD_STUN, randint1(dam), TRUE);
            }

            Rand_quick = TRUE;

            take_hit(dam, name);
        }

        /* Explain what just happened. */
        else
            msg_print("A falling branch just misses you.");

        /* No more */
        cave_info[y][x] &= ~(CAVE_MARK);
        cave_set_feat(y, x, FEAT_TREE);

        break;
    }

    /* falling tree branch */
    case FEAT_TRAP_HEAD + 0x0B:
    {
        /* determine if the missile hits. */
        if (check_trap_hit(75 + p_ptr->depth)) {
            /* Take damage */
            dam = damroll(3, 5);
            msg_print("A branch hits you from above.");

            Rand_quick = FALSE;

            /* critical hits. */
            if (randint1(2) == 1) {
                msg_print("It was heavy!");
                dam = 3 * dam / 2;

                /* stun the player. */
                (void) inc_timed(TMD_STUN, randint1(dam), TRUE);
            }

            Rand_quick = TRUE;

            take_hit(dam, name);
        }

        /* Explain what just happened. */
        else
            msg_print("A falling branch just misses you.");

        /* No more */
        cave_info[y][x] &= ~(CAVE_MARK);
        cave_set_feat(y, x, FEAT_TREE2);

        break;
    }

    /* undefined trap. */
    case FEAT_TRAP_HEAD + 0x0C:
    {
        msg_print("A dagger is thrown at you from the shadows!");
        dam = damroll(3, 4);
        take_hit(dam, name);

        break;
    }

    /* undefined trap. */
    case FEAT_TRAP_HEAD + 0x0D:
    {
        msg_print("A dagger is thrown at you from the shadows!");
        dam = damroll(3, 4);
        take_hit(dam, name);

        break;
    }

    /* undefined trap. */
    case FEAT_TRAP_HEAD + 0x0E:
    {
        msg_print("A dagger is thrown at you from the shadows!");
        dam = damroll(3, 4);
        take_hit(dam, name);

        break;
    }

    /* undefined trap. */
    case FEAT_TRAP_HEAD + 0x0F:
    {
        msg_print("A dagger is thrown at you from the shadows!");
        dam = damroll(3, 4);
        take_hit(dam, name);

        break;
    }

    }

    /* Revert to usage of the complex RNG. */
    Rand_quick = FALSE;
}
Beispiel #12
0
/*
 * Chests have traps too.  High-level chests can be very dangerous, no
 * matter what level they are opened at.  Various traps added in Oangband. -LM-
 *
 * Exploding chest destroys contents (and traps).
 * Note that the chest itself is never destroyed.
 */
static void chest_trap(int y, int x, s16b o_idx)
{
	int i, trap, nasty_tricks_count;
	int j;

	object_type *o_ptr = &o_list[o_idx];

	/* Compensate for the averaging routine in the summon monster function. */
	int summon_level = o_ptr->pval + o_ptr->pval - p_ptr->depth;

	/* Ignore disarmed chests */
	if (o_ptr->pval <= 0) return;

	/* Obtain the traps */
	trap = chest_traps[o_ptr->pval];

	/* Lose strength */
	if (trap & (CHEST_LOSE_STR))
	{
		msg_print("A small needle has pricked you!");
		take_hit(damroll(1, 4), "a poison needle");
		(void)do_dec_stat(A_STR);
	}

	/* Lose constitution */
	if (trap & (CHEST_LOSE_CON))
	{
		msg_print("A small needle has pricked you!");
		take_hit(damroll(1, 4), "a poison needle");
		(void)do_dec_stat(A_CON);
	}

	/* Poison */
	if (trap & (CHEST_POISON))
	{
		msg_print("A puff of green gas surrounds you!");
		pois_hit(25);
	}

	/* Paralyze */
	if (trap & (CHEST_PARALYZE))
	{
		msg_print("A puff of yellow gas surrounds you!");
		if (!p_ptr->free_act)
		{
			(void)set_paralyzed(p_ptr->paralyzed + 10 + randint1(20));
		}
	}

	/* Summon monsters */
	if (trap & (CHEST_SUMMON))
	{
		int num = 2 + randint1(3);
		msg_print("You are enveloped in a cloud of smoke!");
		(void)summon_specific(y, x, FALSE, summon_level, 0, num);
	}

	/* Explode */
	if (trap & (CHEST_EXPLODE))
	{
		msg_print("There is a sudden explosion!");
		msg_print("Everything inside the chest is destroyed!");
		o_ptr->pval = 0;
		take_hit(damroll(5, 8), "an exploding chest");
	}

	/* Scatter contents. */
	if (trap & (CHEST_SCATTER))
	{
		msg_print("The contents of the chest scatter all over the dungeon!");
		chest_death(TRUE, y, x, o_idx);
		o_ptr->pval = 0;
	}

	/* Elemental summon. */
	if (trap & (CHEST_E_SUMMON))
	{
		j = randint1(3) + 5;
		msg_print("Elemental beings appear to protect their treasures!");
		(void) summon_specific(y, x, FALSE, summon_level, SUMMON_ELEMENTAL, j);
	}

	/* Force clouds, then summon birds. */
	if (trap & (CHEST_BIRD_STORM))
	{
		msg_print("A storm of birds swirls around you!");

		j = randint1(3) + 3;
		for (i = 0; i < j; i++)
			(void)fire_meteor(0, GF_FORCE, y, x, o_ptr->pval / 5, 7, TRUE);

		j = randint1(5) + o_ptr->pval /5;
		(void)summon_specific(y, x, TRUE, summon_level, SUMMON_BIRD, j);
	}

	/* Various colorful summonings. */
	if (trap & (CHEST_H_SUMMON))
	{
		/* Summon demons. */
		if (randint0(4) == 0)
		{
			msg_print("Demons materialize in clouds of fire and brimstone!");

			j = randint1(3) + 2;
			for (i = 0; i < j; i++)
			{
				(void)fire_meteor(0, GF_FIRE, y, x, 10, 5, TRUE);
				(void)summon_specific(y, x, FALSE, summon_level, SUMMON_DEMON, 1);
			}
		}

		/* Summon dragons. */
		else if (randint0(3) == 0)
		{
			msg_print("Draconic forms loom out of the darkness!");

			j = randint1(3) + 2;
			(void)summon_specific(y, x, FALSE, summon_level, SUMMON_DRAGON, j);
		}

		/* Summon hybrids. */
		else if (randint0(2) == 0)
		{
			msg_print("Creatures strange and twisted assault you!");

			j = randint1(5) + 3;
			(void)summon_specific(y, x, FALSE, summon_level, SUMMON_HYBRID, j);
		}

		/* Summon vortices (scattered) */
		else
		{
			msg_print("Vortices coalesce and wreak destruction!");

			j = randint1(3) + 2;
			(void)summon_specific(y, x, TRUE, summon_level, SUMMON_VORTEX, j);
		}
	}

	/* Dispel player. */
	if (trap & (CHEST_RUNES_OF_EVIL))
	{
		/* Message. */
		msg_print("Hideous voices bid: 'Let the darkness have thee!'");

		/* Determine how many nasty tricks can be played. */
		nasty_tricks_count = 4 + randint0(3);

		/* This is gonna hurt... */
		for (; nasty_tricks_count > 0; nasty_tricks_count--)
		{
			/* ...but a high saving throw does help a little. */
			if (!check_save(2 * o_ptr->pval))
			{
				if (randint0(6) == 0) take_hit(damroll(5, 20), "a chest dispel-player trap");
				else if (randint0(5) == 0) (void)set_cut(p_ptr->cut + 200);
				else if (randint0(4) == 0)
				{
					if (!p_ptr->free_act)
						(void)set_paralyzed(p_ptr->paralyzed + 2 +
						randint0(6));
					else
						(void)set_stun(p_ptr->stun + 10 +
						randint0(100));
				}
				else if (randint0(3) == 0) apply_disenchant(0);
				else if (randint0(2) == 0)
				{
					(void)do_dec_stat(A_STR);
					(void)do_dec_stat(A_DEX);
					(void)do_dec_stat(A_CON);
					(void)do_dec_stat(A_INT);
					(void)do_dec_stat(A_WIS);
					(void)do_dec_stat(A_CHR);
				}
				else (void)fire_meteor(0, GF_NETHER, y, x, 150, 1, TRUE);
			}
		}
	}
}
Beispiel #13
0
/*
 * Handle player hitting a real trap
 */
void hit_trap(int y, int x)
{
	int i, num, dam;

	const char *name = "a trap";


	/* Disturb the player */
	disturb(0, 0);

	/* Analyze XXX XXX XXX */
	switch (cave->feat[y][x])
	{
		case FEAT_TRAP_HEAD + 0x00:
		{
			msg("You fall through a trap door!");
			if (p_ptr->state.flags[OF_FEATHER])
			{
				msg("You float gently down to the next level.");
			}
			else
			{
				dam = damroll(2, 8);
				take_hit(dam, name);
			}
			wieldeds_notice_flag(OF_FEATHER);

			/* New depth */
			dungeon_change_level(p_ptr->depth + 1);
			
			break;
		}

		case FEAT_TRAP_HEAD + 0x01:
		{
			msg("You fall into a pit!");
			if (p_ptr->state.flags[OF_FEATHER])
			{
				msg("You float gently to the bottom of the pit.");
			}
			else
			{
				dam = damroll(2, 6);
				take_hit(dam, name);
			}
			wieldeds_notice_flag(OF_FEATHER);
			break;
		}

		case FEAT_TRAP_HEAD + 0x02:
		{
			msg("You fall into a spiked pit!");

			if (p_ptr->state.flags[OF_FEATHER])
			{
				msg("You float gently to the floor of the pit.");
				msg("You carefully avoid touching the spikes.");
			}
			else
			{
				/* Base damage */
				dam = damroll(2, 6);

				/* Extra spike damage */
				if (one_in_(2))
				{
					msg("You are impaled!");

					dam = dam * 2;
					(void)inc_timed(TMD_CUT, randint1(dam), TRUE);
				}

				/* Take the damage */
				take_hit(dam, name);
			}
			wieldeds_notice_flag(OF_FEATHER);
			break;
		}

		case FEAT_TRAP_HEAD + 0x03:
		{
			msg("You fall into a spiked pit!");

			if (p_ptr->state.flags[OF_FEATHER])
			{
				msg("You float gently to the floor of the pit.");
				msg("You carefully avoid touching the spikes.");
			}
			else
			{
				/* Base damage */
				dam = damroll(2, 6);

				/* Extra spike damage */
				if (one_in_(2))
				{
					msg("You are impaled on poisonous spikes!");

					dam = dam * 2;
					(void)inc_timed(TMD_CUT, randint1(dam), TRUE);

					if (p_ptr->state.flags[OF_RES_POIS] || p_ptr->timed[TMD_OPP_POIS])
					{
						msg("The poison does not affect you!");
					}
					else
					{
						dam = dam * 2;
						(void)inc_timed(TMD_POISONED, randint1(dam), TRUE);
					}

					wieldeds_notice_flag(OF_RES_POIS);
				}

				/* Take the damage */
				take_hit(dam, name);
			}
			wieldeds_notice_flag(OF_FEATHER);

			break;
		}

		case FEAT_TRAP_HEAD + 0x04:
		{
			sound(MSG_SUM_MONSTER);
			msg("You are enveloped in a cloud of smoke!");
			cave->info[y][x] &= ~(CAVE_MARK);
			cave_set_feat(cave, y, x, FEAT_FLOOR);
			num = 2 + randint1(3);
			for (i = 0; i < num; i++)
			{
				(void)summon_specific(y, x, p_ptr->depth, 0, 1);
			}
			break;
		}

		case FEAT_TRAP_HEAD + 0x05:
		{
			msg("You hit a teleport trap!");
			teleport_player(100);
			break;
		}

		case FEAT_TRAP_HEAD + 0x06:
		{
			msg("You are enveloped in flames!");
			dam = damroll(4, 6);
			fire_dam(dam, "a fire trap");
			break;
		}

		case FEAT_TRAP_HEAD + 0x07:
		{
			msg("You are splashed with acid!");
			dam = damroll(4, 6);
			acid_dam(dam, "an acid trap");
			break;
		}

		case FEAT_TRAP_HEAD + 0x08:
		{
			if (trap_check_hit(125))
			{
				msg("A small dart hits you!");
				dam = damroll(1, 4);
				take_hit(dam, name);
				(void)inc_timed(TMD_SLOW, randint0(20) + 20, TRUE);
			}
			else
			{
				msg("A small dart barely misses you.");
			}
			break;
		}

		case FEAT_TRAP_HEAD + 0x09:
		{
			if (trap_check_hit(125))
			{
				msg("A small dart hits you!");
				dam = damroll(1, 4);
				take_hit(dam, name);
				(void)do_dec_stat(A_STR, FALSE);
			}
			else
			{
				msg("A small dart barely misses you.");
			}
			break;
		}

		case FEAT_TRAP_HEAD + 0x0A:
		{
			if (trap_check_hit(125))
			{
				msg("A small dart hits you!");
				dam = damroll(1, 4);
				take_hit(dam, name);
				(void)do_dec_stat(A_DEX, FALSE);
			}
			else
			{
				msg("A small dart barely misses you.");
			}
			break;
		}

		case FEAT_TRAP_HEAD + 0x0B:
		{
			if (trap_check_hit(125))
			{
				msg("A small dart hits you!");
				dam = damroll(1, 4);
				take_hit(dam, name);
				(void)do_dec_stat(A_CON, FALSE);
			}
			else
			{
				msg("A small dart barely misses you.");
			}
			break;
		}

		case FEAT_TRAP_HEAD + 0x0C:
		{
			msg("You are surrounded by a black gas!");
			if (!p_ptr->state.flags[OF_RES_BLIND])
				(void)inc_timed(TMD_BLIND, randint0(50) + 25, TRUE);
			wieldeds_notice_flag(OF_RES_BLIND);

			break;
		}

		case FEAT_TRAP_HEAD + 0x0D:
		{
			msg("You are surrounded by a gas of scintillating colors!");
			if (!p_ptr->state.flags[OF_RES_CONFU])
				(void)inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE);
			wieldeds_notice_flag(OF_RES_CONFU);

			break;
		}

		case FEAT_TRAP_HEAD + 0x0E:
		{
			msg("You are surrounded by a pungent green gas!");
			if (!p_ptr->state.flags[OF_RES_POIS] && !p_ptr->timed[TMD_OPP_POIS])
				(void)inc_timed(TMD_POISONED, randint0(20) + 10, TRUE);
			wieldeds_notice_flag(OF_RES_POIS);

			break;
		}

		case FEAT_TRAP_HEAD + 0x0F:
		{
			msg("You are surrounded by a strange white mist!");
			if (!p_ptr->state.flags[OF_FREE_ACT])
				(void)inc_timed(TMD_PARALYZED, randint0(10) + 5, TRUE);
			wieldeds_notice_flag(OF_FREE_ACT);

			break;
		}
	}
}
void chaos_warrior_reward(void)
{
    if (one_in_(6))
    {
        msg_format("%^s rewards you with a mutation!",
            chaos_patrons[p_ptr->chaos_patron]);

        mut_gain_random(NULL);
    }
    else
    {
        char        wrath_reason[32] = "";
        int         nasty_chance = 6;
        int         dummy = 0, dummy2 = 0;
        int         type, effect;
        int         count = 0;

        if (p_ptr->lev == 13) nasty_chance = 2;
        else if (!(p_ptr->lev % 13)) nasty_chance = 3;
        else if (!(p_ptr->lev % 14)) nasty_chance = 12;

        if (one_in_(nasty_chance))
            type = randint1(20); /* Allow the 'nasty' effects */
        else
            type = randint1(15) + 5; /* Or disallow them */

        if (type < 1) type = 1;
        if (type > 20) type = 20;
        type--;

        sprintf(wrath_reason, "the Wrath of %s",
            chaos_patrons[p_ptr->chaos_patron]);

        effect = chaos_rewards[p_ptr->chaos_patron][type];
        switch (effect)
        {
        case REW_POLY_SLF:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Thou needst a new form, mortal!'");

            do_poly_self();
            break;
        case REW_GAIN_EXP:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Well done, mortal! Lead on!'");
            if (p_ptr->prace == RACE_ANDROID)
                msg_print("But, nothing happen.");
            else if (p_ptr->exp < PY_MAX_EXP)
            {
                s32b ee = (p_ptr->exp / 2) + 10;
                if (ee > 100000L) ee = 100000L;
                msg_print("You feel more experienced.");
                gain_exp(ee);
            }
            break;
        case REW_LOSE_EXP:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Thou didst not deserve that, slave.'");

            if (p_ptr->prace == RACE_ANDROID)
                msg_print("But, nothing happen.");
            else
            {
                lose_exp(p_ptr->exp / 6);
            }
            break;
        case REW_GOOD_OBJ:
            msg_format("The voice of %s whispers:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Use my gift wisely.'");
            acquirement(py, px, 1, FALSE, FALSE);
            break;
        case REW_GREA_OBJ:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Use my gift wisely.'");

            acquirement(py, px, 1, TRUE, FALSE);
            break;
        case REW_CHAOS_WP:
        {
            object_type forge;

            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Thy deed hath earned thee a worthy blade.'");

            dummy = TV_SWORD;
            switch (randint1(p_ptr->lev))
            {
                case 0: case 1:
                    dummy2 = SV_DAGGER;
                    break;
                case 2: case 3:
                    dummy2 = SV_MAIN_GAUCHE;
                    break;
                case 4:
                    dummy2 = SV_TANTO;
                    break;
                case 5: case 6:
                    dummy2 = SV_RAPIER;
                    break;
                case 7: case 8:
                    dummy2 = SV_SMALL_SWORD;
                    break;
                case 9: case 10:
                    dummy2 = SV_BASILLARD;
                    break;
                case 11: case 12: case 13:
                    dummy2 = SV_SHORT_SWORD;
                    break;
                case 14: case 15:
                    dummy2 = SV_SABRE;
                    break;
                case 16: case 17:
                    dummy2 = SV_CUTLASS;
                    break;
                case 18:
                    dummy2 = SV_WAKIZASHI;
                    break;
                case 19:
                    dummy2 = SV_KHOPESH;
                    break;
                case 20:
                    dummy2 = SV_TULWAR;
                    break;
                case 21:
                    dummy2 = SV_BROAD_SWORD;
                    break;
                case 22: case 23:
                    dummy2 = SV_LONG_SWORD;
                    break;
                case 24: case 25:
                    dummy2 = SV_SCIMITAR;
                    break;
                case 26:
                    dummy2 = SV_NINJATO;
                    break;
                case 27:
                    dummy2 = SV_KATANA;
                    break;
                case 28: case 29:
                    dummy2 = SV_BASTARD_SWORD;
                    break;
                case 30:
                    dummy2 = SV_GREAT_SCIMITAR;
                    break;
                case 31:
                    dummy2 = SV_CLAYMORE;
                    break;
                case 32:
                    dummy2 = SV_ESPADON;
                    break;
                case 33:
                    dummy2 = SV_TWO_HANDED_SWORD;
                    break;
                case 34:
                    dummy2 = SV_FLAMBERGE;
                    break;
                case 35:
                    dummy2 = SV_NO_DACHI;
                    break;
                case 36:
                    dummy2 = SV_EXECUTIONERS_SWORD;
                    break;
                case 37:
                    dummy2 = SV_ZWEIHANDER;
                    break;
                case 38:
                    dummy2 = SV_HAYABUSA;
                    break;
                default:
                    dummy2 = SV_BLADE_OF_CHAOS;
            }

            object_prep(&forge, lookup_kind(dummy, dummy2));
            forge.to_h = 3 + randint1(dun_level) % 10;
            forge.to_d = 3 + randint1(dun_level) % 10;
            one_resistance(&forge);
            forge.name2 = EGO_WEAPON_CHAOS;

            drop_near(&forge, -1, py, px);
            break;
        }
        case REW_GOOD_OBS:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Thy deed hath earned thee a worthy reward.'");

            acquirement(py, px, randint1(2) + 1, FALSE, FALSE);
            break;
        case REW_GREA_OBS:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Behold, mortal, how generously I reward thy loyalty.'");

            acquirement(py, px, randint1(2) + 1, TRUE, FALSE);
            break;
        case REW_TY_CURSE:
            msg_format("The voice of %s thunders:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Thou art growing arrogant, mortal.'");

            activate_ty_curse(FALSE, &count);
            break;
        case REW_SUMMON_M:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'My pets, destroy the arrogant mortal!'");
            for (dummy = 0; dummy < randint1(5) + 1; dummy++)
                summon_specific(0, py, px, dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET));
            break;
        case REW_H_SUMMON:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Thou needst worthier opponents!'");
            activate_hi_summon(py, px, FALSE);
            break;
        case REW_DO_HAVOC:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Death and destruction! This pleaseth me!'");
            call_chaos(100);
            break;
        case REW_GAIN_ABL:
            msg_format("The voice of %s rings out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Stay, mortal, and let me mold thee.'");
            if (one_in_(3) && !(chaos_stats[p_ptr->chaos_patron] < 0))
                do_inc_stat(chaos_stats[p_ptr->chaos_patron]);
            else
                do_inc_stat(randint0(6));
            break;
        case REW_LOSE_ABL:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'I grow tired of thee, mortal.'");

            if (one_in_(3) && !(chaos_stats[p_ptr->chaos_patron] < 0))
                do_dec_stat(chaos_stats[p_ptr->chaos_patron]);
            else
                do_dec_stat(randint0(6));
            break;
        case REW_RUIN_ABL:
            msg_format("The voice of %s thunders:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Thou needst a lesson in humility, mortal!'");
            msg_print("You feel less powerful!");

            for (dummy = 0; dummy < 6; dummy++)
                dec_stat(dummy, 10 + randint1(15), TRUE);
            break;
        case REW_POLY_WND:
            msg_format("You feel the power of %s touch you.", chaos_patrons[p_ptr->chaos_patron]);
            do_poly_wounds();
            break;
        case REW_AUGM_ABL:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Receive this modest gift from me!'");
            for (dummy = 0; dummy < 6; dummy++)
                do_inc_stat(dummy);
            break;
        case REW_HURT_LOT:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Suffer, pathetic fool!'");
            fire_ball(GF_DISINTEGRATE, 0, p_ptr->lev * 4, 4);
            take_hit(DAMAGE_NOESCAPE, p_ptr->lev * 4, wrath_reason, -1);
            break;
       case REW_HEAL_FUL:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Rise, my servant!'");
            restore_level();
            set_poisoned(0, TRUE);
            set_blind(0, TRUE);
            set_confused(0, TRUE);
            set_image(0, TRUE);
            set_stun(0, TRUE);
            set_cut(0, TRUE);
            hp_player(5000);
            for (dummy = 0; dummy < 6; dummy++)
                do_res_stat(dummy);
            break;
        case REW_CURSE_WP:
        {
            int slot = equip_random_slot(object_is_melee_weapon);
            if (slot)
            {
                msg_format("The voice of %s booms out:",
                    chaos_patrons[p_ptr->chaos_patron]);
                msg_print("'Thou reliest too much on thy weapon.'");
                curse_weapon(FALSE, slot);
            }
            break;
        }
        case REW_CURSE_AR:
        {
            int slot = equip_random_slot(object_is_armour);
            if (slot)
            {
                msg_format("The voice of %s booms out:",
                    chaos_patrons[p_ptr->chaos_patron]);
                msg_print("'Thou reliest too much on thine equipment.'");
                curse_armor(slot);
            }
            break;
        }
        case REW_PISS_OFF:
            msg_format("The voice of %s whispers:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Now thou shalt pay for annoying me.'");
            switch (randint1(4))
            {
                case 1:
                    activate_ty_curse(FALSE, &count);
                    break;
                case 2:
                    activate_hi_summon(py, px, FALSE);
                    break;
                case 3:
                    if (one_in_(2))
                    {
                        int slot = equip_random_slot(object_is_melee_weapon);
                        if (slot)
                            curse_weapon(FALSE, slot);
                    }
                    else
                    {
                        int slot = equip_random_slot(object_is_armour);
                        if (slot)
                            curse_armor(slot);
                    }
                    break;
                default:
                    for (dummy = 0; dummy < 6; dummy++)
                        dec_stat(dummy, 10 + randint1(15), TRUE);
                    break;
            }
            break;
        case REW_WRATH:
            msg_format("The voice of %s thunders:", chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Die, mortal!'");

            take_hit(DAMAGE_LOSELIFE, p_ptr->lev * 4, wrath_reason, -1);
            for (dummy = 0; dummy < 6; dummy++)
                dec_stat(dummy, 10 + randint1(15), FALSE);
            activate_hi_summon(py, px, FALSE);
            activate_ty_curse(FALSE, &count);
            if (one_in_(2))
            {
                int slot = equip_random_slot(object_is_melee_weapon);
                if (slot)
                    curse_weapon(FALSE, slot);
            }
            if (one_in_(2))
            {
                int slot = equip_random_slot(object_is_armour);
                if (slot)
                    curse_armor(slot);
            }
            break;
        case REW_DESTRUCT:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Death and destruction! This pleaseth me!'");
            destroy_area(py, px, 25, 3 * p_ptr->lev);
            break;
        case REW_GENOCIDE:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Let me relieve thee of thine oppressors!'");
            symbol_genocide(0, FALSE);
            break;
        case REW_MASS_GEN:
            msg_format("The voice of %s booms out:",
                chaos_patrons[p_ptr->chaos_patron]);
            msg_print("'Let me relieve thee of thine oppressors!'");
            mass_genocide(0, FALSE);
            break;
        case REW_DISPEL_C:
            msg_format("You can feel the power of %s assault your enemies!",
                chaos_patrons[p_ptr->chaos_patron]);
            dispel_monsters(p_ptr->lev * 4);
            break;
        case REW_IGNORE:
            msg_format("%s ignores you.",
                chaos_patrons[p_ptr->chaos_patron]);
            break;
        case REW_SER_DEMO:
            msg_format("%s rewards you with a demonic servant!",chaos_patrons[p_ptr->chaos_patron]);
            if (!summon_specific(-1, py, px, dun_level, SUMMON_DEMON, PM_FORCE_PET))
                msg_print("Nobody ever turns up...");
            break;
        case REW_SER_MONS:
            msg_format("%s rewards you with a servant!",chaos_patrons[p_ptr->chaos_patron]);
            if (!summon_specific(-1, py, px, dun_level, 0, PM_FORCE_PET))
                msg_print("Nobody ever turns up...");
            break;
        case REW_SER_UNDE:
            msg_format("%s rewards you with an undead servant!",chaos_patrons[p_ptr->chaos_patron]);
            if (!summon_specific(-1, py, px, dun_level, SUMMON_UNDEAD, PM_FORCE_PET))
                msg_print("Nobody ever turns up...");
            break;
        default:
            msg_format("The voice of %s stammers:", chaos_patrons[p_ptr->chaos_patron]);
            msg_format("'Uh... uh... the answer's %d/%d, what's the question?'", type, effect);
        }
    }
}
static bool quaff_potion(object_type *o_ptr, bool *ident)
{
	/* Analyze the potion */
	switch (o_ptr->sval)
	{
		case SV_POTION_WATER:
		case SV_POTION_APPLE_JUICE:
		case SV_POTION_SLIME_MOLD:
		{
			msg_print("Вы утолили жажду.");
			*ident = TRUE;
			break;
		}

		case SV_POTION_SLOWNESS:
		{
			if (set_slow(p_ptr->slow + randint(25) + 15)) *ident = TRUE;
			break;
		}

		case SV_POTION_SALT_WATER:
		{
			msg_print("Вя-а-а! Вас стошнило!");
			(void)set_food(PY_FOOD_STARVE - 1);
			(void)set_poisoned(0);
			(void)set_paralyzed(p_ptr->paralyzed + 4);
			*ident = TRUE;
			break;
		}

		case SV_POTION_POISON:
		{
			if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
			{
				if (set_poisoned(p_ptr->poisoned + rand_int(15) + 10))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_POTION_BLINDNESS:
		{
			if (!p_ptr->resist_blind)
			{
				if (set_blind(p_ptr->blind + rand_int(100) + 100))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_POTION_CONFUSION:
		{
			if (!p_ptr->resist_confu)
			{
				if (set_confused(p_ptr->confused + rand_int(20) + 15))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_POTION_SLEEP:
		{
			if (!p_ptr->free_act)
			{
				if (set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4))
				{
					*ident = TRUE;
				}
			}
			break;
		}

		case SV_POTION_LOSE_MEMORIES:
		{
			if (!p_ptr->hold_life && (p_ptr->exp > 0))
			{
				msg_print("Ваша жизнь меркнет.");
				lose_exp(p_ptr->exp / 4);
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_RUINATION:
		{
			msg_print("Ваши нервы и мускулы кажутся слабыми и безжизненными!");
			take_hit(damroll(10, 10), "зельем Ослабевания");
			(void)dec_stat(A_DEX, 25, TRUE);
			(void)dec_stat(A_WIS, 25, TRUE);
			(void)dec_stat(A_CON, 25, TRUE);
			(void)dec_stat(A_STR, 25, TRUE);
			(void)dec_stat(A_CHR, 25, TRUE);
			(void)dec_stat(A_INT, 25, TRUE);
			*ident = TRUE;
			break;
		}

		case SV_POTION_DEC_STR:
		{
			if (do_dec_stat(A_STR)) *ident = TRUE;
			break;
		}

		case SV_POTION_DEC_INT:
		{
			if (do_dec_stat(A_INT)) *ident = TRUE;
			break;
		}

		case SV_POTION_DEC_WIS:
		{
			if (do_dec_stat(A_WIS)) *ident = TRUE;
			break;
		}

		case SV_POTION_DEC_DEX:
		{
			if (do_dec_stat(A_DEX)) *ident = TRUE;
			break;
		}

		case SV_POTION_DEC_CON:
		{
			if (do_dec_stat(A_CON)) *ident = TRUE;
			break;
		}

		case SV_POTION_DEC_CHR:
		{
			if (do_dec_stat(A_CHR)) *ident = TRUE;
			break;
		}

		case SV_POTION_DETONATIONS:
		{
			msg_print("Массивные взрывы сотрясают ваше тело!");
			take_hit(damroll(50, 20), "зельем взрыва");
			(void)set_stun(p_ptr->stun + 75);
			(void)set_cut(p_ptr->cut + 5000);
			*ident = TRUE;
			break;
		}

		case SV_POTION_DEATH:
		{
			msg_print("Чувство Смерти протекает сквозь вас...");
			take_hit(5000, "зельем Смерти");
			*ident = TRUE;
			break;
		}

		case SV_POTION_INFRAVISION:
		{
			if (set_tim_infra(p_ptr->tim_infra + 100 + randint(100)))
			{
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_DETECT_INVIS:
		{
			if (set_tim_invis(p_ptr->tim_invis + 12 + randint(12)))
			{
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_SLOW_POISON:
		{
			if (set_poisoned(p_ptr->poisoned / 2)) *ident = TRUE;
			break;
		}

		case SV_POTION_CURE_POISON:
		{
			if (set_poisoned(0)) *ident = TRUE;
			break;
		}

		case SV_POTION_BOLDNESS:
		{
			if (set_afraid(0)) *ident = TRUE;
			break;
		}

		case SV_POTION_SPEED:
		{
			if (!p_ptr->fast)
			{
				if (set_fast(randint(25) + 15)) *ident = TRUE;
			}
			else
			{
				(void)set_fast(p_ptr->fast + 5);
			}
			break;
		}

		case SV_POTION_RESIST_HEAT:
		{
			if (set_oppose_fire(p_ptr->oppose_fire + randint(10) + 10))
			{
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_RESIST_COLD:
		{
			if (set_oppose_cold(p_ptr->oppose_cold + randint(10) + 10))
			{
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_HEROISM:
		{
			if (hp_player(10)) *ident = TRUE;
			if (set_afraid(0)) *ident = TRUE;
			if (set_hero(p_ptr->hero + randint(25) + 25)) *ident = TRUE;
			break;
		}

		case SV_POTION_BERSERK_STRENGTH:
		{
			if (hp_player(30)) *ident = TRUE;
			if (set_afraid(0)) *ident = TRUE;
			if (set_shero(p_ptr->shero + randint(25) + 25)) *ident = TRUE;
			break;
		}

		case SV_POTION_CURE_LIGHT:
		{
			if (hp_player(damroll(2, 8))) *ident = TRUE;
			if (set_blind(0)) *ident = TRUE;
			if (set_cut(p_ptr->cut - 10)) *ident = TRUE;
			break;
		}

		case SV_POTION_CURE_SERIOUS:
		{
			if (hp_player(damroll(4, 8))) *ident = TRUE;
			if (set_blind(0)) *ident = TRUE;
			if (set_confused(0)) *ident = TRUE;
			if (set_cut((p_ptr->cut / 2) - 50)) *ident = TRUE;
			break;
		}

		case SV_POTION_CURE_CRITICAL:
		{
			if (hp_player(damroll(6, 8))) *ident = TRUE;
			if (set_blind(0)) *ident = TRUE;
			if (set_confused(0)) *ident = TRUE;
			if (set_poisoned(0)) *ident = TRUE;
			if (set_stun(0)) *ident = TRUE;
			if (set_cut(0)) *ident = TRUE;
			break;
		}

		case SV_POTION_HEALING:
		{
			if (hp_player(300)) *ident = TRUE;
			if (set_blind(0)) *ident = TRUE;
			if (set_confused(0)) *ident = TRUE;
			if (set_poisoned(0)) *ident = TRUE;
			if (set_stun(0)) *ident = TRUE;
			if (set_cut(0)) *ident = TRUE;
			break;
		}

		case SV_POTION_STAR_HEALING:
		{
			if (hp_player(1200)) *ident = TRUE;
			if (set_blind(0)) *ident = TRUE;
			if (set_confused(0)) *ident = TRUE;
			if (set_poisoned(0)) *ident = TRUE;
			if (set_stun(0)) *ident = TRUE;
			if (set_cut(0)) *ident = TRUE;
			break;
		}

		case SV_POTION_LIFE:
		{
			msg_print("Чуство Жизни протекает в вас!");
			restore_level();
			(void)set_poisoned(0);
			(void)set_blind(0);
			(void)set_confused(0);
			(void)set_image(0);
			(void)set_stun(0);
			(void)set_cut(0);
			(void)do_res_stat(A_STR);
			(void)do_res_stat(A_CON);
			(void)do_res_stat(A_DEX);
			(void)do_res_stat(A_WIS);
			(void)do_res_stat(A_INT);
			(void)do_res_stat(A_CHR);

			/* Recalculate max. hitpoints */
			update_stuff();

			hp_player(5000);

			*ident = TRUE;
			break;
		}

		case SV_POTION_RESTORE_MANA:
		{
			if (p_ptr->csp < p_ptr->msp)
			{
				p_ptr->csp = p_ptr->msp;
				p_ptr->csp_frac = 0;
				msg_print("Ваша голова проясняется.");
				p_ptr->redraw |= (PR_MANA);
				p_ptr->window |= (PW_PLAYER_0 | PW_PLAYER_1);
				*ident = TRUE;
			}
			break;
		}

		case SV_POTION_RESTORE_EXP:
		{
			if (restore_level()) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_STR:
		{
			if (do_res_stat(A_STR)) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_INT:
		{
			if (do_res_stat(A_INT)) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_WIS:
		{
			if (do_res_stat(A_WIS)) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_DEX:
		{
			if (do_res_stat(A_DEX)) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_CON:
		{
			if (do_res_stat(A_CON)) *ident = TRUE;
			break;
		}

		case SV_POTION_RES_CHR:
		{
			if (do_res_stat(A_CHR)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_STR:
		{
			if (do_inc_stat(A_STR)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_INT:
		{
			if (do_inc_stat(A_INT)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_WIS:
		{
			if (do_inc_stat(A_WIS)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_DEX:
		{
			if (do_inc_stat(A_DEX)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_CON:
		{
			if (do_inc_stat(A_CON)) *ident = TRUE;
			break;
		}

		case SV_POTION_INC_CHR:
		{
			if (do_inc_stat(A_CHR)) *ident = TRUE;
			break;
		}

		case SV_POTION_AUGMENTATION:
		{
			if (do_inc_stat(A_STR)) *ident = TRUE;
			if (do_inc_stat(A_INT)) *ident = TRUE;
			if (do_inc_stat(A_WIS)) *ident = TRUE;
			if (do_inc_stat(A_DEX)) *ident = TRUE;
			if (do_inc_stat(A_CON)) *ident = TRUE;
			if (do_inc_stat(A_CHR)) *ident = TRUE;
			break;
		}

		case SV_POTION_ENLIGHTENMENT:
		{
			msg_print("Изображение подземелья формируется у вас в голове...");
			wiz_lite();
			*ident = TRUE;
			break;
		}

		case SV_POTION_STAR_ENLIGHTENMENT:
		{
			msg_print("Вы чувствуете себя просвещенным...");
			message_flush();
			wiz_lite();
			(void)do_inc_stat(A_INT);
			(void)do_inc_stat(A_WIS);
			(void)detect_traps();
			(void)detect_doors();
			(void)detect_stairs();
			(void)detect_treasure();
			(void)detect_objects_gold();
			(void)detect_objects_normal();
			identify_pack();
			self_knowledge();
			*ident = TRUE;
			break;
		}

		case SV_POTION_SELF_KNOWLEDGE:
		{
			msg_print("Вы познаете себя немного лучше...");
			message_flush();
			self_knowledge();
			*ident = TRUE;
			break;
		}

		case SV_POTION_EXPERIENCE:
		{
			if (p_ptr->exp < PY_MAX_EXP)
			{
				s32b ee = (p_ptr->exp / 2) + 10;
				if (ee > 100000L) ee = 100000L;
				msg_print("Вы чувствуете себя более опытным.");
				gain_exp(ee);
				*ident = TRUE;
			}
			break;
		}
	}

	return (TRUE);
}