summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/monstuff.cc
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-22 06:03:43 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-22 06:03:43 +0000
commit8ab4abaf147cd83736d27c874d39989afa1b2c0a (patch)
treee6ddf716d04f25a1c81ed863fb43c75036302b62 /crawl-ref/source/monstuff.cc
parentf119c29736878ef93deed692013d3c974831b038 (diff)
downloadcrawl-ref-8ab4abaf147cd83736d27c874d39989afa1b2c0a.tar.gz
crawl-ref-8ab4abaf147cd83736d27c874d39989afa1b2c0a.zip
Improve AI handling of clouds, so that clouds will only cause sumbergable
monsters to submerge if it's a cloud tpye the monster wants to avoid, rather than always for all cloud types, and prevent lurking monsters from unsubmerging if it would expose them to a cloud type they want to avoid. Monsters submerging now consume some energy, except for air elementals and vapours submerging into the air. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7531 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/monstuff.cc')
-rw-r--r--crawl-ref/source/monstuff.cc175
1 files changed, 99 insertions, 76 deletions
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 9b1cbb25cb..71d91827e3 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -88,6 +88,8 @@ static bool immobile_monster[MAX_MONSTERS];
#define FAR_AWAY 1000000 // used in monster_move()
+#define ENERGY_SUBMERGE(entry) (std::max(entry->energy_usage.swim / 2, 1))
+
// This function creates an artificial item to represent a mimic's appearance.
// Eventually, mimics could be redone to be more like dancing weapons...
// there'd only be one type and it would look like the item it carries. -- bwr
@@ -3894,6 +3896,71 @@ static bool _is_player_or_mon_sanct(const monsters* monster)
|| is_sanctuary(monster->pos()));
}
+static bool _mons_avoids_cloud(const monsters *monster, cloud_type cl_type)
+{
+ switch (cl_type)
+ {
+ case CLOUD_MIASMA:
+ // Even the dumbest monsters will avoid miasma if they can.
+ return (mons_res_miasma(monster) <= 0);
+
+ case CLOUD_FIRE:
+ if (mons_res_fire(monster) > 1)
+ return (false);
+
+ if (monster->hit_points >= 15 + random2avg(46, 5))
+ return (false);
+ break;
+
+ case CLOUD_STINK:
+ if (mons_res_poison(monster) > 0)
+ return (false);
+ if (x_chance_in_y(monster->hit_dice - 1, 5))
+ return (false);
+ if (monster->hit_points >= random2avg(19, 2))
+ return (false);
+ break;
+
+ case CLOUD_COLD:
+ if (mons_res_cold(monster) > 1)
+ return (false);
+
+ if (monster->hit_points >= 15 + random2avg(46, 5))
+ return (false);
+ break;
+
+ case CLOUD_POISON:
+ if (mons_res_poison(monster) > 0)
+ return (false);
+
+ if (monster->hit_points >= random2avg(37, 4))
+ return (false);
+ break;
+
+ case CLOUD_GREY_SMOKE:
+ // This isn't harmful, but dumb critters might think so.
+ if (mons_intel(monster) > I_ANIMAL || coinflip())
+ return (false);
+
+ if (mons_res_fire(monster) > 0)
+ return (false);
+
+ if (monster->hit_points >= random2avg(19, 2))
+ return (false);
+ break;
+
+ default:
+ break;
+ }
+
+ // Exceedingly dumb creatures will wander into harmful clouds.
+ if (is_harmless_cloud(cl_type) || mons_intel(monster) == I_PLANT)
+ return (false);
+
+ // If we get here, the cloud is potentially harmful.
+ return (true);
+}
+
//---------------------------------------------------------------
//
// handle_nearby_ability
@@ -3947,7 +4014,10 @@ static void _handle_nearby_ability(monsters *monster)
&& !mons_is_lurking(monster) // Handled elsewhere.
&& monster->wants_submerge())
{
+ monsterentry* entry = get_monster_data(monster->type);
+
monster->add_ench(ENCH_SUBMERGED);
+ monster->speed_increment -= ENERGY_SUBMERGE(entry);
update_beholders(monster);
return;
}
@@ -5860,18 +5930,24 @@ static void _handle_monster_move(int i, monsters *monster)
monster->shield_blocks = 0;
- if (env.cgrid(monster->pos()) != EMPTY_CLOUD)
+ const int cloud_num = env.cgrid(monster->pos());
+ const cloud_type cl_type =
+ cloud_num == EMPTY_CLOUD ? CLOUD_NONE : env.cloud[cloud_num].type;
+ if (cloud_num != EMPTY_CLOUD)
{
- if (mons_is_submerged(monster))
+ if (_mons_avoids_cloud(monster, cl_type))
{
- monster->speed_increment -= entry->energy_usage.swim;
- break;
- }
+ if (mons_is_submerged(monster))
+ {
+ monster->speed_increment -= entry->energy_usage.swim;
+ break;
+ }
- if (monster->type == -1)
- {
- monster->speed_increment -= entry->energy_usage.move;
- break; // problem with vortices
+ if (monster->type == -1)
+ {
+ monster->speed_increment -= entry->energy_usage.move;
+ break; // problem with vortices
+ }
}
_mons_in_cloud(monster);
@@ -5901,10 +5977,13 @@ static void _handle_monster_move(int i, monsters *monster)
_handle_behaviour(monster);
// Submerging monsters will hide from clouds.
- if (monster_can_submerge(monster, grd(monster->pos()))
- && env.cgrid(monster->pos()) != EMPTY_CLOUD)
+ if (cloud_num != EMPTY_CLOUD && _mons_avoids_cloud(monster, cl_type)
+ && monster_can_submerge(monster, grd(monster->pos()))
+ && !monster->submerged())
{
monster->add_ench(ENCH_SUBMERGED);
+ monster->speed_increment -= ENERGY_SUBMERGE(entry);
+ continue;
}
if (monster->speed >= 100)
@@ -5947,9 +6026,11 @@ static void _handle_monster_move(int i, monsters *monster)
if (mons_is_submerged(monster))
{
// Don't unsubmerge if the monster is too damaged or
- // if the monster is afraid.
+ // if the monster is afraid, or if it's avoiding the
+ // cloud on top of the water.
if (monster->hit_points <= monster->max_hit_points / 2
- || monster->has_ench(ENCH_FEAR))
+ || monster->has_ench(ENCH_FEAR)
+ || _mons_avoids_cloud(monster, cl_type))
{
monster->speed_increment -= non_move_energy;
continue;
@@ -6877,13 +6958,13 @@ static bool _mon_can_move_to_pos(const monsters *monster,
if (monster->type == MONS_FIRE_ELEMENTAL || one_chance_in(5))
no_water = true;
- const int targ_cloud_num = env.cgrid(targ);
- const int targ_cloud_type =
+ const int targ_cloud_num = env.cgrid(targ);
+ const cloud_type targ_cloud_type =
(targ_cloud_num == EMPTY_CLOUD) ? CLOUD_NONE
: env.cloud[targ_cloud_num].type;
- const int curr_cloud_num = env.cgrid(monster->pos());
- const int curr_cloud_type =
+ const int curr_cloud_num = env.cgrid(monster->pos());
+ const cloud_type curr_cloud_type =
(curr_cloud_num == EMPTY_CLOUD) ? CLOUD_NONE
: env.cloud[curr_cloud_num].type;
@@ -7005,65 +7086,7 @@ static bool _mon_can_move_to_pos(const monsters *monster,
return (true);
}
- switch (targ_cloud_type)
- {
- case CLOUD_MIASMA:
- // Even the dumbest monsters will avoid miasma if they can.
- return (mons_res_miasma(monster) > 0);
-
- case CLOUD_FIRE:
- if (mons_res_fire(monster) > 1)
- return (true);
-
- if (monster->hit_points >= 15 + random2avg(46, 5))
- return (true);
- break;
-
- case CLOUD_STINK:
- if (mons_res_poison(monster) > 0)
- return (true);
- if (x_chance_in_y(monster->hit_dice - 1, 5))
- return (true);
- if (monster->hit_points >= random2avg(19, 2))
- return (true);
- break;
-
- case CLOUD_COLD:
- if (mons_res_cold(monster) > 1)
- return (true);
-
- if (monster->hit_points >= 15 + random2avg(46, 5))
- return (true);
- break;
-
- case CLOUD_POISON:
- if (mons_res_poison(monster) > 0)
- return (true);
-
- if (monster->hit_points >= random2avg(37, 4))
- return (true);
- break;
-
- case CLOUD_GREY_SMOKE:
- // This isn't harmful, but dumb critters might think so.
- if (mons_intel(monster) > I_ANIMAL || coinflip())
- return (true);
-
- if (mons_res_fire(monster) > 0)
- return (true);
-
- if (monster->hit_points >= random2avg(19, 2))
- return (true);
- break;
-
- default:
- return (true); // harmless clouds
- }
-
- // If we get here, the cloud is potentially harmful.
- // Exceedingly dumb creatures will still wander in.
- if (mons_intel(monster) != I_PLANT)
- return (false);
+ return !_mons_avoids_cloud(monster, targ_cloud_type);
}
// If we end up here the monster can safely move.