git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4169 c06c8d41-db1a-0410-9941-cceddc491573
W45PMU4HNPSAMMEBJ4XH4MTHLPVIASZT4FXTBPID5LFXKIMNUBKAC
W52PTX4I7TUG2LS36FJHLZ72DWCVXGUCTUIKPI3IGEYO5KWL6OVAC
DHOSSNN4CUCGXX32MBLW6BAHHH5HUE4SAC6BNFHAG2OZZP6JQ7LAC
ZI6K4LOBYQJKSMHZ766HTJS66AL2KB6IYSBUYPETTKPOKW4ZNK7AC
B7MSPF6X2RLGWN4M6ZZF3WSOPKGYPTTD7LIJVST7DXN27DG6JHNAC
JR4ZZK4HOXQIG3WXBGTPZAPPNF7HHBCUZ3TE7RBCS64NHCOX7B2QC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
C22455VGUQOSUX2OORA32LROFQ7NNYDMD2ZDTTUZSAQLXK4AD6QAC
TLA5UN6LZPXGKERI27EFY4HKIIU3VU5Y7ZU54WXL6ANBUV2VOTMQC
2YSMM7QMFZOPD5NXAD2OAMDJEY5LOZO4NCYBC7UCQVANKINJRNBAC
XAFFD52IHN6FWFR2TT5F2KCUS7HAVCBI5CWTFMKPQG77GGTGAHLAC
TLO257LZSB6ZO36STDUEWJBO2LETXFKTFGXELA6Y4BZBVAEIIINAC
45EMD3KLQPMERNMIKU5G76H6556XOMIW352TSBP7VLWJX2YYGS7AC
FSD7GIK3YLZXWLEH37BU6KV3IUCFGXPQL6IZ7H65YWNRBEKDBX5AC
ED62QWGKBPORWVKDFOQRKJXEIWZVNGR3O4KWQBDSRNPT36AYOQYAC
2WRXQTGYDBLV46WRNVIUKGNA5QS563XZNNW3N2L6PVOCHIP2YGHQC
2G55UEHQ7554OPNSZVTUCZTWSHIFKGT56QEGSYFKCTX547I4AL3AC
GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC
AO3KHGKGSX2ZR24KJVIOTUY7EHYHMMI5W4HN3CAG4YGQHBOHLGDQC
SCWXQW5H65OXUP2MEJ2MEEAVPSRJDT3RQGKYCMKVTORS2334PQSQC
E5JKWMBVQQGVSCAX4UOGHI6QW5RFOX6PJB77LHL3UI2NJ427BFFQC
D6AJOTSOJNLJBBLQC2RAQOTPJJQENNBBVNRP45CZKDUHLLZLBFFQC
3XZOL3FFQZITUJIGDD6B6V6ZYMBN524JKNN6ZPJAXEC7RY433I3QC
PJ52ZBDCBPZMFAH5VRITX3OM67W4DCSZQP3BG44GU6N3DQC2YSEAC
56C44YMFHZ62GXAAOLYSLLGBVGRWXB53W2VI37Q26ZECEK2XG5SQC
IVVTHLTTLOP5TSULXJWUSSXHOKYWVU3OWKYVK45A7RIB6V34MYQAC
ECJNCUSSE63BKED3EAYIXQCI62I76QGNHCSFO3CDWPRZF3JQP44QC
MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC
7J3H7JY6AUO2UHNF6DAHDZI4O33JMTUUTYTPRM3CKNPUOF2RQOGAC
KCHX2F3JFEWOZT3WMJVZAAQUU2QSZ5Q7RDCD7WUJ7VE65J52JFUQC
ZHFUXYUHS6V47WK2NRH7OU6RX77NRKTXOZC3MND2GG7PEEWSGFTAC
IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC
ZVK4J5HTKFNOOIVCI62ZWEYGXEE5TYJ65DLYYZAZWTADFSXE62ZAC
WLX2RQMMOMP2PYPAGJRM4VFD2WTLJTOAZZPPY3MV76FU2EGEJ54QC
H3552BCIAVBLKAYKE4DHFLBLFW5RGRMYBMRRYHYEB5IPIJRUVU5QC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
7PRZJ6KZLG26YVTAMXT7YOTQLWZHGWGRTKXZZ52P4XYCQD4GT5WQC
4KZCX2DSUCAWFYONVHEM7EXGF3KNNKZEIA2N3Z6ICLBQLQJHOG5AC
5BJPWUPLJFS34FUTFJVKA4A52YMIGV6EWDXLNSDCWBJWBGVSQFGQC
5UVDIVD4NSXA52U4QMQIVST3GSZJ2A2YZK3RUEXKPM43YVQ7LI5AC
TZ55IZNANEJO2WDTKYWVLY2W2VV6BR7WKIN7XLNISAMMFT6LG2WQC
WWR4IDWLXP4XLBWDZBA5GFG7CRKUJQNRK7FFUFOISK6OJTMYQPFQC
// Returns true if the given square is okay for use by any character,
// but always false for squares in non-transparent vaults. This
// function returns sane results only immediately after dungeon generation
// (specifically, saving and restoring a game discards information on the
// vaults used in the current level).
bool dgn_square_is_passable(const coord_def &c);
// 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));
}
static inline bool _dgn_square_is_passable(const coord_def &c)
{
return (!(dgn_map_mask(c) & MMT_OPAQUE) && _dgn_grid_is_passable(grd(c)));
return (!(dgn_Map_Mask(c) & MMT_OPAQUE) &&
is_travelsafe_square(c.x, c.y, false, true));
static void _dgn_fill_zone( const coord_def &c, int zone, point_record &prec,
bool (*passable)(const coord_def &)
= _dgn_square_is_passable)
static bool _dgn_fill_zone(
const coord_def &start, int zone,
point_record &record_point,
bool (*passable)(const coord_def &) = dgn_square_is_passable,
bool (*iswanted)(const coord_def &) = NULL)
travel_point_distance[c.x][c.y] = zone;
for (int yi = -1; yi <= 1; ++yi)
for (int xi = -1; xi <= 1; ++xi)
for (points[cur].push_back(start); !points[cur].empty(); )
{
for (std::list<coord_def>::const_iterator i = points[cur].begin();
i != points[cur].end(); ++i)
const coord_def cp(c.x + xi, c.y + yi);
if (travel_point_distance[cp.x][cp.y] || !passable(cp))
continue;
travel_point_distance[c.x][c.y] = zone;
if (iswanted && iswanted(c))
ret = true;
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 (!map_bounds(cp)
|| travel_point_distance[cp.x][cp.y] || !passable(cp))
continue;
_dgn_fill_zone(coord_def(x, y), ++nzones, _dgn_point_record_stub);
bool found_exit_stair =
_dgn_fill_zone(coord_def(x, y), ++nzones,
_dgn_point_record_stub,
dgn_square_is_passable,
choose_stairless? _is_exit_stair : NULL);
// If we want only stairless zones, screen out zones that did
// have stairs.
if (choose_stairless && found_exit_stair)
--nzones;
}
}
// Also check for isolated regions that have no stairs.
if (you.level_type == LEVEL_DUNGEON
&& !(branches[you.where_are_you].branch_flags & BFLAG_ISLANDED)
&& _dgn_count_disconnected_zones(true) > 0)
{
dgn_level_vetoed = true;
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS,
"VETO: %s has isolated areas with no stairs.",
level_id::current().describe().c_str());
#endif
return;
}
}
static map_mask mg_MapMask;
static bool _mg_region_flood(const coord_def &c, int region, bool flag)
{
bool found_exit = false;
mg_MapMask(c) = region;
if (flag)
{
env.map(c).flags = 0;
set_terrain_mapped(c.x, c.y);
}
const dungeon_feature_type ft = grd(c);
if (is_travelable_stair(ft))
found_exit = true;
for (int yi = -1; yi <= 1; ++yi)
for (int xi = -1; xi <= 1; ++xi)
{
if (!xi && !yi)
continue;
coord_def ci = c + coord_def(xi, yi);
if (!in_bounds(ci) || mg_MapMask(ci) || !dgn_square_is_passable(ci))
continue;
if (_mg_region_flood(ci, region, flag))
found_exit = true;
}
return (found_exit);
}
static bool _mg_is_disconnected_level()
{
// Don't care about non-Dungeon levels.
if (you.level_type != LEVEL_DUNGEON
|| (branches[you.where_are_you].branch_flags & BFLAG_ISLANDED))
return (false);
std::vector<coord_def> region_seeds;
mg_MapMask.init(0);
coord_def c;
int region = 0;
int good_regions = 0;
for (c.y = 0; c.y < GYM; ++c.y)
for (c.x = 0; c.x < GXM; ++c.x)
if (!mg_MapMask(c) && dgn_square_is_passable(c))
{
if (_mg_region_flood(c, ++region, false))
++good_regions;
else
region_seeds.push_back(c);
}
mg_MapMask.init(0);
for (int i = 0, size = region_seeds.size(); i < size; ++i)
_mg_region_flood(region_seeds[i], 1, true);
return (good_regions < region);
continue;
}
for (int y = 0; y < GYM; ++y)
for (int x = 0; x < GXM; ++x)
{
switch (grd[x][y])
{
case DNGN_SECRET_DOOR:
grd[x][y] = DNGN_CLOSED_DOOR;
break;
default:
break;
}
}
{
unwind_bool wiz(you.wizard, true);
magic_mapping(1000, 100, true, true);
}
if (_mg_is_disconnected_level())
{
extern std::vector<vault_placement> Level_Vaults;
std::string vaults;
for (int j = 0, size = Level_Vaults.size(); j < size; ++j)
{
if (j && !vaults.empty())
vaults += ", ";
vaults += Level_Vaults[j].map.name;
}
if (!vaults.empty())
vaults = " (" + vaults + ")";
extern std::string dgn_Build_Method;
mprf(MSGCH_WARN,
"Bad (disconnected) level on %s%s",
level_id::current().describe().c_str(),
vaults.c_str());
FILE *fp = fopen("map.dump", "w");
fprintf(fp, "Bad (disconnected) level (%s) on %s%s.\n\n",
dgn_Build_Method.c_str(),
level_id::current().describe().c_str(),
vaults.c_str());
// Mapping would only have mapped squares that the player can
// reach - explicitly map the full level.
for (int y = 0; y < GYM; ++y)
for (int x = 0; x < GXM; ++x)
set_envmap_obj(x, y, grd[x][y]);
dump_map(fp);
return (false);
}
MONS: red draconian/green draconian/yellow draconian/pale draconian/black draconian/grey draconian/purple draconian
MONS: grey draconian monk/pale draconian knight/green draconian annihilator/purple draconian knight
MONS: red draconian/green draconian/yellow draconian/pale draconian/black draconian/purple draconian
MONS: pale draconian knight/green draconian annihilator/purple draconian knight