/* * Count the number of "corridor" grids adjacent to the given grid. * * Note -- Assumes "in_bounds(y1, x1)" * * XXX XXX This routine currently only counts actual "empty floor" * grids which are not in rooms. We might want to also count stairs, * open doors, closed doors, etc. */ static int next_to_corr(int y1, int x1) { int i, y, x, k = 0; cave_type *c_ptr; /* Scan adjacent grids */ for (i = 0; i < 4; i++) { /* Extract the location */ y = y1 + ddy_ddd[i]; x = x1 + ddx_ddd[i]; /* Access the grid */ c_ptr = &cave[y][x]; /* Skip non floors */ if (cave_have_flag_grid(c_ptr, FF_WALL)) continue; /* Skip non "empty floor" grids */ if (!is_floor_grid(c_ptr)) continue; /* Skip grids inside rooms */ if (c_ptr->info & (CAVE_ROOM)) continue; /* Count these grids */ k++; } /* Return the number of corridors */ return (k); }
static bool _get_loc(int set, int* x, int *y) { int dummy = 0; while (dummy < SAFE_MAX_ATTEMPTS) { bool room; cave_type *c_ptr; dummy++; *x = randint0(cur_wid); *y = randint0(cur_hgt); c_ptr = &cave[*y][*x]; if (!is_floor_grid(c_ptr) || c_ptr->o_idx || c_ptr->m_idx) continue; if (player_bold(*y, *x)) continue; room = (cave[*y][*x].info & CAVE_ROOM) ? TRUE : FALSE; if (set == ALLOC_SET_CORR && room) continue; if (set == ALLOC_SET_ROOM && !room) continue; return TRUE; } return FALSE; }
/* * Create up to "num" objects near the given coordinates * Only really called by some of the "vault" routines. */ void vault_objects(int y, int x, int num) { int dummy = 0; int i = 0, j = y, k = x; cave_type *c_ptr; /* Attempt to place 'num' objects */ for (; num > 0; --num) { /* Try up to 11 spots looking for empty space */ for (i = 0; i < 11; ++i) { /* Pick a random location */ while (dummy < SAFE_MAX_ATTEMPTS) { j = rand_spread(y, 2); k = rand_spread(x, 3); dummy++; if (!in_bounds(j, k)) continue; break; } if (dummy >= SAFE_MAX_ATTEMPTS) { if (cheat_room) { msg_print("Warning! Could not place vault object!"); } } /* Require "clean" floor space */ c_ptr = &cave[j][k]; if (!is_floor_grid(c_ptr) || c_ptr->o_idx) continue; /* Place an item */ if (randint0(100) < 75) { place_object(j, k, 0L); } /* Place gold */ else { place_gold(j, k); } /* Placement accomplished */ break; } } }
/* * Helper function for alloc_stairs(). * * Is this a good location for stairs? */ static bool alloc_stairs_aux(int y, int x, int walls) { /* Access the grid */ cave_type *c_ptr = &cave[y][x]; /* Require "naked" floor grid */ if (!is_floor_grid(c_ptr)) return FALSE; if (pattern_tile(y, x)) return FALSE; if (c_ptr->o_idx || c_ptr->m_idx) return FALSE; /* Require a certain number of adjacent walls */ if (next_to_walls(y, x) < walls) return FALSE; return TRUE; }
/* * Place an up/down staircase at given location */ void place_random_stairs(int y, int x) { bool up_stairs = TRUE; bool down_stairs = TRUE; cave_type *c_ptr; /* Paranoia */ c_ptr = &cave[y][x]; if (!is_floor_grid(c_ptr) || c_ptr->o_idx) return; /* Town */ if (!dun_level) up_stairs = FALSE; /* Ironman */ if (ironman_downward) up_stairs = FALSE; /* Bottom */ if (dun_level >= d_info[dungeon_type].maxdepth) down_stairs = FALSE; /* Quest-level */ if (quest_number(dun_level) && (dun_level > 1)) down_stairs = FALSE; /* We can't place both */ if (down_stairs && up_stairs) { /* Choose a staircase randomly */ if (randint0(100) < 50) up_stairs = FALSE; else down_stairs = FALSE; } /* Place the stairs */ if (up_stairs) place_up_stairs(y, x); else if (down_stairs) place_down_stairs(y, x); }
/* * Place a trap with a given displacement of point */ void vault_trap_aux(int y, int x, int yd, int xd) { int count = 0, y1 = y, x1 = x; int dummy = 0; cave_type *c_ptr; /* Place traps */ for (count = 0; count <= 5; count++) { /* Get a location */ while (dummy < SAFE_MAX_ATTEMPTS) { y1 = rand_spread(y, yd); x1 = rand_spread(x, xd); dummy++; if (!in_bounds(y1, x1)) continue; break; } if (dummy >= SAFE_MAX_ATTEMPTS) { if (cheat_room) { msg_print("Warning! Could not place vault trap!"); } } /* Require "naked" floor grids */ c_ptr = &cave[y1][x1]; if (!is_floor_grid(c_ptr) || c_ptr->o_idx || c_ptr->m_idx) continue; /* Place the trap */ place_trap(y1, x1); /* Done */ break; } }
/* * This routine maps a path from (x1, y1) to (x2, y2) avoiding SOLID walls. * Permanent rock is ignored in this path finding- sometimes there is no * path around anyway -so there will be a crash if we try to find one. * This routine is much like the river creation routine in Zangband. * It works by dividing a line segment into two. The segments are divided * until they are less than "cutoff" - when the corresponding routine from * "short_seg_hack" is called. * Note it is VERY important that the "stop if hit another passage" logic * stays as is. Without this the dungeon turns into Swiss Cheese... */ bool build_tunnel2(int x1, int y1, int x2, int y2, int type, int cutoff) { int x3, y3, dx, dy; int changex, changey; int length; int i; bool retval, firstsuccede; cave_type *c_ptr; length = distance(x1, y1, x2, y2); if (length > cutoff) { /* * Divide path in half and call routine twice. */ dx = (x2 - x1) / 2; dy = (y2 - y1) / 2; /* perturbation perpendicular to path */ changex = (randint0(abs(dy) + 2) * 2 - abs(dy) - 1) / 2; /* perturbation perpendicular to path */ changey = (randint0(abs(dx) + 2) * 2 - abs(dx) - 1) / 2; /* Work out "mid" ponit */ x3 = x1 + dx + changex; y3 = y1 + dy + changey; /* See if in bounds - if not - do not perturb point */ if (!in_bounds(y3, x3)) { x3 = (x1 + x2) / 2; y3 = (y1 + y2) / 2; } /* cache c_ptr */ c_ptr = &cave[y3][x3]; if (is_solid_grid(c_ptr)) { /* move midpoint a bit to avoid problem. */ i = 50; dy = 0; dx = 0; while ((i > 0) && is_solid_bold(y3 + dy, x3 + dx)) { dy = randint0(3) - 1; dx = randint0(3) - 1; if (!in_bounds(y3 + dy, x3 + dx)) { dx = 0; dy = 0; } i--; } if (i == 0) { /* Failed for some reason: hack - ignore the solidness */ place_outer_bold(y3, x3); dx = 0; dy = 0; } y3 += dy; x3 += dx; c_ptr = &cave[y3][x3]; } if (is_floor_grid(c_ptr)) { if (build_tunnel2(x1, y1, x3, y3, type, cutoff)) { if ((cave[y3][x3].info & CAVE_ROOM) || (randint1(100) > 95)) { /* do second half only if works + if have hit a room */ retval = build_tunnel2(x3, y3, x2, y2, type, cutoff); } else { /* have hit another tunnel - make a set of doors here */ retval = FALSE; /* Save the door location */ if (dun->door_n < DOOR_MAX) { dun->door[dun->door_n].y = y3; dun->door[dun->door_n].x = x3; dun->door_n++; } else return FALSE; } firstsuccede = TRUE; } else { /* false- didn't work all the way */ retval = FALSE; firstsuccede = FALSE; } } else { /* tunnel through walls */ if (build_tunnel2(x1, y1, x3, y3, type, cutoff)) { retval = build_tunnel2(x3, y3, x2, y2, type, cutoff); firstsuccede = TRUE; } else { /* false- didn't work all the way */ retval = FALSE; firstsuccede = FALSE; } } if (firstsuccede) { /* only do this if the first half has worked */ set_tunnel(&x3, &y3, TRUE); } /* return value calculated above */ return retval; } else { /* Do a short segment */ retval = TRUE; short_seg_hack(x1, y1, x2, y2, type, 0, &retval); /* Hack - ignore return value so avoid infinite loops */ return TRUE; } }
/* * Allocates some objects (using "place" and "type") */ static void alloc_object(int set, int typ, int num) { int y = 0, x = 0, k; int dummy = 0; cave_type *c_ptr; /* A small level has few objects. */ num = num * cur_hgt * cur_wid / (MAX_HGT*MAX_WID) +1; /* Place some objects */ for (k = 0; k < num; k++) { /* Pick a "legal" spot */ while (dummy < SAFE_MAX_ATTEMPTS) { bool room; dummy++; /* Location */ y = randint0(cur_hgt); x = randint0(cur_wid); c_ptr = &cave[y][x]; /* Require "naked" floor grid */ if (!is_floor_grid(c_ptr) || c_ptr->o_idx || c_ptr->m_idx) continue; /* Avoid player location */ if (player_bold(y, x)) continue; /* Check for "room" */ room = (cave[y][x].info & CAVE_ROOM) ? TRUE : FALSE; /* Require corridor? */ if ((set == ALLOC_SET_CORR) && room) continue; /* Require room? */ if ((set == ALLOC_SET_ROOM) && !room) continue; /* Accept it */ break; } if (dummy >= SAFE_MAX_ATTEMPTS) { if (cheat_room) { #ifdef JP msg_print("警告!アイテムを配置できません!"); #else msg_print("Warning! Could not place object!"); #endif } return; } /* Place something */ switch (typ) { case ALLOC_TYP_RUBBLE: { place_rubble(y, x); cave[y][x].info &= ~(CAVE_FLOOR); break; } case ALLOC_TYP_TRAP: { place_trap(y, x); cave[y][x].info &= ~(CAVE_FLOOR); break; } case ALLOC_TYP_GOLD: { place_gold(y, x); break; } case ALLOC_TYP_OBJECT: { place_object(y, x, 0L); break; } } } }