summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-05-26 13:47:37 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-05-26 13:47:37 +0000
commita33ad3c3e6b0bf53a63554e96eb52db78b4a48f0 (patch)
tree8ff69133c16dfb19852f0e52b75283864eb60cdd
parentd73035c53987d171d07b7a39fdd23caf4f5967f5 (diff)
downloadcrawl-ref-a33ad3c3e6b0bf53a63554e96eb52db78b4a48f0.tar.gz
crawl-ref-a33ad3c3e6b0bf53a63554e96eb52db78b4a48f0.zip
Run some sanity checks when loading ghosts. If anything seems fishy
* don't load the ghost(s) * print an error message mentioning the bones file * don't delete the bones file, so players can attach it to a bug report The last point means that the player (or admin, in the case of the servers) has to delete a buggy bones file themselves, but the benefits of making tracking down bugs easier should outweigh that inconvenience. Add a new wizmode command that calls debug_stethoscope even if the game is not compiled in debugging mode. Also, Stone Soup 0.5 bones files are now officially incompatible with 0.4. (The changes to the spell ids cause ghosts casting spells to crash the game.) git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@9832 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/docs/changes.stone_soup2
-rw-r--r--crawl-ref/source/cmd-keys.h1
-rw-r--r--crawl-ref/source/cmd-name.h1
-rw-r--r--crawl-ref/source/command.cc1
-rw-r--r--crawl-ref/source/debug.cc35
-rw-r--r--crawl-ref/source/debug.h2
-rw-r--r--crawl-ref/source/directn.cc6
-rw-r--r--crawl-ref/source/enum.h1
-rw-r--r--crawl-ref/source/files.cc15
-rw-r--r--crawl-ref/source/ghost.cc40
-rw-r--r--crawl-ref/source/ghost.h2
-rw-r--r--crawl-ref/source/player.cc2
-rw-r--r--crawl-ref/source/spl-util.cc1
-rw-r--r--crawl-ref/source/travel.cc4
14 files changed, 91 insertions, 22 deletions
diff --git a/crawl-ref/docs/changes.stone_soup b/crawl-ref/docs/changes.stone_soup
index 4b54004c0d..33c71802b0 100644
--- a/crawl-ref/docs/changes.stone_soup
+++ b/crawl-ref/docs/changes.stone_soup
@@ -3,7 +3,7 @@ Stone Soup 0.5.0 (2009????)
Disclaimer: The code and this list are very much a work in progress.
-Breaks saves compatibility.
+Breaks saves and bones compatibility.
0.5 Highlights
diff --git a/crawl-ref/source/cmd-keys.h b/crawl-ref/source/cmd-keys.h
index 579fd57b24..f45e2383fd 100644
--- a/crawl-ref/source/cmd-keys.h
+++ b/crawl-ref/source/cmd-keys.h
@@ -153,6 +153,7 @@
{'M', CMD_TARGET_WIZARD_MISCAST},
{'S', CMD_TARGET_WIZARD_MAKE_SUMMONED},
{'~', CMD_TARGET_WIZARD_POLYMORPH},
+{'D', CMD_TARGET_WIZARD_DEBUG_MONSTER},
#endif
{'v', CMD_TARGET_DESCRIBE},
{'?', CMD_TARGET_HELP},
diff --git a/crawl-ref/source/cmd-name.h b/crawl-ref/source/cmd-name.h
index 7667397bdd..5aa7954b3a 100644
--- a/crawl-ref/source/cmd-name.h
+++ b/crawl-ref/source/cmd-name.h
@@ -197,6 +197,7 @@
{CMD_TARGET_WIZARD_MISCAST, "CMD_TARGET_WIZARD_MISCAST"},
{CMD_TARGET_WIZARD_MAKE_SUMMONED, "CMD_TARGET_WIZARD_MAKE_SUMMONED"},
{CMD_TARGET_WIZARD_POLYMORPH, "CMD_TARGET_WIZARD_POLYMORPH"},
+{CMD_TARGET_WIZARD_DEBUG_MONSTER, "CMD_TARGET_WIZARD_DEBUG_MONSTER"},
{CMD_TARGET_MOUSE_MOVE, "CMD_TARGET_MOUSE_MOVE"},
{CMD_TARGET_MOUSE_SELECT, "CMD_TARGET_MOUSE_SELECT"},
{CMD_TARGET_HELP, "CMD_TARGET_HELP"},
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index 8b07755b10..ce6644780c 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -777,6 +777,7 @@ static const char *targeting_help_1 =
"<w>m</w>: move monster or player\n"
"<w>M</w>: cause spell miscast for monster or player\n"
"<w>w</w>: calculate shortest path to any point on the map\n"
+ "<w>D</w>: get debugging information about the monster\n"
"<w>~</w>: polymorph monster to specific type\n"
#endif
;
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index a2b5c7aaa6..0bccde0e96 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -386,7 +386,7 @@ static int _debug_prompt_for_int( const char *prompt, bool nonneg )
char *end;
int ret = strtol( specs, &end, 10 );
- if ((ret < 0 && nonneg) || (ret == 0 && end == specs))
+ if (ret < 0 && nonneg || ret == 0 && end == specs)
ret = (nonneg ? -1 : 0);
return (ret);
@@ -2512,8 +2512,10 @@ void wizard_list_items()
continue;
if (item.link != NON_ITEM)
+ {
mprf("(%2d,%2d): %s", item.pos.x, item.pos.y,
item.name(DESC_PLAIN, false, false, false).c_str() );
+ }
}
mpr(EOL);
@@ -2532,7 +2534,6 @@ void wizard_list_items()
}
#endif
-#ifdef DEBUG_DIAGNOSTICS
// Prints a number of useful (for debugging, that is) stats on monsters.
void debug_stethoscope(int mon)
{
@@ -2583,7 +2584,7 @@ void debug_stethoscope(int mon)
(mons.attitude == ATT_FRIENDLY) ? "friendly" :
(mons.attitude == ATT_NEUTRAL) ? "neutral" :
(mons.attitude == ATT_GOOD_NEUTRAL) ? "good neutral"
- : "unknown alignment") );
+ : "unknown alignment") );
// Print stats and other info.
mprf(MSGCH_DIAGNOSTICS,
@@ -2619,7 +2620,7 @@ void debug_stethoscope(int mon)
mons_is_cornered(&mons) ? "cornered" :
mons_is_panicking(&mons) ? "panic" :
mons_is_lurking(&mons) ? "lurk"
- : "unknown"),
+ : "unknown"),
mons.behaviour,
((mons.foe == MHITYOU) ? "you" :
(mons.foe == MHITNOT) ? "none" :
@@ -2641,6 +2642,31 @@ void debug_stethoscope(int mon)
mprf(MSGCH_DIAGNOSTICS, "ench: %s",
mons.describe_enchantments().c_str());
+ std::ostringstream spl;
+ const monster_spells &hspell_pass = mons.spells;
+ bool found_spell = false;
+ for (int k = 0; k < NUM_MONSTER_SPELL_SLOTS; ++k)
+ {
+ if (hspell_pass[k] != SPELL_NO_SPELL)
+ {
+ if (found_spell)
+ spl << ", ";
+
+ found_spell = true;
+
+ spl << k << ": ";
+
+ if (hspell_pass[k] >= NUM_SPELLS)
+ spl << "buggy spell";
+ else
+ spl << spell_title(hspell_pass[k]);
+
+ spl << " (" << static_cast<int>(hspell_pass[k]) << ")";
+ }
+ }
+ if (found_spell)
+ mprf(MSGCH_DIAGNOSTICS, "spells: %s", spl.str().c_str());
+
if (mons.type == MONS_PLAYER_GHOST
|| mons.type == MONS_PANDEMONIUM_DEMON)
{
@@ -2650,7 +2676,6 @@ void debug_stethoscope(int mon)
ghost.damage, ghost.brand );
}
}
-#endif
#if DEBUG_ITEM_SCAN
static void _dump_item( const char *name, int num, const item_def &item )
diff --git a/crawl-ref/source/debug.h b/crawl-ref/source/debug.h
index d91965e254..c285d17739 100644
--- a/crawl-ref/source/debug.h
+++ b/crawl-ref/source/debug.h
@@ -116,9 +116,7 @@ void debug_test_explore();
* called from: directn
* *********************************************************************** */
void error_message_to_player(void);
-#if DEBUG_DIAGNOSTICS
void debug_stethoscope(int mon);
-#endif
class monsters;
struct coord_def;
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index 756b9a5e3b..e68d8e3f9e 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -1559,6 +1559,12 @@ void direction(dist& moves, targeting_type restricts,
wizard_polymorph_monster(m);
break;
+ case CMD_TARGET_WIZARD_DEBUG_MONSTER:
+ if (!you.wizard || !in_bounds(moves.target))
+ break;
+ if (monster_at(moves.target))
+ debug_stethoscope(mgrd(moves.target));
+ break;
#endif
case CMD_TARGET_DESCRIBE:
full_describe_square(moves.target);
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index e563735a17..c29d578af2 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -653,6 +653,7 @@ enum command_type
CMD_TARGET_WIZARD_MISCAST,
CMD_TARGET_WIZARD_MAKE_SUMMONED,
CMD_TARGET_WIZARD_POLYMORPH,
+ CMD_TARGET_WIZARD_DEBUG_MONSTER,
CMD_TARGET_MOUSE_MOVE,
CMD_TARGET_MOUSE_SELECT,
CMD_TARGET_HELP,
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index e0fe414bde..4ea0bd5fee 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -1600,7 +1600,7 @@ void _load_ghost(void)
if (!_determine_ghost_version(gfile, majorVersion, minorVersion))
{
fclose(gfile);
-#if DEBUG_DIAGNOSTICS
+#if DEBUG_BONES | DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS,
"Ghost file \"%s\" seems to be invalid.", cha_fil.c_str());
more();
@@ -1610,7 +1610,6 @@ void _load_ghost(void)
if (majorVersion != TAG_MAJOR_VERSION || minorVersion > TAG_MINOR_VERSION)
{
-
fclose(gfile);
unlink(cha_fil.c_str());
return;
@@ -1623,7 +1622,7 @@ void _load_ghost(void)
if (!feof(gfile))
{
fclose(gfile);
-#if DEBUG_DIAGNOSTICS
+#if DEBUG_BONES | DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Incomplete read of \"%s\".",
cha_fil.c_str() );
more();
@@ -1633,7 +1632,15 @@ void _load_ghost(void)
fclose(gfile);
-#if DEBUG_DIAGNOSTICS
+ if (!debug_check_ghosts())
+ {
+ mprf(MSGCH_DIAGNOSTICS, "Refusing to load buggy ghost from file \"%s\"! "
+ "Please submit a bug report.",
+ cha_fil.c_str());
+ return;
+ }
+
+#if DEBUG_BONES | DEBUG_DIAGNOSTICS
mpr("Loaded ghost.", MSGCH_DIAGNOSTICS);
#endif
diff --git a/crawl-ref/source/ghost.cc b/crawl-ref/source/ghost.cc
index 38a3546d49..3b68663bd1 100644
--- a/crawl-ref/source/ghost.cc
+++ b/crawl-ref/source/ghost.cc
@@ -25,6 +25,10 @@ REVISION("$Rev$");
#include "religion.h"
#include <vector>
+#define MAX_GHOST_DAMAGE 50
+#define MAX_GHOST_HP 400
+#define MAX_GHOST_EVASION 60
+
std::vector<ghost_demon> ghosts;
// Order for looking for conjurations for the 1st & 2nd spell slots,
@@ -293,12 +297,12 @@ void ghost_demon::init_random_demon()
void ghost_demon::init_player_ghost()
{
name = you.your_name;
- max_hp = ((you.hp_max >= 400) ? 400 : you.hp_max);
+ max_hp = ((you.hp_max >= MAX_GHOST_HP) ? MAX_GHOST_HP : you.hp_max);
ev = player_evasion();
ac = player_AC();
- if (ev > 60)
- ev = 60;
+ if (ev > MAX_GHOST_EVASION)
+ ev = MAX_GHOST_EVASION;
see_invis = player_see_invis();
resists.fire = player_res_fire();
@@ -344,8 +348,8 @@ void ghost_demon::init_player_ghost()
damage += you.strength / 4;
- if (damage > 50)
- damage = 50;
+ if (damage > MAX_GHOST_DAMAGE)
+ damage = MAX_GHOST_DAMAGE;
species = you.species;
job = you.char_class;
@@ -526,7 +530,7 @@ void ghost_demon::find_transiting_ghosts(
void ghost_demon::announce_ghost(const ghost_demon &g)
{
-#ifdef DEBUG_DIAGNOSTICS
+#if DEBUG_BONES | DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Saving ghost: %s", g.name.c_str());
#endif
}
@@ -589,3 +593,27 @@ int ghost_demon::n_extra_ghosts()
return (1 + x_chance_in_y(lev, 20) + x_chance_in_y(lev, 40));
}
+
+// Sanity checks for some ghost values.
+bool debug_check_ghosts()
+{
+ for (unsigned int k = 0; k < ghosts.size(); ++k)
+ {
+ ghost_demon ghost = ghosts[k];
+ // Values greater than the allowed maximum signalize bugginess.
+ if (ghost.damage > MAX_GHOST_DAMAGE)
+ return (false);
+ if (ghost.max_hp > MAX_GHOST_HP)
+ return (false);
+ if (ghost.xl > 27)
+ return (false);
+ if (ghost.ev > MAX_GHOST_EVASION)
+ return (false);
+
+ // Check for non-existing spells.
+ for (int sp = 0; sp < NUM_MONSTER_SPELL_SLOTS; ++sp)
+ if (ghost.spells[sp] < 0 || ghost.spells[sp] >= NUM_SPELLS)
+ return (false);
+ }
+ return (true);
+}
diff --git a/crawl-ref/source/ghost.h b/crawl-ref/source/ghost.h
index 8cb574dd4b..d10a664c68 100644
--- a/crawl-ref/source/ghost.h
+++ b/crawl-ref/source/ghost.h
@@ -58,6 +58,8 @@ private:
spell_type translate_spell(spell_type playerspell) const;
};
+bool debug_check_ghosts();
+
extern std::vector<ghost_demon> ghosts;
#endif
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 624393f230..e633ffe977 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -1880,7 +1880,7 @@ int player_prot_life(bool calc_unid, bool temp, bool items)
// speed, not a movement cost, so higher is better.
int player_ghost_base_movement_speed()
{
- int speed = you.species == SP_NAGA ? 8 : 10;
+ int speed = (you.species == SP_NAGA ? 8 : 10);
if (player_mutation_level(MUT_FAST))
speed += player_mutation_level(MUT_FAST) + 1;
diff --git a/crawl-ref/source/spl-util.cc b/crawl-ref/source/spl-util.cc
index c8bfdd0d94..4b52954da6 100644
--- a/crawl-ref/source/spl-util.cc
+++ b/crawl-ref/source/spl-util.cc
@@ -943,7 +943,6 @@ int spell_skill2type(unsigned int skill)
static spell_desc *_seekspell(spell_type spell)
{
ASSERT(spell >= 0 && spell < NUM_SPELLS);
-
const int index = spell_list[spell];
ASSERT(index != -1);
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index cdf5a42b89..4cfb3e457d 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -3066,9 +3066,9 @@ level_id level_id::get_next_level_id(const coord_def &pos)
int gridc = grd(pos);
level_id id = current();
- for ( int i = 0; i < NUM_BRANCHES; ++i )
+ for (int i = 0; i < NUM_BRANCHES; ++i)
{
- if ( gridc == branches[i].entry_stairs )
+ if (gridc == branches[i].entry_stairs)
{
id.branch = static_cast<branch_type>(i);
id.depth = 1;