Fix: Known mimics are now included in playervisible monster list
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3951 c06c8d41-db1a-0410-9941-cceddc491573
NO2HRD7RZS42S55UG4FQ5EFQDY6WYWKGIXHUKYLWF36HHE3VZ7WAC JJHOTW7LDUJ6DLUG2DTFWASCAFPGD2WBW7MHBSECJZU7PTJYWQDQC DKRSOHZXL6EPSLKOKHF7GJXSZEJVY7CXGACSHWLM5B5FTRETWWCAC OEISFRW2B7E4YRJSWXNXBH2IAJO4O3LHNYFPFD3MBY57LYVRHMZQC 4UQBOVCMAMNCCF6PPX222H6JJO7MPYOKKC2NBKMVYIT5R5FOACNAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC IQFLSXLOKMSMM65BL7XOEI5ZP55WKZ7BFBOIA44AMTPNJ7DAQXBQC 3VWSZUGYL36SO5AOZRASGK3VHFCFZUGGCGRT3R7BZB36IZPN7OSQC TM35IHKZZNBCMR3ERBS4EYHGUK5IVCPUT2JUITMT74AYAIUZSYFQC G3BGTWSXRETYVNLG24E4O7SRMTB352REOQAFOIL4WB7X74P4RDIAC YMC3RKF4Z7DOHZNGG7INC343SXCTWOPK7ISD42I3WA3AZZNVBGIAC FACD4S74A4PYPEYDEIDP56BPE5NJGRK2RWVOKROXLMT7FJUPTYQAC ELMP33CXUMJE3D5XQXR3GWKNAVYTBA4E5BFDVCZ5KKWKKGMGYIHQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC 43ZTEB57FU7KE5EVMYWZONNVJBZCGF3JEAJZIY25LC4LGE65PG5QC JM7UAK777RAVDAVLQLEOBRTGNW2B47S5G55XITJXO243IUNZHVYQC UDYVF65OZSNPANLHDI3ODBEGUAKAVZ4KH4OZFAKR2CQJPO4AXU6QC UWMN4HLG6YA2YFQEVIVMDISD6APKEPIZXMMPMNUYCBQDSAUYSXPQC ZP2KE7A2LE7Z2S7AC45WE4CXDSEVDTWIMV2EM4IBUKXYJIDU6R7QC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC }#ifndef USE_TILEstatic int _average_hp(const monsters* mon){const monsterentry* me = get_monster_data(mon->type);return me->hpdice[0] * (me->hpdice[1] + me->hpdice[2]>>1) + me->hpdice[3];}// Return true if m1 < m2static 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 = _average_hp(m1);const int xp2 = _average_hp(m2);if (xp1 > xp2)return true;else if (xp1 < xp2)return false;// This last so monsters of the same type clump togetherif (m1->type < m2->type)return true;return false;}static void_print_next_monster_desc(const std::vector<monsters*>& mons, int& start){// skip forward to past the end of the range of identical monstersunsigned int end;for (end=start+1; end < mons.size(); ++end){// Array is sorted, so if !(m1 < m2), m1 and m2 are "equal"if (_by_attitude_and_experience(mons[start], mons[end]))break;}// Postcondition: all monsters in [start, end) are "equal"// Print one of the monsters we've found; shouldn't matter which.{const monsters* mon = mons[start]; // arbitraryunsigned int glyph;unsigned short glyph_color;get_mons_glyph(mon, &glyph, &glyph_color);textcolor(glyph_color);cprintf( stringize_glyph(glyph).c_str() );const int count = (end - start);textcolor(LIGHTGREY);cprintf(" - ");if (count == 1){std::string name = mons_type_name(mon->type, DESC_CAP_A);cprintf("%s", name.c_str());}else{std::string name = pluralise(mons_type_name(mon->type, DESC_PLAIN));cprintf("%d %s", count, name.c_str());}#if DEBUG_DIAGNOSTICScprintf(" av%d %d/%d", _average_hp(mon), mon->hit_points,mon->max_hit_points);#endif// Friendliness -- maybe use color instead?{const mon_attitude_type att = mons_attitude(mon);switch (att){case ATT_FRIENDLY: cprintf(" (friendly)"); break;case ATT_NEUTRAL: cprintf(" (neutral)"); break;case ATT_HOSTILE: /*cprintf(" (hostile)")*/; break;}}}// Set start to the next un-described monsterstart = end;textcolor(LIGHTGREY);
void update_monster_pane(){// TODO:// - display rough health (color, or text?)// - fix up issues with the sorting (see _by_attitude_and_experience)const int start_row = 1;const int max_print = crawl_view.mlistsz.y;// 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);
// Print the monsters!for (int i_print = 0, i_mons=0; i_print < max_print; ++i_print){// Can't clear to end of line, as the monster pane// may be to the left of the hud or view pane.for (int x = 1; x <= crawl_view.mlistsz.x; x++){cgotoxy(x, start_row+i_print, GOTO_MLIST);putch(' ');}cgotoxy(1, start_row+i_print, GOTO_MLIST);// i_mons is incremented by _print_next_monster_descif (i_mons < (int)mons.size()){cgotoxy(1, start_row+i_print, GOTO_MLIST);_print_next_monster_desc(mons, i_mons);}}}#else// FIXME: implement this for tilesvoid update_monster_pane() {}#endif
// ----------------------------------------------------------------------// Monster pane// ----------------------------------------------------------------------#ifndef USE_TILE// Monster info used by the pane; precomputes some data// to help with sorting and rendering.class monster_pane_info{public:static bool less_than(const monster_pane_info& m1,const monster_pane_info& m2);monster_pane_info(const monsters* m): m_mon(m){// 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.m_attitude = mons_attitude(m);// Currently, difficulty is defined as "average hp". Leaks too much info?const monsterentry* me = get_monster_data(m->type);m_difficulty = me->hpdice[0] * (me->hpdice[1] + me->hpdice[2]>>1)+ me->hpdice[3];m_brands = 0;if (mons_looks_stabbable(m)) m_brands |= 1;if (mons_looks_distracted(m)) m_brands |= 2;if (m->has_ench(ENCH_BERSERK)) m_brands |= 4;}void to_string(int count, std::string& desc, int& desc_color) const;const monsters* m_mon;mon_attitude_type m_attitude;int m_difficulty;int m_brands;};// Sort monsters by:// attitude// difficulty// type// brandbool // staticmonster_pane_info::less_than(const monster_pane_info& m1,const monster_pane_info& m2){if (m1.m_attitude < m2.m_attitude)return true;else if (m1.m_attitude > m2.m_attitude)return false;// By descending difficultyif (m1.m_difficulty > m2.m_difficulty)return true;else if (m1.m_difficulty < m2.m_difficulty)return false;if (m1.m_mon->type < m2.m_mon->type)return true;else if (m1.m_mon->type > m2.m_mon->type)return false;// By descending brands, so no brands sorts to the endif (m1.m_brands > m2.m_brands)return true;else if (m1.m_brands < m2.m_brands)return false;return false;}voidmonster_pane_info::to_string(int count,std::string& desc,int& desc_color) const{std::ostringstream out;if (count == 1){out << mons_type_name(m_mon->type, DESC_CAP_A);}else{out << count << " "<< pluralise(mons_type_name(m_mon->type, DESC_PLAIN));}#if DEBUG_DIAGNOSTICSout << " av" << m_difficulty << " "<< m_mon->hit_points << "/" << m_mon->max_hit_points;#endifif (m_mon->has_ench(ENCH_BERSERK))out << " (berserk)";else if (mons_looks_stabbable(m_mon))out << " (resting)";else if (mons_looks_distracted(m_mon))out << " (distracted)";else if (m_mon->has_ench(ENCH_INVIS))out << " (invisible)";// Damage (maybe too distracting/verbose?){std::string damage_desc;mon_dam_level_type damage_level;mons_get_damage_level(m_mon, damage_desc, damage_level);if (damage_level != MDAM_OKAY)out << " (" << damage_desc << ")";}// Friendlinessswitch (m_attitude){case ATT_FRIENDLY://out << " (friendly)";desc_color = GREEN;break;case ATT_NEUTRAL://out << " (neutral)";desc_color = BROWN;break;case ATT_HOSTILE:// out << " (hostile)";desc_color = LIGHTGREY;break;}desc = out.str();}static void_print_next_monster_desc(const std::vector<monster_pane_info>& mons, int& start){// skip forward to past the end of the range of identical monstersunsigned int end;for (end=start+1; end < mons.size(); ++end){// Array is sorted, so if !(m1 < m2), m1 and m2 are "equal"if (monster_pane_info::less_than(mons[start], mons[end]))break;}// Postcondition: all monsters in [start, end) are "equal"// Print one of the monsters we've found; shouldn't matter which.{const monster_pane_info& minfo = mons[start]; // arbitraryconst monsters* mon = minfo.m_mon;unsigned int glyph;unsigned short glyph_color;get_mons_glyph(mon, &glyph, &glyph_color);textcolor(glyph_color);cprintf( stringize_glyph(glyph).c_str() );const int count = (end - start);
textcolor(LIGHTGREY);cprintf(" - ");int desc_color;std::string desc;minfo.to_string(count, desc, desc_color);textcolor(desc_color);// "-4" because 4 chars have been printed alreadydesc.resize(crawl_view.mlistsz.x-4, ' ');cprintf("%s", desc.c_str());}// Set start to the next un-described monsterstart = end;textcolor(LIGHTGREY);}void update_monster_pane(){// TODO:// - display rough health (color, or text?)// - fix up issues with the sorting (see monster_pane_info::less_than)const int start_row = 1;const int max_print = crawl_view.mlistsz.y;// Sadly, the defaults don't leave _any_ room for monsters :(if (max_print <= 0)return;std::vector<monster_pane_info> mons;{std::vector<monsters*> visible;get_playervisible_monsters(visible);for (unsigned int i=0; i<visible.size(); i++)mons.push_back(monster_pane_info(visible[i]));}std::sort(mons.begin(), mons.end(), monster_pane_info::less_than);// Print the monsters!std::string blank; blank.resize(crawl_view.mlistsz.x, ' ');for (int i_print = 0, i_mons=0; i_print < max_print; ++i_print){cgotoxy(1, start_row+i_print, GOTO_MLIST);// i_mons is incremented by _print_next_monster_descif (i_mons < (int)mons.size())_print_next_monster_desc(mons, i_mons);elsecprintf("%s", blank.c_str());}}#else// FIXME: implement this for tilesvoid update_monster_pane() {}#endif