Exemple #1
0
/**
 * Check if the monster can occupy a grid safely
 */
static bool monster_hates_grid(struct chunk *c, struct monster *mon, int y,
							   int x)
{
	/* Only some creatures can handle damaging terrain */
	if (square_isdamaging(c, y, x) &&
		!rf_has(mon->race->flags, square_feat(c, y, x)->resist_flag)) {
		return true;
	}
	return false;
}
Exemple #2
0
/**
 * This will push objects off a square.
 *
 * The methodology is to load all objects on the square into a queue. Replace
 * the previous square with a type that does not allow for objects. Drop the
 * objects. Last, put the square back to its original type.
 */
void push_object(int y, int x)
{
	/* Save the original terrain feature */
	struct feature *feat_old = square_feat(cave, y, x);

	struct object *obj = square_object(cave, y, x);

	struct queue *queue = q_new(z_info->floor_size);

	bool glyph = square_iswarded(cave, y, x);

	/* Push all objects on the square, stripped of pile info, into the queue */
	while (obj) {
		struct object *next = obj->next;
		q_push_ptr(queue, obj);

		/* Orphan the object */
		obj->next = NULL;
		obj->prev = NULL;
		obj->iy = 0;
		obj->ix = 0;

		/* Next object */
		obj = next;
	}

	/* Disassociate the objects from the square */
	cave->squares[y][x].obj = NULL;

	/* Set feature to an open door */
	square_force_floor(cave, y, x);
	square_add_door(cave, y, x, false);

	/* Drop objects back onto the floor */
	while (q_len(queue) > 0) {
		/* Take object from the queue */
		obj = q_pop_ptr(queue);

		/* Drop the object */
		drop_near(cave, &obj, 0, y, x, false);
	}

	/* Reset cave feature and rune if needed */
	square_set_feat(cave, y, x, feat_old->fidx);
	if (glyph)
		square_add_ward(cave, y, x);

	q_free(queue);
}
Exemple #3
0
/**
 * Determine if a cave grid is allowed to have player traps in it.
 */
bool square_player_trap_allowed(struct chunk *c, int y, int x)
{
    /*
     * We currently forbid multiple traps in a grid under normal conditions.
     * If this changes, various bits of code elsewhere will have to change too.
     */
    if (square_istrap(c, y, x))
		return false;

    /* We currently forbid traps in a grid with objects. */
    if (square_object(c, y, x))
		return false;

    /* Check the feature trap flag */
    return (tf_has(square_feat(c, y, x)->flags, TF_TRAP));
}
Exemple #4
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 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);
}