/*! * @brief 階段移動先のフロアが生成できない時に簡単な行き止まりマップを作成する / Builds the dead end * @return なし */ static void build_dead_end(void) { int x,y; /* Clear and empty the cave */ clear_cave(); /* Fill the arrays of floors and walls in the good proportions */ set_floor_and_wall(0); /* Smallest area */ cur_hgt = SCREEN_HGT; cur_wid = SCREEN_WID; /* Filled with permanent walls */ for (y = 0; y < MAX_HGT; y++) { for (x = 0; x < MAX_WID; x++) { /* Create "solid" perma-wall */ place_solid_perm_bold(y, x); } } /* Place at center of the floor */ p_ptr->y = cur_hgt / 2; p_ptr->x = cur_wid / 2; /* Give one square */ place_floor_bold(p_ptr->y, p_ptr->x); wipe_generate_cave_flags(); }
/* * Place a random type of normal door at the given location. */ void place_closed_door(int y, int x, int type) { int tmp; s16b feat = feat_none; if (d_info[dungeon_type].flags1 & DF1_NO_DOORS) { place_floor_bold(y, x); return; } /* Choose an object */ tmp = randint0(400); /* Closed doors (300/400) */ if (tmp < 300) { /* Create closed door */ feat = feat_door[type].closed; } /* Locked doors (99/400) */ else if (tmp < 399) { /* Create locked door */ feat = feat_locked_door_random(type); } /* Stuck doors (1/400) */ else { /* Create jammed door */ feat = feat_jammed_door_random(type); } if (feat != feat_none) { cave_set_feat(y, x, feat); /* Now it is not floor */ cave[y][x].info &= ~(CAVE_MASK); } else { place_floor_bold(y, x); } }
/* * Make an empty square floor, for the middle of rooms */ void place_floor(int x1, int x2, int y1, int y2, bool light) { int x, y; /* Place a full floor under the room */ for (y = y1 - 1; y <= y2 + 1; y++) { for (x = x1 - 1; x <= x2 + 1; x++) { place_floor_bold(y, x); add_cave_info(y, x, CAVE_ROOM); if (light) add_cave_info(y, x, CAVE_GLOW); } } }
/* Set a square to be floor. (Includes range checking.) */ void set_floor(int x, int y) { if (!in_bounds(y, x)) { /* Out of bounds */ return; } if (cave[y][x].info & CAVE_ROOM) { /* A room border don't touch. */ return; } /* Set to be floor if is a wall (don't touch lakes). */ if (is_extra_bold(y, x)) place_floor_bold(y, x); }
/* * This routine adds the square to the tunnel * It also checks for SOLID walls - and returns a nearby * non-SOLID square in (x,y) so that a simple avoiding * routine can be used. The returned boolean value reflects * whether or not this routine hit a SOLID wall. * * "affectwall" toggles whether or not this new square affects * the boundaries of rooms. - This is used by the catacomb * routine. */ static bool set_tunnel(int *x, int *y, bool affectwall) { int i, j, dx, dy; cave_type *c_ptr = &cave[*y][*x]; if (!in_bounds(*y, *x)) return TRUE; if (is_inner_grid(c_ptr)) { return TRUE; } if (is_extra_bold(*y,*x)) { /* Save the tunnel location */ if (dun->tunn_n < TUNN_MAX) { dun->tunn[dun->tunn_n].y = *y; dun->tunn[dun->tunn_n].x = *x; dun->tunn_n++; return TRUE; } else return FALSE; } if (is_floor_bold(*y, *x)) { /* Don't do anything */ return TRUE; } if (is_outer_grid(c_ptr) && affectwall) { /* Save the wall location */ if (dun->wall_n < WALL_MAX) { dun->wall[dun->wall_n].y = *y; dun->wall[dun->wall_n].x = *x; dun->wall_n++; } else return FALSE; /* Forbid re-entry near this piercing */ for (j = *y - 1; j <= *y + 1; j++) { for (i = *x - 1; i <= *x + 1; i++) { /* Convert adjacent "outer" walls as "solid" walls */ if (is_outer_bold(j, i)) { /* Change the wall to a "solid" wall */ place_solid_noperm_bold(j, i); } } } /* Clear mimic type */ cave[*y][*x].mimic = 0; place_floor_bold(*y, *x); return TRUE; } if (is_solid_grid(c_ptr) && affectwall) { /* cannot place tunnel here - use a square to the side */ /* find usable square and return value in (x,y) */ i = 50; dy = 0; dx = 0; while ((i > 0) && is_solid_bold(*y + dy, *x + dx)) { dy = randint0(3) - 1; dx = randint0(3) - 1; if (!in_bounds(*y + dy, *x + dx)) { dx = 0; dy = 0; } i--; } if (i == 0) { /* Failed for some reason: hack - ignore the solidness */ place_outer_grid(c_ptr); dx = 0; dy = 0; } /* Give new, acceptable coordinate. */ *x = *x + dx; *y = *y + dy; return FALSE; } return TRUE; }
/* * Place a random type of door at the given location */ void place_random_door(int y, int x, bool room) { int tmp, type; s16b feat = feat_none; cave_type *c_ptr = &cave[y][x]; /* Initialize mimic info */ c_ptr->mimic = 0; /* if (dungeon_type == DUNGEON_ARENA) { place_rubble_bold(y, x); return; }*/ if (d_info[dungeon_type].flags1 & DF1_NO_DOORS) { place_floor_bold(y, x); return; } type = ((d_info[dungeon_type].flags1 & DF1_CURTAIN) && one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN : ((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR); /* Choose an object */ tmp = randint0(1000); /* Open doors (300/1000) */ if (tmp < 300) { /* Create open door */ feat = feat_door[type].open; } /* Broken doors (100/1000) */ else if (tmp < 400) { /* Create broken door */ feat = feat_door[type].broken; } /* Secret doors (200/1000) */ else if (tmp < 600) { /* Create secret door */ place_closed_door(y, x, type); if (type != DOOR_CURTAIN) { /* Hide. If on the edge of room, use outer wall. */ c_ptr->mimic = room ? feat_wall_outer : fill_type[randint0(100)]; /* Floor type terrain cannot hide a door */ if (feat_supports_los(c_ptr->mimic) && !feat_supports_los(c_ptr->feat)) { if (have_flag(f_info[c_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[c_ptr->mimic].flags, FF_CAN_FLY)) { c_ptr->feat = one_in_(2) ? c_ptr->mimic : floor_type[randint0(100)]; } c_ptr->mimic = 0; } } } /* Closed, locked, or stuck doors (400/1000) */ else place_closed_door(y, x, type); if (tmp < 400) { if (feat != feat_none) { set_cave_feat(y, x, feat); } else { place_floor_bold(y, x); } } delete_monster(y, x); }
/* * Generate a new dungeon level * * Note that "dun_body" adds about 4000 bytes of memory to the stack. */ static bool cave_gen(void) { int i, k, y, x; dun_data dun_body; /* Global data */ dun = &dun_body; dun->destroyed = FALSE; dun->empty_level = FALSE; dun->cavern = FALSE; dun->laketype = 0; /* Fill the arrays of floors and walls in the good proportions */ set_floor_and_wall(dungeon_type); /* Prepare allocation table */ get_mon_num_prep(get_monster_hook(), NULL); /* Randomize the dungeon creation values */ dun_tun_rnd = rand_range(DUN_TUN_RND_MIN, DUN_TUN_RND_MAX); dun_tun_chg = rand_range(DUN_TUN_CHG_MIN, DUN_TUN_CHG_MAX); dun_tun_con = rand_range(DUN_TUN_CON_MIN, DUN_TUN_CON_MAX); dun_tun_pen = rand_range(DUN_TUN_PEN_MIN, DUN_TUN_PEN_MAX); dun_tun_jct = rand_range(DUN_TUN_JCT_MIN, DUN_TUN_JCT_MAX); /* Actual maximum number of rooms on this level */ dun->row_rooms = cur_hgt / BLOCK_HGT; dun->col_rooms = cur_wid / BLOCK_WID; /* Initialize the room table */ for (y = 0; y < dun->row_rooms; y++) { for (x = 0; x < dun->col_rooms; x++) { dun->room_map[y][x] = FALSE; } } /* No rooms yet */ dun->cent_n = 0; /* Empty arena levels */ if (ironman_empty_levels || ((d_info[dungeon_type].flags1 & DF1_ARENA) && (empty_levels && one_in_(EMPTY_LEVEL)))) { dun->empty_level = TRUE; if (cheat_room) msg_print("Arena level."); } if (dun->empty_level) { /* Start with floors */ for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { place_floor_bold(y, x); } } /* Special boundary walls -- Top and bottom */ for (x = 0; x < cur_wid; x++) { place_extra_bold(0, x); place_extra_bold(cur_hgt - 1, x); } /* Special boundary walls -- Left and right */ for (y = 1; y < (cur_hgt - 1); y++) { place_extra_bold(y, 0); place_extra_bold(y, cur_wid - 1); } } else { /* Start with walls */ for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { place_extra_bold(y, x); } } } /* Generate various caverns and lakes */ gen_caverns_and_lakes(); /* Build maze */ if (d_info[dungeon_type].flags1 & DF1_MAZE) { build_maze_vault(cur_wid/2-1, cur_hgt/2-1, cur_wid-4, cur_hgt-4, FALSE); /* Place 3 or 4 down stairs near some walls */ if (!alloc_stairs(feat_down_stair, rand_range(4, 5), 3)) return FALSE; /* Place 1 or 2 up stairs near some walls */ if (!alloc_stairs(feat_up_stair, 1, 2)) return FALSE; } /* Build some rooms */ else { int tunnel_fail_count = 0; /* * Build each type of room in turn until we cannot build any more. */ if (!generate_rooms()) return FALSE; /* Make a hole in the dungeon roof sometimes at level 1 But not in Angband. See Issue #3 */ if (dun_level == 1 && dungeon_type != DUNGEON_ANGBAND) { while (one_in_(DUN_MOS_DEN)) { place_trees(randint1(cur_wid - 2), randint1(cur_hgt - 2)); } } /* Destroy the level if necessary */ if (dun->destroyed) destroy_level(); /* Hack -- Add some rivers */ if (one_in_(7) && (randint1(dun_level) > 5)) { int feat1 = 0, feat2 = 0; /* Choose water or lava */ if ( randint1(MAX_DEPTH * 2) - 1 > dun_level && ( (d_info[dungeon_type].flags1 & DF1_WATER_RIVER) || (no_wilderness && one_in_(3)) ) ) { feat1 = feat_deep_water; feat2 = feat_shallow_water; } else if (d_info[dungeon_type].flags1 & DF1_LAVA_RIVER) { feat1 = feat_deep_lava; feat2 = feat_shallow_lava; } else feat1 = 0; if (feat1) { feature_type *f_ptr = &f_info[feat1]; /* Only add river if matches lake type or if have no lake at all */ if (((dun->laketype == LAKE_T_LAVA) && have_flag(f_ptr->flags, FF_LAVA)) || ((dun->laketype == LAKE_T_WATER) && have_flag(f_ptr->flags, FF_WATER)) || !dun->laketype) { add_river(feat1, feat2); } } } /* Hack -- Scramble the room order */ for (i = 0; i < dun->cent_n; i++) { int ty, tx; int pick = rand_range(0, i); ty = dun->cent[i].y; tx = dun->cent[i].x; dun->cent[i].y = dun->cent[pick].y; dun->cent[i].x = dun->cent[pick].x; dun->cent[pick].y = ty; dun->cent[pick].x = tx; } /* Start with no tunnel doors */ dun->door_n = 0; /* Hack -- connect the first room to the last room */ y = dun->cent[dun->cent_n-1].y; x = dun->cent[dun->cent_n-1].x; /* Connect all the rooms together */ for (i = 0; i < dun->cent_n; i++) { int j; /* Reset the arrays */ dun->tunn_n = 0; dun->wall_n = 0; /* Connect the room to the previous room */ if (randint1(dun_level) > d_info[dungeon_type].tunnel_percent) { /* make cave-like tunnel */ (void)build_tunnel2(dun->cent[i].x, dun->cent[i].y, x, y, 2, 2); } else { /* make normal tunnel */ if (!build_tunnel(dun->cent[i].y, dun->cent[i].x, y, x)) tunnel_fail_count++; } if (tunnel_fail_count >= 2) return FALSE; /* Turn the tunnel into corridor */ for (j = 0; j < dun->tunn_n; j++) { cave_type *c_ptr; feature_type *f_ptr; /* Access the grid */ y = dun->tunn[j].y; x = dun->tunn[j].x; /* Access the grid */ c_ptr = &cave[y][x]; f_ptr = &f_info[c_ptr->feat]; /* Clear previous contents (if not a lake), add a floor */ if (!have_flag(f_ptr->flags, FF_MOVE) || (!have_flag(f_ptr->flags, FF_WATER) && !have_flag(f_ptr->flags, FF_LAVA))) { /* Clear mimic type */ c_ptr->mimic = 0; place_floor_grid(c_ptr); } } /* Apply the piercings that we found */ for (j = 0; j < dun->wall_n; j++) { cave_type *c_ptr; /* Access the grid */ y = dun->wall[j].y; x = dun->wall[j].x; /* Access the grid */ c_ptr = &cave[y][x]; /* Clear mimic type */ c_ptr->mimic = 0; /* Clear previous contents, add up floor */ place_floor_grid(c_ptr); /* Occasional doorway */ if ((randint0(100) < dun_tun_pen) && !(d_info[dungeon_type].flags1 & DF1_NO_DOORS)) { /* Place a random door */ place_random_door(y, x, TRUE); } } /* Remember the "previous" room */ y = dun->cent[i].y; x = dun->cent[i].x; } /* Place intersection doors */ for (i = 0; i < dun->door_n; i++) { /* Extract junction location */ y = dun->door[i].y; x = dun->door[i].x; /* Try placing doors */ try_door(y, x - 1); try_door(y, x + 1); try_door(y - 1, x); try_door(y + 1, x); } if (!alloc_stairs(feat_down_stair, rand_range(4, 5), 3)) return FALSE; /* Place 1 or 2 up stairs near some walls */ if (!alloc_stairs(feat_up_stair, rand_range(1, 2), 3)) return FALSE; } if (!dun->laketype) { if (d_info[dungeon_type].stream2) { /* Hack -- Add some quartz streamers */ for (i = 0; i < DUN_STR_QUA; i++) { build_streamer(d_info[dungeon_type].stream2, DUN_STR_QC); } } if (d_info[dungeon_type].stream1) { /* Hack -- Add some magma streamers */ for (i = 0; i < DUN_STR_MAG; i++) { build_streamer(d_info[dungeon_type].stream1, DUN_STR_MC); } } } /* Special boundary walls -- Top and bottom */ for (x = 0; x < cur_wid; x++) { set_bound_perm_wall(&cave[0][x]); set_bound_perm_wall(&cave[cur_hgt - 1][x]); } /* Special boundary walls -- Left and right */ for (y = 1; y < (cur_hgt - 1); y++) { set_bound_perm_wall(&cave[y][0]); set_bound_perm_wall(&cave[y][cur_wid - 1]); } /* Determine the character location */ if (!new_player_spot()) return FALSE; /* Basic "amount" */ k = (dun_level / 3); if (k > 10) k = 10; if (k < 2) k = 2; /* Pick a base number of monsters */ i = d_info[dungeon_type].min_m_alloc_level; /* To make small levels a bit more playable */ if (cur_hgt < MAX_HGT || cur_wid < MAX_WID) { int small_tester = i; i = (i * cur_hgt) / MAX_HGT; i = (i * cur_wid) / MAX_WID; i += 1; if (i > small_tester) i = small_tester; else if (cheat_hear) { msg_format("Reduced monsters base from %d to %d", small_tester, i); } } if (dungeon_type != DUNGEON_ARENA) { i += randint1(8); /* Put some monsters in the dungeon */ for (i = (dun_level < 50 ? (i+k) : (i+k)*6/10); i > 0; i--) { (void)alloc_monster(0, PM_ALLOW_SLEEP); } } /* Place some traps in the dungeon */ alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint1(k*3/2)); /* Put some rubble in corridors (except NO_CAVE dungeon (Castle)) */ if (!(d_info[dungeon_type].flags1 & DF1_NO_CAVE)) alloc_object(ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint1(k)); if (dungeon_type != DUNGEON_ARENA) { /* Put some objects in rooms */ alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3)); /* Put some objects/gold in the dungeon */ alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ITEM, 3)); alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3)); /* Experimental: Guarantee certain objects. Give surprise goodies. */ if (one_in_(2)) alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_FOOD, 1); if (dun_level <= 15) alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_LIGHT, 1); if (dun_level >= 10 && one_in_(2)) alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_RECALL, 1); if (dun_level >= 10 && one_in_(20)) alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_SKELETON, damroll(3, 5)); _mon_give_extra_drop(MFLAG2_DROP_BASIC, 1); _mon_give_extra_drop(MFLAG2_DROP_UTILITY, randint0(4)); if (dun_level > max_dlv[dungeon_type]) _mon_give_extra_drop(MFLAG2_DROP_PRIZE, 1); } /* Set back to default */ object_level = base_level; /* Put the Guardian */ if (!alloc_guardian(TRUE)) return FALSE; if (dun->empty_level && (!one_in_(DARK_EMPTY) || (randint1(100) > dun_level)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)) { /* Lite the cave */ for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { cave[y][x].info |= (CAVE_GLOW); } } } return TRUE; }