summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorRobert Vollmert <rvollmert@gmx.net>2010-03-11 15:36:14 +0100
committerRobert Vollmert <rvollmert@gmx.net>2010-03-11 17:02:01 +0100
commit4cdaf99143c1297bdc7300893451de09c056bba4 (patch)
treee9b7151339399343313769abfd14ca3ab19a64f2 /crawl-ref/source
parentf4f0cf5d0b90244611aeb2622455a9606c633337 (diff)
downloadcrawl-ref-4cdaf99143c1297bdc7300893451de09c056bba4.tar.gz
crawl-ref-4cdaf99143c1297bdc7300893451de09c056bba4.zip
Fix monsters not using doors.
Previously, monsters would only open doors if they were straight on the way to their target. E.g.: @#g .+. g won't open the door if its target is @. This can be reproduced for example as follows (eg Sprint 1 start): .1#3. ..+.2 ..### Stand at one, open door, place monster at 2, close door. The monster will move to 3 and wait there until you open the door. I'm not sure why monsters didn't fall back to pathfinding if they couldn't get to you directly. These changes also unify some monster traversability checks between mon-pathfind and mon-act.
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/mon-act.cc82
-rw-r--r--crawl-ref/source/mon-pathfind.cc62
-rw-r--r--crawl-ref/source/mon-pathfind.h4
-rw-r--r--crawl-ref/source/mon-util.cc102
-rw-r--r--crawl-ref/source/mon-util.h4
5 files changed, 138 insertions, 116 deletions
diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc
index 4d892f267f..2b2e90e54b 100644
--- a/crawl-ref/source/mon-act.cc
+++ b/crawl-ref/source/mon-act.cc
@@ -2813,12 +2813,12 @@ static bool _mon_can_move_to_pos(const monsters *monster,
if (delta.x != 0 && delta.y != 0)
return (false);
}
- else if (!monster->can_pass_through_feat(target_grid)
- || no_water && feat_is_water(target_grid))
+ else if (no_water && feat_is_water(target_grid))
{
return (false);
}
- else if (!_habitat_okay(monster, target_grid))
+ else if (!mons_can_traverse(monster, targ, false)
+ && !_habitat_okay(monster, target_grid))
{
// If the monster somehow ended up in this habitat (and is
// not dead by now), give it a chance to get out again.
@@ -3098,6 +3098,31 @@ static bool _do_move_monster(monsters *monster, const coord_def& delta)
return (true);
}
+ if (mons_can_open_door(monster, f))
+ {
+ _mons_open_door(monster, f);
+ return (true);
+ }
+ else if (mons_can_eat_door(monster, f))
+ {
+ grd(f) = DNGN_FLOOR;
+
+ _jelly_grows(monster);
+
+ if (you.see_cell(f))
+ {
+ viewwindow(false);
+
+ if (!you.can_see(monster))
+ {
+ mpr("The door mysteriously vanishes.");
+ interrupt_activity( AI_FORCE_INTERRUPT );
+ }
+ else
+ simple_monster_message(monster, " eats the door!");
+ }
+ } // done door-eating jellies
+
// The monster gave a "comes into view" message and then immediately
// moved back out of view, leaing the player nothing to see, so give
// this message to avoid confusion.
@@ -3291,57 +3316,6 @@ static bool _monster_move(monsters *monster)
// Now we know where we _can_ move.
const coord_def newpos = monster->pos() + mmov;
- bool restricted = (env.markers.property_at(newpos,
- MAT_ANY, "door_restrict") == "veto");
- // Normal/smart monsters know about secret doors, since they live in
- // the dungeon, unless they're marked specifically not to be opened unless
- // already opened by the player {bookofjude}.
- if ((grd(newpos) == DNGN_CLOSED_DOOR
- || feat_is_secret_door(grd(newpos)) && mons_intel(monster) >= I_NORMAL)
- && !restricted)
- {
- if (mons_is_zombified(monster))
- {
- // For zombies, monster type is kept in mon->base_monster.
- if (mons_class_itemuse(monster->base_monster) >= MONUSE_OPEN_DOORS)
- {
- _mons_open_door(monster, newpos);
- return (true);
- }
- }
- else if (mons_itemuse(monster) >= MONUSE_OPEN_DOORS)
- {
- _mons_open_door(monster, newpos);
- return (true);
- }
- } // endif - secret/closed doors
-
- // Monsters that eat items (currently only jellies) also eat doors.
- // However, they don't realise that secret doors make good eating.
- if ((grd(newpos) == DNGN_CLOSED_DOOR || grd(newpos) == DNGN_OPEN_DOOR)
- && mons_itemeat(monster) == MONEAT_ITEMS
- // Doors with permarock marker cannot be eaten.
- && !feature_marker_at(newpos, DNGN_PERMAROCK_WALL)
- && !restricted)
- {
- grd(newpos) = DNGN_FLOOR;
-
- _jelly_grows(monster);
-
- if (you.see_cell(newpos))
- {
- viewwindow(false);
-
- if (!you.can_see(monster))
- {
- mpr("The door mysteriously vanishes.");
- interrupt_activity( AI_FORCE_INTERRUPT );
- }
- else
- simple_monster_message(monster, " eats the door!");
- }
- } // done door-eating jellies
-
// Water creatures have a preference for water they can hide in -- bwr
// [ds] Weakened the powerful attraction to deep water if the monster
// is in good health.
diff --git a/crawl-ref/source/mon-pathfind.cc b/crawl-ref/source/mon-pathfind.cc
index 0374285ba0..5c0e3774da 100644
--- a/crawl-ref/source/mon-pathfind.cc
+++ b/crawl-ref/source/mon-pathfind.cc
@@ -384,7 +384,7 @@ std::vector<coord_def> monster_pathfind::calc_waypoints()
return (waypoints);
}
-bool monster_pathfind::traversable(const coord_def p)
+bool monster_pathfind::traversable(const coord_def& p)
{
if (!traverse_unmapped && grd(p) == DNGN_UNSEEN)
return (false);
@@ -404,65 +404,9 @@ bool monster_pathfind::traversable(const coord_def p)
// Checks whether a given monster can pass over a certain position, respecting
// its preferred habit and capability of flight or opening doors.
-bool monster_pathfind::mons_traversable(const coord_def p)
+bool monster_pathfind::mons_traversable(const coord_def& p)
{
- const monster_type montype = mons_is_zombified(mons)
- ? mons_zombie_base(mons)
- : mons->type;
- const dungeon_feature_type feat = grd(p);
- // Monsters that can't open doors won't be able to pass them, and
- // only monsters of normal or greater intelligence can pathfind through
- // secret doors.
- if (feat == DNGN_CLOSED_DOOR ||
- (mons_intel(mons) >= I_NORMAL &&
- (feat == DNGN_DETECTED_SECRET_DOOR || feat == DNGN_SECRET_DOOR)))
- {
- if (mons->is_habitable_feat(DNGN_FLOOR))
- {
- if (env.markers.property_at(p, MAT_ANY, "door_restrict") == "veto")
- return (false);
- if (mons_eats_items(mons))
- return (true);
- else if (mons_is_zombified(mons))
- {
- if (mons_class_itemuse(montype) >= MONUSE_OPEN_DOORS)
- return (true);
- }
- else if (mons_itemuse(mons) >= MONUSE_OPEN_DOORS)
- return (true);
- }
- }
-
- if (!mons->is_habitable_feat(grd(p)))
- return (false);
-
- // Your friends only know about doors you know about, unless they feel
- // at home in this branch.
- if (grd(p) == DNGN_SECRET_DOOR && mons->friendly()
- && (mons_intel(mons) < I_NORMAL || !mons_is_native_in_branch(mons)))
- {
- return (false);
- }
-
- const trap_def* ptrap = find_trap(p);
- if (ptrap)
- {
- const trap_type tt = ptrap->type;
-
- // Don't allow allies to pass over known (to them) Zot traps.
- if (tt == TRAP_ZOT
- && ptrap->is_known(mons)
- && mons->friendly())
- {
- return (false);
- }
-
- // Monsters cannot travel over teleport traps.
- if (!can_place_on_trap(montype, tt))
- return (false);
- }
-
- return (true);
+ return (mons_can_traverse(mons, p));
}
int monster_pathfind::travel_cost(coord_def npos)
diff --git a/crawl-ref/source/mon-pathfind.h b/crawl-ref/source/mon-pathfind.h
index 9507680f31..4be31dbed1 100644
--- a/crawl-ref/source/mon-pathfind.h
+++ b/crawl-ref/source/mon-pathfind.h
@@ -26,9 +26,9 @@ public:
protected:
// protected methods
bool calc_path_to_neighbours(void);
- bool traversable(coord_def p);
+ bool traversable(const coord_def& p);
int travel_cost(coord_def npos);
- bool mons_traversable(coord_def p);
+ bool mons_traversable(const coord_def& p);
int mons_travel_cost(coord_def npos);
int estimated_cost(coord_def npos);
void add_new_pos(coord_def pos, int total);
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 5ed1af303d..7011355f40 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -17,6 +17,7 @@
#include "coordit.h"
#include "database.h"
#include "directn.h"
+#include "env.h"
#include "fprop.h"
#include "fight.h"
#include "ghost.h"
@@ -24,6 +25,7 @@
#include "itemname.h"
#include "kills.h"
#include "libutil.h"
+#include "mapmark.h"
#include "mislead.h"
#include "mon-behv.h"
#include "mon-clone.h"
@@ -38,8 +40,8 @@
#include "spl-util.h"
#include "state.h"
#include "stuff.h"
-#include "env.h"
#include "terrain.h"
+#include "traps.h"
#include "viewchar.h"
//jmf: moved from inside function
@@ -3115,6 +3117,104 @@ bool mons_can_pass(const monsters *mon, dungeon_feature_type grid)
return (mons_class_can_pass(montype, grid));
}
+static bool _mons_can_open_doors(const monsters *mon)
+{
+ // Zombies inherit base monster's open doors capability, but not
+ // other item use.
+ if (mons_is_zombified(mon))
+ return (mons_class_itemuse(mon->base_monster) >= MONUSE_OPEN_DOORS);
+ else
+ return (mons_itemuse(mon) >= MONUSE_OPEN_DOORS);
+}
+
+// Some functions that check whether a monster can open/eat/pass a
+// given door. These all return false if there's no closed door there.
+
+// Normal/smart monsters know about secret doors, since they live in
+// the dungeon, unless they're marked specifically not to be opened unless
+// already opened by the player {bookofjude}.
+bool mons_can_open_door(const monsters* mon, const coord_def& pos)
+{
+ if (env.markers.property_at(pos, MAT_ANY, "door_restrict") == "veto")
+ return (false);
+
+ if (!_mons_can_open_doors(mon))
+ return (false);
+
+ dungeon_feature_type feat = env.grid(pos);
+ return (feat == DNGN_CLOSED_DOOR
+ || feat_is_secret_door(feat) && mons_intel(mon) >= I_NORMAL);
+}
+
+// Monsters that eat items (currently only jellies) also eat doors.
+// However, they don't realise that secret doors make good eating.
+bool mons_can_eat_door(const monsters* mon, const coord_def& pos)
+{
+ if (mons_itemeat(mon) != MONEAT_ITEMS)
+ return (false);
+
+ dungeon_feature_type feat = env.grid(pos);
+ if (feat == DNGN_OPEN_DOOR)
+ return (true);
+
+ if (env.markers.property_at(pos, MAT_ANY, "door_restrict") == "veto"
+ // Doors with permarock marker cannot be eaten.
+ || feature_marker_at(pos, DNGN_PERMAROCK_WALL))
+ {
+ return (false);
+ }
+
+ return (feat == DNGN_CLOSED_DOOR);
+}
+
+static bool _mons_can_pass_door(const monsters* mon, const coord_def& pos)
+{
+ return (mons_can_pass(mon, DNGN_FLOOR)
+ && (mons_can_open_door(mon, pos)
+ || mons_can_eat_door(mon, pos)));
+}
+
+bool mons_can_traverse(const monsters* mons, const coord_def& p,
+ bool checktraps)
+{
+ if (_mons_can_pass_door(mons, p))
+ return (true);
+
+ if (!mons->is_habitable_feat(env.grid(p)))
+ return (false);
+
+ // Your friends only know about doors you know about, unless they feel
+ // at home in this branch.
+ if (grd(p) == DNGN_SECRET_DOOR && mons->friendly()
+ && (mons_intel(mons) < I_NORMAL || !mons_is_native_in_branch(mons)))
+ {
+ return (false);
+ }
+
+ const trap_def* ptrap = find_trap(p);
+ if (checktraps && ptrap)
+ {
+ const trap_type tt = ptrap->type;
+
+ // Don't allow allies to pass over known (to them) Zot traps.
+ if (tt == TRAP_ZOT
+ && ptrap->is_known(mons)
+ && mons->friendly())
+ {
+ return (false);
+ }
+
+ // Monsters cannot travel over teleport traps.
+ const monster_type montype = mons_is_zombified(mons)
+ ? mons_zombie_base(mons)
+ : mons->type;
+ if (!can_place_on_trap(montype, tt))
+ return (false);
+ }
+
+ return (true);
+}
+
void mons_remove_from_grid(const monsters *mon)
{
const coord_def pos = mon->pos();
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 620756e171..086ac38e47 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -404,6 +404,10 @@ std::string get_mon_shape_str(const mon_body_shape shape);
bool mons_class_can_pass(int mc, const dungeon_feature_type grid);
bool mons_can_pass(const monsters *mon, dungeon_feature_type grid);
+bool mons_can_open_door(const monsters* mon, const coord_def& pos);
+bool mons_can_eat_door(const monsters* mon, const coord_def& pos);
+bool mons_can_traverse(const monsters* mon, const coord_def& pos,
+ bool checktraps = true);
mon_inv_type equip_slot_to_mslot(equipment_type eq);
mon_inv_type item_to_mslot(const item_def &item);