void on_p_hit_m(int m_idx)
{
    if (p_ptr->special_attack & ATTACK_CONFUSE)
    {
        monster_type *m_ptr = &m_list[m_idx];
        monster_race *r_ptr = &r_info[m_ptr->r_idx];
        char          m_name[MAX_NLEN];

        monster_desc(m_name, m_ptr, 0);

        p_ptr->special_attack &= ~(ATTACK_CONFUSE);
        msg_print("Your hands stop glowing.");
        p_ptr->redraw |= (PR_STATUS);

        if (r_ptr->flags3 & RF3_NO_CONF)
        {
            mon_lore_3(m_ptr, RF3_NO_CONF);
            msg_format("%^s is unaffected.", m_name);
        }
        else if (randint0(100) < r_ptr->level)
        {
            msg_format("%^s is unaffected.", m_name);
        }
        else
        {
            msg_format("%^s appears confused.", m_name);
            (void)set_monster_confused(m_idx, MON_CONFUSED(m_ptr) + 10 + randint0(p_ptr->lev) / 5);
        }
    }
}
예제 #2
0
파일: wizard2.c 프로젝트: naota/hengband
/*!
 * @brief フロアに存在する全モンスターを消去する /
 * Hack -- Delete all monsters
 * @return なし
 */
static void do_cmd_wiz_zap_all(void)
{
	int i;

	/* Genocide everyone */
	for (i = 1; i < m_max; i++)
	{
		monster_type *m_ptr = &m_list[i];

		/* Paranoia -- Skip dead monsters */
		if (!m_ptr->r_idx) continue;

		/* Skip the mount */
		if (i == p_ptr->riding) continue;

		if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname)
		{
			char m_name[80];

			monster_desc(m_name, m_ptr, MD_INDEF_VISIBLE);
			do_cmd_write_nikki(NIKKI_NAMED_PET, RECORD_NAMED_PET_WIZ_ZAP, m_name);
		}

		/* Delete this monster */
		delete_monster_idx(i);
	}
}
예제 #3
0
파일: target.c 프로젝트: CJNyfalt/angband
bool target_set_closest(int mode)
{
	int y, x, m_idx;
	monster_type *m_ptr;
	char m_name[80];
	bool visibility;
	struct point_set *targets;

	/* Cancel old target */
	target_set_monster(0);

	/* Get ready to do targetting */
	targets = target_set_interactive_prepare(mode);

	/* If nothing was prepared, then return */
	if (point_set_size(targets) < 1)
	{
		msg("No Available Target.");
		point_set_dispose(targets);
		return FALSE;
	}

	/* Find the first monster in the queue */
	y = targets->pts[0].y;
	x = targets->pts[0].x;
	m_idx = cave->m_idx[y][x];
	
	/* Target the monster, if possible */
	if ((m_idx <= 0) || !target_able(m_idx))
	{
		msg("No Available Target.");
		point_set_dispose(targets);
		return FALSE;
	}

	/* Target the monster */
	m_ptr = cave_monster(cave, m_idx);
	monster_desc(m_name, sizeof(m_name), m_ptr, 0x00);
	if (!(mode & TARGET_QUIET))
		msg("%^s is targeted.", m_name);
	Term_fresh();

	/* Set up target information */
	monster_race_track(m_ptr->r_idx);
	health_track(p_ptr, cave->m_idx[y][x]);
	target_set_monster(m_idx);

	/* Visual cue */
	Term_get_cursor(&visibility);
	(void)Term_set_cursor(TRUE);
	move_cursor_relative(y, x);
	Term_redraw_section(x, y, x, y);

	/* TODO: what's an appropriate amount of time to spend highlighting */
	Term_xtra(TERM_XTRA_DELAY, 150);
	(void)Term_set_cursor(visibility);

	point_set_dispose(targets);
	return TRUE;
}
예제 #4
0
/**
 * Attack the monster at the given location
 *
 * We get blows until energy drops below that required for another blow, or
 * until the target monster dies. Each blow is handled by py_attack_real().
 * We don't allow @ to spend more than 100 energy in one go, to avoid slower
 * monsters getting double moves.
 */
void py_attack(int y, int x) {
	int blow_energy = 10000 / p_ptr->state.num_blows;
	int blows = 0;
	bool fear = FALSE;
	monster_type *m_ptr = cave_monster(cave, cave->m_idx[y][x]);
	
	/* disturb the player */
	disturb(p_ptr, 0,0);

	/* Initialize the energy used */
	p_ptr->energy_use = 0;

	/* Attack until energy runs out or enemy dies. We limit energy use to 100
	 * to avoid giving monsters a possible double move. */
	while (p_ptr->energy >= blow_energy * (blows + 1)) {
		bool stop = py_attack_real(y, x, &fear);
		p_ptr->energy_use += blow_energy;
		if (stop || p_ptr->energy_use + blow_energy > 100) break;
		blows++;
	}
	
	/* Hack - delay fear messages */
	if (fear && m_ptr->ml) {
		char m_name[80];
		monster_desc(m_name, sizeof(m_name), m_ptr, 0);
		add_monster_message(m_name, cave->m_idx[y][x], MON_MSG_FLEE_IN_TERROR, TRUE);
	}
}
예제 #5
0
/**
 * Attack the monster at the given location
 *
 * We get blows until energy drops below that required for another blow, or
 * until the target monster dies. Each blow is handled by py_attack_real().
 * We don't allow @ to spend more than 100 energy in one go, to avoid slower
 * monsters getting double moves.
 */
void py_attack(int y, int x)
{
	int blow_energy = 100 * z_info->move_energy / player->state.num_blows;
	int blows = 0;
	bool fear = FALSE;
	struct monster *mon = square_monster(cave, y, x);
	
	/* disturb the player */
	disturb(player, 0);

	/* Initialize the energy used */
	player->upkeep->energy_use = 0;

	/* Attack until energy runs out or enemy dies. We limit energy use to 100
	 * to avoid giving monsters a possible double move. */
	while (player->energy >= blow_energy * (blows + 1)) {
		bool stop = py_attack_real(y, x, &fear);
		player->upkeep->energy_use += blow_energy;
		if (player->upkeep->energy_use + blow_energy > z_info->move_energy ||
			stop) break;
		blows++;
	}
	
	/* Hack - delay fear messages */
	if (fear && mflag_has(mon->mflag, MFLAG_VISIBLE)) {
		char m_name[80];
		/* Don't set monster_desc flags, since add_monster_message does string
		 * processing on m_name */
		monster_desc(m_name, sizeof(m_name), mon, MDESC_DEFAULT);
		add_monster_message(m_name, mon, MON_MSG_FLEE_IN_TERROR, TRUE);
	}
}
예제 #6
0
/* Handle the Terrifying Aura of Fear! */
void fear_process_p(void)
{
    int i, r_level;
    for (i = 1; i < m_max; i++)
    {
        monster_type *m_ptr = &m_list[i];
        monster_race *r_ptr;

        if (!m_ptr->r_idx) continue;
        if (!m_ptr->ml) continue;

        r_ptr = &r_info[m_ptr->ap_r_idx];

        if (!(r_ptr->flags2 & RF2_AURA_FEAR)) continue;
        if (is_pet(m_ptr) || is_friendly(m_ptr)) continue;
        if (!projectable(py, px, m_ptr->fy, m_ptr->fx)) continue;

        r_level = _r_level(r_ptr);
        if (!fear_save_p(r_level/MAX(1, m_ptr->cdis-2)))
        {
            char m_name[80];
            monster_desc(m_name, m_ptr, 0);
            msg_format("You behold the terrifying visage of %s!", m_name);
            mon_lore_2(m_ptr, RF2_AURA_FEAR);
            fear_add_p(r_level/MAX(1, m_ptr->cdis-2));
        }
    }
}
예제 #7
0
/*
 * Hack -- Display the "name" and "attr/chars" of a monster race
 */
static void roff_top(const int r_idx, int m_idx)
{
	byte a1, a2;
	char c1, c2;

	char desc[80];
	monster_race *r_ptr = &r_info[r_idx];

	/* Describe the monster */
	if (m_idx)
	{
		/* Describe the monster */
		monster_desc(desc, sizeof(desc), m_idx, 0x80);

		/* Capitalise the first letter */
		if (islower(desc[0])) desc[0] = toupper(desc[0]);
	}
	/* Not describing a specific monster, so hack a description */
	else
	{
		/* Get the name */
		race_desc(desc, sizeof(desc), r_idx, 0x400, 1);
		
		/* Capitalise the first letter */
		if (islower(desc[0])) desc[0] = toupper(desc[0]);
	}

	/* Get the chars */
	c1 = r_ptr->d_char;
	c2 = r_ptr->x_char;

	/* Get the attrs */
	a1 = r_ptr->d_attr;
	a2 = r_ptr->x_attr;


	/* Clear the top line */
	Term_erase(0, 0, 255);

	/* Reset the cursor */
	Term_gotoxy(0, 0);

	/* Dump the name */
	Term_addstr(-1, TERM_WHITE, desc);

	if (!use_dbltile && !use_trptile)
	{
		/* Append the "standard" attr/char info */
		Term_addstr(-1, TERM_WHITE, " ('");
		Term_addch(a1, c1);
		Term_addstr(-1, TERM_WHITE, "')");

		/* Append the "optional" attr/char info */
		Term_addstr(-1, TERM_WHITE, "/('");
		Term_addch(a2, c2);
		if (use_bigtile && (a2 & 0x80)) Term_addch(255, -1);
		Term_addstr(-1, TERM_WHITE, "'):");
	}
}
예제 #8
0
void _rodeo_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Rodeo");
        break;
    case SPELL_DESC:
        var_set_string(res, "");
        break;
    case SPELL_CAST:
    {
        char m_name[80];
        monster_type *m_ptr;
        monster_race *r_ptr;
        int rlev;

        var_set_bool(res, FALSE);
        if (p_ptr->riding)
        {
            msg_print("You are already riding.");
            return;
        }
        if (!do_riding(TRUE)) return;
        
        var_set_bool(res, TRUE);

        m_ptr = &m_list[p_ptr->riding];
        r_ptr = &r_info[m_ptr->r_idx];
        monster_desc(m_name, m_ptr, 0);
        msg_format("You ride on %s.", m_name);
        if (is_pet(m_ptr)) break;
        rlev = r_ptr->level;
        if (r_ptr->flags1 & RF1_UNIQUE) rlev = rlev * 3 / 2;
        if (rlev > 60) rlev = 60+(rlev-60)/2;
        if ( randint1(skills_riding_current() / 120 + p_ptr->lev * 2 / 3) > rlev
          && one_in_(2) 
          && !p_ptr->inside_arena 
          && !p_ptr->inside_battle
          && !(r_ptr->flags7 & RF7_GUARDIAN) 
          && !(r_ptr->flags1 & RF1_QUESTOR)
          && rlev < p_ptr->lev * 3 / 2 + randint0(p_ptr->lev / 5) )
        {
            msg_format("You tame %s.", m_name);
            set_pet(m_ptr);
        }
        else
        {
            msg_format("You have thrown off by %s.", m_name);
            rakuba(1,TRUE);
            p_ptr->riding = 0;
        }
        break;
    }
    default:
        default_spell(cmd, res);
        break;
    }
}
예제 #9
0
파일: cmd2.c 프로젝트: CJNyfalt/angband
/*
 * 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);
}
예제 #10
0
파일: mon-timed.c 프로젝트: Colt374/angband
/**
 * Attempts to set the timer of the given monster effect to `timer`.
 *
 * Checks to see if the monster resists the effect, using mon_resist_effect().
 * If not, the effect is set to `timer` turns. If `timer` is 0, or if the
 * effect timer was 0, or if MON_TMD_FLG_NOTIFY is set in `flag`, then a
 * message is printed, unless MON_TMD_FLG_NOMESSAGE is set in `flag`.
 *
 * Set a timed monster event to 'v'.  Give messages if the right flags are set.
 * Check if the monster is able to resist the spell.  Mark the lore.
 * Returns TRUE if the monster was affected.
 * Return FALSE if the monster was unaffected.
 */
static bool mon_set_timed(monster_type *m_ptr, int ef_idx, int timer,
	u16b flag, bool id)
{
	mon_timed_effect *effect;

	int m_note = 0;
	int resisted;
	int old_timer;

	assert(ef_idx >= 0 && ef_idx < MON_TMD_MAX);
	effect = &effects[ef_idx];

	assert(m_ptr);
	old_timer = m_ptr->m_timed[ef_idx];

	/* Ignore dead monsters */
	if (!m_ptr->r_idx) return FALSE;

	/* No change */
	if (old_timer == timer) return FALSE;

	if (timer == 0) {
		/* Turning off, usually mention */
		m_note = effect->message_end;
		flag |= MON_TMD_FLG_NOTIFY;
	} else if (old_timer == 0) {
		/* Turning on, usually mention */
		flag |= MON_TMD_FLG_NOTIFY;
		m_note = effect->message_begin;
	} else if (timer > old_timer) {
		/* Different message for increases, but don't automatically mention. */
		m_note = effect->message_increase;
	}

	/* Determine if the monster resisted or not */
	resisted = mon_resist_effect(m_ptr, ef_idx, timer, flag);

	if (resisted)
		m_note = MON_MSG_UNAFFECTED;
	else
		m_ptr->m_timed[ef_idx] = timer;

	if (p_ptr->health_who == m_ptr->midx) p_ptr->redraw |= (PR_HEALTH);

	/* Update the visuals, as appropriate. */
	p_ptr->redraw |= (PR_MONLIST);

	/* Print a message if there is one, if the effect allows for it, and if
	 * either the monster is visible, or we're trying to ID something */
	if (m_note && (m_ptr->ml || id) && !(flag & MON_TMD_FLG_NOMESSAGE) &&
			(flag & MON_TMD_FLG_NOTIFY)) {
		char m_name[80];
		monster_desc(m_name, sizeof(m_name), m_ptr, 0x04);
		add_monster_message(m_name, m_ptr->midx, m_note, TRUE);
	}

	return !resisted;
}
예제 #11
0
/* Monster Fear */
bool fear_process_m(int m_idx)
{
    monster_type *m_ptr = &m_list[m_idx];
    if (MON_MONFEAR(m_ptr) && !MON_CSLEEP(m_ptr))
    {
        if (fear_save_m(m_ptr))
        {
            bool recovered = FALSE;
            if (fear_save_m(m_ptr))
            {
                set_monster_monfear(m_idx, 0);
                recovered = TRUE;
            }
            else
            {
            monster_race *r_ptr = &r_info[m_ptr->ap_r_idx];

                recovered = set_monster_monfear(m_idx,
                    MON_MONFEAR(m_ptr) - randint1(r_ptr->level / 20 + 1));
            }

            if (recovered && is_seen(m_ptr))
            {
                char m_name[80];
                char m_poss[80];

                monster_desc(m_poss, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
                monster_desc(m_name, m_ptr, 0);

                msg_format("%^s recovers %s courage.", m_name, m_poss);
            }
        }
        else if (one_in_(3) && !fear_save_m(m_ptr))
        {
            if (is_seen(m_ptr))
            {
                char m_name[80];
                monster_desc(m_name, m_ptr, 0);
                msg_format("%^s is scared stiff!", m_name);
            }
            return FALSE;
        }
    }
    return TRUE;
}
예제 #12
0
void _grasp_spell(int cmd, variant *res)
{
    switch (cmd)
    {
    case SPELL_NAME:
        var_set_string(res, "Vampiric Grasp");
        break;
    case SPELL_DESC:
        var_set_string(res, "Pulls a target creature to you.");
        break;
    case SPELL_CAST:
    {
        int           m_idx;
        bool          fear = FALSE;
        monster_type *m_ptr;
        monster_race *r_ptr;
        char m_name[MAX_NLEN];

        var_set_bool(res, FALSE);

        if (!target_set(TARGET_KILL)) break;
        if (!cave[target_row][target_col].m_idx) break;
        if (!player_has_los_bold(target_row, target_col)) break;
        if (!projectable(py, px, target_row, target_col)) break;

        var_set_bool(res, TRUE);

        m_idx = cave[target_row][target_col].m_idx;
        m_ptr = &m_list[m_idx];
        r_ptr = &r_info[m_ptr->r_idx];
        monster_desc(m_name, m_ptr, 0);
        if (r_ptr->flagsr & RFR_RES_TELE)
        {
            if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flagsr & RFR_RES_ALL))
            {
                if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE;
                msg_format("%s is unaffected!", m_name);
                break;
            }
            else if (r_ptr->level > randint1(100))
            {
                if (is_original_ap_and_seen(m_ptr)) r_ptr->r_flagsr |= RFR_RES_TELE;
                msg_format("%s resists!", m_name);
                break;
            }
        }
        msg_format("You grasp %s.", m_name);
        teleport_monster_to(m_idx, py, px, 100, TELEPORT_PASSIVE);
        mon_take_hit(m_idx, damroll(10, 10), &fear, extract_note_dies(real_r_ptr(m_ptr)));
        break;
    }
    default:
        default_spell(cmd, res);
        break;
    }
}
예제 #13
0
/*
 * Determine if a given grid may be "walked"
 */
static bool do_cmd_walk_test(int y, int x)
{
	/* Allow attack on visible monsters if unafraid */
	if ((cave_m_idx[y][x] > 0) && (mon_list[cave_m_idx[y][x]].ml))
	{
		/* Handle player fear */
		if(p_ptr->state.afraid)
		{
			/* Extract monster name (or "it") */
			char m_name[80];
			monster_type *m_ptr;

			m_ptr = &mon_list[cave_m_idx[y][x]];
			monster_desc(m_name, sizeof(m_name), m_ptr, 0);

			/* Message */
			message_format(MSG_AFRAID, 0,
				"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 or PASS_WALL/KILL_WALL flag -Simon */
	if (!cave_floor_bold(y, x) && !(player_has(PF_PASS_WALL) || player_has(PF_KILL_WALL)))
	{			
		/* Rubble */
		if (cave_feat[y][x] == FEAT_RUBBLE)
			message(MSG_HITWALL, 0, "There is a pile of rubble in the way!");
		
		/* Door */
		else if (cave_feat[y][x] < FEAT_SECRET)
			return TRUE;

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

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

		/* Nope */
		return (FALSE);
	}

	/* Okay */
	return (TRUE);
}
예제 #14
0
파일: mon-move.c 프로젝트: magnate/angband
/**
 * Wake a monster or reduce its depth of sleep
 *
 * Chance of waking up is dependent only on the player's stealth, but the
 * amount of sleep reduction takes into account the monster's distance from
 * the player.  Currently straight line distance is used; possibly this
 * should take into account dungeon structure.
 */
static void monster_reduce_sleep(struct chunk *c, struct monster *mon)
{
	bool woke_up = false;
	int stealth = player->state.skills[SKILL_STEALTH];
	int player_noise = 1 << (30 - stealth);
	int notice = randint0(1024);
	struct monster_lore *lore = get_lore(mon->race);

	/* Aggravation */
	if (player_of_has(player, OF_AGGRAVATE)) {
		char m_name[80];

		/* Wake the monster */
		mon_clear_timed(mon, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, false);

		/* Get the monster name */
		monster_desc(m_name, sizeof(m_name), mon,
					 MDESC_CAPITAL | MDESC_IND_HID);

		/* Notify the player if aware */
		if (monster_is_obvious(mon))
			msg("%s wakes up.", m_name);

		woke_up = true;

	} else if ((notice * notice * notice) <= player_noise) {
		int sleep_reduction = 1;
		int local_noise = c->noise.grids[mon->fy][mon->fx];

		/* Test - wake up faster in hearing distance of the player 
		 * Note no dependence on stealth for now */
		if ((local_noise > 0) && (local_noise < 50)) {
			sleep_reduction = (100 / local_noise);
		}

		/* Note a complete wakeup */
		if (mon->m_timed[MON_TMD_SLEEP] <= sleep_reduction) {
			woke_up = true;
		}

		/* Monster wakes up a bit */
		mon_dec_timed(mon, MON_TMD_SLEEP, sleep_reduction, MON_TMD_FLG_NOTIFY,
					  false);

		/* Update knowledge */
		if (monster_is_obvious(mon)) {
			if (!woke_up && lore->ignore < UCHAR_MAX)
				lore->ignore++;
			else if (woke_up && lore->wake < UCHAR_MAX)
				lore->wake++;
			lore_update(mon->race, lore);
		}
	}
}
예제 #15
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);
}
예제 #16
0
파일: monster3.c 프로젝트: jcubic/ToME
void talk_to_monster(s32b m_idx)
{
	char m_name[100];

	/* Extract monster name (or "it") */
	monster_desc(m_name, get_monster(m_idx), 0);

	/* Process hook if there are any */
	if (!process_hooks(HOOK_CHAT, "(d)", m_idx))
	{
		msg_print("The monster does not want to chat.");
	}
}
예제 #17
0
/**
 * Monster self-healing.
 *
 * \param m_ptr is the monster casting
 * \param rlev is its level
 * \param seen is whether @ can see it
 */
static void heal_self(struct monster *m_ptr, int rlev, bool seen)
{
	char m_name[80], m_poss[80];

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

	/* Get the monster possessive ("his"/"her"/"its") */
	monster_desc(m_poss, sizeof(m_poss), m_ptr,
			MDESC_PRO_VIS | MDESC_POSS);

	/* Heal some */
	m_ptr->hp += (rlev * 6);

	/* Fully healed */
	if (m_ptr->hp >= m_ptr->maxhp) {
		m_ptr->hp = m_ptr->maxhp;

		if (seen)
			msg("%s looks REALLY healthy!", m_name);
		else
			msg("%s sounds REALLY healthy!", m_name);
	} else if (seen) { /* Partially healed */
		msg("%s looks healthier.", m_name);
	} else {
		msg("%s sounds healthier.", m_name);
	}

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

	/* Cancel fear */
	if (m_ptr->m_timed[MON_TMD_FEAR]) {
		mon_clear_timed(m_ptr, MON_TMD_FEAR, MON_TMD_FLG_NOMESSAGE, FALSE);
		msg("%s recovers %s courage.", m_name, m_poss);
	}
}
예제 #18
0
파일: mon-spell.c 프로젝트: Colt374/angband
/**
 * Drain mana from the player, healing the caster.
 *
 * \param m_idx is the monster casting
 * \param rlev is its level
 * \param seen is whether @ can see it
 */
static void drain_mana(int m_idx, int rlev, bool seen)
{
	monster_type *m_ptr = cave_monster(cave, m_idx);
	int r1;
	char m_name[80];

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

	if (!p_ptr->csp) {
		msg("The draining fails.");
		if (OPT(birth_ai_learn) && !(m_ptr->smart & SM_IMM_MANA)) {
			msg("%^s notes that you have no mana!", m_name);
			m_ptr->smart |= SM_IMM_MANA;
		}
		return;
	}

	/* Attack power */
	r1 = (randint1(rlev) / 2) + 1;

	/* Full drain */
	if (r1 >= p_ptr->csp) {
		r1 = p_ptr->csp;
		p_ptr->csp = 0;
		p_ptr->csp_frac = 0;
	}
	/* Partial drain */
	else
		p_ptr->csp -= r1;

	/* Redraw mana */
	p_ptr->redraw |= PR_MANA;

	/* Heal the monster */
	if (m_ptr->hp < m_ptr->maxhp) {
		m_ptr->hp += (6 * r1);
		if (m_ptr->hp > m_ptr->maxhp)
			m_ptr->hp = m_ptr->maxhp;

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

		/* Special message */
		if (seen)
			msg("%^s appears healthier.", m_name);
	}
}
예제 #19
0
void fear_update_m(monster_type *m_ptr)
{
    monster_race *r_ptr = &r_info[m_ptr->ap_r_idx];
    if ((r_ptr->flags2 & RF2_AURA_FEAR) && m_ptr->ml && !is_pet(m_ptr) && !is_friendly(m_ptr))
    {
        int r_level = _r_level(r_ptr);
        if (!fear_save_p(r_level))
        {
            char m_name[80];
            monster_desc(m_name, m_ptr, 0);
            msg_format("You behold the terrifying visage of %s!", m_name);
            mon_lore_2(m_ptr, RF2_AURA_FEAR);
            fear_add_p(r_level);
        }
    }
}
예제 #20
0
/**
 * Try to push past / kill another monster.  Returns true on success.
 */
static bool process_monster_try_push(struct chunk *c, struct monster *mon,
									 const char *m_name, int nx, int ny)
{
	struct monster *mon1 = square_monster(c, ny, nx);
	struct monster_lore *lore = get_lore(mon->race);

	/* Kill weaker monsters */
	int kill_ok = rf_has(mon->race->flags, RF_KILL_BODY);

	/* Move weaker monsters if they can swap places */
	/* (not in a wall) */
	int move_ok = (rf_has(mon->race->flags, RF_MOVE_BODY) &&
				   square_ispassable(c, mon->fy, mon->fx));

	if (compare_monsters(mon, mon1) > 0) {
		/* Learn about pushing and shoving */
		if (mflag_has(mon->mflag, MFLAG_VISIBLE)) {
			rf_on(lore->flags, RF_KILL_BODY);
			rf_on(lore->flags, RF_MOVE_BODY);
		}

		if (kill_ok || move_ok) {
			/* Get the names of the monsters involved */
			char n_name[80];
			monster_desc(n_name, sizeof(n_name), mon1, MDESC_IND_HID);

			/* Reveal mimics */
			if (is_mimicking(mon1))
				become_aware(mon1);

			/* Note if visible */
			if (mflag_has(mon->mflag, MFLAG_VISIBLE) &&
				mflag_has(mon->mflag, MFLAG_VIEW))
				msg("%s %s %s.", m_name,
					kill_ok ? "tramples over" : "pushes past", n_name);

			/* Monster ate another monster */
			if (kill_ok)
				delete_monster(ny, nx);

			monster_swap(mon->fy, mon->fx, ny, nx);
			return true;
		} 
	}

	return false;
}
예제 #21
0
파일: mon-msg.c 프로젝트: Colt374/angband
/**
 * Adds to the message queue a message describing a monster's reaction
 * to damage.
 */
void message_pain(int m_idx, int dam)
{
	long oldhp, newhp, tmp;
	int percentage;

	monster_type *m_ptr;

	int msg_code = MON_MSG_UNHARMED;
	char m_name[80];

	assert(m_idx > 0);
	m_ptr = cave_monster(cave, m_idx);

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

	/* Notice non-damage */
	if (dam == 0)
	{
		add_monster_message(m_name, m_idx, msg_code, FALSE);
		return;
	}

	/* Note -- subtle fix -CFT */
	newhp = (long)(m_ptr->hp);
	oldhp = newhp + (long)(dam);
	tmp = (newhp * 100L) / oldhp;
	percentage = (int)(tmp);

	if (percentage > 95)
		msg_code = MON_MSG_95;
	else if (percentage > 75)
		msg_code = MON_MSG_75;
	else if (percentage > 50)
		msg_code = MON_MSG_50;
	else if (percentage > 35)
		msg_code = MON_MSG_35;
	else if (percentage > 20)
		msg_code = MON_MSG_20;
	else if (percentage > 10)
		msg_code = MON_MSG_10;
	else
		msg_code = MON_MSG_0;

	add_monster_message(m_name, m_idx, msg_code, FALSE);
}
예제 #22
0
파일: target.c 프로젝트: Axydlbaaxr/angband
/**
 * Set target to closest monster.
 */
bool target_set_closest(int mode)
{
	int y, x;
	struct monster *mon;
	char m_name[80];
	struct point_set *targets;

	/* Cancel old target */
	target_set_monster(0);

	/* Get ready to do targetting */
	targets = target_get_monsters(mode);

	/* If nothing was prepared, then return */
	if (point_set_size(targets) < 1) {
		msg("No Available Target.");
		point_set_dispose(targets);
		return false;
	}

	/* Find the first monster in the queue */
	y = targets->pts[0].y;
	x = targets->pts[0].x;
	mon = square_monster(cave, y, x);
	
	/* Target the monster, if possible */
	if (!target_able(mon)) {
		msg("No Available Target.");
		point_set_dispose(targets);
		return false;
	}

	/* Target the monster */
	monster_desc(m_name, sizeof(m_name), mon, MDESC_CAPITAL);
	if (!(mode & TARGET_QUIET))
		msg("%s is targeted.", m_name);

	/* Set up target information */
	monster_race_track(player->upkeep, mon->race);
	health_track(player->upkeep, mon);
	target_set_monster(mon);

	point_set_dispose(targets);
	return true;
}
/*
 * Anger the monster
 */
void anger_monster(monster_type *m_ptr)
{
    if (p_ptr->inside_battle) return;
    if (is_friendly(m_ptr))
    {
        char m_name[80];

        monster_desc(m_name, m_ptr, 0);
        msg_format("%^s gets angry!", m_name);

        set_hostile(m_ptr);

        virtue_add(VIRTUE_INDIVIDUALISM, 1);
        virtue_add(VIRTUE_HONOUR, -1);
        virtue_add(VIRTUE_JUSTICE, -1);
        virtue_add(VIRTUE_COMPASSION, -1);
    }
}
예제 #24
0
cptr duelist_current_challenge(void)
{
    static char current_challenge[200];

    /* paranoia ... this only seems to happen with wizard mode summoned monsters
       after a save and restore, so probably the wizard 'n' command is broken */
    if (p_ptr->duelist_target_idx && !m_list[p_ptr->duelist_target_idx].r_idx)
        p_ptr->duelist_target_idx = 0;

    if (p_ptr->duelist_target_idx)
    {
        monster_desc(current_challenge, &m_list[p_ptr->duelist_target_idx], MD_ASSUME_VISIBLE);
        return current_challenge;
    }
    if (_equip_error())
        return "Talents Disrupted";

    return "No Current Challenge";
}
예제 #25
0
파일: monster3.c 프로젝트: jcubic/ToME
/* Player and monster swap places */
bool player_monster_swap(monster_type *m_ptr)
{
	char m_name[80];
	cave_type *c_ptr;

	if (!m_ptr) return FALSE;

	if (has_flag(m_ptr, FLAG_NO_PUSHBACK)) return FALSE;

	c_ptr = &cave[m_ptr->fy][m_ptr->fx];

	m_ptr->csleep = 0;

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

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

	/* Track a new monster */
	if (m_ptr->ml) health_track(c_ptr->m_idx);

	/* displace? */
	if (cave_floor_bold(p_ptr->py, p_ptr->px) ||
		monst_can_pass_square(m_ptr, p_ptr->py, p_ptr->px, NULL))
	{
		msg_format("You push past %s.", m_name);
		m_ptr->fy = p_ptr->py;
		m_ptr->fx = p_ptr->px;
		cave[p_ptr->py][p_ptr->px].m_idx = c_ptr->m_idx;
		c_ptr->m_idx = 0;
		update_mon(cave[p_ptr->py][p_ptr->px].m_idx, TRUE);
		return TRUE;
	}
	else
	{
		msg_format("%^s is in your way!", m_name);
		energy_use = 0;
		return FALSE;
	}
}
예제 #26
0
/**
 * Adds to the message queue a message describing a monster's reaction
 * to damage.
 */
void message_pain(struct monster *m_ptr, int dam)
{
    long oldhp, newhp, tmp;
    int percentage;

    int msg_code = MON_MSG_UNHARMED;
    char m_name[80];

    /* Get the monster name  - don't use monster_desc flags because
     * add_monster_message does string processing on m_name */
    monster_desc(m_name, sizeof(m_name), m_ptr, MDESC_DEFAULT);

    /* Notice non-damage */
    if (dam == 0) {
        add_monster_message(m_name, m_ptr, msg_code, FALSE);
        return;
    }

    /* Note -- subtle fix -CFT */
    newhp = (long)(m_ptr->hp);
    oldhp = newhp + (long)(dam);
    tmp = (newhp * 100L) / oldhp;
    percentage = (int)(tmp);

    if (percentage > 95)
        msg_code = MON_MSG_95;
    else if (percentage > 75)
        msg_code = MON_MSG_75;
    else if (percentage > 50)
        msg_code = MON_MSG_50;
    else if (percentage > 35)
        msg_code = MON_MSG_35;
    else if (percentage > 20)
        msg_code = MON_MSG_20;
    else if (percentage > 10)
        msg_code = MON_MSG_10;
    else
        msg_code = MON_MSG_0;

    add_monster_message(m_name, m_ptr, msg_code, FALSE);
}
예제 #27
0
/**
 * Process a monster spell 
 *
 * \param index is the monster spell flag (RSF_FOO)
 * \param mon is the attacking monster
 * \param seen is whether the player can see the monster at this moment
 */
void do_mon_spell(int index, struct monster *mon, bool seen)
{
	char m_name[80];
	bool ident, hits = FALSE;

	/* Extract the monster level */
	int rlev = ((mon->race->level >= 1) ? mon->race->level : 1);

	const struct monster_spell *spell = monster_spell_by_index(index);

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

	/* See if it hits */
	if (spell->hit == 100)
		hits = TRUE;
	else if (spell->hit == 0)
		hits = FALSE;
	else
		hits = check_hit(player, spell->hit, rlev);

	/* Tell the player what's going on */
	disturb(player, 1);
	spell_message(mon, spell, seen, hits);

	if (!hits) return;

	/* Try a saving throw if available */
	if (spell->save_message &&
		randint0(100) < player->state.skills[SKILL_SAVE]) {
		msg("%s", spell->save_message);
		return;
	}

	/* Do effects */
	effect_do(spell->effect, NULL, &ident, TRUE, 0, 0, 0);

	return;
}
예제 #28
0
파일: monster3.c 프로젝트: jcubic/ToME
/*
 * Turns a simple pet into a faithful companion
 */
void do_cmd_companion()
{
	monster_type *m_ptr;
	s32b ii, jj;

	if (!can_create_companion())
	{
		msg_print("You cannot get anymore companion.");
		return;
	}

	if (!tgt_pt(&ii, &jj))
	{
		msg_print("You must target a pet.");
		return;
	}

	if (cave[jj][ii].m_idx)
	{
		char m_name[100];

		m_ptr = get_monster(cave[jj][ii].m_idx);

		monster_desc(m_name, m_ptr, 0);
		if (m_ptr->faction == FACTION_PLAYER)
		{
			bool_flag(m_ptr, FLAG_PERMANENT);
			msg_format("%^s agrees to follow you.", m_name);
		}
		else
		{
			msg_format("%^s is not in your faction!", m_name);
		}
	}
	else
		msg_print("You must target a monster of your own faction.");
}
예제 #29
0
/*
 * Examine a grid, return a keypress.
 *
 * The "mode" argument contains the "TARGET_LOOK" bit flag, which
 * indicates that the "space" key should scan through the contents
 * of the grid, instead of simply returning immediately.  This lets
 * the "look" command get complete information, without making the
 * "target" command annoying.
 *
 * The "info" argument contains the "commands" which should be shown
 * inside the "[xxx]" text.  This string must never be empty, or grids
 * containing monsters will be displayed with an extra comma.
 *
 * Note that if a monster is in the grid, we update both the monster
 * recall info and the health bar info to track that monster.
 *
 * This function correctly handles multiple objects per grid, and objects
 * and terrain features in the same grid, though the latter never happens.
 *
 * This function must handle blindness/hallucination.
 */
static ui_event_data target_set_interactive_aux(int y, int x, int mode, cptr info, bool list_floor_objects)
{
	s16b this_o_idx, next_o_idx = 0;
	s16b this_x_idx, next_x_idx = 0;

	cptr s1, s2, s3;

	bool floored;

	u16b feat;

	ui_event_data query;

	char out_val[256];

	char coords[20];

	/* Describe the square location */
	coords_desc(coords, sizeof(coords), y, x);

	/* Repeat forever */
	while (1)
	{
		int i;

		char feat_name[80];
		/* Terrain suffix for monsters and objects */
		char terrain_suffix[200];

		/* Temporary array of visible effects */
		s16b x_seen[50];
		u16b size_x_seen = 0;

		/* Paranoia */
		query.key = ' ';

		/* Default */
		s1 = "You see ";
		s2 = "";
		s3 = "on ";


		/* The player */
		if (cave_m_idx[y][x] < 0)
		{
			/* Description */
			s1 = "You are ";

			/* Preposition */
			s2 = "on ";
		}

		/* Feature (apply "mimic") */
		feat = f_info[cave_feat[y][x]].f_mimic;

		/* Require knowledge about grid, or ability to see grid */
		if (!(cave_info[y][x] & (CAVE_MARK)) && !player_can_see_bold(y,x))
		{
			/* Forget feature */
			feat = FEAT_NONE;
		}

		else
		{
			/* Hack -- track the current feature */
			feature_kind_track(feat);

			/* Window stuff */
			p_ptr->redraw |= (PR_FEATURE);
		}

		/* Pick a prefix */
		if (*s2 && (!feat_ff1_match(feat, FF1_MOVE) ||
			!feat_ff1_match(feat, FF1_LOS) ||
			feat_ff1_match(feat, FF1_SHOP | FF1_DOOR) ||
			feat_ff2_match(feat, FF2_SHALLOW | FF2_DEEP) ||
			feat_ff3_match(feat, FF3_NEED_TREE)))
		{
			s3 = "in ";
		}

		/* Get a default name */
		if (feat <= FEAT_NONE)
		{
			my_strcpy(feat_name, "an unknown grid", sizeof(feat_name));
		}
		/* Get the real name */
		else
		{
			feature_desc(feat_name, sizeof (feat_name), feat, TRUE, FALSE);
		}

		/* List all effects in the grid */
		for (this_x_idx = cave_x_idx[y][x]; this_x_idx; this_x_idx = next_x_idx)
		{
			effect_type *x_ptr;

			/* Get the effect */
			x_ptr = &x_list[this_x_idx];

			/* Get the next effect */
			next_x_idx = x_ptr->next_x_idx;

			/* Describe it, if not hidden */
			if (!(x_ptr->x_flags & (EF1_HIDDEN)) && x_ptr->x_f_idx)
			{
				/* Check for available space */
				if (size_x_seen < N_ELEMENTS(x_seen))
				{
					x_seen[size_x_seen++] = x_ptr->x_f_idx;
				}
			}
		}

		/* Prepare the terrain suffix for monsters and objects */
		my_strcpy(terrain_suffix, format(" %s%s", s3, feat_name), sizeof(terrain_suffix));

		/* Concat the collected effect names */
		for (i = 0; i < size_x_seen; i++)
		{
			char x_name[80];

			/* Obtain an object description */
			feature_desc(x_name, sizeof(x_name), x_seen[i], TRUE, TRUE);

			/* First effect */
			if (i == 0)
			{
				if ((feat == FEAT_NONE) || !feat_ff1_match(feat, FF1_MOVE) ||
					cave_any_trap_bold(y, x))
				{
					/* Basic info */
					my_strcat(terrain_suffix, format(" with %s", x_name),
						sizeof(terrain_suffix));
				}
				else
				{
					/* Basic info */
					my_strcat(terrain_suffix, format(" beneath %s", x_name),
						sizeof(terrain_suffix));
				}
			}

			/* Basic info */
			else if (i < (size_x_seen - 1))
			{
				my_strcat(terrain_suffix, format(", %s", x_name), sizeof(terrain_suffix));
			}

			/* Basic info */
			else
			{
				my_strcat(terrain_suffix, format(" and %s", x_name), sizeof(terrain_suffix));
			}
		}

		/* Ignore the terrain suffix if certain things happen */
		if ((size_x_seen == 0) && (feat <= FEAT_FLOOR))
		{
			terrain_suffix[0] = '\0';
		}

		/* Hack -- hallucination */
		if (p_ptr->timed[TMD_IMAGE])
		{
			cptr name = "something strange";

			/* Display a message */
			if (p_ptr->wizard)
			{
				strnfmt(out_val, sizeof(out_val),
						"%s%s%s, [%s] %s (%d:%d).", s1, s2, name, info, coords, y, x);
			}
			else
			{
				strnfmt(out_val, sizeof(out_val),
						"%s%s%s [%s], %s.", s1, s2, name, info, coords);
			}

			prt(out_val, 0, 0);
			move_cursor_relative(y, x);

			query = inkey_ex();

			/* Stop on everything but "return" */
			if ((query.key != '\n') && (query.key != '\r')) break;

			/* Repeat forever */
			continue;
		}

		/* Actual monsters */
		if (cave_m_idx[y][x] > 0)
		{
			monster_type *m_ptr = &mon_list[cave_m_idx[y][x]];
			monster_race *r_ptr = &r_info[m_ptr->r_idx];

			/* Visible */
			if (m_ptr->ml)
			{
				bool recall = FALSE;

				char m_name[80];

				if (m_ptr->mimic_k_idx)
				{
					/*get the description*/
					mimic_desc_object(m_name, sizeof(m_name), m_ptr->mimic_k_idx);
				}

				else
				{
					/* Get the monster name ("a kobold") */
					monster_desc(m_name, sizeof(m_name), m_ptr, 0x08);

					/* Hack -- track this monster race */
					monster_race_track(m_ptr->r_idx);

					/* Hack -- health bar for this monster */
					health_track(cave_m_idx[y][x]);

					/*Track the feature*/
					feature_kind_track(cave_feat[y][x]);

					/* Window stuff */
					p_ptr->redraw |= (PR_FEATURE);

					/* Hack -- handle stuff */
					handle_stuff();
				}

				/* Interact */
				while (1)
				{
					if (recall)	button_add("[CLEAR_RECALL]", 'r');
					else 		button_add("[RECALL]", 'r');
					if (cave_o_idx[y][x] > 0)button_add("[VIEW_FLOOR]", 'f');
					event_signal(EVENT_MOUSEBUTTONS);

					/* Recall, but not mimics */
					if ((recall) && (!(m_ptr->mimic_k_idx)))
					{
						/* Save screen */
						screen_save();

						/* Recall on screen */
						screen_roff(m_ptr->r_idx);

						/* Hack -- Complete the prompt (again) */
						Term_addstr(-1, TERM_WHITE, format(" [r,%s]", info));

						/* Command */
						query = inkey_ex();

						/* Load screen */
						screen_load();
					}

					/* Normal */
					else
					{

						/* Basic info */
						strnfmt(out_val, sizeof(out_val),
							"%s%s%s", s1, s2, m_name);

						/* Describe the monster, unless a mimic */
						if (!(m_ptr->mimic_k_idx))
						{
							char buf[80];

							look_mon_desc(buf, sizeof(buf), cave_m_idx[y][x]);

							/* Monster state, terrain suffix, options  */
							my_strcat(out_val, format(" (%s)%s [r,%s]",
								buf, terrain_suffix, info),
								sizeof(out_val));
						}

						/* Mimics */
						else
						{
							/* Terrain suffix, options */
							my_strcat(out_val,
								format("%s [I,%s]", terrain_suffix,
								info), sizeof(out_val));
						}

						/* Wizards want coordinates */
						if (p_ptr->wizard)
						{
							my_strcat(out_val, format(" (%d:%d)", y, x),
								sizeof(out_val));
						}

						prt(out_val, 0, 0);

						/* Place cursor */
						move_cursor_relative(y, x);

						/* Command */
						query = inkey_ex();
					}

					button_kill('r');
					button_kill('f');
					event_signal(EVENT_MOUSEBUTTONS);

					/* Handle fake object recall */
					if (m_ptr->mimic_k_idx)
					{
						object_type body;
						object_type *o_ptr = &body;

						/* Validate input first */
						if (query.key != 'I') break;

						/* Paranoia */
						object_wipe(o_ptr);

						/* Prepare */
						object_prep(o_ptr, m_ptr->mimic_k_idx);

						/* Fake history */
						object_history(o_ptr, ORIGIN_FLOOR, 0);

						/* Clear prompt. Place cursor */
						prt("", 0, 0);

						/* Show the fake info - EXPERIMENTAL */
						object_info_screen(o_ptr);
					}
					/* Regular monsters */
					else
					{
						/* Normal commands */
						if (query.key != 'r') break;

						/* Toggle recall */
						recall = !recall;
					}
				}

				/* Stop on everything but "return"/"space", or floor */
				if ((query.key != '\n') && (query.key != '\r') &&
					(query.key != ' ') && (query.key != 'f')) break;

				/* continue with 'f' only if there are floor items....*/
				if ((query.key == 'f') && (!cave_o_idx[y][x])) break;

				/* Sometimes stop at "space" key */
				if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break;

				/* Change the intro */
				s1 = "It is ";

				/* Hack -- take account of gender */
				if (r_ptr->flags1 & (RF1_FEMALE)) s1 = "She is ";
				else if (r_ptr->flags1 & (RF1_MALE)) s1 = "He is ";

				/* Use a preposition */
				s2 = "carrying ";

				/* Scan all objects being carried */
				for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
				{
					char o_name[80];

					object_type *o_ptr;

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

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

					/*Don't let the player see certain objects (used for vault treasure)*/
					if ((o_ptr->ident & (IDENT_HIDE_CARRY)) && (!p_ptr->wizard) &&
						(!cheat_peek))	 continue;

					/* Obtain an object description */
					object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL);

					/* Describe the object */
					strnfmt(out_val, sizeof(out_val),
						"%s%s%s [%s]", s1, s2, o_name, info);

					/* Wizards want coordinates */
					if (p_ptr->wizard)
					{
						my_strcat(out_val, format(" (%d:%d)", y, x), sizeof(out_val));
					}

					prt(out_val, 0, 0);
					move_cursor_relative(y, x);
					query = inkey_ex();

					/* Stop on everything but "return"/"space" */
					if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break;

					/* Sometimes stop at "space" key */
					if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break;

					/* Change the intro */
					s2 = "also carrying ";
				}

				/* Double break */
				if (this_o_idx) break;

				/* Use a preposition */
				s2 = "on ";
			}
		}

		/* Assume not floored */
		floored = FALSE;

		/* Scan all objects in the grid */
		if (TRUE)
		{
			int floor_list[MAX_FLOOR_STACK];
			int floor_num;

			track_object(-floor_list[0]);
			handle_stuff();

			/* Scan for floor objects */
			floor_num = scan_floor(floor_list, MAX_FLOOR_STACK, y, x, 0x02);

			/* Actual pile */
			if (floor_num > 1)
			{
				/* Floored */
				floored = TRUE;

				/* Describe */
				while (1)
				{
					/* Basic info */
					strnfmt(out_val, sizeof(out_val),
						"%s%sa pile of %d objects%s [r,%s]", s1, s2,
						floor_num, terrain_suffix, info);

					/* Wizards want coordinates */
					if (p_ptr->wizard)
					{
						my_strcat(out_val, format(" (%d:%d)", y, x), sizeof(out_val));
					}

					prt(out_val, 0, 0);

					if (list_floor_objects)
					{
						/* Save screen */
						screen_save();

						/* Display */
						show_floor(floor_list, floor_num, (OLIST_WEIGHT | OLIST_GOLD));
					}
					move_cursor_relative(y, x);
					query = inkey_ex();

					if (list_floor_objects)
					{
						screen_load();
					}

					/* Display objects */
					if (query.key == 'r')
					{
						int pos;

						pos = query.key - 'a';
						if (0 <= pos && pos < floor_num)
						{
							track_object(-floor_list[pos]);
							handle_stuff();
						}
					}

					/* Done */
					break;
				}

				/* Stop on everything but "return"/"space" */
				if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break;

				/* Sometimes stop at "space" key */
				if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break;

				/* Change the intro */
				s1 = "It is ";

				/* Preposition */
				s2 = "on ";
			}
		}

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

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

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

			/* Skip objects if floored */
			if (floored) continue;

			/* Describe it */
			if (o_ptr->marked)
			{
				char o_name[80];

				/* Obtain an object description */
				object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL);

				/* Basic info */
				strnfmt(out_val, sizeof(out_val), "%s%s%s%s [I,%s]",
					s1, s2, o_name, terrain_suffix, info);

				/* Wizards want coordinates */
				if (p_ptr->wizard)
				{
					my_strcat(out_val, format(" (%d:%d)", y, x),
						sizeof(out_val));
				}

				/* Show object. Handle object recall */
				while (TRUE)
				{
					/* Print the prompt */
					prt(out_val, 0, 0);

					/* Move cursor to that location */
					move_cursor_relative(y, x);

					/* Read input key */
					query = inkey_ex();

					/* No object recall */
					if (query.key != 'I') break;

					/* Object recall. Clear the first line */
					prt("", 0, 0);

					/* Do it */
					object_info_screen(o_ptr);
				}

				/* Stop on everything but "return"/"space" */
				if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break;

				/* Sometimes stop at "space" key */
				if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break;

				/* Change the intro */
				s1 = "It is ";

				/* Plurals */
				if (o_ptr->number != 1) s1 = "They are ";

				/* Preposition */
				s2 = "on ";
			}
		}

		/* Double break */
		if (this_o_idx) break;

		/* Display terrain */
		if (TRUE)
		{
			u16b temp_feat;
			bool enable_recall;
			bool show_recall = FALSE;
			char temp_name[80];

			/*
			 * Display terrain and effects
			 */
			for (i = 0; i <= size_x_seen; i++)
			{
				/* Hack - This is the mark for the feature stored in cave_feat */
				if (i == size_x_seen)
				{
				       	temp_feat = feat;

					/* Just copy the feature name */
					my_strcpy(temp_name, feat_name, sizeof(temp_name));
				}
				/* Any other value is an effect stored x_list */
				else
				{
					temp_feat = x_seen[i];

					/* Get the effect's name */
					feature_desc(temp_name, sizeof(temp_name), temp_feat, TRUE, TRUE);
				}

				/* Don't display feature recall if the grid is unknown */
				enable_recall = (temp_feat != FEAT_NONE);

				/* Handle recall */
				while (TRUE)
				{

					/* Handle recall mode */
					if (show_recall && enable_recall)
					{
						/* Save screen */
						screen_save();

						/* Recall feature on screen */
						screen_feature_roff(temp_feat);
					}

					/* Display a message */
					strnfmt(out_val, sizeof(out_val),
						"%s%s%s [%s%s]%s", s1, s2, temp_name,
						(enable_recall ? "r,": ""), info,
						(i < size_x_seen) ? " (more)": "");

					/* Wizards want coordinates */
					if (p_ptr->wizard)
					{
						my_strcat(out_val, format(" (%d:%d)", y, x), sizeof(out_val));
					}

					/*Track this feature*/
					feature_kind_track(temp_feat);

					/* Hack -- handle stuff */
					handle_stuff();

					prt(out_val, 0, 0);
					move_cursor_relative(y, x);
					query = inkey_ex();

					/* Load screen if necessary */
					if (show_recall && enable_recall)
					{
						screen_load();
					}

					/* Stop on everything but the recall command, if enabled */
					if (!enable_recall || (query.key != 'r')) break;

					/* Toggle recall */
					show_recall = !show_recall;
				}

				/* Stop on everything but "return"/"space" */
				if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break;
			}
		}

		/* Hack -- handle stuff */
		handle_stuff();

		/* Stop on everything but "return" */
		if ((query.key != '\n') && (query.key != '\r')) break;
	}

	/* Keep going */
	return (query);
}
예제 #30
0
파일: target.c 프로젝트: EpicMan/angband
/*
 * Examine a grid, return a keypress.
 *
 * The "mode" argument contains the "TARGET_LOOK" bit flag, which
 * indicates that the "space" key should scan through the contents
 * of the grid, instead of simply returning immediately.  This lets
 * the "look" command get complete information, without making the
 * "target" command annoying.
 *
 * The "info" argument contains the "commands" which should be shown
 * inside the "[xxx]" text.  This string must never be empty, or grids
 * containing monsters will be displayed with an extra comma.
 *
 * Note that if a monster is in the grid, we update both the monster
 * recall info and the health bar info to track that monster.
 *
 * This function correctly handles multiple objects per grid, and objects
 * and terrain features in the same grid, though the latter never happens.
 *
 * This function must handle blindness/hallucination.
 */
static ui_event_data target_set_interactive_aux(int y, int x, int mode)
{
	s16b this_o_idx = 0, next_o_idx = 0;

	cptr s1, s2, s3;

	bool boring;

	bool floored;

	int feat;

	int floor_list[MAX_FLOOR_STACK];
	int floor_num;

	ui_event_data query;

	char out_val[256];

	char coords[20];
	
	/* Describe the square location */
	coords_desc(coords, sizeof(coords), y, x);

	/* Repeat forever */
	while (1)
	{
		/* Paranoia */
		query.key = ' ';

		/* Assume boring */
		boring = TRUE;

		/* Default */
		s1 = "You see ";
		s2 = "";
		s3 = "";


		/* The player */
		if (cave_m_idx[y][x] < 0)
		{
			/* Description */
			s1 = "You are ";

			/* Preposition */
			s2 = "on ";
		}

		/* Hack -- hallucination */
		if (p_ptr->timed[TMD_IMAGE])
		{
			cptr name = "something strange";

			/* Display a message */
			if (p_ptr->wizard)
			{
				strnfmt(out_val, sizeof(out_val),
						"%s%s%s%s, %s (%d:%d).", s1, s2, s3, name, coords, y, x);
			}
			else
			{
				strnfmt(out_val, sizeof(out_val),
						"%s%s%s%s, %s.", s1, s2, s3, name, coords);
			}

			prt(out_val, 0, 0);
			move_cursor_relative(y, x);
			query = inkey_ex();

			/* Stop on everything but "return" */
			if ((query.key != '\n') && (query.key != '\r')) break;

			/* Repeat forever */
			continue;
		}

		/* Actual monsters */
		if (cave_m_idx[y][x] > 0)
		{
			monster_type *m_ptr = &mon_list[cave_m_idx[y][x]];
			monster_race *r_ptr = &r_info[m_ptr->r_idx];

			/* Visible */
			if (m_ptr->ml)
			{
				bool recall = FALSE;

				char m_name[80];

				/* Not boring */
				boring = FALSE;

				/* Get the monster name ("a kobold") */
				monster_desc(m_name, sizeof(m_name), m_ptr, MDESC_IND2);

				/* Hack -- track this monster race */
				monster_race_track(m_ptr->r_idx);

				/* Hack -- health bar for this monster */
				health_track(cave_m_idx[y][x]);

				/* Hack -- handle stuff */
				handle_stuff();

				/* Interact */
				while (1)
				{
					/* Recall */
					if (recall)
					{
						/* Save screen */
						screen_save();

						/* Recall on screen */
						screen_roff(m_ptr->r_idx);

						/* Command */
						query = inkey_ex();

						/* Load screen */
						screen_load();
					}

					/* Normal */
					else
					{
						char buf[80];

						/* Describe the monster */
						look_mon_desc(buf, sizeof(buf), cave_m_idx[y][x]);

						/* Describe, and prompt for recall */
						if (p_ptr->wizard)
						{
							strnfmt(out_val, sizeof(out_val),
									"%s%s%s%s (%s), %s (%d:%d).",
									s1, s2, s3, m_name, buf, coords, y, x);
						}
						else
						{
							strnfmt(out_val, sizeof(out_val),
									"%s%s%s%s (%s), %s.",
									s1, s2, s3, m_name, buf, coords);
						}

						prt(out_val, 0, 0);

						/* Place cursor */
						move_cursor_relative(y, x);

						/* Command */
						query = inkey_ex();
					}

					/* Normal commands */
					if (query.key != 'r') break;

					/* Toggle recall */
					recall = !recall;
				}

				/* Stop on everything but "return"/"space" */
				if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break;

				/* Sometimes stop at "space" key */
				if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break;

				/* Change the intro */
				s1 = "It is ";

				/* Hack -- take account of gender */
				if (rf_has(r_ptr->flags, RF_FEMALE)) s1 = "She is ";
				else if (rf_has(r_ptr->flags, RF_MALE)) s1 = "He is ";

				/* Use a preposition */
				s2 = "carrying ";

				/* Scan all objects being carried */
				for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
				{
					char o_name[80];

					object_type *o_ptr;

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

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

					/* Obtain an object description */
					object_desc(o_name, sizeof(o_name), o_ptr,
								ODESC_PREFIX | ODESC_FULL);

					/* Describe the object */
					if (p_ptr->wizard)
					{
						strnfmt(out_val, sizeof(out_val),
								"%s%s%s%s, %s (%d:%d).",
								s1, s2, s3, o_name, coords, y, x);
					}
					else
					{
						strnfmt(out_val, sizeof(out_val),
								"%s%s%s%s, %s.", s1, s2, s3, o_name, coords);
					}

					prt(out_val, 0, 0);
					move_cursor_relative(y, x);
					query = inkey_ex();

					/* Stop on everything but "return"/"space" */
					if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break;

					/* Sometimes stop at "space" key */
					if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break;

					/* Change the intro */
					s2 = "also carrying ";
				}

				/* Double break */
				if (this_o_idx) break;

				/* Use a preposition */
				s2 = "on ";
			}
		}


		/* Assume not floored */
		floored = FALSE;

		floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), y, x, 0x02);

		/* Scan all marked objects in the grid */
		if ((floor_num > 0) &&
		    (!(p_ptr->timed[TMD_BLIND]) || (y == p_ptr->py && x == p_ptr->px)))
		{
			/* Not boring */
			boring = FALSE;

			track_object(-floor_list[0]);
			handle_stuff();

			/* If there is more than one item... */
			if (floor_num > 1) while (1)
			{
				floored = TRUE;

				/* Describe the pile */
				if (p_ptr->wizard)
				{
					strnfmt(out_val, sizeof(out_val),
							"%s%s%sa pile of %d objects, %s (%d:%d).",
							s1, s2, s3, floor_num, coords, y, x);
				}
				else
				{
					strnfmt(out_val, sizeof(out_val),
							"%s%s%sa pile of %d objects, %s.",
							s1, s2, s3, floor_num, coords);
				}

				prt(out_val, 0, 0);
				move_cursor_relative(y, x);
				query = inkey_ex();

				/* Display objects */
				if (query.key == 'r')
				{
					int rdone = 0;
					int pos;
					while (!rdone)
					{
						/* Save screen */
						screen_save();

						/* Display */
						show_floor(floor_list, floor_num, (OLIST_WEIGHT | OLIST_GOLD));

						/* Describe the pile */
						prt(out_val, 0, 0);
						query = inkey_ex();

						/* Load screen */
						screen_load();

						pos = query.key - 'a';
						if (0 <= pos && pos < floor_num)
						{
							track_object(-floor_list[pos]);
							handle_stuff();
							continue;
						}
						rdone = 1;
					}

					/* Now that the user's done with the display loop, let's */
					/* the outer loop over again */
					continue;
				}

				/* Done */
				break;
			}
			/* Only one object to display */
			else
			{

				char o_name[80];

				/* Get the single object in the list */
				object_type *o_ptr = &o_list[floor_list[0]];

				/* Not boring */
				boring = FALSE;

				/* Obtain an object description */
				object_desc(o_name, sizeof(o_name), o_ptr,
							ODESC_PREFIX | ODESC_FULL);

				/* Describe the object */
				if (p_ptr->wizard)
				{
					strnfmt(out_val, sizeof(out_val),
							"%s%s%s%s, %s (%d:%d).",
							s1, s2, s3, o_name, coords, y, x);
				}
				else
				{
					strnfmt(out_val, sizeof(out_val),
							"%s%s%s%s, %s.", s1, s2, s3, o_name, coords);
				}

				prt(out_val, 0, 0);
				move_cursor_relative(y, x);
				query = inkey_ex();

				/* Stop on everything but "return"/"space" */
				if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break;

				/* Sometimes stop at "space" key */
				if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break;

				/* Change the intro */
				s1 = "It is ";

				/* Plurals */
				if (o_ptr->number != 1) s1 = "They are ";

				/* Preposition */
				s2 = "on ";
			}

		}

		/* Double break */
		if (this_o_idx) break;


		/* Feature (apply "mimic") */
		feat = f_info[cave_feat[y][x]].mimic;

		/* Require knowledge about grid, or ability to see grid */
		if (!(cave_info[y][x] & (CAVE_MARK)) && !player_can_see_bold(y,x))
		{
			/* Forget feature */
			feat = FEAT_NONE;
		}

		/* Terrain feature if needed */
		if (boring || (feat > FEAT_INVIS))
		{
			cptr name = f_info[feat].name;

			/* Hack -- handle unknown grids */
			if (feat == FEAT_NONE) name = "unknown grid";

			/* Pick a prefix */
			if (*s2 && (feat >= FEAT_DOOR_HEAD)) s2 = "in ";

			/* Pick proper indefinite article */
			s3 = (is_a_vowel(name[0])) ? "an " : "a ";

			/* Hack -- special introduction for store doors */
			if ((feat >= FEAT_SHOP_HEAD) && (feat <= FEAT_SHOP_TAIL))
			{
				s3 = "the entrance to the ";
			}

			/* Display a message */
			if (p_ptr->wizard)
			{
				strnfmt(out_val, sizeof(out_val),
						"%s%s%s%s, %s (%d:%d).", s1, s2, s3, name, coords, y, x);
			}
			else
			{
				strnfmt(out_val, sizeof(out_val),
						"%s%s%s%s, %s.", s1, s2, s3, name, coords);
			}

			prt(out_val, 0, 0);
			move_cursor_relative(y, x);
			query = inkey_ex();

			/* Stop on everything but "return"/"space" */
			if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break;
		}

		/* Stop on everything but "return" */
		if ((query.key != '\n') && (query.key != '\r')) break;
	}

	/* Keep going */
	return (query);
}