summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/monspeak.cc
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-11 20:18:40 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-11 20:18:40 +0000
commit7f1f52b6d4774fb6cc523ec035dbf4ac4cd4af48 (patch)
treea3dac50cafd840505cbe1a06e2aabc76a3e8b827 /crawl-ref/source/monspeak.cc
parent1daa1c18ab74074b6d4d0bb4b3fb2c4e250516af (diff)
downloadcrawl-ref-7f1f52b6d4774fb6cc523ec035dbf4ac4cd4af48.tar.gz
crawl-ref-7f1f52b6d4774fb6cc523ec035dbf4ac4cd4af48.zip
Another of those commits on monster speech, hopefully the last one for
some time, though. I added a new prefix "related" if the player character has the same genus as the monster. My new prefix additions (hostile, related and religion) can now be skipped in the speech lookup, which fixes a couple of problems where several monsters were forced silent because of lookup problems. Also clean up the lookup process for silence, allow charmed monsters to sometimes speak (if rarely) and added several debugging statements that are also mentioned in monster_speech.txt that is now clearer than ever before (I hope). Fixed a couple of bugs in the monster shape calculation where the old glyphs were still being used. Also, a Draconian character eating any type of Draconian will now count as cannibalism. Also: FR 1894060: Level annotations now prompt for confirmation if they contain an exclamation mark (rather than "WARN"). Fix 1859443: Arriving on a square via staircase now calls request_autopickup and will describe items on the square. Oh, and fix init.txt to really allow reading in macros from external files. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3604 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/monspeak.cc')
-rw-r--r--crawl-ref/source/monspeak.cc208
1 files changed, 150 insertions, 58 deletions
diff --git a/crawl-ref/source/monspeak.cc b/crawl-ref/source/monspeak.cc
index ed373e7944..8528276860 100644
--- a/crawl-ref/source/monspeak.cc
+++ b/crawl-ref/source/monspeak.cc
@@ -42,34 +42,84 @@
#include "stuff.h"
#include "view.h"
-static std::string get_speak_string(const std::vector<std::string> prefixes,
+// Try the exact key lookup along with the entire prefix list.
+// If that fails, start ignoring hostile/religion/silence, in that order,
+// first skipping hostile, then hostile *and* religion, then all three.
+static std::string try_exact_string(const std::vector<std::string> prefixes,
const std::string key,
- const monsters *monster,
+ bool ignore_hostile = false,
+ bool ignore_related = false,
+ bool ignore_religion = false,
bool ignore_silenced = false)
{
- std::string prefix = "";
+ bool hostile = false;
+ bool related = false;
+ bool religion = false;
bool silenced = false;
+
+ std::string prefix = "";
+ std::string msg = "";
const int size = prefixes.size();
for (int i = 0; i < size; i++)
{
- if (prefixes[i] == "silenced")
- {
- if (ignore_silenced)
- continue;
- silenced = true;
- }
- prefix += prefixes[i];
- prefix += " ";
+ if (prefixes[i] == "hostile")
+ {
+ if (ignore_hostile)
+ continue;
+ hostile = true;
+ }
+ else if (prefixes[i] == "related")
+ {
+ if (ignore_related)
+ continue;
+ related = true;
+ }
+ else if (prefixes[i] == "silenced")
+ {
+ if (ignore_silenced)
+ continue;
+ silenced = true;
+ }
+ else if (prefixes[i] == "beogh" || prefixes[i] == "good god"
+ || prefixes[i] == "evil god")
+ {
+ if (ignore_religion)
+ continue;
+ religion = true;
+ }
+ prefix += prefixes[i];
+ prefix += " ";
+ }
+ msg = getSpeakString(prefix + key);
+
+ if (msg.empty())
+ {
+ if (hostile)
+ msg = try_exact_string(prefixes, key, true);
+ else if (related)
+ msg = try_exact_string(prefixes, key, true, true);
+ else if (religion)
+ msg = try_exact_string(prefixes, key, true, true, true);
+ // 50% use non-verbal monster speech,
+ // 50% try for more general silenced monster message instead
+ else if (silenced && coinflip())
+ msg = try_exact_string(prefixes, key, true, true, true, true);
}
+ return msg;
+}
- std::string msg = "";
+static std::string get_speak_string(const std::vector<std::string> prefixes,
+ const std::string key,
+ const monsters *monster)
+{
+ std::string msg = try_exact_string(prefixes, key);
- // try string of all prefixes
- msg = getSpeakString(prefix + key);
- if (msg != "")
+ if (!msg.empty())
return msg;
// Combinations of prefixes by threes
+ const int size = prefixes.size();
+ std::string prefix = "";
if (size >= 3)
{
for (int i = 0; i < (size - 2); i++)
@@ -81,7 +131,8 @@ static std::string get_speak_string(const std::vector<std::string> prefixes,
prefix += prefixes[k] + " ";
msg = getSpeakString("default " + prefix + key);
- if (msg != "")
+
+ if (!msg.empty())
return msg;
}
}
@@ -96,7 +147,8 @@ static std::string get_speak_string(const std::vector<std::string> prefixes,
prefix += prefixes[j] + " ";
msg = getSpeakString("default " + prefix + key);
- if (msg != "")
+
+ if (!msg.empty())
return msg;
}
}
@@ -109,7 +161,8 @@ static std::string get_speak_string(const std::vector<std::string> prefixes,
prefix = prefixes[i] + " ";
msg = getSpeakString("default " + prefix + key);
- if (msg != "")
+
+ if (!msg.empty())
return msg;
}
}
@@ -117,10 +170,6 @@ static std::string get_speak_string(const std::vector<std::string> prefixes,
// No prefixes
msg = getSpeakString("default " + key);
- // try the same ignoring silence
- if (msg == "" && silenced)
- return get_speak_string(prefixes, key, monster, true);
-
return msg;
}
@@ -139,12 +188,11 @@ static std::string player_ghost_speak_str(const monsters *monster,
prefix += " ";
}
+ // first try together with class name
std::string msg = getSpeakString(prefix + ghost_class + " player ghost");
- if (msg == "__NONE")
- return "";
-
- if (msg == "" || msg == "__NEXT")
+ // else try without class name
+ if (msg.empty() || msg == "__NEXT")
msg = getSpeakString(prefix + "player ghost");
return msg;
@@ -173,19 +221,24 @@ bool mons_speaks(const monsters *monster)
return false;
}
- // charmed monsters aren't too expressive
- if (monster->has_ench(ENCH_CHARM))
- return false;
-
// berserk monsters just want your hide.
if (monster->has_ench(ENCH_BERSERK))
return false;
+ // charmed monsters aren't too expressive
+ if (monster->has_ench(ENCH_CHARM) && !one_chance_in(3))
+ return false;
+
+
std::vector<std::string> prefixes;
- if (monster->attitude == ATT_FRIENDLY)
- prefixes.push_back("friendly");
- else if (monster->attitude == ATT_NEUTRAL)
+ if (mons_neutral(monster))
+ {
+ if (coinflip()) // neutrals speak half as often
+ return false;
prefixes.push_back("neutral");
+ }
+ else if (mons_friendly(monster))
+ prefixes.push_back("friendly");
else
prefixes.push_back("hostile");
@@ -201,17 +254,38 @@ bool mons_speaks(const monsters *monster)
if (monster->has_ench(ENCH_CONFUSION))
prefixes.push_back("confused");
-
+
+ // only look at the current player form
+ if (is_player_same_species(monster->type, true))
+ prefixes.push_back("related");
+
// Add Beogh to list of prefixes for orcs (hostile and friendly) if you
// worship Beogh. (This assumes you being a Hill Orc, so might have odd
- // results in wizard mode.)
- if (you.religion == GOD_BEOGH && mons_genus(monster->type) == MONS_ORC)
+ // results in wizard mode.) Don't count charmed orcs.
+ if (you.religion == GOD_BEOGH && mons_genus(monster->type) == MONS_ORC
+ && !monster->has_ench(ENCH_CHARM))
+ {
prefixes.push_back("beogh");
+ }
else if (is_good_god(you.religion))
prefixes.push_back("good god");
else if (is_evil_god(you.religion))
prefixes.push_back("evil god");
+#ifdef DEBUG_MONSPEAK
+{
+ std::string prefix = "";
+ const int size = prefixes.size();
+ for (int i = 0; i < size; i++)
+ {
+ prefix += prefixes[i];
+ prefix += " ";
+ }
+ mprf(MSGCH_DIAGNOSTICS, "monster speech lookup for %s: prefix = %s",
+ monster->name(DESC_PLAIN).c_str(), prefix.c_str());
+}
+#endif
+
std::string msg;
// First, try its exact name
@@ -225,23 +299,13 @@ bool mons_speaks(const monsters *monster)
else
msg = get_speak_string(prefixes, monster->name(DESC_PLAIN), monster);
- // The exact name brought no results, try species.
- if (msg.empty() || msg == "__NEXT")
+ // The exact name brought no results, try monster genus.
+ if ((msg.empty() || msg == "__NEXT")
+ && mons_genus(monster->type) != monster->type)
{
- if (mons_species(monster->type) != monster->type)
- {
- msg = get_speak_string(prefixes,
- mons_type_name(mons_species(monster->type), DESC_PLAIN),
+ msg = get_speak_string(prefixes,
+ mons_type_name(mons_genus(monster->type), DESC_PLAIN),
monster);
- }
- // Still nothing found? Try monster genus!
- if ((msg.empty() || msg == "__NEXT")
- && mons_genus(monster->type) != monster->type)
- {
- msg = get_speak_string(prefixes,
- mons_type_name(mons_genus(monster->type), DESC_PLAIN),
- monster);
- }
}
// __NONE means to be silent, and __NEXT means to try the next,
@@ -249,16 +313,21 @@ bool mons_speaks(const monsters *monster)
// string.
if (msg == "__NONE")
+ {
+#ifdef DEBUG_MONSPEAK
+ mpr("result: \"__NONE\"!", MSGCH_DIAGNOSTICS);
+#endif
return false;
+ }
// Now that we're not dealing with a specific monster name, include
// whether or not it can move in the prefix
if (mons_is_stationary(monster))
prefixes.insert(prefixes.begin(), "stationary");
- // Names for the monster, its species and its genus all failed,
+ // Names for the exact monster name and its genus have failed,
// so try the monster's glyph/symbol.
- if (msg == "" || msg == "__NEXT")
+ if (msg.empty() || msg == "__NEXT")
{
std::string key = "'";
@@ -271,7 +340,12 @@ bool mons_speaks(const monsters *monster)
msg = get_speak_string(prefixes, key, monster);
}
if (msg == "__NONE")
+ {
+#ifdef DEBUG_MONSPEAK
+ mpr("result: \"__NONE\"!", MSGCH_DIAGNOSTICS);
+#endif
return false;
+ }
// Monster symbol didn't work, try monster shape. Since we're
// dealing with just the monster shape, change the prefix to
@@ -314,14 +388,20 @@ bool mons_speaks(const monsters *monster)
prefixes.insert(prefixes.begin(), "smart");
}
- if (msg == "" || msg == "__NEXT")
+ if (msg.empty() || msg == "__NEXT")
msg = get_speak_string(prefixes, get_mon_shape_str(shape), monster);
+
if (msg == "__NONE")
+ {
+#ifdef DEBUG_MONSPEAK
+ mpr("result: \"__NONE\"!", MSGCH_DIAGNOSTICS);
+#endif
return false;
+ }
// If we failed to get a message with a winged or tailed humanoid,
// or a naga or centaur, try moving closer to plain humanoid
- if ((msg == "" || msg == "__NEXT") && shape > MON_SHAPE_HUMANOID
+ if ((msg.empty() || msg == "__NEXT") && shape > MON_SHAPE_HUMANOID
&& shape <= MON_SHAPE_NAGA)
{
// If a humanoid monster has both wings and a tail, try
@@ -335,15 +415,21 @@ bool mons_speaks(const monsters *monster)
monster);
// Only be silent if both tailed and winged return __NONE
- if (msg == "" || msg == "__NONE" || msg == "__NEXT")
+ if (msg.empty() || msg == "__NONE" || msg == "__NEXT")
{
shape = MON_SHAPE_HUMANOID_WINGED;
std::string msg2;
msg2 = get_speak_string(prefixes,
get_mon_shape_str(shape),
monster);
+
if (msg == "__NONE" && msg2 == "__NONE")
+ {
+#ifdef DEBUG_MONSPEAK
+ mpr("result: \"__NONE\"!", MSGCH_DIAGNOSTICS);
+#endif
return false;
+ }
if (msg2 == "__NONE")
msg2 = "";
@@ -351,7 +437,7 @@ bool mons_speaks(const monsters *monster)
msg = msg2;
}
} // if (shape == MON_SHAPE_HUMANOID_WINGED_TAILED)
- if (msg == "" || msg == "__NONE" || msg == "__NEXT")
+ if (msg.empty() || msg == "__NONE" || msg == "__NEXT")
{
shape = MON_SHAPE_HUMANOID;
msg = get_speak_string(prefixes,
@@ -359,8 +445,14 @@ bool mons_speaks(const monsters *monster)
monster);
}
}
- if (msg == "__NONE" || msg == "")
+ if (msg.empty() || msg == "__NONE")
+ {
+#ifdef DEBUG_MONSPEAK
+ mprf(MSGCH_DIAGNOSTICS, "final result: %s!",
+ (msg.empty() ? "empty" : "\"__NONE\""));
+#endif
return false;
+ }
if (msg == "__NEXT")
{