summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
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
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')
-rw-r--r--crawl-ref/source/dat/database/insult.txt229
-rw-r--r--crawl-ref/source/dat/database/monspeak.txt23
-rw-r--r--crawl-ref/source/database.cc3
-rw-r--r--crawl-ref/source/delay.cc10
-rw-r--r--crawl-ref/source/misc.cc12
-rw-r--r--crawl-ref/source/mon-util.cc64
-rw-r--r--crawl-ref/source/monspeak.cc208
-rw-r--r--crawl-ref/source/player.cc64
-rw-r--r--crawl-ref/source/player.h2
9 files changed, 391 insertions, 224 deletions
diff --git a/crawl-ref/source/dat/database/insult.txt b/crawl-ref/source/dat/database/insult.txt
index 11be0548eb..c68281146e 100644
--- a/crawl-ref/source/dat/database/insult.txt
+++ b/crawl-ref/source/dat/database/insult.txt
@@ -45,123 +45,6 @@ Thy @body_or_spiritual_part@ shall be my @meal@!
I @will_or_shall@ @feast_or_devour@ thy @body_or_spiritual_part@!
-# Not currently used:
-#Thou @generic_insult@!
-
-%%%%
-body_or_spiritual_part
-
-w:3
-@important_body_part@
-
-w:1
-@important_spiritual_part@
-
-%%%%
-will_or_shall
-
-will
-
-shall
-
-%%%%
-feast_or_devour
-
-feast on
-
-devour
-
-%%%%
-#######################################################
-# generic insults consists of three random parts
-#######################################################
-generic_insult
-
-@insult_adjective1@ @insult_adjective2@ @insult_noun@
-
-%%%%
-
-important_body_part
-
-head
-
-brain
-
-heart
-
-viscera
-
-eyes
-
-lungs
-
-liver
-
-throat
-
-neck
-
-skull
-
-spine
-%%%%
-
-important_spiritual_part
-
-soul
-
-spirit
-
-inner light
-
-hope
-
-faith
-
-will
-
-heart
-
-mind
-
-sanity
-
-fortitude
-
-life force
-%%%%
-
-meal
-
-meal
-
-breakfast
-
-lunch
-
-dinner
-
-supper
-
-repast
-
-snack
-
-victuals
-
-refection
-
-junket
-
-luncheon
-
-snackling
-
-curdle
-
-snacklet
-
-mouthful
%%%%
# capitalized "flee" verbs
run_away
@@ -304,6 +187,118 @@ whilst thou art whole
whilst life thou hast
%%%%
+body_or_spiritual_part
+
+w:3
+@important_body_part@
+
+w:1
+@important_spiritual_part@
+
+%%%%
+will_or_shall
+
+will
+
+shall
+
+%%%%
+feast_or_devour
+
+feast on
+
+devour
+
+%%%%
+important_body_part
+
+head
+
+brain
+
+heart
+
+viscera
+
+eyes
+
+lungs
+
+liver
+
+throat
+
+neck
+
+skull
+
+spine
+
+%%%%
+important_spiritual_part
+
+soul
+
+spirit
+
+inner light
+
+hope
+
+faith
+
+will
+
+heart
+
+mind
+
+sanity
+
+fortitude
+
+life force
+%%%%
+
+meal
+
+meal
+
+breakfast
+
+lunch
+
+dinner
+
+supper
+
+repast
+
+snack
+
+victuals
+
+refection
+
+junket
+
+luncheon
+
+snackling
+
+curdle
+
+snacklet
+
+mouthful
+%%%%
+#######################################################
+# generic insults consist of three random parts
+#######################################################
+generic_insult
+
+@insult_adjective1@ @insult_adjective2@ @insult_noun@
+%%%%
###############################################################
# adjective1, usually short and/or consisting of one word only
###############################################################
diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt
index cd50fdb7f5..1b26f010d9 100644
--- a/crawl-ref/source/dat/database/monspeak.txt
+++ b/crawl-ref/source/dat/database/monspeak.txt
@@ -530,6 +530,25 @@ VISUAL:@The_monster@ tries to recover @possessive@ lost courage.
VISUAL:@The_monster@ looks really @rattled@.
## END fleeing humanoid ##
%%%%
+friendly_family
+
+@The_monster@ says, "I like you, cousin!"
+
+@The_monster@ says, "Family always sticks together, @player_name@!"
+
+@The_monster@ says, "@player_genus@kind's got to stick together!"
+
+@The_monster@ shouts, "@player_genus_plural@ are the best!"
+
+@The_monster@ says happily, "You and me, we're family."
+%%%%
+default friendly related humanoid
+
+w:2
+@friendly_family@
+
+@default friendly humanoid@
+%%%%
default friendly humanoid
@The_monster@ yells, "Run! I'll cover you!"
@@ -708,8 +727,6 @@ __NONE
w:1
@_friendly_imp_@
-%%%%
-
####################################################################
# Player ghost phrases. Ghosts with different classes can be given
# different messages.
@@ -815,7 +832,7 @@ VISUAL:@The_monster@ grins evilly.
@The_monster@ screams, "Give me everything and get away!"
-@The_monster@ screams, "I want your rings! And amulets! And... EVERYTHIGNG!"
+@The_monster@ screams, "I want your rings! And amulets! And... EVERYTHING!"
@The_monster@ screams, "I hate dirty adventurers like you!"
diff --git a/crawl-ref/source/database.cc b/crawl-ref/source/database.cc
index 853d5a9a4a..fc33b797a8 100644
--- a/crawl-ref/source/database.cc
+++ b/crawl-ref/source/database.cc
@@ -742,6 +742,9 @@ std::string getSpeakString(const std::string &monst)
int num_replacements = 0;
+#ifdef DEBUG_MONSPEAK
+ mprf(MSGCH_DIAGNOSTICS, "monster speech lookup for %s", monst.c_str());
+#endif
return getRandomizedStr(speakDB, monst, "", num_replacements);
}
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index cf282c8458..5448984ea0 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -859,13 +859,13 @@ static void finish_delay(const delay_queue_item &delay)
(you.has_usable_claws() || you.mutation[MUT_FANGS] == 3) ?
"ripping" : "chopping");
- if (you.religion == GOD_ZIN && mons_intel(item.plus) >= I_NORMAL)
- simple_god_message(" expects more respect for this departed "
- "soul.");
- else if (is_good_god(you.religion) && is_player_same_species(item.plus))
+ if (is_good_god(you.religion) && is_player_same_species(item.plus))
simple_god_message(" expects more respect for your departed "
"relatives.");
-
+ else if (you.religion == GOD_ZIN && mons_intel(item.plus) >= I_NORMAL)
+ simple_god_message(" expects more respect for this departed "
+ "soul.");
+
if (you.species == SP_VAMPIRE &&
mons_corpse_effect(item.plus) != CE_HCL &&
(!god_likes_butchery(you.religion) ||
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 4cb63046bc..ad5f84db63 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -650,12 +650,12 @@ void up_stairs(dungeon_feature_type force_stair,
crawl_state.level_annotation_shown = false;
- if (level_annotation_has("WARN", next_level_id)
+ if (level_annotation_has("!", next_level_id)
&& next_level_id != level_id::current()
&& next_level_id.level_type == LEVEL_DUNGEON && !force_stair)
{
mpr("Warning: level annotation for next level is:", MSGCH_PROMPT);
- mpr(get_level_annotation(next_level_id).c_str(), MSGCH_PROMPT);
+ mpr(get_level_annotation(next_level_id).c_str(), MSGCH_PLAIN, YELLOW);
if (!yesno("Enter next level anyway?", true, 0, true, false))
{
@@ -711,7 +711,7 @@ void up_stairs(dungeon_feature_type force_stair,
old_level_info.update();
// Make sure we return to our main dungeon level... labyrinth entrances
- // in the abyss or pandemonium a bit trouble (well the labyrinth does
+ // in the abyss or pandemonium are a bit trouble (well the labyrinth does
// provide a way out of those places, its really not that bad I suppose)
if (level_type_exits_up(you.level_type))
you.level_type = LEVEL_DUNGEON;
@@ -885,6 +885,7 @@ void up_stairs(dungeon_feature_type force_stair,
}
}
}
+ request_autopickup();
} // end up_stairs()
void down_stairs( int old_level, dungeon_feature_type force_stair,
@@ -1031,12 +1032,12 @@ void down_stairs( int old_level, dungeon_feature_type force_stair,
crawl_state.level_annotation_shown = false;
- if (level_annotation_has("WARN", next_level_id)
+ if (level_annotation_has("!", next_level_id)
&& next_level_id != level_id::current()
&& next_level_id.level_type == LEVEL_DUNGEON && !force_stair)
{
mpr("Warning: level annotation for next level is:", MSGCH_PROMPT);
- mpr(get_level_annotation(next_level_id).c_str(), MSGCH_PROMPT);
+ mpr(get_level_annotation(next_level_id).c_str(), MSGCH_PLAIN, YELLOW);
if (!yesno("Enter next level anyways?", true, 0, true, false))
{
@@ -1393,6 +1394,7 @@ void down_stairs( int old_level, dungeon_feature_type force_stair,
new_level_info.update_stair(you.x_pos, you.y_pos, lp, true);
}
}
+ request_autopickup();
} // end down_stairs()
void trackers_init_new_level(bool transit)
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 8e5e5450c7..e0a2cd14ee 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -5418,6 +5418,21 @@ static std::string get_species_insult(const std::string type)
return (insult);
}
+static std::string pluralise_player_genus()
+{
+ std::string sp = species_name(you.species, 1, true);
+ if (player_genus(GENPC_ELVEN, you.species)
+ || player_genus(GENPC_DWARVEN, you.species))
+ {
+ sp = sp.substr(0, sp.find("f"));
+ sp += "ves";
+ }
+ else if (you.species != SP_DEMONSPAWN)
+ sp += "s";
+
+ return (sp);
+}
+
// Replaces the "@foo@" strings in monster shout and monster speak
// definitions.
std::string do_mon_str_replacements(const std::string &in_msg,
@@ -5466,6 +5481,12 @@ std::string do_mon_str_replacements(const std::string &in_msg,
}
msg = replace_all(msg, "@player_name@", you.your_name);
+ msg = replace_all(msg, "@player_species@",
+ species_name(you.species, 1).c_str());
+ msg = replace_all(msg, "@player_genus@",
+ species_name(you.species, 1, true).c_str());
+ msg = replace_all(msg, "@player_genus_plural@",
+ pluralise_player_genus().c_str());
if (player_monster_visible(monster))
{
@@ -5518,9 +5539,12 @@ std::string do_mon_str_replacements(const std::string &in_msg,
msg = replace_all(msg, "@Player_god@", replace_god_name(false, true));
// replace with species specific insults
- msg = replace_all(msg, "@species_insult_adj1@", get_species_insult("adj1"));
- msg = replace_all(msg, "@species_insult_adj2@", get_species_insult("adj2"));
- msg = replace_all(msg, "@species_insult_noun@", get_species_insult("noun"));
+ if (msg.find("@species_insult_") != std::string::npos)
+ {
+ msg = replace_all(msg, "@species_insult_adj1@", get_species_insult("adj1"));
+ msg = replace_all(msg, "@species_insult_adj2@", get_species_insult("adj2"));
+ msg = replace_all(msg, "@species_insult_noun@", get_species_insult("noun"));
+ }
static const char * sound_list[] =
{
@@ -5618,8 +5642,8 @@ mon_body_shape get_mon_shape(const int type)
case 'c': // centaurs
return(MON_SHAPE_CENTAUR);
case 'd': // draconions and drakes
- if (mons_genus(type) == MONS_DRACONIAN ||
- mons_class_flag(type, M_HUMANOID))
+ if (mons_genus(type) == MONS_DRACONIAN
+ || mons_class_flag(type, M_HUMANOID))
{
if (mons_class_flag(type, M_FLIES))
return(MON_SHAPE_HUMANOID_WINGED_TAILED);
@@ -5640,38 +5664,39 @@ mon_body_shape get_mon_shape(const int type)
else
return(MON_SHAPE_HUMANOID);
case 'h': // hounds
- case 'j': // jackals
return(MON_SHAPE_QUADRUPED);
+ case 'j': // snails
+ return(MON_SHAPE_SNAIL);
case 'k': // killer bees
return(MON_SHAPE_INSECT_WINGED);
case 'l': // lizards
return(MON_SHAPE_QUADRUPED);
- case 'm': // minotaurs, manticores, and snails/slugs/etc
- if (type == MONS_MINOTAUR)
- return(MON_SHAPE_HUMANOID);
- else if (type == MONS_MANTICORE)
- return(MON_SHAPE_QUADRUPED);
- else
- return(MON_SHAPE_SNAIL);
+ case 'm': // merfolk
+ return(MON_SHAPE_HUMANOID);
case 'n': // necrophages and ghouls
return(MON_SHAPE_HUMANOID);
case 'o': // orcs
return(MON_SHAPE_HUMANOID);
case 'p': // ghosts
- if (type != MONS_INSUBSTANTIAL_WISP &&
- type != MONS_PLAYER_GHOST)
+ if (type != MONS_INSUBSTANTIAL_WISP
+ && type != MONS_PLAYER_GHOST) // handled elsewhere
+ {
return(MON_SHAPE_HUMANOID);
+ }
+ break;
case 'q': // quasists
return(MON_SHAPE_HUMANOID_TAILED);
case 'r': // rodents
return(MON_SHAPE_QUADRUPED);
- case 's': // arachnids and centidpeds
+ case 's': // arachnids and centipedes
if (type == MONS_GIANT_CENTIPEDE)
return(MON_SHAPE_CENTIPEDE);
else
return(MON_SHAPE_ARACHNID);
case 'u': // ugly things are humanoid???
return(MON_SHAPE_HUMANOID);
+ case 't': // minotaurs
+ return(MON_SHAPE_HUMANOID);
case 'v': // vortices and elementals
return(MON_SHAPE_MISC);
case 'w': // worms
@@ -5703,8 +5728,11 @@ mon_body_shape get_mon_shape(const int type)
return(MON_SHAPE_QUADRUPED_TAILLESS);
case 'G': // floating eyeballs and orbs
return(MON_SHAPE_ORB);
- case 'H': // hippogriffs and griffns
- return(MON_SHAPE_QUADRUPED_WINGED);
+ case 'H': // manticores, hippogriffs and griffins
+ if (type == MONS_MANTICORE)
+ return(MON_SHAPE_QUADRUPED);
+ else
+ return(MON_SHAPE_QUADRUPED_WINGED);
case 'I': // ice beasts
return(MON_SHAPE_QUADRUPED);
case 'J': // jellies and jellyfish
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")
{
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 772462174b..9a1f80d31a 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -426,54 +426,83 @@ bool player_genus(genus_type which_genus, species_type species)
return (false);
} // end player_genus()
-bool is_player_same_species(const int mon)
+// If transform is true, compare with current transformation instead
+// of (or in addition to) underlying species.
+// (See mon-data.h for species/genus use.)
+bool is_player_same_species(const int mon, bool transform)
{
+ if (transform)
+ {
+ switch (you.attribute[ATTR_TRANSFORMATION])
+ {
+ case TRAN_AIR:
+ return (false);
+ // unique monsters
+ case TRAN_BAT:
+ return (mon == MONS_GIANT_BAT);
+ case TRAN_ICE_BEAST:
+ return (mon == MONS_ICE_BEAST);
+ case TRAN_SERPENT_OF_HELL:
+ return (mon == MONS_SERPENT_OF_HELL);
+ // compare with monster *species*
+ case TRAN_LICH:
+ return (mons_species(mon) == MONS_LICH);
+ // compare with monster *genus*
+ case TRAN_SPIDER:
+ return (mons_genus(mon) == MONS_WOLF_SPIDER);
+ case TRAN_DRAGON:
+ return (mons_genus(mon) == MONS_DRAGON); // includes all drakes
+ default:
+ break; // check real (non-transformed) form
+ }
+ }
+
switch (you.species)
{
case SP_HUMAN:
- if (mons_species(mon) == MONS_HUMAN)
+ if (mons_genus(mon) == MONS_HUMAN)
return (true);
return (false);
case SP_CENTAUR:
- if (mons_species(mon) == MONS_CENTAUR)
+ if (mons_genus(mon) == MONS_CENTAUR)
return (true);
return (false);
case SP_OGRE:
case SP_OGRE_MAGE:
- if (mons_species(mon) == MONS_OGRE)
+ if (mons_genus(mon) == MONS_OGRE)
return (true);
return (false);
case SP_TROLL:
- if (mons_species(mon) == MONS_TROLL)
+ if (mons_genus(mon) == MONS_TROLL)
return (true);
return (false);
case SP_MUMMY:
- if (mons_species(mon) == MONS_MUMMY)
+ if (mons_genus(mon) == MONS_MUMMY)
return (true);
return (false);
- case SP_GHOUL:
+ case SP_GHOUL: // genus would include necrophage and rotting hulk
if (mons_species(mon) == MONS_GHOUL)
return (true);
return (false);
case SP_VAMPIRE:
- if (mons_species(mon) == MONS_VAMPIRE)
+ if (mons_genus(mon) == MONS_VAMPIRE)
return (true);
return (false);
case SP_MINOTAUR:
- if (mons_species(mon) == MONS_MINOTAUR)
+ if (mons_genus(mon) == MONS_MINOTAUR)
return (true);
return (false);
case SP_NAGA:
- if (mons_species(mon) == MONS_NAGA)
+ if (mons_genus(mon) == MONS_NAGA)
return (true);
return (false);
case SP_HILL_ORC:
- if (mons_species(mon) == MONS_ORC)
+ if (mons_genus(mon) == MONS_ORC)
return (true);
return (false);
case SP_MERFOLK:
- if (mons_species(mon) == MONS_MERFOLK
- || mons_species(mon) == MONS_MERMAID)
+ if (mons_genus(mon) == MONS_MERFOLK
+ || mons_genus(mon) == MONS_MERMAID)
{
return (true);
}
@@ -483,7 +512,7 @@ bool is_player_same_species(const int mon)
case SP_HIGH_ELF:
case SP_DEEP_ELF:
case SP_SLUDGE_ELF:
- if (mons_species(mon) == MONS_ELF)
+ if (mons_genus(mon) == MONS_ELF)
return (true);
return (false);
@@ -496,12 +525,12 @@ bool is_player_same_species(const int mon)
case SP_PURPLE_DRACONIAN:
case SP_MOTTLED_DRACONIAN:
case SP_PALE_DRACONIAN:
- if (mons_species(mon) == MONS_DRACONIAN)
+ if (mons_genus(mon) == MONS_DRACONIAN)
return (true);
return (false);
case SP_KOBOLD:
- if (mons_species(mon) == MONS_KOBOLD)
+ if (mons_genus(mon) == MONS_KOBOLD)
return (true);
return (false);
default: // no monster equivalent
@@ -3934,7 +3963,8 @@ std::string species_name(species_type speci, int level, bool genus, bool adj)
// We've previously declared that these are radically
// different from Ogres... so we're not going to
// refer to them as Ogres. -- bwr
- case SP_OGRE_MAGE: res = "Ogre-Mage"; break;
+ // Not the species, but genus... why not? -- jpeg
+ case SP_OGRE_MAGE: res = (genus? "Ogre" : "Ogre-Mage"); break;
case SP_CENTAUR: res = "Centaur"; break;
case SP_SPRIGGAN: res = "Spriggan"; break;
case SP_MINOTAUR: res = "Minotaur"; break;
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index 378629316c..11840c558d 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -326,7 +326,7 @@ void redraw_skill(const std::string &your_name, const std::string &class_name);
* *********************************************************************** */
bool player_genus( genus_type which_genus,
species_type species = SP_UNKNOWN );
-bool is_player_same_species( const int mon );
+bool is_player_same_species( const int mon, bool = false );
bool you_can_wear( int eq, bool special_armour = false );
bool player_has_feet(void);