the dumped information in the morgue. Change monster naming to the precise listing of zombie sub types etc. but list monster types in brackets for non-unique named monsters, so you can now find information like the following in your morgue file:
"You can see a goblin, an orc, two orc warriors, thirteen friendly orcs, and the friendly Bogrim (orc priest)."
Since the concise version of the monster list is still an in-game command ('F'), this also neatly solves the problem of orc players not knowing the type of their followers.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5223 c06c8d41-db1a-0410-9941-cceddc491573
QSRRV725GCNDOMIDS36NYAA65MOLDMAZSENVSZ3PNOLBFSGHH7BQC
QV3SYOLTVIFCTWMVKJNJAUGJPCYSGXJOE64242YB2KV74Q46QB7QC
XE5FBYASPYLMBNHWKL5MRN7TQGIWR4O6PF72I7WXRTUJ7HS2O2LAC
PVMLVMD53B2PAH2X3MOVFOOLVBNMHRWJ35H7IKHAPUW6MIM7NMYAC
5NNXFH3NRVYSU2ZSN6EUDB6RUVO7LZPYQDMKCQ2BWHNC7JPHR2ZAC
M2EUGZPKR6XTZSLQYDO7CDBBR2WPPMCBIBKJSZW5P7KYUOUPZSZQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
YYIBXE7VFJTRT73QDNFL3MQ3LP3OK4KML5YMEMRKQUQZJVAWORWAC
47NSOFQMBZCDIBHEAZSENFUGDSQCX3GJHFBUZ65ARDKCYIZ435LAC
VEPHAIXR3GSPHBLOW5DWFFU4ULEMVWRQG4G5PKSKRA2I6RHYROUAC
RHV7P556KYXDQ6QYGSRLOZBRKLMKWHHKLRQTP2WBMUZYMIAG7OBQC
TR4NPGNO5QNNRJNVMNSUEO5QLT37HCXXDOBKXCB5XWXRQNAJ5SHAC
TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC
YIIILIV4ZPRIPWWT4GL7YWSJCUVH6RJJLXV4XIHY6SF3H7Y3EAYAC
QSJECU2LZOQ5K5QUQDQOPQ4J3GAZEE5ZWIIM4DVBXYLVVX5DYLWQC
4UQBOVCMAMNCCF6PPX222H6JJO7MPYOKKC2NBKMVYIT5R5FOACNAC
QYUAYEGK7WPBJLZRSWZVDWD5SMNAWWIJSQPWYA7BEYXMEBD2SDKAC
Q263OF72GJOH2VQHGCF5IYZ5UHKV5DNX3J3WTCEONPN3WGGNZOUQC
NY5JJY33IHF5EKTLPDFVYTN3PFNKV4A3MAH5MRQ3AWH53L2HFIQQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
NO2HRD7RZS42S55UG4FQ5EFQDY6WYWKGIXHUKYLWF36HHE3VZ7WAC
5B5DP5S6A6LQMKZYVLQAEMHQZWFWYDHPCKQGRNSCNNYIBQYZ6BIQC
P2YNOE2TUTZFAOBTHJOIVD6TCV7J7D2UKUX67LHZUL6QY44ZMENQC
TM35IHKZZNBCMR3ERBS4EYHGUK5IVCPUT2JUITMT74AYAIUZSYFQC
7NDXS36TE7QVXTXJWMYSVG5UHCCLPIO4VL6NXFGTDK3ZNKE3A2IAC
HYS3HXTXATFPN7GLN3WBGDCP22UT2D3JBVUS7SP5FE7L54TDCJRQC
JR2RAQ523LOWNDYJNK6AZVKI6WVMI622PIV72XWOVZYPXPUKSQWAC
UL6TJFCVOYWGHMOYG7PCODNN2TRWXLZ46YP6AMFJF5YIKYQVLUTQC
CGYTZT5QWIEGYKUOLOK7MFXSLJKLYRZONER5ZCDZO5XYWSLG475QC
HL47H6Q4SA2KSPHWZSOCGHHCDB6JGC4LLHPA4JUHNCCPF2ZGQNTAC
7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC
JJULXW764V5C2HJKZNWQAEWB6QM5YZADD7ZCE35LYTBFEM6PMYCAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
YATODO2EN3AW7IXW5PL25HHK34YHF6Y32QBMOUZXEATZZ4YQQWZQC
WW6THKR7JN447YC23YYHYYNH7ABMCFFSECNUFTIJBZX6JHX6W7TAC
GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC
YA24HFHVUI2LDWFOZR5QSHRIVTAWGSGPAH5E2FPP6ANCL2MTUSTAC
UOW2X5KTUHYCM73SWNOSJPHUKWVLF3OJTNSISSSENEURBX2XWHVQC
ZWBYOITMEKDLV22GQT32FZ4WXTZLHB6T5HUUYVE5G53KFASUNO7QC
BWAQ3FHBBM6G3K3KYP75CRTR343RDQZJRYX5ZGYUEXYBAC3APDLAC
5V47S4NNTHWTSAHV3YLO2VGH7JTUIYJ3GBPDN5ZM4UQALT2ZEXDQC
TAVHZJPVNJBZR7CUURAOYNDZPNVQ3AGHTXDEP5K4JGYETBLQJDRQC
5RK245FAGZFCDDYG4AZAXSC7JPVIJG4DSAVAKHWWVBUNGICHYNJQC
AYYQVALBAAKFK5U52WGHWE2N7LCVZM3BGRADPVJQWOFLS2TXK6QAC
547JREUJXTZNYVGHNNAET5F5O5JYYGNTDQB6ABZNT7YX5EY64OHAC
5367JDYN2THJDKXGPP3UJYZFLBOUHCWRPPMBEQCFUALLAHLGAPOAC
DOZORMA366M4HB5JKSS27BMCR6ET7QNZNND2B7KV3NVEEPR5H7EAC
FLKXPXQ7SRFZPJPDM35D5CG6M52WP4SL32QNEZNSHGBNZYTKYGYAC
7PRZJ6KZLG26YVTAMXT7YOTQLWZHGWGRTKXZZ52P4XYCQD4GT5WQC
XX62GOJVDP352L4BH7MELNYXHMZNA6VAGF7B6RWWOSULX7VJR5YAC
7VRY3OH6WA7QLMNNOX76RR7C6HA7CLNYLZLWPXJWAP75QRF5B27AC
NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC
3VWSZUGYL36SO5AOZRASGK3VHFCFZUGGCGRT3R7BZB36IZPN7OSQC
ELMP33CXUMJE3D5XQXR3GWKNAVYTBA4E5BFDVCZ5KKWKKGMGYIHQC
WL5WZXFJ6TONUQRSHUY4GQ5USU47ILWNN5X2JDQZO4CRJJZSRQIAC
RVST2QHYJ757ZHK4AUJ5NGPDZ44AD6RVFVXYPKQIBJXZBDNUCHXQC
EHSY6DVGUMI6C67WKET3GDJVLWJWGYBYQONNDK5JVT7BCTHBEZVAC
void print_stats();
void print_stats_level();
void draw_border();
void print_stats(void);
void print_stats_level(void);
void draw_border(void);
std::string mpr_monster_list(bool past = false);
static bool _mons_hostile(const monsters *mon)
{
return (!mons_friendly(mon) && !mons_neutral(mon));
}
static const char* _get_monster_name(const monsters *mon, bool list_a = false)
{
std::string desc = "";
bool adj = false;
if (mons_friendly(mon))
{
desc += "friendly ";
adj = true;
}
else if (mons_neutral(mon))
{
desc += "neutral ";
adj = true;
}
if (adj && list_a)
{
desc = (mon->is_named() ? "the " : "a ") + desc;
list_a = false;
}
desc += mon->name(list_a ? DESC_NOCAP_A : DESC_PLAIN);
if (!(mon->mname).empty())
{
desc += " (";
desc += mons_type_name(mon->type, DESC_PLAIN);
desc += ")";
}
return desc.c_str();
}
// Returns true if the first monster is more aggressive (in terms of
// hostile/neutral/friendly) than the second, or, if both monsters share the
// same attitude, if the first monster has a lower type.
// If monster type and attitude are the same, return false.
static bool _compare_monsters_attitude( const monsters *m1, const monsters *m2 )
{
if (_mons_hostile(m1) && !_mons_hostile(m2))
return (true);
if (mons_neutral(m1))
{
if (mons_friendly(m2))
return (true);
if (_mons_hostile(m2))
return (false);
}
if (mons_friendly(m1) && !mons_friendly(m2))
return (false);
// If we get here then monsters have the same attitude.
// FIXME: replace with difficulty comparison
return (m1->type < m2->type);
}
static void _get_visible_monsters(std::vector<std::string>& describe)
{
int ystart = you.y_pos - 9, xstart = you.x_pos - 9;
int yend = you.y_pos + 9, xend = you.x_pos + 9;
if ( xstart < 0 ) xstart = 0;
if ( ystart < 0 ) ystart = 0;
if ( xend >= GXM ) xend = GXM;
if ( yend >= GYM ) yend = GYM;
std::vector<const monsters*> mons;
// monster check
for (int y = ystart; y < yend; ++y)
for (int x = xstart; x < xend; ++x)
if (see_grid(x,y))
{
const unsigned short targ_monst = mgrd[x][y];
if (targ_monst != NON_MONSTER)
{
const monsters *mon = &menv[targ_monst];
if (player_monster_visible(mon)
&& !mons_is_submerged(mon)
&& !mons_is_mimic(mon->type))
{
mons.push_back(mon);
}
}
}
if (mons.empty())
return;
std::sort( mons.begin(), mons.end(), _compare_monsters_attitude );
int count = 0;
int size = mons.size();
for (int i = 0; i < size; ++i)
{
if (i > 0 && _compare_monsters_attitude(mons[i-1], mons[i]))
{
if (count == 1)
describe.push_back(_get_monster_name(mons[i-1], true));
else
{
describe.push_back(number_in_words(count) + " "
+ pluralise(_get_monster_name(mons[i-1])));
}
count = 0;
}
count++;
}
// handle last monster
if (mons.size() == 1
|| _compare_monsters_attitude(mons[size-2], mons[size-1]))
{
describe.push_back(_get_monster_name(mons[size-1], true));
}
else
{
describe.push_back(number_in_words(count) + " "
+ pluralise(_get_monster_name(mons[size-1])));
}
}
// If past is true, the messages should be printed in the past tense
// because they're needed for the morgue dump.
std::string mpr_monster_list(bool past)
{
std::vector<std::string> describe;
_get_visible_monsters(describe);
std::string msg = "";
if (describe.empty())
{
msg = "There ";
msg += (past ? "were" : "are");
msg += " no monsters in sight!";
return (msg);
}
msg = "You ";
msg += (past ? "could" : "can");
msg += " see ";
if (describe.size() == 1)
msg += describe[0];
else
{
msg += comma_separated_line(describe.begin(), describe.end(),
", and ", ", ");
}
msg += ".";
return (msg);
}
const int rmuta = wearing_amulet(AMU_RESIST_MUTATION, calc_unid)
|| player_mutation_level(MUT_MUTATION_RESISTANCE) == 3
|| you.religion == GOD_ZIN && you.piety >= 150;
const int rmuta = (wearing_amulet(AMU_RESIST_MUTATION, calc_unid)
|| player_mutation_level(MUT_MUTATION_RESISTANCE) == 3
|| you.religion == GOD_ZIN && you.piety >= 150);
// special behaviour for size == 0, largely because the return value
// in that case varies depending on which standard is being used (SUSv2
// special behaviour for size == 0, largely because the return value
// in that case varies depending on which standard is being used (SUSv2
dump_kill_places =
field == "none"? KDO_NO_PLACES :
field == "all" ? KDO_ALL_PLACES :
KDO_ONE_PLACE;
dump_kill_places = (field == "none" ? KDO_NO_PLACES :
field == "all" ? KDO_ALL_PLACES
: KDO_ONE_PLACE);
static const char* _get_monster_name(const monsters *mon, bool list_a = false)
{
std::string desc = "";
bool adj = false;
if (mons_friendly(mon))
{
desc += "friendly ";
adj = true;
}
else if (mons_neutral(mon))
{
desc += "neutral ";
adj = true;
}
if (adj && list_a)
{
desc = "a " + desc;
list_a = false;
}
desc += mons_type_name(mon->type, (list_a ? DESC_NOCAP_A : DESC_PLAIN));
return desc.c_str();
}
// Returns true if the first monster is more aggressive (in terms of
// hostile/neutral/friendly) than the second or, if both monsters share the
// same attitude, if the first monster has a lower type.
// If monster type and attitude are the same, return false.
static bool _compare_monsters_attitude( const monsters *m1, const monsters *m2 )
{
if (_mons_hostile(m1) && !_mons_hostile(m2))
return (true);
if (mons_neutral(m1))
{
if (mons_friendly(m2))
return (true);
if (_mons_hostile(m2))
return (false);
}
if (mons_friendly(m1) && !mons_friendly(m2))
return (false);
// If we get here then monsters have the same attitude.
// FIX ME: replace with difficulty comparison
return (m1->type < m2->type);
}
void get_visible_monsters(std::vector<std::string>& describe)
{
int ystart = you.y_pos - 9, xstart = you.x_pos - 9;
int yend = you.y_pos + 9, xend = you.x_pos + 9;
if ( xstart < 0 ) xstart = 0;
if ( ystart < 0 ) ystart = 0;
if ( xend >= GXM ) xend = GXM;
if ( yend >= GYM ) yend = GYM;
std::vector<const monsters*> mons;
// monster check
for ( int y = ystart; y < yend; ++y )
for ( int x = xstart; x < xend; ++x )
if ( see_grid(x,y) )
{
const unsigned short targ_monst = mgrd[x][y];
if ( targ_monst != NON_MONSTER )
{
const monsters *mon = &menv[targ_monst];
if ( player_monster_visible(mon)
&& !mons_is_submerged(mon)
&& !mons_is_mimic(mon->type))
{
mons.push_back(mon);
}
}
}
if (mons.empty())
return;
std::sort( mons.begin(), mons.end(), _compare_monsters_attitude );
int count = 0;
int size = mons.size();
for (int i = 0; i < size; ++i)
{
if (i > 0 && _compare_monsters_attitude(mons[i-1], mons[i]))
{
if (count == 1)
describe.push_back(_get_monster_name(mons[i-1], true));
else
{
describe.push_back(number_in_words(count) + " "
+ pluralise(_get_monster_name(mons[i-1])));
}
count = 0;
}
count++;
}
// handle last monster
if (mons.size() == 1 ||
_compare_monsters_attitude(mons[size-2], mons[size-1]))
{
describe.push_back(_get_monster_name(mons[size-1], true));
}
else
{
describe.push_back(number_in_words(count) + " "
+ pluralise(_get_monster_name(mons[size-1])));
}
}
static void _mpr_monsters()
{
std::vector<std::string> describe;
get_visible_monsters(describe);
if (describe.empty())
{
mpr("There are no monsters in sight!");
}
else if (describe.size() == 1)
{
mprf("You can see %s.", describe[0].c_str());
}
else
{
std::string msg = "You can see ";
msg += comma_separated_line(describe.begin(),
describe.end(),
", and ", ", ");
msg += ".";
mpr(msg.c_str());
}
}