X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Frooms.c;h=dbb86f138c03b96b306839d7bb2fd29fa752e715;hb=54facace929e172feabe50f4b973efe056f30d61;hp=8188c82aab6b273374e3376dfd63bba4a116b136;hpb=45ce36c00fc1651e3dc60a56b33b26c100759923;p=hengband%2Fhengband.git diff --git a/src/rooms.c b/src/rooms.c index 8188c82aa..dbb86f138 100644 --- a/src/rooms.c +++ b/src/rooms.c @@ -51,18 +51,22 @@ static room_info_type room_info_normal[ROOM_T_MAX] = {{ 1, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60}, 10}, /*CRYPT */ {{ 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 8}, 20}, /*TRAP_PIT */ {{ 0, 0, 1, 1, 1, 2, 3, 4, 5, 6, 8}, 20}, /*TRAP */ + {{ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2}, 40}, /*GLASS */ + {{ 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3}, 1}, /*ARCADE */ }; /* Build rooms in descending order of difficulty. */ static byte room_build_order[ROOM_T_MAX] = { ROOM_T_GREATER_VAULT, + ROOM_T_ARCADE, ROOM_T_RANDOM_VAULT, ROOM_T_LESSER_VAULT, ROOM_T_TRAP_PIT, ROOM_T_PIT, ROOM_T_NEST, ROOM_T_TRAP, + ROOM_T_GLASS, ROOM_T_INNER_FEAT, ROOM_T_OVAL, ROOM_T_CRYPT, @@ -81,12 +85,13 @@ static void place_locked_door(int y, int x) } else { - set_cave_feat(y, x, FEAT_DOOR_HEAD+randint1(7)); + set_cave_feat(y, x, feat_locked_door_random((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR)); cave[y][x].info &= ~(CAVE_FLOOR); + delete_monster(y, x); } } -static void place_secret_door(int y, int x) +static void place_secret_door(int y, int x, int type) { if (d_info[dungeon_type].flags1 & DF1_NO_DOORS) { @@ -96,20 +101,34 @@ static void place_secret_door(int y, int x) { cave_type *c_ptr = &cave[y][x]; - /* Create secret door */ - place_closed_door(y, x); + if (type == DOOR_DEFAULT) + { + 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); + } - /* Hide by inner wall because this is used in rooms only */ - c_ptr->mimic = feat_wall_inner; + /* Create secret door */ + place_closed_door(y, x, type); - /* Floor type terrain cannot hide a door */ - if (feat_supports_los(c_ptr->mimic) && !feat_supports_los(c_ptr->feat)) + if (type != DOOR_CURTAIN) { - if (have_flag(f_info[c_ptr->mimic].flags, FF_MOVE)) c_ptr->feat = c_ptr->mimic; - c_ptr->mimic = 0; + /* Hide by inner wall because this is used in rooms only */ + c_ptr->mimic = feat_wall_inner; + + /* 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; + } } c_ptr->info &= ~(CAVE_FLOOR); + delete_monster(y, x); } } @@ -139,10 +158,10 @@ static void build_small_room(int x0, int y0) /* Place a secret door on one side */ switch (randint0(4)) { - case 0: place_secret_door(y0, x0 - 1); break; - case 1: place_secret_door(y0, x0 + 1); break; - case 2: place_secret_door(y0 - 1, x0); break; - case 3: place_secret_door(y0 + 1, x0); break; + case 0: place_secret_door(y0, x0 - 1, DOOR_DEFAULT); break; + case 1: place_secret_door(y0, x0 + 1, DOOR_DEFAULT); break; + case 2: place_secret_door(y0 - 1, x0, DOOR_DEFAULT); break; + case 3: place_secret_door(y0 + 1, x0, DOOR_DEFAULT); break; } /* Clear mimic type */ @@ -339,29 +358,17 @@ static bool find_space(int *y, int *x, int height, int width) if (dun->row_rooms < blocks_high) return FALSE; if (dun->col_rooms < blocks_wide) return FALSE; -#if 0 - /* Sometimes, little rooms like to have more space. */ - if (blocks_wide == 2) - { - if (one_in_(3)) blocks_wide = 3; - } - else if (blocks_wide == 1) - { - if (one_in_(2)) blocks_wide = rand_range(2, 3); - } -#endif - /* Initiallize */ candidates = 0; - /* Count the number of varid places */ + /* Count the number of valid places */ for (block_y = dun->row_rooms - blocks_high; block_y >= 0; block_y--) { for (block_x = dun->col_rooms - blocks_wide; block_x >= 0; block_x--) { if (find_space_aux(blocks_high, blocks_wide, block_y, block_x)) { - /* Find a varid place */ + /* Find a valid place */ candidates++; } } @@ -470,6 +477,8 @@ static bool find_space(int *y, int *x, int height, int width) * 12 -- crypts * 13 -- trapped monster pits * 14 -- trapped room + * 15 -- glass room + * 16 -- underground arcade */ @@ -485,6 +494,9 @@ static bool build_type1(void) cave_type *c_ptr; + bool curtain = (d_info[dungeon_type].flags1 & DF1_CURTAIN) && + one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 48 : 512); + /* Pick a room size */ y1 = randint1(4); x1 = randint1(11); @@ -495,7 +507,20 @@ static bool build_type1(void) ysize = y1 + y2 + 1; /* Find and reserve some space in the dungeon. Get center of room. */ - if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE; + if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) + { + /* Limit to the minimum room size, and retry */ + y1 = 1; + x1 = 1; + y2 = 1; + x2 = 1; + + xsize = x1 + x2 + 1; + ysize = y1 + y2 + 1; + + /* Find and reserve some space in the dungeon. Get center of room. */ + if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE; + } /* Choose lite or dark */ light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)); @@ -537,6 +562,30 @@ static bool build_type1(void) } + /* Hack -- Occasional curtained room */ + if (curtain && (y2 - y1 > 2) && (x2 - x1 > 2)) + { + for (y = y1; y <= y2; y++) + { + c_ptr = &cave[y][x1]; + c_ptr->feat = feat_door[DOOR_CURTAIN].closed; + c_ptr->info &= ~(CAVE_MASK); + c_ptr = &cave[y][x2]; + c_ptr->feat = feat_door[DOOR_CURTAIN].closed; + c_ptr->info &= ~(CAVE_MASK); + } + for (x = x1; x <= x2; x++) + { + c_ptr = &cave[y1][x]; + c_ptr->feat = feat_door[DOOR_CURTAIN].closed; + c_ptr->info &= ~(CAVE_MASK); + c_ptr = &cave[y2][x]; + c_ptr->feat = feat_door[DOOR_CURTAIN].closed; + c_ptr->info &= ~(CAVE_MASK); + } + } + + /* Hack -- Occasional pillar room */ if (one_in_(20)) { @@ -590,12 +639,16 @@ static bool build_type1(void) /* Hack -- Occasional divided room */ else if (one_in_(50)) { + bool curtain2 = (d_info[dungeon_type].flags1 & DF1_CURTAIN) && + one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 2 : 128); + if (randint1(100) < 50) { /* Horizontal wall */ for (x = x1; x <= x2; x++) { place_inner_bold(yval, x); + if (curtain2) cave[yval][x].feat = feat_door[DOOR_CURTAIN].closed; } /* Prevent edge of wall from being tunneled */ @@ -608,6 +661,7 @@ static bool build_type1(void) for (y = y1; y <= y2; y++) { place_inner_bold(y, xval); + if (curtain2) cave[y][xval].feat = feat_door[DOOR_CURTAIN].closed; } /* Prevent edge of wall from being tunneled */ @@ -616,6 +670,7 @@ static bool build_type1(void) } place_random_door(yval, xval, TRUE); + if (curtain2) cave[yval][xval].feat = feat_door[DOOR_CURTAIN].closed; } return TRUE; @@ -907,10 +962,10 @@ static bool build_type3(void) /* Place a secret door on the inner room */ switch (randint0(4)) { - case 0: place_secret_door(y1b, xval); break; - case 1: place_secret_door(y2b, xval); break; - case 2: place_secret_door(yval, x1a); break; - case 3: place_secret_door(yval, x2a); break; + case 0: place_secret_door(y1b, xval, DOOR_DEFAULT); break; + case 1: place_secret_door(y2b, xval, DOOR_DEFAULT); break; + case 2: place_secret_door(yval, x1a, DOOR_DEFAULT); break; + case 3: place_secret_door(yval, x2a, DOOR_DEFAULT); break; } /* Place a treasure in the vault */ @@ -954,10 +1009,14 @@ static bool build_type3(void) /* Sometimes shut using secret doors */ if (one_in_(3)) { - place_secret_door(yval, x1a - 1); - place_secret_door(yval, x2a + 1); - place_secret_door(y1b - 1, xval); - place_secret_door(y2b + 1, xval); + int door_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); + + place_secret_door(yval, x1a - 1, door_type); + place_secret_door(yval, x2a + 1, door_type); + place_secret_door(y1b - 1, xval, door_type); + place_secret_door(y2b + 1, xval, door_type); } } @@ -1082,10 +1141,10 @@ static bool build_type4(void) /* Place a secret door */ switch (randint1(4)) { - case 1: place_secret_door(y1 - 1, xval); break; - case 2: place_secret_door(y2 + 1, xval); break; - case 3: place_secret_door(yval, x1 - 1); break; - case 4: place_secret_door(yval, x2 + 1); break; + case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break; + case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break; + case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break; + case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break; } /* Place a monster in the room */ @@ -1100,10 +1159,10 @@ static bool build_type4(void) /* Place a secret door */ switch (randint1(4)) { - case 1: place_secret_door(y1 - 1, xval); break; - case 2: place_secret_door(y2 + 1, xval); break; - case 3: place_secret_door(yval, x1 - 1); break; - case 4: place_secret_door(yval, x2 + 1); break; + case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break; + case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break; + case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break; + case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break; } /* Place another inner room */ @@ -1153,10 +1212,10 @@ static bool build_type4(void) /* Place a secret door */ switch (randint1(4)) { - case 1: place_secret_door(y1 - 1, xval); break; - case 2: place_secret_door(y2 + 1, xval); break; - case 3: place_secret_door(yval, x1 - 1); break; - case 4: place_secret_door(yval, x2 + 1); break; + case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break; + case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break; + case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break; + case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break; } /* Large Inner Pillar */ @@ -1191,6 +1250,10 @@ static bool build_type4(void) /* Occasionally, some Inner rooms */ if (one_in_(3)) { + int door_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); + /* Long horizontal walls */ for (x = xval - 5; x <= xval + 5; x++) { @@ -1207,8 +1270,8 @@ static bool build_type4(void) place_inner_grid(c_ptr); /* Secret doors (random top/bottom) */ - place_secret_door(yval - 3 + (randint1(2) * 2), xval - 3); - place_secret_door(yval - 3 + (randint1(2) * 2), xval + 3); + place_secret_door(yval - 3 + (randint1(2) * 2), xval - 3, door_type); + place_secret_door(yval - 3 + (randint1(2) * 2), xval + 3, door_type); /* Monsters */ vault_monsters(yval, xval - 2, randint1(2)); @@ -1228,10 +1291,10 @@ static bool build_type4(void) /* Place a secret door */ switch (randint1(4)) { - case 1: place_secret_door(y1 - 1, xval); break; - case 2: place_secret_door(y2 + 1, xval); break; - case 3: place_secret_door(yval, x1 - 1); break; - case 4: place_secret_door(yval, x2 + 1); break; + case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break; + case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break; + case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break; + case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break; } /* Maze (really a checkerboard) */ @@ -1264,6 +1327,10 @@ static bool build_type4(void) /* Four small rooms. */ case 5: { + int door_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); + /* Inner "cross" */ for (y = y1; y <= y2; y++) { @@ -1280,18 +1347,18 @@ static bool build_type4(void) if (randint0(100) < 50) { int i = randint1(10); - place_secret_door(y1 - 1, xval - i); - place_secret_door(y1 - 1, xval + i); - place_secret_door(y2 + 1, xval - i); - place_secret_door(y2 + 1, xval + i); + place_secret_door(y1 - 1, xval - i, door_type); + place_secret_door(y1 - 1, xval + i, door_type); + place_secret_door(y2 + 1, xval - i, door_type); + place_secret_door(y2 + 1, xval + i, door_type); } else { int i = randint1(3); - place_secret_door(yval + i, x1 - 1); - place_secret_door(yval - i, x1 - 1); - place_secret_door(yval + i, x2 + 1); - place_secret_door(yval - i, x2 + 1); + place_secret_door(yval + i, x1 - 1, door_type); + place_secret_door(yval - i, x1 - 1, door_type); + place_secret_door(yval + i, x2 + 1, door_type); + place_secret_door(yval - i, x2 + 1, door_type); } /* Treasure, centered at the center of the cross */ @@ -2087,7 +2154,7 @@ static void ang_sort_swap_nest_mon_info(vptr u, vptr v, int a, int b) * "appropriate" non-unique monsters for the nest. * * Note that the "get_mon_num()" function may (rarely) fail, in which - * case the nest will be empty, and will not affect the level rating. + * case the nest will be empty. * * Note that "monster nests" will never contain "unique" monsters. */ @@ -2217,10 +2284,10 @@ static bool build_type5(void) /* Place a secret door */ switch (randint1(4)) { - case 1: place_secret_door(y1 - 1, xval); break; - case 2: place_secret_door(y2 + 1, xval); break; - case 3: place_secret_door(yval, x1 - 1); break; - case 4: place_secret_door(yval, x2 + 1); break; + case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break; + case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break; + case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break; + case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break; } /* Describe */ @@ -2234,15 +2301,6 @@ static bool build_type5(void) #endif } - /* Increase the level rating */ - rating += 10; - - /* (Sometimes) Cause a "special feeling" (for "Monster Nests") */ - if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300)) - { - good_item_flag = TRUE; - } - /* Place some monsters */ for (y = yval - 2; y <= yval + 2; y++) { @@ -2315,7 +2373,7 @@ static bool build_type5(void) * "appropriate" non-unique monsters for the pit. * * Note that the "get_mon_num()" function may (rarely) fail, in which case - * the pit will be empty, and will not effect the level rating. + * the pit will be empty. * * Note that "monster pits" will never contain "unique" monsters. */ @@ -2443,10 +2501,10 @@ static bool build_type6(void) /* Place a secret door */ switch (randint1(4)) { - case 1: place_secret_door(y1 - 1, xval); break; - case 2: place_secret_door(y2 + 1, xval); break; - case 3: place_secret_door(yval, x1 - 1); break; - case 4: place_secret_door(yval, x2 + 1); break; + case 1: place_secret_door(y1 - 1, xval, DOOR_DEFAULT); break; + case 2: place_secret_door(y2 + 1, xval, DOOR_DEFAULT); break; + case 3: place_secret_door(yval, x1 - 1, DOOR_DEFAULT); break; + case 4: place_secret_door(yval, x2 + 1, DOOR_DEFAULT); break; } /* Sort the entries */ @@ -2495,15 +2553,6 @@ static bool build_type6(void) } } - /* Increase the level rating */ - rating += 10; - - /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */ - if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300)) - { - good_item_flag = TRUE; - } - /* Top and bottom rows */ for (x = xval - 9; x <= xval + 9; x++) { @@ -2659,11 +2708,21 @@ static void build_vault(int yval, int xval, int ymax, int xmax, cptr data, place_inner_grid(c_ptr); break; + /* Glass wall (inner) */ + case '$': + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + break; + /* Permanent wall (inner) */ case 'X': - c_ptr->feat = FEAT_PERM_INNER; - c_ptr->info &= ~(CAVE_MASK); - c_ptr->info |= CAVE_INNER; + place_inner_perm_grid(c_ptr); + break; + + /* Permanent glass wall (inner) */ + case 'Y': + place_inner_perm_grid(c_ptr); + c_ptr->feat = feat_permanent_glass_wall; break; /* Treasure/trap */ @@ -2680,7 +2739,18 @@ static void build_vault(int yval, int xval, int ymax, int xmax, cptr data, /* Secret doors */ case '+': - place_secret_door(y, x); + place_secret_door(y, x, DOOR_DEFAULT); + break; + + /* Secret glass doors */ + case '-': + place_secret_door(y, x, DOOR_GLASS_DOOR); + if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall; + break; + + /* Curtains */ + case '\'': + place_secret_door(y, x, DOOR_CURTAIN); break; /* Trap */ @@ -2690,37 +2760,37 @@ static void build_vault(int yval, int xval, int ymax, int xmax, cptr data, /* Black market in a dungeon */ case 'S': - set_cave_feat(y, x, FEAT_SHOP_HEAD + STORE_BLACK); + set_cave_feat(y, x, feat_black_market); store_init(NO_TOWN, STORE_BLACK); break; - + /* The Pattern */ case 'p': - set_cave_feat(y, x, FEAT_PATTERN_START); + set_cave_feat(y, x, feat_pattern_start); break; - + case 'a': - set_cave_feat(y, x, FEAT_PATTERN_1); + set_cave_feat(y, x, feat_pattern_1); break; - + case 'b': - set_cave_feat(y, x, FEAT_PATTERN_2); + set_cave_feat(y, x, feat_pattern_2); break; - + case 'c': - set_cave_feat(y, x, FEAT_PATTERN_3); + set_cave_feat(y, x, feat_pattern_3); break; - + case 'd': - set_cave_feat(y, x, FEAT_PATTERN_4); + set_cave_feat(y, x, feat_pattern_4); break; - + case 'P': - set_cave_feat(y, x, FEAT_PATTERN_END); + set_cave_feat(y, x, feat_pattern_end); break; - + case 'B': - set_cave_feat(y, x, FEAT_PATTERN_XTRA1); + set_cave_feat(y, x, feat_pattern_exit); break; case 'A': @@ -2916,16 +2986,6 @@ static bool build_type7(void) if (cheat_room) msg_format("Lesser vault (%s)", v_name + v_ptr->name); #endif - /* Boost the rating */ - rating += v_ptr->rat; - - /* (Sometimes) Cause a special feeling */ - if ((dun_level <= 50) || - (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400)) - { - good_item_flag = TRUE; - } - /* Hack -- Build the vault */ build_vault(yval, xval, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text, xoffset, yoffset, transno); @@ -3024,16 +3084,6 @@ static bool build_type8(void) if (cheat_room) msg_format("Greater vault (%s)", v_name + v_ptr->name); #endif - /* Boost the rating */ - rating += v_ptr->rat; - - /* (Sometimes) Cause a special feeling */ - if ((dun_level <= 50) || - (randint1((dun_level - 40) * (dun_level - 40) + 50) < 400)) - { - good_item_flag = TRUE; - } - /* Hack -- Build the vault */ build_vault(yval, xval, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text, xoffset, yoffset, transno); @@ -3130,7 +3180,7 @@ static void store_height(int x, int y, int val) * The tricky part is making sure the created cave is connected. This * is done by 'filling' from the inside and only keeping the 'filled' * floor. Walls bounding the 'filled' floor are also kept. Everything -* else is converted to the normal granite FEAT_WALL_EXTRA. +* else is converted to the normal _extra_. */ @@ -3400,6 +3450,7 @@ static bool hack_isnt_wall(int y, int x, int c1, int c2, int c3, int feat1, int else if (cave[y][x].feat <= c3) { cave[y][x].feat = feat3; + cave[y][x].info &= ~(CAVE_MASK); cave[y][x].info |= info3; return TRUE; } @@ -3675,7 +3726,7 @@ static bool generate_fracave(int y0, int x0, int xsize, int ysize, int cutoff, b * XXX XXX XXX There is a slight problem when tunnels pierce the caves: * Extra doors appear inside the system. (Its not very noticeable though.) * This can be removed by "filling" from the outside in. This allows a separation - * from FEAT_WALL_OUTER with FEAT_WALL_INNER. (Internal walls are F.W.OUTER instead.) + * from _outer_ with _inner_. (Internal walls are _outer_ instead.) * The extra effort for what seems to be only a minor thing (even non-existant if you * think of the caves not as normal rooms, but as holes in the dungeon), doesn't seem * worth it. @@ -3699,7 +3750,22 @@ static bool build_type9(void) ysize = randint1(15) * 2 + 6; /* Find and reserve some space in the dungeon. Get center of room. */ - if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE; + if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) + { + /* Limit to the minimum room size, and retry */ + xsize = 8; + ysize = 8; + + /* Find and reserve some space in the dungeon. Get center of room. */ + if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) + { + /* + * Still no space?! + * Try normal room + */ + return build_type1(); + } + } light = done = FALSE; room = TRUE; @@ -3785,39 +3851,39 @@ static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, switch (type) { case LAKE_T_LAVA: /* Lava */ - feat1 = FEAT_DEEP_LAVA; - feat2 = FEAT_SHAL_LAVA; + feat1 = feat_deep_lava; + feat2 = feat_shallow_lava; feat3 = floor_type[randint0(100)]; break; case LAKE_T_WATER: /* Water */ - feat1 = FEAT_DEEP_WATER; - feat2 = FEAT_SHAL_WATER; + feat1 = feat_deep_water; + feat2 = feat_shallow_water; feat3 = floor_type[randint0(100)]; break; case LAKE_T_CAVE: /* Collapsed cave */ feat1 = floor_type[randint0(100)]; feat2 = floor_type[randint0(100)]; - feat3 = FEAT_RUBBLE; + feat3 = feat_rubble; break; case LAKE_T_EARTH_VAULT: /* Earth vault */ - feat1 = FEAT_RUBBLE; + feat1 = feat_rubble; feat2 = floor_type[randint0(100)]; - feat3 = FEAT_RUBBLE; + feat3 = feat_rubble; break; case LAKE_T_AIR_VAULT: /* Air vault */ - feat1 = FEAT_GRASS; - feat2 = FEAT_TREES; - feat3 = FEAT_GRASS; + feat1 = feat_grass; + feat2 = feat_tree; + feat3 = feat_grass; break; case LAKE_T_WATER_VAULT: /* Water vault */ - feat1 = FEAT_SHAL_WATER; - feat2 = FEAT_DEEP_WATER; - feat3 = FEAT_SHAL_WATER; + feat1 = feat_shallow_water; + feat2 = feat_deep_water; + feat3 = feat_shallow_water; break; case LAKE_T_FIRE_VAULT: /* Fire Vault */ - feat1 = FEAT_SHAL_LAVA; - feat2 = FEAT_DEEP_LAVA; - feat3 = FEAT_SHAL_LAVA; + feat1 = feat_shallow_lava; + feat2 = feat_deep_lava; + feat3 = feat_shallow_lava; break; /* Paranoia */ @@ -3905,7 +3971,7 @@ static bool generate_lake(int y0, int x0, int xsize, int ysize, int c1, int c2, cave[y0 + y - yhsize][x0 + x - xhsize].info &= ~(CAVE_ICKY | CAVE_ROOM); /* Light lava */ - if (have_flag(f_flags_bold(y0 + y - yhsize, x0 + x - xhsize), FF_LAVA)) + if (cave_have_flag_bold(y0 + y - yhsize, x0 + x - xhsize, FF_LAVA)) { if (!(d_info[dungeon_type].flags1 & DF1_DARKNESS)) cave[y0 + y - yhsize][x0 + x - xhsize].info |= CAVE_GLOW; } @@ -3994,7 +4060,7 @@ static void add_door(int x, int y) (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1))) { /* secret door */ - place_secret_door(y, x); + place_secret_door(y, x, DOOR_DEFAULT); /* set boundarys so don't get wide doors */ place_solid_bold(y, x - 1); @@ -4014,7 +4080,7 @@ static void add_door(int x, int y) is_floor_bold(y,x-1) && is_floor_bold(y,x+1)) { /* secret door */ - place_secret_door(y, x); + place_secret_door(y, x, DOOR_DEFAULT); /* set boundarys so don't get wide doors */ place_solid_bold(y - 1, x); @@ -4051,7 +4117,7 @@ static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty) /* if floor, shallow water and lava */ if (is_floor_bold(y, x) || - (have_flag(f_flags_bold(y, x), FF_PLACE) && have_flag(f_flags_bold(y, x), FF_DROP))) + (cave_have_flag_bold(y, x, FF_PLACE) && cave_have_flag_bold(y, x, FF_DROP))) { /* The smaller 'value' is, the better the stuff */ if (value < 0) @@ -4188,8 +4254,8 @@ static void build_bubble_vault(int x0, int y0, int xsize, int ysize) if (cheat_room) msg_print("Bubble Vault"); /* Allocate center of bubbles */ - center[0].x = randint1(xsize - 3) + 1; - center[0].y = randint1(ysize - 3) + 1; + center[0].x = (byte)randint1(xsize - 3) + 1; + center[0].y = (byte)randint1(ysize - 3) + 1; for (i = 1; i < BUBBLENUM; i++) { @@ -4714,9 +4780,7 @@ static void build_mini_c_vault(int x0, int y0, int xsize, int ysize) c_ptr->info |= (CAVE_ROOM | CAVE_ICKY); /* Permanent walls */ - c_ptr->feat = FEAT_PERM_INNER; - c_ptr->info &= ~(CAVE_MASK); - c_ptr->info |= CAVE_INNER; + place_inner_perm_grid(c_ptr); } } @@ -5023,8 +5087,7 @@ static void build_castle_vault(int x0, int y0, int xsize, int ysize) * Note: no range checking is done so must be inside dungeon * This routine also stomps on doors */ -static void add_outer_wall(int x, int y, int light, - int x1, int y1, int x2, int y2) +static void add_outer_wall(int x, int y, int light, int x1, int y1, int x2, int y2) { cave_type *c_ptr; feature_type *f_ptr; @@ -5064,7 +5127,7 @@ static void add_outer_wall(int x, int y, int light, place_outer_bold(y, x); if (light) c_ptr->info |= CAVE_GLOW; } - else if (have_flag(f_ptr->flags, FF_WALL) && have_flag(f_ptr->flags, FF_PERMANENT) && have_flag(f_ptr->flags, FF_OUTER)) + else if (permanent_wall(f_ptr)) { /* Set bounding walls */ if (light) c_ptr->info |= CAVE_GLOW; @@ -5329,21 +5392,21 @@ static bool build_type10(void) /* Find and reserve some space in the dungeon. Get center of room. */ if (!find_space(&y0, &x0, ysize + 1, xsize + 1)) return FALSE; - /* Boost the rating- higher than lesser vaults and lower than greater vaults */ - rating += 10; - - /* (Sometimes) Cause a special feeling */ - if ((dun_level <= 50) || - (randint1((dun_level - 40) * (dun_level - 40) + 1) < 400)) - { - good_item_flag = TRUE; - } - /* Select type of vault */ #ifdef ALLOW_CAVERNS_AND_LAKES - vtype = randint1(15); + do + { + vtype = randint1(15); + } + while ((d_info[dungeon_type].flags1 & DF1_NO_CAVE) && + ((vtype == 1) || (vtype == 3) || (vtype == 8) || (vtype == 9) || (vtype == 11))); #else /* ALLOW_CAVERNS_AND_LAKES */ - vtype = randint1(7); + do + { + vtype = randint1(7); + } + while ((d_info[dungeon_type].flags1 & DF1_NO_CAVE) && + ((vtype == 1) || (vtype == 3))); #endif /* ALLOW_CAVERNS_AND_LAKES */ switch (vtype) @@ -5529,7 +5592,7 @@ static bool vault_aux_trapped_pit(int r_idx) /* - * Type 12 -- Trapped monster pits + * Type 13 -- Trapped monster pits * * A trapped monster pit is a "big" room with a straight corridor in * which wall opening traps are placed, and with two "inner" rooms @@ -5568,7 +5631,7 @@ static bool vault_aux_trapped_pit(int r_idx) * "appropriate" non-unique monsters for the pit. * * Note that the "get_mon_num()" function may (rarely) fail, in which case - * the pit will be empty, and will not effect the level rating. + * the pit will be empty. * * Note that "monster pits" will never contain "unique" monsters. */ @@ -5761,7 +5824,7 @@ static bool build_type13(void) /* Place the wall open trap */ cave[yval][xval].mimic = cave[yval][xval].feat; - cave[yval][xval].feat = FEAT_TRAP_OPEN; + cave[yval][xval].feat = feat_trap_open; /* Sort the entries */ for (i = 0; i < 16 - 1; i++) @@ -5809,15 +5872,6 @@ static bool build_type13(void) } } - /* Increase the level rating */ - rating += 20; - - /* (Sometimes) Cause a "special feeling" (for "Monster Pits") */ - if ((dun_level <= 40) && (randint1(dun_level * dun_level + 50) < 300)) - { - good_item_flag = TRUE; - } - for (i = 0; placing[i][2] >= 0; i++) { y = yval + placing[i][0]; @@ -5896,9 +5950,9 @@ static bool build_type14(void) } if (dun_level < 30 + randint1(30)) - trap = FEAT_TRAP_PIRANHA; + trap = feat_trap_piranha; else - trap = FEAT_TRAP_ARMAGEDDON; + trap = feat_trap_armageddon; /* Place a special trap */ c_ptr = &cave[rand_spread(yval, ysize/4)][rand_spread(xval, xsize/4)]; @@ -5920,12 +5974,600 @@ static bool build_type14(void) /* + * Helper function for "glass room" + */ +static bool vault_aux_lite(int r_idx) +{ + monster_race *r_ptr = &r_info[r_idx]; + + /* Validate the monster */ + if (!vault_monster_okay(r_idx)) return FALSE; + + /* Require lite attack */ + if (!(r_ptr->flags4 & RF4_BR_LITE) && !(r_ptr->flags5 & RF5_BA_LITE)) return FALSE; + + /* No wall passing monsters */ + if (r_ptr->flags2 & (RF2_PASS_WALL | RF2_KILL_WALL)) return FALSE; + + /* No disintegrating monsters */ + if (r_ptr->flags4 & RF4_BR_DISI) return FALSE; + + return TRUE; +} + +/* + * Helper function for "glass room" + */ +static bool vault_aux_shards(int r_idx) +{ + monster_race *r_ptr = &r_info[r_idx]; + + /* Validate the monster */ + if (!vault_monster_okay(r_idx)) return FALSE; + + /* Require shards breath attack */ + if (!(r_ptr->flags4 & RF4_BR_SHAR)) return FALSE; + + return TRUE; +} + +/* + * Hack -- determine if a template is potion + */ +static bool kind_is_potion(int k_idx) +{ + return k_info[k_idx].tval == TV_POTION; +} + +/* + * Type 15 -- glass rooms + */ +static bool build_type15(void) +{ + int y, x, y2, x2, yval, xval; + int y1, x1, xsize, ysize; + bool light; + + cave_type *c_ptr; + + /* Pick a room size */ + xsize = rand_range(9, 13); + ysize = rand_range(9, 13); + + /* Find and reserve some space in the dungeon. Get center of room. */ + if (!find_space(&yval, &xval, ysize + 2, xsize + 2)) return FALSE; + + /* Choose lite or dark */ + light = ((dun_level <= randint1(25)) && !(d_info[dungeon_type].flags1 & DF1_DARKNESS)); + + /* Get corner values */ + y1 = yval - ysize / 2; + x1 = xval - xsize / 2; + y2 = yval + (ysize - 1) / 2; + x2 = xval + (xsize - 1) / 2; + + /* Place a full floor under the room */ + for (y = y1 - 1; y <= y2 + 1; y++) + { + for (x = x1 - 1; x <= x2 + 1; x++) + { + c_ptr = &cave[y][x]; + place_floor_grid(c_ptr); + c_ptr->feat = feat_glass_floor; + c_ptr->info |= (CAVE_ROOM); + if (light) c_ptr->info |= (CAVE_GLOW); + } + } + + /* Walls around the room */ + for (y = y1 - 1; y <= y2 + 1; y++) + { + c_ptr = &cave[y][x1 - 1]; + place_outer_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + c_ptr = &cave[y][x2 + 1]; + place_outer_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + } + for (x = x1 - 1; x <= x2 + 1; x++) + { + c_ptr = &cave[y1 - 1][x]; + place_outer_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + c_ptr = &cave[y2 + 1][x]; + place_outer_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + } + + switch (randint1(3)) + { + case 1: /* 4 lite breathers + potion */ + { + int dir1, dir2; + + /* Prepare allocation table */ + get_mon_num_prep(vault_aux_lite, NULL); + + /* Place fixed lite berathers */ + for (dir1 = 4; dir1 < 8; dir1++) + { + int r_idx = get_mon_num(dun_level); + + y = yval + 2 * ddy_ddd[dir1]; + x = xval + 2 * ddx_ddd[dir1]; + if (r_idx) place_monster_aux(0, y, x, r_idx, PM_ALLOW_SLEEP); + + /* Walls around the breather */ + for (dir2 = 0; dir2 < 8; dir2++) + { + c_ptr = &cave[y + ddy_ddd[dir2]][x + ddx_ddd[dir2]]; + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + } + } + + /* Walls around the potion */ + for (dir1 = 0; dir1 < 4; dir1++) + { + y = yval + 2 * ddy_ddd[dir1]; + x = xval + 2 * ddx_ddd[dir1]; + c_ptr = &cave[y][x]; + place_inner_perm_grid(c_ptr); + c_ptr->feat = feat_permanent_glass_wall; + cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]].info |= (CAVE_ICKY); + } + + /* Glass door */ + dir1 = randint0(4); + y = yval + 2 * ddy_ddd[dir1]; + x = xval + 2 * ddx_ddd[dir1]; + place_secret_door(y, x, DOOR_GLASS_DOOR); + c_ptr = &cave[y][x]; + if (is_closed_door(c_ptr->feat)) c_ptr->mimic = feat_glass_wall; + + /* Place a potion */ + get_obj_num_hook = kind_is_potion; + place_object(yval, xval, AM_NO_FIXED_ART); + cave[yval][xval].info |= (CAVE_ICKY); + } + break; + + case 2: /* 1 lite breather + random object */ + { + int r_idx, dir1; + + /* Pillars */ + c_ptr = &cave[y1 + 1][x1 + 1]; + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + + c_ptr = &cave[y1 + 1][x2 - 1]; + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + + c_ptr = &cave[y2 - 1][x1 + 1]; + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + + c_ptr = &cave[y2 - 1][x2 - 1]; + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + + /* Prepare allocation table */ + get_mon_num_prep(vault_aux_lite, NULL); + + r_idx = get_mon_num(dun_level); + if (r_idx) place_monster_aux(0, yval, xval, r_idx, 0L); + + /* Walls around the breather */ + for (dir1 = 0; dir1 < 8; dir1++) + { + c_ptr = &cave[yval + ddy_ddd[dir1]][xval + ddx_ddd[dir1]]; + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + } + + /* Curtains around the breather */ + for (y = yval - 1; y <= yval + 1; y++) + { + place_closed_door(y, xval - 2, DOOR_CURTAIN); + place_closed_door(y, xval + 2, DOOR_CURTAIN); + } + for (x = xval - 1; x <= xval + 1; x++) + { + place_closed_door(yval - 2, x, DOOR_CURTAIN); + place_closed_door(yval + 2, x, DOOR_CURTAIN); + } + + /* Place an object */ + place_object(yval, xval, AM_NO_FIXED_ART); + cave[yval][xval].info |= (CAVE_ICKY); + } + break; + + case 3: /* 4 shards breathers + 2 potions */ + { + int dir1; + + /* Walls around the potion */ + for (y = yval - 2; y <= yval + 2; y++) + { + c_ptr = &cave[y][xval - 3]; + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + c_ptr = &cave[y][xval + 3]; + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + } + for (x = xval - 2; x <= xval + 2; x++) + { + c_ptr = &cave[yval - 3][x]; + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + c_ptr = &cave[yval + 3][x]; + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + } + for (dir1 = 4; dir1 < 8; dir1++) + { + c_ptr = &cave[yval + 2 * ddy_ddd[dir1]][xval + 2 * ddx_ddd[dir1]]; + place_inner_grid(c_ptr); + c_ptr->feat = feat_glass_wall; + } + + /* Prepare allocation table */ + get_mon_num_prep(vault_aux_shards, NULL); + + /* Place shard berathers */ + for (dir1 = 4; dir1 < 8; dir1++) + { + int r_idx = get_mon_num(dun_level); + + y = yval + ddy_ddd[dir1]; + x = xval + ddx_ddd[dir1]; + if (r_idx) place_monster_aux(0, y, x, r_idx, 0L); + } + + /* Place two potions */ + if (one_in_(2)) + { + get_obj_num_hook = kind_is_potion; + place_object(yval, xval - 1, AM_NO_FIXED_ART); + get_obj_num_hook = kind_is_potion; + place_object(yval, xval + 1, AM_NO_FIXED_ART); + } + else + { + get_obj_num_hook = kind_is_potion; + place_object(yval - 1, xval, AM_NO_FIXED_ART); + get_obj_num_hook = kind_is_potion; + place_object(yval + 1, xval, AM_NO_FIXED_ART); + } + + for (y = yval - 2; y <= yval + 2; y++) + for (x = xval - 2; x <= xval + 2; x++) + cave[y][x].info |= (CAVE_ICKY); + + } + break; + } + + /* Message */ + if (cheat_room) + { +#ifdef JP + msg_print("¥¬¥é¥¹¤ÎÉô²°"); +#else + msg_print("Glass room"); +#endif + } + + return TRUE; +} + + +/* Create a new floor room with optional light */ +void generate_room_floor(int y1, int x1, int y2, int x2, int light) +{ + int y, x; + + cave_type *c_ptr; + + for (y = y1; y <= y2; y++) + { + for (x = x1; x <= x2; x++) + { + /* Point to grid */ + c_ptr = &cave[y][x]; + place_floor_grid(c_ptr); + c_ptr->info |= (CAVE_ROOM); + if (light) c_ptr->info |= (CAVE_GLOW); + } + } +} + +void generate_fill_perm_bold(int y1, int x1, int y2, int x2) +{ + int y, x; + + for (y = y1; y <= y2; y++) + { + for (x = x1; x <= x2; x++) + { + /* Point to grid */ + place_extra_perm_bold(y, x); + } + } +} + +/* Minimum & maximum town size */ +#define MIN_TOWN_WID ((MAX_WID / 3) / 2) +#define MIN_TOWN_HGT ((MAX_HGT / 3) / 2) +#define MAX_TOWN_WID ((MAX_WID / 3) * 2 / 3) +#define MAX_TOWN_HGT ((MAX_HGT / 3) * 2 / 3) + +/* Struct for build underground buildings */ +typedef struct +{ + int y0, x0; /* North-west corner (relative) */ + int y1, x1; /* South-east corner (relative) */ +} +ugbldg_type; + +ugbldg_type *ugbldg; + +/* + * Precalculate buildings' location of underground arcade + */ +static bool precalc_ugarcade(int town_hgt, int town_wid, int n) +{ + int i, y, x, center_y, center_x, tmp, attempt = 10000; + int max_bldg_hgt = 3 * town_hgt / MAX_TOWN_HGT; + int max_bldg_wid = 5 * town_wid / MAX_TOWN_WID; + ugbldg_type *cur_ugbldg; + bool **ugarcade_used, abort; + + /* Allocate "ugarcade_used" array (2-dimension) */ + C_MAKE(ugarcade_used, town_hgt, bool *); + C_MAKE(*ugarcade_used, town_hgt * town_wid, bool); + for (y = 1; y < town_hgt; y++) ugarcade_used[y] = *ugarcade_used + y * town_wid; + + /* Calculate building locations */ + for (i = 0; i < n; i++) + { + cur_ugbldg = &ugbldg[i]; + (void)WIPE(cur_ugbldg, ugbldg_type); + + do + { + /* Find the "center" of the store */ + center_y = rand_range(2, town_hgt - 3); + center_x = rand_range(2, town_wid - 3); + + /* Determine the store boundaries */ + tmp = center_y - randint1(max_bldg_hgt); + cur_ugbldg->y0 = MAX(tmp, 1); + tmp = center_x - randint1(max_bldg_wid); + cur_ugbldg->x0 = MAX(tmp, 1); + tmp = center_y + randint1(max_bldg_hgt); + cur_ugbldg->y1 = MIN(tmp, town_hgt - 2); + tmp = center_x + randint1(max_bldg_wid); + cur_ugbldg->x1 = MIN(tmp, town_wid - 2); + + /* Scan this building's area */ + for (abort = FALSE, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++) + { + for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++) + { + if (ugarcade_used[y][x]) + { + abort = TRUE; + break; + } + } + } + + attempt--; + } + while (abort && attempt); /* Accept this building if no overlapping */ + + /* Failed to generate underground arcade */ + if (!attempt) break; + + /* + * Mark to ugarcade_used[][] as "used" + * Note: Building-adjacent grids are included for preventing + * connected bulidings. + */ + for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++) + { + for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++) + { + ugarcade_used[y][x] = TRUE; + } + } + } + + /* Free "ugarcade_used" array (2-dimension) */ + C_KILL(*ugarcade_used, town_hgt * town_wid, bool); + C_KILL(ugarcade_used, town_hgt, bool *); + + /* If i < n, generation is not allowed */ + return i == n; +} + +/* + * Actually create buildings + * Note: ltcy and ltcx indicate "left top corner". + */ +static void build_stores(int ltcy, int ltcx, int stores[], int n) +{ + int i, j, y, x; + ugbldg_type *cur_ugbldg; + + for (i = 0; i < n; i++) + { + cur_ugbldg = &ugbldg[i]; + + /* Generate new room */ + generate_room_floor( + ltcy + cur_ugbldg->y0 - 2, ltcx + cur_ugbldg->x0 - 2, + ltcy + cur_ugbldg->y1 + 2, ltcx + cur_ugbldg->x1 + 2, + FALSE); + } + + for (i = 0; i < n; i++) + { + cur_ugbldg = &ugbldg[i]; + + /* Build an invulnerable rectangular building */ + generate_fill_perm_bold( + ltcy + cur_ugbldg->y0, ltcx + cur_ugbldg->x0, + ltcy + cur_ugbldg->y1, ltcx + cur_ugbldg->x1); + + /* Pick a door direction (S,N,E,W) */ + switch (randint0(4)) + { + /* Bottom side */ + case 0: + y = cur_ugbldg->y1; + x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1); + break; + + /* Top side */ + case 1: + y = cur_ugbldg->y0; + x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1); + break; + + /* Right side */ + case 2: + y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1); + x = cur_ugbldg->x1; + break; + + /* Left side */ + default: + y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1); + x = cur_ugbldg->x0; + break; + } + + for (j = 0; j < max_f_idx; j++) + { + if (have_flag(f_info[j].flags, FF_STORE)) + { + if (f_info[j].subtype == stores[i]) break; + } + } + + /* Clear previous contents, add a store door */ + if (j < max_f_idx) + { + cave_set_feat(ltcy + y, ltcx + x, j); + + /* Init store */ + store_init(NO_TOWN, stores[i]); + } + } +} + + +/* + * Type 16 -- Underground Arcade + * + * Town logic flow for generation of new town + * Originally from Vanilla 3.0.3 + * + * We start with a fully wiped cave of normal floors. + * + * Note that town_gen_hack() plays games with the R.N.G. + * + * This function does NOT do anything about the owners of the stores, + * nor the contents thereof. It only handles the physical layout. + */ +static bool build_type16(void) +{ + int stores[] = + { + STORE_GENERAL, STORE_ARMOURY, STORE_WEAPON, STORE_TEMPLE, + STORE_ALCHEMIST, STORE_MAGIC, STORE_BLACK, STORE_BOOK, + }; + int n = sizeof stores / sizeof (int); + int i, y, x, y1, x1, yval, xval; + int town_hgt = rand_range(MIN_TOWN_HGT, MAX_TOWN_HGT); + int town_wid = rand_range(MIN_TOWN_WID, MAX_TOWN_WID); + bool prevent_bm = FALSE; + + /* Hack -- If already exist black market, prevent building */ + for (y = 0; (y < cur_hgt) && !prevent_bm; y++) + { + for (x = 0; x < cur_wid; x++) + { + if (cave[y][x].feat == FF_STORE) + { + prevent_bm = (f_info[cave[y][x].feat].subtype == STORE_BLACK); + break; + } + } + } + for (i = 0; i < n; i++) + { + if ((stores[i] == STORE_BLACK) && prevent_bm) stores[i] = stores[--n]; + } + if (!n) return FALSE; + + /* Allocate buildings array */ + C_MAKE(ugbldg, n, ugbldg_type); + + /* If cannot build stores, abort */ + if (!precalc_ugarcade(town_hgt, town_wid, n)) + { + /* Free buildings array */ + C_KILL(ugbldg, n, ugbldg_type); + return FALSE; + } + + /* Find and reserve some space in the dungeon. Get center of room. */ + if (!find_space(&yval, &xval, town_hgt + 4, town_wid + 4)) + { + /* Free buildings array */ + C_KILL(ugbldg, n, ugbldg_type); + return FALSE; + } + + /* Get top left corner */ + y1 = yval - (town_hgt / 2); + x1 = xval - (town_wid / 2); + + /* Generate new room */ + generate_room_floor( + y1 + town_hgt / 3, x1 + town_wid / 3, + y1 + town_hgt * 2 / 3, x1 + town_wid * 2 / 3, FALSE); + + /* Build stores */ + build_stores(y1, x1, stores, n); + +#ifdef JP + if (cheat_room) msg_print("Ãϲ¼³¹"); +#else + if (cheat_room) msg_print("Underground Arcade"); +#endif + + /* Free buildings array */ + C_KILL(ugbldg, n, ugbldg_type); + + return TRUE; +} + + +/* * Attempt to build a room of the given type at the given block * * Note that we restrict the number of "crowded" rooms to reduce * the chance of overflowing the monster list during level creation. */ -bool room_build(int typ) +static bool room_build(int typ) { /* Build a room */ switch (typ) @@ -5945,6 +6587,8 @@ bool room_build(int typ) case ROOM_T_CRYPT: return build_type12(); case ROOM_T_TRAP_PIT: return build_type13(); case ROOM_T_TRAP: return build_type14(); + case ROOM_T_GLASS: return build_type15(); + case ROOM_T_ARCADE: return build_type16(); } /* Paranoia */ @@ -5959,7 +6603,7 @@ bool room_build(int typ) * * Generate rooms in dungeon. Build bigger rooms at first. */ -void generate_rooms(void) +bool generate_rooms(void) { int i; bool remain; @@ -5979,7 +6623,6 @@ void generate_rooms(void) /* Assume normal cave */ room_info_type *room_info_ptr = room_info_normal; - /* * Initialize probability list. */ @@ -6001,7 +6644,7 @@ void generate_rooms(void) */ /* Ironman sees only Greater Vaults */ - if (ironman_rooms && !((d_info[dungeon_type].flags1 & (DF1_BEGINNER | DF1_CHAMELEON)))) + if (ironman_rooms && !((d_info[dungeon_type].flags1 & (DF1_BEGINNER | DF1_CHAMELEON | DF1_SMALLEST)))) { for (i = 0; i < ROOM_T_MAX; i++) { @@ -6039,6 +6682,16 @@ void generate_rooms(void) prob_list[ROOM_T_FRACAVE] = 0; } + /* Forbidden glass rooms */ + if (!(d_info[dungeon_type].flags1 & DF1_GLASS_ROOM)) + { + prob_list[ROOM_T_GLASS] = 0; + } + + if (!(d_info[dungeon_type].flags1 & DF1_ARCADE)) + { + prob_list[ROOM_T_ARCADE] = 0; + } /* * Initialize number of rooms, @@ -6078,6 +6731,8 @@ void generate_rooms(void) case ROOM_T_PIT: case ROOM_T_LESSER_VAULT: case ROOM_T_TRAP_PIT: + case ROOM_T_GLASS: + case ROOM_T_ARCADE: /* Large room */ i -= 2; @@ -6134,13 +6789,14 @@ void generate_rooms(void) room_num[ROOM_T_NEST] = 0; room_num[ROOM_T_TRAP_PIT] = 0; } - } - } + break; - /* Stop building this type on failure. */ - else - { - room_num[room_type] = 0; + case ROOM_T_ARCADE: + + /* Avoid double-town */ + room_num[ROOM_T_ARCADE] = 0; + break; + } } } @@ -6148,6 +6804,8 @@ void generate_rooms(void) if (!remain) break; } + if (rooms_built < 2) return FALSE; + if (cheat_room) { #ifdef JP @@ -6156,4 +6814,6 @@ void generate_rooms(void) msg_format("Number of Rooms: %d", rooms_built); #endif } + + return TRUE; }