and gather statistics on maps used and Lua errors encountered.
To use it, run "crawl -mapstat" with a full-debug build. Output will be mapgen.log in the current directory.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1805 c06c8d41-db1a-0410-9941-cceddc491573
WLX2RQMMOMP2PYPAGJRM4VFD2WTLJTOAZZPPY3MV76FU2EGEJ54QC
PKR7JPAXDEL6NSRX5OO45BXOMJL7IQ3L4JV4O5CF2DQJFBEC2NJAC
OWNMHNCGA5H3A6AULXXW473PKC7N6IINE3LJCB3KCFG2XA3TYCQQC
5V47S4NNTHWTSAHV3YLO2VGH7JTUIYJ3GBPDN5ZM4UQALT2ZEXDQC
C22455VGUQOSUX2OORA32LROFQ7NNYDMD2ZDTTUZSAQLXK4AD6QAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
IVVTHLTTLOP5TSULXJWUSSXHOKYWVU3OWKYVK45A7RIB6V34MYQAC
KCHX2F3JFEWOZT3WMJVZAAQUU2QSZ5Q7RDCD7WUJ7VE65J52JFUQC
WE3JT43OR4L6675GINGU4B3YDBMURJZHDDYY3VLHUJEBAKH2HYEAC
GSQ72ULBSL6WBJZUB3GJKAPQDXZIQV7B2TDBA5OP2WVGHVJMCQFQC
Z3RI4XAN7J2GUABAQ5G6YIOQYMBOAEQFFGRBWHMUEB2A2QYXO5MQC
YRY2TC3VHOYE47M23UJGUWDGF7H7WGU7WLWI4SUNM4EDNTGUPHGAC
PL6I2CMSTHY5ZHWVMIQE5YTM5S5VPKBNZM6QJVHZSSKOJGIJ5W4AC
IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC
NEECVIIAOBP72T6O44DWAA6HFSDY3KSWYCFMKAEMDMVOI7XASD7QC
OYTCBRC7LE44EUVRZVYTOOVKQWJ6P6YE3FXTOGUTNKEMLNWPHKSQC
XY77S75KH5KV54MZVAPMUC64TVRE2QM2KVJAAGJGCIBGQEC5GUTQC
SCWXQW5H65OXUP2MEJ2MEEAVPSRJDT3RQGKYCMKVTORS2334PQSQC
ZJLJGSB2XSBQU42OFQMXL3EG4CXAQGOYAU6YTV2SAWZEJIPFH2CAC
KFZYPFHHOWRUZEK2PW26EI73Z6I6DLHW2YEJV2CB5XBWFRRNBFXQC
DTO3EUKWHZ5RJNGNCFYXSOVTIPVXPP637F2W7WFGYKJ7JK7VNKNQC
Y56C5OMUQ5XF2G6DKDV4R5MED44UOIUPTBBQVWQBUHYIXYA5MOZAC
4JNV6RTRY2UR3PZFMCNPRGCBSUAB7QTXYJCSYBIUAFMCCYVGN6PQC
BUUPPUTWFL2NTMFJWP7LKDXON74CX47E37WDAZ3QI4N55UOUQTXAC
34C4U6EQWERY75GZJKUCM5KVGU2OUICETS5LGZF6RMKMZT4R5SQAC
Y2VKZYSQXLYYQNB6OSQP44IYLT2M56SE2ZW2MHOAZUODKCVDHEAQC
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);
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)
// 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);
#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