git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8169 c06c8d41-db1a-0410-9941-cceddc491573
OMAUFQNBWGX4FDABHQCVPGDYRVKMDASGQJVRH7AOPPEMHAP2LQSQC 2ZWSJ2ZV5VI4MYCBS4TNOE43VPKIMSLPWLVNFGRCGDQPD2PS6EXAC UQZESUMXKG6SRYSP52RYO6EUX7TRLHRALAOX2S3HUGZMR2C5NDCQC BSU7KFO5UGBSWPF2W7MWUWG42JJZ556H7PQG3BEZOZ53YPPLTZAAC 7DLDFEEB5IHCPN5VL2BBI7JM6SJB6M6FTYM2DMM6R6QV33COOA6QC JQKRFPNPLYBHUWMVQLPX5UB5RRP5PKY6NQ5LRHJRIOY6IKN2AH6AC XIFNWKKXBHUZG52JL2PICXF4C3I5HDGFAEU2CHHVBXNT75WQE5NAC SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC B7DNCNY7SXL5WAW5B3XZP5KIQSBWOJ3N2YW46WOUQKTRBRRZ7YOQC AO3KHGKGSX2ZR24KJVIOTUY7EHYHMMI5W4HN3CAG4YGQHBOHLGDQC KIDHPMZSLUVK3TF4565MH7SJ57C45SORJXR274VJTOULNOTGHQ4AC VTJOYDSSNQZOK23N65C64NUGDTGPL6QZWGCALRQHQDQXAPYBRKMAC BW6QCGQDWZ6G2UGDD4EXI5VVDZHM5S53MJIC5CKG3Q3VQ4IDQ2VQC ZVK4J5HTKFNOOIVCI62ZWEYGXEE5TYJ65DLYYZAZWTADFSXE62ZAC MT3256427VMCV4JUFWCN7ULY4KXSND5ZL5THDKYNWWYOXXR5DLIQC IVVTHLTTLOP5TSULXJWUSSXHOKYWVU3OWKYVK45A7RIB6V34MYQAC ZJLJGSB2XSBQU42OFQMXL3EG4CXAQGOYAU6YTV2SAWZEJIPFH2CAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC JR4ZZK4HOXQIG3WXBGTPZAPPNF7HHBCUZ3TE7RBCS64NHCOX7B2QC KTRWLM6WDL4GAAJZNLQEEA3TGY2OKYZZUAAT4TCAVKRTR2NQBWUQC CREW3VTGN2BV622ZXHCPHUEZWBAGEQMNUELDLTHLEKG4VBXGMRPQC KCHX2F3JFEWOZT3WMJVZAAQUU2QSZ5Q7RDCD7WUJ7VE65J52JFUQC PISXY4NKSKL5KDJWAHD7CTXWTQDH3NFWQSFAHUAI3VVATWKXRODQC FSD7GIK3YLZXWLEH37BU6KV3IUCFGXPQL6IZ7H65YWNRBEKDBX5AC NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC ILOED4VB4I6VPAUTR75ZWX6MXDYXB5DO2EDK2UH67O3HNKWV23RQC FQ7XALBL6NZAGBKKYIFHYQ7MUWIHR4TEU4TCS33EG4I3JTND5SQAC KSCU43RIVSEIHTN6BRAKXENI66L3IRDZQHUBT5VS4NJBBCQQPHUQC SM6YRPYZS6LMDQA6X3VAOK2PGMUFKPD7JMWJISOQSMX2CBR4ISPAC AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC NKONHW4JNY6HP2M63MNPM3H64ZWSUNUT5FX2STW4KTS4AMXJXXVQC 4N5PW5S3OV25HFN634NNWMMYX26NA2TB6TVFG4UMYSZ2VBJWKE4QC B7MSPF6X2RLGWN4M6ZZF3WSOPKGYPTTD7LIJVST7DXN27DG6JHNAC HZK3YN3SAISTDS5JI4COBYFG7YB4ABDVENXWZZEYLFA2LDI232VAC AOLWOUIFBQDQTCMSVB7N7GAKFUY5J5LH7CJZAY3HEY3WEUSLADZAC 45EMD3KLQPMERNMIKU5G76H6556XOMIW352TSBP7VLWJX2YYGS7AC SH6NU4H5TG4O7CRXRHZ7MDHABZLWWXQ77NJDBHI7KCVHXHQYK46QC GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC EJ4GIPFSSQCQASUMRF4CR2WPUQOTEHFRGLOYEZ7BH6YEMIR6DN4QC AYAQKTO6HOZJ44NDH5UIP6WFNB54Z5EZ4UMUISIQ67ZOIDB6OIQAC ANBVGN4RZOMY5LI4QSHOV2477FN55H353ZYLSVCPTXC7AWWSQZBAC 6QWZDCP5HGYLTJO3WWYJJGRRT7QFY6IG64TC7TUB553Z7GAA2HIQC KXUQB3WNWC5IFL6VFWADEPQMMU3VV3NDI5FLA666PGOEWFYUHCLQC FIYBXLWALQINNQTHG2KNDUUTAQAZRDDLXW2XOVSKDKBADJ3XCJ4AC KKNUX66ORZWWQH4ARKCHPHNDOYCI65STE3A27LKA3FWUKIX7MAXQC 34C4U6EQWERY75GZJKUCM5KVGU2OUICETS5LGZF6RMKMZT4R5SQAC 43NBC6HJOFQQTASUMC5W7MWLS355ASIUS7SEFRO6PJWQDY7MRZZQC FKRLQJYHK3GB6HHSNNFQ7L57ZAR52LSTBG5B6SNJBYZ2LQ36P67AC 3UKFCWWS5BLFQWZRB5FUA46CE2XGX5VRCEWC3K3XH5RCGQK64N2AC 56C44YMFHZ62GXAAOLYSLLGBVGRWXB53W2VI37Q26ZECEK2XG5SQC UOW2X5KTUHYCM73SWNOSJPHUKWVLF3OJTNSISSSENEURBX2XWHVQC ZJU5Z2WDMI7HN4XJ3NVTVRHIZO2CGFUQ2FSKIRJVTQG47XHNCZFQC C22455VGUQOSUX2OORA32LROFQ7NNYDMD2ZDTTUZSAQLXK4AD6QAC 4RFKVDJKTCRBZU6WPJ2E5OVI5IRPY3UTRPOBLC5QHY4CQJJTLZKQC CUNNC574MESEMTTONZ6YB6CJ2S5P6VA3V7Z3OODESWAK37GYOBPAC W45PMU4HNPSAMMEBJ4XH4MTHLPVIASZT4FXTBPID5LFXKIMNUBKAC UEI5JAVCMN7Y2SACTEZPZSNFJWOJTC55G24Q6LKQCT4XNDH5ZQIAC AF7VAKCSGEYCXRTITS2WAW7VTM3OEQOECMNXR6YMOQLBCVZZFAVQC 2YSMM7QMFZOPD5NXAD2OAMDJEY5LOZO4NCYBC7UCQVANKINJRNBAC 6CHNAAPWNROCQNX6EWPLXZOWX5HHKL5ZOHO24XRMNQTQF3CWB3VQC SCWXQW5H65OXUP2MEJ2MEEAVPSRJDT3RQGKYCMKVTORS2334PQSQC A3CO4KBFTFU3ZSHWRY2OPPX3MMTFV7OUCZGL7Q4Y2FU7JO4AP7MAC ECJNCUSSE63BKED3EAYIXQCI62I76QGNHCSFO3CDWPRZF3JQP44QC CPBVQFT7NWEYLYD34D5VYZIEOZ32YADXYTSFMS635YNXX4OFIZVAC JT672SIJK4BOIUAGL2WQ6NR2NF4PSWP3BT6Q4HMNRF25UN6JQ2MAC K6ELQ4HEZYDROC7CJFLPJS64AAJQ4G6RVLL4GBRUG6FJMKSBDDIQC L6O4LGZRKBURVWEY7XRVCSQLJ5RULNBEWMQJ6I2UYVWWB66FM3MQC J7GPW2YXLT6FGSKJ24FGQ24GTRZ6A2BDYM6CIXV4R6YBEHP6BGPAC 6ZQY6HMQHBIQP6RPQZTK4KJ6YGCW2SJJUYHGI6UVATES5GKJRP7QC XAFFD52IHN6FWFR2TT5F2KCUS7HAVCBI5CWTFMKPQG77GGTGAHLAC OY7KHQPESOUHPBXRZ2JSNUKPAC7DCDY73TAUHCSJG5V6TPAHBVYQC IHV7JHD4E67NEGLZEO3FPQGJPJF3IAV6QV5A63FPG4SU2VRFV47QC X7MFMKQTNZ2IWBFVGS6WQV7NRNKJ3DWQAW2X7IQMFQQXW24AHPZQC PKXXBHS3LWLPZI2QVRX22MSQ4R2626IXRSNHFFYHXYTLJJQU54LQC TLA5UN6LZPXGKERI27EFY4HKIIU3VU5Y7ZU54WXL6ANBUV2VOTMQC ILN2K6ASDZSMEHOPJ22IZLZJUO6DDGZTKAKXM3YXG6JZZHJNLX4AC R6XS2HO5QX2FJUGL5UQQRNETKCMYWTUFPHPPS5SYWK3OQA4UDUQQC BPPMLLPJLP6W2LZSPAMOMYA7YWCIFJTNNL3XBWU2MRHAQBZ5M4XAC ZTDYCQQQQSLWGFJOUB3HKGHMJLNY6UHF4OOC2XVVHXSZTTZK5A5AC MXOCLQAUGWLOS7AOTYZ46JZDMRL4EVRK5YN4JJUQ76GLKBOBHEVAC // Return value of zero forces dungeon.cc to regenerate the level, except// for branch entry vaults where dungeon.cc just rejects the vault and// places a vanilla entry.
// Return value of MAP_NONE forces dungeon.cc to regenerate the// level, except for branch entry vaults where dungeon.cc just// rejects the vault and places a vanilla entry.
}// Determines if the region specified by (x, y, x + width - 1, y + height - 1)// is a bad place to build a vault.static bool bad_map_place(const map_def &map, const coord_def &c,const coord_def &size){const std::vector<std::string> &lines = map.map.get_lines();for (rectangle_iterator r(c, c + size - 1); r; ++r){const coord_def &p(*r);const coord_def dp = p - c;if (lines[dp.y][dp.x] == ' ')continue;if (dgn_Map_Mask[p.x][p.y])return (true);if (igrd(p) != NON_ITEM || mgrd(p) != NON_MONSTER)return (true);const dungeon_feature_type grid = grd(p);if (!grid_is_opaque(grid)&& grid != DNGN_FLOOR&& grid != DNGN_SHALLOW_WATER&& grid != DNGN_CLOSED_DOOR&& grid != DNGN_OPEN_DOOR&& grid != DNGN_SECRET_DOOR){#ifdef DEBUG_DIAGNOSTICSmprf(MSGCH_DIAGNOSTICS,"Rejecting place because of %s at (%d,%d)",dungeon_feature_name(grid), p.x, p.y);#endifreturn (true);}}return (false);
}// Used for placement of vaults.static bool _may_overwrite_feature(const dungeon_feature_type grid,bool water_ok, bool wall_ok = true){// Deep water grids may be overwritten if water_ok == true.if (grid == DNGN_DEEP_WATER)return (water_ok);// Handle all other non-LOS blocking grids here.if (!grid_is_opaque(grid)&& grid != DNGN_FLOOR&& grid != DNGN_SHALLOW_WATER&& grid != DNGN_CLOSED_DOOR&& grid != DNGN_OPEN_DOOR&& grid != DNGN_SECRET_DOOR){return (false);}if (grid_is_wall(grid))return (wall_ok);// Otherwise, feel free to clobber this feature.return (true);}static bool _safe_vault_place(const map_def &map,const coord_def &c,const coord_def &size){if (size.zero())return (true);const bool water_ok = map.has_tag("water_ok");const std::vector<std::string> &lines = map.map.get_lines();for (rectangle_iterator ri(c, c + size - 1); ri; ++ri){const coord_def &cp(*ri);const coord_def &dp(cp - c);if (lines[dp.y][dp.x] == ' ')continue;if (dgn_Map_Mask[cp.x][cp.y])return (false);const dungeon_feature_type dfeat = grd(cp);// Don't overwrite features other than floor, rock wall, doors,// nor water, if !water_ok.if (!_may_overwrite_feature(dfeat, water_ok))return (false);// Don't overwrite items or monsters, either!if (igrd(cp) != NON_ITEM || mgrd(cp) != NON_MONSTER)return (false);}return (true);}static bool _connected_minivault_place(const coord_def &c,const vault_placement &place){if (place.size.zero())return (true);// Must not be completely isolated.const bool water_ok = place.map.has_tag("water_ok");const std::vector<std::string> &lines = place.map.map.get_lines();for (rectangle_iterator ri(c, c + place.size - 1); ri; ++ri){const coord_def &ci(*ri);if (lines[ci.y - c.y][ci.x - c.x] == ' ')continue;if (_may_overwrite_feature(grd(ci), water_ok, false))return (true);}return (false);}static coord_def _find_minivault_place(const vault_placement &place,bool check_place){// [ds] The margin around the edges of the map where the minivault// won't be placed. Purely arbitrary as far as I can see.const int margin = MAPGEN_BORDER * 2;// Find a target area which can be safely overwritten.for (int tries = 0; tries < 600; ++tries){coord_def v1(random_range( margin, GXM - margin - place.size.x ),random_range( margin, GYM - margin - place.size.y ));if (check_place && !map_place_valid(place.map, v1, place.size))continue;if (_connected_minivault_place(v1, place))return (v1);}return (coord_def(-1, -1));
static bool _build_minivaults(int level_number,const map_def *vault,bool clobber = false,bool make_no_exits = false,const coord_def &where = coord_def() );
const map_def *vault = random_map_for_tag("shoal_rune", true);_build_minivaults( level_number, vault, false, false,centres[1] );
const map_def *vault = random_map_for_tag("shoal_rune");_build_secondary_vault(level_number, vault, -1, false, false,centres[1]);
}int chance = you.your_level == 0? 50 : 100;while (chance && x_chance_in_y(chance, 100) || nvaults-- > 0){const map_def *vault = _dgn_random_map_for_place(true);if (!vault)break;_build_minivaults(you.your_level, vault);chance /= 4;
// ORIENT: encompass maps are unsuitable as secondary vaults.if (vault && vault->orient == MAP_ENCOMPASS)vault = NULL;
// Used for placement of vaults.static bool _may_overwrite_feature(const dungeon_feature_type grid,bool water_ok, bool rock_ok = true){// Floor, and closed/secret doors may always be overwritten.if (grid == DNGN_FLOOR|| grid == DNGN_CLOSED_DOOR || grid == DNGN_SECRET_DOOR){return (true);}if (grid == DNGN_ROCK_WALL)return (rock_ok);// Watery grids may be overwritten if water_ok == true.if (grid == DNGN_DEEP_WATER || grid == DNGN_SHALLOW_WATER)return (water_ok);// Otherwise, don't overwrite this feature.return (false);}
static bool _safe_minivault_place(int v1x, int v1y,const vault_placement &place,bool clobber){if (clobber)return (true);
const bool water_ok = place.map.has_tag("water_ok");const std::vector<std::string> &lines = place.map.map.get_lines();for (int vx = v1x; vx < v1x + place.size.x; vx++)for (int vy = v1y; vy < v1y + place.size.y; vy++){if (lines[vy - v1y][vx - v1x] == ' ')continue;if (dgn_Map_Mask[vx][vy])return (false);const dungeon_feature_type dfeat = grd[vx][vy];// Don't overwrite features other than floor, rock wall, doors,// nor water, if !water_ok.if (!_may_overwrite_feature(dfeat, water_ok))return (false);// Don't overwrite items or monsters, either!if (igrd[vx][vy] != NON_ITEM || mgrd[vx][vy] != NON_MONSTER)return (false);}return (true);}static bool _connected_minivault_place(int v1x, int v1y,const vault_placement &place){// Must not be completely isolated.const bool water_ok = place.map.has_tag("water_ok");const std::vector<std::string> &lines = place.map.map.get_lines();for (int vx = v1x; vx < v1x + place.size.x; vx++)for (int vy = v1y; vy < v1y + place.size.y; vy++){if (lines[vy - v1y][vx - v1x] == ' ')continue;// Overwrite floor, doors or water, but not rock walls.if (_may_overwrite_feature(grd[vx][vy], water_ok, false))return (true);}return (false);}static bool _find_minivault_place(const vault_placement &place,coord_def& v1, bool clobber){// [ds] The margin around the edges of the map where the minivault// won't be placed. Purely arbitrary as far as I can see.const int margin = MAPGEN_BORDER * 2;// Find a target area which can be safely overwritten.for (int tries = 0; tries < 600; ++tries){v1.x = random_range( margin, GXM - margin - place.size.x );v1.y = random_range( margin, GYM - margin - place.size.y );if (!_safe_minivault_place( v1.x, v1.y, place, clobber ))continue;if (_connected_minivault_place(v1.x, v1.y, place))return (true);}return (false);}static bool _build_minivaults(int level_number, const map_def *vault,bool clobber, bool make_no_exits,const coord_def &where){if (dgn_check_connectivity && !dgn_zones)dgn_zones = _dgn_count_disconnected_zones(false);vault_placement place;place.level_number = level_number;vault_main(place, vault);coord_def v1;// Not map_bounds, minivaults should never touch edge.if (in_bounds(where)){coord_def tl(where - place.size / 2);fit_region_into_map_bounds(tl, place.size, 1);v1 = tl;}else if (!_find_minivault_place(place, v1, clobber))return (false);place.pos = v1;Level_Vaults.push_back(place);#ifdef DEBUG_DIAGNOSTICSif (crawl_state.map_stat_gen)mapgen_report_map_use(place.map);#endifdgn_register_place(place, true);place.apply_grid();if (!make_no_exits){// This is a throwaway.std::vector<coord_def> &target_connections = place.exits;if (target_connections.empty() && place.map.has_tag("mini_float"))_pick_float_exits(place, target_connections);if (!target_connections.empty())_connect_vault(place);}return (true);} // end build_minivaults()
if (mdef->is_minivault()){did_map = _build_minivaults(you.your_level, mdef, clobber,make_no_exits, where);}else{dungeon_feature_type rune_subst = DNGN_FLOOR;if (mdef->has_tag_suffix("_entry"))rune_subst = _dgn_find_rune_subst_tags(mdef->tags);did_map = _build_secondary_vault(you.your_level, mdef, rune_subst,clobber, make_no_exits, where);}
dungeon_feature_type rune_subst = DNGN_FLOOR;if (mdef->has_tag_suffix("_entry"))rune_subst = _dgn_find_rune_subst_tags(mdef->tags);did_map = _build_secondary_vault(you.your_level, mdef, rune_subst,clobber, make_no_exits, where);
Minivaults are distinguished from normal vaults solely by the absence of anORIENT: declaration. Any map without a specified ORIENT: is a minivault.
1. Floating vaults may be placed before the rest of the level layoutis generated, and the rest of the level may be built around the floatingvault. This is never the case for minivaults.2. Floating vaults may be placed anywhere in the map, including placescompletely separated from the rest of the level by rock. Thedungeon builder will then connect the exits from the floating vaultto the rest of the level, usually producing obvious "passages" fromthe floating vault to the main body of the level.In contrast, minivaults are placed such that at least one square ofthe minivault overlaps with an existing part of the level, and arethus more likely to look like part of the level. Unlike floatingvaults, the dungeon builder assumes that any one square of overlapis enough to connect the minivault to the rest of the level andmakes no effort to connect exits from the minivault to the level.You can ask the dungeon builder to connect exits from yourminivault with the "mini_float" tag.