diff options
Diffstat (limited to 'crawl-ref')
-rw-r--r-- | crawl-ref/source/acr.cc | 21 | ||||
-rw-r--r-- | crawl-ref/source/dat/descript.txt | 1 | ||||
-rw-r--r-- | crawl-ref/source/debug.cc | 139 | ||||
-rw-r--r-- | crawl-ref/source/debug.h | 8 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 16 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 12 | ||||
-rw-r--r-- | crawl-ref/source/initfile.cc | 22 | ||||
-rw-r--r-- | crawl-ref/source/maps.cc | 15 |
9 files changed, 210 insertions, 26 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 71d9ccc754..c8e75f5b61 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -1638,7 +1638,8 @@ static void decrement_durations() you.duration[DUR_REPEL_MISSILES]--; if (you.duration[DUR_REPEL_MISSILES] == 6) { - mpr("Your repel missiles spell is about to expire...", MSGCH_DURATION); + mpr("Your repel missiles spell is about to expire...", + MSGCH_DURATION); if (coinflip()) you.duration[DUR_REPEL_MISSILES]--; } @@ -1654,7 +1655,8 @@ static void decrement_durations() you.duration[DUR_DEFLECT_MISSILES]--; if (you.duration[DUR_DEFLECT_MISSILES] == 6) { - mpr("Your deflect missiles spell is about to expire...", MSGCH_DURATION); + mpr("Your deflect missiles spell is about to expire...", + MSGCH_DURATION); if (coinflip()) you.duration[DUR_DEFLECT_MISSILES]--; } @@ -1726,8 +1728,6 @@ static void decrement_durations() break; case SPWPN_DISTORTION: msg += " seems straighter."; - // [dshaligram] Makes the brand unusable - // miscast_effect( SPTYP_TRANSLOCATION, 9, 90, 100, "a distortion effect" ); break; case SPWPN_PAIN: msg += " seems less painful."; @@ -3016,15 +3016,18 @@ static bool initialise(void) // system initialisation stuff: textbackground(0); -#ifdef DOS - directvideo = 1; -#endif - clrscr(); +#ifdef DEBUG_DIAGNOSTICS + if (crawl_state.map_stat_gen) + { + generate_map_stats(); + end(0, false); + } +#endif + // sets up a new game: const bool newc = new_game(); - if (!newc) restore_game(); diff --git a/crawl-ref/source/dat/descript.txt b/crawl-ref/source/dat/descript.txt index fbe3ee1f12..e88f8c0501 100644 --- a/crawl-ref/source/dat/descript.txt +++ b/crawl-ref/source/dat/descript.txt @@ -92,6 +92,7 @@ A small twisted demon with a long, sharply pointed tail. %%%% rat Wherever there are men, there are rats -- rattus rattus. This rat has grown large and aggressive in the pestilential dungeon environment. + How now? a rat? Dead, for a ducat, dead! -William Shakespeare, Hamlet, Act III, 4 %%%% diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc index 903180a9c0..92dfd46534 100644 --- a/crawl-ref/source/debug.cc +++ b/crawl-ref/source/debug.cc @@ -51,6 +51,8 @@ #include "item_use.h" #include "items.h" #include "makeitem.h" +#include "mapdef.h" +#include "maps.h" #include "misc.h" #include "monplace.h" #include "monstuff.h" @@ -2116,3 +2118,140 @@ void debug_card() } #endif + +#ifdef DEBUG_DIAGNOSTICS + +// Map statistics generation. + +std::map<std::string, int> mapgen_try_count; +std::map<std::string, int> mapgen_use_count; +std::map<level_id, int> mapgen_level_maps; +std::map<std::string, std::string> mapgen_errors; +std::string mapgen_last_error; + +static int mg_levels_tried = 0, mg_levels_failed = 0; +static void mg_build_levels(int niters) +{ + mesclr(); + mprf("Generating dungeon map stats"); + + for (int br = BRANCH_MAIN_DUNGEON; br < NUM_BRANCHES; ++br) + { + if (branches[br].depth == -1) + continue; + + const branch_type branch = static_cast<branch_type>(br); + for (int depth = 1; depth <= branches[br].depth; ++depth) + { + you.your_level = absdungeon_depth(branch, depth); + you.where_are_you = branch; + you.level_type = LEVEL_DUNGEON; + + mesclr(); + mprf("On %s (%d); %d levels, %d failed, %d errors%s, %d maps", + level_id::current().describe().c_str(), niters, + mg_levels_tried, mg_levels_failed, mapgen_errors.size(), + mapgen_last_error.empty()? "" + : (" (" + mapgen_last_error + ")").c_str(), + mapgen_use_count.size()); + + no_messages mx; + for (int i = 0; i < niters; ++i) + { + if (kbhit() && getch() == ESCAPE) + return; + ++mg_levels_tried; + if (!builder(you.your_level, you.level_type)) + ++mg_levels_failed; + } + } + } +} + +void mapgen_report_map_try(const map_def &map) +{ + mapgen_try_count[map.name]++; + mapgen_level_maps[level_id::current()]++; +} + +void mapgen_report_map_use(const map_def &map) +{ + mapgen_use_count[map.name]++; +} + +void mapgen_report_error(const map_def &map, const std::string &err) +{ + mapgen_last_error = err; +} + +static void write_mapgen_stats() +{ + FILE *outf = fopen("mapgen.log", "w"); + fprintf(outf, "Map Generation Stats\n\n"); + fprintf(outf, "Levels attempted: %d, built: %d, failed: %d\n", + mg_levels_tried, mg_levels_tried - mg_levels_failed, + mg_levels_failed); + + if (!mapgen_errors.empty()) + { + fprintf(outf, "\n\nMap errors:\n"); + for (std::map<std::string, std::string>::const_iterator i = + mapgen_errors.begin(); i != mapgen_errors.end(); ++i) + { + fprintf(outf, "%s: %s\n", + i->first.c_str(), i->second.c_str()); + } + } + + std::vector<level_id> mapless; + for (int i = BRANCH_MAIN_DUNGEON; i < NUM_BRANCHES; ++i) + { + if (branches[i].depth == -1) + continue; + + const branch_type br = static_cast<branch_type>(i); + for (int dep = 1; dep <= branches[i].depth; ++i) + { + const level_id lid(br, dep); + if (mapgen_level_maps.find(lid) == mapgen_level_maps.end()) + mapless.push_back(lid); + } + } + + if (!mapless.empty()) + { + fprintf(outf, "\n\nLevels with no maps:\n"); + for (int i = 0, size = mapless.size(); i < size; ++i) + fprintf(outf, "%d) %s\n", i + 1, mapless[i].describe().c_str()); + } + + fprintf(outf, "\n\nMaps used:\n\n"); + std::multimap<int, std::string> usedmaps; + for (std::map<std::string, int>::const_iterator i = + mapgen_try_count.begin(); i != mapgen_try_count.end(); ++i) + usedmaps.insert(std::pair<int, std::string>(i->second, i->first)); + + for (std::multimap<int, std::string>::const_reverse_iterator i = + usedmaps.rbegin(); i != usedmaps.rend(); ++i) + { + const int tries = i->first; + std::map<std::string, int>::const_iterator iuse = + mapgen_use_count.find(i->second); + const int uses = iuse == mapgen_use_count.end()? 0 : iuse->second; + if (tries == uses) + fprintf(outf, "%4d : %s\n", tries, i->second.c_str()); + else + fprintf(outf, "%4d (%4d): %s\n", uses, tries, i->second.c_str()); + } + fclose(outf); +} + +void generate_map_stats() +{ + // We have to run map preludes ourselves. + run_map_preludes(); + mg_build_levels(SysEnv.map_gen_iters); + write_mapgen_stats(); +} + +#endif // DEBUG_DIAGNOSTICS diff --git a/crawl-ref/source/debug.h b/crawl-ref/source/debug.h index 3e647052df..fe9efa0340 100644 --- a/crawl-ref/source/debug.h +++ b/crawl-ref/source/debug.h @@ -152,4 +152,12 @@ void debug_set_stats( void ); void debug_card(); +#ifdef DEBUG_DIAGNOSTICS +void generate_map_stats(); +class map_def; +void mapgen_report_map_try(const map_def &map); +void mapgen_report_map_use(const map_def &map); +void mapgen_report_error(const map_def &map, const std::string &err); +#endif + #endif diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 6ef81ba2d4..b7229487e3 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -233,7 +233,7 @@ static void place_altars() /********************************************************************** * builder() - kickoff for the dungeon generator. *********************************************************************/ -void builder(int level_number, int level_type) +bool builder(int level_number, int level_type) { // N tries to build the level, after which we bail with a capital B. int tries = 20; @@ -243,13 +243,17 @@ void builder(int level_number, int level_type) build_dungeon_level(level_number, level_type); if (!dgn_level_vetoed && valid_dungeon_level(level_number, level_type)) - return; + return (true); } - // Failed to build level, bail out. - save_game(true, - make_stringf("Unable to generate level for '%s'!", - level_id::current().describe().c_str()).c_str()); + if (!crawl_state.map_stat_gen) + { + // Failed to build level, bail out. + save_game(true, + make_stringf("Unable to generate level for '%s'!", + level_id::current().describe().c_str()).c_str()); + } + return (false); } static void mask_vault(const vault_placement &place, unsigned mask) diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h index 60d953c931..8912d1d252 100644 --- a/crawl-ref/source/dungeon.h +++ b/crawl-ref/source/dungeon.h @@ -110,7 +110,7 @@ struct dgn_region bool overlaps(const map_mask &dgn_map_mask) const; }; -void builder(int level_number, int level_type); +bool builder(int level_number, int level_type); void define_zombie(int mid, int ztype, int cs, int power); bool is_wall(int feature); bool place_specific_trap(int spec_x, int spec_y, trap_type spec_type); diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index 994fa1dd22..8477dfad3a 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -1278,8 +1278,10 @@ struct game_state bool saving_game; // Set to true while in save_game. bool updating_scores; // Set to true while updating hiscores. - int seen_hups; // Set to true if SIGHUP received. + int seen_hups; // Set to true if SIGHUP received. + bool map_stat_gen; // Set if we're generating stats on maps. + bool unicode_ok; // Is unicode support available? std::string (*glyph2strfn)(unsigned glyph); @@ -1290,9 +1292,9 @@ struct game_state game_state() : mouse_enabled(false), waiting_for_command(false), terminal_resized(false), io_inited(false), need_save(false), saving_game(false), updating_scores(false), - seen_hups(0), unicode_ok(false), glyph2strfn(NULL), - multibyte_strlen(NULL), terminal_resize_handler(NULL), - terminal_resize_check(NULL) + seen_hups(0), map_stat_gen(false), unicode_ok(false), + glyph2strfn(NULL), multibyte_strlen(NULL), + terminal_resize_handler(NULL), terminal_resize_check(NULL) { } @@ -1351,6 +1353,8 @@ struct system_environment std::string scorefile; std::vector<std::string> cmd_args; + + int map_gen_iters; }; extern system_environment SysEnv; diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 73b10fc005..82d888ed4f 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -586,7 +586,7 @@ void game_options::reset_options() prev_weapon = WPN_UNKNOWN; prev_book = SBT_NO_SELECTION; prev_randpick = false; - remember_name = false; + remember_name = true; #ifdef USE_ASCII_CHARACTERS char_set = CSET_ASCII; @@ -2548,6 +2548,7 @@ enum commandline_option_type { CLO_SCOREFILE, CLO_MORGUE, CLO_MACRO, + CLO_MAPSTAT, CLO_NOPS }; @@ -2555,7 +2556,7 @@ enum commandline_option_type { static const char *cmd_ops[] = { "scores", "name", "race", "class", "pizza", "plain", "dir", "rc", "tscores", "vscores", "scorefile", "morgue", - "macro" }; + "macro", "mapstat" }; const int num_cmd_ops = CLO_NOPS; bool arg_seen[num_cmd_ops]; @@ -2671,6 +2672,20 @@ bool parse_args( int argc, char **argv, bool rc_only ) } break; + case CLO_MAPSTAT: + crawl_state.map_stat_gen = true; + if (next_is_param) + { + SysEnv.map_gen_iters = atoi(next_arg); + if (SysEnv.map_gen_iters < 1) + SysEnv.map_gen_iters = 1; + else if (SysEnv.map_gen_iters > 10000) + SysEnv.map_gen_iters = 10000; + } + else + SysEnv.map_gen_iters = 100; + break; + case CLO_MACRO: if (!next_is_param) return (false); @@ -2708,9 +2723,6 @@ bool parse_args( int argc, char **argv, bool rc_only ) if (!next_is_param) return (false); - // if (strlen(next_arg) != 1) - // return (false); - if (!rc_only) { if (o == 2) diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index d2d63f6eef..a71392ce46 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -63,6 +63,8 @@ int vault_main( #ifdef DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, "Generating level: %s", vdefs[which_vault].name.c_str()); + if (crawl_state.map_stat_gen) + mapgen_report_map_try(vdefs[which_vault]); #endif // first, fill in entirely with walls and null-terminate {dlb}: @@ -78,7 +80,14 @@ int vault_main( // Return value of zero forces dungeon.cc to regenerate the level, except // for branch entry vaults where dungeon.cc just rejects the vault and // places a vanilla entry. - return write_vault( vdefs[which_vault], vgrid, place, avoid ); + const int result = write_vault( vdefs[which_vault], vgrid, place, avoid ); + +#ifdef DEBUG_DIAGNOSTICS + if (crawl_state.map_stat_gen && result > 0) + mapgen_report_map_use(vdefs[which_vault]); +#endif + + return (result); } static int write_vault(map_def &mdef, map_type map, @@ -117,6 +126,10 @@ static bool resolve_map(map_def &map, const map_def &original) std::string err = map.run_lua(true); if (!err.empty()) { +#ifdef DEBUG_DIAGNOSTICS + if (crawl_state.map_stat_gen) + mapgen_report_error(map, err); +#endif mprf(MSGCH_WARN, "Lua error: %s", err.c_str()); return (false); } |