end of level generation do not isolate parts of the level that were not already isolated. This does not apply to weird level-types such as Labyrinths and the Abyss.
Added level veto stats to -mapstat output.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1831 c06c8d41-db1a-0410-9941-cceddc491573
2YSMM7QMFZOPD5NXAD2OAMDJEY5LOZO4NCYBC7UCQVANKINJRNBAC HZK3YN3SAISTDS5JI4COBYFG7YB4ABDVENXWZZEYLFA2LDI232VAC QFWQG7G6KTZX3GP52K3N4BDWLMNH7A3A5ILJLXDIK6PYYLF3KO3AC OYTCBRC7LE44EUVRZVYTOOVKQWJ6P6YE3FXTOGUTNKEMLNWPHKSQC C22455VGUQOSUX2OORA32LROFQ7NNYDMD2ZDTTUZSAQLXK4AD6QAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC 6QWZDCP5HGYLTJO3WWYJJGRRT7QFY6IG64TC7TUB553Z7GAA2HIQC SCWXQW5H65OXUP2MEJ2MEEAVPSRJDT3RQGKYCMKVTORS2334PQSQC XAFFD52IHN6FWFR2TT5F2KCUS7HAVCBI5CWTFMKPQG77GGTGAHLAC ZJLJGSB2XSBQU42OFQMXL3EG4CXAQGOYAU6YTV2SAWZEJIPFH2CAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC WLX2RQMMOMP2PYPAGJRM4VFD2WTLJTOAZZPPY3MV76FU2EGEJ54QC KXUQB3WNWC5IFL6VFWADEPQMMU3VV3NDI5FLA666PGOEWFYUHCLQC 3XZOL3FFQZITUJIGDD6B6V6ZYMBN524JKNN6ZPJAXEC7RY433I3QC 4RFKVDJKTCRBZU6WPJ2E5OVI5IRPY3UTRPOBLC5QHY4CQJJTLZKQC WWR4IDWLXP4XLBWDZBA5GFG7CRKUJQNRK7FFUFOISK6OJTMYQPFQC TZ55IZNANEJO2WDTKYWVLY2W2VV6BR7WKIN7XLNISAMMFT6LG2WQC ZVK4J5HTKFNOOIVCI62ZWEYGXEE5TYJ65DLYYZAZWTADFSXE62ZAC ECJNCUSSE63BKED3EAYIXQCI62I76QGNHCSFO3CDWPRZF3JQP44QC }static inline bool dgn_grid_is_isolating(const dungeon_feature_type grid){// Rock wall check is superfluous, but is the most common case.return (grid == DNGN_ROCK_WALL|| (grid_is_solid(grid) && grid != DNGN_CLOSED_DOOR&& grid != DNGN_SECRET_DOOR));}// Counts the number of mutually unreachable areas in the map,// excluding isolated zones within vaults (we assume the vault author// knows what she's doing). This is an easy way to check whether a map// has isolated parts of the level that were not formerly isolated.//// All squares within vaults are treated as non-reachable, to simplify// life, because vaults may change the level layout and isolate// different areas without changing the number of isolated areas.// Here's a before and after example of such a vault that would cause// problems if we considered floor in the vault as non-isolating (the// vault is represented as V for walls and o for floor squares in the// vault).//// Before://// xxxxx xxxxx// x<..x x.2.x// x.1.x xxxxx 3 isolated zones// x>..x x.3.x// xxxxx xxxxx//// After://// xxxxx xxxxx// x<1.x x.2.x// VVVVVVVVVVoooV 3 isolated zones, but the isolated zones are different.// x>3.x x...x// xxxxx xxxxx//static int dgn_count_disconnected_zones(){memset(travel_point_distance, 0, sizeof(travel_distance_grid_t));int nzones = 0;for (int y = 0; y < GYM; ++y){for (int x = 0; x < GXM; ++x){if (travel_point_distance[x][y] || dgn_map_mask[x][y])continue;if (dgn_grid_is_isolating(grd[x][y]))continue;dgn_fill_zone(coord_def(x, y), ++nzones);}}return (nzones);
static void dgn_fill_zone(const coord_def &c, int zone){// No bounds checks, assuming the level has at least one layer of// rock border.travel_point_distance[c.x][c.y] = zone;for (int yi = -1; yi <= 1; ++yi){for (int xi = -1; xi <= 1; ++xi){if (!xi && !yi)continue;const coord_def cp(c.x + xi, c.y + yi);if (travel_point_distance[cp.x][cp.y]|| dgn_map_mask(cp)|| dgn_grid_is_isolating(grd(cp))){continue;}dgn_fill_zone(cp, zone);}}}
static void dgn_verify_connectivity(unsigned nvaults){// After placing vaults, make sure parts of the level have not been// disconnected.if (!dgn_level_vetoed && dgn_zones && nvaults != level_vaults.size()){const int newzones = dgn_count_disconnected_zones();if (newzones > dgn_zones){dgn_level_vetoed = true;#ifdef DEBUG_DIAGNOSTICSstd::ostringstream vlist;for (unsigned i = nvaults; i < level_vaults.size(); ++i){if (i > nvaults)vlist << ", ";vlist << level_vaults[i].map.name;}mprf(MSGCH_DIAGNOSTICS,"VETO: %s broken by [%s] (had %d zones, ""now have %d zones.",level_id::current().describe().c_str(),vlist.str().c_str(), dgn_zones, newzones);#endif}}}
// Try to place minivaults that really badly want to be placed. Still// no guarantees, seeing this is a minivault.if (!player_in_branch(BRANCH_SHOALS))place_special_minivaults(level_number, level_type);
const unsigned nvaults = level_vaults.size();// Any further vaults must make sure not to disrupt level layout.dgn_check_connectivity = true;// Try to place minivaults that really badly want to be placed. Still// no guarantees, seeing this is a minivault.if (!player_in_branch(BRANCH_SHOALS))place_special_minivaults(level_number, level_type);place_branch_entrances( level_number, level_type );place_extra_vaults();dgn_verify_connectivity(nvaults);if (dgn_level_vetoed)return;if (!player_in_branch( BRANCH_ECUMENICAL_TEMPLE ))place_traps(level_number);
if (mg_vetoes){fprintf(outf, "\n\nMost vetoed levels:\n");std::multimap<int, level_id> sortedvetos;for (std::map< level_id, std::pair<int, int> >::const_iteratori = mapgen_map_builds.begin(); i != mapgen_map_builds.end();++i){if (!i->second.second)continue;sortedvetos.insert(std::pair<int, level_id>( i->second.second, i->first ));}
int count = 0;for (std::multimap<int, level_id>::reverse_iteratori = sortedvetos.rbegin(); i != sortedvetos.rend(); ++i){const int vetoes = i->first;const int tries = mapgen_map_builds[i->second].first;fprintf(outf, "%3d) %s (%d of %d vetoed, %.2f%%)\n",++count, i->second.describe().c_str(),vetoes, tries, vetoes * 100.0 / tries);}}