Exemple #1
0
/* Is the player capable of casting a spell? */
bool player_can_cast(void)
{
	/* Races without Horns or Hands cannot cast arcane spells */
	if((!rp_ptr->num_rings) && p_ptr->cumber_glove) {
	    msg("You need a horn or hands to cast arcane spells.");
	    return FALSE;
	}
	
    if (player_has(PF_PROBE)) {
		if (p_ptr->lev < 35) {
			msg("You do not know how to probe monsters yet.");
			return FALSE;
		} else if ((p_ptr->timed[TMD_CONFUSED])
				   || (p_ptr->timed[TMD_IMAGE])) {
			msg("You feel awfully confused.");
			return FALSE;
		}
	}

	if (p_ptr->timed[TMD_BLIND] || no_light()) {
		msg("You cannot see!");
		return FALSE;
	}

	if (p_ptr->timed[TMD_CONFUSED]) {
		msg("You are too confused!");
		return FALSE;
	}

	return TRUE;
}
Exemple #2
0
/* Determine if the player can read scrolls. */
bool player_can_read(void)
{
	if (p_ptr->timed[TMD_BLIND])
	{
		msg_print("You can't see anything.");
		return FALSE;
	}

	if (no_light())
	{
		msg_print("You have no light to read by.");
		return FALSE;
	}

	if (p_ptr->timed[TMD_CONFUSED])
	{
		msg_print("You are too confused to read!");
		return FALSE;
	}

	if (p_ptr->timed[TMD_AMNESIA])
	{
		msg_print("You can't remember how to read!");
		return FALSE;
	}

	return TRUE;
}
Exemple #3
0
/**
 * Turn a basic monster trap into an advanced one -BR-
 */
extern bool py_modify_trap(int y, int x)
{
    if (p_ptr->timed[TMD_BLIND] || no_light()) {
        msg_print("You can not see to modify your trap.");
        return FALSE;
    }

    if (p_ptr->timed[TMD_CONFUSED] || p_ptr->timed[TMD_IMAGE]) {
        msg_print("You are too confused.");
        return FALSE;
    }

    /* No setting traps while shapeshifted */
    if (SCHANGE) {
        msg_print("You can not set traps while shapechanged.");
        msg_print("Use the ']' command to return to your normal form.");
        return FALSE;
    }

    trap_y = y;
    trap_x = x;

    /* get choice */
    if (trap_menu()) {
        /* Notify the player. */
        msg_print("You modify the monster trap.");
    }

    /* Trap was modified */
    return TRUE;
}
Exemple #4
0
/* Is the player capable of casting a spell? */
bool player_can_cast(void)
{
    if (player_has(PF_PROBE)) {
        if (p_ptr->lev < 35) {
            msg("You do not know how to probe monsters yet.");
            return FALSE;
        } else if ((p_ptr->timed[TMD_CONFUSED])
                   || (p_ptr->timed[TMD_IMAGE])) {
            msg("You feel awfully confused.");
            return FALSE;
        }
    }

    if (p_ptr->timed[TMD_BLIND] || no_light()) {
        msg("You cannot see!");
        return FALSE;
    }

    if (p_ptr->timed[TMD_CONFUSED]) {
        msg("You are too confused!");
        return FALSE;
    }

    return TRUE;
}
Exemple #5
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);
}
Exemple #6
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);
}
Exemple #7
0
/**
 * Perform the command "lock door"
 *
 * Assume there is no monster blocking the destination
 *
 * Returns true if repeated commands may continue
 */
static bool do_cmd_lock_door(int y, int x)
{
	int i, j, power;
	bool more = false;

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

	/* Get the "disarm" factor */
	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;

	/* Calculate lock "power" */
	power = m_bonus(7, player->depth);

	/* Extract the difficulty */
	j = i - power;

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

	/* Success */
	if (randint0(100) < j) {
		msg("You lock the door.");
		square_set_door_lock(cave, y, x, power);
	}

	/* Failure -- Keep trying */
	else if ((i > 5) && (randint1(i) > 5)) {
		event_signal(EVENT_INPUT_FLUSH);
		msg("You failed to lock the door.");

		/* We may keep trying */
		more = true;
	}
	/* Failure */
	else
		msg("You failed to lock the door.");

	/* Result */
	return more;
}
Exemple #8
0
/*
 * Perform the command "lock door"
 *
 * Assume there is no monster blocking the destination
 *
 * Returns TRUE if repeated commands may continue
 */
static bool do_cmd_lock_door(int y, int x)
{
	int i, j, power;
	bool more = FALSE;

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

	/* Get the "disarm" factor */
	i = p_ptr->state.skills[SKILL_DISARM];

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

	/* Calculate lock "power" */
	power = m_bonus(7, p_ptr->depth);

	/* Extract the difficulty */
	j = i - power;

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

	/* Success */
	if (randint0(100) < j) {
		msg("You lock the door.");
		cave_set_feat(cave, y, x, FEAT_DOOR_HEAD + power);
	}

	/* Failure -- Keep trying */
	else if ((i > 5) && (randint1(i) > 5)) {
		flush();
		msg("You failed to lock the door.");

		/* We may keep trying */
		more = TRUE;
	}
	/* Failure */
	else
		msg("You failed to lock the door.");

	/* Result */
	return more;
}
Exemple #9
0
/**
 * Search for traps or secret doors
 */
static void search(void)
{
	int py = player->py;
	int px = player->px;
	int y, x;
	struct object *obj;

	/* Various conditions mean no searching */
	if (player->timed[TMD_BLIND] || no_light() ||
		player->timed[TMD_CONFUSED] || player->timed[TMD_IMAGE])
		return;

	/* Search the nearby grids, which are always in bounds */
	for (y = (py - 1); y <= (py + 1); y++) {
		for (x = (px - 1); x <= (px + 1); x++) {
			/* Traps */
			if (square_issecrettrap(cave, y, x)) {
				if (square_reveal_trap(cave, y, x, true))
					disturb(player, 0);
			}

			/* Secret doors */
			if (square_issecretdoor(cave, y, x)) {
				msg("You have found a secret door.");
				place_closed_door(cave, y, x);
				disturb(player, 0);
			}

			/* Traps on chests */
			for (obj = square_object(cave, y, x); obj; obj = obj->next) {
				if (!obj->known || !is_trapped_chest(obj))
					continue;

				if (obj->known->pval != obj->pval) {
					msg("You have discovered a trap on the chest!");
					obj->known->pval = obj->pval;
					disturb(player, 0);
				}
			}
		}
	}
}
Exemple #10
0
/* Is the player capable of casting a spell? */
bool player_can_cast(void)
{
	if (!cp_ptr->spell_book)
	{
		msg_print("You cannot pray or produce magics.");
		return FALSE;
	}

	if (p_ptr->timed[TMD_BLIND] || no_light())
	{
		msg_print("You cannot see!");
		return FALSE;
	}

	if (p_ptr->timed[TMD_CONFUSED])
	{
		msg_print("You are too confused!");
		return FALSE;
	}

	return TRUE;
}
Exemple #11
0
/*
 * Attempt to open the given chest at the given location
 *
 * Assume there is no monster blocking the destination
 *
 * Returns TRUE if repeated commands may continue
 */
bool do_cmd_open_chest(int y, int x, s16b o_idx)
{
	int i, j;

	bool flag = TRUE;

	bool more = FALSE;

	object_type *o_ptr = object_byid(o_idx);


	/* Attempt to unlock it */
	if (o_ptr->pval[DEFAULT_PVAL] > 0)
	{
		/* Assume locked, and thus not open */
		flag = FALSE;

		/* Get the "disarm" factor */
		i = p_ptr->state.skills[SKILL_DISARM];

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

		/* Extract the difficulty */
		j = i - o_ptr->pval[DEFAULT_PVAL];

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

		/* Success -- May still have traps */
		if (randint0(100) < j)
		{
			msgt(MSG_LOCKPICK, "You have picked the lock.");
			player_exp_gain(p_ptr, 1);
			flag = TRUE;
		}

		/* Failure -- Keep trying */
		else
		{
			/* We may continue repeating */
			more = TRUE;
			flush();
			msgt(MSG_LOCKPICK_FAIL, "You failed to pick the lock.");
		}
	}

	/* Allowed to open */
	if (flag)
	{
		/* Apply chest traps, if any */
		chest_trap(y, x, o_idx);

		/* Let the Chest drop items */
		chest_death(y, x, o_idx);

		/* Squelch chest if autosquelch calls for it */
		p_ptr->notice |= PN_SQUELCH;

	}

	/*
	 * empty chests were always squelched in squelch_item_okay so we
	 * might as well squelch it here
	 */
	if (o_ptr->pval[DEFAULT_PVAL] == 0) {
		o_ptr->ignore = TRUE;
	}

	/* Redraw chest, to be on the safe side (it may have been squelched) */
	cave_light_spot(cave, y, x);

	/* Refresh */
	Term_fresh();

	/* Result */
	return (more);
}
/**
 * Attempt to open the given chest at the given location
 *
 * Assume there is no monster blocking the destination
 *
 * Returns TRUE if repeated commands may continue
 */
bool do_cmd_open_chest(int y, int x, struct object *obj)
{
	int i, j;

	bool flag = TRUE;

	bool more = FALSE;

	/* Attempt to unlock it */
	if (obj->pval > 0) {
		/* Assume locked, and thus not open */
		flag = FALSE;

		/* Get the "disarm" factor */
		i = player->state.skills[SKILL_DISARM];

		/* 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;

		/* Success -- May still have traps */
		if (randint0(100) < j) {
			msgt(MSG_LOCKPICK, "You have picked the lock.");
			player_exp_gain(player, 1);
			flag = TRUE;
		} else {
			/* We may continue repeating */
			more = TRUE;
			event_signal(EVENT_INPUT_FLUSH);
			msgt(MSG_LOCKPICK_FAIL, "You failed to pick the lock.");
		}
	}

	/* Allowed to open */
	if (flag) {
		/* Apply chest traps, if any */
		chest_trap(y, x, obj);

		/* Let the Chest drop items */
		chest_death(y, x, obj);

		/* Ignore chest if autoignore calls for it */
		player->upkeep->notice |= PN_IGNORE;
	}

	/* Empty chests were always ignored in ignore_item_okay so we
	 * might as well ignore it here
	 */
	if (obj->pval == 0)
		obj->ignore = TRUE;

	/* Redraw chest, to be on the safe side (it may have been ignored) */
	square_light_spot(cave, y, x);

	/* Result */
	return (more);
}
Exemple #13
0
/*
 * Perform the basic "open" command on doors
 *
 * Assume there is no monster blocking the destination
 *
 * Returns TRUE if repeated commands may continue
 */
static bool do_cmd_open_aux(int y, int x)
{
	int i, j;

	bool more = FALSE;


	/* Verify legality */
	if (!do_cmd_open_test(y, x)) return (FALSE);


	/* Locked door */
	if (cave_islockeddoor(cave, y, x))
	{
		/* Disarm factor */
		i = p_ptr->state.skills[SKILL_DISARM];

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

		/* Extract the lock power */
		j = cave_door_power(cave, y, x);

		/* Extract the difficulty XXX XXX XXX */
		j = i - (j * 4);

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

		/* Success */
		if (randint0(100) < j)
		{
			/* Message */
			msgt(MSG_LOCKPICK, "You have picked the lock.");

			/* Open the door */
			cave_open_door(cave, y, x);

			/* Update the visuals */
			p_ptr->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

			/* Experience */
			/* Removed to avoid exploit by repeatedly locking and unlocking door */
			/* player_exp_gain(p_ptr, 1); */
		}

		/* Failure */
		else
		{
			flush();

			/* Message */
			msgt(MSG_LOCKPICK_FAIL, "You failed to pick the lock.");

			/* We may keep trying */
			more = TRUE;
		}
	}

	/* Closed door */
	else
	{
		/* Open the door */
		cave_open_door(cave, y, x);

		/* Update the visuals */
		p_ptr->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

		/* Sound */
		sound(MSG_OPENDOOR);
	}

	/* Result */
	return (more);
}
Exemple #14
0
/**
 * Search for hidden things.  Returns true if a search was attempted, returns
 * false when the player has a 0% chance of finding anything.  Prints messages
 * for negative confirmation when verbose mode is requested.
 */
bool search(bool verbose)
{
	int py = player->py;
	int px = player->px;
	int y, x, chance;
	bool found = false;
	struct object *obj;

	/* Start with base search ability */
	chance = player->state.skills[SKILL_SEARCH];

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

	/* Prevent fruitless searches */
	if (chance <= 0) {
		if (verbose) {
			msg("You can't make out your surroundings well enough to search.");

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

		return false;
	}

	/* Search the nearby grids, which are always in bounds */
	for (y = (py - 1); y <= (py + 1); y++) {
		for (x = (px - 1); x <= (px + 1); x++) {
			/* Sometimes, notice things */
			if (randint0(100) < chance) {
				if (square_issecrettrap(cave, y, x)) {
					found = true;

					/* Reveal trap, display a message */
					if (square_reveal_trap(cave, y, x, chance, true))
						/* Disturb */
						disturb(player, 0);
				}

				/* Secret door */
				if (square_issecretdoor(cave, y, x)) {
					found = true;

					/* Message */
					msg("You have found a secret door.");

					/* Pick a door */
					place_closed_door(cave, y, x);

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

				/* Scan all objects in the grid */
				for (obj = square_object(cave, y, x); obj; obj = obj->next) {
					/* Skip if not a trapped chest */
					if (!is_trapped_chest(obj)) continue;

					/* Identify once */
					if (!object_is_known(obj)) {
						found = true;

						/* Message */
						msg("You have discovered a trap on the chest!");

						/* Know the trap */
						object_notice_everything(obj);

						/* Notice it */
						disturb(player, 0);
					}
				}
			}
		}
	}

	if (verbose && !found) {
		if (chance >= 100)
			msg("There are no secrets here.");
		else
			msg("You found nothing.");
	}

	return true;
}
Exemple #15
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 i, j, power;
    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 "disarm" factor */
	i = player->state.skills[SKILL_DISARM];

	/* 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;

	/* XXX XXX XXX Variable power? */

	/* Extract trap "power" */
	power = 5;

	/* Extract the difficulty */
	j = i - power;

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

	/* Success */
	if (randint0(100) < j) {
		/* Message */
		msgt(MSG_DISARM, "You have disarmed the %s.", trap->kind->name);

		/* Reward */
		player_exp_gain(player, power);

		/* Forget the trap */
		square_forget(cave, y, x);

		/* Remove the trap */
		square_destroy_trap(cave, y, x);
	} else if ((i > 5) && (randint1(i) > 5)) {
		/* Failure -- Keep trying */
		event_signal(EVENT_INPUT_FLUSH);
		msg("You failed to disarm the %s.", trap->kind->name);
		more = true;
	} else {
		/* Failure -- Set off the trap */
		msg("You set off the %s!", trap->kind->name);
		hit_trap(y, x);
	}

	/* Result */
	return (more);
}
Exemple #16
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, s16b o_idx)
{
	int i, j;

	bool more = FALSE;

	object_type *o_ptr = object_byid(o_idx);


	/* Get the "disarm" factor */
	i = p_ptr->state.skills[SKILL_DISARM];

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

	/* Extract the difficulty */
	j = i - o_ptr->pval[DEFAULT_PVAL];

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

	/* Must find the trap first. */
	if (!object_is_known(o_ptr))
	{
		msg("I don't see any traps.");
	}

	/* Already disarmed/unlocked or no traps */
	else if (!is_trapped_chest(o_ptr))
	{
		msg("The chest is not trapped.");
	}

	/* Success (get a lot of experience) */
	else if (randint0(100) < j)
	{
		msgt(MSG_DISARM, "You have disarmed the chest.");
		player_exp_gain(p_ptr, o_ptr->pval[DEFAULT_PVAL]);
		o_ptr->pval[DEFAULT_PVAL] = (0 - o_ptr->pval[DEFAULT_PVAL]);
	}

	/* Failure -- Keep trying */
	else if ((i > 5) && (randint1(i) > 5))
	{
		/* We may keep trying */
		more = TRUE;
		flush();
		msg("You failed to disarm the chest.");
	}

	/* Failure -- Set off the trap */
	else
	{
		msg("You set off a trap!");
		chest_trap(y, x, o_idx);
	}

	/* Result */
	return (more);
}
Exemple #17
0
/**
 * Rogues may steal gold from monsters.  The monster needs to have
 * something to steal (it must drop some form of loot), and should
 * preferably be asleep.  Humanoids and dragons are a rogue's favorite
 * targets.  Steal too often on a level, and monsters will be more wary,
 * and the hue and cry will be eventually be raised.  Having every
 * monster on the level awake and aggravated is not pleasant. -LM-
 */
extern void py_steal(int y, int x)
{
    cptr act = NULL;

    monster_type *m_ptr = &m_list[cave_m_idx[y][x]];
    monster_race *r_ptr = &r_info[m_ptr->r_idx];

    char m_name[80];

    int i;
    int effect, theft_protection;
    int filching_power = 0;
    int purse = 0;

    bool thief = FALSE;
    bool success = FALSE;

    /* Check intent */
    if ((m_ptr->hostile != -1)
            && !get_check("Do you want to steal from this being?")) {
        py_attack(y, x, FALSE);
        return;
    }

    /* Hard limit on theft. */
    if (number_of_thefts_on_level > 4) {
        msg_print
        ("Everyone is keeping a lookout for you.  You can steal nothing here.");
        return;
    }

    /* Determine the cunning of the thief. */
    filching_power = 2 * p_ptr->lev;

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

    /* Determine how much protection the monster has. */
    theft_protection = (7 * (r_ptr->level + 2) / 4);
    theft_protection += (m_ptr->mspeed - p_ptr->state.pspeed);
    if (theft_protection < 1)
        theft_protection = 1;

    /* Send a thief to catch a thief. */
    for (i = 0; i < 4; i++) {
        /* Extract infomation about the blow effect */
        effect = r_ptr->blow[i].effect;
        if (effect == RBE_EAT_GOLD)
            thief = TRUE;
        if (effect == RBE_EAT_ITEM)
            thief = TRUE;
    }
    if (thief)
        theft_protection += 30;

    if (m_ptr->csleep)
        theft_protection = 3 * theft_protection / 5;

    /* Special player stealth magics aid stealing, but are lost in the process */
    if (p_ptr->timed[TMD_SSTEALTH]) {
        theft_protection = 3 * theft_protection / 5;
        (void) clear_timed(TMD_SSTEALTH, TRUE);
    }

    /* The more you steal on a level, the more wary the monsters. */
    theft_protection += number_of_thefts_on_level * 15;

    /* Did the theft succeed? */
    if (randint1(theft_protection) < filching_power)
        success = TRUE;


    /* If the theft succeeded, determine the value of the purse. */
    if (success) {
        purse = (r_ptr->level + 1) + randint1(3 * (r_ptr->level + 1) / 2);

        /* Uniques are juicy targets. */
        if (rf_has(r_ptr->flags, RF_UNIQUE))
            purse *= 3;

        /* But some monsters are dirt poor. */
        if (!(rf_has(r_ptr->flags, RF_DROP_60))
                || rf_has(r_ptr->flags, RF_DROP_90)
                || rf_has(r_ptr->flags, RF_DROP_1D2)
                || rf_has(r_ptr->flags, RF_DROP_2D2)
                || rf_has(r_ptr->flags, RF_DROP_3D2)
                || rf_has(r_ptr->flags, RF_DROP_4D2))
            purse = 0;

        /* Some monster races are far better to steal from than others. */
        if ((r_ptr->d_char == 'D') || (r_ptr->d_char == 'd')
                || (r_ptr->d_char == 'p') || (r_ptr->d_char == 'h'))
            purse *= 2 + randint1(3) + randint1(r_ptr->level / 20);
        else if ((r_ptr->d_char == 'P') || (r_ptr->d_char == 'o')
                 || (r_ptr->d_char == 'O') || (r_ptr->d_char == 'T')
                 || (r_ptr->d_char == 'n') || (r_ptr->d_char == 'W')
                 || (r_ptr->d_char == 'k') || (r_ptr->d_char == 'L')
                 || (r_ptr->d_char == 'V') || (r_ptr->d_char == 'y'))
            purse *= 1 + randint1(3) + randint1(r_ptr->level / 30);

        /* Pickings are scarce in a land of many thieves. */
        purse = purse * (p_ptr->depth + 5) / (p_ptr->recall[0] + 5);

        /* Increase player gold. */
        p_ptr->au += purse;

        /* Limit to avoid buffer overflow */
        if (p_ptr->au > PY_MAX_GOLD)
            p_ptr->au = PY_MAX_GOLD;

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

        /* Announce the good news. */
        if (purse)
            msg_format("You burgle %d gold.", purse);

        /* Pockets are empty. */
        else
            msg_print("You burgle only dust.");
    }

    /* The victim normally, but not always, wakes up and is aggravated. */
    if (randint1(4) != 1) {
        m_ptr->csleep = 0;
        m_ptr->mflag |= (MFLAG_ACTV);
        if (m_ptr->mspeed < r_ptr->speed + 3)
            m_ptr->mspeed += 10;

        /* Become hostile */
        m_ptr->hostile = -1;

        /* Occasionally, amuse the player with a message. */
        if ((randint1(5) == 1) && (purse) && (rf_has(r_ptr->flags, RF_SMART))) {
            monster_desc(m_name, sizeof(m_name), m_ptr, 0);
            act = desc_victim_outcry[randint0(20)];
            msg_format("%^s cries out %s", m_name, act);
        }
        /* Otherwise, simply explain what happened. */
        else {
            monster_desc(m_name, sizeof(m_name), m_ptr, 0);
            msg_format("You have aroused %s.", m_name);
        }
    }

    /* The thief also speeds up, but only for just long enough to escape. */
    if (!p_ptr->timed[TMD_FAST])
        p_ptr->timed[TMD_FAST] += 2;

    /* Recalculate bonuses */
    p_ptr->update |= (PU_BONUS);

    /* Handle stuff */
    handle_stuff();


    /* Increment the number of thefts, and possibly raise the hue and cry. */
    number_of_thefts_on_level++;

    if (number_of_thefts_on_level > 4) {
        /* Notify the player of the trouble he's in. */
        msg_print("All the level is in an uproar over your misdeeds!");

        /* Aggravate and speed up all monsters on level. */
        (void) aggravate_monsters(1, TRUE);
    }

    else if ((number_of_thefts_on_level > 2) || (randint1(8) == 1)) {
        msg_print
        ("You hear hunting parties scouring the area for a notorious burgler.");

        /* Aggravate monsters nearby. */
        (void) aggravate_monsters(1, FALSE);
    }

    /* Rogue "Hit and Run" attack. */
    if (p_ptr->special_attack & (ATTACK_FLEE)) {
        /* Cancel the fleeing spell */
        p_ptr->special_attack &= ~(ATTACK_FLEE);

        /* Message */
        msg_print("You escape into the shadows!");

        /* Teleport. */
        teleport_player(6 + p_ptr->lev / 5, TRUE);

        /* Redraw the state */
        p_ptr->redraw |= (PR_STATUS);
    }
}
Exemple #18
0
/**
 * Rogues may set traps.  Only one such trap may exist at any one time,
 * but an old trap can be disarmed to free up equipment for a new trap.
 * -LM-
 */
extern bool py_set_trap(int y, int x)
{
    int max_traps;
    s16b this_o_idx, next_o_idx = 0;
    object_type *o_ptr;
    bool destroy_message = FALSE;

    max_traps =
        1 + ((p_ptr->lev >= 25) ? 1 : 0) +
        (player_has(PF_EXTRA_TRAP) ? 1 : 0);

    if (p_ptr->timed[TMD_BLIND] || no_light()) {
        msg_print("You can not see to set a trap.");
        return FALSE;
    }

    if (p_ptr->timed[TMD_CONFUSED] || p_ptr->timed[TMD_IMAGE]) {
        msg_print("You are too confused.");
        return FALSE;
    }

    /* Paranoia -- Forbid more than max_traps being set. */
    if (num_trap_on_level >= max_traps) {
        msg_print
        ("You must disarm your existing trap to free up your equipment.");
        return FALSE;
    }

    /* No setting traps while shapeshifted */
    if (SCHANGE) {
        msg_print("You can not set traps while shapechanged.");
        msg_print("Use the ']' command to return to your normal form.");
        return FALSE;
    }

    /* Scan all objects in the grid */
    for (this_o_idx = cave_o_idx[y][x]; this_o_idx; this_o_idx = next_o_idx) {
        /* Acquire object */
        o_ptr = &o_list[this_o_idx];

        /* Acquire next object */
        next_o_idx = o_ptr->next_o_idx;

        /* Artifact */
        if (o_ptr->name1) {
            msg_print("There is an indestructible object here.");
            return FALSE;
        }

        /* Visible object to be destroyed */
        if (!squelch_hide_item(o_ptr))
            destroy_message = TRUE;
    }

    /* Verify */
    if (cave_o_idx[y][x]) {
        if (destroy_message)
            if (!get_check("Destroy all items and set a trap?"))
                return FALSE;

        for (this_o_idx = cave_o_idx[y][x]; this_o_idx; this_o_idx = next_o_idx) {
            /* Acquire object */
            o_ptr = &o_list[this_o_idx];

            /* Acquire next object */
            next_o_idx = o_ptr->next_o_idx;

            /* Delete the object */
            delete_object_idx(this_o_idx);
        }

        /* Redraw */
        light_spot(y, x);
    }

    /* Set the trap, and draw it. */
    cave_set_feat(y, x, FEAT_MTRAP_BASE);

    /* Notify the player. */
    msg_print("You set a monster trap.");

    /* Increment the number of monster traps. */
    num_trap_on_level++;

    /* A trap has been set */
    return TRUE;
}
Exemple #19
0
/*
 * Search for hidden things.  Returns true if a search was attempted, returns
 * false when the player has a 0% chance of finding anything.  Prints messages
 * for negative confirmation when verbose mode is requested.
 */
bool search(bool verbose)
{
	int py = p_ptr->py;
	int px = p_ptr->px;

	int y, x, chance;

	bool found = FALSE;

	object_type *o_ptr;


	/* Start with base search ability */
	chance = p_ptr->state.skills[SKILL_SEARCH];

	/* Penalize various conditions */
	if (p_ptr->timed[TMD_BLIND] || no_light()) chance = chance / 10;
	if (p_ptr->timed[TMD_CONFUSED] || p_ptr->timed[TMD_IMAGE]) chance = chance / 10;

	/* Prevent fruitless searches */
	if (chance <= 0)
	{
		if (verbose)
		{
			msg("You can't make out your surroundings well enough to search.");

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

		return FALSE;
	}

	/* Search the nearby grids, which are always in bounds */
	for (y = (py - 1); y <= (py + 1); y++)
	{
		for (x = (px - 1); x <= (px + 1); x++)
		{
			/* Sometimes, notice things */
			if (randint0(100) < chance)
			{
				/* Invisible trap */
				if (cave->feat[y][x] == FEAT_INVIS)
				{
					found = TRUE;

					/* Pick a trap */
					pick_trap(y, x);

					/* Message */
					msg("You have found a trap.");

					/* Disturb */
					disturb(p_ptr, 0, 0);
				}

				/* Secret door */
				if (cave->feat[y][x] == FEAT_SECRET)
				{
					found = TRUE;

					/* Message */
					msg("You have found a secret door.");

					/* Pick a door */
					place_closed_door(cave, y, x);

					/* Disturb */
					disturb(p_ptr, 0, 0);
				}

				/* Scan all objects in the grid */
				for (o_ptr = get_first_object(y, x); o_ptr; o_ptr = get_next_object(o_ptr))
				{
					/* Skip non-chests */
					if (o_ptr->tval != TV_CHEST) continue;

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

					/* Skip non-trapped chests */
					if (!chest_traps[o_ptr->pval[DEFAULT_PVAL]]) continue;

					/* Identify once */
					if (!object_is_known(o_ptr))
					{
						found = TRUE;

						/* Message */
						msg("You have discovered a trap on the chest!");

						/* Know the trap */
						object_notice_everything(o_ptr);

						/* Notice it */
						disturb(p_ptr, 0, 0);
					}
				}
			}
		}
	}

	if (verbose && !found)
	{
		if (chance >= 100)
			msg("There are no secrets here.");
		else
			msg("You found nothing.");
	}

	return TRUE;
}
Exemple #20
0
/**
 * Pick up objects and treasure on the floor, now also used for telekinesis.
 *
 * Called with pickup:
 * 0 to grab gold and describe non-gold objects.
 * 1 to pick up objects either with or without displaying a menu.
 * 2 to pick up objects, forcing a menu for multiple objects.
 * 3 to pick up objects, forcing a menu for any number of objects.
 *
 * Scan the list of objects in that floor grid.   Pick up gold automatically.
 * Pick up objects automatically until pile or backpack space is full if 
 * auto-pickup option is on, carry_query_floor option is not, and menus are 
 * not forced (which the "get" command does). Otherwise, store objects on 
 * floor in an array, and tally both how many there are and can be picked up.
 *
 * If the player is not picking up objects, describe a single object or 
 * indicate the presence of a floor stack.  If player is picking up objects, 
 * name a single object, or indicate a stack of objects, that cannot go in 
 * the backpack.
 *
 * Pick up a single object without menus, unless menus for single items are 
 * forced.  Confirm pickup if that option is on.
 *
 * Pick up multiple objects (unless using autopickup, no confirm) using Tim
 * Baker's menu system.   Recursively call this function (forcing menus for any 
 * number of objects) until objects are gone, backpack is full, or player is 
 * satisfied.
 *
 * Keep track of number of objects picked up (to calculate time spent).
 */
byte py_pickup(int pickup, int y, int x)
{
    s16b this_o_idx, next_o_idx = 0;

    char o_name[120];
    object_type *o_ptr;

    /* Objects picked up.  Used to determine time cost of command. */
    byte objs_picked_up = 0;

    size_t floor_num = 0;
    int floor_list[MAX_FLOOR_STACK + 1], floor_o_idx = 0;

    int can_pickup = 0;
    bool call_function_again = FALSE;
    bool blind = ((p_ptr->timed[TMD_BLIND]) || (no_light()));
    bool msg = TRUE;
    bool telekinesis = (!(y == p_ptr->py) || !(x == p_ptr->px));

    /* Nothing to pick up -- return */
    if (!cave_o_idx[y][x]) return (0);

    /* Always pickup gold, effortlessly */
    if (!telekinesis) py_pickup_gold();

    /* Scan the pile of objects */
    for (this_o_idx = cave_o_idx[y][x]; this_o_idx; this_o_idx = next_o_idx) {

	/* Access the object */
	o_ptr = &o_list[this_o_idx];

	/* Access the next object */
	next_o_idx = o_ptr->next_o_idx;

	/* Ordinary pickup */
	if (!telekinesis) {

	    /* Ignore all hidden objects and non-objects */
	    if (squelch_hide_item(o_ptr) || !o_ptr->k_idx)
		continue;

	    /* Hack -- disturb */
	    disturb(0, 0);

	    /* Automatically pick up some items */
	    if (auto_pickup_okay(o_ptr)) {
		/* Pick up the object */
		py_pickup_aux(this_o_idx, TRUE);
		objs_picked_up++;

		/* Check the next object */
		continue;
	    }
	}

	/* Tally objects and store them in an array. */
	
	/* Remember this object index */
	floor_list[floor_num] = this_o_idx;
	
	/* Count non-gold objects that remain on the floor. */
	floor_num++;
	
	/* Tally objects that can be picked up.*/
	if (inven_carry_okay(o_ptr))
	    can_pickup++;
    }

    /* There are no non-gold objects */
    if (!floor_num)
	return (objs_picked_up);

    /* Get hold of the last floor index */
    floor_o_idx = floor_list[floor_num - 1];

    /* Mention the objects if player is not picking them up. */
    if (pickup == 0 || !(can_pickup || telekinesis))
    {
	const char *p = "see";

	/* One object */
	if (floor_num == 1)
	{
	    if (!can_pickup)	p = "have no room for";
	    else if (blind)     p = "feel";

	    /* Get the object */
	    o_ptr = &o_list[floor_o_idx];

	    /* Describe the object.  Less detail if blind. */
	    if (blind)
		object_desc(o_name, sizeof(o_name), o_ptr,
			    ODESC_PREFIX | ODESC_BASE);
	    else
		object_desc(o_name, sizeof(o_name), o_ptr,
			    ODESC_PREFIX | ODESC_FULL);

	    /* Message */
	    message_flush();
	    msg_format("You %s %s.", p, o_name);
	}
	else
	{
	    /* Optionally, display more information about floor items */
	    if (OPT(pickup_detail))
	    {
		ui_event_data e;

		if (!can_pickup)	p = "have no room for the following objects";
		else if (blind)     p = "feel something on the floor";

		/* Scan all marked objects in the grid */
		floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), y, x, 0x03);

		/* Save screen */
		screen_save();

		/* Display objects on the floor */
		show_floor(floor_list, floor_num, (OLIST_WEIGHT));

		/* Display prompt */
		prt(format("You %s: ", p), 0, 0);

		/* Move cursor back to character, if needed */
		if (OPT(highlight_player)) move_cursor_relative(p_ptr->py, p_ptr->px);

		/* Wait for it.  Use key as next command. */
		e = inkey_ex();
		Term_event_push(&e);

		/* Restore screen */
		screen_load();
	    }

	    /* Show less detail */
	    else
	    {
		message_flush();

		if (!can_pickup)
		    msg_print("You have no room for any of the items on the floor.");
		else
		    msg_format("You %s a pile of %d items.", (blind ? "feel" : "see"), floor_num);
	    }
	}

	/* Done */
	return (objs_picked_up);
    }

    /* We can pick up objects.  Menus are not requested (yet). */
    if (pickup == 1)
    {
	/* Scan floor (again) */
	floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), y, x, 0x03);

	/* Use a menu interface for multiple objects, or get single objects */
	if (floor_num > 1)
	    pickup = 2;
	else
	    this_o_idx = floor_o_idx;
    }


    /* Display a list if requested. */
    if (pickup == 2)
    {
	cptr q, s;
	int item;

	/* Get an object or exit. */
	q = "Get which item?";
	s = "You see nothing there.";

	/* Telekinesis */
	if (telekinesis) {
	    item_tester_hook = inven_carry_okay;

	    if (!get_item(&item, q, s, CMD_PICKUP, USE_TARGET))
		return (objs_picked_up);

	    this_o_idx = 0 - item;
	}
	else {
	    /* Restrict the choices */
	    item_tester_hook = inven_carry_okay;

	    if (!get_item(&item, q, s, CMD_PICKUP, USE_FLOOR))
		return (objs_picked_up);

	    this_o_idx = 0 - item;
	    call_function_again = TRUE;
	}

	/* With a list, we do not need explicit pickup messages */
	msg = FALSE;
    }

    /* Pick up object, if legal */
    if (this_o_idx)
    {
	/* Regular pickup or telekinesis with pack not full */
	if (can_pickup) {
	    /* Pick up the object */
	    py_pickup_aux(this_o_idx, msg);
	}
	/* Telekinesis with pack full */
	else {
	    /* Access the object */
	    o_ptr = &o_list[this_o_idx];
	    
	    /* Drop it */
	    drop_near(o_ptr, -1, p_ptr->py, p_ptr->px, TRUE);
	    
	    /* Delete the old object */
	    delete_object_idx(this_o_idx);
	}
    }

    /* Indicate an object picked up. */
    objs_picked_up = 1;

    /* If requested, call this function recursively.  Count objects picked up.
     * Force the display of a menu in all cases. */
    if (call_function_again)
	objs_picked_up += py_pickup(3, y, x);

    /* Indicate how many objects have been picked up. */
    return (objs_picked_up);
}
Exemple #21
0
/**
 * Perform the basic "open" command on doors
 *
 * Assume there is no monster blocking the destination
 *
 * Returns true if repeated commands may continue
 */
static bool do_cmd_open_aux(int y, int x)
{
	int i, j;
	bool more = false;

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

	/* Locked door */
	if (square_islockeddoor(cave, y, x)) {
		/* Disarm factor */
		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 lock power */
		j = square_door_power(cave, y, x);

		/* Extract the difficulty XXX XXX XXX */
		j = i - (j * 4);

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

		if (randint0(100) < j) {
			/* Message */
			msgt(MSG_LOCKPICK, "You have picked the lock.");

			/* Open the door */
			square_open_door(cave, y, x);

			/* Update the visuals */
			square_memorize(cave, y, x);
			square_light_spot(cave, y, x);
			player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

			/* Experience */
			/* Removed to avoid exploit by repeatedly locking and unlocking */
			/* player_exp_gain(player, 1); */
		} else {
			event_signal(EVENT_INPUT_FLUSH);

			/* Message */
			msgt(MSG_LOCKPICK_FAIL, "You failed to pick the lock.");

			/* We may keep trying */
			more = true;
		}
	} else {
		/* Closed door */
		square_open_door(cave, y, x);
		square_memorize(cave, y, x);
		square_light_spot(cave, y, x);
		player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);
		sound(MSG_OPENDOOR);
	}

	/* Result */
	return (more);
}
Exemple #22
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 i, j, power;

	cptr name;

	bool more = FALSE;


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


	/* Get the trap name */
	name = f_info[cave_feat[y][x]].name;

	/* Get the "disarm" factor */
	i = p_ptr->state.skills[SKILL_DISARM];

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

	/* XXX XXX XXX Variable power? */

	/* Extract trap "power" */
	power = 5;

	/* Extract the difficulty */
	j = i - power;

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

	/* Success */
	if (randint0(100) < j)
	{
		/* Message */
		message_format(MSG_DISARM, 0, "You have disarmed the %s.", name);

		/* Reward */
		gain_exp(power);

		/* Forget the trap */
		cave_info[y][x] &= ~(CAVE_MARK);

		/* Remove the trap */
		cave_set_feat(y, x, FEAT_FLOOR);
	}

	/* Failure -- Keep trying */
	else if ((i > 5) && (randint1(i) > 5))
	{
		flush();

		/* Message */
		msg_format("You failed to disarm the %s.", name);

		/* We may keep trying */
		more = TRUE;
	}

	/* Failure -- Set off the trap */
	else
	{
		/* Message */
		msg_format("You set off the %s!", name);

		/* Hit the trap */
		hit_trap(y, x);
	}

	/* Result */
	return (more);
}
Exemple #23
0
/*
 * Perform the basic "open" command on doors
 *
 * Assume there is no monster blocking the destination
 *
 * Returns TRUE if repeated commands may continue
 */
static bool do_cmd_open_aux(int y, int x)
{
	int i, j;

	bool more = FALSE;


	/* Verify legality */
	if (!do_cmd_open_test(y, x)) return (FALSE);


	/* Jammed door */
	if (cave_feat[y][x] >= FEAT_DOOR_HEAD + 0x08)
	{
		/* Stuck */
		msg_print("The door appears to be stuck.");
	}

	/* Locked door */
	else if (cave_feat[y][x] >= FEAT_DOOR_HEAD + 0x01)
	{
		/* Disarm factor */
		i = p_ptr->state.skills[SKILL_DISARM];

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

		/* Extract the lock power */
		j = cave_feat[y][x] - FEAT_DOOR_HEAD;

		/* Extract the difficulty XXX XXX XXX */
		j = i - (j * 4);

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

		/* Success */
		if (randint0(100) < j)
		{
			/* Message */
			message(MSG_LOCKPICK, 0, "You have picked the lock.");

			/* Open the door */
			cave_set_feat(y, x, FEAT_OPEN);

			/* Update the visuals */
			p_ptr->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

			/* Experience */
			gain_exp(1);
		}

		/* Failure */
		else
		{
			flush();

			/* Message */
			message(MSG_LOCKPICK_FAIL, 0, "You failed to pick the lock.");

			/* We may keep trying */
			more = TRUE;
		}
	}

	/* Closed door */
	else
	{
		/* Open the door */
		cave_set_feat(y, x, FEAT_OPEN);

		/* Update the visuals */
		p_ptr->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

		/* Sound */
		sound(MSG_OPENDOOR);
	}

	/* Result */
	return (more);
}
Exemple #24
0
/* Scrolls for the reading				-RAK-	*/
void read_scroll()
{
  int32u i;
  int j, k, item_val, y, x;
  int tmp[6], flag, used_up;
  bigvtype out_val, tmp_str;
  register int ident, l;
  register inven_type *i_ptr;
  register struct misc *m_ptr;

  free_turn_flag = TRUE;
  if (py.flags.blind > 0)
    msg_print("You can't see to read the scroll.");
  else if (no_light())
    msg_print("You have no light to read by.");
  else if (py.flags.confused > 0)
    msg_print("You are too confused to read a scroll.");
  else if (inven_ctr == 0)
    msg_print("You are not carrying anything!");
  else if (!find_range(TV_SCROLL1, TV_SCROLL2, &j, &k))
    msg_print ("You are not carrying any scrolls!");
  else if (get_item(&item_val, "Read which scroll?", j, k, 0))
    {
      i_ptr = &inventory[item_val];
      free_turn_flag = FALSE;
      used_up = TRUE;
      i = i_ptr->flags;
      ident = FALSE;

      while (i != 0)
	{
	  j = bit_pos(&i) + 1;
	  if (i_ptr->tval == TV_SCROLL2)
	    j += 32;

	  /* Scrolls.			*/
	  switch(j)
	    {
	    case 1:
	      i_ptr = &inventory[INVEN_WIELD];
	      if (i_ptr->tval != TV_NOTHING)
		{
		  objdes(tmp_str, i_ptr, FALSE);
		  (void) sprintf(out_val, "Your %s glows faintly!", tmp_str);
		  msg_print(out_val);
		  if (enchant(&i_ptr->tohit))
		    {
		      i_ptr->flags &= ~TR_CURSED;
		      calc_bonuses();
		    }
		  else
		    msg_print("The enchantment fails.");
		  ident = TRUE;
		}
	      break;
	    case 2:
	      i_ptr = &inventory[INVEN_WIELD];
	      if (i_ptr->tval != TV_NOTHING)
		{
		  objdes(tmp_str, i_ptr, FALSE);
		  (void) sprintf(out_val, "Your %s glows faintly!", tmp_str);
		  msg_print(out_val);
		  if (enchant(&i_ptr->todam))
		    {
		      i_ptr->flags &= ~TR_CURSED;
		      calc_bonuses ();
		    }
		  else
		    msg_print("The enchantment fails.");
		  ident = TRUE;
		}
	      break;
	    case 3:
	      k = 0;
	      l = 0;
	      if (inventory[INVEN_BODY].tval != TV_NOTHING)
		tmp[k++] = INVEN_BODY;
	      if (inventory[INVEN_ARM].tval != TV_NOTHING)
		tmp[k++] = INVEN_ARM;
	      if (inventory[INVEN_OUTER].tval != TV_NOTHING)
		tmp[k++] = INVEN_OUTER;
	      if (inventory[INVEN_HANDS].tval != TV_NOTHING)
		tmp[k++] = INVEN_HANDS;
	      if (inventory[INVEN_HEAD].tval != TV_NOTHING)
		tmp[k++] = INVEN_HEAD;
	      /* also enchant boots */
	      if (inventory[INVEN_FEET].tval != TV_NOTHING)
		tmp[k++] = INVEN_FEET;

	      if (k > 0)  l = tmp[randint(k)-1];
	      if (TR_CURSED & inventory[INVEN_BODY].flags)
		l = INVEN_BODY;
	      else if (TR_CURSED & inventory[INVEN_ARM].flags)
		l = INVEN_ARM;
	      else if (TR_CURSED & inventory[INVEN_OUTER].flags)
		l = INVEN_OUTER;
	      else if (TR_CURSED & inventory[INVEN_HEAD].flags)
		l = INVEN_HEAD;
	      else if (TR_CURSED & inventory[INVEN_HANDS].flags)
		l = INVEN_HANDS;
	      else if (TR_CURSED & inventory[INVEN_FEET].flags)
		l = INVEN_FEET;

	      if (l > 0)
		{
		  i_ptr = &inventory[l];
		  objdes(tmp_str, i_ptr, FALSE);
		  (void) sprintf(out_val, "Your %s glows faintly!", tmp_str);
		  msg_print(out_val);
		  if (enchant(&i_ptr->toac))
		    {
		      i_ptr->flags &= ~TR_CURSED;
		      calc_bonuses ();
		    }
		  else
		    msg_print("The enchantment fails.");
		  ident = TRUE;
		}
	      break;
	    case 4:
	      msg_print("This is an identify scroll.");
	      ident = TRUE;
	      used_up = ident_spell();

	      /* the identify may merge objects, causing the identify scroll
		 to move to a different place.	Check for that here. */
	      if (i_ptr->tval != TV_SCROLL1 || i_ptr->flags != 0x00000008)
		{
		  item_val--;
		  i_ptr = &inventory[item_val];
		  if (i_ptr->tval != TV_SCROLL1 || i_ptr->flags != 0x00000008)
		    {
		      msg_print("internal error with identify spell.");
		      msg_print("Please tell the wizard!");
		      return;
		    }
		}
	      break;
	    case 5:
	      if (remove_curse())
		{
		  msg_print("You feel as if someone is watching over you.");
		  ident = TRUE;
		}
	      break;
	    case 6:
	      ident = light_area(char_row, char_col);
	      break;
	    case 7:
	      for (k = 0; k < randint(3); k++)
		{
		  y = char_row;
		  x = char_col;
		  ident |= summon_monster(&y, &x, FALSE);
		}
	      break;
	    case 8:
	      teleport(10);
	      ident = TRUE;
	      break;
	    case 9:
	      teleport(100);
	      ident = TRUE;
	      break;
	    case 10:
	      (void) tele_level();
	      ident = TRUE;
	      break;
	    case 11:
	      if (py.flags.confuse_monster == 0)
		{
		  msg_print("Your hands begin to glow.");
		  py.flags.confuse_monster = TRUE;
		  ident = TRUE;
		}
	      break;
	    case 12:
	      ident = TRUE;
	      map_area();
	      break;
	    case 13:
	      ident = sleep_monsters1(char_row, char_col);
	      break;
	    case 14:
	      ident = TRUE;
	      warding_glyph();
	      break;
	    case 15:
	      ident = detect_treasure();
	      break;
	    case 16:
	      ident = detect_object();
	      break;
	    case 17:
	      ident = detect_trap();
	      break;
	    case 18:
	      ident = detect_sdoor();
	      break;
	    case 19:
	      msg_print("This is a mass genocide scroll.");
	      ident = mass_genocide(TRUE);
	      break;
	    case 20:
	      ident = detect_invisible();
	      break;
	    case 21:
	      ident = aggravate_monster(20);
	      if (ident)
		msg_print("There is a high pitched humming noise.");
	      break;
	    case 22:
	      ident = trap_creation();
	      break;
	    case 23:
	      ident = td_destroy();
	      break;
	    case 24:  /* Not Used , used to be door creation */
	      break;
	    case 25:
	      msg_print("This is a Recharge-Item scroll.");
	      ident = TRUE;
	      used_up = recharge(60);
	      break;
	    case 26:
	      msg_print("This is a genocide scroll.");
	      ident = genocide(TRUE);
	      break;
	    case 27:
	      ident = unlight_area(char_row, char_col);
	      break;
	    case 28:
	      ident = protect_evil();
	      break;
	    case 29:
	      ident = TRUE;
	      create_food();
	      break;
	    case 30:
	      ident = dispel_creature(UNDEAD, 60);
	      break;
	    case 31:
	      remove_all_curse();
	      ident = TRUE;
	      break;
	    case 33:
	      i_ptr = &inventory[INVEN_WIELD];
	      if (i_ptr->tval != TV_NOTHING)
		{
		  objdes(tmp_str, i_ptr, FALSE);
		  (void) sprintf(out_val, "Your %s glows brightly!", tmp_str);
		  msg_print(out_val);
		  flag = FALSE;
		  for (k = 0; k < randint(2); k++)
		    if (enchant(&i_ptr->tohit))
		      flag = TRUE;
		  for (k = 0; k < randint(2); k++)
		    if (enchant(&i_ptr->todam))
		      flag = TRUE;
		  if (flag)
		    {
		      i_ptr->flags &= ~TR_CURSED;
		      calc_bonuses ();
		    }
		  else
		    msg_print("The enchantment fails.");
		  ident = TRUE;
		}
	      break;
	    case 34:
	      i_ptr = &inventory[INVEN_WIELD];
	      if (i_ptr->tval != TV_NOTHING)
		{
		  objdes(tmp_str, i_ptr, FALSE);
		  (void)sprintf(out_val,"Your %s glows black, fades.",tmp_str);
		  msg_print(out_val);
		  unmagic_name(i_ptr);
		  i_ptr->tohit = -randint(5) - randint(5);
		  i_ptr->todam = -randint(5) - randint(5);
		  i_ptr->flags = TR_CURSED;
		  py_bonuses(i_ptr, -1);
		  calc_bonuses ();
		  ident = TRUE;
		}
	      break;
	    case 35:
	      k = 0;
	      l = 0;
	      if (inventory[INVEN_BODY].tval != TV_NOTHING)
		tmp[k++] = INVEN_BODY;
	      if (inventory[INVEN_ARM].tval != TV_NOTHING)
		tmp[k++] = INVEN_ARM;
	      if (inventory[INVEN_OUTER].tval != TV_NOTHING)
		tmp[k++] = INVEN_OUTER;
	      if (inventory[INVEN_HANDS].tval != TV_NOTHING)
		tmp[k++] = INVEN_HANDS;
	      if (inventory[INVEN_HEAD].tval != TV_NOTHING)
		tmp[k++] = INVEN_HEAD;
	      /* also enchant boots */
	      if (inventory[INVEN_FEET].tval != TV_NOTHING)
		tmp[k++] = INVEN_FEET;

	      if (k > 0)  l = tmp[randint(k)-1];
	      if (TR_CURSED & inventory[INVEN_BODY].flags)
		l = INVEN_BODY;
	      else if (TR_CURSED & inventory[INVEN_ARM].flags)
		l = INVEN_ARM;
	      else if (TR_CURSED & inventory[INVEN_OUTER].flags)
		l = INVEN_OUTER;
	      else if (TR_CURSED & inventory[INVEN_HEAD].flags)
		l = INVEN_HEAD;
	      else if (TR_CURSED & inventory[INVEN_HANDS].flags)
		l = INVEN_HANDS;
	      else if (TR_CURSED & inventory[INVEN_FEET].flags)
		l = INVEN_FEET;

	      if (l > 0)
		{
		  i_ptr = &inventory[l];
		  objdes(tmp_str, i_ptr, FALSE);
		  (void) sprintf(out_val,"Your %s glows brightly!", tmp_str);
		  msg_print(out_val);
		  flag = FALSE;
		  for (k = 0; k < randint(2) + 1; k++)
		    if (enchant(&i_ptr->toac))
		      flag = TRUE;
		  if (flag)
		    {
		      i_ptr->flags &= ~TR_CURSED;
		      calc_bonuses ();
		    }
		  else
		    msg_print("The enchantment fails.");
		  ident = TRUE;
		}
	      break;
	    case 36:
	      if ((inventory[INVEN_BODY].tval != TV_NOTHING)
		  && (randint(4) == 1))
		k = INVEN_BODY;
	      else if ((inventory[INVEN_ARM].tval != TV_NOTHING)
		       && (randint(3) ==1))
		k = INVEN_ARM;
	      else if ((inventory[INVEN_OUTER].tval != TV_NOTHING)
		       && (randint(3) ==1))
		k = INVEN_OUTER;
	      else if ((inventory[INVEN_HEAD].tval != TV_NOTHING)
		       && (randint(3) ==1))
		k = INVEN_HEAD;
	      else if ((inventory[INVEN_HANDS].tval != TV_NOTHING)
		       && (randint(3) ==1))
		k = INVEN_HANDS;
	      else if ((inventory[INVEN_FEET].tval != TV_NOTHING)
		       && (randint(3) ==1))
		k = INVEN_FEET;
	      else if (inventory[INVEN_BODY].tval != TV_NOTHING)
		k = INVEN_BODY;
	      else if (inventory[INVEN_ARM].tval != TV_NOTHING)
		k = INVEN_ARM;
	      else if (inventory[INVEN_OUTER].tval != TV_NOTHING)
		k = INVEN_OUTER;
	      else if (inventory[INVEN_HEAD].tval != TV_NOTHING)
		k = INVEN_HEAD;
	      else if (inventory[INVEN_HANDS].tval != TV_NOTHING)
		k = INVEN_HANDS;
	      else if (inventory[INVEN_FEET].tval != TV_NOTHING)
		k = INVEN_FEET;
	      else
		k = 0;

	      if (k > 0)
		{
		  i_ptr = &inventory[k];
		  objdes(tmp_str, i_ptr, FALSE);
		  (void)sprintf(out_val,"Your %s glows black, fades.",tmp_str);
		  msg_print(out_val);
		  unmagic_name(i_ptr);
		  i_ptr->flags = TR_CURSED;
		  i_ptr->toac = -randint(5) - randint(5);
		  calc_bonuses ();
		  ident = TRUE;
		}
	      break;
	    case 37:
	      ident = FALSE;
	      for (k = 0; k < randint(3); k++)
		{
		  y = char_row;
		  x = char_col;
		  ident |= summon_undead(&y, &x);
		}
	      break;
	    case 38:
	      ident = TRUE;
	      bless(randint(12)+6);
	      break;
	    case 39:
	      ident = TRUE;
	      bless(randint(24)+12);
	      break;
	    case 40:
	      ident = TRUE;
	      bless(randint(48)+24);
	      break;
	    case 41:
	      ident = TRUE;
	      if (py.flags.word_recall == 0)
		py.flags.word_recall = 25 + randint(30);
	      msg_print("The air about you becomes charged.");
	      break;
	    case 42:
	      destroy_area(char_row, char_col);
	      ident = TRUE;
	      break;
	    case 43:
	      place_special(char_row, char_col, SPECIAL);
	      prt_map();
	      break;
	    case 44:
	      special_random_object(char_row, char_col, 1);
	      prt_map();
	      break;
	    default:
	      msg_print("Internal error in scroll()");
	      break;
	    }
	  /* End of Scrolls.			       */
	}
      i_ptr = &inventory[item_val];
      if (ident)
	{
	  if (!known1_p(i_ptr))
	    {
	      m_ptr = &py.misc;
	      /* round half-way case up */
	      m_ptr->exp += (i_ptr->level +(m_ptr->lev >> 1)) / m_ptr->lev;
	      prt_experience();

	      identify(&item_val);
	      i_ptr = &inventory[item_val];
	    }
	}