summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authordolorous <dolorous@c06c8d41-db1a-0410-9941-cceddc491573>2009-09-08 00:54:06 +0000
committerdolorous <dolorous@c06c8d41-db1a-0410-9941-cceddc491573>2009-09-08 00:54:06 +0000
commit0e33755da27b53c81548aa7df4894ae859887b4c (patch)
treef4a654475d6d58d61f56a81fea7618ca9f017e6d /crawl-ref
parent37750174d01d5f928b84f5fcbd1ab668af5f8079 (diff)
downloadcrawl-ref-0e33755da27b53c81548aa7df4894ae859887b4c.tar.gz
crawl-ref-0e33755da27b53c81548aa7df4894ae859887b4c.zip
Add a monster ability to eat food (including corpses), and let harpies
have it. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@10638 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/mon-data.h11
-rw-r--r--crawl-ref/source/mon-util.cc5
-rw-r--r--crawl-ref/source/mon-util.h2
-rw-r--r--crawl-ref/source/monstuff.cc152
4 files changed, 119 insertions, 51 deletions
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index 3a609ff8b3..03870e5fe3 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -130,10 +130,13 @@
gmon_eat explanation:
MONEAT_ITEMS,
- MONEAT_CORPSES
+ MONEAT_CORPSES,
+ MONEAT_FOOD
- Monsters with MONEAT_ITEMS are capable of eating most items, while
- monsters with MONEAT_CORPSES are capable of eating corpses.
+ Monsters with MONEAT_ITEMS are capable of eating most items,
+ monsters with MONEAT_CORPSES are capable of eating corpses, and
+ monsters with MONEAT_FOOD are capable of eating food (note that
+ corpses also count as food).
size:
SIZE_TINY, // rats/bats
@@ -2183,7 +2186,7 @@ static monsterentry mondata[] = {
AT_NO_ATK, AT_NO_ATK },
{ 7, 3, 5, 0 },
2, 10, MST_NO_SPELLS, CE_CONTAMINATED, Z_BIG, S_SCREECH, I_NORMAL,
- HT_LAND, 25, DEFAULT_ENERGY, MONUSE_NOTHING, MONEAT_NOTHING, SIZE_MEDIUM
+ HT_LAND, 25, DEFAULT_ENERGY, MONUSE_NOTHING, MONEAT_FOOD, SIZE_MEDIUM
},
// ice beast ('I')
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 9c728d72f3..0c22376de6 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -665,6 +665,11 @@ bool mons_eats_corpses(const monsters *mon)
return (mons_itemeat(mon) == MONEAT_CORPSES);
}
+bool mons_eats_food(const monsters *mon)
+{
+ return (mons_itemeat(mon) == MONEAT_FOOD);
+}
+
bool mons_is_skeletal(int mc)
{
return (mc == MONS_SKELETON_SMALL
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 389a8e44e0..e36a5cd111 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -205,6 +205,7 @@ enum mon_itemeat_type
MONEAT_NOTHING,
MONEAT_ITEMS,
MONEAT_CORPSES,
+ MONEAT_FOOD,
NUM_MONEAT
};
@@ -803,6 +804,7 @@ bool mons_class_is_plant(int mc);
bool mons_is_plant(const monsters *mon);
bool mons_eats_items(const monsters *mon);
bool mons_eats_corpses(const monsters *mon);
+bool mons_eats_food(const monsters *mon);
bool mons_has_lifeforce(const monsters *mon);
monster_type mons_genus(int mc);
monster_type mons_species(int mc);
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index aa48da6b7f..d80e3aab30 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -7495,19 +7495,6 @@ static void _handle_monster_move(monsters *monster)
continue;
}
- // Harpies may eat food/corpses on the ground.
- if (monster->type == MONS_HARPY && !mons_is_fleeing(monster)
- && (mons_wont_attack(monster)
- || (grid_distance(monster->pos(), you.pos()) > 1))
- && (mons_is_wandering(monster) && one_chance_in(3)
- || one_chance_in(5))
- && expose_items_to_element(BEAM_STEAL_FOOD, monster->pos(), 10))
- {
- simple_monster_message(monster, " eats something on the ground.");
- monster->speed_increment -= non_move_energy;
- continue;
- }
-
if (igrd(monster->pos()) != NON_ITEM
&& (mons_itemuse(monster) >= MONUSE_WEAPONS_ARMOUR
|| mons_itemeat(monster) != MONEAT_NOTHING))
@@ -7837,7 +7824,7 @@ static bool _is_item_jelly_edible(const item_def &item)
}
// XXX: This function assumes that only jellies eat items.
-static bool _monster_eat_item(monsters *monster, bool monster_nearby)
+static bool _monster_eat_item(monsters *monster, bool nearby)
{
if (!mons_eats_items(monster))
return (false);
@@ -7969,7 +7956,7 @@ static bool _monster_eat_item(monsters *monster, bool monster_nearby)
if (player_can_hear(monster->pos()))
{
mprf(MSGCH_SOUND, "You hear a%s slurping noise.",
- monster_nearby ? "" : " distant");
+ nearby ? "" : " distant");
}
if (eaten_net)
@@ -7981,51 +7968,113 @@ static bool _monster_eat_item(monsters *monster, bool monster_nearby)
return (eaten > 0);
}
-// XXX: This function assumes that only undead (which can heal from
-// eating) eat corpses.
-static bool _monster_eat_corpse(monsters *monster, bool monster_nearby)
+static bool _monster_eat_single_corpse(monsters *monster, item_def& item,
+ bool do_heal, bool nearby)
{
- if (!mons_eats_corpses(monster))
+ if (item.base_type != OBJ_CORPSES || item.sub_type != CORPSE_BODY)
return (false);
- int eaten = 0;
-
- for (stack_iterator si(monster->pos()); si; ++si)
+ if (do_heal)
{
- if (si->base_type != OBJ_CORPSES || si->sub_type != CORPSE_BODY)
- continue;
-
- monster->hit_points += 1 + random2(mons_weight(si->plus)) / 100;
+ monster->hit_points += 1 + random2(mons_weight(item.plus)) / 100;
// Limited growth factor here -- should 77 really be the cap? {dlb}:
monster->hit_points = std::min(100, monster->hit_points);
monster->max_hit_points = std::max(monster->hit_points,
monster->max_hit_points);
+ }
+
+ if (nearby)
+ {
+ mprf("%s eats %s.", monster->name(DESC_CAP_THE).c_str(),
+ item.name(DESC_NOCAP_THE).c_str());
+ }
+
+ // Assume that eating a corpse requires butchering it. Use logic
+ // from misc.cc:turn_corpse_into_chunks() and the butchery-related
+ // delays in delay.cc:stop_delay().
+
+ const int max_chunks = mons_weight(item.plus) / 150;
+
+ // Only fresh corpses bleed enough to colour the ground.
+ if (!food_is_rotten(item))
+ bleed_onto_floor(monster->pos(), item.plus, max_chunks, true);
- if (monster_nearby)
+ if (mons_skeleton(item.plus) && one_chance_in(3))
+ turn_corpse_into_skeleton(item);
+ else
+ destroy_item(item.index());
+
+ return (true);
+}
+
+static bool _monster_eat_corpse(monsters *monster, bool do_heal, bool nearby)
+{
+ if (!mons_eats_corpses(monster))
+ return (false);
+
+ int eaten = 0;
+
+ for (stack_iterator si(monster->pos()); si; ++si)
+ {
+ if (_monster_eat_single_corpse(monster, *si, do_heal, nearby))
{
- mprf("%s eats %s.", monster->name(DESC_CAP_THE).c_str(),
- si->name(DESC_NOCAP_THE).c_str());
+ eaten++;
+ break;
}
+ }
- // Assume that eating a corpse requires butchering it.
- //
- // Use logic from misc.cc:turn_corpse_into_chunks() and
- // the butchery-related delays in delay.cc:stop_delay().
+ return (eaten > 0);
+}
- const int max_chunks = mons_weight(si->plus) / 150;
+static bool _monster_eat_food(monsters *monster, bool nearby)
+{
+ if (!mons_eats_food(monster))
+ return (false);
- // Only fresh corpses bleed enough to colour the ground.
- if (!food_is_rotten(*si))
- bleed_onto_floor(monster->pos(), si->plus, max_chunks, true);
+ if (mons_is_fleeing(monster))
+ return (false);
- if (mons_skeleton(si->plus) && one_chance_in(3))
- turn_corpse_into_skeleton(*si);
- else
- destroy_item(si->index());
+ int eaten = 0;
- eaten++;
- break;
+ for (stack_iterator si(monster->pos()); si; ++si)
+ {
+ const bool is_food = (si->base_type == OBJ_FOOD);
+ const bool is_corpse = (si->base_type == OBJ_CORPSES
+ && si->sub_type == CORPSE_BODY);
+
+ if (!is_food && !is_corpse)
+ continue;
+
+ if ((mons_wont_attack(monster)
+ || grid_distance(monster->pos(), you.pos()) > 1)
+ && one_chance_in(3))
+ {
+ if (is_food)
+ {
+ if (nearby)
+ {
+ mprf("%s eats %s.", monster->name(DESC_CAP_THE).c_str(),
+ quant_name(*si, 1, DESC_NOCAP_THE).c_str());
+ }
+
+ dec_mitm_item_quantity(si.link(), 1);
+
+ eaten++;
+ break;
+ }
+ else
+ {
+ // Assume that only undead can heal from eating corpses.
+ if (_monster_eat_single_corpse(monster, *si,
+ monster->holiness() == MH_UNDEAD,
+ nearby))
+ {
+ eaten++;
+ break;
+ }
+ }
+ }
}
return (eaten > 0);
@@ -8043,19 +8092,28 @@ static bool _handle_pickup(monsters *monster)
if (mons_is_sleeping(monster) || mons_is_submerged(monster))
return (false);
- const bool monster_nearby = mons_near(monster);
+ const bool nearby = mons_near(monster);
int count_pickup = 0;
if (mons_itemeat(monster) != MONEAT_NOTHING)
{
if (mons_eats_items(monster))
{
- if (_monster_eat_item(monster, monster_nearby))
+ if (_monster_eat_item(monster, nearby))
return (false);
}
else if (mons_eats_corpses(monster))
{
- if (_monster_eat_corpse(monster, monster_nearby))
+ // Assume that only undead can heal from eating corpses.
+ if (_monster_eat_corpse(monster, monster->holiness() == MH_UNDEAD,
+ nearby))
+ {
+ return (false);
+ }
+ }
+ else if (mons_eats_food(monster))
+ {
+ if (_monster_eat_food(monster, nearby))
return (false);
}
}
@@ -8072,7 +8130,7 @@ static bool _handle_pickup(monsters *monster)
// (jpeg)
for (stack_iterator si(monster->pos()); si; ++si)
{
- if (monster->pickup_item(*si, monster_nearby))
+ if (monster->pickup_item(*si, nearby))
count_pickup++;
if (count_pickup > 1 || coinflip())