Ejemplo n.º 1
0
static bool is_valid_pf(int y, int x)
{
	/* Unvisited means allowed */
	if (!square_ismark(cave, y, x)) return (TRUE);

	/* Require open space */
	return (square_ispassable(cave, y, x));
}
Ejemplo n.º 2
0
const char *square_apparent_name(struct chunk *c, struct player *p, int y, int x) {
	int f = f_info[c->squares[y][x].feat].mimic;

	if (!square_ismark(c, y, x) && !square_isseen(c, y, x))
		return "unknown grid";

	return f_info[f].name;
}
Ejemplo n.º 3
0
/**
 * Light up the dungeon using "claravoyance"
 *
 * This function "illuminates" every grid in the dungeon, memorizes all
 * "objects" (or notes the existence of an object "if" full is true),
 * and memorizes all grids as with magic mapping.
 */
void wiz_light(struct chunk *c, struct player *p, bool full)
{
	int i, y, x;

	/* Scan all grids */
	for (y = 1; y < c->height - 1; y++) {
		for (x = 1; x < c->width - 1; x++) {
			/* Process all non-walls */
			if (!square_seemslikewall(c, y, x)) {
				if (!square_in_bounds_fully(c, y, x)) continue;

				/* Scan all neighbors */
				for (i = 0; i < 9; i++) {
					int yy = y + ddy_ddd[i];
					int xx = x + ddx_ddd[i];

					/* Perma-light the grid */
					sqinfo_on(c->squares[yy][xx].info, SQUARE_GLOW);

					/* Memorize normal features */
					if (!square_isfloor(c, yy, xx) || 
						square_isvisibletrap(c, yy, xx)) {
						square_memorize(c, yy, xx);
						square_mark(c, yy, xx);
					}
				}
			}

			/* Memorize objects */
			if (full) {
				square_know_pile(c, y, x);
			} else {
				square_sense_pile(c, y, x);
			}

			/* Forget unprocessed, unknown grids in the mapping area */
			if (!square_ismark(c, y, x) && square_isnotknown(c, y, x))
				square_forget(c, y, x);
		}
	}

	/* Unmark grids */
	for (y = 1; y < c->height - 1; y++) {
		for (x = 1; x < c->width - 1; x++) {
			if (!square_in_bounds(c, y, x)) continue;
			square_unmark(c, y, x);
		}
	}

	/* Fully update the visuals */
	p->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS);

	/* Redraw whole map, monster list */
	p->upkeep->redraw |= (PR_MAP | PR_MONLIST | PR_ITEMLIST);
}
Ejemplo n.º 4
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 *m_ptr = cave_monster(cave, m_idx);

	/* Allow attack on visible monsters if unafraid */
	if (m_idx > 0 && mflag_has(m_ptr->mflag, MFLAG_VISIBLE) &&
		!is_mimicking(m_ptr)) {
		/* 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), m_ptr, 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_ismark(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);
}
Ejemplo n.º 5
0
/**
 * Determine if a given grid may be "opened"
 */
static bool do_cmd_open_test(int y, int x)
{
	/* Must have knowledge */
	if (!square_ismark(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);
}
Ejemplo 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)
{
	object_type *obj;

	/* Require "seen" flag */
	if (!square_isseen(c, y, x))
		return;

	for (obj = square_object(c, y, x); obj; obj = obj->next)
		obj->marked = MARK_SEEN;

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

	/* Memorize this grid */
	sqinfo_on(c->squares[y][x].info, SQUARE_MARK);
}
Ejemplo n.º 7
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_ismark(cave, y, x)) return (FALSE);

	/* Default */
	return (TRUE);
}
Ejemplo n.º 8
0
/**
 * Determine if a given grid may be "disarmed"
 */
static bool do_cmd_disarm_test(int y, int x)
{
	/* Must have knowledge */
	if (!square_ismark(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;
}
Ejemplo n.º 9
0
/**
 * Try to break a glyph.
 */
static bool process_monster_glyph(struct chunk *c, struct monster *m_ptr,
								  int nx, int ny)
{
	assert(square_iswarded(c, ny, nx));

	/* Break the ward */
	if (randint1(z_info->glyph_hardness) < m_ptr->race->level) {
		/* Describe observable breakage */
		if (square_ismark(c, ny, nx))
			msg("The rune of protection is broken!");

		/* Forget the rune */
		sqinfo_off(c->squares[ny][nx].info, SQUARE_MARK);

		/* Break the rune */
		square_remove_ward(c, ny, nx);

		return TRUE;
	}

	/* Unbroken ward - can't move */
	return FALSE;
}
Ejemplo 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_ismark(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);
}
Ejemplo 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_ismark(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);
}
Ejemplo n.º 12
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_ismark(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 */
        *y = yy;
        *x = xx;
    }

    /* All done */
    return count;
}
Ejemplo n.º 13
0
/**
 * Determine if a given location is "interesting"
 */
bool target_accept(int y, int x)
{
	object_type *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) {
		monster_type *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, y, x); obj; obj = obj->next)
		/* Memorized object */
		if (obj->marked && !ignore_item_ok(obj)) return (TRUE);

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

	/* Nope */
	return (FALSE);
}
Ejemplo 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_ismark(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_ismark(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->marked && !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_ismark(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);
    }
}
Ejemplo n.º 15
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(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, grid_data *g)
{
	object_type *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 = 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;
	g->trapborder = (square_isdedge(cave, y, x)) ? TRUE : FALSE;

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

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

		/* Remember seen feature */
		cave_k->squares[y][x].feat = cave->squares[y][x].feat;
	} else if (!square_ismark(cave, y, x)) {
		g->f_idx = FEAT_NONE;
		//cave_k->squares[y][x].feat = FEAT_NONE;
	} else if (square_isglow(cave, y, x)) {
		g->lighting = LIGHTING_LIT;
	}

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

    /* There is a trap in this square */
    if (square_istrap(cave, y, x) && square_ismark(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 */
				g->trap = trap;
				break;
			}
			trap = trap->next;
		}
    }

	/* Objects */
	for (obj = square_object(cave, y, x); obj; obj = obj->next) {
		if (obj->marked == MARK_AWARE) {

			/* Distinguish between unseen money and objects */
			if (tval_is_money(obj)) {
				g->unseen_money = TRUE;
			} else {
				g->unseen_object = TRUE;
			}

		} else if (obj->marked == MARK_SEEN && !ignore_item_ok(obj)) {
			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.*/
		monster_type *m_ptr = cave_monster(cave, g->m_idx);
		if (!mflag_has(m_ptr->mflag, MFLAG_VISIBLE)) 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. */
}
Ejemplo 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 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 *m_ptr = 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(m_ptr)) {
			become_aware(m_ptr);

			/* Mimic wakes up */
			mon_clear_timed(m_ptr, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, FALSE);

		} else {
			py_attack(y, x);
		}
	} else if (disarm && square_ismark(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_ismark(cave, y, x)) {
			if (square_isrubble(cave, y, x)) {
				msgt(MSG_HITWALL,
					 "You feel a pile of rubble blocking your way.");
				sqinfo_on(cave->squares[y][x].info, SQUARE_MARK);
				square_light_spot(cave, y, x);
			} else if (square_iscloseddoor(cave, y, x)) {
				msgt(MSG_HITWALL, "You feel a door blocking your way.");
				sqinfo_on(cave->squares[y][x].info, SQUARE_MARK);
				square_light_spot(cave, y, x);
			} else {
				msgt(MSG_HITWALL, "You feel a wall blocking your way.");
				sqinfo_on(cave->squares[y][x].info, SQUARE_MARK);
				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 {
			/* Handle objects (later) */
			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;
}
Ejemplo n.º 17
0
/**
 * Draw a visible path over the squares between (x1,y1) and (x2,y2).
 *
 * The path consists of "*", which are white except where there is a
 * monster, object or feature in the grid.
 *
 * This routine has (at least) three weaknesses:
 * - remembered objects/walls which are no longer present are not shown,
 * - squares which (e.g.) the player has walked through in the dark are
 *   treated as unknown space.
 * - walls which appear strange due to hallucination aren't treated correctly.
 *
 * The first two result from information being lost from the dungeon arrays,
 * which requires changes elsewhere
 */
static int draw_path(u16b path_n, struct loc *path_g, wchar_t *c, int *a,
					 int y1, int x1)
{
	int i;
	bool on_screen;

	/* No path, so do nothing. */
	if (path_n < 1) return 0;

	/* The starting square is never drawn, but notice if it is being
     * displayed. In theory, it could be the last such square.
     */
	on_screen = panel_contains(y1, x1);

	/* Draw the path. */
	for (i = 0; i < path_n; i++) {
		byte colour;

		/* Find the co-ordinates on the level. */
		int y = path_g[i].y;
		int x = path_g[i].x;
		struct monster *mon = square_monster(cave, y, x);
		struct object *obj = square_object(cave, y, x);

		/*
		 * As path[] is a straight line and the screen is oblong,
		 * there is only section of path[] on-screen.
		 * If the square being drawn is visible, this is part of it.
		 * If none of it has been drawn, continue until some of it
		 * is found or the last square is reached.
		 * If some of it has been drawn, finish now as there are no
		 * more visible squares to draw.
		 */
		 if (panel_contains(y,x)) on_screen = TRUE;
		 else if (on_screen) break;
		 else continue;

	 	/* Find the position on-screen */
		move_cursor_relative(y,x);

		/* This square is being overwritten, so save the original. */
		Term_what(Term->scr->cx, Term->scr->cy, a+i, c+i);

		/* Choose a colour. */
		if (mon && mflag_has(mon->mflag, MFLAG_VISIBLE)) {
			/* Mimics act as objects */
			if (rf_has(mon->race->flags, RF_UNAWARE)) 
				colour = COLOUR_YELLOW;
			else
				/* Visible monsters are red. */
				colour = COLOUR_L_RED;
		} else if (obj && obj->marked)
			/* Known objects are yellow. */
			colour = COLOUR_YELLOW;

		else if ((!square_isprojectable(cave, y,x) && square_ismark(cave, y, x))
				 || square_isseen(cave, y, x))
			/* Known walls are blue. */
			colour = COLOUR_BLUE;

		else if (!square_ismark(cave, y, x) && !square_isseen(cave, y, x))
			/* Unknown squares are grey. */
			colour = COLOUR_L_DARK;

		else
			/* Unoccupied squares are white. */
			colour = COLOUR_WHITE;

		/* Draw the path segment */
		(void)Term_addch(colour, L'*');
	}
	return i;
}
Ejemplo n.º 18
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)
{
	int x, y;

	/* 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 {
			/* Pathfinding */
			if (pf_result_index < 0) {
				/* Abort if the path is finished */
				disturb(player, 0);
				player->upkeep->running_withpathfind = FALSE;
				return;
			} else if (pf_result_index == 0) {
				/* Abort if we would hit a wall */
				y = player->py + ddy[pf_result[pf_result_index] - '0'];
				x = player->px + ddx[pf_result[pf_result_index] - '0'];

				/* Known wall */
				if (square_ismark(cave, y, x) &&
					!square_ispassable(cave, y, x)) {
					disturb(player, 0);
					player->upkeep->running_withpathfind = FALSE;
					return;
				}
			} else if (pf_result_index > 0) {
				/* 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_ismark(cave, y, x) &&
					!square_ispassable(cave, y, x)) {
					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_ismark(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--;

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

	/* Move the player */
	move_player(run_cur_dir, TRUE);

	/* Prepare the next step */
	if (player->upkeep->running) {
		cmdq_push(CMD_RUN);
		cmd_set_arg_direction(cmdq_peek(), "direction", 0);
	}
}
Ejemplo n.º 19
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) {
			monster_type *m_ptr = square_monster(cave, row, col);

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

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

		/* Assume unknown */
		inv = TRUE;

		/* Check memorized grids */
		if (square_ismark(cave, row, col)) {
			bool notice = square_noticeable(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) {
			monster_type *m_ptr = square_monster(cave, row, col);
			
			/* Visible monster */
			if (mflag_has(m_ptr->mflag, MFLAG_VISIBLE) && !is_mimicking(m_ptr))
				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_ismark(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_ismark(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);
}