Esempio n. 1
0
/*
 * Determine if a given grid may be "walked"
 */
static bool do_cmd_walk_test(int y, int x)
{

	int m_idx = cave->m_idx[y][x];
	
	/* Allow attack on visible monsters if unafraid */
	if ((m_idx > 0) && (cave_monster(cave, m_idx)->ml) && !is_mimicking(m_idx))
	{
		/* Handle player fear */
		if(check_state(p_ptr, OF_AFRAID, p_ptr->state.flags))
		{
			/* Extract monster name (or "it") */
			char m_name[80];
			const monster_type *m_ptr;

			m_ptr = cave_monster(cave, m_idx);
			monster_desc(m_name, sizeof(m_name), m_ptr, 0);

			/* Message */
			msgt(MSG_AFRAID,
				"You are too afraid to attack %s!", m_name);

			/* Nope */
			return (FALSE);
		}
		
		return (TRUE);
	}

	/* If we don't know the grid, allow attempts to walk into it */
	if (!(cave->info[y][x] & CAVE_MARK))
		return TRUE;

	/* Require open space */
	if (!cave_floor_bold(y, x))
	{
		/* Rubble */
		if (cave->feat[y][x] == FEAT_RUBBLE)
			msgt(MSG_HITWALL, "There is a pile of rubble in the way!");

		/* Door */
		else if (cave->feat[y][x] < FEAT_SECRET)
			return TRUE;

		/* Wall */
		else
			msgt(MSG_HITWALL, "There is a wall in the way!");

		/* Cancel repeat */
		disturb(p_ptr, 0, 0);

		/* Nope */
		return (FALSE);
	}

	/* Okay */
	return (TRUE);
}
Esempio n. 2
0
/**
 * Determine if a given grid may be "walked"
 */
static bool do_cmd_walk_test(int y, int x)
{
	int m_idx = cave->squares[y][x].mon;
	struct monster *mon = cave_monster(cave, m_idx);

	/* Allow attack on visible monsters if unafraid */
	if (m_idx > 0 && mflag_has(mon->mflag, MFLAG_VISIBLE) &&
		!is_mimicking(mon)) {
		/* Handle player fear */
		if (player_of_has(player, OF_AFRAID)) {
			/* Extract monster name (or "it") */
			char m_name[80];
			monster_desc(m_name, sizeof(m_name), mon, MDESC_DEFAULT);

			/* Message */
			msgt(MSG_AFRAID, "You are too afraid to attack %s!", m_name);

			/* Nope */
			return (false);
		}

		return (true);
	}

	/* If we don't know the grid, allow attempts to walk into it */
	if (!square_isknown(cave, y, x))
		return true;

	/* Require open space */
	if (!square_ispassable(cave, y, x)) {
		if (square_isrubble(cave, y, x))
			/* Rubble */
			msgt(MSG_HITWALL, "There is a pile of rubble in the way!");
		else if (square_iscloseddoor(cave, y, x))
			/* Door */
			return true;
		else if (square_isbright(cave, y, x))
			/* Lava */
			msgt(MSG_HITWALL, "The heat of the lava turns you away!");
		else
			/* Wall */
			msgt(MSG_HITWALL, "There is a wall in the way!");

		/* Cancel repeat */
		disturb(player, 0);

		/* Nope */
		return (false);
	}

	/* Okay */
	return (true);
}
Esempio n. 3
0
/**
 * Go up one level
 */
void do_cmd_go_up(struct command *cmd)
{
	/* Verify stairs */
	if (!square_isupstairs(cave, player->py, player->px)) {
		msg("I see no up staircase here.");
		return;
	}

	/* Force descend */
	if (OPT(birth_force_descend)) {
		msg("Nothing happens!");
		return;
	}

	/* Take a turn */
	player->upkeep->energy_use = z_info->move_energy;

	/* Success */
	msgt(MSG_STAIRS_UP, "You enter a maze of up staircases.");

	/* Create a way back */
	player->upkeep->create_up_stair = FALSE;
	player->upkeep->create_down_stair = TRUE;

	/* Change level */
	dungeon_change_level(player->depth - 1);
}
Esempio n. 4
0
static void adjust_level(struct player *p, bool verbose)
{
	if (p->exp < 0)
		p->exp = 0;

	if (p->max_exp < 0)
		p->max_exp = 0;

	if (p->exp > PY_MAX_EXP)
		p->exp = PY_MAX_EXP;

	if (p->max_exp > PY_MAX_EXP)
		p->max_exp = PY_MAX_EXP;

	if (p->exp > p->max_exp)
		p->max_exp = p->exp;

	p->upkeep->redraw |= PR_EXP;

	handle_stuff(p);

	while ((p->lev > 1) &&
	       (p->exp < (player_exp[p->lev-2] * p->expfact / 100L)))
		p->lev--;


	while ((p->lev < PY_MAX_LEVEL) &&
	       (p->exp >= (player_exp[p->lev-1] * p->expfact / 100L))) {
		char buf[80];

		p->lev++;

		/* Save the highest level */
		if (p->lev > p->max_lev)
			p->max_lev = p->lev;

		if (verbose) {
			/* Log level updates */
			strnfmt(buf, sizeof(buf), "Reached level %d", p->lev);
			history_add(p, buf, HIST_GAIN_LEVEL);

			/* Message */
			msgt(MSG_LEVEL, "Welcome to level %d.",	p->lev);
		}

		effect_simple(EF_RESTORE_STAT, "0", STAT_STR, 1, 0, NULL);
		effect_simple(EF_RESTORE_STAT, "0", STAT_INT, 1, 0, NULL);
		effect_simple(EF_RESTORE_STAT, "0", STAT_WIS, 1, 0, NULL);
		effect_simple(EF_RESTORE_STAT, "0", STAT_DEX, 1, 0, NULL);
		effect_simple(EF_RESTORE_STAT, "0", STAT_CON, 1, 0, NULL);
	}

	while ((p->max_lev < PY_MAX_LEVEL) &&
	       (p->max_exp >= (player_exp[p->max_lev-1] * p->expfact / 100L)))
		p->max_lev++;

	p->upkeep->update |= (PU_BONUS | PU_HP | PU_SPELLS);
	p->upkeep->redraw |= (PR_LEV | PR_TITLE | PR_EXP | PR_STATS);
	handle_stuff(p);
}
Esempio n. 5
0
/* Destroy an item */
void do_cmd_destroy(cmd_code code, cmd_arg args[])
{
	object_type *o_ptr;
	int item = args[0].item;

	if (!item_is_available(item, NULL, USE_INVEN | USE_EQUIP | USE_FLOOR))
	{
		msg("You do not have that item to ignore it.");
		return;
	}

	o_ptr = object_from_item_idx(item);

	if ((item >= INVEN_WIELD) && cursed_p(o_ptr->flags)) {
		msg("You cannot ignore cursed items.");
	} else {	
		char o_name[80];

		object_desc(o_name, sizeof o_name, o_ptr, ODESC_PREFIX | ODESC_FULL);
		msgt(MSG_DESTROY, "Ignoring %s.", o_name);

		o_ptr->ignore = TRUE;
		p_ptr->notice |= PN_SQUELCH;
	}
}
Esempio n. 6
0
/**
 * Take off a non-cursed equipment item
 *
 * Note that taking off an item when "full" may cause that item
 * to fall to the ground.
 *
 * Note also that this function does not try to combine the taken off item
 * with other inventory items - that must be done by the calling function.
 */
void inven_takeoff(struct object *obj)
{
	int slot = equipped_item_slot(player->body, obj);
	const char *act;
	char o_name[80];

	/* Paranoia */
	if (slot == player->body.count) return;

	/* Describe the object */
	object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL);

	/* Describe removal by slot */
	if (slot_type_is(slot, EQUIP_WEAPON))
		act = "You were wielding";
	else if (slot_type_is(slot, EQUIP_BOW))
		act = "You were holding";
	else if (slot_type_is(slot, EQUIP_LIGHT))
		act = "You were holding";
	else
		act = "You were wearing";

	/* De-equip the object */
	player->body.slots[slot].obj = NULL;
	player->upkeep->equip_cnt--;

	/* Message */
	msgt(MSG_WIELD, "%s %s (%c).", act, o_name, I2A(slot));

	player->upkeep->update |= (PU_BONUS | PU_INVEN);
	player->upkeep->notice |= (PN_IGNORE);
	return;
}
Esempio n. 7
0
/*
 * Go down one level
 */
void do_cmd_go_down(void)
{
	int py = p_ptr->py;
	int px = p_ptr->px;

	char answer;

	/* Verify stairs */
	if (cave_feat[py][px] != FEAT_MORE)
	{
		msg_print("I see no down staircase here.");
		return;
	}

	/* Make certain the player really wants to leave a themed level. -LM- */
	if (p_ptr->themed_level)
	{
		msg_print("This level will never appear again.  Really leave? (y/n)");
		answer = inkey();
		if ((answer != 'Y') && (answer != 'y')) return;
	}


	/* Hack -- take a turn */
	p_ptr->energy_use = 100;

	/* Success */
	msgt(MSG_STAIRS_DOWN, "You enter a maze of down staircases.");

	/* Create a way back */
	p_ptr->create_up_stair = TRUE;

	/* New level */
	p_ptr->depth++;


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

	/* Use the coordinates of the staircase to seed the RNG. */
	Rand_value = py * px;

	/* If the new level is not a quest level, or the bottom of the dungeon,
	 * there is a 50% chance of descending another level. -LM-
	 */
	if ((is_quest(p_ptr->depth) == FALSE) && (p_ptr->depth < MAX_DEPTH -1) &&
		(randint1(2) == 1))
	{
		msg_print("The stairs continue down.  Go down another level? (y/n)");

		answer = inkey();
		if ((answer == 'Y') || (answer == 'y')) p_ptr->depth++;
	}

	/* Revert to use of the "complex" RNG. */
	Rand_quick = FALSE;

	/* Leaving */
	p_ptr->leaving = TRUE;
}
Esempio n. 8
0
/*
 * Go up one level
 */
void do_cmd_go_up(cmd_code code, cmd_arg args[])
{
	/* Verify stairs */
	if (!cave_isupstairs(cave, p_ptr->py, p_ptr->px)) {
		msg("I see no up staircase here.");
		return;
	}

	/* Force descend */
	if (OPT(birth_force_descend)) {
		msg("Nothing happens!");
		return;
	}

	/* Hack -- take a turn */
	p_ptr->energy_use = 100;

	/* Success */
	msgt(MSG_STAIRS_UP, "You enter a maze of up staircases.");

	/* Create a way back */
	p_ptr->create_up_stair = FALSE;
	p_ptr->create_down_stair = TRUE;

	/* Change level */
	dungeon_change_level(p_ptr->depth - 1);
}
Esempio n. 9
0
/*
 * Go up one level
 */
void do_cmd_go_up(cmd_code code, cmd_arg args[])
{
	/* Verify stairs */
	if (cave->feat[p_ptr->py][p_ptr->px] != FEAT_LESS)
	{
		msg("I see no up staircase here.");
		return;
	}

	/* Ironman */
	if (OPT(birth_ironman))
	{
		msg("Nothing happens!");
		return;
	}

	/* Hack -- take a turn */
	p_ptr->energy_use = 100;

	/* Success */
	msgt(MSG_STAIRS_UP, "You enter a maze of up staircases.");

	/* Create a way back */
	p_ptr->create_up_stair = FALSE;
	p_ptr->create_down_stair = TRUE;

	/* Change level */
	dungeon_change_level(p_ptr->depth - 1);
}
Esempio n. 10
0
/*
 * Determine if a given grid may be "opened"
 */
static bool do_cmd_open_test(int y, int x)
{
	/* Must have knowledge */
	if (!(cave_info[y][x] & (CAVE_MARK)))
	{
		/* Message */
		msg_print("You see nothing there.");

		/* Nope */
		return (FALSE);
	}

	/* Must be a closed door */
	if (!((cave_feat[y][x] >= FEAT_DOOR_HEAD) &&
	      (cave_feat[y][x] <= FEAT_DOOR_TAIL)))
	{
		/* Message */
		msgt(MSG_NOTHING_TO_OPEN, "You see nothing there to open.");

		/* Nope */
		return (FALSE);
	}

	/* Okay */
	return (TRUE);
}
Esempio n. 11
0
/**
 * Perform the basic "disarm" command
 *
 * Assume there is no monster blocking the destination
 *
 * Returns true if repeated commands may continue
 */
static bool do_cmd_disarm_aux(int y, int x)
{
	int skill, power, chance;
    struct trap *trap = cave->squares[y][x].trap;
	bool more = false;

	/* Verify legality */
	if (!do_cmd_disarm_test(y, x)) return (false);

    /* Choose first player trap */
	while (trap) {
		if (trf_has(trap->flags, TRF_TRAP))
			break;
		trap = trap->next;
	}
	if (!trap)
		return false;

	/* Get the base disarming skill */
	if (trf_has(trap->flags, TRF_MAGICAL))
		skill = player->state.skills[SKILL_DISARM_MAGIC];
	else
		skill = player->state.skills[SKILL_DISARM_PHYS];

	/* Penalize some conditions */
	if (player->timed[TMD_BLIND] || no_light() || player->timed[TMD_CONFUSED] ||
		player->timed[TMD_IMAGE])
		skill = skill / 10;

	/* Extract trap power */
	power = cave->depth / 5;

	/* Extract the percentage success */
	chance = skill - power;

	/* Always have a small chance of success */
	if (chance < 2) chance = 2;

	/* Two chances - one to disarm, one not to set the trap off */
	if (randint0(100) < chance) {
		msgt(MSG_DISARM, "You have disarmed the %s.", trap->kind->name);
		player_exp_gain(player, power);

		/* Trap is gone */
		square_forget(cave, y, x);
		square_destroy_trap(cave, y, x);
	} else if (randint0(100) < chance) {
		event_signal(EVENT_INPUT_FLUSH);
		msg("You failed to disarm the %s.", trap->kind->name);

		/* Player can try again */
		more = true;
	} else {
		msg("You set off the %s!", trap->kind->name);
		hit_trap(y, x);
	}

	/* Result */
	return (more);
}
Esempio n. 12
0
/**
 * Destroy all {squelch}able items.
 *
 * Imported, with thanks, from Ey... much cleaner than the original.
 */
void squelch_items(void)
{
	int floor_list[MAX_FLOOR_STACK];
	int floor_num, n;
	int count = 0;

	object_type *o_ptr;

	/* Set the hook and scan the floor */
	item_tester_hook = squelch_item_ok;
	floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), p_ptr->py,
						   p_ptr->px, 0x01);

	if (floor_num) {
		for (n = 0; n < floor_num; n++) {
			o_ptr = &o_list[floor_list[n]];

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

			if (item_tester_okay(o_ptr)) {
				/* Destroy item */
				floor_item_increase(floor_list[n], -o_ptr->number);
				floor_item_optimize(floor_list[n]);
				count++;
			}
		}
	}

	/* Scan through the slots backwards */
	for (n = INVEN_PACK - 1; n >= 0; n--) {
		o_ptr = &p_ptr->inventory[n];

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

		if (item_tester_okay(o_ptr)) {
			/* Destroy item */
			inven_item_increase(n, -o_ptr->number);
			inven_item_optimize(n);
			count++;
		}
	}

	item_tester_hook = NULL;

	/* Mention casualties */
	if (count > 0) {
		msgt(MSG_GENERIC, "%d item%s squelched.",
			 count, ((count > 1) ? "s" : ""));

		/* Combine/reorder the pack */
		p_ptr->notice |= (PN_COMBINE | PN_REORDER | PN_SORT_QUIVER);
	}
}
Esempio n. 13
0
/**
 * Let a shop-keeper React to a purchase
 *
 * We paid "price", it was worth "value", and we thought it was worth "guess"
 */
static void purchase_analyze(s32b price, s32b value, s32b guess)
{
	/* Item was worthless, but we bought it */
	if ((value <= 0) && (price > value))
		msgt(MSG_STORE1, "%s", ONE_OF(comment_worthless));

	/* Item was cheaper than we thought, and we paid more than necessary */
	else if ((value < guess) && (price > value))
		msgt(MSG_STORE2, "%s", ONE_OF(comment_bad));

	/* Item was a good bargain, and we got away with it */
	else if ((value > guess) && (value < (4 * guess)) && (price < value))
		msgt(MSG_STORE3, "%s", ONE_OF(comment_good));

	/* Item was a great bargain, and we got away with it */
	else if ((value > guess) && (price < value))
		msgt(MSG_STORE4, "%s", ONE_OF(comment_great));
}
Esempio n. 14
0
/**
 * Remove a trap
 */
static void remove_trap_aux(struct chunk *c, struct trap *trap, int y, int x,
							bool domsg)
{
    /* We are deleting a rune */
    if (trf_has(trap->flags, TRF_RUNE)) {
		if (domsg)
			msg("You have removed the %s.", trap->kind->name);
    } else if (domsg)
		/* We are disarming a trap */
		msgt(MSG_DISARM, "You have disarmed the %s.", trap->kind->name);

    /* Wipe the trap */
	mem_free(trap);
}
Esempio n. 15
0
/**
 * Determine if a given grid may be "opened"
 */
static bool do_cmd_open_test(int y, int x)
{
	/* Must have knowledge */
	if (!square_isknown(cave, y, x)) {
		msg("You see nothing there.");
		return false;
	}

	/* Must be a closed door */
	if (!square_iscloseddoor(cave, y, x)) {
		msgt(MSG_NOTHING_TO_OPEN, "You see nothing there to open.");
		return false;
	}

	return (true);
}
Esempio n. 16
0
/*
 * Determine if a given grid may be "opened"
 */
static bool do_cmd_open_test(int y, int x)
{
	/* Must have knowledge */
	if (!(cave->info[y][x] & (CAVE_MARK))) {
		msg("You see nothing there.");
		return FALSE;
	}

	if (!cave_iscloseddoor(cave, y, x)) {
		msgt(MSG_NOTHING_TO_OPEN, "You see nothing there to open.");
		return FALSE;
	}

	/* Okay */
	return (TRUE);
}
Esempio n. 17
0
/**
 * Attempt to disarm the chest at the given location
 *
 * Assume there is no monster blocking the destination
 *
 * Returns true if repeated commands may continue
 */
bool do_cmd_disarm_chest(int y, int x, struct object *obj)
{
	int i, j;

	bool more = false;

	/* Get the "disarm" factor */
	if (obj->pval > 0 && (chest_traps[obj->pval] & CHEST_SUMMON))
		i = player->state.skills[SKILL_DISARM_MAGIC];
	else
		i = player->state.skills[SKILL_DISARM_PHYS];

	/* Penalize some conditions */
	if (player->timed[TMD_BLIND] || no_light()) i = i / 10;
	if (player->timed[TMD_CONFUSED] || player->timed[TMD_IMAGE]) i = i / 10;

	/* Extract the difficulty */
	j = i - obj->pval;

	/* Always have a small chance of success */
	if (j < 2) j = 2;

	/* Must find the trap first. */
	if (!obj->known->pval) {
		msg("I don't see any traps.");
	} else if (!is_trapped_chest(obj)) {
		/* Already disarmed/unlocked or no traps */
		msg("The chest is not trapped.");
	} else if (randint0(100) < j) {
		/* Success (get a lot of experience) */
		msgt(MSG_DISARM, "You have disarmed the chest.");
		player_exp_gain(player, obj->pval);
		obj->pval = (0 - obj->pval);
	} else if (randint0(100) < j) {
		/* Failure -- Keep trying */
		more = true;
		event_signal(EVENT_INPUT_FLUSH);
		msg("You failed to disarm the chest.");
	} else {
		/* Failure -- Set off the trap */
		msg("You set off a trap!");
		chest_trap(y, x, obj);
	}

	/* Result */
	return (more);
}
Esempio n. 18
0
/*
 * Learn the specified spell.
 */
void spell_learn(int spell)
{
    int i;

    magic_type *mt_ptr;

    /* Learn the spell */
    p_ptr->spell_flags[spell] |= PY_SPELL_LEARNED;
    
    /* Find the next open entry in "spell_order[]" */
    for (i = 0; i < PY_MAX_SPELLS; i++) {
	/* Stop at the first empty space */
	if (p_ptr->spell_order[i] == 99)
	    break;
    }

    /* Add the spell to the known list */
    p_ptr->spell_order[i] = spell;

    /* Access the spell */
    mt_ptr = &mp_ptr->info[spell];

    /* Mention the result */
    msgt(MSG_STUDY, "You have learned the %s of %s.", 
		   magic_desc[mp_ptr->spell_realm][SPELL_NOUN],
		   get_spell_name(mt_ptr->index));

    /* Sound */
    sound(MSG_STUDY);

    /* One less spell available */
    p_ptr->new_spells--;

    /* Message if needed */
    if (p_ptr->new_spells) {
	/* Message */
	msg("You can learn %d more %s%s.", p_ptr->new_spells,
		   magic_desc[mp_ptr->spell_realm][SPELL_NOUN],
		   ((p_ptr->new_spells != 1)
		    && (!mp_ptr->spell_book != TV_DRUID_BOOK)) ? "s" : "");
    }

    /* Redraw Study Status */
    p_ptr->redraw |= (PR_STUDY | PR_OBJECT);
}
Esempio n. 19
0
/**
 * Remove a trap
 */
static void remove_trap_aux(struct chunk *c, struct trap *trap, int y, int x,
							bool domsg)
{
	/* Message if needed */
	if (domsg) {
		/* We are deleting a rune */
		if (trf_has(trap->flags, TRF_RUNE)) {
			if (c->mon_current < 0) {
				/* Removed by player */
				msg("You have removed the %s.", trap->kind->name);
			}
		} else {
			/* We are disarming a trap */
			msgt(MSG_DISARM, "You have disarmed the %s.", trap->kind->name);
		}
	}

    /* Wipe the trap */
	mem_free(trap);
}
Esempio n. 20
0
/*
 * Go down one level
 */
void do_cmd_go_down(cmd_code code, cmd_arg args[])
{
	/* Verify stairs */
	if (cave->feat[p_ptr->py][p_ptr->px] != FEAT_MORE)
	{
		msg("I see no down staircase here.");
		return;
	}

	/* Hack -- take a turn */
	p_ptr->energy_use = 100;

	/* Success */
	msgt(MSG_STAIRS_DOWN, "You enter a maze of down staircases.");

	/* Create a way back */
	p_ptr->create_up_stair = TRUE;
	p_ptr->create_down_stair = FALSE;

	/* Change level */
	dungeon_change_level(p_ptr->depth + 1);
}
Esempio n. 21
0
/**
 * Go down one level
 */
void do_cmd_go_down(struct command *cmd)
{
	int descend_to = player->depth + 1;

	/* Verify stairs */
	if (!square_isdownstairs(cave, player->py, player->px)) {
		msg("I see no down staircase here.");
		return;
	}

	/* Paranoia, no descent from z_info->max_depth - 1 */
	if (player->depth == z_info->max_depth - 1) {
		msg("The dungeon does not appear to extend deeper");
		return;
	}

	/* Warn a force_descend player if they're going to a quest level */
	if (OPT(birth_force_descend)) {
		if (is_quest(player->max_depth + 1) &&
			!get_check("Are you sure you want to descend?"))
			return;

		/* Don't overshoot */
		descend_to = MIN(player->max_depth + 1, z_info->max_depth - 1);
	}

	/* Hack -- take a turn */
	player->upkeep->energy_use = z_info->move_energy;

	/* Success */
	msgt(MSG_STAIRS_DOWN, "You enter a maze of down staircases.");

	/* Create a way back */
	player->upkeep->create_up_stair = TRUE;
	player->upkeep->create_down_stair = FALSE;

	/* Change level */
	dungeon_change_level(descend_to);
}
Esempio n. 22
0
/**
 * Go up one level
 */
void do_cmd_go_up(struct command *cmd)
{
	int ascend_to;

	/* Verify stairs */
	if (!square_isupstairs(cave, player->py, player->px)) {
		msg("I see no up staircase here.");
		return;
	}

	/* Force descend */
	if (OPT(birth_force_descend)) {
		msg("Nothing happens!");
		return;
	}
	
	ascend_to = dungeon_get_next_level(player->depth, -1);
	
	if (ascend_to == player->depth) {
		msg("You can't go up from here!");
		return;
	}

	/* Take a turn */
	player->upkeep->energy_use = z_info->move_energy;

	/* Success */
	msgt(MSG_STAIRS_UP, "You enter a maze of up staircases.");

	/* Create a way back */
	player->upkeep->create_up_stair = false;
	player->upkeep->create_down_stair = true;
	
	/* Change level */
	dungeon_change_level(ascend_to);
}
Esempio n. 23
0
/*
 * Learn the specified spell.
 */
void spell_learn(int spell)
{
	int i;
	const char *p = ((cp_ptr->spell_book == TV_MAGIC_BOOK) ? "spell" : "prayer");

	/* Learn the spell */
	p_ptr->spell_flags[spell] |= PY_SPELL_LEARNED;

	/* Find the next open entry in "spell_order[]" */
	for (i = 0; i < PY_MAX_SPELLS; i++)
	{
		/* Stop at the first empty space */
		if (p_ptr->spell_order[i] == 99) break;
	}

	/* Add the spell to the known list */
	p_ptr->spell_order[i] = spell;

	/* Mention the result */
	msgt(MSG_STUDY, "You have learned the %s of %s.",
	           p, get_spell_name(cp_ptr->spell_book, spell));

	/* One less spell available */
	p_ptr->new_spells--;

	/* Message if needed */
	if (p_ptr->new_spells)
	{
		/* Message */
		msg("You can learn %d more %s%s.",
		           p_ptr->new_spells, p, PLURAL(p_ptr->new_spells));
	}

	/* Redraw Study Status */
	p_ptr->redraw |= (PR_STUDY | PR_OBJECT);
}
Esempio n. 24
0
/**
 * Called from project() to affect objects
 *
 * Called for projections with the PROJECT_ITEM flag set, which includes
 * beam, ball and breath effects.
 *
 * \param who is the monster list index of the caster
 * \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 (GF_) type
 * \param protected_obj is an object that should not be affected by the 
 *        projection, typically the object that created it
 * \return whether the effects were obvious
 *
 * Note that this function determines if the player can see anything that
 * happens by taking into account: blindness, line-of-sight, and illumination.
 *
 * Hack -- effects on objects which are memorized but not in view are also seen.
 */
bool project_o(int who, int r, int y, int x, int dam, int typ,
			   const struct object *protected_obj)
{
	struct object *obj = square_object(cave, y, x);
	bool obvious = false;

	/* Scan all objects in the grid */
	while (obj) {
		bool ignore = false;
		bool do_kill = false;
		const char *note_kill = NULL;
		struct object *next = obj->next;
		project_object_handler_context_t context = {
			who,
			r,
			y,
			x,
			dam,
			typ,
			obj,
			obvious,
			do_kill,
			ignore,
			note_kill,
		};
		project_object_handler_f object_handler = object_handlers[typ];

		if (object_handler != NULL)
			object_handler(&context);

		obvious = context.obvious;
		do_kill = context.do_kill && (obj != protected_obj);
		ignore = context.ignore;
		note_kill = context.note_kill;

		/* Attempt to destroy the object */
		if (do_kill) {
			char o_name[80];

			/* Effect observed */
			if (obj->known && !ignore_item_ok(obj) &&
				square_isseen(cave, y, x)) {
				obvious = true;
				object_desc(o_name, sizeof(o_name), obj, ODESC_BASE);
			}

			/* Artifacts, and other objects, get to resist */
			if (obj->artifact || ignore) {
				/* Observe the resist */
				if (obvious && obj->known && !ignore_item_ok(obj))
					msg("The %s %s unaffected!", o_name,
						VERB_AGREEMENT(obj->number, "is", "are"));
			} else if (obj->mimicking_m_idx) {
				/* Reveal mimics */
				if (obvious)
					become_aware(cave_monster(cave, obj->mimicking_m_idx));
			} else {
				/* Describe if needed */
				if (obvious && obj->known && note_kill && !ignore_item_ok(obj))
					msgt(MSG_DESTROY, "The %s %s!", o_name, note_kill);

				/* Delete the object */
				square_excise_object(cave, y, x, obj);
				delist_object(cave, obj);
				object_delete(&obj);

				/* Redraw */
				square_note_spot(cave, y, x);
				square_light_spot(cave, y, x);
			}
		}

		/* Next object */
		obj = next;
	}

	/* Return "Anything seen?" */
	return (obvious);
}
Esempio n. 25
0
/**
 * Destroys a type of item on a given percent chance.
 * The chance 'cperc' is in hundredths of a percent (1-in-10000)
 * Note that missiles are no longer necessarily all destroyed
 *
 * Returns number of items destroyed.
 */
int inven_damage(struct player *p, int type, int cperc)
{
	int j, k, amt;
	struct object *obj = p->gear;
	char o_name[80];
	bool damage;

	/* No chance means no damage */
	if (cperc <= 0)
		return 0;

	/* Count the casualties */
	k = 0;

	/* Scan through the gear */
	while (obj) {
		struct object *next = obj->next;
		if (object_is_equipped(p->body, obj)) {
			obj = next;
			continue;
		}

		/* Hack -- for now, skip artifacts */
		if (obj->artifact) {
			obj = next;
			continue;
		}

		/* Give this item slot a shot at death if it is vulnerable */
		if ((obj->el_info[type].flags & EL_INFO_HATES) &&
			!(obj->el_info[type].flags & EL_INFO_IGNORE)) {
			/* Chance to destroy this item */
			int chance = cperc;

			/* Track if it is damaged instead of destroyed */
			damage = false;

			/* Analyze the type to see if we just damage it
			 * - we also check for rods to reduce chance */
			if (tval_is_weapon(obj) && !tval_is_ammo(obj)) {
				/* Chance to damage it */
				if (randint0(10000) < cperc) {
					/* Damage the item */
					obj->to_h--;
					if (p->obj_k->to_h)
						obj->known->to_h = obj->to_h;
					obj->to_d--;
					if (p->obj_k->to_d)
						obj->known->to_d = obj->to_d;

					/* Damaged! */
					damage = true;
				} else {
					obj = next;
					continue;
				}
			} else if (tval_is_armor(obj)) {
				/* Chance to damage it */
				if (randint0(10000) < cperc) {
					/* Damage the item */
					obj->to_a--;
					if (p->obj_k->to_a)
						obj->known->to_a = obj->to_a;

					/* Damaged! */
					damage = true;
				} else {
					obj = next;
					continue;
				}
			} else if (tval_is_rod(obj)) {
				chance = (chance / 4);
			}


			/* Damage instead of destroy */
			if (damage) {
				p->upkeep->update |= (PU_BONUS);
				p->upkeep->redraw |= (PR_EQUIP);

				/* Casualty count */
				amt = obj->number;
			} else
				/* ... or count the casualties */
				for (amt = j = 0; j < obj->number; ++j)
					if (randint0(10000) < chance) amt++;

			/* Some casualities */
			if (amt) {
				struct object *destroyed;
				bool none_left = false;

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

				/* Message */
				msgt(MSG_DESTROY, "%sour %s (%c) %s %s!",
				           ((obj->number > 1) ?
				            ((amt == obj->number) ? "All of y" :
				             (amt > 1 ? "Some of y" : "One of y")) : "Y"),
				           o_name, gear_to_label(obj),
				           ((amt > 1) ? "were" : "was"),
					   (damage ? "damaged" : "destroyed"));

				/* Damage already done? */
				if (damage)
					continue;

				/* Destroy "amt" items */
				destroyed = gear_object_for_use(obj, amt, false, &none_left);
				if (destroyed->known)
					object_delete(&destroyed->known);
				object_delete(&destroyed);

				/* Count the casualties */
				k += amt;
			}
		}
		obj = next;
	}

	/* Return the casualty count */
	return (k);
}
Esempio n. 26
0
/**
 * Wield or wear a single item from the pack or floor
 */
void inven_wield(struct object *obj, int slot)
{
	struct object *wielded, *old = player->body.slots[slot].obj;

	const char *fmt;
	char o_name[80];
	bool dummy = false;

	/* Increase equipment counter if empty slot */
	if (old == NULL)
		player->upkeep->equip_cnt++;

	/* Take a turn */
	player->upkeep->energy_use = z_info->move_energy;

	/* It's either a gear object or a floor object */
	if (object_is_carried(player, obj)) {
		/* Split off a new object if necessary */
		if (obj->number > 1) {
			wielded = gear_object_for_use(obj, 1, false, &dummy);

			/* The new item needs new gear and known gear entries */
			wielded->next = obj->next;
			obj->next = wielded;
			wielded->prev = obj;
			if (wielded->next)
				(wielded->next)->prev = wielded;
			wielded->known->next = obj->known->next;
			obj->known->next = wielded->known;
			wielded->known->prev = obj->known;
			if (wielded->known->next)
				(wielded->known->next)->prev = wielded->known;
		} else {
			/* Just use the object directly */
			wielded = obj;
		}
	} else {
		/* Get a floor item and carry it */
		wielded = floor_object_for_use(obj, 1, false, &dummy);
		inven_carry(player, wielded, false, false);
	}

	/* Wear the new stuff */
	player->body.slots[slot].obj = wielded;

	/* Do any ID-on-wield */
	object_learn_on_wield(player, wielded);

	/* Where is the item now */
	if (tval_is_melee_weapon(wielded))
		fmt = "You are wielding %s (%c).";
	else if (wielded->tval == TV_BOW)
		fmt = "You are shooting with %s (%c).";
	else if (tval_is_light(wielded))
		fmt = "Your light source is %s (%c).";
	else
		fmt = "You are wearing %s (%c).";

	/* Describe the result */
	object_desc(o_name, sizeof(o_name), wielded, ODESC_PREFIX | ODESC_FULL);

	/* Message */
	msgt(MSG_WIELD, fmt, o_name, I2A(slot));

	/* Cursed! */
	if (wielded->curses) {
		/* Warn the player */
		msgt(MSG_CURSED, "Oops! It feels deathly cold!");
	}

	/* See if we have to overflow the pack */
	combine_pack();
	pack_overflow(old);

	/* Recalculate bonuses, torch, mana, gear */
	player->upkeep->notice |= (PN_IGNORE);
	player->upkeep->update |= (PU_BONUS | PU_INVEN);
	player->upkeep->redraw |= (PR_INVEN | PR_EQUIP | PR_ARMOR);
	player->upkeep->redraw |= (PR_STATS | PR_HP | PR_MANA | PR_SPEED);

	/* Disable repeats */
	cmd_disable_repeat();
}
Esempio n. 27
0
/**
 * This is a helper function used by do_cmd_throw and do_cmd_fire.
 *
 * It abstracts out the projectile path, display code, identify and clean up
 * logic, while using the 'attack' parameter to do work particular to each
 * kind of attack.
 */
static void ranged_helper(int item, int dir, int range, int shots, ranged_attack attack) {
	/* Get the ammo */
	object_type *o_ptr = object_from_item_idx(item);

	int i, j;
	byte missile_attr = object_attr(o_ptr);
	char missile_char = object_char(o_ptr);

	object_type object_type_body;
	object_type *i_ptr = &object_type_body;

	char o_name[80];

	int path_n;
	u16b path_g[256];

	int msec = op_ptr->delay_factor;

	/* Start at the player */
	int x = p_ptr->px;
	int y = p_ptr->py;

	/* Predict the "target" location */
	s16b ty = y + 99 * ddy[dir];
	s16b tx = x + 99 * ddx[dir];

	bool hit_target = FALSE;

	/* Check for target validity */
	if ((dir == 5) && target_okay()) {
		int taim;
		char msg[80];
		target_get(&tx, &ty);
		taim = distance(y, x, ty, tx);
		if (taim > range) {
			sprintf (msg, "Target out of range by %d squares. Fire anyway? ",
				taim - range);
			if (!get_check(msg)) return;
		}
	}

	/* Sound */
	sound(MSG_SHOOT);

	object_notice_on_firing(o_ptr);

	/* Describe the object */
	object_desc(o_name, sizeof(o_name), o_ptr, ODESC_FULL | ODESC_SINGULAR);

	/* Actually "fire" the object -- Take a partial turn */
	p_ptr->energy_use = (100 / shots);

	/* Calculate the path */
	path_n = project_path(path_g, range, y, x, ty, tx, 0);

	/* Hack -- Handle stuff */
	handle_stuff(p_ptr);

	/* Start at the player */
	x = p_ptr->px;
	y = p_ptr->py;

	/* Project along the path */
	for (i = 0; i < path_n; ++i) {
		int ny = GRID_Y(path_g[i]);
		int nx = GRID_X(path_g[i]);

		/* Hack -- Stop before hitting walls */
		if (!cave_floor_bold(ny, nx)) break;

		/* Advance */
		x = nx;
		y = ny;

		/* Only do visuals if the player can "see" the missile */
		if (player_can_see_bold(y, x)) {
			print_rel(missile_char, missile_attr, y, x);
			move_cursor_relative(y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff(p_ptr);

			Term_xtra(TERM_XTRA_DELAY, msec);
			cave_light_spot(cave, y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff(p_ptr);
		} else {
			/* Delay anyway for consistency */
			Term_xtra(TERM_XTRA_DELAY, msec);
		}

		/* Handle monster */
		if (cave->m_idx[y][x] > 0) break;
	}

	/* Try the attack on the monster at (x, y) if any */
	if (cave->m_idx[y][x] > 0) {
		monster_type *m_ptr = cave_monster(cave, cave->m_idx[y][x]);
		monster_race *r_ptr = &r_info[m_ptr->r_idx];
		int visible = m_ptr->ml;

		bool fear = FALSE;
		char m_name[80];
		const char *note_dies = monster_is_unusual(r_ptr) ? " is destroyed." : " dies.";

		struct attack_result result = attack(o_ptr, y, x);
		int dmg = result.dmg;
		u32b msg_type = result.msg_type;
		const char *hit_verb = result.hit_verb;

		if (result.success) {
			hit_target = TRUE;

			/* Get "the monster" or "it" */
			monster_desc(m_name, sizeof(m_name), m_ptr, 0);
		
			object_notice_attack_plusses(o_ptr);
		
			/* No negative damage; change verb if no damage done */
			if (dmg <= 0) {
				dmg = 0;
				hit_verb = "fail to harm";
			}
		
			if (!visible) {
				/* Invisible monster */
				msgt(MSG_SHOOT_HIT, "The %s finds a mark.", o_name);
			} else {
				/* Visible monster */
				if (msg_type == MSG_SHOOT_HIT)
					msgt(MSG_SHOOT_HIT, "The %s %s %s.", o_name, hit_verb, m_name);
				else if (msg_type == MSG_HIT_GOOD) {
					msgt(MSG_HIT_GOOD, "The %s %s %s. %s", o_name, hit_verb, m_name, "It was a good hit!");
				} else if (msg_type == MSG_HIT_GREAT) {
					msgt(MSG_HIT_GREAT, "The %s %s %s. %s", o_name, hit_verb, m_name,
						 "It was a great hit!");
				} else if (msg_type == MSG_HIT_SUPERB) {
					msgt(MSG_HIT_SUPERB, "The %s %s %s. %s", o_name, hit_verb, m_name,
						 "It was a superb hit!");
				}
		
				/* Track this monster */
				if (m_ptr->ml) monster_race_track(m_ptr->r_idx);
				if (m_ptr->ml) health_track(p_ptr, cave->m_idx[y][x]);
			}
		
			/* Complex message */
			if (p_ptr->wizard)
				msg("You do %d (out of %d) damage.", dmg, m_ptr->hp);
		
			/* Hit the monster, check for death */
			if (!mon_take_hit(cave->m_idx[y][x], dmg, &fear, note_dies)) {
				message_pain(cave->m_idx[y][x], dmg);
				if (fear && m_ptr->ml)
					add_monster_message(m_name, cave->m_idx[y][x], MON_MSG_FLEE_IN_TERROR, TRUE);
			}
		}
	}

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

	/* See if the ammunition broke or not */
	j = breakage_chance(i_ptr, hit_target);

	/* Drop (or break) near that location */
	drop_near(cave, i_ptr, j, y, x, TRUE);

	if (item >= 0) {
		/* The ammo is from the inventory */
		inven_item_increase(item, -1);
		inven_item_describe(item);
		inven_item_optimize(item);
	} else {
		/* The ammo is from the floor */
		floor_item_increase(0 - item, -1);
		floor_item_optimize(0 - item);
	}
}
Esempio n. 28
0
/**
 * Attack the monster at the given location with a single blow.
 */
static bool py_attack_real(int y, int x, bool *fear) {
	/* Information about the target of the attack */
	monster_type *m_ptr = cave_monster(cave, cave->m_idx[y][x]);
	monster_race *r_ptr = &r_info[m_ptr->r_idx];
	char m_name[80];
	bool stop = FALSE;

	/* The weapon used */
	object_type *o_ptr = &p_ptr->inventory[INVEN_WIELD];

	/* Information about the attack */
	int bonus = p_ptr->state.to_h + o_ptr->to_h;
	int chance = p_ptr->state.skills[SKILL_TO_HIT_MELEE] + bonus * BTH_PLUS_ADJ;
	bool do_quake = FALSE;
	bool success = FALSE;

	/* Default to punching for one damage */
	const char *hit_verb = "punch";
	int dmg = 1;
	u32b msg_type = MSG_HIT;

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

	/* Auto-Recall if possible and visible */
	if (m_ptr->ml) monster_race_track(m_ptr->r_idx);

	/* Track a new monster */
	if (m_ptr->ml) health_track(p_ptr, cave->m_idx[y][x]);

	/* Handle player fear (only for invisible monsters) */
	if (check_state(p_ptr, OF_AFRAID, p_ptr->state.flags)) {
		msgt(MSG_AFRAID, "You are too afraid to attack %s!", m_name);
		return FALSE;
	}

	/* Disturb the monster */
	mon_clear_timed(cave->m_idx[y][x], MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE);

	/* See if the player hit */
	success = test_hit(chance, r_ptr->ac, m_ptr->ml);

	/* If a miss, skip this hit */
	if (!success) {
		msgt(MSG_MISS, "You miss %s.", m_name);
		return FALSE;
	}

	/* Handle normal weapon */
	if (o_ptr->kind) {
		int i;
		const struct slay *best_s_ptr = NULL;

		hit_verb = "hit";

		/* Get the best attack from all slays or
		 * brands on all non-launcher equipment */
		for (i = INVEN_LEFT; i < INVEN_TOTAL; i++) {
			struct object *obj = &p_ptr->inventory[i];
			if (obj->kind)
				improve_attack_modifier(obj, m_ptr, &best_s_ptr, TRUE, FALSE);
		}

		improve_attack_modifier(o_ptr, m_ptr, &best_s_ptr, TRUE, FALSE);
		if (best_s_ptr != NULL)
			hit_verb = best_s_ptr->melee_verb;

		dmg = damroll(o_ptr->dd, o_ptr->ds);
		dmg *= (best_s_ptr == NULL) ? 1 : best_s_ptr->mult;

		dmg += o_ptr->to_d;
		dmg = critical_norm(o_ptr->weight, o_ptr->to_h, dmg, &msg_type);

		/* Learn by use for the weapon */
		object_notice_attack_plusses(o_ptr);

		if (check_state(p_ptr, OF_IMPACT, p_ptr->state.flags) && dmg > 50) {
			do_quake = TRUE;
			wieldeds_notice_flag(p_ptr, OF_IMPACT);
		}
	}

	/* Learn by use for other equipped items */
	wieldeds_notice_on_attack();

	/* Apply the player damage bonuses */
	dmg += p_ptr->state.to_d;

	/* No negative damage */
	if (dmg <= 0) dmg = 0;

	/* Tell the player what happened */
	if (dmg <= 0)
		msgt(MSG_MISS, "You fail to harm %s.", m_name);
	else if (msg_type == MSG_HIT)
		msgt(MSG_HIT, "You %s %s.", hit_verb, m_name);
	else if (msg_type == MSG_HIT_GOOD)
		msgt(MSG_HIT_GOOD, "You %s %s. %s", hit_verb, m_name, "It was a good hit!");
	else if (msg_type == MSG_HIT_GREAT)
		msgt(MSG_HIT_GREAT, "You %s %s. %s", hit_verb, m_name, "It was a great hit!");
	else if (msg_type == MSG_HIT_SUPERB)
		msgt(MSG_HIT_SUPERB, "You %s %s. %s", hit_verb, m_name, "It was a superb hit!");
	else if (msg_type == MSG_HIT_HI_GREAT)
		msgt(MSG_HIT_HI_GREAT, "You %s %s. %s", hit_verb, m_name, "It was a *GREAT* hit!");
	else if (msg_type == MSG_HIT_HI_SUPERB)
		msgt(MSG_HIT_HI_SUPERB, "You %s %s. %s", hit_verb, m_name, "It was a *SUPERB* hit!");

	/* Complex message */
	if (p_ptr->wizard)
		msg("You do %d (out of %d) damage.", dmg, m_ptr->hp);

	/* Confusion attack */
	if (p_ptr->confusing) {
		p_ptr->confusing = FALSE;
		msg("Your hands stop glowing.");

		mon_inc_timed(cave->m_idx[y][x], MON_TMD_CONF,
				(10 + randint0(p_ptr->lev) / 10), MON_TMD_FLG_NOTIFY);
	}

	/* Damage, check for fear and death */
	stop = mon_take_hit(cave->m_idx[y][x], dmg, fear, NULL);

	if (stop)
		(*fear) = FALSE;

	/* Apply earthquake brand */
	if (do_quake) {
		earthquake(p_ptr->py, p_ptr->px, 10);
		if (cave->m_idx[y][x] == 0) stop = TRUE;
	}

	return stop;
}
Esempio n. 29
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;
}
Esempio n. 30
0
/**
 * Move player in the given direction.
 *
 * This routine should only be called when energy has been expended.
 *
 * Note that this routine handles monsters in the destination grid,
 * and also handles attempting to move into walls/doors/rubble/etc.
 */
void move_player(int dir, bool disarm)
{
	int y = player->py + ddy[dir];
	int x = player->px + ddx[dir];

	int m_idx = cave->squares[y][x].mon;
	struct monster *mon = cave_monster(cave, m_idx);
	bool alterable = (square_isknowntrap(cave, y, x) ||
					  square_iscloseddoor(cave, y, x));

	/* Attack monsters, alter traps/doors on movement, hit obstacles or move */
	if (m_idx > 0) {
		/* Mimics surprise the player */
		if (is_mimicking(mon)) {
			become_aware(mon);

			/* Mimic wakes up */
			mon_clear_timed(mon, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, false);

		} else {
			py_attack(y, x);
		}
	} else if (disarm && square_isknown(cave, y, x) && alterable) {
		/* Auto-repeat if not already repeating */
		if (cmd_get_nrepeats() == 0)
			cmd_set_repeat(99);

		do_cmd_alter_aux(dir);
	} else if (player->upkeep->running && square_isknowntrap(cave, y, x)) {
		/* Stop running before known traps */
		disturb(player, 0);
	} else if (!square_ispassable(cave, y, x)) {
		disturb(player, 0);

		/* Notice unknown obstacles, mention known obstacles */
		if (!square_isknown(cave, y, x)) {
			if (square_isrubble(cave, y, x)) {
				msgt(MSG_HITWALL,
					 "You feel a pile of rubble blocking your way.");
				square_memorize(cave, y, x);
				square_light_spot(cave, y, x);
			} else if (square_iscloseddoor(cave, y, x)) {
				msgt(MSG_HITWALL, "You feel a door blocking your way.");
				square_memorize(cave, y, x);
				square_light_spot(cave, y, x);
			} else {
				msgt(MSG_HITWALL, "You feel a wall blocking your way.");
				square_memorize(cave, y, x);
				square_light_spot(cave, y, x);
			}
		} else {
			if (square_isrubble(cave, y, x))
				msgt(MSG_HITWALL,
					 "There is a pile of rubble blocking your way.");
			else if (square_iscloseddoor(cave, y, x))
				msgt(MSG_HITWALL, "There is a door blocking your way.");
			else
				msgt(MSG_HITWALL, "There is a wall blocking your way.");
		}
	} else {
		/* Move player */
		monster_swap(player->py, player->px, y, x);

		/* Handle store doors, or notice objects */
		if (square_isshop(cave, y, x)) {
			disturb(player, 0);
			event_signal(EVENT_ENTER_STORE);
			event_remove_handler_type(EVENT_ENTER_STORE);
			event_signal(EVENT_USE_STORE);
			event_remove_handler_type(EVENT_USE_STORE);
			event_signal(EVENT_LEAVE_STORE);
			event_remove_handler_type(EVENT_LEAVE_STORE);
		} else {
			square_know_pile(cave, y, x);
			cmdq_push(CMD_AUTOPICKUP);
		}

		/* Discover invisible traps, set off visible ones */
		if (square_issecrettrap(cave, y, x)) {
			disturb(player, 0);
			hit_trap(y, x);
		} else if (square_isknowntrap(cave, y, x)) {
			disturb(player, 0);
			hit_trap(y, x);
		}

		/* Update view and search */
		update_view(cave, player);
		search();
	}

	player->upkeep->running_firststep = false;
}