예제 #1
0
파일: cave.c 프로젝트: datatypevoid/angband
/**
 * Standard "find me a location" function, now with all legal outputs!
 *
 * Obtains a legal location within the given distance of the initial
 * location, and with "los()" from the source to destination location.
 *
 * This function is often called from inside a loop which searches for
 * locations while increasing the "d" distance.
 *
 * need_los determines whether line of sight is needed
 */
void scatter(struct chunk *c, int *yp, int *xp, int y, int x, int d,
			 bool need_los)
{
	int nx, ny;
	int tries = 0;

	/* Pick a location, try many times */
	while (tries < 1000) {
		/* Pick a new location */
		ny = rand_spread(y, d);
		nx = rand_spread(x, d);
		tries++;

		/* Ignore annoying locations */
		if (!square_in_bounds_fully(c, ny, nx)) continue;

		/* Ignore "excessively distant" locations */
		if ((d > 1) && (distance(y, x, ny, nx) > d)) continue;
		
		/* Require "line of sight" if set */
		if (need_los && !los(c, y, x, ny, nx)) continue;

		/* Set the location and return */
		(*yp) = ny;
		(*xp) = nx;
		return;
	}
}
예제 #2
0
파일: cave.c 프로젝트: CrypticGator/angband
/**
 * Standard "find me a location" function
 *
 * Obtains a legal location within the given distance of the initial
 * location, and with "los()" from the source to destination location.
 *
 * This function is often called from inside a loop which searches for
 * locations while increasing the "d" distance.
 *
 * need_los determines whether line of sight is needed
 */
void scatter(struct chunk *c, int *yp, int *xp, int y, int x, int d, bool need_los)
{
	int nx, ny;


	/* Pick a location */
	while (true)
	{
		/* Pick a new location */
		ny = rand_spread(y, d);
		nx = rand_spread(x, d);

		/* Ignore annoying locations */
		if (!square_in_bounds_fully(c, ny, nx)) continue;

		/* Ignore "excessively distant" locations */
		if ((d > 1) && (distance(y, x, ny, nx) > d)) continue;
		
		/* Don't need los */
		if (!need_los) break;

		/* Require "line of sight" if set */
		if (need_los && (los(c, y, x, ny, nx))) break;
	}

	/* Save the location */
	(*yp) = ny;
	(*xp) = nx;
}
예제 #3
0
/**
 * Light or Darken the town
 */
void cave_illuminate(struct chunk *c, bool daytime)
{
	int y, x, i;

	/* Apply light or darkness */
	for (y = 0; y < c->height; y++)
		for (x = 0; x < c->width; x++) {
			int d;
			bool light = FALSE;
			feature_type *f_ptr = &f_info[c->squares[y][x].feat];
			
			/* Skip grids with no surrounding floors or stairs */
			for (d = 0; d < 9; d++) {
				/* Extract adjacent (legal) location */
				int yy = y + ddy_ddd[d];
				int xx = x + ddx_ddd[d];

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

				/* Test */
				if (square_isfloor(c, yy, xx) || square_isstairs(c, yy, xx))
					light = TRUE;
			}

			if (!light) continue;

			/* Only interesting grids at night */
			if (daytime || !tf_has(f_ptr->flags, TF_FLOOR)) {
				sqinfo_on(c->squares[y][x].info, SQUARE_GLOW);
				sqinfo_on(c->squares[y][x].info, SQUARE_MARK);
			} else {
				sqinfo_off(c->squares[y][x].info, SQUARE_GLOW);
				sqinfo_off(c->squares[y][x].info, SQUARE_MARK);
			}
		}
			
			
	/* Light shop doorways */
	for (y = 0; y < c->height; y++) {
		for (x = 0; x < c->width; x++) {
			if (!square_isshop(c, y, x))
				continue;
			for (i = 0; i < 8; i++) {
				int yy = y + ddy_ddd[i];
				int xx = x + ddx_ddd[i];
				sqinfo_on(c->squares[yy][xx].info, SQUARE_GLOW);
				sqinfo_on(c->squares[yy][xx].info, SQUARE_MARK);
			}
		}
	}


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

	/* Redraw map, monster list */
	player->upkeep->redraw |= (PR_MAP | PR_MONLIST | PR_ITEMLIST);
}
예제 #4
0
/**
 * Checks if a square is at the (inner) edge of a trap detect area 
 */ 
bool square_dtrap_edge(struct chunk *c, int y, int x) 
{ 
	/* Check if the square is a dtrap in the first place */ 
	if (!square_isdtrap(c, y, x)) return FALSE;

 	/* Check for non-dtrap adjacent grids */ 
	if (square_in_bounds_fully(c, y + 1, x) && (!square_isdtrap(c, y + 1, x)))
		return TRUE;
	if (square_in_bounds_fully(c, y, x + 1) && (!square_isdtrap(c, y, x + 1)))
		return TRUE;
	if (square_in_bounds_fully(c, y - 1, x) && (!square_isdtrap(c, y - 1, x)))
		return TRUE;
	if (square_in_bounds_fully(c, y, x - 1) && (!square_isdtrap(c, y, x - 1)))
		return TRUE;

	return FALSE; 
}
예제 #5
0
파일: mon-move.c 프로젝트: magnate/angband
/**
 * Choose a good hiding place near a monster for it to run toward.
 *
 * Pack monsters will use this to "ambush" the player and lure him out
 * of corridors into open space so they can swarm him.
 *
 * Return true if a good location is available.
 */
static bool get_move_find_hiding(struct chunk *c, struct monster *mon)
{
	struct loc mon_grid = loc(mon->fx, mon->fy);
	struct loc player_grid = loc(player->px, player->py);

	int i, y, x, dy, dx, d, dis;
	int gy = 0, gx = 0, gdis = 999, min;

	const int *y_offsets, *x_offsets;

	/* Closest distance to get */
	min = distance(player_grid, mon_grid) * 3 / 4 + 2;

	/* Start with adjacent locations, spread further */
	for (d = 1; d < 10; d++) {
		/* Get the lists of points with a distance d from monster */
		y_offsets = dist_offsets_y[d];
		x_offsets = dist_offsets_x[d];

		/* Check the locations */
		for (i = 0, dx = x_offsets[0], dy = y_offsets[0];
		     dx != 0 || dy != 0;
		     i++, dx = x_offsets[i], dy = y_offsets[i]) {
			y = mon_grid.y + dy;
			x = mon_grid.x + dx;

			/* Skip illegal locations */
			if (!square_in_bounds_fully(c, y, x)) continue;

			/* Skip occupied locations */
			if (!square_isempty(c, y, x)) continue;

			/* Check for hidden, available grid */
			if (!square_isview(c, y, x) &&
				projectable(c, mon_grid.y, mon_grid.x, y, x, PROJECT_STOP)) {
				/* Calculate distance from player */
				dis = distance(loc(x, y), player_grid);

				/* Remember if closer than previous */
				if (dis < gdis && dis >= min) {
					gy = y;
					gx = x;
					gdis = dis;
				}
			}
		}

		/* Check for success */
		if (gdis < 999) {
			/* Good location */
			mon->target.grid = loc(gx, gy);
			return (true);
		}
	}

	/* No good place */
	return (false);
}
예제 #6
0
파일: cave-map.c 프로젝트: lhz/angband
/**
 * 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);
}
예제 #7
0
파일: target.c 프로젝트: Axydlbaaxr/angband
/**
 * Set the target to a location
 */
void target_set_location(int y, int x)
{
	/* Legal target */
	if (square_in_bounds_fully(cave, y, x)) {
		/* Save target info */
		target_set = true;
		target_who = NULL;
		target_y = y;
		target_x = x;
		return;
	}

	/* Reset target info */
	target_set = false;
	target_who = 0;
	target_y = 0;
	target_x = 0;
}
예제 #8
0
/**
 * Return a target set of target_able monsters.
 */
struct point_set *target_get_monsters(int mode, monster_predicate pred)
{
	int y, x;
	int min_y, min_x, max_y, max_x;
	struct point_set *targets = point_set_new(TS_INITIAL_SIZE);

	/* Get the current panel */
	get_panel(&min_y, &min_x, &max_y, &max_x);

	/* Scan for targets */
	for (y = min_y; y < max_y; y++) {
		for (x = min_x; x < max_x; x++) {
			struct loc grid = loc(x, y);

			/* Check bounds */
			if (!square_in_bounds_fully(cave, grid)) continue;

			/* Require "interesting" contents */
			if (!target_accept(y, x)) continue;

			/* Special mode */
			if (mode & (TARGET_KILL)) {
				struct monster *mon = square_monster(cave, grid);

				/* Must contain a monster */
				if (mon == NULL) continue;

				/* Must be a targettable monster */
				if (!target_able(mon)) continue;

				/* Must be the right sort of monster */
				if (pred && !pred(mon)) continue;
			}

			/* Save the location */
			add_to_point_set(targets, grid);
		}
	}

	sort(targets->pts, point_set_size(targets), sizeof(*(targets->pts)),
		 cmp_distance);
	return targets;
}
예제 #9
0
/**
 * Set the target to a location
 */
void target_set_location(int y, int x)
{
	struct loc grid = loc(x, y);

	/* Legal target */
	if (square_in_bounds_fully(cave, grid)) {
		/* Save target info */
		target_set = true;
		target.midx = 0;
		target.grid = grid;
		return;
	}

	/* Reset target info */
	target_set = false;
	target.midx = 0;
	target.grid.y = 0;
	target.grid.x = 0;
}
예제 #10
0
/* From Will Asher in DJA:
 * Find whether a monster is near a permanent wall
 * this decides whether PASS_WALL & KILL_WALL monsters 
 * use the monster flow code
 */
static bool near_permwall(const struct monster *mon, struct chunk *c)
{
	int y, x;
	int my = mon->fy;
	int mx = mon->fx;
	
	/* if PC is in LOS, there's no need to go around walls */
    if (projectable(cave, my, mx, player->py, player->px, PROJECT_NONE)) 
		return false;
    
    /* PASS_WALL & KILL_WALL monsters occasionally flow for a turn anyway */
    if (randint0(99) < 5) return true;
    
	/* Search the nearby grids, which are always in bounds */
	for (y = (my - 2); y <= (my + 2); y++) {
		for (x = (mx - 2); x <= (mx + 2); x++) {
            if (!square_in_bounds_fully(c, y, x)) continue;
            if (square_isperm(c, y, x)) return true;
		}
	}
	return false;
}
예제 #11
0
/**
 * Set the target to a location
 */
void target_set_location(int y, int x)
{
	/* Legal target */
	if (square_in_bounds_fully(cave, y, x)) {
		struct monster *mon = square_monster(cave, y, x);

		/* Save target info */
		target_set = TRUE;
		target_who = NULL;
		if (mon && target_able(mon))
			target_who = mon;
		target_y = y;
		target_x = x;
		return;
	}

	/* Reset target info */
	target_set = FALSE;
	target_who = 0;
	target_y = 0;
	target_x = 0;
}
예제 #12
0
파일: cave.c 프로젝트: CrypticGator/angband
/**
 * 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;
}
예제 #13
0
/**
 * Place the player at a random starting location.
 * \param c current chunk
 * \param p the player
 */
void new_player_spot(struct chunk *c, struct player *p)
{
    int y, x;

    /* Try to find a good place to put the player */
	if (OPT(p, birth_levels_persist) &&
		square_in_bounds_fully(c, p->py, p->px) &&
		square_isstairs(c, p->py, p->px)) {
		y = p->py;
		x = p->px;
	} else if (!find_start(c, &y, &x)) {
		quit("Failed to place player!");
	}

    /* Create stairs the player came down if allowed and necessary */
    if (!OPT(p, birth_connect_stairs))
		;
	else if (p->upkeep->create_down_stair)
		square_set_feat(c, y, x, FEAT_MORE);
	else if (p->upkeep->create_up_stair)
		square_set_feat(c, y, x, FEAT_LESS);

    player_place(c, p, y, x);
}
예제 #14
0
파일: target.c 프로젝트: Axydlbaaxr/angband
/**
 * Return a target set of target_able monsters.
 */
struct point_set *target_get_monsters(int mode)
{
	int y, x;
	int min_y, min_x, max_y, max_x;
	struct point_set *targets = point_set_new(TS_INITIAL_SIZE);

	/* Get the current panel */
	get_panel(&min_y, &min_x, &max_y, &max_x);

	/* Scan for targets */
	for (y = min_y; y < max_y; y++) {
		for (x = min_x; x < max_x; x++) {
			/* Check bounds */
			if (!square_in_bounds_fully(cave, y, x)) continue;

			/* Require "interesting" contents */
			if (!target_accept(y, x)) continue;

			/* Special mode */
			if (mode & (TARGET_KILL)) {
				/* Must contain a monster */
				if (!(cave->squares[y][x].mon > 0)) continue;

				/* Must be a targettable monster */
			 	if (!target_able(square_monster(cave, y, x))) continue;
			}

			/* Save the location */
			add_to_point_set(targets, y, x);
		}
	}

	sort(targets->pts, point_set_size(targets), sizeof(*(targets->pts)),
		 cmp_distance);
	return targets;
}
예제 #15
0
파일: mon-move.c 프로젝트: magnate/angband
/**
 * Choose a "safe" location near a monster for it to run toward.
 *
 * A location is "safe" if it can be reached quickly and the player
 * is not able to fire into it (it isn't a "clean shot").  So, this will
 * cause monsters to "duck" behind walls.  Hopefully, monsters will also
 * try to run towards corridor openings if they are in a room.
 *
 * This function may take lots of CPU time if lots of monsters are fleeing.
 *
 * Return true if a safe location is available.
 */
static bool get_move_find_safety(struct chunk *c, struct monster *mon)
{
	int fy = mon->fy;
	int fx = mon->fx;

	int py = player->py;
	int px = player->px;

	int i, y, x, dy, dx, d, dis;
	int gy = 0, gx = 0, gdis = 0;

	const int *y_offsets;
	const int *x_offsets;

	/* Start with adjacent locations, spread further */
	for (d = 1; d < 10; d++) {
		/* Get the lists of points with a distance d from (fx, fy) */
		y_offsets = dist_offsets_y[d];
		x_offsets = dist_offsets_x[d];

		/* Check the locations */
		for (i = 0, dx = x_offsets[0], dy = y_offsets[0];
		     dx != 0 || dy != 0;
		     i++, dx = x_offsets[i], dy = y_offsets[i]) {
			y = fy + dy;
			x = fx + dx;

			/* Skip illegal locations */
			if (!square_in_bounds_fully(c, y, x)) continue;

			/* Skip locations in a wall */
			if (!square_ispassable(c, y, x)) continue;

			/* Ignore too-distant grids */
			if (c->noise.grids[y][x] > c->noise.grids[fy][fx] + 2 * d)
				continue;

			/* Ignore damaging terrain if they can't handle it */
			if (square_isdamaging(c, y, x) &&
				!rf_has(mon->race->flags, square_feat(c, y, x)->resist_flag))
				continue;

			/* Check for absence of shot (more or less) */
			if (!square_isview(c, y, x)) {
				/* Calculate distance from player */
				dis = distance(loc(x, y), loc(px, py));

				/* Remember if further than previous */
				if (dis > gdis) {
					gy = y;
					gx = x;
					gdis = dis;
				}
			}
		}

		/* Check for success */
		if (gdis > 0) {
			/* Good location */
			mon->target.grid = loc(gx, gy);
			return (true);
		}
	}

	/* No safe place */
	return (false);
}
예제 #16
0
void square_add_trap(struct chunk *c, int y, int x)
{
	assert(square_in_bounds_fully(c, y, x));
	place_trap(c, y, x, -1, c->depth);
}
예제 #17
0
파일: obj-pile.c 프로젝트: awalding/angband
/**
 * Let an object fall to the ground at or near a location.
 *
 * The initial location is assumed to be "square_in_bounds_fully(cave, )".
 *
 * This function takes a parameter "chance".  This is the percentage
 * chance that the item will "disappear" instead of drop.  If the object
 * has been thrown, then this is the chance of disappearance on contact.
 *
 * This function will produce a description of a drop event under the player
 * when "verbose" is true.
 *
 * We check several locations to see if we can find a location at which
 * the object can combine, stack, or be placed.  Artifacts will try very
 * hard to be placed, including "teleporting" to a useful grid if needed.
 *
 * Objects which fail to be carried by the floor are deleted.  This function
 * attempts to add successfully dropped objects to, and to remove failures
 * from, the object list (as dropped items may or may not be already listed).
 */
void drop_near(struct chunk *c, struct object *dropped, int chance, int y,
			   int x, bool verbose)
{
	int i, k, n, d, s;

	int bs, bn;
	int by, bx;
	int dy, dx;
	int ty, tx;

	struct object *obj;

	char o_name[80];

	bool flag = false;

	/* Only called in the current level */
	assert(c == cave);

	/* Describe object */
	object_desc(o_name, sizeof(o_name), dropped, ODESC_BASE);

	/* Handle normal "breakage" */
	if (!dropped->artifact && (randint0(100) < chance)) {
		/* Message */
		msg("The %s %s.", o_name,
			VERB_AGREEMENT(dropped->number, "breaks", "break"));

		/* Failure */
		if (dropped->known) {
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
		delist_object(c, dropped);
		object_delete(&dropped);
		return;
	}

	/* Score */
	bs = -1;

	/* Picker */
	bn = 0;

	/* Default */
	by = y;
	bx = x;

	/* Scan local grids */
	for (dy = -3; dy <= 3; dy++) {
		for (dx = -3; dx <= 3; dx++) {
			bool comb = false;

			/* Calculate actual distance */
			d = (dy * dy) + (dx * dx);

			/* Ignore distant grids */
			if (d > 10) continue;

			/* Location */
			ty = y + dy;
			tx = x + dx;

			/* Skip illegal grids */
			if (!square_in_bounds_fully(c, ty, tx)) continue;

			/* Require line of sight */
			if (!los(c, y, x, ty, tx)) continue;

			/* Require floor space */
			if (!square_isfloor(c, ty, tx)) continue;

			/* Require no trap or rune */
			if (square_isplayertrap(c, ty, tx) ||
				square_iswarded(c, ty, tx))
				continue;

			/* No objects */
			k = 0;
			n = 0;

			/* Scan objects in that grid */
			for (obj = square_object(c, ty, tx); obj; obj = obj->next) {
				/* Check for possible combination */
				if (object_similar(obj, dropped, OSTACK_FLOOR))
					comb = true;

				/* Count objects */
				if (!ignore_item_ok(obj))
					k++;
				else
					n++;
			}

			/* Add new object */
			if (!comb) k++;

			/* Option -- disallow stacking */
			if (OPT(birth_no_stacking) && (k > 1)) continue;

			/* Paranoia? */
			if ((k + n) > z_info->floor_size &&
				!floor_get_oldest_ignored(ty, tx)) continue;

			/* Calculate score */
			s = 1000 - (d + k * 5);

			/* Skip bad values */
			if (s < bs) continue;

			/* New best value */
			if (s > bs) bn = 0;

			/* Apply the randomizer to equivalent values */
			if ((++bn >= 2) && (randint0(bn) != 0)) continue;

			/* Keep score */
			bs = s;

			/* Track it */
			by = ty;
			bx = tx;

			/* Okay */
			flag = true;
		}
	}

	/* Handle lack of space */
	if (!flag && !dropped->artifact) {
		/* Message */
		msg("The %s %s.", o_name,
			VERB_AGREEMENT(dropped->number, "disappears", "disappear"));

		/* Debug */
		if (player->wizard) msg("Breakage (no floor space).");

		/* Failure */
		if (dropped->known) {
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
		delist_object(c, dropped);
		object_delete(&dropped);
		return;
	}

	/* Find a grid */
	for (i = 0; !flag; i++) {
		/* Bounce around */
		if (i < 1000) {
			ty = rand_spread(by, 1);
			tx = rand_spread(bx, 1);
		} else {
			/* Random locations */
			ty = randint0(c->height);
			tx = randint0(c->width);
		}

		/* Require floor space */
		if (!square_canputitem(c, ty, tx)) continue;

		/* Bounce to that location */
		by = ty;
		bx = tx;

		/* Okay */
		flag = true;
	}

	/* Give it to the floor */
	if (!floor_carry(c, by, bx, dropped, false)) {
		/* Message */
		msg("The %s %s.", o_name,
			VERB_AGREEMENT(dropped->number, "disappears", "disappear"));

		/* Debug */
		if (player->wizard) msg("Breakage (too many objects).");

		if (dropped->artifact) dropped->artifact->created = false;

		/* Failure */
		if (dropped->known) {
			delist_object(cave_k, dropped->known);
			object_delete(&dropped->known);
		}
		delist_object(c, dropped);
		object_delete(&dropped);
		return;
	}

	/* Sound */
	sound(MSG_DROP);

	/* Message when an object falls under the player */
	if (verbose && (c->squares[by][bx].mon < 0))
		/* Check the item still exists and isn't ignored */
		if (c->objects[dropped->oidx] && !ignore_item_ok(dropped))
			msg("You feel something roll beneath your feet.");
}
예제 #18
0
/**
 * Choose a good hiding place near a monster for it to run toward.
 *
 * Pack monsters will use this to "ambush" the player and lure him out
 * of corridors into open space so they can swarm him.
 *
 * Return true if a good location is available.
 */
static bool find_hiding(struct chunk *c, struct monster *mon)
{
	int fy = mon->fy;
	int fx = mon->fx;

	int py = player->py;
	int px = player->px;

	int i, y, x, dy, dx, d, dis;
	int gy = 0, gx = 0, gdis = 999, min;

	const int *y_offsets, *x_offsets;

	/* Closest distance to get */
	min = distance(py, px, fy, fx) * 3 / 4 + 2;

	/* Start with adjacent locations, spread further */
	for (d = 1; d < 10; d++) {
		/* Get the lists of points with a distance d from (fx, fy) */
		y_offsets = dist_offsets_y[d];
		x_offsets = dist_offsets_x[d];

		/* Check the locations */
		for (i = 0, dx = x_offsets[0], dy = y_offsets[0];
		     dx != 0 || dy != 0;
		     i++, dx = x_offsets[i], dy = y_offsets[i]) {
			y = fy + dy;
			x = fx + dx;

			/* Skip illegal locations */
			if (!square_in_bounds_fully(c, y, x)) continue;

			/* Skip occupied locations */
			if (!square_isempty(c, y, x)) continue;

			/* Check for hidden, available grid */
			if (!square_isview(c, y, x) &&
				projectable(c, fy, fx, y, x, PROJECT_STOP)) {
				/* Calculate distance from player */
				dis = distance(y, x, py, px);

				/* Remember if closer than previous */
				if (dis < gdis && dis >= min) {
					gy = y;
					gx = x;
					gdis = dis;
				}
			}
		}

		/* Check for success */
		if (gdis < 999) {
			/* Good location */
			mon->ty = gy;
			mon->tx = gx;

			/* Found good place */
			return (true);
		}
	}

	/* No good place */
	return (false);
}
예제 #19
0
/**
 * Choose a "safe" location near a monster for it to run toward.
 *
 * A location is "safe" if it can be reached quickly and the player
 * is not able to fire into it (it isn't a "clean shot").  So, this will
 * cause monsters to "duck" behind walls.  Hopefully, monsters will also
 * try to run towards corridor openings if they are in a room.
 *
 * This function may take lots of CPU time if lots of monsters are fleeing.
 *
 * Return true if a safe location is available.
 */
static bool find_safety(struct chunk *c, struct monster *mon)
{
	int fy = mon->fy;
	int fx = mon->fx;

	int py = player->py;
	int px = player->px;

	int i, y, x, dy, dx, d, dis;
	int gy = 0, gx = 0, gdis = 0;

	const int *y_offsets;
	const int *x_offsets;

	/* Start with adjacent locations, spread further */
	for (d = 1; d < 10; d++) {
		/* Get the lists of points with a distance d from (fx, fy) */
		y_offsets = dist_offsets_y[d];
		x_offsets = dist_offsets_x[d];

		/* Check the locations */
		for (i = 0, dx = x_offsets[0], dy = y_offsets[0];
		     dx != 0 || dy != 0;
		     i++, dx = x_offsets[i], dy = y_offsets[i]) {
			y = fy + dy;
			x = fx + dx;

			/* Skip illegal locations */
			if (!square_in_bounds_fully(c, y, x)) continue;

			/* Skip locations in a wall */
			if (!square_ispassable(c, y, x)) continue;

			/* Ignore grids very far from the player */
			if (c->squares[y][x].scent < c->squares[py][px].scent) continue;

			/* Ignore too-distant grids */
			if (c->squares[y][x].noise > c->squares[fy][fx].noise + 2 * d)
				continue;

			/* Ignore lava if they can't handle the heat */
			if (square_isfiery(c, y, x) &&
				!rf_has(mon->race->flags, RF_IM_FIRE))
				continue;

			/* Check for absence of shot (more or less) */
			if (!square_isview(c, y, x)) {
				/* Calculate distance from player */
				dis = distance(y, x, py, px);

				/* Remember if further than previous */
				if (dis > gdis) {
					gy = y;
					gx = x;
					gdis = dis;
				}
			}
		}

		/* Check for success */
		if (gdis > 0) {
			/* Good location */
			mon->ty = gy;
			mon->tx = gx;

			/* Found safe place */
			return (true);
		}
	}

	/* No safe place */
	return (false);
}
예제 #20
0
파일: mon-move.c 프로젝트: myshkin/angband
/*
 * Choose a "safe" location near a monster for it to run toward.
 *
 * A location is "safe" if it can be reached quickly and the player
 * is not able to fire into it (it isn't a "clean shot").  So, this will
 * cause monsters to "duck" behind walls.  Hopefully, monsters will also
 * try to run towards corridor openings if they are in a room.
 *
 * This function may take lots of CPU time if lots of monsters are fleeing.
 *
 * Return TRUE if a safe location is available.
 */
static bool find_safety(struct chunk *c, struct monster *m_ptr)
{
	int fy = m_ptr->fy;
	int fx = m_ptr->fx;

	int py = player->py;
	int px = player->px;

	int i, y, x, dy, dx, d, dis;
	int gy = 0, gx = 0, gdis = 0;

	const int *y_offsets;
	const int *x_offsets;

	/* Start with adjacent locations, spread further */
	for (d = 1; d < 10; d++)
	{
		/* Get the lists of points with a distance d from (fx, fy) */
		y_offsets = dist_offsets_y[d];
		x_offsets = dist_offsets_x[d];

		/* Check the locations */
		for (i = 0, dx = x_offsets[0], dy = y_offsets[0];
		     dx != 0 || dy != 0;
		     i++, dx = x_offsets[i], dy = y_offsets[i])
		{
			y = fy + dy;
			x = fx + dx;

			/* Skip illegal locations */
			if (!square_in_bounds_fully(cave, y, x)) continue;

			/* Skip locations in a wall */
			if (!square_ispassable(cave, y, x)) continue;

			/* Ignore grids very far from the player */
			if (c->squares[y][x].when < c->squares[py][px].when) continue;

			/* Ignore too-distant grids */
			if (c->squares[y][x].cost > c->squares[fy][fx].cost + 2 * d) continue;

			/* Check for absence of shot (more or less) */
			if (!player_has_los_bold(y,x))
			{
				/* Calculate distance from player */
				dis = distance(y, x, py, px);

				/* Remember if further than previous */
				if (dis > gdis)
				{
					gy = y;
					gx = x;
					gdis = dis;
				}
			}
		}

		/* Check for success */
		if (gdis > 0)
		{
			/* Good location */
			m_ptr->ty = gy;
			m_ptr->tx = gx;

			/* Found safe place */
			return (TRUE);
		}
	}

	/* No safe place */
	return (FALSE);
}
예제 #21
0
void calc_cave_distances(int **cave_dist)
{
	int dist, i;
	int oy, ox, ty, tx, d;

	/* Squares with distance from player of n - 1 */
	int d_x_old[DIST_MAX];
	int d_y_old[DIST_MAX];
	int d_old_max;

	/* Squares with distance from player of n */
	int d_x_new[DIST_MAX];
	int d_y_new[DIST_MAX];
	int d_new_max;

	/* Get player location */
	oy = d_y_old[0] = player->py;
	ox = d_x_old[0] = player->px;
	d_old_max = 1;

	/* Distance from player starts at 0 */
	dist = 0;

	/* Assign the distance value to the first square (player) */
	cave_dist[oy][ox] = dist;

	do {
		d_new_max = 0;
		dist++;

		/* Loop over all visited squares of the previous iteration */
		for (i = 0; i < d_old_max; i++){

			/* Get the square we want to look at */
			oy = d_y_old[i];
			ox = d_x_old[i];

			/* debug
			msg("x: %d y: %d dist: %d %d ",ox,oy,dist-1,i); */

			/* Get all adjacent squares */
			for (d = 0; d < 8; d++) {
				/* Adjacent square location */
				ty = oy + ddy_ddd[d];
				tx = ox + ddx_ddd[d];

				if (!(square_in_bounds_fully(cave, ty, tx))) continue;

				/* Have we been here before? */
				if (cave_dist[ty][tx] >= 0) continue;

				/* Is it a wall? */
				if (square_iswall(cave, ty, tx)) continue;

				/* Add the new location */
				d_y_new[d_new_max] = ty;
				d_x_new[d_new_max] = tx;

				/* Assign the distance to that spot */
				cave_dist[ty][tx] = dist;

				d_new_max++;

				/* debug
				msg("x: %d y: %d dist: %d ",tx,ty,dist); */
			}
		}

		/* Copy the new distance list to the old one */
		for (i = 0; i < d_new_max; i++) {
			d_y_old[i] = d_y_new[i];
			d_x_old[i] = d_x_new[i];
		}
		d_old_max = d_new_max;

	} while ((d_old_max > 0) || dist == DIST_MAX);
}
예제 #22
0
파일: obj-pile.c 프로젝트: fizzix/angband
/**
 * Find a grid near the given one for an object to fall on
 *
 * We check several locations to see if we can find a location at which
 * the object can combine, stack, or be placed.  Artifacts will try very
 * hard to be placed, including "teleporting" to a useful grid if needed.
 *
 * If no appropriate grid is found, the given grid is unchanged
 */
static void drop_find_grid(struct object *drop, int *y, int *x)
{
	int best_score = -1;
	int best_y = *y;
	int best_x = *x;
	int i, dy, dx;
	struct object *obj;

	/* Scan local grids */
	for (dy = -3; dy <= 3; dy++) {
		for (dx = -3; dx <= 3; dx++) {
			bool combine = false;
			int dist = (dy * dy) + (dx * dx);
			int ty = *y + dy;
			int tx = *x + dx;
			int num_shown = 0;
			int num_ignored = 0;
			int score;

			/* Lots of reasons to say no */
			if ((dist > 10) ||
				!square_in_bounds_fully(cave, ty, tx) ||
				!los(cave, *y, *x, ty, tx) ||
				!square_isfloor(cave, ty, tx) ||
				square_isplayertrap(cave, ty, tx) ||
				square_iswarded(cave, ty, tx))
				continue;

			/* Analyse the grid for carrying the new object */
			for (obj = square_object(cave, ty, tx); obj; obj = obj->next) {
				/* Check for possible combination */
				if (object_similar(obj, drop, OSTACK_FLOOR))
					combine = true;

				/* Count objects */
				if (!ignore_item_ok(obj))
					num_shown++;
				else
					num_ignored++;
			}
			if (!combine)
				num_shown++;

			/* Disallow if the stack size is too big */
			if ((OPT(player, birth_stacking) && (num_shown > 1)) ||
				((num_shown + num_ignored) > z_info->floor_size &&
				 !floor_get_oldest_ignored(ty, tx)))
				continue;

			/* Score the location based on how close and how full the grid is */
			score = 1000 - (dist + num_shown * 5);

			if ((score < best_score) || ((score == best_score) && one_in_(2)))
				continue;

			best_score = score;
			best_y = ty;
			best_x = tx;
		}
	}

	/* Return if we have a score, otherwise fail or try harder for artifacts */
	if (best_score >= 0) {
		*y = best_y;
		*x = best_x;
		return;
	} else if (!drop->artifact) {
		return;
	}
	for (i = 0; i < 2000; i++) {
		/* Start bouncing from grid to grid, stopping if we find an empty one */
		if (i < 1000) {
			best_y = rand_spread(best_y, 1);
			best_x = rand_spread(best_x, 1);
		} else {
			/* Now go to purely random locations */
			best_y = randint0(cave->height);
			best_x = randint0(cave->width);
		}
		if (square_canputitem(cave, best_y, best_x)) {
			*y = best_y;
			*x = best_x;
			return;
		}
	}
}