I've updated the patch to the current mlist code, but there are still a couple of bugs that will need to be ironed out. For example, monsters are picked by comparing their attitude and type, which is not sufficient in the case of (non-collapsed) zombies, as well as mimics or ghosts. Also if the number of monsters in the visible list is greater than its rows (because some appear in the same row) then monsters outside of the visible list can be targetted. I guess this is an unintended feature. :) I'm certain there'll be more bugs, though.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@6129 c06c8d41-db1a-0410-9941-cceddc491573
SKWBAGSAB625IIN4UP3NCPRX2H3KCPC2LULHS2A7JVRLO3EUBJDAC 5UOH5KYJW6OO5GYRNLLHSQF3UU4JBGJ32K6ZUFBRLVVVP43XJ4LQC C3C6VLGVL7RLM53TCSL7ZWUTVV45MMZXCDL75BEAI4RIO43W6J7AC PYZVEUF25HRJ6FFJH4HEQHUROLBJEYLOSTBKORAGQ5BEZ7DCKYDQC GZGHMS7PHX5HPU66QXVWDELSIVA76PLB4OF734KSPKL3SETFIIOQC HAM54HXIO2245W6REO4RZDY2QMIH476AWWJSMYAMSYYNEBBJSHWAC FEKRY3DYIDLWVBLAZN7W2WFNEKZPCAHABXOSM6K5RLTH5WY2NODQC FWVE7KM7BGEZUFQVM7H7UFGM3QMMPT7QHLNXSP62HG3SMBIPZBSQC 25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC NY5JJY33IHF5EKTLPDFVYTN3PFNKV4A3MAH5MRQ3AWH53L2HFIQQC QSRRV725GCNDOMIDS36NYAA65MOLDMAZSENVSZ3PNOLBFSGHH7BQC JR2RAQ523LOWNDYJNK6AZVKI6WVMI622PIV72XWOVZYPXPUKSQWAC NO2HRD7RZS42S55UG4FQ5EFQDY6WYWKGIXHUKYLWF36HHE3VZ7WAC QV3SYOLTVIFCTWMVKJNJAUGJPCYSGXJOE64242YB2KV74Q46QB7QC F2YWDQUXULLS2WKLVMNEJKEGSGG2MPEREVI2RKH7ROS2YYKKMXHAC HT2Z5ZWY5G2QVHXCKFDQT62FRNGPRRD3HHJ2UULBWRTMAJICUDGAC LDBTCT5WIPLJPZWXS2RUQ26QKISCUUTLO77M464WOE6VSYSNPKYAC ZB77QXJUJWBFNVMJTAEHJNIILHJD4LIE5DVBEVXOEZ2RYT6I7DRAC APWL24FMDRVA6NXFFCGNP3Z3FJJ6WFSRWO4ESHEOVT7Z5JGXPUQQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC FBK5ECMQ6HJSQSN7C3DICKJIRJ3CSO3CHCQ3ONPBKLLSHDGPBQ7QC I2B33Z7NZGC33AMDSSK446AZZYWKPHWLAGULVHKKZU4MVB4BNJOAC IXW2IM5ITYDCXDB3ORDDVAR5XUSPVQ3BWLP3Q6TRXNTIKGMZTHXAC VD4KDTGHVKCN35AWREYB4TEOUMCTW7SAUPAMTMF5ABC7VBHVKP4AC FWLLPRIZDBJVQ336TPOLYAFT6WYGAFC52OFIOTRN2YQPFZ3PQVRQC TJRYL3NXPW5IUGEV3YOC7JYWEXCZDBFPLT4AUG4P227WVKVB72ZAC UEI5JAVCMN7Y2SACTEZPZSNFJWOJTC55G24Q6LKQCT4XNDH5ZQIAC FEGNPOJI2SALUA2PVIXIQ2CIXFLSXD7UB7CNUSAAKV4L3POXCRFQC GVCGKTH5IJ4VSQEIN4CRC7ZFVZW26JPIYNCPTO7GY66CSZZEW3ZQC HSRRNAU5UAYC6B6IQWGJPFROMZBTJICPCH6DJVZDHDTAGOQ6IOYAC JM7UAK777RAVDAVLQLEOBRTGNW2B47S5G55XITJXO243IUNZHVYQC JFWC6LBPSC4SE52KE5FCBC2ZVCGLEJ6SJH5UUN5JRJLTNENENIJQC V4DWL5WBO2JCODVS5QQNWXDH4DAYZN3D5V3UDCHM2KKOMADOTEDQC IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC ABLV37FMURRJPEZV2VRKOUYAKEMLI7E6RA4PDAII2EJ5L7WBHKZQC YHSVOROKPYS33Y4RYZRVZTE3G5LXOFX52HEDNLV6HIXOJYNOKH3QC YAAJ6PTN6QUSWE52URI5AENOGD366FIHOIFUOXFUJLVZYE4OG6HQC EOMCPVNQLX3IMLC46EAO67DPBH5KEG2FQTPBLGU62HIRWA3UQ7XQC PI5BATR2SER3RFE76IUGHM2AGXVFOUM3PLU7WC2K2Q2BA5K2E73QC 5K2ANIEXD3CPJM4XNKNPZINP2G4NT7SJBKRN62WNBUKJXFERTILQC RJI2QPQBXWAO73WAWUFUZGPUUKQTCXWHMYIVIADBTS5QYN7IQABAC RVST2QHYJ757ZHK4AUJ5NGPDZ44AD6RVFVXYPKQIBJXZBDNUCHXQC #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, bool zombified = true);monster_pane_info(const monsters* m);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;bool m_fullname;};void get_monster_pane_info(std::vector<monster_pane_info>& mons);
#endif
public:static bool less_than(const monster_pane_info& m1,const monster_pane_info& m2, bool zombified = true);monster_pane_info(const monsters* m): m_mon(m){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;m_fullname = true;}
// 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);
void to_string(int count, std::string& desc, int& desc_color) const;
// 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];
const monsters* m_mon;mon_attitude_type m_attitude;int m_difficulty;int m_brands;bool m_fullname;};
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 get_monster_pane_info(std::vector<monster_pane_info>& mons){std::vector<monsters*> visible;get_playervisible_monsters(visible);for (unsigned int i = 0; i < visible.size(); i++){if (Options.target_zero_exp|| !mons_class_flag( visible[i]->type, M_NO_EXP_GAIN )){mons.push_back(monster_pane_info(visible[i]));}}std::sort(mons.begin(), mons.end(), monster_pane_info::less_than);}
{std::vector<monsters*> visible;get_playervisible_monsters(visible);for (unsigned int i = 0; i < visible.size(); i++){if (Options.target_zero_exp|| !mons_class_flag( visible[i]->type, M_NO_EXP_GAIN )){mons.push_back(monster_pane_info(visible[i]));}}}
get_monster_pane_info(mons);
if ((i_print >= skip_lines) && (i_mons < (int)mons.size()))_print_next_monster_desc(mons, i_mons, zombified);
if (i_print >= skip_lines && i_mons < (int) mons.size()){_print_next_monster_desc(mons, i_mons, zombified,Options.mlist_targetting == MLIST_TARGET_ON ? i_print: -1);}
//---------------------------------------------------------------
//--------------------------------------------------------------#ifndef USE_TILE// XXX: Hack - can't pass mlist entries into _find_mlist().std::vector<monster_pane_info> mlist;static void _fill_monster_list(void){std::vector<monster_pane_info> temp;get_monster_pane_info(temp);// Get the unique entries.mlist.clear();int start = 0, end = 1;while (start < (int) temp.size()){mlist.push_back(temp[start]);for (end = start + 1; end < (int) temp.size(); ++end)if (monster_pane_info::less_than(temp[start], temp[end]))break;start = end;}}#endif
#ifndef USE_TILEif (key_command >= CMD_TARGET_CYCLE_MLIST&& key_command <= CMD_TARGET_CYCLE_MLIST_END){const int idx = key_command - CMD_TARGET_CYCLE_MLIST;if (_find_square_wrapper(moves.tx, moves.ty, monsfind_pos, 1,_find_mlist, needs_path, idx, range,Options.target_wrap)){moves.tx = monsfind_pos[0];moves.ty = monsfind_pos[1];}else if (!skip_iter)flush_input_buffer(FLUSH_ON_FAILURE);}#endif
break;#ifndef USE_TILEcase CMD_TARGET_TOGGLE_MLIST:if (Options.mlist_targetting == MLIST_TARGET_ON)Options.mlist_targetting = MLIST_TARGET_OFF;elseOptions.mlist_targetting = MLIST_TARGET_ON;update_monster_pane();if (Options.mlist_targetting == MLIST_TARGET_ON)_fill_monster_list();
}#ifndef USE_TILEstatic bool _find_mlist( int x, int y, int idx, bool need_path, int range = -1){if ((int) mlist.size() <= idx)return (false);if (!_is_target_in_range(x, y, range) || !in_los(x,y))return (false);const int targ_mon = mgrd[ x ][ y ];if (targ_mon == NON_MONSTER)return (false);int real_idx = 0;for (unsigned int i = 0; i < mlist.size()-1; i++){if (real_idx == idx){real_idx = i;break;}// While the monsters are identical, don't increase real_idx.if (mlist[i].m_mon->type == mlist[i+1].m_mon->type&& mlist[i].m_attitude == mlist[i+1].m_attitude){continue;}real_idx++;}monsters *mon = &menv[targ_mon];const monsters *monl = mlist[real_idx].m_mon;extern mon_attitude_type mons_attitude(const monsters *m);return (mons_attitude(mon) == mlist[idx].m_attitude&& mon->type == monl->type);
switch ( key )
#ifndef USE_TILE// Overrides the movement keys while mlist_targetting is active.if (Options.mlist_targetting == MLIST_TARGET_ON && islower(key))return static_cast<command_type> (CMD_TARGET_CYCLE_MLIST + (key - 'a'));#endifswitch (key)