summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-26 15:43:29 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-26 15:43:29 +0000
commit13d0f16c1a40183c0561bd1ca6d5ac645788cd30 (patch)
treeddb54cd5a46f47afb5a4a0428bc040dbaac99805 /crawl-ref
parent265597e3aacbd17cb2ea57610209fccadf5e6ee5 (diff)
downloadcrawl-ref-13d0f16c1a40183c0561bd1ca6d5ac645788cd30.tar.gz
crawl-ref-13d0f16c1a40183c0561bd1ca6d5ac645788cd30.zip
Add blood and glass to labyrinths.
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
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/dungeon.cc200
-rw-r--r--crawl-ref/source/misc.cc30
-rw-r--r--crawl-ref/source/misc.h2
-rw-r--r--crawl-ref/source/tile2.cc2
4 files changed, 219 insertions, 15 deletions
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 5255a053fe..68e4bfd606 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -6666,6 +6666,203 @@ static void _labyrinth_place_entry_point(const dgn_region &region,
env.markers.add(new map_feature_marker(p, DNGN_ENTER_LABYRINTH));
}
+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 &region)
+{
+ 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 &region)
+{
+ 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 &region,
+ 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 &region)
+{
+ 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);
+ }
+}
+
static void _labyrinth_level(int level_number)
{
dgn_Layout_Type = "labyrinth";
@@ -6726,6 +6923,9 @@ static void _labyrinth_level(int level_number)
_change_labyrinth_border(lab, DNGN_METAL_WALL);
+ _labyrinth_add_blood_trail(lab);
+ _labyrinth_add_glass_walls(lab);
+
_labyrinth_place_entry_point(lab, end);
link_items();
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 43b9951ba1..7e4dd3fdd0 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -1127,8 +1127,9 @@ static bool allow_bleeding_on_square(const coord_def& where)
return (true);
}
-static void maybe_bloodify_square(const coord_def& where, int amount,
- bool spatter = false)
+static void _maybe_bloodify_square(const coord_def& where, int amount,
+ bool spatter = false,
+ bool smell_alert = true)
{
if (amount < 1)
return;
@@ -1146,22 +1147,25 @@ static void maybe_bloodify_square(const coord_def& where, int amount,
if (allow_bleeding_on_square(where))
env.map(where).property |= FPROP_BLOODY;
- // 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);
+ }
if (spatter)
{
// Smaller chance of spattering surrounding squares.
- for ( adjacent_iterator ai(where); ai; ++ai )
+ for (adjacent_iterator ai(where); ai; ++ai)
{
// Spattering onto walls etc. less likely.
if (grd(*ai) < DNGN_MINMOVE && !one_chance_in(3))
continue;
- maybe_bloodify_square(*ai, amount/15);
+ _maybe_bloodify_square(*ai, amount/15);
}
}
}
@@ -1171,18 +1175,18 @@ static void maybe_bloodify_square(const coord_def& where, int amount,
// "damage" depends on damage taken (or hitpoints, if damage higher),
// or, for sacrifices, on the number of chunks possible to get out of a corpse.
void bleed_onto_floor(const coord_def& where, int montype,
- int damage, bool spatter)
+ int damage, bool spatter, bool smell_alert)
{
ASSERT(in_bounds(where));
if (!victim_can_bleed(montype))
return;
- maybe_bloodify_square(where, damage, spatter);
+ _maybe_bloodify_square(where, damage, spatter, smell_alert);
}
static void _spatter_neighbours(const coord_def& where, int chance)
{
- for ( adjacent_iterator ai(where, false); ai; ++ai )
+ for (adjacent_iterator ai(where, false); ai; ++ai)
{
if (!allow_bleeding_on_square(*ai))
continue;
@@ -2477,7 +2481,7 @@ void new_level(void)
}
else
take_note(Note(NOTE_DUNGEON_LEVEL_CHANGE));
-
+
print_stats_level();
#ifdef DGL_WHEREIS
whereis_record();
diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h
index 0eb05999b0..a228cebea1 100644
--- a/crawl-ref/source/misc.h
+++ b/crawl-ref/source/misc.h
@@ -42,7 +42,7 @@ void split_potions_into_decay( int obj, int amount, bool need_msg = true );
bool victim_can_bleed(int montype);
void bleed_onto_floor(const coord_def& where, int mon, int damage,
- bool spatter = false);
+ bool spatter = false, bool smell_alert = true);
void generate_random_blood_spatter_on_level();
// last updated 12may2000 {dlb}
diff --git a/crawl-ref/source/tile2.cc b/crawl-ref/source/tile2.cc
index d228f35922..70943d6c5d 100644
--- a/crawl-ref/source/tile2.cc
+++ b/crawl-ref/source/tile2.cc
@@ -66,7 +66,7 @@ int get_floor_special_tile_idx()
}
// TODO: Add this sort of determinism to the lua maps,
-// at least for the portal walls.
+// at least for the portal vaults.
void WallIdx(int &wall, int &floor, int &special)
{
// Note: This function must be deterministic.