summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-10-24 12:42:08 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-10-24 12:42:08 +0000
commitc19b2fdd21ba70ded0b4f42a8c7d018108d2d70d (patch)
tree4b4c96386291048dbb254a73cf7a5d80c604b0e7
parent873dd0bfae9f9f78b3e978edb574e4793af7b03f (diff)
downloadcrawl-ref-c19b2fdd21ba70ded0b4f42a8c7d018108d2d70d.tar.gz
crawl-ref-c19b2fdd21ba70ded0b4f42a8c7d018108d2d70d.zip
[1818799] Reduce message spam from Olgreb's toxic radiance.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2535 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/beam.cc15
-rw-r--r--crawl-ref/source/beam.h4
-rw-r--r--crawl-ref/source/libutil.cc105
-rw-r--r--crawl-ref/source/libutil.h29
-rw-r--r--crawl-ref/source/spells2.cc26
5 files changed, 167 insertions, 12 deletions
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 08779d1c69..aad4afc6af 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -2116,16 +2116,17 @@ bool curare_hits_monster( const bolt &beam,
}
// actually poisons a monster (w/ message)
-void poison_monster( monsters *monster,
+bool poison_monster( monsters *monster,
kill_category from_whom,
int levels,
- bool force )
+ bool force,
+ bool verbose)
{
if (!monster->alive())
- return;
+ return (false);
if (!force && mons_res_poison(monster) > 0)
- return;
+ return (false);
const mon_enchant old_pois = monster->get_ench(ENCH_POISON);
monster->add_ench( mon_enchant(ENCH_POISON, levels, from_whom) );
@@ -2133,7 +2134,7 @@ void poison_monster( monsters *monster,
// actually do the poisoning
// note: order important here
- if (new_pois.degree > old_pois.degree)
+ if (new_pois.degree > old_pois.degree && verbose)
{
simple_monster_message( monster,
!old_pois.degree? " is poisoned."
@@ -2143,7 +2144,9 @@ void poison_monster( monsters *monster,
// finally, take care of deity preferences
if (from_whom == KC_YOU)
did_god_conduct( DID_POISON, 5 + random2(3) );
-} // end poison_monster()
+
+ return (new_pois.degree > old_pois.degree);
+}
// actually napalms a monster (w/ message)
void sticky_flame_monster( int mn, kill_category who, int levels )
diff --git a/crawl-ref/source/beam.h b/crawl-ref/source/beam.h
index 4c61cb5b88..78b3eaf484 100644
--- a/crawl-ref/source/beam.h
+++ b/crawl-ref/source/beam.h
@@ -238,8 +238,8 @@ int mons_ench_f2( struct monsters *monster, struct bolt &pbolt );
/* ***********************************************************************
* called from: fight - monstuff - spells2
* *********************************************************************** */
-void poison_monster( struct monsters *monster, kill_category who,
- int levels = 1, bool force = false );
+bool poison_monster( monsters *monster, kill_category who,
+ int levels = 1, bool force = false, bool verbose = true );
/* ***********************************************************************
diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc
index 586de1db77..ed0b640680 100644
--- a/crawl-ref/source/libutil.cc
+++ b/crawl-ref/source/libutil.cc
@@ -18,6 +18,7 @@
#include "externs.h"
#include "macro.h"
#include "stuff.h"
+#include <sstream>
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
@@ -75,6 +76,39 @@ description_level_type description_type_by_name(const char *desc)
return DESC_PLAIN;
}
+std::string number_to_string(unsigned number, bool in_words)
+{
+ return (in_words? number_in_words(number) : make_stringf("%u", number));
+}
+
+std::string apply_description(description_level_type desc,
+ const std::string &name,
+ int quantity, bool in_words)
+{
+ switch (desc)
+ {
+ case DESC_CAP_THE:
+ return ("The " + name);
+ case DESC_NOCAP_THE:
+ return ("the " + name);
+ case DESC_CAP_A:
+ return (quantity > 1?
+ number_to_string(quantity, in_words) + name
+ : article_a(name, false));
+ case DESC_NOCAP_A:
+ return (quantity > 1?
+ number_to_string(quantity, in_words) + name
+ : article_a(name, true));
+ case DESC_CAP_YOUR:
+ return ("Your " + name);
+ case DESC_NOCAP_YOUR:
+ return ("your " + name);
+ case DESC_PLAIN:
+ default:
+ return (name);
+ }
+}
+
// Should return true if the filename contains nothing that
// the shell can do damage with.
bool shell_safe(const char *file)
@@ -527,6 +561,77 @@ int snprintf( char *str, size_t size, const char *format, ... )
#endif
+//////////////////////////////////////////////////////////////////////////
+// named_thing_collection
+
+named_thing_collection::named_thing_collection()
+ : names(), nnames(0u)
+{
+}
+
+void named_thing_collection::add_thing(const std::string &name)
+{
+ names[name]++;
+ nnames++;
+}
+
+size_t named_thing_collection::size() const
+{
+ return (nnames);
+}
+
+bool named_thing_collection::empty() const
+{
+ return (!nnames);
+}
+
+std::string named_thing_collection::describe(
+ description_level_type desc,
+ const char **plural_qualifiers,
+ const char **no_qualifier_suffixes) const
+{
+ if (empty())
+ return ("");
+
+ std::ostringstream out;
+ for (name_count_map::const_iterator i = names.begin();
+ i != names.end(); )
+ {
+ const std::pair<std::string, int> &curr(*i);
+ if (i != names.begin())
+ {
+ ++i;
+ out << (i == names.end()? " and " : ", ");
+ }
+ else
+ ++i;
+
+ const std::string name =
+ curr.second > 1? pluralise(curr.first, plural_qualifiers,
+ no_qualifier_suffixes)
+ : curr.first;
+ out << apply_description(desc, name, curr.second);
+
+ switch (desc)
+ {
+ case DESC_CAP_A:
+ desc = DESC_NOCAP_A;
+ break;
+ case DESC_CAP_THE:
+ desc = DESC_NOCAP_THE;
+ break;
+ case DESC_CAP_YOUR: case DESC_NOCAP_YOUR:
+ desc = DESC_PLAIN;
+ break;
+ default:
+ break;
+ }
+ }
+ return (out.str());
+}
+
+/////////////////////////////////////////////////////////////////////////
+
///////////////////////////////////////////////////////////////////////
// Pattern matching
diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h
index 751baef885..42102991a4 100644
--- a/crawl-ref/source/libutil.h
+++ b/crawl-ref/source/libutil.h
@@ -19,9 +19,37 @@
#include <cctype>
#include <string>
#include <vector>
+#include <map>
+
+// A collection of named things that can be stacked. The collection merges
+// things that should be merged (by name) and outputs a comma-separated list
+// with the preferred description type.
+class named_thing_collection
+{
+public:
+ named_thing_collection();
+ void add_thing(const std::string &name);
+ std::string describe(description_level_type desc,
+ const char **plural_qualifiers = NULL,
+ const char **no_qualifier_suffix = NULL) const;
+ size_t size() const;
+ bool empty() const;
+private:
+ typedef std::map<std::string, int> name_count_map;
+ name_count_map names;
+ size_t nnames;
+};
extern const char *standard_plural_qualifiers[];
+// Applies a description type to a name, but does not pluralise! You
+// must pluralise the name if needed. The quantity is used to prefix the
+// name with a quantity if appropriate.
+std::string apply_description(description_level_type desc,
+ const std::string &name,
+ int quantity = 1,
+ bool num_in_words = false);
+
description_level_type description_type_by_name(const char *desc);
std::string lowercase_string(std::string s);
@@ -42,6 +70,7 @@ std::string pluralise(
const char *no_of[] = NULL);
std::string number_in_words(unsigned number, int pow = 0);
+std::string number_to_string(unsigned number, bool in_words = false);
bool shell_safe(const char *file);
diff --git a/crawl-ref/source/spells2.cc b/crawl-ref/source/spells2.cc
index a03676bdc2..b43476a608 100644
--- a/crawl-ref/source/spells2.cc
+++ b/crawl-ref/source/spells2.cc
@@ -834,6 +834,7 @@ void cast_toxic_radiance(void)
poison_player(2);
}
+ named_thing_collection affected_monsters;
// determine which monsters are hit by the radiance: {dlb}
for (int toxy = 0; toxy < MAX_MONSTERS; toxy++)
{
@@ -846,11 +847,14 @@ void cast_toxic_radiance(void)
// this check should not be !monster->invisible().
if (!monster->has_ench(ENCH_INVIS))
{
- poison_monster(monster, KC_YOU);
+ bool affected =
+ poison_monster(monster, KC_YOU, 1, false, false);
- if (coinflip()) // 50-50 chance for a "double hit" {dlb}
- poison_monster(monster, KC_YOU);
+ if (coinflip() && poison_monster(monster, KC_YOU, false, false))
+ affected = true;
+ if (affected)
+ affected_monsters.add_thing(monster->name(DESC_PLAIN));
}
else if (player_see_invis())
{
@@ -860,7 +864,21 @@ void cast_toxic_radiance(void)
}
}
}
-} // end cast_toxic_radiance()
+
+ if (!affected_monsters.empty())
+ {
+ const std::string message =
+ make_stringf("%s %s poisoned.",
+ affected_monsters.describe(DESC_CAP_THE).c_str(),
+ affected_monsters.size() == 1? "is" : "are");
+ if (static_cast<int>(message.length()) < get_number_of_cols() - 2)
+ mpr(message.c_str());
+ else
+ // Exclamation mark to suggest that a lot of creatures were
+ // affected.
+ mpr("The monsters around you are poisoned!");
+ }
+}
void cast_refrigeration(int pow)
{