they will be displayed in a menu, which the user can select from. Menu entries for monsters will be given the same color as the monster, with the monster's symbol added to the end of the string.
Entering a single character as input to the "?/" describe command lists all monsters with that display symbol.
Monsters sharing the same display symbol can now have the same string appended or prepended to their description (implemented to make the "?/" command have to deal with less special cases). Currently only used by nagas with __N_suffix. Has the side-effect advantage that the naga subspicies description and the "attractive/repulsive" description goes before the big block of quoted text, rather than after it.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2177 c06c8d41-db1a-0410-9941-cceddc491573
VRFQK6S2TXOFFO5K5HRDXPR7QEKKAZAVCASSIJVPWQ4GE26UOGTQC
ZIFFVCQ72K35WGIUMZYN3KOXIUXF2CNXWKG6ZWEZ6LT3NSF3XOQAC
KEYK3CH5J46U6TTOKTWRNMYTZXMQXFVEAZUC4ZQ4QCOSJHVIBDRQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
RSIUBEQUGNU4LO6KH4PKVROWQS33DAKSY4XFVGN7T3CEKSXABCSAC
QDWDUURSNLMT6AXNNJ3DEQCWAKCAIHV6MP5F7QGIBGXOG2BI2NPQC
CRX4RG35C3DH57NIXCW4CG4X7SBMSX7TAJR2BAFQ4LQKCLYUNANQC
Z6XF4AIERIW4U4AR3HU2ILYFZ54IK4K4ORQ6JKCEWRO5LZODWDDAC
X2FMEN4E345XD26Z2X7JMJ7VGHOGCGIELMHQRE2ITLVNQACP3NOQC
Y56C5OMUQ5XF2G6DKDV4R5MED44UOIUPTBBQVWQBUHYIXYA5MOZAC
J6APXOT4QOGQFONWB7G546VTVF6QG42HVOROMHF7YBDJPR4K26OAC
I7QLYOTE6DLQZM7YWUWYLKHRJRB2A3STQ42ALSRGQICEWKD2QTEQC
TFYLN3PQEKFQNOYRVJRCXFJ4J6VSKC7QQFOHNWTDPSVYWAPAJABAC
4RFKVDJKTCRBZU6WPJ2E5OVI5IRPY3UTRPOBLC5QHY4CQJJTLZKQC
M47QBURKKRV2JFK6U7GQNVWK7RUTBVPBJ5FHURC55SKQSXAUFSBAC
NTHQ3RE6DK47HACSWRRVH7QPETSRCLTWMUN2AWKNVWYSV55GFNZAC
LW4N5EHKL776DURXZMAM6JEW3JPWWX5BSNP7TCZHTLCDOQTTGFCAC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
NXVPOFYKJFWQWKVPQUMWH2Y2KJEZX44BUOBFJ4JD4KFGPEGYHG4QC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
JJH7VX2LLBZPDKG24SQREWQLX6I6RYNWFECHRZVK7PT5KPQ4MAMAC
switch (mons.type)
{
case MONS_GUARDIAN_NAGA:
description << getLongDescription("naga")
<< "$These nagas are often used as guardians "
"by powerful creatures.$";
break;
case MONS_GREATER_NAGA:
description << getLongDescription("naga")
<< "$It looks strong and aggressive.$";
break;
case MONS_NAGA_MAGE:
description << getLongDescription("naga")
<< "$An eldritch nimbus trails its motions.$";
break;
case MONS_NAGA_WARRIOR:
description << getLongDescription("naga")
<< "$It bears scars of many past battles.$";
break;
}
matches.push_back(key);
dbKey = dbm_nextkey(database);
}
return (matches);
}
std::vector<std::string> database_find_bodies(DBM *database,
const std::string ®ex,
bool ignore_case)
{
text_pattern tpat(regex, ignore_case);
std::vector<std::string> matches;
datum dbKey = dbm_firstkey(database);
while (dbKey.dptr != NULL)
{
std::string key((const char *)dbKey.dptr, dbKey.dsize);
if (key.find("__") != std::string::npos)
{
dbKey = dbm_nextkey(database);
continue;
}
datum dbBody = dbm_fetch(database, dbKey);
std::string body((const char *)dbBody.dptr, dbBody.dsize);
if (tpat.matches(body))
__N_suffix
$"The insensible son of Pandu sank down till he reached the Naga kingdom.
Nagas, furnished with fangs containing virulent venom, bit him by
thousands. The vegetable poison, mingled in the blood of the son of the
Wind god, was neutralised by the snake-poison. The serpents had bitten
all over his frame, except his chest, the skin of which was so tough that
their fangs could not penetrate it.
"On regaining consciousness, the son of Kunti burst his bands and began
to press the snakes down under the ground. A remnant fled for life, and
going to their king Vasuki, represented, 'O king of snakes, a man drowned
under the water, bound in chords of shrubs; probably he had drunk poison.
For when he fell amongst us, he was insensible. But when we began to bite
him, he regained his senses, and bursting his fetters, commenced laying
at us. May it please Your Majesty to enquire who is.'"
-_The Mahabharata, Sambhava Parva, Section CXXVIII
%%%%
"The insensible son of Pandu sank down till he reached the Naga kingdom.
Nagas, furnished with fangs containing virulent venom, bit him by
thousands. The vegetable poison, mingled in the blood of the son of the
Wind god, was neutralised by the snake-poison. The serpents had bitten
all over his frame, except his chest, the skin of which was so tough that
their fangs could not penetrate it.
"On regaining consciousness, the son of Kunti burst his bands and began
to press the snakes down under the ground. A remnant fled for life, and
going to their king Vasuki, represented, 'O king of snakes, a man drowned
under the water, bound in chords of shrubs; probably he had drunk poison.
For when he fell amongst us, he was insensible. But when we began to bite
him, he regained his senses, and bursting his fetters, commenced laying
at us. May it please Your Majesty to enquire who is.'"
-_The Mahabharata, Sambhava Parva, Section CXXVIII
An eldritch nimbus trails its motions.
%%%%
naga warrior
A hybrid; human from the chest up, with a scaly, muscular torso trailing off like that of a snake.
It bears scars of many past battles.
static void find_description()
desc_menu.set_highlighter(NULL);
for (unsigned int i = 0, size = keys.size(); i < size; i++)
{
const char letter = index_to_letter(i);
std::string str = uppercase_first(keys[i]);
MenuEntry *me = new MenuEntry(uppercase_first(keys[i]),
MEL_ITEM, 1, letter);
monster_type mon = get_monster_by_name(str, true);
if (mon < NUM_MONSTERS && mon != MONS_PROGRAM_BUG)
{
monsterentry *mon_en = get_monster_data(mon);
me->colour = mon_en->colour;
if (me->colour == BLACK)
me->colour = LIGHTGREY;
str += " ('";
str += (char) mon_en->showchar;
str += "')";
me->text = str;
}
me->data = (void*) &keys[i];
desc_menu.add_entry(me);
}
std::vector<MenuEntry*> sel = desc_menu.show();
redraw_screen();
if ( sel.empty() )
{
list_commands_err = "Okay, then.";
return ("");
}
else
{
ASSERT(sel.size() == 1);
ASSERT(sel[0]->hotkeys.size() == 1);
return *((std::string*) sel[0]->data);
}
}
static std::string find_description_key(std::string regex)
{
std::vector<std::string> key_matches = getLongDescKeysByRegex(regex);
if (key_matches.size() == 1)
return (key_matches[0]);
else if (key_matches.size() > 52)
{
list_commands_err = "Too many matches for '";
list_commands_err += regex + "'";
return ("");
}
std::vector<std::string> body_matches = getLongDescBodiesByRegex(regex);
if (key_matches.size() == 0 && body_matches.size() == 0)
{
list_commands_err = "No matches for '";
list_commands_err += regex + "'";
return ("");
}
else if (key_matches.size() == 0 && body_matches.size() == 1)
return (body_matches[0]);
// Merge key_matches and body_matches, discarding duplicates.
std::vector<std::string> tmp = key_matches;
tmp.insert(tmp.end(), body_matches.begin(), body_matches.end());
std::sort(tmp.begin(), tmp.end());
std::vector<std::string> all_matches;
for (unsigned int i = 0, size = tmp.size(); i < size; i++)
if (i == 0 || all_matches[all_matches.size() - 1] != tmp[i])
{
all_matches.push_back(tmp[i]);
}
if (all_matches.size() > 52)
{
list_commands_err = "Too many matches for '";
list_commands_err += regex + "'";
return ("");
}
return select_desc_key(all_matches);
}
static std::string find_monster_key(unsigned char showchar)
{
std::vector<std::string> mon_keys;
for (int i = 0; i < NUM_MONSTERS; i++)
{
if (i == MONS_PROGRAM_BUG)
continue;
monsterentry *me = get_monster_data(i);
if (me == NULL || me->name == NULL || me->name[0] == '\0')
continue;
if (me->mc != i)
continue;
if (getLongDescription(me->name) == "")
continue;
if (me->showchar == showchar)
mon_keys.push_back(me->name);
}
if (mon_keys.size() == 0)
{
list_commands_err = "No monsters displayed with symbol '";
list_commands_err += showchar;
list_commands_err += "'";
return ("");
}
else if (mon_keys.size() > 52)
{
list_commands_err = "Too many monsters for symbol '";
list_commands_err += showchar;
list_commands_err += "'";
return ("");
}
std::sort(mon_keys.begin(), mon_keys.end());
return select_desc_key(mon_keys);
}
static bool find_description()
// Use mpr_comma_separated_list() because the list
// might be *LONG*.
mpr_comma_separated_list(prefix, matches, " and ", ", ",
MSGCH_PLAIN);
return;
}
else
desc = getLongDescription(key);
}
else if (desc == "")
{
// Try to get an exact match first.
key = regex;
desc = getLongDescription(key);
key = find_description_key(regex);
if (key == "")
return (false);
desc = getLongDescription(key);
}
monster_type mon_num = get_monster_by_name(key, true);
if (mon_num < NUM_MONSTERS && mon_num != MONS_PROGRAM_BUG)
{
if (mons_genus(mon_num) == MONS_DRACONIAN)
// Only one match, use that.
key = matches[0];
desc = getLongDescription(key);
monsters mon;
mon.type = mon_num;
switch (mon_num)
{
case MONS_BLACK_DRACONIAN:
case MONS_MOTTLED_DRACONIAN:
case MONS_YELLOW_DRACONIAN:
case MONS_GREEN_DRACONIAN:
case MONS_PURPLE_DRACONIAN:
case MONS_RED_DRACONIAN:
case MONS_WHITE_DRACONIAN:
case MONS_PALE_DRACONIAN:
mon.number = mon_num;
break;
default:
mon.number = 0;
break;
}
describe_monsters(mon);
return (false);
unsigned char symbol = get_monster_data(mon_num)->showchar;
std::string symbol_prefix = "__";
symbol_prefix += symbol;
symbol_prefix += "_prefix";
desc = getLongDescription(symbol_prefix) + desc;
std::string symbol_suffix = "__";
symbol_suffix += symbol;
symbol_suffix += "_suffix";
desc += getLongDescription(symbol_suffix);