Monster names are now stored in the monster struct and saved.
Changed some monster-finding functions to return monsters* instead of monster index for type-safety.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4859 c06c8d41-db1a-0410-9941-cceddc491573
WQLOHSNCA3VOMDJF6IINJYKSYVYZEBPJJWBB33QSNE4RP5HEXPMAC
H7W5Q3C6V33ANX3BSCWSUYPG5XUFDMOCHZ7BZIL7JEWGI74V3LOQC
QL3UTDJCNTASBU67LD5QODTIH7LCSAOW672CLJCDT4HED6PP5OPAC
AM7QPHDAWNXHLUEVUHVRHG2RO2DOIEFFU4GV3DCIROW6O5HW7H4AC
BNAITVINXHVPC6TOL7IEBVJM2AW5WQKEJJQ432WJSWPPG2K52YUQC
SZTNOT2A7U72CTVG64DABG4ZPHOBENTSMRBOIH2MCAWLBWP4RSGQC
5JS3QSE3EIXSBVI4DATH2EIFD7QN3POAFEUM7MK4NRMPH5JOPAAQC
VRI4B3CAG2C3RNICONUZUBS4ZV43HM646APKVYLGAWYMP7V5M65QC
22YVHM74WBJNJE4PA5CBEUTDWM6FAGGGILI26A4LXAURX55TNRKAC
GXXYPBFEWKRZQ6OBGYNS2EXZN52NGNV3UU3WM6S5R74CMJBAKGTAC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
G5UQZMFTP25NABFYCATJ7URTOPQ2XEAOKXOCOQXSMDS3JM3WMVVQC
IOMAHHDYJ6P65ZZK4Q44YX2PEBZWBPB7ZOA3OKXPUBI5BRLRQ5JAC
NMZFCCM6O3KO2GJWKOSULN27B3QIZKWPBOB62PAILXMRQD4JMIMAC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
5UVDIVD4NSXA52U4QMQIVST3GSZJ2A2YZK3RUEXKPM43YVQ7LI5AC
LDBTCT5WIPLJPZWXS2RUQ26QKISCUUTLO77M464WOE6VSYSNPKYAC
7KWDC7XFNMBLSUO2HISIROBINZBX5T67LJEEXTAORXW2YZ7VWFGAC
NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC
X7TRUBJTRDVUI53BROBYHF4UDC4I5SUYWBUOGQMZNN2WEZAFVGVQC
62CWUC7WKYRODVOOUFHRPDZXGTBUIU7XPR3EHJWESPG2XVUM7SDAC
2TFYJ7D72JY4DYQW3GSPEONA2WYIVHAJXTIQ2QRDIWF65XN2QFGAC
6TEISZD7HYSSL24EOKIBNURU66KGSQX7B7SNAHBP4DQSAOTGH2MQC
O6EVISSX36HYR7FNQ74LAJIFTUGZ3SAHPW2YC3AHMW4CRBQRNLSAC
IDXDKKTEX3UNLT4GUOWZAWPCMGYFDAHPRUS5FM4FFHFQD6HG7BCAC
6PP4GO7DFTZ26H564BRDMMYRANI7QISGOB3MDTVUMOX6STWFONLQC
INWKDE6QMV7PUWMZ65IZTUF4WB2G2OR2Q2NPTNID4Y3NVD7JWN3AC
M2EUGZPKR6XTZSLQYDO7CDBBR2WPPMCBIBKJSZW5P7KYUOUPZSZQC
N6AB4D7CBK3YG43GL5MZIHKGYXSQWQ3MRKXGEX3QAADLGNDIKL7AC
POP6UTTHSJGDU5NU7ENQJOZVFUHYM63HJ6HLPXDDLK7XFIP4XEIQC
OVYC2AOOLEVUE4SSF65W46J4QLLZKRXB4DQY7F6S767XJLPQUU6AC
YYIBXE7VFJTRT73QDNFL3MQ3LP3OK4KML5YMEMRKQUQZJVAWORWAC
I2PL54BONLM4RYG4OE7M2UEWDYXPVB4SYGTXZM3OPQPAQCG3VLTQC
PCZU6R5IXBVWZ3TALJJNEBBLWSAVQGFFIMRTILFSCEP76ZD4OLQAC
L5KQH3FHNYTFE4D2L3ZGWCBCMW3PAR7EHD5555GSKJGVK7HQWPXAC
P2OYYNPHIBGOLT4CRLNTTIXDN34EU2QCMFQJNLAMUAHQXZTEDPXQC
AZ2RCXNVULJUSCBDBK3VARTUCTPEJXHTA7ALP73S4EXLJB6YYB5QC
VEPHAIXR3GSPHBLOW5DWFFU4ULEMVWRQG4G5PKSKRA2I6RHYROUAC
47NSOFQMBZCDIBHEAZSENFUGDSQCX3GJHFBUZ65ARDKCYIZ435LAC
E2LCSPRMB2Y5ZYYRIM46I426ZUJ6ZLV6BQO7SDRGCTFVVAWVSSXQC
PRAEZIJQO6PNMV5XLOGPEHJNAFS2WL6F6NHI5APDNWVBSNKTMX4AC
KPAWRUS24XJH5H5Q5YC26JTRHBDV6QOJ53UP7B7BKIEK6JM2EPUAC
6DV6Q7PO6RHI4JMADPHUDUROLA7LCEMSLCRSFFHXNKMGIAG7ZNAAC
T7WNH6S3VICGMHV7MJ6RHR2YKH75TLMZBOF7SDSE6TOHTIJNT63QC
XWPDPZ3OIMZBDV4BA6UYRBQNAPG7AFI52HZZUKX25XOK3NEDLG4AC
XAKHV2E3U5KQ5LV77HI7XFKNCKGYXT2LPBOHZP2VOH4Y67QBH4SQC
K27R6ZMYMKVNXIV7K3QU2NXRVOGQRLMR6TI6ZQQSVKXVKS76NLSQC
ZJXN47ARPBCZQBWEMEMQ5Q4IY2M233RPLKXWCP7EZQ53FWYWS5LAC
GRWDBVQM7X6QS7EW5PU5WQNOMR46H5ITKU57J3ZVJPIL3ILXIYPAC
6U5OXFVONPHTWJWWS77QGTRIONYKYWMUWNWJ4WHMI2ISSOWZJETQC
MAVCYXGLWJHJ53DKGEIG7JLXZUFOBMUDF3BIGRU772QTMRJT7CSAC
RHV7P556KYXDQ6QYGSRLOZBRKLMKWHHKLRQTP2WBMUZYMIAG7OBQC
UPNIIOG2FHJ4WFGGPZBFYK3GYONL3Z5LO4FEYRJPE7WHNI5R7UZQC
NDCVITU5R7TBEUC4FILNFRKWQGUNCJUGW5HA5KW3CQTU6AYRLYWQC
NUYXKJP5YXHRDUQW5QW7UC3D5U3VPANIOZAOHFCPWMSRYGMA3GCAC
X5WLJCJVW55SXZVP7IKP7ADCJIGNKN4PKAXFECVR6TNK7XSMZR7QC
OSGS3PH2L5CBTDVZCZS6OCFQNA4A7RMEXBYJQB7DDZBYYJW7QSSAC
PMCHUVWMCDXOWGXB4SWMBXFGHJYZG7KZ34SE33HFUGHPQYP3LYEAC
F7QFSXE22UPQTBLYJLY26HJ3QPHFNBJMUOFJRV35R5YCHSGKTBYQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
E5DMZFW6WCFAKTKKOQPYTQXZ2CGLWMVH64LRXDUI2UIG4VYUHIVQC
QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC
7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC
R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC
RSIUBEQUGNU4LO6KH4PKVROWQS33DAKSY4XFVGN7T3CEKSXABCSAC
UWI3ZNJDRQRL7CXFNFEG46TA6SAK24XUFY5YOKVOTJA3VG3OBNFAC
W5VEC2PBIM5DMU5233HOWAZUEPTGWJRZZIA3H35YYQQW6BTP6XUAC
TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC
22MF6OUN62WDBJR5QFNJTKU7Q5TIQ76XWCEIRBFWAZDMZUSKJGCAC
J6APXOT4QOGQFONWB7G546VTVF6QG42HVOROMHF7YBDJPR4K26OAC
5UC5TI7B6NWGIGN74QRBZKDBYUMHLM2ZO5ATXEZ6TZOGOLF3JX5QC
X4OCLD5YEXCYVQNMOQORLIO72AKUEMT3BT6FB3TW2HARKN5X7MEQC
NWJ5IHZJXYE4I7CKSDNMTLGTIKOWK42LC2UYZL2TLXSZLM67WKRAC
TVC7W7C2XKBQSD2IJFMWFVGXZAOD4EUOW43NAQTOF5KFMAUOJABQC
JP7SVXCIKEPVDD4Q5CDYDATPK7X5XOYW3T6QK2Y6EWHFH52LBK3QC
KHHAE5ZK7ITEZVMMUKYROKECLE2RU5ZU5OQ4Z4XSRQXE2R65O67AC
whom = get_unique_monster_name(mon);
if (whom.empty())
whom = "your " + mon->name(DESC_PLAIN);
if (follower->is_named())
whom = follower->name(DESC_PLAIN);
else
whom = "your " + follower->name(DESC_PLAIN);
int choose_random_nearby_monster(int weight,
bool (*suitable)(const monsters* mon) =
choose_any_monster,
bool in_sight = true,
bool prefer_named = false);
monsters *choose_random_nearby_monster(
int weight,
bool (*suitable)(const monsters* mon) =
choose_any_monster,
bool in_sight = true,
bool prefer_named = false);
int choose_random_monster_on_level(int weight,
bool (*suitable)(const monsters* mon) =
choose_any_monster,
bool in_sight = true, bool near_by = false,
bool prefer_named = false);
monsters *choose_random_monster_on_level(
int weight,
bool (*suitable)(const monsters* mon) =
choose_any_monster,
bool in_sight = true, bool near_by = false,
bool prefer_named = false);
int choose_random_nearby_monster(int weight,
bool (*suitable)(const monsters* mon),
bool in_sight, bool prefer_named)
monsters *choose_random_nearby_monster(int weight,
bool (*suitable)(const monsters* mon),
bool in_sight, bool prefer_named)
int choose_random_monster_on_level(int weight,
bool (*suitable)(const monsters* mon),
bool in_sight, bool near_by,
bool prefer_named)
monsters *choose_random_monster_on_level(int weight,
bool (*suitable)(const monsters* mon),
bool in_sight, bool near_by,
bool prefer_named)
if (prefer_named
&& !(get_unique_monster_name(&menv[mon]).empty()))
// FIXME: if the intent is to favour monsters
// named by $DEITY, we should set a flag on the
// monster (something like MF_DEITY_PREFERRED) and
// use that instead of checking the name, given
// that other monsters can also have names.
if (prefer_named && mon->is_named())
menv[id].inv.init(NON_ITEM);
// scrap monster enchantments
menv[id].enchantments.clear();
menv[id].ench_countdown = 0;
menv[id].reset();
}
// XXX: unique as in "proper name", not unique as in "name not used elsewhere"?
static std::string _get_unique_monster_name(const monsters *mon)
{
const monsterentry *me = mon->find_monsterentry();
if (!me)
return ("");
std::string name = getRandNameString(me->name, " name");
if (!name.empty())
return name;
name = getRandNameString(get_monster_data(mons_genus(mon->type))->name,
" name");
if (!name.empty())
return name;
name = getRandNameString("generic_monster_name");
return name;
{
return false;
}
}
else
{
// need their number parameter for other information
if (mon->type == MONS_HYDRA // #heads
|| mon->type == MONS_ABOMINATION_SMALL // colour
|| mon->type == MONS_ABOMINATION_LARGE // colour
|| mon->type == MONS_MANTICORE // #spikes
|| mons_genus(mon->type) == MONS_DRACONIAN // subspecies
|| mons_class_is_zombified(mon->type)) // zombie type
}
// randomly pick a number
// XXX: Why does unsigned int (number's type) get munged on save & reload?
mon->number = (unsigned char) random_int();
// mprf(MSGCH_DIAGNOSTICS, "new monster number is %d", mon->number);
return (mon->number != 0 && mon->number != MONS_PROGRAM_BUG);
}
std::string get_unique_monster_name(const monsters *mon)
{
if (mon->type == MONS_PLAYER_GHOST)
return mon->ghost->name + "'s ghost";
if (mon->type == MONS_PANDEMONIUM_DEMON)
return mon->ghost->name;
if (mons_is_unique(mon->type))
return get_monster_data(mon->type)->name;
// Since the seed for the monster name is stored in mon->number
// any monster that uses number for something else cannot be named.
if (mon->type == MONS_HYDRA // #heads
|| mon->type == MONS_ABOMINATION_SMALL // colour
|| mon->type == MONS_ABOMINATION_LARGE // colour
|| mon->type == MONS_MANTICORE // #spikes
|| mons_genus(mon->type) == MONS_DRACONIAN // subspecies
|| mons_class_is_zombified(mon->type)) // zombie type
{
return "";
// unnamed, sorry
if (mon->number <= 0 || mon->number == MONS_PROGRAM_BUG)
return "";
// mprf(MSGCH_DIAGNOSTICS, "get name from number %d", mon->number);
rng_save_excursion rng_state;
seed_rng( mon->number );
std::string name
= getRandNameString(get_monster_data(mon->type)->name, " name");
if (!name.empty())
return name;
}
void monsters::reset()
{
destroy_inventory();
mname.clear();
enchantments.clear();
ench_countdown = 0;
inv.init(NON_ITEM);
flags = 0;
experience = 0L;
type = -1;
hit_points = 0;
max_hit_points = 0;
hit_dice = 0;
ac = 0;
ev = 0;
speed_increment = 0;
attitude = ATT_HOSTILE;
behaviour = BEH_SLEEP;
foe = MHITNOT;
number = 0;
if (in_bounds(x, y))
mgrd[x][y] = NON_MONSTER;
x = y = 0;
ghost.reset(NULL);
std::string mname = _str_monam(*this, desc, force_vis);
return (possessive? apostrophise(mname) : mname);
std::string monnam = _str_monam(*this, desc, force_vis);
return (possessive? apostrophise(monnam) : monnam);
}
void monsters::reset()
{
destroy_inventory();
enchantments.clear();
ench_countdown = 0;
inv.init(NON_ITEM);
flags = 0;
experience = 0L;
type = -1;
hit_points = 0;
max_hit_points = 0;
hit_dice = 0;
ac = 0;
ev = 0;
speed_increment = 0;
attitude = ATT_HOSTILE;
behaviour = BEH_SLEEP;
foe = MHITNOT;
number = 0;
if (in_bounds(x, y))
mgrd[x][y] = NON_MONSTER;
x = y = 0;
ghost.reset(NULL);