Beispiel #1
0
static void _greater_focus_rage_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Focus *Rage*");
        break;
    case SPELL_DESC:
        var_set_string(res, "Damage yourself and regain spell points.");
        break;
    case SPELL_INFO:
        if (p_ptr->shero)
            var_set_string(res, info_damage(0, 0, 2 * p_ptr->lev));
        else
            var_set_string(res, info_damage(0, 0, 10 + p_ptr->lev));
        break;
    case SPELL_FAIL:
    {
        int hp = 10 + p_ptr->lev;
        if (p_ptr->shero)
            hp = 2 * p_ptr->lev;
        take_hit(DAMAGE_NOESCAPE, hp, "Rage", -1);
        break;
    }
    case SPELL_CAST:
    {
        int hp = 10 + p_ptr->lev;

        var_set_bool(res, FALSE);
        
        if (p_ptr->shero)
            hp = 2 * p_ptr->lev;

        if (p_ptr->chp < hp)
        {
            if (!get_check("Really? This will kill you!")) return;
        }

        take_hit(DAMAGE_NOESCAPE, hp, "Rage", -1);
        sp_player(hp * 2);

        _unclear_mind = FALSE; /* Hack to avoid automatic mana drain for this action */
        var_set_bool(res, TRUE);
        break;    
    }
    default:
        default_spell(cmd, res);
        break;
    }
}
/**
 * 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, struct object *obj)
{
	int trap;

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

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

	/* Lose strength */
	if (trap & (CHEST_LOSE_STR)) {
		msg("A small needle has pricked you!");
		take_hit(player, damroll(1, 4), "a poison needle");
		effect_simple(EF_DRAIN_STAT, "0", STAT_STR, 0, 0, NULL);
	}

	/* Lose constitution */
	if (trap & (CHEST_LOSE_CON)) {
		msg("A small needle has pricked you!");
		take_hit(player, damroll(1, 4), "a poison needle");
		effect_simple(EF_DRAIN_STAT, "0", STAT_CON, 0, 0, NULL);
	}

	/* Poison */
	if (trap & (CHEST_POISON)) {
		msg("A puff of green gas surrounds you!");
		effect_simple(EF_TIMED_INC, "10+1d20", TMD_POISONED, 0, 0, NULL);
	}

	/* Paralyze */
	if (trap & (CHEST_PARALYZE)) {
		msg("A puff of yellow gas surrounds you!");
		effect_simple(EF_TIMED_INC, "10+1d20", TMD_PARALYZED, 0, 0, NULL);
	}

	/* Summon monsters */
	if (trap & (CHEST_SUMMON)) {
		msg("You are enveloped in a cloud of smoke!");
		effect_simple(EF_SUMMON, "2+1d3", 0, 0, 0, NULL);
	}

	/* Explode */
	if (trap & (CHEST_EXPLODE)) {
		msg("There is a sudden explosion!");
		msg("Everything inside the chest is destroyed!");
		obj->pval = 0;
		take_hit(player, damroll(5, 8), "an exploding chest");
	}
}
/**
 * Melee effect handler: Cause an earthquake around the player.
 */
static void melee_effect_handler_SHATTER(melee_effect_handler_context_t *context)
{
	/* Obvious */
	context->obvious = TRUE;

	/* Hack -- Reduce damage based on the player armor class */
	context->damage = adjust_dam_armor(context->damage, context->ac);

	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Player is dead */
	if (context->p->is_dead)
		return;

	/* Radius 8 earthquake centered at the monster */
	if (context->damage > 23) {
		int px_old = context->p->px;
		int py_old = context->p->py;

		effect_simple(EF_EARTHQUAKE, "0", 0, 8, 0, NULL);

		/* Stop the blows if the player is pushed away */
		if ((px_old != context->p->px) ||
			(py_old != context->p->py))
			context->do_break = TRUE;
	}
}
Beispiel #4
0
/**
 * Handle falling off cliffs 
 */
void fall_off_cliff(int levels)
{
	int dam;

	msg("You fall into the darkness!");

	/* New chunk */
	chunk_change(1, 0, 0);

	/* Hit the ground... */
	if (!tf_has(f_info[cave_feat[p_ptr->py][p_ptr->px]].flags, TF_FALL)) {
		if (p_ptr->state.ffall) {
			notice_obj(OF_FEATHER, 0);
			dam = damroll(2 * levels, 8);
			(void) inc_timed(TMD_STUN, damroll(2 * levels, 8), TRUE);
			(void) inc_timed(TMD_CUT, damroll(2 * levels, 8), TRUE);
		} else {
			dam = damroll(4 * levels, 8);
			(void) inc_timed(TMD_STUN, damroll(4 * levels, 8), TRUE);
			(void) inc_timed(TMD_CUT, damroll(4 * levels, 8), TRUE);
		}
		take_hit(dam, "falling off a precipice");
	}

	/* ...or not */
	else
		fall_off_cliff(levels + 1);
}
/**
 * Do damage as the result of an experience draining melee attack.
 *
 * \param context is the information for the current attack.
 * \param chance is the player's chance of resisting drain if they have
 * OF_HOLD_LIFE.
 * \param drain_amount is the base amount of experience to drain.
 */
static void melee_effect_experience(melee_effect_handler_context_t *context,
									int chance, int drain_amount)
{
	/* Obvious */
	context->obvious = TRUE;

	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);
	update_smart_learn(context->mon, context->p, OF_HOLD_LIFE, 0, -1);

	/* Player is dead */
	if (context->p->is_dead)
		return;

	if (player_of_has(context->p, OF_HOLD_LIFE) && (randint0(100) < chance)) {
		msg("You keep hold of your life force!");
	} else {
		s32b d = drain_amount +
			(context->p->exp/100) * z_info->life_drain_percent;
		if (player_of_has(context->p, OF_HOLD_LIFE)) {
			msg("You feel your life slipping away!");
			player_exp_lose(context->p, d / 10, FALSE);
		} else {
			msg("You feel your life draining away!");
			player_exp_lose(context->p, d, FALSE);
		}
	}
}
/**
 * Melee effect handler: Absorb the player's light.
 */
static void melee_effect_handler_EAT_LIGHT(melee_effect_handler_context_t *context)
{
	int light_slot = slot_by_name(context->p, "light");
	struct object *obj = slot_object(context->p, light_slot);

	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Player is dead */
	if (context->p->is_dead)
		return;

	/* Drain fuel where applicable */
	if (obj && !of_has(obj->flags, OF_NO_FUEL) && (obj->timeout > 0)) {
		/* Reduce fuel */
		obj->timeout -= (250 + randint1(250));
		if (obj->timeout < 1) obj->timeout = 1;

		/* Notice */
		if (!context->p->timed[TMD_BLIND]) {
			msg("Your light dims.");
			context->obvious = TRUE;
		}

		/* Redraw stuff */
		context->p->upkeep->redraw |= (PR_EQUIP);
	}
}
void hellfire_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Hellfire");
        break;
    case SPELL_DESC:
        var_set_string(res, "Fires a powerful ball of evil power directly from the bowels of hell. Good monsters are especially susceptible.");
        break;
    case SPELL_INFO:
        var_set_string(res, info_damage(0, 0, spell_power(666)));
        break;
    case SPELL_CAST:
    {
        int dir = 0;
        var_set_bool(res, FALSE);
        if (get_aim_dir(&dir))
        {
            fire_ball(GF_HELL_FIRE, dir, spell_power(666), 3);
            if (!demon_is_(DEMON_BALROG))
                take_hit(DAMAGE_USELIFE, 20 + randint1(30), "the strain of casting Hellfire", -1);
            var_set_bool(res, TRUE);
        }
        break;
    }
    default:
        default_spell(cmd, res);
        break;
    }
}
/**
 * Do damage as the result of a melee attack that has a status effect.
 *
 * \param context is the information for the current attack.
 * \param type is the TMD_ constant for the effect.
 * \param amount is the amount that the timer should be increased by.
 * \param of_flag is the OF_ flag that is passed on to monster learning for
 * this effect.
 * \param attempt_save indicates if a saving throw should be attempted for
 * this effect.
 * \param save_msg is the message that is displayed if the saving throw is
 * successful.
 */
static void melee_effect_timed(melee_effect_handler_context_t *context,
							   int type, int amount, int of_flag,
							   bool attempt_save, const char *save_msg)
{
	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Player is dead */
	if (context->p->is_dead)
		return;

	/* Perform a saving throw if desired. */
	if (attempt_save && randint0(100) < context->p->state.skills[SKILL_SAVE]) {
		if (save_msg != NULL)
			msg("%s", save_msg);

		context->obvious = TRUE;
	}
	else {
		/* Increase timer for type. */
		if (player_inc_timed(context->p, type, amount, TRUE, TRUE))
			context->obvious = TRUE;
	}

	/* Learn about the player */
	update_smart_learn(context->mon, context->p, of_flag, 0, -1);
}
Beispiel #9
0
/**
 * Do damage as the result of a melee attack that drains a stat.
 *
 * \param context is the information for the current attack.
 * \param stat is the STAT_ constant for the desired stat.
 */
static void melee_effect_stat(melee_effect_handler_context_t *context, int stat)
{
	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Damage (stat) */
	effect_simple(EF_DRAIN_STAT, "0", stat, 0, 0, &context->obvious);
}
Beispiel #10
0
void
Yeti::kill_squished(GameObject& object)
{
  auto player = dynamic_cast<Player*>(&object);
  if (player) {
    player->bounce(*this);
    take_hit(*player);
  }
}
Beispiel #11
0
/**
 * Melee effect handler: Hurt the player with no side effects.
 */
static void melee_effect_handler_HURT(melee_effect_handler_context_t *context)
{
	/* Obvious */
	context->obvious = TRUE;

	/* Hack -- Player armor reduces total damage */
	context->damage = adjust_dam_armor(context->damage, context->ac);

	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);
}
Beispiel #12
0
/**
 * Melee effect handler: Drain all of the player's stats.
 */
static void melee_effect_handler_LOSE_ALL(melee_effect_handler_context_t *context)
{
	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Damage (stats) */
	effect_simple(EF_DRAIN_STAT, "0", STAT_STR, 0, 0, &context->obvious);
	effect_simple(EF_DRAIN_STAT, "0", STAT_DEX, 0, 0, &context->obvious);
	effect_simple(EF_DRAIN_STAT, "0", STAT_CON, 0, 0, &context->obvious);
	effect_simple(EF_DRAIN_STAT, "0", STAT_INT, 0, 0, &context->obvious);
	effect_simple(EF_DRAIN_STAT, "0", STAT_WIS, 0, 0, &context->obvious);
}
Beispiel #13
0
/**
 * Melee effect handler: Absorb the player's light.
 */
static void melee_effect_handler_EAT_LIGHT(melee_effect_handler_context_t *context)
{
	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Player is dead */
	if (context->p->is_dead)
		return;

	/* Drain the light source */
	effect_simple(EF_DRAIN_LIGHT, "250+1d250", 0, 0, 0, &context->obvious);
}
Beispiel #14
0
/**
 * Melee effect handler: Disenchant the player.
 */
static void melee_effect_handler_DISENCHANT(melee_effect_handler_context_t *context)
{
	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Apply disenchantmen if no resist */
	if (!player_resists(context->p, ELEM_DISEN))
		effect_simple(EF_DISENCHANT, "0", 0, 0, 0, &context->obvious);

	/* Learn about the player */
	update_smart_learn(context->m_ptr, context->p, 0, 0, ELEM_DISEN);
}
static void _pay_cost(int cost)
{
    if (p_ptr->csp < cost)
    {
        int dam = cost - p_ptr->csp;
        p_ptr->csp = 0;
        take_hit(DAMAGE_USELIFE, dam, "concentrating too hard", -1);
    }
    else 
        p_ptr->csp -= cost;

    p_ptr->redraw |= (PR_MANA | PR_HP);
}
Beispiel #16
0
/**
 * Melee effect handler: Make the player hallucinate.
 *
 * Note that we don't use melee_effect_timed(), due to the different monster
 * learning function.
 */
static void melee_effect_handler_HALLU(melee_effect_handler_context_t *context)
{
	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Increase "image" */
	if (player_inc_timed(context->p, TMD_IMAGE, 3 + randint1(context->rlev / 2),
						 TRUE, TRUE))
		context->obvious = TRUE;

	/* Learn about the player */
	update_smart_learn(context->m_ptr, context->p, 0, 0, ELEM_CHAOS);
}
Beispiel #17
0
/**
 * Melee effect handler: Eat the player's food.
 */
static void melee_effect_handler_EAT_FOOD(melee_effect_handler_context_t *context)
{
	/* Steal some food */
	int tries;

	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Player is dead */
	if (context->p->is_dead)
		return;

	for (tries = 0; tries < 10; tries++) {
		/* Pick an item from the pack */
		int index = randint0(z_info->pack_size);
		struct object *obj, *eaten;
		char o_name[80];
		bool none_left = false;

		/* Get the item */
		obj = context->p->upkeep->inven[index];

		/* Skip non-objects */
		if (obj == NULL) continue;

		/* Skip non-food objects */
		if (!tval_is_edible(obj)) continue;

		if (obj->number == 1) {
			object_desc(o_name, sizeof(o_name), obj, ODESC_BASE);
			msg("Your %s (%c) was eaten!", o_name, I2A(index));
		} else {
			object_desc(o_name, sizeof(o_name), obj,
						ODESC_PREFIX | ODESC_BASE);
			msg("One of your %s (%c) was eaten!", o_name,
				I2A(index));
		}

		/* Steal and eat */
		eaten = gear_object_for_use(obj, 1, false, &none_left);
		if (eaten->known)
			object_delete(&eaten->known);
		object_delete(&eaten);

		/* Obvious */
		context->obvious = true;

		/* Done */
		break;
	}
}
Beispiel #18
0
/**
 * Melee effect handler: Make the player hallucinate.
 *
 * Note that we don't use melee_effect_timed(), due to the different monster
 * learning function.
 */
static void melee_effect_handler_HALLU(melee_effect_handler_context_t *context)
{
	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Player is dead */
	if (context->p->is_dead)
		return;

	/* Increase "image" */
	if (player_inc_timed(context->p, TMD_IMAGE, 3 + randint1(context->rlev / 2),
						 true, true))
		context->obvious = true;

	/* Learn about the player */
	update_smart_learn(context->mon, context->p, 0, 0, ELEM_CHAOS);
}
Beispiel #19
0
/**
 * Do damage as the result of a melee attack that has an elemental aspect.
 *
 * \param context is information for the current attack.
 * \param type is the GF_ constant for the element.
 * \param pure_element should be TRUE if no side effects (mostly a hack
 * for poison).
 */
static void melee_effect_elemental(melee_effect_handler_context_t *context,
								   int type, bool pure_element)
{
	int physical_dam, elemental_dam;

	if (pure_element) {
		/* Obvious */
		context->obvious = TRUE;
	}

	switch (type) {
		case GF_ACID: msg("You are covered in acid!");
			break;
		case GF_ELEC: msg("You are struck by electricity!");
			break;
		case GF_FIRE: msg("You are enveloped in flames!");
			break;
		case GF_COLD: msg("You are covered with frost!");
			break;
	}

	/* Give the player a small bonus to ac for elemental attacks */
	physical_dam = adjust_dam_armor(context->damage, context->ac + 50);

	/* Some attacks do no physical damage */
	if (!monster_blow_method_physical(context->method))
		physical_dam = 0;

	elemental_dam = adjust_dam(player, type, context->damage, RANDOMISE, 0);

	/* Take the larger of physical or elemental damage */
	context->damage = (physical_dam > elemental_dam) ?
		physical_dam : elemental_dam;

	if (context->damage > 0)
		take_hit(context->p, context->damage, context->ddesc);
	if (elemental_dam > 0)
		inven_damage(context->p, type, MIN(elemental_dam * 5, 300));

	if (pure_element) {
		/* Learn about the player */
		update_smart_learn(context->m_ptr, context->p, 0, 0, type);
	}
}
Beispiel #20
0
static void _rage_strike_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Ragestrike");
        break;
    case SPELL_DESC:
        var_set_string(res, "Fire a ball of pure rage at chosen foe, striking with everything you've got!");
        break;
    case SPELL_INFO:
        var_set_string(res, info_damage(0, 0, _rage_strike_dam()));
        break;
    case SPELL_FAIL:
        sp_player(-p_ptr->csp);
        break;
    case SPELL_CAST:
    {
        int dir;
        var_set_bool(res, FALSE);

        if (p_ptr->chp < 100)
        {
            if (!get_check("Really? This will kill you!")) return;
        }

        if (!get_aim_dir(&dir)) return;

        fire_ball(GF_MISSILE, dir, _rage_strike_dam(), 0);
        take_hit(DAMAGE_NOESCAPE, 100, "Rage", -1);
        if (!p_ptr->shero)
            set_stun(99, FALSE); /* 100 is Knocked Out */

        sp_player(-p_ptr->csp); /* Don't use SPELL_COST_EXTRA since we pay mana up front these days! */
        var_set_bool(res, TRUE);
        break;
    }
    default:
        default_spell(cmd, res);
        break;
    }
}
Beispiel #21
0
static void _pharaohs_curse_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Pharaoh's Curse");
        break;
    case SPELL_DESC:
        var_set_string(res, "Curses all nearby monsters, doing great damage and various effects.");
        break;
    case SPELL_CAST:
        {
            int power = spell_power(p_ptr->lev * 4);
            project_hack(GF_PHARAOHS_CURSE, p_ptr->lev + randint1(p_ptr->lev));
            if (p_ptr->lev >= 46)
                confuse_monsters(power);
            if (p_ptr->lev >= 47)
                slow_monsters(power);
            if (p_ptr->lev >= 48)
                turn_monsters(power);
            if (p_ptr->lev >= 49)
                stun_monsters(power);
            if (one_in_(5))
            {
                int mode = 0;
                if (one_in_(2))
                    mode = PM_FORCE_PET;
                if (summon_named_creature(0, py, px, MON_GREATER_MUMMY, mode))
                {
                    msg_print("You have disturbed the rest of an ancient pharaoh!");
                }
            }
            take_hit(DAMAGE_USELIFE, p_ptr->lev + randint1(p_ptr->lev), "the Pharaoh's Curse", -1);
            var_set_bool(res, TRUE);
        }
        break;
    default:
        default_spell(cmd, res);
        break;
    }
}
Beispiel #22
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 #23
0
/**
 * Melee effect handler: Take something from the player's inventory.
 */
static void melee_effect_handler_EAT_ITEM(melee_effect_handler_context_t *context)
{
	int tries;

    /* Take damage */
    take_hit(context->p, context->damage, context->ddesc);

    /* Saving throw (unless paralyzed) based on dex and level */
    if (!context->p->timed[TMD_PARALYZED] &&
        (randint0(100) < (adj_dex_safe[context->p->state.stat_ind[STAT_DEX]] +
                          context->p->lev))) {
        /* Saving throw message */
        msg("You grab hold of your backpack!");

        /* Occasional "blink" anyway */
        context->blinked = TRUE;

        /* Obvious */
        context->obvious = TRUE;

        /* Done */
        return;
    }

    /* Find an item */
    for (tries = 0; tries < 10; tries++) {
		struct object *obj, *stolen;
		char o_name[80];
		bool split = FALSE;

        /* Pick an item */
		int index = randint0(z_info->pack_size);

        /* Obtain the item */
        obj = context->p->upkeep->inven[index];

		/* Skip non-objects */
		if (obj == NULL) continue;

        /* Skip artifacts */
        if (obj->artifact) continue;

        /* Get a description */
        object_desc(o_name, sizeof(o_name), obj, ODESC_FULL);

		/* Is it one of a stack being stolen? */
		if (obj->number > 1)
			split = TRUE;

        /* Message */
        msg("%s %s (%c) was stolen!", (split ? "One of your" : "Your"),
			o_name, I2A(index));

        /* Steal and carry */
		stolen = gear_object_for_use(obj, 1, FALSE);
        (void)monster_carry(cave, context->m_ptr, stolen);

        /* Obvious */
        context->obvious = TRUE;

        /* Blink away */
        context->blinked = TRUE;

        /* Done */
        break;
    }
}
Beispiel #24
0
/**
 * Melee effect handler: Take the player's gold.
 */
static void melee_effect_handler_EAT_GOLD(melee_effect_handler_context_t *context)
{
	struct player *player = context->p;

    /* Take damage */
    take_hit(context->p, context->damage, context->ddesc);

    /* Obvious */
    context->obvious = TRUE;

    /* Attempt saving throw (unless paralyzed) based on dex and level */
    if (!player->timed[TMD_PARALYZED] &&
        (randint0(100) < (adj_dex_safe[player->state.stat_ind[STAT_DEX]]
						  + player->lev))) {
        /* Saving throw message */
        msg("You quickly protect your money pouch!");

        /* Occasional blink anyway */
        if (randint0(3)) context->blinked = TRUE;
    } else {
        s32b gold = (player->au / 10) + randint1(25);
        if (gold < 2) gold = 2;
        if (gold > 5000) gold = (player->au / 20) + randint1(3000);
        if (gold > player->au) gold = player->au;
        player->au -= gold;
        if (gold <= 0) {
            msg("Nothing was stolen.");
            return;
        }

        /* Let the player know they were robbed */
        msg("Your purse feels lighter.");
        if (player->au)
            msg("%d coins were stolen!", gold);
        else
            msg("All of your coins were stolen!");

        /* While we have gold, put it in objects */
        while (gold > 0) {
            int amt;

            /* Create a new temporary object */
            object_type *obj = object_new();
            object_prep(obj, money_kind("gold", gold), 0, MINIMISE);

            /* Amount of gold to put in this object */
            amt = gold > MAX_PVAL ? MAX_PVAL : gold;
            obj->pval = amt;
            gold -= amt;

            /* Set origin to stolen, so it is not confused with
             * dropped treasure in monster_death */
            obj->origin = ORIGIN_STOLEN;
			obj->origin_depth = player->depth;

            /* Give the gold to the monster */
            monster_carry(cave, context->m_ptr, obj);
        }

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

        /* Blink away */
        context->blinked = TRUE;
    }
}
Beispiel #25
0
/**
 * Melee effect handler: Drain charges from the player's inventory.
 */
static void melee_effect_handler_DRAIN_CHARGES(melee_effect_handler_context_t *context)
{
	struct object *obj;
	struct monster *monster = context->m_ptr;
	struct player *player = context->p;
	int tries;
	int unpower = 0, newcharge;

	/* Take damage */
	take_hit(context->p, context->damage, context->ddesc);

	/* Find an item */
	for (tries = 0; tries < 10; tries++) {
		/* Pick an item */
		obj = context->p->upkeep->inven[randint0(z_info->pack_size)];

		/* Skip non-objects */
		if (obj == NULL) continue;

		/* Drain charged wands/staves */
		if (tval_can_have_charges(obj)) {
			/* Charged? */
			if (obj->pval) {
				/* Get number of charge to drain */
				unpower = (context->rlev / (obj->kind->level + 2)) + 1;

				/* Get new charge value, don't allow negative */
				newcharge = MAX((obj->pval - unpower),0);

				/* Remove the charges */
				obj->pval = newcharge;
			}
		}

		if (unpower) {
			int heal = context->rlev * unpower;

			msg("Energy drains from your pack!");

			context->obvious = TRUE;

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

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

			/* Redraw (later) if needed */
			if (player->upkeep->health_who == monster)
				player->upkeep->redraw |= (PR_HEALTH);

			/* Combine the pack */
			player->upkeep->notice |= (PN_COMBINE);

			/* Redraw stuff */
			player->upkeep->redraw |= (PR_INVEN);

			/* Affect only a single inventory slot */
			break;
		}
	}
}
void hp_to_sp_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Convert HP to SP");
        break;
    case SPELL_DESC:
        var_set_string(res, "Converts HP into SP");
        break;
    case SPELL_GAIN_MUT:
        msg_print("You are subject to fits of painful clarity.");
        break;
    case SPELL_LOSE_MUT:
        msg_print("You are no longer subject to fits of painful clarity.");
        break;
    case SPELL_MUT_DESC:
        var_set_string(res, "Your blood sometimes rushes to your head.");
        break;
    case SPELL_PROCESS:
        if (!p_ptr->anti_magic && one_in_(4000))
        {
            int wounds = p_ptr->msp - p_ptr->csp;

            if (wounds > 0 && p_ptr->pclass != CLASS_RUNE_KNIGHT)
            {
                int healing = p_ptr->chp;

                if (healing > wounds)
                    healing = wounds;

                p_ptr->csp += healing;

                p_ptr->redraw |= (PR_MANA);
                take_hit(DAMAGE_LOSELIFE, healing, "blood rushing to the head", -1);
            }
        }
        break;

    case SPELL_CAST:
    {
        int gain_sp = take_hit(DAMAGE_USELIFE, p_ptr->lev, "thoughtless convertion from HP to SP", -1) / 5;
        if (gain_sp && p_ptr->pclass != CLASS_RUNE_KNIGHT)
        {
            p_ptr->csp += gain_sp;
            if (p_ptr->csp > p_ptr->msp)
            {
                p_ptr->csp = p_ptr->msp;
                p_ptr->csp_frac = 0;
            }

            p_ptr->redraw |= PR_MANA;
        }
        else
            msg_print("You failed to convert.");

        var_set_bool(res, TRUE);
        break;
    }
    default:
        default_spell(cmd, res);
        break;
    }
}
Beispiel #27
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 #28
0
void do_cmd_power(void)
{
    spell_info spells[MAX_SPELLS];
    int ct = 0; 
    int choice = 0;
    race_t *race_ptr = get_race();
    class_t *class_ptr = get_class();
    
    if (p_ptr->confused)
    {
        msg_print("You are too confused!");
        return;
    }

    /* Hack ... Rethink this a bit, but the alternative of hacking into
       the 'm' command is a million times worse! 
       Doppelgangers need to be able to cancel their current mimicry.
       Also, add Mimic power back first so it always stays in the 'a' slot. */
    if (race_ptr->mimic && p_ptr->prace == RACE_DOPPELGANGER)
    {
        ct += (get_true_race()->get_powers)(spells + ct, MAX_SPELLS - ct);
    }
    
    if (race_ptr->get_powers != NULL)
    {
        ct += (race_ptr->get_powers)(spells + ct, MAX_SPELLS - ct);
    }

    if (class_ptr != NULL && class_ptr->get_powers != NULL)
    {
        ct += (class_ptr->get_powers)(spells + ct, MAX_SPELLS - ct);
    }

    ct += mut_get_powers(spells + ct, MAX_SPELLS - ct);

    if (ct == 0)
    {
        msg_print("You have no powers.");
        return;
    }

    _add_extra_costs_powers(spells, ct);

    choice = choose_spell(spells, ct, "power", p_ptr->csp + p_ptr->chp);

    if (p_ptr->special_defense & (KATA_MUSOU | KATA_KOUKIJIN))
    {
        set_action(ACTION_NONE);
    }

    if (choice >= 0 && choice < ct)
    {
        spell_info *spell = &spells[choice];
        
        if (spell->level > p_ptr->lev)
        {
            msg_print("You can't use that power yet!");
            return;
        }

        if (spell->cost > p_ptr->chp + p_ptr->csp)
        {
            msg_print("Using this power will kill you!  Why not rest a bit first?");
            return;
        }

        /* Check for Failure */
        if (randint0(100) < spell->fail)
        {
            spell_stats_on_fail(spell);
            sound(SOUND_FAIL); /* Doh! */
            fail_spell(spell->fn);
            if (flush_failure) flush();
            msg_print("You failed to concentrate hard enough!");
        }
        else
        {
            if (!cast_spell(spell->fn))
                return;
            spell_stats_on_cast(spell);
            sound(SOUND_ZAP); /* Wahoo! */
        }

        energy_use = get_spell_energy(spell->fn);

        /* Casting costs spill over into hit points */
        if (p_ptr->csp < spell->cost)
        {
            int cost = spell->cost - p_ptr->csp;
            p_ptr->csp = 0;
            take_hit(DAMAGE_USELIFE, cost, "concentrating too hard", -1);
        }
        else 
            p_ptr->csp -= spell->cost;

        p_ptr->redraw |= (PR_MANA);
        p_ptr->redraw |= (PR_HP);
        p_ptr->window |= (PW_SPELL);
    }
}
Beispiel #29
0
/**
 * Called from project() to affect the player
 *
 * Called for projections with the PROJECT_PLAY flag set, which includes
 * bolt, beam, ball and breath effects.
 *
 * \param src is the origin of the effect
 * \param r is the distance from the centre of the effect
 * \param y the coordinates of the grid being handled
 * \param x the coordinates of the grid being handled
 * \param dam is the "damage" from the effect at distance r from the centre
 * \param typ is the projection (PROJ_) type
 * \return whether the effects were obvious
 *
 * If "r" is non-zero, then the blast was centered elsewhere; the damage
 * is reduced in project() before being passed in here.  This can happen if a
 * monster breathes at the player and hits a wall instead.
 *
 * We assume the player is aware of some effect, and always return "true".
 */
bool project_p(struct source origin, int r, int y, int x, int dam, int typ)
{
	bool blind = (player->timed[TMD_BLIND] ? true : false);
	bool seen = !blind;
	bool obvious = true;

	/* Monster or trap name (for damage) */
	char killer[80];

	project_player_handler_f player_handler = player_handlers[typ];
	project_player_handler_context_t context = {
		origin,
		r,
		y,
		x,
		dam,
		typ,
		obvious,
	};

	/* No player here */
	if (!square_isplayer(cave, y, x)) {
		return false;
	}

	switch (origin.what) {
		case SRC_PLAYER:
			/* Never affect projector */
			return false;

		case SRC_MONSTER: {
			struct monster *mon = cave_monster(cave, origin.which.monster);

			/* Check it is visible */
			if (!monster_is_visible(mon))
				seen = false;

			/* Get the monster's real name */
			monster_desc(killer, sizeof(killer), mon, MDESC_DIED_FROM);

			break;
		}

		case SRC_TRAP: {
			struct trap *trap = origin.which.trap;

			/* Get the trap name */
			strnfmt(killer, sizeof(killer), "a %s", trap->kind->desc);

			break;
		}

		case SRC_OBJECT: {
			struct object *obj = origin.which.object;
			object_desc(killer, sizeof(killer), obj, ODESC_PREFIX | ODESC_BASE);
			break;
		}

		case SRC_NONE: {
			/* Assume the caller has set the killer variable */
			break;
		}
	}

	/* Let player know what is going on */
	if (!seen) {
		msg("You are hit by %s!", projections[typ].blind_desc);
	}

	/* Adjust damage for resistance, immunity or vulnerability, and apply it */
	dam = adjust_dam(player,
						typ,
						dam,
						RANDOMISE,
					 player->state.el_info[typ].res_level,
					 true);
	if (dam) {
		take_hit(player, dam, killer);
	}

	/* Handle side effects */
	if (player_handler != NULL && player->is_dead == false) {
		player_handler(&context);
	}

	/* Disturb */
	disturb(player, 1);

	/* Return "Anything seen?" */
	return context.obvious;
}
Beispiel #30
0
void do_cmd_spell(void)
{
    spell_info spells[MAX_SPELLS];
    caster_info *caster = get_caster_info();
    int ct = 0; 
    int choice = 0;
    int max_cost = 0;

    if (!caster) 
    {
        msg_print("You cannot cast spells.");
        return;
    }
    
    if (p_ptr->confused)
    {
        msg_print("You are too confused!");
        return;
    }

    if (p_ptr->special_defense & KATA_MASK)
    {
        set_action(ACTION_NONE);
    }
    
    ct = _get_spell_table(spells, MAX_SPELLS);
    if (ct == 0)
    {
        /* User probably canceled the prompt for a spellbook */
        return;
    }

    if (caster->options & CASTER_USE_HP)
        max_cost = p_ptr->chp;
    else
        max_cost = p_ptr->csp;
    choice = choose_spell(spells, ct, caster->magic_desc, max_cost);

    if (choice >= 0 && choice < ct)
    {
        spell_info *spell = &spells[choice];

        if (spell->level > p_ptr->lev)
        {
            msg_print("You can't use that spell yet!");
            return;
        }

        /* Verify Cost ... Note, I'm removing options for over exertion 
           Also note we now pay casting costs up front for mana casters. 
           If the user cancels, then we return the cost below.
        */
        if (caster->options & CASTER_USE_HP)
        {
            if (spell->cost > p_ptr->chp)
            {
                msg_print("You do not have enough hp to use this power.");
                return;
            }
        }
        else
        {
            if (spell->cost > p_ptr->csp)
            {
                msg_print("You do not have enough mana to use this power.");
                return;
            }
            p_ptr->csp -= spell->cost;
        }

        /* Check for Failure */
        if (randint0(100) < spell->fail)
        {
            sound(SOUND_FAIL); /* Doh! */
            spell_stats_on_fail(spell);
            fail_spell(spell->fn);
            if (flush_failure) flush();
            msg_print("You failed to concentrate hard enough!");
            if (!(caster->options & CASTER_USE_HP) && demigod_is_(DEMIGOD_ATHENA) )
                p_ptr->csp += spell->cost/2;
            if (caster->on_fail != NULL)
                (caster->on_fail)(spell);
        }
        else
        {
            if (!cast_spell(spell->fn))
            {
                /* Give back the spell cost, since the user canceled the spell */
                if (!(caster->options & CASTER_USE_HP)) p_ptr->csp += spell->cost;
                return;
            }
            spell_stats_on_cast(spell);
            sound(SOUND_ZAP); /* Wahoo! */
        }

        energy_use = get_spell_energy(spell->fn);

        if ((caster->options & CASTER_USE_HP) && spell->cost > 0)
            take_hit(DAMAGE_USELIFE, spell->cost, "concentrating too hard", -1);

        if (caster->on_cast != NULL)
            (caster->on_cast)(spell);

        p_ptr->redraw |= (PR_MANA);
        p_ptr->redraw |= (PR_HP);
        p_ptr->window |= (PW_SPELL);
    }
}