summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/output.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/output.cc')
-rw-r--r--crawl-ref/source/output.cc205
1 files changed, 185 insertions, 20 deletions
diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc
index 41084a1c79..5fdbcbebe7 100644
--- a/crawl-ref/source/output.cc
+++ b/crawl-ref/source/output.cc
@@ -1012,6 +1012,166 @@ void draw_border(void)
// Monster pane
// ----------------------------------------------------------------------
+static bool _mons_hostile(const monsters *mon)
+{
+ return (!mons_friendly(mon) && !mons_neutral(mon));
+}
+
+static const char* _get_monster_name(const monsters *mon, bool list_a = false)
+{
+ std::string desc = "";
+
+ bool adj = false;
+ if (mons_friendly(mon))
+ {
+ desc += "friendly ";
+ adj = true;
+ }
+ else if (mons_neutral(mon))
+ {
+ desc += "neutral ";
+ adj = true;
+ }
+
+ if (adj && list_a)
+ {
+ desc = (mon->is_named() ? "the " : "a ") + desc;
+ list_a = false;
+ }
+
+ desc += mon->name(list_a ? DESC_NOCAP_A : DESC_PLAIN);
+ if (!(mon->mname).empty())
+ {
+ desc += " (";
+ desc += mons_type_name(mon->type, DESC_PLAIN);
+ desc += ")";
+ }
+
+ return desc.c_str();
+}
+
+// Returns true if the first monster is more aggressive (in terms of
+// hostile/neutral/friendly) than the second, or, if both monsters share the
+// same attitude, if the first monster has a lower type.
+// If monster type and attitude are the same, return false.
+static bool _compare_monsters_attitude( const monsters *m1, const monsters *m2 )
+{
+ if (_mons_hostile(m1) && !_mons_hostile(m2))
+ return (true);
+
+ if (mons_neutral(m1))
+ {
+ if (mons_friendly(m2))
+ return (true);
+ if (_mons_hostile(m2))
+ return (false);
+ }
+
+ if (mons_friendly(m1) && !mons_friendly(m2))
+ return (false);
+
+ // If we get here then monsters have the same attitude.
+ // FIXME: replace with difficulty comparison
+ return (m1->type < m2->type);
+}
+
+static void _get_visible_monsters(std::vector<std::string>& describe)
+{
+ int ystart = you.y_pos - 9, xstart = you.x_pos - 9;
+ int yend = you.y_pos + 9, xend = you.x_pos + 9;
+ if ( xstart < 0 ) xstart = 0;
+ if ( ystart < 0 ) ystart = 0;
+ if ( xend >= GXM ) xend = GXM;
+ if ( yend >= GYM ) yend = GYM;
+
+ std::vector<const monsters*> mons;
+
+ // monster check
+ for (int y = ystart; y < yend; ++y)
+ for (int x = xstart; x < xend; ++x)
+ if (see_grid(x,y))
+ {
+ const unsigned short targ_monst = mgrd[x][y];
+ if (targ_monst != NON_MONSTER)
+ {
+ const monsters *mon = &menv[targ_monst];
+ if (player_monster_visible(mon)
+ && !mons_is_submerged(mon)
+ && !mons_is_mimic(mon->type))
+ {
+ mons.push_back(mon);
+ }
+ }
+ }
+
+ if (mons.empty())
+ return;
+
+ std::sort( mons.begin(), mons.end(), _compare_monsters_attitude );
+
+ int count = 0;
+ int size = mons.size();
+ for (int i = 0; i < size; ++i)
+ {
+ if (i > 0 && _compare_monsters_attitude(mons[i-1], mons[i]))
+ {
+ if (count == 1)
+ describe.push_back(_get_monster_name(mons[i-1], true));
+ else
+ {
+ describe.push_back(number_in_words(count) + " "
+ + pluralise(_get_monster_name(mons[i-1])));
+ }
+ count = 0;
+ }
+ count++;
+ }
+ // handle last monster
+ if (mons.size() == 1
+ || _compare_monsters_attitude(mons[size-2], mons[size-1]))
+ {
+ describe.push_back(_get_monster_name(mons[size-1], true));
+ }
+ else
+ {
+ describe.push_back(number_in_words(count) + " "
+ + pluralise(_get_monster_name(mons[size-1])));
+ }
+}
+
+// If past is true, the messages should be printed in the past tense
+// because they're needed for the morgue dump.
+std::string mpr_monster_list(bool past)
+{
+ std::vector<std::string> describe;
+ _get_visible_monsters(describe);
+
+ std::string msg = "";
+ if (describe.empty())
+ {
+ msg = "There ";
+ msg += (past ? "were" : "are");
+ msg += " no monsters in sight!";
+
+ return (msg);
+ }
+
+ msg = "You ";
+ msg += (past ? "could" : "can");
+ msg += " see ";
+
+ if (describe.size() == 1)
+ msg += describe[0];
+ else
+ {
+ msg += comma_separated_line(describe.begin(), describe.end(),
+ ", and ", ", ");
+ }
+ msg += ".";
+
+ return (msg);
+}
+
#ifndef USE_TILE
// Monster info used by the pane; precomputes some data
@@ -1031,11 +1191,11 @@ class monster_pane_info
// 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];
+ + me->hpdice[3];
m_brands = 0;
- if (mons_looks_stabbable(m)) m_brands |= 1;
- if (mons_looks_distracted(m)) m_brands |= 2;
+ 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;
}
@@ -1083,11 +1243,8 @@ monster_pane_info::less_than(const monster_pane_info& m1,
return false;
}
-void
-monster_pane_info::to_string(
- int count,
- std::string& desc,
- int& desc_color) const
+void monster_pane_info::to_string( int count, std::string& desc,
+ int& desc_color) const
{
std::ostringstream out;
@@ -1327,8 +1484,8 @@ const char *equip_slot_to_name(int equip)
if (equip == EQ_RINGS || equip == EQ_LEFT_RING || equip == EQ_RIGHT_RING)
return "Ring";
- if (equip == EQ_BOOTS &&
- (you.species == SP_CENTAUR || you.species == SP_NAGA))
+ if (equip == EQ_BOOTS
+ && (you.species == SP_CENTAUR || you.species == SP_NAGA))
{
return "Barding";
}
@@ -1821,15 +1978,19 @@ char _get_overview_screen_results()
if (you.intel == you.max_intel)
snprintf(buf, sizeof buf, "Int %2d", you.intel);
else
+ {
snprintf(buf, sizeof buf, "Int <yellow>%2d</yellow> (%d)",
you.intel, you.max_intel);
+ }
cols1.add_formatted(1, buf, false);
if (you.dex == you.max_dex)
snprintf(buf, sizeof buf, "Dex %2d", you.dex);
else
+ {
snprintf(buf, sizeof buf, "Dex <yellow>%2d</yellow> (%d)",
you.dex, you.max_dex);
+ }
cols1.add_formatted(1, buf, false);
snprintf(buf, sizeof buf, "AC %2d" , player_AC());
@@ -1850,9 +2011,9 @@ char _get_overview_screen_results()
char god_colour_tag[20];
god_colour_tag[0] = 0;
std::string godpowers(god_name(you.religion));
- if ( you.religion != GOD_NO_GOD )
+ if (you.religion != GOD_NO_GOD)
{
- if ( player_under_penance() )
+ if (player_under_penance())
strcpy(god_colour_tag, "<red>*");
else
{
@@ -1860,12 +2021,13 @@ char _get_overview_screen_results()
colour_to_str(god_colour(you.religion)));
// piety rankings
int prank = piety_rank() - 1;
- if ( prank < 0 || you.religion == GOD_XOM)
+ if (prank < 0 || you.religion == GOD_XOM)
prank = 0;
+
// Careful about overflow. We erase some of the god's name
// if necessary.
- godpowers = godpowers.substr(0, 29 - prank) + " " +
- std::string(prank, '*');
+ godpowers = godpowers.substr(0, 29 - prank)
+ + " " + std::string(prank, '*');
}
}
@@ -1878,7 +2040,8 @@ char _get_overview_screen_results()
(you.experience_level < 27?
make_stringf(", need: %d", xp_needed).c_str() : ""),
god_colour_tag, godpowers.c_str(),
- you.spell_no, player_spell_levels(), (player_spell_levels() == 1) ? "" : "s");
+ you.spell_no, player_spell_levels(),
+ (player_spell_levels() == 1) ? "" : "s");
cols1.add_formatted(3, buf, false);
{
@@ -1897,9 +2060,9 @@ char _get_overview_screen_results()
const int rpois = player_res_poison(calc_unid);
const int relec = player_res_electricity(calc_unid);
const int rsust = player_sust_abil(calc_unid);
- const int rmuta = wearing_amulet(AMU_RESIST_MUTATION, calc_unid)
- || player_mutation_level(MUT_MUTATION_RESISTANCE) == 3
- || you.religion == GOD_ZIN && you.piety >= 150;
+ const int rmuta = (wearing_amulet(AMU_RESIST_MUTATION, calc_unid)
+ || player_mutation_level(MUT_MUTATION_RESISTANCE) == 3
+ || you.religion == GOD_ZIN && you.piety >= 150);
const int rslow = wearing_amulet(AMU_RESIST_SLOW, calc_unid);
@@ -1964,8 +2127,10 @@ char _get_overview_screen_results()
cols.add_formatted(1, buf, false);
if ( scan_randarts(RAP_PREVENT_TELEPORTATION, calc_unid) )
+ {
snprintf(buf, sizeof buf, "\n%sPrev.Telep.: %s",
_determine_color_string(-1), itosym1(1));
+ }
else
{
const int rrtel = !!player_teleport(calc_unid);
@@ -1993,7 +2158,7 @@ char _get_overview_screen_results()
std::vector<formatted_string> blines = cols.formatted_lines();
for (unsigned int i = 0; i < blines.size(); ++i )
{
- // Kind of a hack -- we don't care really what items these
+ // Kind of a hack -- we don't really care what items these
// hotkeys go to. So just pick the first few.
const char hotkey = (i < equip_chars.size()) ? equip_chars[i] : 0;
overview.add_item_formatted_string(blines[i], hotkey);