Esempio n. 1
0
/* Make doors */
static void project_feature_handler_MAKE_DOOR(project_feature_handler_context_t *context)
{
	const int x = context->x;
	const int y = context->y;

	/* Require a grid without monsters */
	if (square_monster(cave, y, x)) return;

	/* Require a floor grid */
	if (!square_isfloor(cave, y, x)) return;

	/* Push objects off the grid */
	if (square_object(cave, y, x))
		push_object(y,x);

	/* Create closed door */
	square_add_door(cave, y, x, true);

	/* Observe */
	if (square_isknown(cave, y, x))
		context->obvious = true;

	/* Update the visuals */
	player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);
}
Esempio n. 2
0
static bool is_valid_pf(int y, int x)
{
	/* Unvisited means allowed */
	if (!square_isknown(cave, y, x)) return (true);

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

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

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

			/* Nope */
			return (false);
		}

		return (true);
	}

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

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

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

		/* Nope */
		return (false);
	}

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

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

	return (true);
}
Esempio n. 5
0
/**
 * Hack -- Check for a "known wall" (see below)
 */
static int see_wall(int dir, int y, int x)
{
	/* Get the new location */
	y += ddy[dir];
	x += ddx[dir];

	/* Illegal grids are not known walls XXX XXX XXX */
	if (!square_in_bounds(cave, y, x)) return (false);

	/* Non-wall grids are not known walls */
	if (!square_seemslikewall(cave, y, x))
		return false;

	/* Unknown walls are not known walls */
	if (!square_isknown(cave, y, x)) return (false);

	/* Default */
	return (true);
}
Esempio n. 6
0
/**
 * Memorize interesting viewable object/features in the given grid
 *
 * This function should only be called on "legal" grids.
 *
 * This function will memorize the object and/or feature in the given grid,
 * if they are (1) see-able and (2) interesting.  Note that all objects are
 * interesting, all terrain features except floors (and invisible traps) are
 * interesting, and floors (and invisible traps) are interesting sometimes
 * (depending on various options involving the illumination of floor grids).
 *
 * The automatic memorization of all objects and non-floor terrain features
 * as soon as they are displayed allows incredible amounts of optimization
 * in various places, especially "map_info()" and this function itself.
 *
 * Note that the memorization of objects is completely separate from the
 * memorization of terrain features, preventing annoying floor memorization
 * when a detected object is picked up from a dark floor, and object
 * memorization when an object is dropped into a floor grid which is
 * memorized but out-of-sight.
 *
 * This function should be called every time the "memorization" of a grid
 * (or the object in a grid) is called into question, such as when an object
 * is created in a grid, when a terrain feature "changes" from "floor" to
 * "non-floor", and when any grid becomes "see-able" for any reason.
 *
 * This function is called primarily from the "update_view()" function, for
 * each grid which becomes newly "see-able".
 */
void square_note_spot(struct chunk *c, int y, int x)
{
	/* Require "seen" flag and the current level */
	if (c != cave) return;
	if (!square_isseen(c, y, x)) return;

	/* Make the player know precisely what is on this grid */
	square_know_pile(c, y, x);

	/* Notice traps */
	if (square_issecrettrap(c, y, x)) {
		square_reveal_trap(c, y, x, false, true);
	}

	if (square_isknown(c, y, x))
		return;

	/* Memorize this grid */
	square_memorize(c, y, x);
}
Esempio n. 7
0
/**
 * Determine if a given grid may be "disarmed"
 */
static bool do_cmd_disarm_test(int y, int x)
{
	/* Must have knowledge */
	if (!square_isknown(cave, y, x)) {
		msg("You see nothing there.");
		return false;
	}

	/* Look for a closed, unlocked door to lock */
	if (square_iscloseddoor(cave, y, x) && !square_islockeddoor(cave, y, x))
		return true;

	/* Look for a trap */
	if (!square_isknowntrap(cave, y, x)) {
		msg("You see nothing there to disarm.");
		return false;
	}

	/* Okay */
	return true;
}
Esempio n. 8
0
/**
 * Return the number of doors/traps around (or under) the character.
 */
int count_feats(int *y, int *x, bool (*test)(struct chunk *c, int y, int x), bool under)
{
	int d;
	int xx, yy;
	int count = 0; /* Count how many matches */

	/* Check around (and under) the character */
	for (d = 0; d < 9; d++)
	{
		/* if not searching under player continue */
		if ((d == 8) && !under) continue;

		/* Extract adjacent (legal) location */
		yy = player->py + ddy_ddd[d];
		xx = player->px + ddx_ddd[d];

		/* Paranoia */
		if (!square_in_bounds_fully(cave, yy, xx)) continue;

		/* Must have knowledge */
		if (!square_isknown(cave, yy, xx)) continue;

		/* Not looking for this feature */
		if (!((*test)(cave, yy, xx))) continue;

		/* Count it */
		++count;

		/* Remember the location of the last door found */
		if (x && y) {
			*y = yy;
			*x = xx;
		}
	}

	/* All done */
	return count;
}
Esempio n. 9
0
/**
 * Determine if a given location is "interesting"
 */
bool target_accept(int y, int x)
{
	struct loc grid = loc(x, y);
	struct object *obj;

	/* Player grids are always interesting */
	if (square(cave, grid).mon < 0) return true;

	/* Handle hallucination */
	if (player->timed[TMD_IMAGE]) return false;

	/* Obvious monsters */
	if (square(cave, grid).mon > 0) {
		struct monster *mon = square_monster(cave, grid);
		if (monster_is_obvious(mon)) {
			return true;
		}
	}

	/* Traps */
	if (square_isvisibletrap(cave, grid)) return true;

	/* Scan all objects in the grid */
	for (obj = square_object(player->cave, grid); obj; obj = obj->next) {
		/* Memorized object */
		if ((obj->kind == unknown_item_kind) || !ignore_known_item_ok(obj)) {
			return true;
		}
	}

	/* Interesting memorized features */
	if (square_isknown(cave, grid) && square_isinteresting(cave, grid)) {
		return true;
	}

	/* Nope */
	return false;
}
Esempio n. 10
0
/**
 * Determine if a given grid may be "tunneled"
 */
static bool do_cmd_tunnel_test(int y, int x)
{
	/* Must have knowledge */
	if (!square_isknown(cave, y, x)) {
		msg("You see nothing there.");
		return (false);
	}

	/* Titanium */
	if (square_isperm(cave, y, x)) {
		msg("This seems to be permanent rock.");
		return (false);
	}

	/* Must be a wall/door/etc */
	if (!(square_isdiggable(cave, y, x) || square_iscloseddoor(cave, y, x))) {
		msg("You see nothing there to tunnel.");
		return (false);
	}

	/* Okay */
	return (true);
}
Esempio n. 11
0
/**
 * Determine if a given grid may be "closed"
 */
static bool do_cmd_close_test(int y, int x)
{
	/* Must have knowledge */
	if (!square_isknown(cave, y, x)) {
		/* Message */
		msg("You see nothing there.");

		/* Nope */
		return (false);
	}

 	/* Require open/broken door */
	if (!square_isopendoor(cave, y, x) && !square_isbrokendoor(cave, y, x)) {
		/* Message */
		msg("You see nothing there to close.");

		/* Nope */
		return (false);
	}

	/* Okay */
	return (true);
}
Esempio n. 12
0
/**
 * Determine if a given location is "interesting"
 */
bool target_accept(int y, int x)
{
	struct object *obj;

	/* Player grids are always interesting */
	if (cave->squares[y][x].mon < 0) return (true);

	/* Handle hallucination */
	if (player->timed[TMD_IMAGE]) return (false);

	/* Visible monsters */
	if (cave->squares[y][x].mon > 0) {
		struct monster *mon = square_monster(cave, y, x);

		/* Visible monsters */
		if (mflag_has(mon->mflag, MFLAG_VISIBLE) &&
			!mflag_has(mon->mflag, MFLAG_UNAWARE))
			return (true);
	}

	/* Traps */
	if (square_isvisibletrap(cave, y, x))
		return(true);

	/* Scan all objects in the grid */
	for (obj = square_object(cave_k, y, x); obj; obj = obj->next)
		/* Memorized object */
		if (!ignore_known_item_ok(obj)) return (true);

	/* Interesting memorized features */
	if (square_isknown(cave, y, x) && square_isinteresting(cave, y, x))
		return (true);

	/* Nope */
	return (false);
}
Esempio n. 13
0
/**
 * This function takes a grid location (x, y) and extracts information the
 * player is allowed to know about it, filling in the grid_data structure
 * passed in 'g'.
 *
 * The information filled in is as follows:
 *  - g->f_idx is filled in with the terrain's feature type, or FEAT_NONE
 *    if the player doesn't know anything about the grid.  The function
 *    makes use of the "mimic" field in terrain in order to allow one
 *    feature to look like another (hiding secret doors, invisible traps,
 *    etc).  This will return the terrain type the player "Knows" about,
 *    not necessarily the real terrain.
 *  - g->m_idx is set to the monster index, or 0 if there is none (or the
 *    player doesn't know it).
 *  - g->first_kind is set to the object_kind of the first object in a grid
 *    that the player knows about, or NULL for no objects.
 *  - g->muliple_objects is true if there is more than one object in the
 *    grid that the player knows and cares about (to facilitate any special
 *    floor stack symbol that might be used).
 *  - g->in_view is true if the player can currently see the grid - this can
 *    be used to indicate field-of-view, such as through the 
 *    OPT(player, view_bright_light) option.
 *  - g->lighting is set to indicate the lighting level for the grid:
 *    LIGHTING_DARK for unlit grids, LIGHTING_LIT for inherently light
 *    grids (lit rooms, etc), LIGHTING_TORCH for grids lit by the player's
 *    light source, and LIGHTING_LOS for grids in the player's line of sight.
 *    Note that lighting is always LIGHTING_LIT for known "interesting" grids
 *    like walls.
 *  - g->is_player is true if the player is on the given grid.
 *  - g->hallucinate is true if the player is hallucinating something "strange"
 *    for this grid - this should pick a random monster to show if the m_idx
 *    is non-zero, and a random object if first_kind is non-zero.
 * 
 * NOTES:
 * This is called pretty frequently, whenever a grid on the map display
 * needs updating, so don't overcomplicate it.
 *
 * Terrain is remembered separately from objects and monsters, so can be
 * shown even when the player can't "see" it.  This leads to things like
 * doors out of the player's view still change from closed to open and so on.
 *
 * TODO:
 * Hallucination is currently disabled (it was a display-level hack before,
 * and we need it to be a knowledge-level hack).  The idea is that objects
 * may turn into different objects, monsters into different monsters, and
 * terrain may be objects, monsters, or stay the same.
 */
void map_info(unsigned y, unsigned x, struct grid_data *g)
{
	struct object *obj;

	assert(x < (unsigned) cave->width);
	assert(y < (unsigned) cave->height);

	/* Default "clear" values, others will be set later where appropriate. */
	g->first_kind = NULL;
	g->trap = NULL;
	g->multiple_objects = false;
	g->lighting = LIGHTING_DARK;
	g->unseen_object = false;
	g->unseen_money = false;

	/* Use real feature (remove later) */
	g->f_idx = cave->squares[y][x].feat;
	if (f_info[g->f_idx].mimic)
		g->f_idx = lookup_feat(f_info[g->f_idx].mimic);

	g->in_view = (square_isseen(cave, y, x)) ? true : false;
	g->is_player = (cave->squares[y][x].mon < 0) ? true : false;
	g->m_idx = (g->is_player) ? 0 : cave->squares[y][x].mon;
	g->hallucinate = player->timed[TMD_IMAGE] ? true : false;

	if (g->in_view) {
		g->lighting = LIGHTING_LOS;

		if (!square_isglow(cave, y, x) && OPT(player, view_yellow_light))
			g->lighting = LIGHTING_TORCH;

		/* Remember seen feature */
		square_memorize(cave, y, x);
	} else if (!square_isknown(cave, y, x)) {
		g->f_idx = FEAT_NONE;
	} else if (square_isglow(cave, y, x)) {
		g->lighting = LIGHTING_LIT;
	}

	/* Use known feature */
	g->f_idx = player->cave->squares[y][x].feat;
	if (f_info[g->f_idx].mimic)
		g->f_idx = lookup_feat(f_info[g->f_idx].mimic);

    /* There is a trap in this square */
    if (square_istrap(cave, y, x) && square_isknown(cave, y, x)) {
		struct trap *trap = cave->squares[y][x].trap;

		/* Scan the square trap list */
		while (trap) {
			if (trf_has(trap->flags, TRF_TRAP) ||
				trf_has(trap->flags, TRF_RUNE)) {
				/* Accept the trap - only if not disabled, maybe we need
				 * a special graphic for this */
				if (!trap->timeout) {
					g->trap = trap;
					break;
				}
			}
			trap = trap->next;
		}
    }

	/* Objects */
	for (obj = square_object(player->cave, y, x); obj; obj = obj->next) {
		if (obj->kind == unknown_gold_kind) {
			g->unseen_money = true;
		} else if (obj->kind == unknown_item_kind) {
			g->unseen_object = true;
		} else if (ignore_known_item_ok(obj)) {
			/* Item stays hidden */
		} else if (!g->first_kind) {
			g->first_kind = obj->kind;
		} else {
			g->multiple_objects = true;
			break;
		}
	}

	/* Monsters */
	if (g->m_idx > 0) {
		/* If the monster isn't "visible", make sure we don't list it.*/
		struct monster *mon = cave_monster(cave, g->m_idx);
		if (!monster_is_visible(mon)) g->m_idx = 0;
	}

	/* Rare random hallucination on non-outer walls */
	if (g->hallucinate && g->m_idx == 0 && g->first_kind == 0) {
		if (one_in_(128) && (int) g->f_idx != FEAT_PERM)
			g->m_idx = 1;
		else if (one_in_(128) && (int) g->f_idx != FEAT_PERM)
			/* if hallucinating, we just need first_kind to not be NULL */
			g->first_kind = k_info;
		else
			g->hallucinate = false;
	}

	assert((int) g->f_idx <= FEAT_PASS_RUBBLE);
	if (!g->hallucinate)
		assert((int)g->m_idx < cave->mon_max);
	/* All other g fields are 'flags', mostly booleans. */
}
Esempio n. 14
0
/**
 * Take one step along the current "run" path
 *
 * Called with a real direction to begin a new run, and with zero
 * to continue a run in progress.
 */
void run_step(int dir)
{
	/* Start or continue run */
	if (dir) {
		/* Initialize */
		run_init(dir);

		/* Hack -- Set the run counter */
		player->upkeep->running = 1000;

		/* Calculate torch radius */
		player->upkeep->update |= (PU_TORCH);
	} else {
		/* Continue running */
		if (!player->upkeep->running_withpathfind) {
			/* Update regular running */
			if (run_test()) {
				/* Disturb */
				disturb(player, 0);
				return;
			}
		} else if (pf_result_index < 0) {
			/* Pathfinding, and the path is finished */
			disturb(player, 0);
			player->upkeep->running_withpathfind = false;
			return;
		} else {
			int y = player->py + ddy[pf_result[pf_result_index] - '0'];
			int x = player->px + ddx[pf_result[pf_result_index] - '0'];

			if (pf_result_index == 0) {
				/* Known wall */
				if (square_isknown(cave, y, x) &&
					!square_ispassable(cave, y, x)) {
					disturb(player, 0);
					player->upkeep->running_withpathfind = false;
					return;
				}
			} else if (pf_result_index > 0) {
				struct object *obj;

				/* If the player has computed a path that is going to end up
				 * in a wall, we notice this and convert to a normal run. This
				 * allows us to click on unknown areas to explore the map.
				 *
				 * We have to look ahead two, otherwise we don't know which is
				 * the last direction moved and don't initialise the run
				 * properly. */
				y = player->py + ddy[pf_result[pf_result_index] - '0'];
				x = player->px + ddx[pf_result[pf_result_index] - '0'];

				/* Known wall */
				if (square_isknown(cave, y, x) &&
					!square_ispassable(cave, y, x)) {
					disturb(player, 0);
					player->upkeep->running_withpathfind = false;
					return;
				}

				/* Visible monsters abort running */
				if (cave->squares[y][x].mon > 0) {
					struct monster *mon = square_monster(cave, y, x);

					/* Visible monster */
					if (mflag_has(mon->mflag, MFLAG_VISIBLE)) {
						disturb(player, 0);
						player->upkeep->running_withpathfind = false;
						return;
					}
				}

				/* Visible objects abort running */
				for (obj = square_object(cave, y, x); obj; obj = obj->next)
					/* Visible object */
					if (obj->known && !ignore_item_ok(obj)) {
					disturb(player, 0);
					player->upkeep->running_withpathfind = false;
					return;
				}

				/* Get step after */
				y = y + ddy[pf_result[pf_result_index - 1] - '0'];
				x = x + ddx[pf_result[pf_result_index - 1] - '0'];

				/* Known wall, so run the direction we were going */
				if (square_isknown(cave, y, x) &&
					!square_ispassable(cave, y, x)) {
					player->upkeep->running_withpathfind = false;
					run_init(pf_result[pf_result_index] - '0');
				}
			}

			/* Now actually run the step if we're still going */
			run_cur_dir = pf_result[pf_result_index--] - '0';
		}
	}

	/* Decrease counter if it hasn't been cancelled */
	if (player->upkeep->running)
		player->upkeep->running--;
	else if (!player->upkeep->running_withpathfind)
		return;

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

	/* Move the player; running straight into a trap == trying to disarm */
	move_player(run_cur_dir, dir ? true : false);

	/* Prepare the next step */
	if (player->upkeep->running) {
		cmdq_push(CMD_RUN);
		cmd_set_arg_direction(cmdq_peek(), "direction", 0);
	}
}
Esempio n. 15
0
/**
 * Update the current "run" path
 *
 * Return true if the running should be stopped
 */
static bool run_test(void)
{
	int py = player->py;
	int px = player->px;

	int prev_dir;
	int new_dir;

	int row, col;
	int i, max, inv;
	int option, option2;


	/* No options yet */
	option = 0;
	option2 = 0;

	/* Where we came from */
	prev_dir = run_old_dir;


	/* Range of newly adjacent grids */
	max = (prev_dir & 0x01) + 1;


	/* Look at every newly adjacent square. */
	for (i = -max; i <= max; i++) {
		struct object *obj;

		/* New direction */
		new_dir = cycle[chome[prev_dir] + i];

		/* New location */
		row = py + ddy[new_dir];
		col = px + ddx[new_dir];


		/* Visible monsters abort running */
		if (cave->squares[row][col].mon > 0) {
			struct monster *mon = square_monster(cave, row, col);

			/* Visible monster */
			if (mflag_has(mon->mflag, MFLAG_VISIBLE)) return (true);
		}

		/* Visible objects abort running */
		for (obj = square_object(cave, row, col); obj; obj = obj->next)
			/* Visible object */
			if (obj->known && !ignore_item_ok(obj)) return (true);

		/* Assume unknown */
		inv = true;

		/* Check memorized grids */
		if (square_isknown(cave, row, col)) {
			bool notice = square_isinteresting(cave, row, col);

			/* Interesting feature */
			if (notice) return (true);

			/* The grid is "visible" */
			inv = false;
		}

		/* Analyze unknown grids and floors */
		if (inv || square_ispassable(cave, row, col)) {
			/* Looking for open area */
			if (run_open_area) {
				/* Nothing */
			} else if (!option) {
				/* The first new direction. */
				option = new_dir;
			} else if (option2) {
				/* Three new directions. Stop running. */
				return (true);
			} else if (option != cycle[chome[prev_dir] + i - 1]) {
				/* Two non-adjacent new directions.  Stop running. */
				return (true);
			} else if (new_dir & 0x01) {
				/* Two new (adjacent) directions (case 1) */
				option2 = new_dir;
			} else {
				/* Two new (adjacent) directions (case 2) */
				option2 = option;
				option = new_dir;
			}
		} else { /* Obstacle, while looking for open area */
			if (run_open_area) {
				if (i < 0) {
					/* Break to the right */
					run_break_right = true;
				} else if (i > 0) {
					/* Break to the left */
					run_break_left = true;
				}
			}
		}
	}


	/* Look at every soon to be newly adjacent square. */
	for (i = -max; i <= max; i++) {		
		/* New direction */
		new_dir = cycle[chome[prev_dir] + i];
		
		/* New location */
		row = py + ddy[prev_dir] + ddy[new_dir];
		col = px + ddx[prev_dir] + ddx[new_dir];
		
		/* HACK: Ugh. Sometimes we come up with illegal bounds. This will
		 * treat the symptom but not the disease. */
		if (row >= cave->height || col >= cave->width) continue;
		if (row < 0 || col < 0) continue;

		/* Visible monsters abort running */
		if (cave->squares[row][col].mon > 0) {
			struct monster *mon = square_monster(cave, row, col);
			
			/* Visible monster */
			if (mflag_has(mon->mflag, MFLAG_VISIBLE) && !is_mimicking(mon))
				return (true);
		}
	}

	/* Looking for open area */
	if (run_open_area) {
		/* Hack -- look again */
		for (i = -max; i < 0; i++) {
			new_dir = cycle[chome[prev_dir] + i];

			row = py + ddy[new_dir];
			col = px + ddx[new_dir];

			/* Unknown grid or non-wall */
			/* Was: square_ispassable(cave, row, col) */
			if (!square_isknown(cave, row, col) ||
			    (square_ispassable(cave, row, col))) {
				/* Looking to break right */
				if (run_break_right) {
					return (true);
				}
			} else { /* Obstacle */
				/* Looking to break left */
				if (run_break_left) {
					return (true);
				}
			}
		}

		/* Hack -- look again */
		for (i = max; i > 0; i--) {
			new_dir = cycle[chome[prev_dir] + i];

			row = py + ddy[new_dir];
			col = px + ddx[new_dir];

			/* Unknown grid or non-wall */
			/* Was: square_ispassable(cave, row, col) */
			if (!square_isknown(cave, row, col) ||
			    (square_ispassable(cave, row, col))) {
				/* Looking to break left */
				if (run_break_left) {
					return (true);
				}
			} else { /* Obstacle */
				/* Looking to break right */
				if (run_break_right) {
					return (true);
				}
			}
		}
	} else { /* Not looking for open area */
		/* No options */
		if (!option) {
			return (true);
		} else if (!option2) { /* One option */
			/* Primary option */
			run_cur_dir = option;

			/* No other options */
			run_old_dir = option;
		} else { /* Two options, examining corners */
			/* Primary option */
			run_cur_dir = option;

			/* Hack -- allow curving */
			run_old_dir = option2;
		}
	}


	/* About to hit a known wall, stop */
	if (see_wall(run_cur_dir, py, px))
		return (true);


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

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

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

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

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

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

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

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

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

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

	player->upkeep->running_firststep = false;
}
Esempio n. 17
0
/**
 * Move player in the given direction.
 *
 * This routine should only be called when energy has been expended.
 *
 * Note that this routine handles monsters in the destination grid,
 * and also handles attempting to move into walls/doors/rubble/etc.
 */
void move_player(int dir, bool disarm)
{
	int py = player->py;
	int px = player->px;

	int y = py + ddy[dir];
	int x = px + ddx[dir];

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

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

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

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

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

		/* Notice unknown obstacles, mention known obstacles */
		if (!square_isknown(cave, y, x)) {
			if (square_isrubble(cave, y, x)) {
				msgt(MSG_HITWALL,
					 "You feel a pile of rubble blocking your way.");
				square_memorize(cave, y, x);
				square_light_spot(cave, y, x);
			} else if (square_iscloseddoor(cave, y, x)) {
				msgt(MSG_HITWALL, "You feel a door blocking your way.");
				square_memorize(cave, y, x);
				square_light_spot(cave, y, x);
			} else {
				msgt(MSG_HITWALL, "You feel a wall blocking your way.");
				square_memorize(cave, y, x);
				square_light_spot(cave, y, x);
			}
		} else {
			if (square_isrubble(cave, y, x))
				msgt(MSG_HITWALL,
					 "There is a pile of rubble blocking your way.");
			else if (square_iscloseddoor(cave, y, x))
				msgt(MSG_HITWALL, "There is a door blocking your way.");
			else
				msgt(MSG_HITWALL, "There is a wall blocking your way.");
		}
	} else {
		/* See if trap detection status will change */
		bool old_dtrap = square_isdtrap(cave, py, px);
		bool new_dtrap = square_isdtrap(cave, y, x);

		/* Note the change in the detect status */
		if (old_dtrap != new_dtrap)
			player->upkeep->redraw |= (PR_DTRAP);

		/* Disturb player if the player is about to leave the area */
		if (player->upkeep->running && !player->upkeep->running_firststep && 
			old_dtrap && !new_dtrap) {
			disturb(player, 0);
			return;
		}

		/* Move player */
		monster_swap(py, px, y, x);

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

		/* Searching */
		if (player->searching ||
				(player->state.skills[SKILL_SEARCH_FREQUENCY] >= 50) ||
				one_in_(50 - player->state.skills[SKILL_SEARCH_FREQUENCY]))
			search(false);

		/* Handle store doors, or notice objects */
		if (square_isshop(cave, player->py, player->px)) {
			/* Disturb */
			disturb(player, 0);
			event_signal(EVENT_ENTER_STORE);
			event_remove_handler_type(EVENT_ENTER_STORE);
			event_signal(EVENT_USE_STORE);
			event_remove_handler_type(EVENT_USE_STORE);
			event_signal(EVENT_LEAVE_STORE);
			event_remove_handler_type(EVENT_LEAVE_STORE);
		} else {
			/* Know objects, queue autopickup */
			floor_pile_know(cave, player->py, player->px);
			cmdq_push(CMD_AUTOPICKUP);
		}


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

			/* Hit the trap. */
			hit_trap(y, x);
		} else if (square_isknowntrap(cave, y, x)) {
			/* Disturb */
			disturb(player, 0);

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

	player->upkeep->running_firststep = false;
}