/** * Place some staircases near walls. * \param c the current chunk * \param feat the stair terrain type * \param num number of staircases to place * \param walls number of walls to surround the stairs (negotiable) */ void alloc_stairs(struct chunk *c, int feat, int num) { int i; /* Place "num" stairs */ for (i = 0; i < num; i++) { int y, x; bool done = false; /* Find the best possible place for the stairs */ if (cave_find_in_range(c, &y, 1, c->height - 2, &x, 1, c->width - 2, square_suits_stairs_well)) { place_stairs(c, y, x, feat); } else if (cave_find_in_range(c, &y, 1, c->height - 2, &x, 1, c->width - 2, square_suits_stairs_ok)) { place_stairs(c, y, x, feat); } else { int walls = 6; /* Gradually reduce number of walls if having trouble */ while (!done) { int j; /* Try hard to find a square with the given number of walls */ for (j = 0; j < 1000; j++) { int total_walls = 0; cave_find_in_range(c, &y, 1, c->height - 2, &x, 1, c->width - 2, square_isempty); if (square_isvault(c, y, x)|| square_isno_stairs(c, y, x)) { continue; } total_walls = square_num_walls_adjacent(c, y, x) + square_num_walls_diagonal(c, y, x); if (total_walls == walls) { place_stairs(c, y, x, feat); done = true; break; } } /* Require fewer walls */ if (walls) walls--; } } } }
/** * Locate a grid nearby (y0, x0) within +/- yd, xd. * \param c current chunk * \param y found y co-ordinate * \param y0 starting y co-ordinate * \param yd y-range * \param x found x co-ordinate * \param x0 starting x co-ordinate * \param xd x-range * \return success */ bool find_nearby_grid(struct chunk *c, int *y, int y0, int yd, int *x, int x0, int xd) { int y1 = y0 - yd; int x1 = x0 - xd; int y2 = y0 + yd + 1; int x2 = x0 + xd + 1; return cave_find_in_range(c, y, y1, y2, x, x1, x2, square_in_bounds_fully); }
/** * Determine whether the given coordinate is a valid starting location. * \param c current chunk * \param y co-ordinates * \param x co-ordinates * \return success */ static bool find_start(struct chunk *c, int *y, int *x) { /* Find the best possible place */ if (cave_find_in_range(c, y, 1, c->height - 2, x, 1, c->width - 2, square_suits_stairs_well)) { return true; } else if (cave_find_in_range(c, y, 1, c->height - 2, x, 1, c->width - 2, square_suits_stairs_ok)) { return true; } else { int walls = 6; /* Gradually reduce number of walls if having trouble */ while (walls >= 0) { int j; /* Try hard to find a square with the given number of walls */ for (j = 0; j < 10000; j++) { int total_walls = 0; cave_find_in_range(c, y, 1, c->height - 2, x, 1, c->width - 2, square_isempty); if (square_isvault(c, *y, *x)|| square_isno_stairs(c, *y, *x)) { continue; } total_walls = square_num_walls_adjacent(c, *y, *x) + square_num_walls_diagonal(c, *y, *x); if (total_walls == walls) { return true; } } walls--; } } return false; }
/** * 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 */ cave_find_in_range(c, &y, 0, c->height, &x, 0, c->width, square_isstart); /* Create stairs the player came down if allowed and necessary */ if (OPT(birth_no_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); }
/** * Locate an empty square for y1 <= y < y2, x1 <= x < x2. * \param c current chunk * \param y found y co-ordinate * \param y1 y-range * \param y2 y-range * \param x found x co-ordinate * \param x1 x-range * \param x2 x-range * \return success */ bool find_empty_range(struct chunk *c, int *y, int y1, int y2, int *x, int x1, int x2) { return cave_find_in_range(c, y, y1, y2, x, x1, x2, square_isempty); }