summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/monstuff.cc
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-05-26 11:22:35 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-05-26 11:22:35 +0000
commit92a5149b413abe69641720581624b5f867e663e5 (patch)
treed84e98dc32f8c68121ee4d4085f035008a4f04f0 /crawl-ref/source/monstuff.cc
parentf910f85b74d9dae832f8d3422f51d87565ea3a08 (diff)
downloadcrawl-ref-92a5149b413abe69641720581624b5f867e663e5.tar.gz
crawl-ref-92a5149b413abe69641720581624b5f867e663e5.zip
Make patrolling monster movement more natural: don't always return to
the patrol centre, make it more likely to return to the patrol area if the monster left it somehow but is still nearby, and make friendly monsters move around the player on their way to their target. Also, highlight wizard commands in the wizard help. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5252 c06c8d41-db1a-0410-9941-cceddc491573
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;