summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/monstuff.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/monstuff.cc')
-rw-r--r--crawl-ref/source/monstuff.cc137
1 files changed, 82 insertions, 55 deletions
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index ab4a48d441..7f586238b1 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -2149,26 +2149,54 @@ void behaviour_event( monsters *mon, int event, int src,
_handle_behaviour( mon );
}
-static bool _choose_random_target_grid_in_los(monsters *mon)
+static bool _choose_random_patrol_target_grid(monsters *mon)
{
+ int patrol_x = mon->patrol_point.x;
+ int patrol_y = mon->patrol_point.y;
+ dungeon_feature_type habitat = habitat2grid(
+ mons_habitat_by_type(mon->type) );
int pos_x, pos_y;
int count_grids = 0;
for (int j = -LOS_RADIUS; j < LOS_RADIUS; j++)
for (int k = -LOS_RADIUS; k < LOS_RADIUS; k++)
{
- if (j == 0 && k == 0)
- continue;
-
- pos_x = mon->x + j;
- pos_y = mon->y + k;
+ pos_x = patrol_x + j;
+ pos_y = patrol_y + k;
if (!in_bounds(pos_x, pos_y))
continue;
- if (!mon->mon_see_grid(pos_x, pos_y))
+
+ if (pos_x == mon->x && pos_y == mon->y)
continue;
+
if (!mon->can_pass_through_feat(grd[pos_x][pos_y]))
continue;
+ if (grid_see_grid(mon->x, mon->y, patrol_x, patrol_y, habitat))
+ {
+ // If the patrol point can be easily (within LOS) reached
+ // from the current position, it suffices if the target is
+ // within reach of the patrol point OR the current position:
+ // we can easily get there.
+ if (!grid_see_grid(patrol_x, patrol_y, pos_x, pos_y, habitat)
+ && !grid_see_grid(mon->x, mon->y, pos_x, pos_y, habitat))
+ {
+ continue;
+ }
+ }
+ else
+ {
+ // If, however, the patrol point is out of reach, we have to
+ // make sure the new target brings us into reach of it.
+ // This means that the target must be reachable BOTH from
+ // the patrol point AND the current position.
+ if (!grid_see_grid(patrol_x, patrol_y, pos_x, pos_y, habitat)
+ || !grid_see_grid(mon->x, mon->y, pos_x, pos_y, habitat))
+ {
+ continue;
+ }
+ }
+
if (one_chance_in(++count_grids))
{
mon->target_x = pos_x;
@@ -2508,9 +2536,11 @@ static void _handle_behaviour(monsters *mon)
{
if (patrolling)
{
- if (mon->patrol_point != coord_def(mon->x, mon->y)
- || !_choose_random_target_grid_in_los(mon))
+ if (!_choose_random_patrol_target_grid(mon))
{
+ // If we couldn't find a target that is within easy
+ // reach of the monster and close to the patrol point,
+ // it's time to head back.
mon->target_x = mon->patrol_point.x;
mon->target_y = mon->patrol_point.y;
}
@@ -2727,7 +2757,7 @@ monsters *choose_random_monster_on_level(int weight,
return chosen;
}
-// note that this function *completely* blocks messaging for monsters
+// Note that this function *completely* blocks messaging for monsters
// distant or invisible to the player ... look elsewhere for a function
// permitting output of "It" messages for the invisible {dlb}
// Intentionally avoids info and str_pass now. -- bwr
@@ -3685,7 +3715,7 @@ static bool _handle_scroll(monsters *monster)
bool was_visible =
mons_near(monster) && player_monster_visible(monster);
- // notice how few cases are actually accounted for here {dlb}:
+ // Notice how few cases are actually accounted for here {dlb}:
const int scroll_type = mitm[monster->inv[MSLOT_SCROLL]].sub_type;
switch (scroll_type)
{
@@ -3880,13 +3910,13 @@ static bool _handle_wand(monsters *monster, bolt &beem)
niceWand = true;
break;
}
- // this break causes the wand to be tried on the player:
+ // This break causes the wand to be tried on the player.
break;
}
return (false);
}
- // fire tracer, if necessary
+ // Fire tracer, if necessary.
if (!niceWand)
{
fire_tracer( monster, beem );
@@ -4623,16 +4653,16 @@ static bool _handle_throw(monsters *monster, bolt & beem)
return (false);
}
- // ok, we'll try it.
+ // Ok, we'll try it.
setup_generic_throw( monster, beem );
- // set fake damage for the tracer.
+ // Set fake damage for the tracer.
beem.damage = dice_def(10, 10);
// fire tracer
fire_tracer( monster, beem );
- // clear fake damage (will be set correctly in mons_throw).
+ // Clear fake damage (will be set correctly in mons_throw).
beem.damage = 0;
// good idea?
@@ -4770,7 +4800,7 @@ static void _handle_monster_move(int i, monsters *monster)
if (monster->hit_points > monster->max_hit_points)
monster->hit_points = monster->max_hit_points;
- // monster just summoned (or just took stairs), skip this action
+ // Monster just summoned (or just took stairs), skip this action.
if (testbits( monster->flags, MF_JUST_SUMMONED ))
{
monster->flags &= ~MF_JUST_SUMMONED;
@@ -4779,7 +4809,7 @@ static void _handle_monster_move(int i, monsters *monster)
_monster_add_energy(monster);
- // Handle clouds on nonmoving monsters:
+ // Handle clouds on nonmoving monsters.
if (monster->speed == 0
&& env.cgrid[monster->x][monster->y] != EMPTY_CLOUD
&& !monster->has_ench(ENCH_SUBMERGED))
@@ -5238,7 +5268,7 @@ void handle_monsters(void)
// If the player got banished, discard pending monster actions.
if (you.banished)
{
- // clear list of beholding monsters
+ // Clear list of beholding monsters.
if (you.duration[DUR_BEHELD])
{
you.beheld_by.clear();
@@ -5284,7 +5314,7 @@ static bool _is_item_jelly_edible(const item_def &item)
//
// handle_pickup
//
-// Returns false if monster doesn't spend any time pickup up
+// Returns false if monster doesn't spend any time picking something up.
//
//---------------------------------------------------------------
static bool _handle_pickup(monsters *monster)
@@ -5455,7 +5485,7 @@ static bool _mons_can_displace(const monsters *mpusher, const monsters *mpushee)
return (false);
}
- // Batty monsters are unpushable
+ // Batty monsters are unpushable.
if (mons_is_batty(mpusher) || mons_is_batty(mpushee))
return (false);
@@ -5630,9 +5660,9 @@ void mons_check_pool(monsters *mons, killer_type killer, int killnum)
}
}
-// returns true for monsters that obviously (to the player) feel
-// "thematically at home" in a branch
-// currently used for native monsters recognizing traps
+// Returns true for monsters that obviously (to the player)
+// feel "thematically at home" in a branch.
+// Currently used for native monsters recognizing traps.
static bool _is_native_in_branch(const monsters *monster,
const branch_type branch)
{
@@ -5777,7 +5807,7 @@ static bool _is_trap_safe(const monsters *monster, const int trap_x,
}
}
- // friendlies will try not to be parted from you
+ // Friendlies will try not to be parted from you.
if (intelligent_ally(monster) && trap.type == TRAP_TELEPORT
&& player_knows_trap && mons_near(monster))
{
@@ -5991,21 +6021,19 @@ bool _mon_can_move_to_pos(const monsters *monster, const int count_x,
// Friendlies shouldn't try to move onto the player's
// location, if they are aiming for some other target.
if (mons_wont_attack(monster)
- && monster->foe != MHITNOT
&& monster->foe != MHITYOU
+ && (monster->foe != MHITNOT || monster->is_patrolling())
&& targ_x == you.x_pos
&& targ_y == you.y_pos)
{
return false;
}
- // wandering through a trap is OK if we're pretty healthy,
- // really stupid, or immune to the trap
+ // Wandering through a trap is OK if we're pretty healthy,
+ // really stupid, or immune to the trap.
const int which_trap = trap_at_xy(targ_x,targ_y);
if (which_trap >= 0 && !_is_trap_safe(monster, targ_x, targ_y, just_check))
- {
return false;
- }
if (targ_cloud_num != EMPTY_CLOUD)
{
@@ -6054,8 +6082,8 @@ bool _mon_can_move_to_pos(const monsters *monster, const int count_x,
return true;
break;
- // this isn't harmful, but dumb critters might think so.
case CLOUD_GREY_SMOKE:
+ // This isn't harmful, but dumb critters might think so.
if (mons_intel(monster->type) > I_ANIMAL || coinflip())
return true;
@@ -6070,13 +6098,13 @@ bool _mon_can_move_to_pos(const monsters *monster, const int count_x,
return true; // harmless clouds
}
- // if we get here, the cloud is potentially harmful.
- // exceedingly dumb creatures will still wander in.
+ // If we get here, the cloud is potentially harmful.
+ // Exceedingly dumb creatures will still wander in.
if (mons_intel(monster->type) != I_PLANT)
return false;
}
- // if we end up here the monster can safely move
+ // If we end up here the monster can safely move.
return true;
}
@@ -6089,7 +6117,7 @@ static bool _monster_move(monsters *monster)
const habitat_type habitat = mons_habitat(monster);
bool deep_water_available = false;
- // Berserking monsters make a lot of racket
+ // Berserking monsters make a lot of racket.
if (monster->has_ench(ENCH_BERSERK))
{
int noise_level = get_shout_noise_level(mons_shouts(monster->type));
@@ -6128,7 +6156,7 @@ static bool _monster_move(monsters *monster)
return false;
}
- // let's not even bother with this if mmov_x and mmov_y are zero.
+ // Let's not even bother with this if mmov_x and mmov_y are zero.
if (mmov_x == 0 && mmov_y == 0)
return false;
@@ -6145,10 +6173,7 @@ static bool _monster_move(monsters *monster)
const int targ_x = monster->x + count_x - 1;
const int targ_y = monster->y + count_y - 1;
- // [ds] Bounds check was after grd[targ_x][targ_y] which would
- // trigger an ASSERT. Moved it up.
-
- // bounds check - don't consider moving out of grid!
+ // Bounds check - don't consider moving out of grid!
if (targ_x < 0 || targ_x >= GXM || targ_y < 0 || targ_y >= GYM)
{
good_move[count_x][count_y] = false;
@@ -6162,11 +6187,13 @@ static bool _monster_move(monsters *monster)
const monsters* mons = dynamic_cast<const monsters*>(monster);
good_move[count_x][count_y] =
_mon_can_move_to_pos(mons, count_x-1, count_y-1);
- } // now we know where we _can_ move.
+ }
+
+ // Now we know where we _can_ move.
const coord_def newpos = monster->pos() + coord_def(mmov_x, mmov_y);
- // normal/smart monsters know about secret doors (they _live_ in the
- // dungeon!)
+ // Normal/smart monsters know about secret doors
+ // (they _live_ in the dungeon!)
if (grd(newpos) == DNGN_CLOSED_DOOR
|| (grd(newpos) == DNGN_SECRET_DOOR
&& (mons_intel(monster_index(monster)) == I_HIGH
@@ -6174,7 +6201,7 @@ static bool _monster_move(monsters *monster)
{
if (mons_is_zombified(monster))
{
- // for zombies, monster type is kept in mon->base_monster
+ // For zombies, monster type is kept in mon->base_monster.
if (mons_itemuse(monster->base_monster) >= MONUSE_OPEN_DOORS)
{
_mons_open_door(monster, newpos);
@@ -6210,7 +6237,7 @@ static bool _monster_move(monsters *monster)
} // done door-eating jellies
- // water creatures have a preference for water they can hide in -- bwr
+ // 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.
if (habitat == HT_WATER
@@ -6309,7 +6336,7 @@ static bool _monster_move(monsters *monster)
if (dist[0] == dist[1] && abs(dist[0]) == FAR_AWAY)
continue;
- // which one was better? -- depends on FLEEING or not
+ // Which one was better? -- depends on FLEEING or not.
if (monster->behaviour == BEH_FLEE)
{
if (dist[0] >= dist[1] && dist[0] >= current_distance)
@@ -6346,10 +6373,10 @@ static bool _monster_move(monsters *monster)
forget_it:
// ------------------------------------------------------------------
- // if we haven't found a good move by this point, we're not going to.
+ // If we haven't found a good move by this point, we're not going to.
// ------------------------------------------------------------------
- // take care of beetle burrowing
+ // Take care of beetle burrowing.
if (monster->type == MONS_BORING_BEETLE)
{
dungeon_feature_type feat =
@@ -6368,7 +6395,7 @@ forget_it:
bool ret = false;
if (good_move[mmov_x + 1][mmov_y + 1] && !(mmov_x == 0 && mmov_y == 0))
{
- // check for attacking player
+ // Check for attacking player.
if (monster->x + mmov_x == you.x_pos
&& monster->y + mmov_y == you.y_pos)
{
@@ -6407,7 +6434,7 @@ forget_it:
}
}
- // check for attacking another monster
+ // Check for attacking another monster.
int targmon = mgrd[monster->x + mmov_x][monster->y + mmov_y];
if (targmon != NON_MONSTER)
{
@@ -6442,8 +6469,8 @@ forget_it:
{
mmov_x = mmov_y = 0;
- // fleeing monsters that can't move will panic and possibly
- // turn to face their attacker
+ // Fleeing monsters that can't move will panic and possibly
+ // turn to face their attacker.
if (monster->behaviour == BEH_FLEE)
behaviour_event(monster, ME_CORNERED);
}
@@ -6844,7 +6871,7 @@ void seen_monster(monsters *monster)
if (monster->flags & MF_SEEN)
return;
- // First time we've seen this particular monster
+ // First time we've seen this particular monster.
monster->flags |= MF_SEEN;
if (!mons_is_mimic(monster->type)
@@ -6878,7 +6905,7 @@ bool shift_monster( monsters *mon, int x, int y )
if (x == 0 && y == 0)
{
- // try and find a random floor space some distance away
+ // Try and find a random floor space some distance away.
for (i = 0; i < 50; i++)
{
tx = 5 + random2( GXM - 10 );
@@ -6902,7 +6929,7 @@ bool shift_monster( monsters *mon, int x, int y )
if (!inside_level_bounds(tx, ty))
continue;
- // don't drop on anything but vanilla floor right now
+ // Don't drop on anything but vanilla floor right now.
if (grd[tx][ty] != DNGN_FLOOR)
continue;