summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2006-09-06 08:53:23 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2006-09-06 08:53:23 +0000
commitab63ef558038d212bca62752d16d584df8a33477 (patch)
tree285dcd9be1d06e662fa01fa55119278f1b8a7675
parent1f5bd141dba6f05deb350f79eceef75cb68276bf (diff)
downloadcrawl-ref-ab63ef558038d212bca62752d16d584df8a33477.tar.gz
crawl-ref-ab63ef558038d212bca62752d16d584df8a33477.zip
r90@xenon: dshaligram | 2006-09-06 14:24:41 +051800
Instrumented Crawl to dump detailed damage numbers for any given weapon to facilitate retuning weapon damage calculations. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/branches/stone_soup@34 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/acr.cc4
-rw-r--r--crawl-ref/source/beam.cc3
-rw-r--r--crawl-ref/source/beam.h2
-rw-r--r--crawl-ref/source/debug.cc316
-rw-r--r--crawl-ref/source/debug.h1
-rw-r--r--crawl-ref/source/externs.h6
-rw-r--r--crawl-ref/source/fight.cc15
-rw-r--r--crawl-ref/source/fight.h2
-rw-r--r--crawl-ref/source/initfile.cc33
-rw-r--r--crawl-ref/source/item_use.cc38
-rw-r--r--crawl-ref/source/item_use.h3
-rw-r--r--crawl-ref/source/message.cc15
-rw-r--r--crawl-ref/source/message.h9
13 files changed, 412 insertions, 35 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 669b72315a..b94e55a2c0 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -580,6 +580,10 @@ static void handle_wizard_command( void )
tweak_object();
break;
+ case 'F':
+ debug_fight_statistics();
+ break;
+
case 'm':
create_spec_monster();
break;
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index ebb4cf0201..e223347e3d 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -71,7 +71,6 @@ static FixedArray < bool, 19, 19 > explode_map;
// be public):
static void sticky_flame_monster( int mn, bool source, int hurt_final );
static bool affectsWalls(struct bolt &beam);
-static int affect(struct bolt &beam, int x, int y);
static bool isBouncy(struct bolt &beam);
static void beam_drop_object( struct bolt &beam, item_def *item, int x, int y );
static bool beam_term_on_target(struct bolt &beam);
@@ -2684,7 +2683,7 @@ static bool fuzzyLine(int nx, int ny, int &tx, int &ty, int lx, int ly,
// 4. if cell holds monster, affect monster affect_monster()
// 5. return range used affectation.
-static int affect(struct bolt &beam, int x, int y)
+int affect(struct bolt &beam, int x, int y)
{
// extra range used by hitting something
int rangeUsed = 0;
diff --git a/crawl-ref/source/beam.h b/crawl-ref/source/beam.h
index 503220db44..d081332bb6 100644
--- a/crawl-ref/source/beam.h
+++ b/crawl-ref/source/beam.h
@@ -92,4 +92,6 @@ void mimic_alert( struct monsters *mimic );
void zapping( char ztype, int power, struct bolt &pbolt );
+int affect(struct bolt &beam, int x, int y);
+
#endif
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index 83b910d236..591cf7ab38 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -29,9 +29,11 @@
#include "direct.h"
#include "dungeon.h"
+#include "fight.h"
#include "invent.h"
#include "itemname.h"
#include "itemprop.h"
+#include "item_use.h"
#include "items.h"
#include "misc.h"
#include "monplace.h"
@@ -393,30 +395,24 @@ void TRACE(const char *format, ...)
//
//---------------------------------------------------------------
#ifdef WIZARD
-static int debug_prompt_for_monster( void )
-{
- char specs[80];
- char obj_name[ ITEMNAME_SIZE ];
- char *ptr;
- mpr( "(Hint: 'generated' names, eg 'orc zombie', won't work)", MSGCH_PROMPT );
- mpr( "Which monster by name? ", MSGCH_PROMPT );
- get_input_line( specs, sizeof( specs ) );
-
- if (specs[0] == '\0')
- return (-1);
+static int get_monnum(const char *name)
+{
+ char search[ITEMNAME_SIZE],
+ mname[ITEMNAME_SIZE];
+ strncpy(search, name, sizeof search);
+ search[ITEMNAME_SIZE - 1] = 0;
+ strlwr(search);
int mon = -1;
-
for (int i = 0; i < NUM_MONSTERS; i++)
{
- moname( i, true, DESC_PLAIN, obj_name );
+ moname( i, true, DESC_PLAIN, mname );
- ptr = strstr( strlwr(obj_name), strlwr(specs) );
+ const char *ptr = strstr( strlwr(mname), search );
if (ptr != NULL)
{
- mpr( obj_name );
- if (ptr == obj_name)
+ if (ptr == mname)
{
// we prefer prefixes over partial matches
mon = i;
@@ -426,9 +422,22 @@ static int debug_prompt_for_monster( void )
mon = i;
}
}
-
return (mon);
}
+
+static int debug_prompt_for_monster( void )
+{
+ char specs[80];
+
+ mpr( "(Hint: 'generated' names, eg 'orc zombie', won't work)", MSGCH_PROMPT );
+ mpr( "Which monster by name? ", MSGCH_PROMPT );
+ get_input_line( specs, sizeof( specs ) );
+
+ if (specs[0] == '\0')
+ return (-1);
+
+ return (get_monnum(specs));
+}
#endif
//---------------------------------------------------------------
@@ -1715,3 +1724,276 @@ void error_message_to_player(void)
mpr("I suggest you leave this level then save as soon as possible.");
} // end error_message_to_player()
+
+#ifdef WIZARD
+
+static int create_dfs_monster(int mtype, int hp)
+{
+ const int mi =
+ create_monster( mtype, 0, BEH_HOSTILE, you.x_pos, you.y_pos,
+ MHITNOT, 250 );
+
+ if (mi == -1)
+ return (mi);
+
+ monsters *mon = &menv[mi];
+ mon->hit_points = mon->max_hit_points = hp;
+ return (mi);
+}
+
+static skill_type dfs_melee_skill(const item_def *item)
+{
+ skill_type sk = SK_UNARMED_COMBAT;
+ if (item)
+ sk = weapon_skill(*item);
+ return (sk);
+}
+
+static void dfs_set_melee_skill(int skill, const item_def *item)
+{
+ you.skills[dfs_melee_skill(item)] = skill;
+ you.skills[SK_FIGHTING] = skill * 15 / 27;
+}
+
+static void dfs_set_ranged_skill(int skill, const item_def *item)
+{
+ you.skills[range_skill(*item)] = skill;
+ you.skills[SK_RANGED_COMBAT] = skill * 15 / 27;
+}
+
+static void dfs_ranged_item(FILE *out, const item_def *launcher,
+ int wskill, unsigned long damage,
+ long iterations, long hits,
+ int maxdam)
+{
+ double hitdam = hits? double(damage) / hits : 0.0;
+ fprintf(out, "Ranged: %s %d. Accuracy: %ld%%, av damage: %.2f, av hitdam: %.2f, max: %d\n",
+ skill_name( range_skill(*launcher) ),
+ wskill,
+ 100 * hits / iterations,
+ double(damage) / iterations,
+ hitdam,
+ maxdam);
+}
+
+static void dfs_melee_item(FILE *out, const item_def *item,
+ int wskill, unsigned long damage,
+ long iterations, long hits,
+ int maxdam)
+{
+ double hitdam = hits? double(damage) / hits : 0.0;
+ fprintf(out, "Melee: %s %d. Accuracy: %ld%%, av damage: %.2f, av hitdam: %.2f, max: %d\n",
+ skill_name( dfs_melee_skill(item) ),
+ wskill,
+ 100 * hits / iterations,
+ double(damage) / iterations,
+ hitdam,
+ maxdam);
+}
+
+static bool dfs_ranged_combat(FILE *out, int wskill, int mi,
+ const item_def *item)
+{
+ monsters &mon = menv[mi];
+ unsigned long cumulative_damage = 0L;
+ long hits = 0L;
+ int maxdam = 0;
+
+ const int thrown = get_fire_item_index();
+ if (thrown == ENDOFPACK)
+ {
+ mprf("No suitable missiles for combat simulation.");
+ return (false);
+ }
+
+ dfs_set_ranged_skill(wskill, item);
+
+ no_messages mx;
+ const long iter_limit = Options.fsim_rounds;
+ const int hunger = you.hunger;
+ for (long i = 0; i < iter_limit; ++i)
+ {
+ mon.hit_points = mon.max_hit_points;
+ bolt beam;
+ if (throw_it(beam, thrown, &mon))
+ hits++;
+ you.hunger = hunger;
+
+ int damage = (mon.max_hit_points - mon.hit_points);
+ cumulative_damage += damage;
+ if (damage > maxdam)
+ maxdam = damage;
+ }
+ dfs_ranged_item(out, item, wskill, cumulative_damage,
+ iter_limit, hits, maxdam);
+
+ return (true);
+}
+
+static bool dfs_melee_combat(FILE *out, int wskill, int mi,
+ const item_def *item)
+{
+ monsters &mon = menv[mi];
+ unsigned long cumulative_damage = 0L;
+ long hits = 0L;
+ int maxdam = 0;
+
+ dfs_set_melee_skill(wskill, item);
+
+ no_messages mx;
+ const long iter_limit = Options.fsim_rounds;
+ const int hunger = you.hunger;
+ for (long i = 0; i < iter_limit; ++i)
+ {
+ mon.hit_points = mon.max_hit_points;
+ if (you_attack(mi, true))
+ hits++;
+ you.hunger = hunger;
+
+ int damage = (mon.max_hit_points - mon.hit_points);
+ cumulative_damage += damage;
+ if (damage > maxdam)
+ maxdam = damage;
+ }
+ dfs_melee_item(out, item, wskill, cumulative_damage, iter_limit, hits,
+ maxdam);
+
+ return (true);
+}
+
+static bool debug_fight_simulate(FILE *out, int wskill, int mi)
+{
+ int weapon = you.equip[EQ_WEAPON];
+ const item_def *iweap = weapon != -1? &you.inv[weapon] : NULL;
+
+ if (iweap && iweap->base_type == OBJ_WEAPONS
+ && is_range_weapon(*iweap))
+ return dfs_ranged_combat(out, wskill, mi, iweap);
+ else
+ return dfs_melee_combat(out, wskill, mi, iweap);
+}
+
+static std::string dfs_weapon()
+{
+ char item_buf[ITEMNAME_SIZE];
+ if (you.equip[EQ_WEAPON] != -1)
+ {
+ const item_def &weapon = you.inv[ you.equip[EQ_WEAPON] ];
+ item_name(weapon, DESC_PLAIN, item_buf, true);
+
+ if (is_range_weapon(weapon))
+ {
+ const int missile = get_fire_item_index();
+ if (missile < ENDOFPACK)
+ {
+ std::string base = item_buf;
+ base += " with ";
+ in_name(missile, DESC_PLAIN, item_buf, true);
+ return (base + item_buf);
+ }
+ }
+ }
+ else
+ {
+ strncpy(item_buf, "unarmed", sizeof item_buf);
+ }
+ return (item_buf);
+}
+
+static void dfs_title(FILE *o, int mon)
+{
+ char buf[ITEMNAME_SIZE];
+ fprintf(o, "Combat simulation: %s %s vs. %s (%ld turns)\n",
+ species_name(you.species, you.experience_level),
+ you.class_name,
+ moname(menv[mon].type, true, DESC_PLAIN, buf),
+ Options.fsim_rounds);
+ fprintf(o, "Experience: %d\n", you.experience_level);
+ fprintf(o, "Strength : %d\n", you.strength);
+ fprintf(o, "Intel. : %d\n", you.intel);
+ fprintf(o, "Dexterity : %d\n", you.dex);
+ fprintf(o, "\nWeapon : %s\n", dfs_weapon().c_str());
+ fprintf(o, "\n");
+}
+
+static int fsim_stat(int stat)
+{
+ return (stat < 1 ? 1 :
+ stat > 60 ? 60 :
+ stat);
+}
+
+// Writes statistics about a fight to fight.stat in the current directory.
+// For fight purposes, a punching bag is summoned and given lots of hp, and the
+// average damage the player does to the p. bag over 10000 hits is noted,
+// advancing the weapon skill from 0 to 27, and keeping fighting skill to 2/5
+// of current weapon skill.
+void debug_fight_statistics()
+{
+ int punching_bag = get_monnum(Options.fsim_mons.c_str());
+ if (punching_bag == -1)
+ punching_bag = MONS_WORM;
+
+ int mindex = create_dfs_monster(punching_bag, 500);
+ if (mindex == -1)
+ {
+ mprf("Failed to create punching bag");
+ return;
+ }
+
+ FILE *ostat = fopen("fight.stat", "a");
+ if (!ostat)
+ {
+ mprf("Can't write fight.stat: %s", strerror(errno));
+ return;
+ }
+
+ FixedVector<unsigned char, 50> skill_backup = you.skills;
+ int ystr = you.strength,
+ yint = you.intel,
+ ydex = you.dex;
+ int yxp = you.experience_level;
+
+ you.experience_level = Options.fsim_xl;
+ if (you.experience_level < 1)
+ you.experience_level = 1;
+ if (you.experience_level > 27)
+ you.experience_level = 27;
+
+ you.strength = fsim_stat(Options.fsim_str);
+ you.intel = fsim_stat(Options.fsim_int);
+ you.dex = fsim_stat(Options.fsim_dex);
+
+ dfs_title(ostat, mindex);
+ for (int wskill = 0; wskill <= 27; ++wskill)
+ {
+ mesclr();
+ mprf("Calculating average damage for %s at skill %d",
+ dfs_weapon().c_str(), wskill);
+ if (!debug_fight_simulate(ostat, wskill, mindex))
+ goto done_combat_sim;
+
+ fflush(ostat);
+ // Not checking in the combat loop itself; that would be more responsive
+ // for the user, but slow down the sim with all the calls to kbhit().
+ if (kbhit() && getch() == 27)
+ {
+ mprf("Canceling simulation\n");
+ goto done_combat_sim;
+ }
+ }
+ you.skills = skill_backup;
+ you.strength = ystr;
+ you.intel = yint;
+ you.dex = ydex;
+ you.experience_level = yxp;
+
+ mprf("Done fight simulation with %s", dfs_weapon().c_str());
+
+done_combat_sim:
+ fprintf(ostat, "-----------------------------------\n\n");
+
+ fclose(ostat);
+ monster_die(&menv[mindex], KILL_DISMISSED, 0);
+}
+#endif
diff --git a/crawl-ref/source/debug.h b/crawl-ref/source/debug.h
index cbc8161d3b..8675ef9de3 100644
--- a/crawl-ref/source/debug.h
+++ b/crawl-ref/source/debug.h
@@ -143,5 +143,6 @@ void stethoscope(int mwh);
void debug_item_scan( void );
void debug_get_religion( void );
void debug_change_species( void );
+void debug_fight_statistics( void );
#endif
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index afa9084e8b..aab1dd2d87 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -775,6 +775,12 @@ struct game_options
// If the player prefers to merge kill records, this option can do that.
int kill_map[KC_NCATEGORIES];
+
+ // Parameters for fight simulations.
+ long fsim_rounds;
+ int fsim_str, fsim_int, fsim_dex;
+ int fsim_xl;
+ std::string fsim_mons;
typedef std::map<std::string, std::string> opt_map;
opt_map named_options; // All options not caught above are
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 2b59c92f03..a478f6002a 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -127,7 +127,8 @@ int effective_stat_bonus( int wepType )
#endif
}
-void you_attack(int monster_attacked, bool unarmed_attacks)
+// Returns true if you hit the monster.
+bool you_attack(int monster_attacked, bool unarmed_attacks)
{
struct monsters *defender = &menv[monster_attacked];
@@ -273,7 +274,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (random2(you.dex) < 4 || one_chance_in(5))
{
mpr("Unstable footing causes you to fumble your attack.");
- return;
+ return (false);
}
}
@@ -949,7 +950,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
snprintf( info, INFO_SIZE, "You %s the ball lightning.", damage_noise);
mpr(info);
}
- return;
+ return (true);
}
if (damage_done < 1 && player_monster_visible( defender ))
@@ -1491,7 +1492,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (coinflip())
{
monster_die(defender, KILL_RESET, 0);
- return;
+ return (true);
}
break;
@@ -1526,7 +1527,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (defender->hit_points < 1)
{
monster_die(defender, KILL_YOU, 0);
- return;
+ return (hit);
}
if (unarmed_attacks)
@@ -1840,7 +1841,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
strcat(info, "the ball lightning.");
mpr(info);
}
- return;
+ return (true);
}
}
else
@@ -1858,7 +1859,7 @@ void you_attack(int monster_attacked, bool unarmed_attacks)
if (hit)
print_wounds(defender);
- return;
+ return (hit);
} // end you_attack()
void monster_attack(int monster_attacking)
diff --git a/crawl-ref/source/fight.h b/crawl-ref/source/fight.h
index 10515868c6..9b54b8b339 100644
--- a/crawl-ref/source/fight.h
+++ b/crawl-ref/source/fight.h
@@ -32,7 +32,7 @@ int weapon_str_weight( int wpn_class, int wpn_type );
/* ***********************************************************************
* called from: acr - it_use3
* *********************************************************************** */
-void you_attack(int monster_attacked, bool unarmed_attacks);
+bool you_attack(int monster_attacked, bool unarmed_attacks);
// last updated: 08jun2000 {dlb}
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index 0e64ebd602..e7e62adc1f 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -433,6 +433,11 @@ void reset_options(bool clear_name)
for (int i = 2; i < NUM_FIRE_TYPES; i++)
Options.fire_order[i] = FIRE_NONE;
+ Options.fsim_rounds = 40000L;
+ Options.fsim_mons = "worm";
+ Options.fsim_str = Options.fsim_int = Options.fsim_dex = 15;
+ Options.fsim_xl = 10;
+
// These are only used internally, and only from the commandline:
// XXX: These need a better place.
Options.sc_entries = 0;
@@ -1281,6 +1286,34 @@ void parse_option_line(const std::string &str, bool runscript)
{
Options.show_waypoints = read_bool(field, Options.show_waypoints);
}
+ else if (key == "fsim_rounds")
+ {
+ Options.fsim_rounds = atol(field.c_str());
+ if (Options.fsim_rounds < 1000)
+ Options.fsim_rounds = 1000;
+ if (Options.fsim_rounds > 500000L)
+ Options.fsim_rounds = 500000L;
+ }
+ else if (key == "fsim_mons")
+ {
+ Options.fsim_mons = field;
+ }
+ else if (key == "fsim_str")
+ {
+ Options.fsim_str = atoi(field.c_str());
+ }
+ else if (key == "fsim_int")
+ {
+ Options.fsim_int = atoi(field.c_str());
+ }
+ else if (key == "fsim_dex")
+ {
+ Options.fsim_dex = atoi(field.c_str());
+ }
+ else if (key == "fsim_xl")
+ {
+ Options.fsim_xl = atoi(field.c_str());
+ }
else if (key == "travel_delay")
{
// Read travel delay in milliseconds.
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index f67fe7cfd7..49ee1a8e2e 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -68,7 +68,6 @@
#include "wpn-misc.h"
bool drink_fountain(void);
-static void throw_it(struct bolt &pbolt, int throw_2);
void use_randart(unsigned char item_wield_2);
static bool enchant_armour( void );
@@ -1159,7 +1158,12 @@ void shoot_thing(void)
// throw_it - currently handles player throwing only. Monster
// throwing is handled in mstuff2:mons_throw()
-static void throw_it(struct bolt &pbolt, int throw_2)
+// Note: If dummy_target is non-NULL, throw_it fakes a bolt and calls
+// affect() on the monster's square.
+//
+// Return value is only relevant if dummy_target is non-NULL, and returns
+// true if dummy_target is hit.
+bool throw_it(struct bolt &pbolt, int throw_2, monsters *dummy_target)
{
struct dist thr;
char shoot_skill = 0;
@@ -1176,16 +1180,26 @@ static void throw_it(struct bolt &pbolt, int throw_2)
bool launched = false; // item is launched
bool thrown = false; // item is sensible thrown item
- mpr( STD_DIRECTION_PROMPT, MSGCH_PROMPT );
- message_current_target();
- direction( thr, DIR_NONE, TARG_ENEMY );
+ if (dummy_target)
+ {
+ thr.isValid = true;
+ thr.isCancel = false;
+ thr.tx = dummy_target->x;
+ thr.ty = dummy_target->y;
+ }
+ else
+ {
+ mpr( STD_DIRECTION_PROMPT, MSGCH_PROMPT );
+ message_current_target();
+ direction( thr, DIR_NONE, TARG_ENEMY );
+ }
if (!thr.isValid)
{
if (thr.isCancel)
canned_msg(MSG_OK);
- return;
+ return (false);
}
// Must unwield before fire_beam() makes a copy in order to remove things
@@ -1783,10 +1797,16 @@ static void throw_it(struct bolt &pbolt, int throw_2)
if (wepClass == OBJ_MISSILES || wepClass == OBJ_WEAPONS)
item.flags |= ISFLAG_THROWN;
+ bool hit = false;
// using copy, since the launched item might be differect (venom blowgun)
- fire_beam( pbolt, &item );
+ if (dummy_target)
+ hit = (affect( pbolt, dummy_target->x, dummy_target->y ) != 0);
+ else
+ {
+ fire_beam( pbolt, &item );
- dec_inv_item_quantity( throw_2, 1 );
+ dec_inv_item_quantity( throw_2, 1 );
+ }
// throwing and blowguns are silent
if (launched && lnchType != WPN_BLOWGUN)
@@ -1796,6 +1816,8 @@ static void throw_it(struct bolt &pbolt, int throw_2)
alert_nearby_monsters();
you.turn_is_over = 1;
+
+ return (hit);
} // end throw_it()
bool puton_item(int item_slot, bool prompt_finger)
diff --git a/crawl-ref/source/item_use.h b/crawl-ref/source/item_use.h
index 9115ecf6bd..93d3ec3098 100644
--- a/crawl-ref/source/item_use.h
+++ b/crawl-ref/source/item_use.h
@@ -15,6 +15,7 @@
#include <string>
+#include "externs.h"
// last updated 12may2000 {dlb}
@@ -130,4 +131,6 @@ bool puton_item(int slot, bool prompt_finger = true);
bool enchant_weapon( int which_stat, bool quiet = false );
+bool throw_it(struct bolt &pbolt, int throw_2, monsters *dummy_target = NULL);
+
#endif
diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc
index c6f391a53e..353a069abc 100644
--- a/crawl-ref/source/message.cc
+++ b/crawl-ref/source/message.cc
@@ -39,6 +39,18 @@ int Next_Message = 0; // end of messages
char Message_Line = 0; // line of next (previous?) message
+static bool suppress_messages = false;
+
+no_messages::no_messages() : msuppressed(suppress_messages)
+{
+ suppress_messages = true;
+}
+
+no_messages::~no_messages()
+{
+ suppress_messages = msuppressed;
+}
+
static char god_message_altar_colour( char god )
{
int rnd;
@@ -244,6 +256,9 @@ void mprf( const char *format, ... )
void mpr(const char *inf, int channel, int param)
{
+ if (suppress_messages)
+ return;
+
char info2[80];
int colour = channel_to_colour( channel, param );
diff --git a/crawl-ref/source/message.h b/crawl-ref/source/message.h
index 8878464d95..83f7787d35 100644
--- a/crawl-ref/source/message.h
+++ b/crawl-ref/source/message.h
@@ -57,6 +57,15 @@ void mpr(const char *inf, int channel = MSGCH_PLAIN, int param = 0);
void mprf( int channel, const char *format, ... );
void mprf( const char *format, ... );
+class no_messages
+{
+public:
+ no_messages();
+ ~no_messages();
+private:
+ bool msuppressed;
+};
+
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr