summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/docs/options_guide.txt11
-rw-r--r--crawl-ref/settings/init.txt1
-rw-r--r--crawl-ref/source/delay.cc5
-rw-r--r--crawl-ref/source/externs.h2
-rw-r--r--crawl-ref/source/initfile.cc4
-rw-r--r--crawl-ref/source/misc.cc40
-rw-r--r--crawl-ref/source/misc.h2
-rw-r--r--crawl-ref/source/monstuff.cc8
-rw-r--r--crawl-ref/source/view.cc5
9 files changed, 75 insertions, 3 deletions
diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt
index 10808897e0..3e41f02daf 100644
--- a/crawl-ref/docs/options_guide.txt
+++ b/crawl-ref/docs/options_guide.txt
@@ -51,7 +51,7 @@ The contents of this text are:
travel_stop_message, force_more_message,
runrest_ignore_message, runrest_ignore_poison,
runrest_ignore_monster, trapwalk_safe_hp,
- trap_prompt, rest_wait_both
+ trap_prompt, rest_wait_both, auto_exclude
4-h Stashes.
stash_filter, annotate_item_class,
annoate_item_dropped
@@ -895,7 +895,14 @@ rest_wait_both = false
If rest_wait_both is set to true then resting will only stop
when both HP and MP are fully restored, not when either one of
them is restored.
-
+
+auto_exclude = <list of monster names>
+ Whenever you encounter a sleeping or stationary monster during
+ exploration that is included in this list, automatically a
+ travel exclusion is set centered on this monster, meaning
+ autoexplore won't ever bring you in its line of sight. If the
+ monster dies or wakes up while you are in sight, this exclusion
+ is automatically removed again.
4-h Stashes.
----------------
diff --git a/crawl-ref/settings/init.txt b/crawl-ref/settings/init.txt
index 0f082af20b..1220add8d1 100644
--- a/crawl-ref/settings/init.txt
+++ b/crawl-ref/settings/init.txt
@@ -161,6 +161,7 @@ trap_item_brand = reverse
# explore_greedy = false
# explore_stop = items,greedy_items,stairs,shops,altars,gates
# explore_improved = true
+auto_exclude = oklob plant,silver statue,orange crystal statue
# tc_reachable = blue
# tc_dangerous = cyan
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index eb9fd015d5..eea7f5820a 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -1657,6 +1657,11 @@ inline static void _monster_warning(activity_interrupt_type ai,
}
else
{
+ // If the monster is in the auto_exclude list, automatically
+ // set an exclusion.
+ if (need_auto_exclude(mon) && !is_exclude_root(mon->pos()))
+ toggle_exclude(mon->pos());
+
std::string text = mon->name(DESC_CAP_A);
// For named monsters also mention the base type.
if (!(mon->mname).empty() && mon->type != MONS_PLAYER_GHOST)
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index a200989c4f..6214570cd7 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1813,6 +1813,8 @@ public:
int tc_exclude_circle; // Colour for squares in the exclusion radius
int tc_dangerous; // Colour for trapped squares, deep water, lava.
int tc_disconnected;// Areas that are completely disconnected.
+ std::vector<text_pattern> auto_exclude; // Automatically set an exclusion
+ // around certain monsters.
int travel_stair_cost;
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index ab9a548b7b..12b3f47370 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -2652,6 +2652,10 @@ void game_options::read_option_line(const std::string &str, bool runscript)
{
tc_disconnected = str_to_colour(field, tc_disconnected);
}
+ else if (key == "auto_exclude")
+ {
+ append_vector(auto_exclude, split_string(",", field));
+ }
else BOOL_OPTION(classic_item_colours);
else BOOL_OPTION(item_colour);
else BOOL_OPTION_NAMED("item_color", item_colour);
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 212636c8ca..609c107a39 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -2326,6 +2326,46 @@ bool mons_is_safe(const struct monsters *mon, bool want_move)
return (is_safe);
}
+static bool _mon_needs_auto_exclude(const monsters *mon, bool sleepy = false)
+{
+ if (mons_is_stationary(mon))
+ {
+ if (sleepy)
+ return (false);
+
+ // Don't give away mimics unless already known.
+ return (!mons_is_mimic(mon->type)
+ || testbits(mon->flags, MF_KNOWN_MIMIC));
+ }
+ // Auto exclusion only makes sense if the monster is still asleep.
+ return (mons_is_sleeping(mon));
+}
+
+// Check whether a given monster is listed in the auto_exclude option.
+bool need_auto_exclude(const monsters *mon, bool sleepy)
+{
+ // This only works if the name is lowercased.
+ std::string name = mon->name(DESC_BASENAME);
+ lowercase(name);
+
+ for (unsigned i = 0; i < Options.auto_exclude.size(); ++i)
+ if (Options.auto_exclude[i].matches(name)
+ && _mon_needs_auto_exclude(mon, sleepy))
+ {
+ return (true);
+ }
+
+ return (false);
+}
+
+// Clear auto exclusion if the monster is killed or wakes up with the
+// player in sight. If sleepy is true, stationary monsters are ignored.
+void remove_auto_exclude(const monsters *mon, bool sleepy)
+{
+ if (need_auto_exclude(mon, sleepy) && is_exclude_root(mon->pos()))
+ toggle_exclude(mon->pos());
+}
+
// Return all nearby monsters in range (default: LOS) that the player
// is able to recognize as being monsters (i.e. no unknown mimics or
// submerged creatures.)
diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h
index 21fc63889c..efccdec0c7 100644
--- a/crawl-ref/source/misc.h
+++ b/crawl-ref/source/misc.h
@@ -72,6 +72,8 @@ std::string weird_sound();
void curare_hits_player(int agent, int degree);
bool mons_is_safe(const monsters *mon, bool want_move = false);
+bool need_auto_exclude(const monsters *mon, bool sleepy = false);
+void remove_auto_exclude(const monsters *mon, bool sleepy = false);
std::vector<monsters*> get_nearby_monsters(bool want_move = false,
bool just_check = false,
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index ede0784ae7..f2549cd11d 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -775,6 +775,9 @@ void monster_die(monsters *monster, killer_type killer,
// Update list of monsters beholding player.
update_beholders(monster, true);
+ // Clear auto exclusion now the monster is killed.
+ remove_auto_exclude(monster);
+
const int monster_killed = monster_index(monster);
const bool hard_reset = testbits(monster->flags, MF_HARD_RESET);
const bool gives_xp = !monster->has_ench(ENCH_ABJ);
@@ -7603,6 +7606,11 @@ void seen_monster(monsters *monster)
// First time we've seen this particular monster.
monster->flags |= MF_SEEN;
+ // If the monster is in the auto_exclude list, automatically
+ // set an exclusion.
+ if (need_auto_exclude(monster) && !is_exclude_root(monster->pos()))
+ toggle_exclude(monster->pos());
+
if (!mons_is_mimic(monster->type)
&& MONST_INTERESTING(monster)
&& monster->type != MONS_PANDEMONIUM_DEMON
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index 9cc0467557..9239c33266 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -1178,9 +1178,12 @@ void monster_grid(bool do_updates)
if (monster->type != -1 && mons_near(monster))
{
if (do_updates && (mons_is_sleeping(monster)
- || mons_is_wandering(monster))
+ || mons_is_wandering(monster))
&& check_awaken(monster))
{
+ if (mons_near(monster))
+ remove_auto_exclude(monster, true);
+
behaviour_event( monster, ME_ALERT, MHITYOU );
handle_monster_shouts(monster);
}