summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShmuale Mark <shm.mark@gmail.com>2014-06-19 08:54:13 -0400
committerShmuale Mark <shm.mark@gmail.com>2014-06-19 12:09:55 -0400
commit61e7c1565861f7a89ca6f0554d135d64ec55a6fe (patch)
tree5bb02d34013d20e3e95c06b541467729eebf8557
parentdf118164fecb6f63ba9eee7a6a750bee6b4b940f (diff)
downloadcrawl-ref-61e7c1565861f7a89ca6f0554d135d64ec55a6fe.tar.gz
crawl-ref-61e7c1565861f7a89ca6f0554d135d64ec55a6fe.zip
Try to reduce duplication in Recite code.
is_chaotic() and is_unclean() have been changed to return an int roughly equal to what would have been returned before by the Zin recite function. Some bool flags were added to the function to make it still work right for the other uses (e.g. silver). Prince Ribbit is no longer specially vulnerable to Recite, and insane/ sluggish uniques are unclean rather than chaotic, which seems more consistent with the other uses of the terms. The special case for nonliving and plant monsters to be unrecitable is removed.
-rw-r--r--crawl-ref/source/actor.h2
-rw-r--r--crawl-ref/source/beam.cc2
-rw-r--r--crawl-ref/source/dactions.cc2
-rw-r--r--crawl-ref/source/godabil.cc168
-rw-r--r--crawl-ref/source/mon-death.cc12
-rw-r--r--crawl-ref/source/mon-ench.cc2
-rw-r--r--crawl-ref/source/mon-info.cc2
-rw-r--r--crawl-ref/source/mon-place.cc4
-rw-r--r--crawl-ref/source/monster.cc132
-rw-r--r--crawl-ref/source/monster.h7
-rw-r--r--crawl-ref/source/player.cc4
-rw-r--r--crawl-ref/source/player.h2
12 files changed, 175 insertions, 164 deletions
diff --git a/crawl-ref/source/actor.h b/crawl-ref/source/actor.h
index e890ac9055..48ce6a7620 100644
--- a/crawl-ref/source/actor.h
+++ b/crawl-ref/source/actor.h
@@ -275,7 +275,7 @@ public:
virtual bool is_holy(bool spells = true) const = 0;
virtual bool is_unholy(bool spells = true) const = 0;
virtual bool is_evil(bool spells = true) const = 0;
- virtual bool is_chaotic() const = 0;
+ virtual int chaos(bool check_spells_god = false) const = 0;
virtual bool is_artificial() const = 0;
virtual bool is_unbreathing() const = 0;
virtual bool is_insubstantial() const = 0;
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index b33f0c6c28..87a047ef6e 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -2148,7 +2148,7 @@ bool curare_actor(actor* source, actor* target, int levels, string name,
int silver_damages_victim(actor* victim, int damage, string &dmg_msg)
{
int ret = 0;
- if (victim->is_chaotic()
+ if (victim->chaos()
|| victim->is_player() && player_is_shapechanged())
{
ret = damage * 3 / 4;
diff --git a/crawl-ref/source/dactions.cc b/crawl-ref/source/dactions.cc
index c5e8c08360..43ee0a4233 100644
--- a/crawl-ref/source/dactions.cc
+++ b/crawl-ref/source/dactions.cc
@@ -85,7 +85,7 @@ bool mons_matches_daction(const monster* mon, daction_type act)
case DACT_ALLY_UNHOLY_EVIL:
return mon->wont_attack() && (mon->is_unholy() || mon->is_evil());
case DACT_ALLY_UNCLEAN_CHAOTIC:
- return mon->wont_attack() && (mon->is_unclean() || mon->is_chaotic());
+ return mon->wont_attack() && (mon->unclean() || mon->chaos());
case DACT_ALLY_SPELLCASTER:
return mon->wont_attack() && mon->is_actual_spellcaster();
case DACT_ALLY_YRED_SLAVE:
diff --git a/crawl-ref/source/godabil.cc b/crawl-ref/source/godabil.cc
index 1ee1073fa5..fd948667ff 100644
--- a/crawl-ref/source/godabil.cc
+++ b/crawl-ref/source/godabil.cc
@@ -436,16 +436,63 @@ string zin_recite_text(const int seed, const int prayertype, int step)
return recite;
}
+/** How vulnerable to RECITE_HERETIC is this monster?
+ *
+ * @param[in] mon The monster to check.
+ * @returns the susceptibility.
+ */
+static int _heretic_recite_weakness(const monster *mon)
+{
+ int degree = 0;
+
+ // Sleeping or paralyzed monsters will wake up or still perceive their
+ // surroundings, respectively. So, you can still recite to them.
+ if (mons_intel(mon) >= I_NORMAL
+ && !(mon->has_ench(ENCH_DUMB) || mons_is_confused(mon)))
+ {
+ // In the eyes of Zin, everyone is a sinner until proven otherwise!
+ degree++;
+
+ // Any priest is a heretic...
+ if (mon->is_priest())
+ degree++;
+
+ // Or those who believe in themselves...
+ if (mon->type == MONS_DEMIGOD)
+ degree++;
+
+ // ...but evil gods are worse.
+ if (is_evil_god(mon->god) || is_unknown_god(mon->god))
+ degree++;
+
+ // (The above mean that worshipers will be treated as
+ // priests for reciting, even if they aren't actually.)
+
+
+ // Sanity check: monsters that won't attack you, and aren't
+ // priests/evil, don't get recited against.
+ if (mon->wont_attack() && degree <= 1)
+ degree = 0;
+
+ // Sanity check: monsters that are holy, know holy spells, or worship
+ // holy gods aren't heretics.
+ if (mon->is_holy() || is_good_god(mon->god))
+ degree = 0;
+ }
+
+ return degree;
+}
+
typedef FixedVector<int, NUM_RECITE_TYPES> recite_counts;
/** Check whether this monster might be influenced by Recite.
*
* @param[in] mon The monster to check.
- * @param[out] eligibility An vector, indexed by recite_type, that indicates
+ * @param[out] eligibility A vector, indexed by recite_type, that indicates
* which recitation types the monster is affected by, if any:
* eligibility[RECITE_FOO] is nonzero if the monster is affected
* by RECITE_FOO. Only modified if the function returns 0 or 1.
- * @return -1 if the monster is already affected or of the wrong holiness.
- * The eligibility vector is unchanged.
+ * @return -1 if the monster is already affected. The eligibility vector
+ * is unchanged.
* @return 0 if the monster is otherwise ineligible for recite. The
* eligibility vector is filled with zeros.
* @return 1 if the monster is eligible for recite. The eligibility vector
@@ -462,75 +509,14 @@ static int _zin_check_recite_to_single_monster(const monster *mon,
const mon_holy_type holiness = mon->holiness();
- // Can't recite at plants or golems.
- if (holiness == MH_PLANT || holiness == MH_NONLIVING)
- return -1;
-
eligibility.init(0);
- // Recitations are based on monster::is_unclean, but are NOT identical to it,
- // because that lumps all forms of uncleanliness together. We want to specify.
-
- // Anti-chaos prayer:
-
- // Hits some specific insane or shapeshifted uniques.
- if (mon->type == MONS_LOUISE
- || mon->type == MONS_PSYCHE
- || mon->type == MONS_GASTRONOK
- || mon->type == MONS_PRINCE_RIBBIT)
- {
- eligibility[RECITE_CHAOTIC]++;
- }
-
- // Hits monsters that have chaotic spells memorized.
- if (mon->has_chaotic_spell() && mon->is_actual_spellcaster())
- eligibility[RECITE_CHAOTIC]++;
-
- // Hits monsters with 'innate' chaos.
- if (mon->is_chaotic())
- eligibility[RECITE_CHAOTIC]++;
-
- // Hits monsters that are worshipers of a chaotic god.
- if (is_chaotic_god(mon->god))
- eligibility[RECITE_CHAOTIC]++;
-
- // Hits (again) monsters that are priests of a chaotic god.
- if (is_chaotic_god(mon->god) && mon->is_priest())
- eligibility[RECITE_CHAOTIC]++;
-
- // Anti-impure prayer:
-
- // Hits monsters that have unclean spells memorized.
- if (mon->has_unclean_spell())
- eligibility[RECITE_IMPURE]++;
-
- // Hits monsters that desecrate the dead.
- if (mons_eats_corpses(mon))
- eligibility[RECITE_IMPURE]++;
-
- // Hits corporeal undead, which are a perversion of natural form.
- if (holiness == MH_UNDEAD && !mon->is_insubstantial())
- eligibility[RECITE_IMPURE]++;
-
- // Hits monsters that have these brands.
- if (mon->has_attack_flavour(AF_VAMPIRIC))
- eligibility[RECITE_IMPURE]++;
- if (mon->has_attack_flavour(AF_HUNGER))
- eligibility[RECITE_IMPURE]++;
- if (mon->has_attack_flavour(AF_ROT))
- eligibility[RECITE_IMPURE]++;
- if (mon->has_attack_flavour(AF_STEAL))
- eligibility[RECITE_IMPURE]++;
-
- // Being naturally mutagenic isn't good either.
- corpse_effect_type ce = mons_corpse_effect(mon->type);
- if ((ce == CE_ROT || ce == CE_MUTAGEN) && !mon->is_chaotic())
- eligibility[RECITE_IMPURE]++;
-
- // Death drakes and necrophage get a bump to uncleanliness.
- if (mon->type == MONS_NECROPHAGE || mon->type == MONS_DEATH_DRAKE)
- eligibility[RECITE_IMPURE]++;
+ // Anti-chaos prayer: Hits things vulnerable to silver, or with chaotic spells/gods.
+ eligibility[RECITE_CHAOTIC] = mon->chaos(true);
+ // Anti-impure prayer: Hits things that Zin hates in general.
+ // Don't look at the monster's god; that's what RECITE_HERETIC is for.
+ eligibility[RECITE_IMPURE] = mon->unclean(false);
// Sanity check: if a monster is 'really' natural, don't consider it impure.
if (mons_intel(mon) < I_NORMAL
&& (holiness == MH_NATURAL || holiness == MH_PLANT)
@@ -541,53 +527,15 @@ static int _zin_check_recite_to_single_monster(const monster *mon,
eligibility[RECITE_IMPURE] = 0;
}
- // Anti-unholy prayer
-
- // Hits demons and incorporeal undead.
+ // Anti-unholy prayer: Hits demons and incorporeal undead.
if (holiness == MH_UNDEAD && mon->is_insubstantial()
|| holiness == MH_DEMONIC)
{
eligibility[RECITE_UNHOLY]++;
}
-
- // Anti-heretic prayer
-
- // Sleeping or paralyzed monsters will wake up or still perceive their
- // surroundings, respectively. So, you can still recite to them.
-
- if (mons_intel(mon) >= I_NORMAL
- && !(mon->has_ench(ENCH_DUMB) || mons_is_confused(mon)))
- {
- // In the eyes of Zin, everyone is a sinner until proven otherwise!
- eligibility[RECITE_HERETIC]++;
-
- // Any priest is a heretic...
- if (mon->is_priest())
- eligibility[RECITE_HERETIC]++;
-
- // Or those who believe in themselves...
- if (mon->type == MONS_DEMIGOD)
- eligibility[RECITE_HERETIC]++;
-
- // ...but evil gods are worse.
- if (is_evil_god(mon->god) || is_unknown_god(mon->god))
- eligibility[RECITE_HERETIC]++;
-
- // (The above mean that worshipers will be treated as
- // priests for reciting, even if they aren't actually.)
-
-
- // Sanity check: monsters that won't attack you, and aren't
- // priests/evil, don't get recited against.
- if (mon->wont_attack() && eligibility[RECITE_HERETIC] <= 1)
- eligibility[RECITE_HERETIC] = 0;
-
- // Sanity check: monsters that are holy, know holy spells, or worship
- // holy gods aren't heretics.
- if (mon->is_holy() || is_good_god(mon->god))
- eligibility[RECITE_HERETIC] = 0;
- }
+ // Anti-heretic prayer: Hits intelligent monsters, especially priests.
+ eligibility[RECITE_HERETIC] = _heretic_recite_weakness(mon);
#ifdef DEBUG_DIAGNOSTICS
string elig;
diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc
index a391fefb1f..30b3703ed4 100644
--- a/crawl-ref/source/mon-death.cc
+++ b/crawl-ref/source/mon-death.cc
@@ -1922,12 +1922,12 @@ int monster_die(monster* mons, killer_type killer,
}
// Zin hates unclean and chaotic beings.
- if (mons->is_unclean())
+ if (mons->unclean())
{
did_god_conduct(DID_KILL_UNCLEAN,
mons->hit_dice, true, mons);
}
- else if (mons->is_chaotic())
+ else if (mons->chaos())
{
did_god_conduct(DID_KILL_CHAOTIC,
mons->hit_dice, true, mons);
@@ -2157,13 +2157,13 @@ int monster_die(monster* mons, killer_type killer,
mons->hit_dice);
}
- if (mons->is_unclean())
+ if (mons->unclean())
{
did_god_conduct(DID_UNCLEAN_KILLED_BY_SERVANT,
mons->hit_dice);
}
- if (mons->is_chaotic())
+ if (mons->chaos())
{
did_god_conduct(DID_CHAOTIC_KILLED_BY_SERVANT,
mons->hit_dice);
@@ -2216,13 +2216,13 @@ int monster_die(monster* mons, killer_type killer,
mons->hit_dice);
}
- if (mons->is_unclean())
+ if (mons->unclean())
{
did_god_conduct(DID_UNCLEAN_KILLED_BY_SERVANT,
mons->hit_dice);
}
- if (mons->is_chaotic())
+ if (mons->chaos())
{
did_god_conduct(DID_CHAOTIC_KILLED_BY_SERVANT,
mons->hit_dice);
diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc
index d75b3afb8a..15a34ff6ca 100644
--- a/crawl-ref/source/mon-ench.cc
+++ b/crawl-ref/source/mon-ench.cc
@@ -1751,7 +1751,7 @@ void monster::apply_enchantment(const mon_enchant &me)
// This is like Corona, but if silver harms them, it has sticky
// flame levels of damage.
case ENCH_SILVER_CORONA:
- if (is_chaotic())
+ if (chaos())
{
int dam = roll_dice(2, 4) - 1;
simple_monster_message(this, " is seared!");
diff --git a/crawl-ref/source/mon-info.cc b/crawl-ref/source/mon-info.cc
index f38a4d195b..edb7642450 100644
--- a/crawl-ref/source/mon-info.cc
+++ b/crawl-ref/source/mon-info.cc
@@ -670,7 +670,7 @@ monster_info::monster_info(const monster* m, int milev)
if (m->is_shapeshifter() && (m->flags & MF_KNOWN_SHIFTER))
mb.set(MB_SHAPESHIFTER);
- if (m->is_known_chaotic())
+ if (m->known_chaos())
mb.set(MB_CHAOTIC);
if (m->submerged())
diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc
index f3c79d362e..fa54ba7827 100644
--- a/crawl-ref/source/mon-place.cc
+++ b/crawl-ref/source/mon-place.cc
@@ -3776,9 +3776,9 @@ conduct_type player_will_anger_monster(monster* mon)
return DID_HOLY;
if (you_worship(GOD_ZIN))
{
- if (mon->is_unclean())
+ if (mon->unclean())
return DID_UNCLEAN;
- if (mon->is_chaotic())
+ if (mon->chaos())
return DID_CHAOS;
}
if (you_worship(GOD_TROG) && mon->is_actual_spellcaster())
diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc
index a74c38dfbd..d97ea95bbc 100644
--- a/crawl-ref/source/monster.cc
+++ b/crawl-ref/source/monster.cc
@@ -3466,85 +3466,147 @@ bool monster::is_evil(bool check_spells) const
return false;
}
-bool monster::is_unclean(bool check_spells) const
+/** Is the monster insane?
+ *
+ * Somewhat subjective, of course.
+ * @returns true if the monster is a unique deemed insane by Zin.
+ */
+bool monster::is_insane() const
{
- if (has_unclean_spell() && check_spells)
- return true;
+ return type == MONS_CRAZY_YIUF
+ || type == MONS_PSYCHE
+ || type == MONS_LOUISE;
+}
- if (has_attack_flavour(AF_HUNGER)
- || has_attack_flavour(AF_ROT)
- || has_attack_flavour(AF_STEAL))
- {
- return true;
- }
+/** Is the monster considered unclean by Zin?
+ *
+ * If not 0, then Zin won't let you have it as an ally, and gives
+ * piety for killing it.
+ * @param check_god whether the monster having a chaotic god matters.
+ * @returns 0 if not hated, a number greater than 0 otherwise.
+ */
+int monster::unclean(bool check_god) const
+{
+ int uncleanliness = 0;
+
+ if (has_attack_flavour(AF_HUNGER))
+ uncleanliness++;
+ if (has_attack_flavour(AF_ROT))
+ uncleanliness++;
+ if (has_attack_flavour(AF_STEAL))
+ uncleanliness++;
+ if (has_attack_flavour(AF_VAMPIRIC))
+ uncleanliness++;
// Zin considers insanity unclean. And slugs that speak.
- if (type == MONS_CRAZY_YIUF
- || type == MONS_PSYCHE
+ if (is_insane()
|| type == MONS_GASTRONOK)
{
- return true;
+ uncleanliness++;
}
// A floating mass of disease is nearly the definition of unclean.
if (type == MONS_ANCIENT_ZYME)
- return true;
+ uncleanliness++;
+
+ // Zin _really_ doesn't like death drakes or necrophages.
+ if (type == MONS_NECROPHAGE || type == MONS_DEATH_DRAKE)
+ uncleanliness++;
// Assume that all unknown gods are not chaotic.
//
// Being a worshipper of a chaotic god doesn't yet make you
// physically/essentially chaotic (so you don't get hurt by silver),
// but Zin does mind.
- if (is_priest() && is_chaotic_god(god) && check_spells)
- return true;
+ if (is_priest() && is_chaotic_god(god) && check_god)
+ uncleanliness++;
- if (has_chaotic_spell() && is_actual_spellcaster() && check_spells)
- return true;
+ if (has_unclean_spell())
+ uncleanliness++;
+
+ if (has_chaotic_spell() && is_actual_spellcaster())
+ uncleanliness++;
corpse_effect_type ce = mons_corpse_effect(type);
- if ((ce == CE_ROT || ce == CE_MUTAGEN) && !is_chaotic())
- return true;
+ if ((ce == CE_ROT || ce == CE_MUTAGEN) && !chaos())
+ uncleanliness++;
- return false;
+ // Zin has a food conduct for monsters too.
+ if (mons_eats_corpses(this))
+ uncleanliness++;
+
+ // Corporeal undead are a perversion of natural form.
+ if (holiness() == MH_UNDEAD && !is_insubstantial())
+ uncleanliness++;
+
+ return uncleanliness;
}
-bool monster::is_known_chaotic() const
+/** How chaotic do you know this monster to be?
+ *
+ * @param check_spells_god whether to look at its spells and/or
+ * religion; silver damage does not.
+ * @returns 0 if not chaotic, a larger number if so.
+ */
+int monster::known_chaos(bool check_spells_god) const
{
+ int chaotic = 0;
+
if (type == MONS_UGLY_THING
|| type == MONS_VERY_UGLY_THING
|| type == MONS_ABOMINATION_SMALL
|| type == MONS_ABOMINATION_LARGE
|| type == MONS_WRETCHED_STAR
- || type == MONS_KILLER_KLOWN // For their random attacks.
- || type == MONS_TIAMAT // For her colour-changing.
- || mons_is_demonspawn(type) // Like player demonspawn
+ || type == MONS_KILLER_KLOWN // For their random attacks.
+ || type == MONS_TIAMAT // For her colour-changing.
+ || mons_is_demonspawn(type) // Like player demonspawn
|| mons_class_is_chimeric(type))
{
- return true;
+ chaotic++;
}
if (is_shapeshifter() && (flags & MF_KNOWN_SHIFTER))
- return true;
+ chaotic++;
// Knowing chaotic spells is not enough to make you "essentially"
- // chaotic (i.e., silver doesn't hurt you), it's just unclean for
- // Zin. Having chaotic abilities (not actual spells) does mean
- // you're truly changed by chaos.
- if (has_chaotic_spell() && !is_actual_spellcaster())
- return true;
+ // chaotic (i.e., silver doesn't hurt you), but it does make you
+ // chaotic enough for Zin's chaos recitation. Having chaotic
+ // abilities (not actual spells) does mean you're truly changed
+ // by chaos.
+ if (has_chaotic_spell() && (!is_actual_spellcaster()
+ || check_spells_god))
+ {
+ chaotic++;
+ }
if (has_attack_flavour(AF_MUTATE)
|| has_attack_flavour(AF_CHAOS))
{
- return true;
+ chaotic++;
}
- return false;
+ if (is_chaotic_god(god))
+ chaotic++;
+
+ if (is_chaotic_god(god) && is_priest())
+ chaotic++;
+
+ return chaotic;
}
-bool monster::is_chaotic() const
+/** How chaotic is this monster really?
+ *
+ * @param check_spells_god whether to look at its spells and/or
+ * religion; silver damage does not.
+ * @returns 0 if not chaotic, a larger number if so.
+ */
+int monster::chaos(bool check_spells_god) const
{
- return is_shapeshifter() || is_known_chaotic();
+ // Don't count known shapeshifters twice.
+ if (is_shapeshifter() && (flags & MF_KNOWN_SHIFTER))
+ return known_chaos(check_spells_god);
+ else
+ return is_shapeshifter() + known_chaos(check_spells_god);
}
bool monster::is_artificial() const
diff --git a/crawl-ref/source/monster.h b/crawl-ref/source/monster.h
index 08fe8a2640..429e8403bc 100644
--- a/crawl-ref/source/monster.h
+++ b/crawl-ref/source/monster.h
@@ -330,9 +330,10 @@ public:
bool is_holy(bool check_spells = true) const;
bool is_unholy(bool check_spells = true) const;
bool is_evil(bool check_spells = true) const;
- bool is_unclean(bool check_spells = true) const;
- bool is_known_chaotic() const;
- bool is_chaotic() const;
+ bool is_insane() const;
+ int unclean(bool check_god = true) const;
+ int known_chaos(bool check_spells_god = false) const;
+ int chaos(bool check_spells_god = false) const;
bool is_artificial() const;
bool is_unbreathing() const;
bool is_insubstantial() const;
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 11f479cc91..275bfc18f2 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -6661,9 +6661,9 @@ bool player::is_evil(bool check_spells) const
// This is a stub. Check is used only for silver damage. Worship of chaotic
// gods should probably be checked in the non-existing player::is_unclean,
// which could be used for something Zin-related (such as a priestly monster).
-bool player::is_chaotic() const
+int player::chaos(bool /*check_spells_god*/) const
{
- return false;
+ return 0;
}
bool player::is_artificial() const
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index ca7e4a781d..13a6e7b54e 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -613,7 +613,7 @@ public:
bool is_holy(bool spells = true) const;
bool is_unholy(bool spells = true) const;
bool is_evil(bool spells = true) const;
- bool is_chaotic() const;
+ int chaos(bool check_spells_god) const;
bool is_artificial() const;
bool is_unbreathing() const;
bool is_insubstantial() const;