diff options
Diffstat (limited to 'crawl-ref')
-rw-r--r-- | crawl-ref/source/enum.h | 3 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/monplace.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 87 | ||||
-rw-r--r-- | crawl-ref/source/traps.cc | 1 |
5 files changed, 89 insertions, 9 deletions
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 14581e94a0..bbdfad70a9 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -2789,7 +2789,8 @@ enum montravel_target_type MTRAV_NONE = 0, MTRAV_PLAYER, // Travelling to reach the player. MTRAV_PATROL, // Travelling to reach the patrol point. - MTRAV_UNREACHABLE // Not travelling because player is unreachable. + MTRAV_UNREACHABLE, // Not travelling because player is unreachable. + MTRAV_EXIT // Travelling to reach a level exit. }; #ifdef WIZARD diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index 7b00dee43e..ce71eccfa7 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -646,7 +646,7 @@ mon_attitude_type mons_attitude(const monsters *m); bool mons_behaviour_perceptible(const monsters *mon); bool mons_is_native_in_branch(const monsters *monster, - const branch_type branch); + const branch_type branch = you.where_are_you); bool mons_is_god_gift(const monsters *mon, god_type god = you.religion); bool mons_is_chaotic(const monsters *mon); bool mons_is_poisoner(const monsters *mon); diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc index 2a54fae689..01a7cf4f8c 100644 --- a/crawl-ref/source/monplace.cc +++ b/crawl-ref/source/monplace.cc @@ -2635,7 +2635,7 @@ bool monster_pathfind::traversable(coord_def p) // at home in this branch. if (grd(p) == DNGN_SECRET_DOOR && mons_friendly(mons) && (mons_intel(mons->type) < I_NORMAL - || !mons_is_native_in_branch(mons, you.where_are_you))) + || !mons_is_native_in_branch(mons))) { return (false); } @@ -2696,8 +2696,7 @@ int monster_pathfind::travel_cost(coord_def npos) bool knows_trap = (!mons_friendly(mons) || grd(npos) != DNGN_UNDISCOVERED_TRAP || mons_intel(mons->type) >= I_NORMAL - && mons_is_native_in_branch(mons, - you.where_are_you)); + && mons_is_native_in_branch(mons)); trap_type tt = env.trap[trap].type; if (tt == TRAP_ALARM || tt == TRAP_ZOT) diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 866b7dbcb4..f84d4c9037 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -2405,6 +2405,68 @@ static void _mark_neighbours_player_unreachable(monsters *mon) } } +static void _mons_find_level_exits(const monsters *mon, + std::vector<coord_def> &e, + int range = -1) +{ + if (range == -1) + range = LOS_RADIUS; + + // Sweep every square within range. + for (radius_iterator ri(mon->pos(), range, true, false); ri; ++ri) + { + // All types of stairs. + if (is_stair(grd(*ri))) + e.push_back(*ri); + + // Teleportation and shaft traps: only known traps if the + // monster isn't native to the branch, or all traps if it is. + trap_type tt = trap_type_at_xy((*ri).x, (*ri).y); + if ((tt == TRAP_TELEPORT || tt == TRAP_SHAFT) + && (grd[(*ri).x][(*ri).y] != DNGN_UNDISCOVERED_TRAP + || mons_is_native_in_branch(mon))) + { + e.push_back(*ri); + } + + // Any place the monster can submerge. + if (monster_can_submerge(mon, grd(*ri))) + e.push_back(*ri); + } +} + +static bool _mons_find_nearest_level_exit(const monsters *mon, + coord_def &e) +{ + std::vector<coord_def> level_exits; + + _mons_find_level_exits(mon, level_exits); + + e.x = -1; + e.y = -1; + + int old_dist = -1; + + for (unsigned int i = 0; i < level_exits.size(); ++i) + { + int dist = distance(mon->x, mon->y, level_exits[i].x, + level_exits[i].y); + + if (old_dist == -1 || old_dist >= dist) + { + if (old_dist == dist && coinflip()) + continue; + + old_dist = dist; + + e.x = level_exits[i].x; + e.y = level_exits[i].y; + } + } + + return (old_dist != -1); +} + static void _make_mons_leave_level(monsters *mon) { if (mons_is_leaving(mon)) @@ -2834,8 +2896,7 @@ static void _handle_behaviour(monsters *mon) #ifdef DEBUG_PATHFIND mprf("Need to calculate a path... (dist = %d)", dist); #endif - const bool native = - mons_is_native_in_branch(mon, you.where_are_you); + const bool native = mons_is_native_in_branch(mon); int range = 0; switch (mons_intel(mon->type)) @@ -3241,6 +3302,26 @@ static void _handle_behaviour(monsters *mon) _make_mons_leave_level(mon); return; } + + // If the monster isn't travelling toward an exit, make it + // start doing so. + if (mon->travel_target != MTRAV_EXIT) + { + coord_def e; + if (_mons_find_nearest_level_exit(mon, e)) + { + mon->foe = MHITNOT; + mon->target_x = e.x; + mon->target_y = e.y; + mon->travel_target = MTRAV_EXIT; + } + } + // If it is, and it's on the exit, make it leave the level. + else if (mon->x == mon->target_x && mon->y == mon->target_y) + { + _make_mons_leave_level(mon); + return; + } break; case BEH_FLEE: @@ -6546,7 +6627,7 @@ static bool _is_trap_safe(const monsters *monster, const int trap_x, // * very intelligent monsters can be assumed to have a high T&D skill // (or have memorised part of the dungeon layout ;) ) if (intel >= I_NORMAL && mechanical - && (mons_is_native_in_branch(monster, you.where_are_you) + && (mons_is_native_in_branch(monster) || monster->attitude == ATT_FRIENDLY && player_knows_trap || intel >= I_HIGH && one_chance_in(3))) diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 1434640c19..d399ae7cd1 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -928,7 +928,6 @@ dungeon_feature_type trap_category(trap_type type) // Returns index of the trap for a given (x,y) coordinate pair {dlb} int trap_at_xy(int which_x, int which_y) { - for (int which_trap = 0; which_trap < MAX_TRAPS; which_trap++) { if (env.trap[which_trap].x == which_x |