From c19b2fdd21ba70ded0b4f42a8c7d018108d2d70d Mon Sep 17 00:00:00 2001 From: dshaligram Date: Wed, 24 Oct 2007 12:42:08 +0000 Subject: [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 --- crawl-ref/source/beam.cc | 15 ++++--- crawl-ref/source/beam.h | 4 +- crawl-ref/source/libutil.cc | 105 ++++++++++++++++++++++++++++++++++++++++++++ crawl-ref/source/libutil.h | 29 ++++++++++++ crawl-ref/source/spells2.cc | 26 +++++++++-- 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 #include #include #include @@ -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 &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 #include #include +#include + +// 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 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(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) { -- cgit v1.2.3-54-g00ecf