Exemplo n.º 1
0
/*
 * Manipulate an adjacent grid in some way
 *
 * Attack monsters, tunnel through walls, disarm traps, open doors.
 *
 * This command must always take energy, to prevent free detection
 * of invisible monsters.
 *
 * The "semantics" of this command must be chosen before the player
 * is confused, and it must be verified against the new grid.
 */
void do_cmd_alter_aux(int dir)
{
	int y, x;
	bool more = FALSE;

	/* Get location */
	y = p_ptr->py + ddy[dir];
	x = p_ptr->px + ddx[dir];

	/* Take a turn */
	p_ptr->energy_use = 100;

	/* Apply confusion */
	if (player_confuse_dir(p_ptr, &dir, FALSE)) {
		/* Get location */
		y = p_ptr->py + ddy[dir];
		x = p_ptr->px + ddx[dir];
	}

	/* Attack monsters */
	if (cave->m_idx[y][x] > 0)
		py_attack(y, x);

	/* Tunnel through walls and rubble */
	else if (cave_isdiggable(cave, y, x))
		more = do_cmd_tunnel_aux(y, x);

	/* Open closed doors */
	else if (cave_iscloseddoor(cave, y, x))
		more = do_cmd_open_aux(y, x);

	/* Disarm traps */
	else if (cave_isknowntrap(cave, y, x))
		more = do_cmd_disarm_aux(y, x);

	/* Oops */
	else
		msg("You spin around.");

	/* Cancel repetition unless we can continue */
	if (!more) disturb(p_ptr, 0, 0);
}
Exemplo n.º 2
0
/**
 * Manipulate an adjacent grid in some way
 *
 * Attack monsters, tunnel through walls, disarm traps, open doors.
 *
 * This command must always take energy, to prevent free detection
 * of invisible monsters.
 *
 * The "semantics" of this command must be chosen before the player
 * is confused, and it must be verified against the new grid.
 */
void do_cmd_alter_aux(int dir)
{
	int y, x;
	bool more = false;

	/* Get location */
	y = player->py + ddy[dir];
	x = player->px + ddx[dir];

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

	/* Apply confusion */
	if (player_confuse_dir(player, &dir, false)) {
		/* Get location */
		y = player->py + ddy[dir];
		x = player->px + ddx[dir];
	}

	/* Action depends on what's there */
	if (cave->squares[y][x].mon > 0)
		/* Attack monsters */
		py_attack(y, x);
	else if (square_isdiggable(cave, y, x))
		/* Tunnel through walls and rubble */
		more = do_cmd_tunnel_aux(y, x);
	else if (square_iscloseddoor(cave, y, x))
		/* Open closed doors */
		more = do_cmd_open_aux(y, x);
	else if (square_isknowntrap(cave, y, x))
		/* Disarm traps */
		more = do_cmd_disarm_aux(y, x);
	else
		/* Oops */
		msg("You spin around.");

	/* Cancel repetition unless we can continue */
	if (!more) disturb(player, 0);
}
Exemplo n.º 3
0
/**
 * Open a closed/locked/jammed door or a closed/locked chest.
 *
 * Unlocking a locked chest is worth one experience point; since doors are
 * player lockable, there is no experience for unlocking doors.
 */
void do_cmd_open(struct command *cmd)
{
	int y, x, dir;
	struct object *obj;
	bool more = false;
	int err;
	struct monster *m;

	/* Get arguments */
	err = cmd_get_arg_direction(cmd, "direction", &dir);
	if (err || dir == DIR_UNKNOWN) {
		int y2, x2;
		int n_closed_doors, n_locked_chests;

		n_closed_doors = count_feats(&y2, &x2, square_iscloseddoor, false);
		n_locked_chests = count_chests(&y2, &x2, CHEST_OPENABLE);

		if (n_closed_doors + n_locked_chests == 1) {
			dir = coords_to_dir(y2, x2);
			cmd_set_arg_direction(cmd, "direction", dir);
		} else if (cmd_get_direction(cmd, "direction", &dir, false)) {
			return;
		}
	}

	/* Get location */
	y = player->py + ddy[dir];
	x = player->px + ddx[dir];

	/* Check for chest */
	obj = chest_check(y, x, CHEST_OPENABLE);

	/* Check for door */
	if (!obj && !do_cmd_open_test(y, x)) {
		/* Cancel repeat */
		disturb(player, 0);
		return;
	}

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

	/* Apply confusion */
	if (player_confuse_dir(player, &dir, false)) {
		/* Get location */
		y = player->py + ddy[dir];
		x = player->px + ddx[dir];

		/* Check for chest */
		obj = chest_check(y, x, CHEST_OPENABLE);
	}

	/* Monster */
	m = square_monster(cave, y, x);
	if (m) {
		/* Mimics surprise the player */
		if (is_mimicking(m)) {
			become_aware(m);

			/* Mimic wakes up */
			mon_clear_timed(m, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, false);
		} else {
			/* Message */
			msg("There is a monster in the way!");

			/* Attack */
			py_attack(y, x);
		}
	} else if (obj) {
		/* Chest */
		more = do_cmd_open_chest(y, x, obj);
	} else {
		/* Door */
		more = do_cmd_open_aux(y, x);
	}

	/* Cancel repeat unless we may continue */
	if (!more) disturb(player, 0);
}
Exemplo n.º 4
0
/*
 * Open a closed/locked/jammed door or a closed/locked chest.
 *
 * Unlocking a locked door/chest is worth one experience point.
 */
void do_cmd_open(cmd_code code, cmd_arg args[])
{
	int y, x, dir;

	s16b o_idx;

	bool more = FALSE;

	dir = args[0].direction;

	/* Get location */
	y = p_ptr->py + ddy[dir];
	x = p_ptr->px + ddx[dir];

	/* Check for chests */
	o_idx = chest_check(y, x);


	/* Verify legality */
	if (!o_idx && !do_cmd_open_test(y, x))
	{
		/* Cancel repeat */
		disturb(0, 0);
		return;
	}

	/* Take a turn */
	p_ptr->energy_use = 100;

	/* Apply confusion */
	if (confuse_dir(&dir))
	{
		/* Get location */
		y = p_ptr->py + ddy[dir];
		x = p_ptr->px + ddx[dir];

		/* Check for chest */
		o_idx = chest_check(y, x);
	}


	/* Monster */
	if (cave_m_idx[y][x] > 0)
	{
		if (mon_list[cave_m_idx[y][x]].align & (AL_PET_MASK))
			msg_print("There is a friendly monster in the way!");
		else
		{
			/* Message */
			msg_print("There is a monster in the way!");

			/* Attack */
			py_attack(y, x);
		}
	}

	/* Chest */
	else if (o_idx)
	{
		/* Open the chest */
		more = do_cmd_open_chest(y, x, o_idx);
	}

	/* Door */
	else
	{
		/* Open the door */
		more = do_cmd_open_aux(y, x);
	}

	/* Cancel repeat unless we may continue */
	if (!more) disturb(0, 0);
}
Exemplo n.º 5
0
/*
 * Manipulate an adjacent grid in some way
 *
 * Attack monsters, tunnel through walls, disarm traps, open doors.
 *
 * This command must always take energy, to prevent free detection
 * of invisible monsters.
 *
 * The "semantics" of this command must be chosen before the player
 * is confused, and it must be verified against the new grid.
 */
void do_cmd_alter_aux(int dir)
{
	int y, x;

	int feat;

	bool more = FALSE;

	/* Get location */
	y = p_ptr->py + ddy[dir];
	x = p_ptr->px + ddx[dir];


	/* Original feature */
	feat = cave_feat[y][x];

	/* Must have knowledge to know feature XXX XXX */
	if (!(cave_info[y][x] & (CAVE_MARK))) feat = FEAT_NONE;


	/* Take a turn */
	p_ptr->energy_use = 100;

	/* Apply confusion */
	if (confuse_dir(&dir))
	{
		/* Get location */
		y = p_ptr->py + ddy[dir];
		x = p_ptr->px + ddx[dir];
	}


	/* Attack monsters */
	if (cave_m_idx[y][x] > 0)
	{
		if (mon_list[cave_m_idx[y][x]].align & (AL_PET_MASK))
		{
			msg_print("There is a friendly monster in the way!");
		}
		else
		{
			/* Attack */
			py_attack(y, x);
		}
	}

	/* Tunnel through walls */
	else if (feat >= FEAT_SECRET)
	{
		more = do_cmd_tunnel_aux(y, x);
	}

#if 0
	/* Bash jammed doors */
	else if (feat >= FEAT_DOOR_HEAD + 0x08)
	{
		more = do_cmd_bash_aux(y, x);
	}
#endif

	/* Open closed doors */
	else if (feat >= FEAT_DOOR_HEAD)
	{
		more = do_cmd_open_aux(y, x);
	}

	/* Disarm traps */
	else if (feat >= FEAT_TRAP_HEAD)
	{
		more = do_cmd_disarm_aux(y, x);
	}

#if 0
	/* Close open doors */
	else if (feat == FEAT_OPEN)
	{
		more = do_cmd_close_aux(y, x);
	}
#endif

	/* Oops */
	else
	{
		msg_print("You spin around.");
	}

	/* Cancel repetition unless we can continue */
	if (!more) disturb(0, 0);
}
Exemplo n.º 6
0
/**
 * Move player in the given direction, with the given "pickup" flag.
 *
 * This routine should only be called when energy has been expended.
 *
 * Note that this routine handles monsters in the destination grid,
 * and also handles attempting to move into walls/doors/etc.
 */
void move_player(int dir)
{
    int py = p_ptr->py;
    int px = p_ptr->px;

    byte str_escape, dex_escape;

    /* Permit the player to move? */
    bool can_move = FALSE;

    /* Player is jumping off a cliff */
    bool falling = FALSE;

    /* Player hits a trap (always unless flying) */
    bool trapped = TRUE;

    int temp;
    int y, x;

    /* Find the result of moving */
    y = py + ddy[dir];
    x = px + ddx[dir];


    /* Hack -- attack monsters */
    if (cave_m_idx[y][x] > 0) {
	/* Attack */
	if (py_attack(y, x, TRUE))
	    return;
    }

    /* It takes some dexterity, or failing that strength, to get out of pits */
    if (cave_feat[p_ptr->py][p_ptr->px] == (FEAT_TRAP_HEAD + 0x01)) {
	str_escape = adj_dex_dis[p_ptr->state.stat_ind[A_STR]];
	dex_escape = adj_dex_dis[p_ptr->state.stat_ind[A_DEX]];

	/* First attempt to leap out of the pit, */
	if ((dex_escape + 1) * 2 < randint1(16)) {
	    /* then attempt to climb out of the pit. */
	    if (str_escape + 3 < randint1(16)) {
		/* Failure costs a turn. */
		msg_print("You remain stuck in the pit.");
		return;
	    } else
		msg_print("You clamber out of the pit.");
	} else
	    msg_print("You leap out of the pit.");
    }


    /* Option to disarm a visible trap. -TNB- */
    /* Hack - Rogues can walk over their own trap - BR */
    if (OPT(easy_alter) && (cave_feat[y][x] >= FEAT_TRAP_HEAD)
	&& (cave_feat[y][x] <= FEAT_TRAP_TAIL)) 
    {
	bool more = FALSE;
	/* Auto-repeat if not already repeating */
	if (cmd_get_nrepeats() == 0)
	    cmd_set_repeat(99);
	
	more = do_cmd_disarm_aux(y, x);

	/* Cancel repeat unless we may continue */
	if (!more)
	    disturb(0, 0);
	return;
    }

    /* Some terrain is impassable for the player, such as stone walls. */
    else if (!cave_passable_bold(y, x)) {
	/* Disturb the player */
	disturb(0, 0);

	/* Notice unknown obstacles */
	if (!(cave_info[y][x] & (CAVE_MARK))) {
	    /* Closed door */
	    if (cave_feat[y][x] < FEAT_SECRET) {
		message(MSG_HITWALL, 0, "You feel a door blocking your way.");
		cave_info[y][x] |= (CAVE_MARK);
		light_spot(y, x);
	    }

	    /* Wall (or secret door) */
	    else {
		message(MSG_HITWALL, 0, "You feel a wall blocking your way.");
		cave_info[y][x] |= (CAVE_MARK);
		light_spot(y, x);
	    }
	}

	/* Mention known obstacles */
	else {
	    /* Closed door */
	    if (cave_feat[y][x] < FEAT_SECRET) {
		/* Option to automatically open doors. -TNB- */
		if (OPT(easy_alter)) {
		    bool more = FALSE;

		    /* Auto-repeat if not already repeating */
		    if (cmd_get_nrepeats() == 0)
			cmd_set_repeat(99);
		    
		    /* Open the door */
		    more = do_cmd_open_aux(y, x);
		    
		    /* Cancel repeat unless we may continue */
		    if (!more)
			disturb(0, 0);
		    return;
		}
		
		/* Otherwise, a message. */
		message(MSG_HITWALL, 0, "There is a door blocking your way.");
	    }

	    /* Wall (or secret door) */
	    else {
		message(MSG_HITWALL, 0, "There is a wall blocking your way.");
	    }
	}

	/* Sound */
	sound(MSG_HITWALL);
    }

    /* Normal movement */
    else 
    {
	/*** Handle traversable terrain.  ***/
	switch (cave_feat[y][x]) {
	case FEAT_RUBBLE:
	    {
		/* Dwarves move easily through rubble */
		if (player_has(PF_DWARVEN))
		    can_move = TRUE;

		/* Bats, dragons can fly */
		else if ((p_ptr->schange == SHAPE_BAT)
			 || (p_ptr->schange == SHAPE_WYRM))
		    can_move = TRUE;

		else if (player_is_crossing == dir)
		{
		    can_move = TRUE;
		    player_is_crossing = 0;
		}
		else 
		{
		    player_is_crossing = dir;
		    cmd_insert(CMD_WALK);
		}

		break;
	    }
	case FEAT_TREE:
	case FEAT_TREE2:
	    {
		/* Druids, rangers, elves and ents (SJGU) slip easily under
		 * trees */
		if (((player_has(PF_WOODSMAN)) || (player_has(PF_ELVEN)))
		    || (player_has(PF_WOODEN)))
		    can_move = TRUE;

		/* Bats, dragons can fly */
		else if ((p_ptr->schange == SHAPE_BAT)
			 || (p_ptr->schange == SHAPE_WYRM))
		    can_move = TRUE;

		/* Allow movement only if partway through already. */
		else if (player_is_crossing == dir)
		{
		    can_move = TRUE;
		    player_is_crossing = 0;
		}
		else 
		{
		    player_is_crossing = dir;
		    cmd_insert(CMD_WALK);
		}
		
		break;
	    }
	case FEAT_WATER:	/* Water now slows rather than stopping -NRM- */
	    {
		/* Stop any run. */
		disturb(0, 0);

		can_move = TRUE;

		/* Speed will need updating */
		p_ptr->update |= PU_BONUS;

		break;
	    }
	case FEAT_LAVA:
	    {
		/* Assume player will continue. */
		temp = TRUE;

		/* Smart enough to stop running. */
		if (p_ptr->running) {
		    if (!get_check("Lava blocks your path.  Step into it? ")) {
			temp = FALSE;
			p_ptr->running = 0;
		    }
		}

		/* Smart enough to sense trouble. */
		else if ((!p_resist_pos(P_RES_FIRE))
			 || (!p_resist_strong(P_RES_FIRE)
			     && (p_ptr->chp <= 100))
			 || (!p_immune(P_RES_FIRE) && (p_ptr->chp <= 30))) {
		    if (!get_check
			("The heat of the lava scalds you! Really enter? ")) {
			temp = FALSE;
		    }
		}

		/* Enter if OK or confirmed. */
		if (temp) {
		    /* Can always cross. */
		    can_move = TRUE;

		    /* Feather fall makes one lightfooted. */
		    if (p_ptr->state.ffall) {
			notice_obj(OF_FEATHER, 0);
			temp = 49 + randint1(51);
		    } else
			temp = 124 + randint1(126);

		    /* Will take serious fire damage. */
		    fire_dam(temp, "burnt to a cinder in molten lava");
		}
		break;
	    }
	case FEAT_VOID:
	    {
		/* Bats, dragons can fly */
		if ((p_ptr->schange == SHAPE_BAT)
		    || (p_ptr->schange == SHAPE_WYRM))
		    can_move = TRUE;
		else {
		    /* Assume player will continue. */
		    temp = TRUE;

		    /* Smart enough to stop running. */
		    if (p_ptr->running) {
			if (!get_check
			    ("You have come to a cliff.  Step off it? ")) {
			    temp = FALSE;
			    p_ptr->running = 0;
			}
		    }

		    /* Smart enough to sense trouble. */
		    else if (!p_ptr->timed[TMD_BLIND]) {
			if (!get_check("It's a cliff! Really step off it? ")) {
			    temp = FALSE;
			}
		    }

		    /* Step off if confirmed. */
		    if (temp) {
			/* Can always jump. */
			can_move = TRUE;

			/* Will take serious damage. */
			falling = TRUE;
		    }
		}
		break;
	    }
	default:
	    {
		/* All other terrain can be traversed normally. */
		can_move = TRUE;
	    }
	}

	/* If the player can move, handle various things. */
	if (can_move) {
	    /* Move player */
	    monster_swap(py, px, y, x);

	    /* Update speed if stepping out of water */
	    if (cave_feat[py][px] == FEAT_WATER)
		p_ptr->update |= PU_BONUS;

	    /* Update stealth for Unlight */
	    if (player_has(PF_UNLIGHT))
		p_ptr->update |= PU_BONUS;

	    /* Superstealth for ents in trees SJGU */
	    if ((player_has(PF_WOODEN))
		&&
		(tf_has
		 (f_info[cave_feat[p_ptr->py][p_ptr->px]].flags, TF_TREE))) {
		if (!(tf_has(f_info[cave_feat[py][px]].flags, TF_TREE))
		    || !(p_ptr->timed[TMD_SSTEALTH])) {
		    (void) inc_timed(TMD_SSTEALTH, 1, FALSE);
		    p_ptr->update |= (PU_BONUS);
		}
	    } else if ((player_has(PF_WOODEN))
		       && (tf_has(f_info[cave_feat[py][px]].flags, TF_TREE))) {
		if (p_ptr->timed[TMD_SSTEALTH]) {
		    (void) dec_timed(TMD_SSTEALTH, 1, FALSE);
		    p_ptr->update |= (PU_BONUS);
		}
	    }

	    /* New location */
	    y = py = p_ptr->py;
	    x = px = p_ptr->px;

	    /* No longer traversing. */
	    player_is_crossing = 0;

	    /* Fall off a cliff */
	    if (falling)
		fall_off_cliff();

	    /* Spontaneous Searching */
	    if (p_ptr->state.skills[SKILL_SEARCH_FREQUENCY] > 49) {
		(void) search(FALSE);
	    } else if (0 == randint0(50 - p_ptr->state.skills[SKILL_SEARCH_FREQUENCY])) 
	    {
		(void) search(FALSE);
	    }

	    /* Continuous Searching */
	    if (p_ptr->searching) {
		(void) search(FALSE);
	    }

	    /* Handle "store doors" */
	    if ((cave_feat[y][x] >= FEAT_SHOP_HEAD)
		&& (cave_feat[y][x] <= FEAT_SHOP_TAIL)) {
		/* Disturb */
		disturb(0, 0);
		cmd_insert(CMD_ENTER_STORE);
	    }

	    /* All other grids (including traps) */
	    else
	    {
		/* Handle objects (later) */
		p_ptr->notice |= (PN_PICKUP);
	    }

	    /* Flying players have a chance to miss traps */
	    if ((p_ptr->schange == SHAPE_BAT) || (p_ptr->schange == SHAPE_WYRM)) {
		if (((cave_feat[y][x] == FEAT_INVIS)
		     || (cave_feat[y][x] == FEAT_GRASS_INVIS))
		    && (randint0(3) != 0))
		    trapped = FALSE;
		else if ((cave_feat[y][x] >= FEAT_TRAP_HEAD)
			 && (cave_feat[y][x] <= FEAT_TRAP_TAIL)
			 && (randint0(10) != 0))
		    trapped = FALSE;
	    }

	    /* Discover invisible traps */
	    else if (((cave_feat[y][x] == FEAT_INVIS)
		      || (cave_feat[y][x] == FEAT_GRASS_INVIS)
		      || (cave_feat[y][x] == FEAT_TREE_INVIS)
		      || (cave_feat[y][x] == FEAT_TREE2_INVIS)) && trapped) {
		/* Disturb */
		disturb(0, 0);

		/* Message */
		msg_print("You stumble upon a trap!");

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

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

	    /* Set off a visible trap */
	    else if ((cave_feat[y][x] >= FEAT_TRAP_HEAD)
		     && (cave_feat[y][x] <= FEAT_TRAP_TAIL) && trapped) {
		/* Disturb */
		disturb(0, 0);

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

	    /* Walk on a monster trap */
	    else if ((cave_feat[y][x] >= FEAT_MTRAP_HEAD)
		     && (cave_feat[y][x] <= FEAT_MTRAP_TAIL)) {
		msg_print("You inspect your cunning trap.");
	    }
	}
    }
}
Exemplo n.º 7
0
/*
 * Open a closed/locked/jammed door or a closed/locked chest.
 *
 * Unlocking a locked door/chest is worth one experience point.
 */
void do_cmd_open(cmd_code code, cmd_arg args[])
{
	int y, x, dir;

	s16b o_idx;

	bool more = FALSE;

	dir = args[0].direction;

	/* Get location */
	y = p_ptr->py + ddy[dir];
	x = p_ptr->px + ddx[dir];

	/* Check for chests */
	o_idx = chest_check(y, x);


	/* Verify legality */
	if (!o_idx && !do_cmd_open_test(y, x))
	{
		/* Cancel repeat */
		disturb(p_ptr, 0, 0);
		return;
	}

	/* Take a turn */
	p_ptr->energy_use = 100;

	/* Apply confusion */
	if (player_confuse_dir(p_ptr, &dir, FALSE))
	{
		/* Get location */
		y = p_ptr->py + ddy[dir];
		x = p_ptr->px + ddx[dir];

		/* Check for chest */
		o_idx = chest_check(y, x);
	}


	/* Monster */
	if (cave->m_idx[y][x] > 0)
	{
		int m_idx = cave->m_idx[y][x];

		/* Mimics surprise the player */
		if (is_mimicking(m_idx)) {
			become_aware(m_idx);

			/* Mimic wakes up */
			mon_clear_timed(m_idx, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE);
		} else {
			/* Message */
			msg("There is a monster in the way!");

			/* Attack */
			py_attack(y, x);
		}
	}

	/* Chest */
	else if (o_idx)
	{
		/* Open the chest */
		more = do_cmd_open_chest(y, x, o_idx);
	}

	/* Door */
	else
	{
		/* Open the door */
		more = do_cmd_open_aux(y, x);
	}

	/* Cancel repeat unless we may continue */
	if (!more) disturb(p_ptr, 0, 0);
}
Exemplo n.º 8
0
/*
 * Manipulate an adjacent grid in some way
 *
 * Attack monsters, tunnel through walls, disarm traps, open doors,
 * or, for rogues, set traps and steal money.
 *
 * This command must always take energy, to prevent free detection
 * of invisible monsters.
 *
 * The "semantics" of this command must be chosen before the player
 * is confused, and it must be verified against the new grid.
 */
void do_cmd_alter(void)
{
	int py = p_ptr->py;
	int px = p_ptr->px;

	int y, x, dir;

	int feat;

	bool did_nothing = TRUE;
	bool more = FALSE;

	monster_type *m_ptr;

	/* Get a direction */
	if (!get_rep_dir(&dir)) return;

	/* Get location */
	y = py + ddy[dir];
	x = px + ddx[dir];


	/* Original feature */
	feat = cave_feat[y][x];

	/* Must have knowledge to know feature XXX XXX */
	if (!(cave_info[y][x] & (CAVE_MARK))) feat = FEAT_NONE;


	/* Take a turn */
	p_ptr->energy_use = 100;

	/* Apply confusion */
	if (confuse_dir(&dir))
	{
		/* Get location */
		y = py + ddy[dir];
		x = px + ddx[dir];
	}


	/* Allow repeated command */
	if (p_ptr->command_arg)
	{
		/* Set repeat count */
		p_ptr->command_rep = p_ptr->command_arg - 1;

		/* Redraw the state */
		p_ptr->redraw |= (PR_STATE);

		/* Cancel the arg */
		p_ptr->command_arg = 0;
	}

	/* If a monster is present, and visible, Rogues may steal from it.
	 * Otherwise, the player will simply attack. -LM-
	 */
	if (cave_m_idx[y][x] > 0)
	{
		if ((check_ability(SP_STEAL)) && (!SCHANGE))
		{
			m_ptr = &m_list[cave_m_idx[y][x]];
			if (m_ptr->ml) py_steal(y, x);
			else py_attack(y, x);
		}
		else py_attack(y, x);
		did_nothing = FALSE;
	}

	/*
	 * Some players can set traps.  Total number is checked in py_set_trap.
	 */
	else if ((check_ability(SP_TRAP)) && (cave_naked_bold(y, x)))
	{
		py_set_trap(y, x);
		did_nothing = FALSE;
	}

	/* Disarm advanced monster traps */
	else if (feat > FEAT_MTRAP_HEAD)
	{
		/* Disarm */
		more = do_cmd_disarm_aux(y, x);
	}

	/* Modify basic monster traps */
	else if (feat == FEAT_MTRAP_HEAD)
	{
		/* Modify */
		py_modify_trap(y, x);
	}

	/* Tunnel through walls */
	else if (feat >= FEAT_SECRET)
	{
		/* Tunnel */
		more = do_cmd_tunnel_aux(y, x);
	}

	/* Bash jammed doors */
	else if (feat >= FEAT_DOOR_HEAD + 0x08)
	{
		/* Bash */
		more = do_cmd_bash_aux(y, x);
	}

	/* Open closed doors */
	else if (feat >= FEAT_DOOR_HEAD)
	{
		/* Close */
		more = do_cmd_open_aux(y, x);
	}

	/* Disarm traps */
	else if (feat >= FEAT_TRAP_HEAD)
	{
		/* Disarm */
		more = do_cmd_disarm_aux(y, x);
	}

	/* Oops */
	else if (did_nothing)
	{
		/* Oops */
		msg_print("You spin around.");
	}

	/* Cancel repetition unless we can continue */
	if (!more) disturb(0, 0);
}
Exemplo n.º 9
0
/*
 * Open a closed/locked/jammed door or a closed/locked chest.
 *
 * Unlocking a locked door/chest is worth one experience point.
 */
void do_cmd_open(void)
{
	int py = p_ptr->py;
	int px = p_ptr->px;

	int y, x, dir;

	s16b o_idx;

	bool more = FALSE;

	/* Option: Pick a direction -TNB- */
	if (easy_open)
	{
		int num_doors, num_chests;

		/* Count closed doors */
		num_doors = count_feats(&y, &x, is_closed, FALSE);

		/* Count chests (locked) */
		num_chests = count_chests(&y, &x, FALSE);

		/* See if there's only one target */
		if ((num_doors + num_chests) == 1)
		{
			p_ptr->command_dir = coords_to_dir(y, x);
		}
	}

	/* Get a direction (or abort) */
	if (!get_rep_dir(&dir)) return;

	/* Get location */
	y = py + ddy[dir];
	x = px + ddx[dir];

	/* Check for chests */
	o_idx = chest_check(y, x);

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

	/* Take a turn */
	p_ptr->energy_use = 100;

	/* Apply confusion */
	if (confuse_dir(&dir))
	{
		/* Get location */
		y = py + ddy[dir];
		x = px + ddx[dir];

		/* Check for chest */
		o_idx = chest_check(y, x);
	}


	/* Allow repeated command */
	if (p_ptr->command_arg)
	{
		/* Set repeat count */
		p_ptr->command_rep = p_ptr->command_arg - 1;

		/* Redraw the state */
		p_ptr->redraw |= (PR_STATE);

		/* Cancel the arg */
		p_ptr->command_arg = 0;
	}

	/* Monster */
	if (cave_m_idx[y][x] > 0)
	{
		/* Message */
		msg_print("There is a monster in the way!");

		/* Attack */
		py_attack(y, x);
	}

	/* Chest */
	else if (o_idx)
	{
		/* Open the chest */
		more = do_cmd_open_chest(y, x, o_idx);
	}

	/* Door */
	else
	{
		/* Open the door */
		more = do_cmd_open_aux(y, x);
	}

	/* Cancel repeat unless we may continue */
	if (!more) disturb(0, 0);
}
Exemplo n.º 10
0
/**
 * Move player in the given direction, with the given "pickup" flag.
 *
 * This routine should only be called when energy has been expended.
 *
 * Note that this routine handles monsters in the destination grid,
 * and also handles attempting to move into walls/doors/etc.
 */
void move_player(int dir, bool no_options)
{
	unsigned int py = p_ptr->py;
	unsigned int px = p_ptr->px;

	byte str_escape, dex_escape;

	/* Permit the player to move? */
	bool can_move = FALSE;

	/* Player is jumping off a cliff */
	bool falling = FALSE;

	/* Player hits a trap (always unless flying) */
	bool trapped = TRUE;
	
	/* Sliding on the ice */
	bool icy_slide = FALSE;

	int temp;
	unsigned int y, x;

	feature_type *f_ptr;

	/* Find the result of moving */
	y = py + ddy[dir];
	x = px + ddx[dir];
	f_ptr = &f_info[cave_feat[y][x]];


	/* Hack -- attack monsters */
	if (cave_m_idx[y][x] > 0) {
		/* Attack */
		if (py_attack(y, x, TRUE))
			return;
	}

	/* It takes some dexterity, or failing that strength, to get out of pits */
	if (cave_feat[py][px] == FEAT_PIT) {
		str_escape = adj_dex_dis[p_ptr->state.stat_ind[A_STR]];
		dex_escape = adj_dex_dis[p_ptr->state.stat_ind[A_DEX]];

		/* First attempt to leap out of the pit, */
		if ((dex_escape + 1) * 2 < randint1(16)) {
			/* then attempt to climb out of the pit. */
			if (str_escape + 3 < randint1(16)) {
				/* Failure costs a turn. */
				msg("You remain stuck in the pit.");
				/* Failure clears movement */
				p_ptr->previous_action[0] = ACTION_NOTHING;
				return;
			} else
				msg("You clamber out of the pit.");
		} else
			msg("You leap out of the pit.");
	}


	/* Rooted players cannot move */
	if (p_ptr->timed[TMD_ROOT])
	{
		can_move = FALSE;
		msg("You are rooted to the ground and can't move.");
		
		/* Prevent repeated attempts */
		disturb(0, 0);
		
		return;
	}
	
	/* Option to disarm a visible trap. -TNB- */
	/* Hack - Rogues can walk over their own trap - BR */
	else if (cave_visible_trap(y, x) && cave_player_trap(y, x)
			&& OPT(easy_alter)) {
		bool more = FALSE;
		/* Auto-repeat if not already repeating */
		if (cmd_get_nrepeats() == 0)
			cmd_set_repeat(99);

		more = do_cmd_disarm_aux(y, x);

		/* Cancel repeat unless we may continue */
		if (!more)
			disturb(0, 0);
		return;
	}

	/* Some terrain is impassable for the player, such as stone walls. */
	else if (!tf_has(f_ptr->flags, TF_PASSABLE)) {
		/* Disturb the player */
		disturb(0, 0);

		/* Notice unknown obstacles */
		if (!sqinfo_has(cave_info[y][x], SQUARE_MARK)) {
			/* Closed door */
			if (tf_has(f_ptr->flags, TF_DOOR_CLOSED)) {
				msgt(MSG_HITWALL, "You feel a door blocking your way.");
				sqinfo_on(cave_info[y][x], SQUARE_MARK);
				light_spot(y, x);
			}

			/* Wall (or secret door) */
			else {
				msgt(MSG_HITWALL, "You feel a wall blocking your way.");
				sqinfo_on(cave_info[y][x], SQUARE_MARK);
				light_spot(y, x);
			}
		}

		/* Mention known obstacles */
		else {
			/* Closed door */
			if (tf_has(f_ptr->flags, TF_DOOR_CLOSED)) {
				/* Option to automatically open doors. -TNB- */
				if (OPT(easy_alter)) {
					bool more = FALSE;

					/* Auto-repeat if not already repeating */
					if (cmd_get_nrepeats() == 0)
						cmd_set_repeat(99);

					/* Open the door */
					more = do_cmd_open_aux(y, x);

					/* Cancel repeat unless we may continue */
					if (!more)
						disturb(0, 0);
					/* Clear action list */
					p_ptr->previous_action[0] = ACTION_NOTHING;
                    return;
				}

				/* Otherwise, a message. */
				msgt(MSG_HITWALL, "There is a door blocking your way.");
			}

			/* Wall (or secret door) */
			else {
				msgt(MSG_HITWALL, "There is a wall blocking your way.");
			}
		}

		/* Sound */
		sound(MSG_HITWALL);
	}

	/* Normal movement */
	else {
		/* Assume terrain can be traversed normally. */
		can_move = TRUE;

		/* Terrain blocked by a friendly monster */
		if (cave_m_idx[y][x] > 0)
		{
		    monster_type *n_ptr = & m_list[cave_m_idx[y][x]];
		    
		    /* Push monster if it doesn't have a target and hasn't been pushed.
			 * This allows the player to move into a corridor with a monster in
			 * front of him, and have the monster move ahead, if it is faster. If its
			 * not faster, the player will push over it on the second move, as the push
			 * flag below will have been set. */
			 if(((n_ptr->mflag & MFLAG_PUSH) == 0) && !(n_ptr->ty) && !(n_ptr->tx) && push_aside_player(p_ptr->py, p_ptr->px, n_ptr))
			 {
			     int dy = n_ptr->fy - y;
			     int dx = n_ptr->fx - x;
			     unsigned int count = 0;
			     
			     n_ptr->ty = n_ptr->fy;
			     n_ptr->tx = n_ptr->fx;
			     
			     /* Hack -- get new target as far as the monster can move in the direction
				 * pushed. We do this with a walking stick approach to prevent us getting
				 * invalid target locations like (0,0) */
				while (in_bounds_fully(n_ptr->ty + dy, n_ptr->tx + dx)
						&& cave_exist_mon(&r_info[n_ptr->r_idx], n_ptr->ty + dy, n_ptr->tx + dx, TRUE)
						&& (count++ < (MAX_SIGHT / 2)))
				{
					n_ptr->ty = n_ptr->ty + dy;
					n_ptr->tx = n_ptr->tx + dx;
				}

				/* Clear target if none available */
				if ((n_ptr->ty == n_ptr->fy) && (n_ptr->tx == n_ptr->fx))
				{
					n_ptr->ty = 0;
					n_ptr->tx = 0;
				}
			}

			/* The other monster cannot switch places */
			else if (!cave_exist_mon(&r_info[n_ptr->r_idx], p_ptr->py, p_ptr->px, TRUE))
			{
				/* Try to push it aside. Allow aborting of move if an ally */
				if ((!push_aside_player(p_ptr->py, p_ptr->px, n_ptr)) && (get_reaction(F_PLAYER, n_ptr->faction) <= REACT_FRIEND))
				{
					/* No warning if sliding */
					if (no_options)	{}
					/* Don't provide more warning */
					else if (!get_check("Are you sure?")) 
					{
					    temp = FALSE;
					    p_ptr->running = 0;
					    can_move = FALSE;
					}
				}
			}

			/* Hack -- we clear the target if we move over a monster */
			else
			{
				n_ptr->ty = 0;
				n_ptr->tx = 0;
			}

			/* Mark monsters as pushed */
			n_ptr->mflag |= (MFLAG_PUSH);
		}
        
        /*** Handle traversable terrain.  ***/
		if (tf_has(f_ptr->flags, TF_ROCK)) {
			/* Dwarves move easily through rubble */
			if (player_has(PF_DWARVEN))
				can_move = TRUE;

			/* Bats, dragons can fly */
			else if ((p_ptr->schange == SHAPE_BAT)
					 || (p_ptr->schange == SHAPE_WYRM))
				can_move = TRUE;

			/* Require more energy */
			else {
				can_move = TRUE;
				p_ptr->energy_use += 100;
			}
		}

		if (tf_has(f_ptr->flags, TF_TREE)) {
			/* Druids, rangers, Plant Cutie Marks slip easily under
			 * trees */
			if ((player_has(PF_WOODSMAN)) || (player_has(PF_PLANT_FRIEND)))
				can_move = TRUE;

			/* Bats, dragons can fly */
			else if ((p_ptr->schange == SHAPE_BAT)
					 || (p_ptr->schange == SHAPE_WYRM))
				can_move = TRUE;

			/* Require more energy */
			else {
				can_move = TRUE;
				p_ptr->energy_use += 100;
			}
		}

		/* Water now slows rather than stopping -NRM- */
		if (tf_has(f_ptr->flags, TF_WATERY)) {
			/* Stop any run. */
			disturb(0, 0);

			can_move = TRUE;

			/* Speed will need updating */
			p_ptr->update |= PU_BONUS;
		}
		
		/* Walking on to ice can cause you to slide an additional square. */
		if (tf_has(f_ptr->flags, TF_ICY)) {
			/* Stop any run */
			disturb(0, 0);
			
			can_move = TRUE;
			
			/* Slide is less likely with Cold Resist. Never slide with Levitation */
			if (!p_ptr->state.ffall && ((!p_immune(P_RES_COLD)) && (randint1((p_resist_pos(P_RES_COLD) || p_resist_strong(P_RES_COLD)) ? 2 : 4) != 1)))
			    icy_slide = TRUE;
			
			/* Speed will need updating */
			p_ptr->update |= PU_BONUS;
		}

		if (tf_has(f_ptr->flags, TF_FIERY)) {
			/* Assume player will continue. */
			temp = TRUE;

			/* Smart enough to stop running. */
			if (p_ptr->running) {
				/* Ice keeps sliding */
				if (no_options) {}
				else if (!get_check("Lava blocks your path.  Step into it? ")) {
					temp = FALSE;
					p_ptr->running = 0;
				}
			}

			/* Smart enough to sense trouble. */
			else if ((!p_resist_pos(P_RES_FIRE))
					 || (!p_resist_strong(P_RES_FIRE)
						 && (p_ptr->chp <= 100))
					 || (!p_immune(P_RES_FIRE) && (p_ptr->chp <= 30))) {
				/* Sliding continues regardless */
				if (no_options) {}
				else if (!get_check
					("The heat of the lava scalds you! Really enter? ")) {
					temp = FALSE;
				}
			}

			/* Enter if OK or confirmed. */
			if (temp) {
				/* Can always cross. */
				can_move = TRUE;

				/* Feather fall makes one lightfooted. */
				if (p_ptr->state.ffall) {
					notice_obj(OF_FEATHER, 0);
					temp = 49 + randint1(51);
				} else
					temp = 124 + randint1(126);

				/* Will take serious fire damage. */
				fire_dam(temp, "burnt to a cinder in molten lava", SOURCE_ENVIRONMENTAL);
			}
			else
				/* Player refuse to go. */
				can_move = FALSE;
		}
		
		if (tf_has(f_ptr->flags, TF_BURNING))
		{
            /* Assume player will continue */
            temp = TRUE;
            
            /* Smart enough to stop running */
            if (p_ptr->running)
            {
            	if (no_options) {}
				else if (!get_check("Your path is block by a burning tree. Step into it? "))
            	{
            		temp = FALSE;
            		p_ptr->running = 9;
            	}
            }
            
            /* Smart enough to sense trouble */
            else if ((!p_resist_pos(P_RES_FIRE))
					 || (!p_resist_strong(P_RES_FIRE)
						 && (p_ptr->chp <= 100))
					 || (!p_immune(P_RES_FIRE) && (p_ptr->chp <= 30))) {
				if (no_options) {}
				else if (!get_check
					("The heat of the fire burns you! Really enter? ")) {
					temp = FALSE;
				}
			}

			/* Enter if OK or confirmed. */
			if (temp) {
				/* Can always cross. */
				can_move = TRUE;

				/* Take light damage from the fire */
				temp = 49 + randint1(51);

				/* Will take serious fire damage. */
				fire_dam(temp, "burnt to death in a fire.", SOURCE_ENVIRONMENTAL);
			}
			else
				/* Player refuse to go. */
				can_move = FALSE;
		}

		if (tf_has(f_ptr->flags, TF_FALL)) {
			/* Bats, dragons can fly */
			if (!(p_ptr->schange == SHAPE_BAT) &&
				!(p_ptr->schange == SHAPE_WYRM)) {
				/* Assume player will continue. */
				temp = TRUE;

				/* Smart enough to stop running. */
				if (p_ptr->running) {
					if (no_options) {}
					else if (!get_check
						("You have come to a cliff.  Step off it? ")) {
						can_move = FALSE;
						temp = FALSE;
						p_ptr->running = 0;
					}
				}

				/* Smart enough to sense trouble. */
				else if (!p_ptr->timed[TMD_BLIND]) {
					if (no_options) {}
					else if (!get_check("It's a cliff! Really step off it? ")) {
						can_move = FALSE;
						temp = FALSE;
					}
				}

				/* Step off if confirmed. */
				if (temp) {
					/* Will take serious damage. */
					falling = TRUE;
				}
			}
		}
	}

	/* If the player can move, handle various things. */
	if (can_move) {
		/* Move player */
		monster_swap(py, px, y, x);

		/* Update speed if stepping out of water */
		if (tf_has(f_info[cave_feat[py][px]].flags, TF_WATERY))
			p_ptr->update |= PU_BONUS;

		/* Update stealth for Unlight */
		if (player_has(PF_UNLIGHT))
			p_ptr->update |= PU_BONUS;

		/* Update speed for Plant cutie mark woodspersons */
		if (player_has(PF_WOODSMAN) && player_has(PF_PLANT_FRIEND))
			p_ptr->update |= PU_BONUS;

		/* New location */
		y = py = p_ptr->py;
		x = px = p_ptr->px;
		f_ptr = &f_info[cave_feat[y][x]];
		    

		/* Fall off a cliff */
		if (falling)
			fall_off_cliff();
			
		
        /* Sliding on ice prevents searching */
        if (!icy_slide)
        {
			/* Spontaneous Searching */
			if (p_ptr->state.skills[SKILL_SEARCH_FREQUENCY] > 49) {
				(void) search(FALSE);
			} else if (0 ==
					   randint0(50 -
								p_ptr->state.skills[SKILL_SEARCH_FREQUENCY])) {
				(void) search(FALSE);
			}
	
			/* Continuous Searching */
			if (p_ptr->searching) {
				(void) search(FALSE);
			}
		}

		/* Handle "store doors" */
		if (tf_has(f_ptr->flags, TF_SHOP)) {
			/* Disturb */
			disturb(0, 0);
			cmd_insert(CMD_ENTER_STORE);
		}

		/* All other grids (including traps) */
		else {
			/* Handle objects (later) */
			p_ptr->notice |= (PN_PICKUP);
		}

		/* Flying players have a chance to miss traps */
		if ((p_ptr->schange == SHAPE_BAT)
			|| (p_ptr->schange == SHAPE_WYRM)) {
			if (cave_invisible_trap(y, x) && cave_player_trap(y, x)
				&& (randint0(3) != 0))
				trapped = FALSE;
			else if (cave_visible_trap(y, x) && cave_player_trap(y, x) &&
					 (randint0(10) != 0))
				trapped = FALSE;
		}

		/* Discover invisible traps */
		if (cave_invisible_trap(y, x) && trapped) {
			/* Disturb */
			disturb(0, 0);

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

		/* Set off a visible trap */
		else if (cave_visible_trap(y, x) && cave_player_trap(y, x) &&
				 trapped) {
			/* Disturb */
			disturb(0, 0);

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

		/* Walk on a monster trap */
		else if (cave_monster_trap(y, x)) {
			msg("You inspect your cunning trap.");
		}
		
		/* Slide an additional square on the ice */
		if (icy_slide)
		    move_player(dir, TRUE);
	}
}