git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3853 c06c8d41-db1a-0410-9941-cceddc491573
IQFLSXLOKMSMM65BL7XOEI5ZP55WKZ7BFBOIA44AMTPNJ7DAQXBQC
JDM5R3HYGXKQKZWY35QZ2KOB24TFZ3FW2PCNXCRCMWG72AZC5ZXQC
6KJRTSXHM3MQVU5CLIMN5XDMCWXAHCYR4A5QKS6MGWWEI3TCXLAQC
ELMP33CXUMJE3D5XQXR3GWKNAVYTBA4E5BFDVCZ5KKWKKGMGYIHQC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
QSJECU2LZOQ5K5QUQDQOPQ4J3GAZEE5ZWIIM4DVBXYLVVX5DYLWQC
3VWSZUGYL36SO5AOZRASGK3VHFCFZUGGCGRT3R7BZB36IZPN7OSQC
UWMN4HLG6YA2YFQEVIVMDISD6APKEPIZXMMPMNUYCBQDSAUYSXPQC
R325RPUV26YH65VIJKYEFZ2XCVXQHO5N3ELPX6RNQ5TSI3JJNQGQC
}
// Return true if m1 < m2
static bool
_by_attitude_and_experience(const monsters* m1, const monsters* m2)
{
// XXX: this doesn't take into account ENCH_NEUTRAL, but that's probably
// a bug for mons_attitude, not this.
// XXX: also, mons_attitude_type should be sorted hostile/neutral/friendly;
// will break saves a little bit though.
const mon_attitude_type a1 = mons_attitude(m1);
const mon_attitude_type a2 = mons_attitude(m2);
if (a1 < a2) return true;
else if (a1 > a2) return false;
// sort by difficulty... but want to avoid information leaks too. Hm.
const int xp1 = mons_type_hit_dice(m1->type);
const int xp2 = mons_type_hit_dice(m2->type);
if (xp1 > xp2) return true;
else if (xp1 < xp2) return false;
// This last so monsters of the same type clump together
if (m1->type < m2->type) return true;
else if (m1->type > m2->type) return false;
return false;
}
static void
_print_next_monster_desc(const std::vector<monsters*>& mons,
int& start)
{
// skip forward to the end of the range of identical monsters
monsters* m1 = mons[start];
unsigned int cur = start;
while (true)
{
if (cur + 1 == mons.size()) break;
// If m1 < m2, they can't be "equal"
// (and since array is sorted, they are otherwise "equal")
if (_by_attitude_and_experience(m1, mons[cur])) break;
cur += 1;
}
// start and cur are "equal" monsters. It shouldn't matter
// which one we choose in that range. I will choose start.
{
unsigned int glyph;
unsigned short glyph_color;
get_mons_glyph(m1, &glyph, &glyph_color);
textcolor(glyph_color);
cprintf( stringize_glyph(glyph).c_str() );
const int count = (cur - start + 1);
textcolor(LIGHTGREY);
cprintf(" - ");
if (count == 1)
{
std::string name = mons_type_name(m1->type, DESC_CAP_A);
cprintf("%s", name.c_str());
}
else
{
std::string name = pluralise(mons_type_name(m1->type, DESC_PLAIN));
cprintf("%d %s", count, name.c_str());
}
// Friendliness -- maybe use color instead?
{
const mon_attitude_type att = mons_attitude(m1);
switch (att) {
case ATT_FRIENDLY: cprintf(" (friendly)"); break;
case ATT_NEUTRAL: cprintf(" (neutral)"); break;
case ATT_HOSTILE: /*cprintf(" (hostile)")*/; break;
}
}
}
// Increment start to the next un-described monster
start = cur + 1;
textcolor(LIGHTGREY);
// - print monster glyph, in proper color
// - get health and friendliness in there (using color and/or text)
extern void get_visible_monsters(std::vector<std::string>& );
std::vector<std::string> describe;
get_visible_monsters(describe);
// - display rough health (color, or text?)
// - fix up issues with the sorting (see _by_attitude_and_experience)
// Print the visible monsters
for (int i=0; i<num_print; i++)
{
cgotoxy(1, i+1, GOTO_MLIST);
clear_to_end_of_line();
cgotoxy(1, i+1, GOTO_MLIST);
cprintf(describe[i].c_str());
}
// Sadly, the defaults don't leave _any_ room for monsters :(
if (max_print <= 0)
return;
extern void get_playervisible_monsters(std::vector<monsters*>& );
std::vector<monsters*> mons;
get_playervisible_monsters(mons);
std::sort(mons.begin(), mons.end(), _by_attitude_and_experience);
// Return all monsters in LOS that the player is able to see.
void get_playervisible_monsters(std::vector<monsters*>& mons)
{
const int ystart = MAX(0, you.y_pos - LOS_RADIUS);
const int yend = MIN(GYM, you.y_pos + LOS_RADIUS);
const int xstart = MAX(0, you.x_pos - LOS_RADIUS);
const int xend = MIN(GXM, you.x_pos + LOS_RADIUS);
// monster check
for ( int y = ystart; y < yend; ++y )
for ( int x = xstart; x < xend; ++x )
{
const unsigned short targ_monst = env.mgrid[x][y];
if ( targ_monst != NON_MONSTER )
{
if ( see_grid(x,y) )
{
monsters *mon = &env.mons[targ_monst];
if ( player_monster_visible(mon) &&
!mons_is_submerged(mon) &&
!mons_is_mimic(mon->type) )
{
mons.push_back(mon);
}
}
}
}
}