In ASCII wizard mode these features are highlighted in the level map (&{) and can then easily be reached via xm (normal map), but only until the first shift takes place. Feedback welcome!
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7637 c06c8d41-db1a-0410-9941-cceddc491573
HBRUWIHAOFRF57K4D7TNGLVAFWP3SLH6UUMQCSVKBFOKG3KYTRVQC
OHKIZHRISXKWSVNXJF2YJRK5OL72K4LUOSV7FACX6VN6AUDPLXCAC
ZWFOOUUA5VCYOXGAHE76DXW65ME4AH2DVN6JVNGZAKTHZNDTVOJAC
25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC
TGJZXTUIAKCFZQJ54ZQEBGFBVZSJCAX6AWDRSH3TP7UJRLGUM5SAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
YF2GZWXNV6NVFFEBEOYS67JQJQK2IUS5BZMGJW3XQPYIJYHQJCEQC
MJWFTUS66PTCNEYXEJA3CUJFXNWXIKDD6H3V24PW7HK64NSVOFSAC
VXSORUQOM2VZA4CAZDC6KPAY373NQIN3UT7CXQXTRCYXO2WM62DAC
TO43FWKHNIA5MVDOFXYHQODTLBQYEZKX5UIUGID57436UF7G2EXQC
J7GPW2YXLT6FGSKJ24FGQ24GTRZ6A2BDYM6CIXV4R6YBEHP6BGPAC
C5U3HSOOQ7BKXKXIDS7MLVXUKDTHAWJ5NXNX6YDXTM3GWY5UWX4QC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
5XNQ3SSNBFXFNWA6DPM74W6FH65NX665P3DMH6YCWVFOPZTJSYCQC
L2PY64KUK7XYXNWKTC6YUN5DZYDNHNQFQHICUVNRGRHBHZAXWH3AC
QYUAYEGK7WPBJLZRSWZVDWD5SMNAWWIJSQPWYA7BEYXMEBD2SDKAC
NOVUGMZP3BXO52ZIWBS7TVFJXAJJURJCZXVDX5ZC3NYLD4DM6OZAC
PJ7HBIWAV3H23LXGZAAD2QYJ7HMOFOIR5ZJ4U2UTHI766LOTRRWQC
PF6QKUU7AKP3X7NBR34O73PQ4BS2MWBMPD5MH5HOV2HLQFMA3PZQC
XPTDBTPHD5CIPPOHIPMI7HBOTQIGGJPYKDOJCHWG2ZTI7SLUHTEAC
// If old or new blood on square, the smell reaches further.
if (testbits(env.map(where).property, FPROP_BLOODY))
blood_smell(12, where);
else // Still allow a lingering smell.
blood_smell(7, where);
if (smell_alert)
{
// If old or new blood on square, the smell reaches further.
if (testbits(env.map(where).property, FPROP_BLOODY))
blood_smell(12, where);
else // Still allow a lingering smell.
blood_smell(7, where);
}
}
static bool _is_deadend(const coord_def pos)
{
std::vector<coord_def> dirs;
dirs.push_back(coord_def(0, -1));
dirs.push_back(coord_def(1, 0));
dirs.push_back(coord_def(0, 1));
dirs.push_back(coord_def(-1, 0));
int count_neighbours = 0;
for (unsigned int i = 0; i < dirs.size(); i++)
{
coord_def p = pos + dirs[i];
if (!in_bounds(p))
continue;
if (grd(p) == DNGN_FLOOR)
count_neighbours++;
}
return (count_neighbours <= 1);
}
static coord_def _find_random_deadend(const dgn_region ®ion)
{
int tries = 0;
coord_def result;
bool floor_pos = false;
while (++tries < 50)
{
coord_def pos = region.random_point();
if (grd(pos) != DNGN_FLOOR)
continue;
else if (!floor_pos)
{
result = pos;
floor_pos = true;
}
if (!_is_deadend(pos))
continue;
return (pos);
}
return (result);
}
// Adds a bloody trail ending in a dead end with spattered walls.
static void _labyrinth_add_blood_trail(const dgn_region ®ion)
{
if (one_chance_in(5))
return;
int count_trails = 1 + one_chance_in(5) + one_chance_in(7);
int tries = 0;
while (++tries < 20)
{
const coord_def start = _find_random_deadend(region);
const coord_def dest = region.random_point();
monster_pathfind mp;
if (!mp.init_pathfind(dest, start))
continue;
const std::vector<coord_def> path = mp.backtrack();
if (path.size() < 10)
continue;
env.map(start).property |= FPROP_BLOODY;
#ifdef WIZARD
env.map(start).property |= FPROP_HIGHLIGHT;
#endif
bleed_onto_floor(start, MONS_HUMAN, 150, true, false);
for (unsigned int step = 0; step < path.size(); step++)
{
coord_def pos = path[step];
if (step < 2 || step < 12 && coinflip()
|| step >= 12 && one_chance_in(step/4))
{
env.map(pos).property |= FPROP_BLOODY;
}
#ifdef WIZARD
env.map(pos).property |= FPROP_HIGHLIGHT;
#endif
if (step >= 10 && one_chance_in(7))
break;
}
if (--count_trails > 0)
continue;
break;
}
}
static bool _find_random_nonmetal_wall(const dgn_region ®ion,
coord_def &pos)
{
int tries = 0;
while (++tries < 50)
{
pos = region.random_point();
if (!in_bounds(pos))
continue;
if (grd(pos) == DNGN_ROCK_WALL || grd(pos) == DNGN_STONE_WALL)
return (true);
}
return (false);
}
static bool _grid_has_wall_neighbours(const coord_def pos, const coord_def dir)
{
std::vector<coord_def> dirs;
dirs.push_back(coord_def(0, -1));
dirs.push_back(coord_def(1, 0));
dirs.push_back(coord_def(0, 1));
dirs.push_back(coord_def(-1, 0));
for (unsigned int i = 0; i < dirs.size(); i++)
{
coord_def p = pos + dirs[i];
if (!in_bounds(p))
continue;
if (dirs[i] == dir)
continue;
if (grd(p) == DNGN_ROCK_WALL || grd(p) == DNGN_STONE_WALL)
return (true);
}
return (false);
}
static void _vitrify_wall_neighbours(const coord_def pos)
{
// This hinges on clear wall types having the same order as non-clear ones!
const int clear_plus = DNGN_CLEAR_ROCK_WALL - DNGN_ROCK_WALL;
std::vector<coord_def> dirs;
dirs.push_back(coord_def(0, -1));
dirs.push_back(coord_def(1, 0));
dirs.push_back(coord_def(0, 1));
dirs.push_back(coord_def(-1, 0));
for (unsigned int i = 0; i < dirs.size(); i++)
{
coord_def p = pos + dirs[i];
if (!in_bounds(p))
continue;
// Don't vitrify vault grids
if (testbits(env.map(p).property, FPROP_VAULT))
continue;
if (grd(p) == DNGN_ROCK_WALL || grd(p) == DNGN_STONE_WALL)
{
grd(p) = static_cast<dungeon_feature_type>(grd(p) + clear_plus);
#ifdef WIZARD
env.map(p).property |= FPROP_HIGHLIGHT;
#endif
if (one_chance_in(3) || _grid_has_wall_neighbours(p, dirs[i]))
_vitrify_wall_neighbours(p);
}
}
}
static void _labyrinth_add_glass_walls(const dgn_region ®ion)
{
int glass_num = random2(3) + random2(4);
if (!glass_num)
return;
// This hinges on clear wall types having the same order as non-clear ones!
const int clear_plus = DNGN_CLEAR_ROCK_WALL - DNGN_ROCK_WALL;
coord_def pos;
while (0 < glass_num--)
{
if (!_find_random_nonmetal_wall(region, pos))
break;
if (_has_vault_in_radius(pos, 6, MMT_VAULT))
continue;
grd(pos) = static_cast<dungeon_feature_type>(grd(pos) + clear_plus);
#ifdef WIZARD
env.map(pos).property |= FPROP_HIGHLIGHT;
#endif
_vitrify_wall_neighbours(pos);
}