When crashing, dump information about the current level, and if the crash happens during level generation dump which vaults were placed.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8838 c06c8d41-db1a-0410-9941-cceddc491573
RNIAOCLZYEW5GB7I536HRPYJ7DSDEXITH5RZP5CPKJYHVUTWBKRQC I342SFETG3E6PUDZLBYD6A5REGW75PFYCI5JAR7WVPGTODDGZX2QC 3TEB6EUUYKQ4S6WJHX46OXUM4JPDSGJJNGACT7K7IBZU3L2SVJQAC MI3OUXIF33ZKK7TBGHTRUQXZJINRCEBXNLTMCVHMQITDR4XRFCMAC NVAQAP5YCPRQHJN4UL3ZYNKZLVUUXCPR57VC7SGVPSB3NPM6ORFAC KOMZPTDEZP3P6EWBUECWDY7OWELOUTMAUKNEOJ7PWX5LJBTMRVQAC JM7UAK777RAVDAVLQLEOBRTGNW2B47S5G55XITJXO243IUNZHVYQC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC IB4IOXRL7AMMYTUE7GKYDYI6FE5ZFDIUG7DXAZIRMNEPA7KVSSWQC T2ZYXC5YLXGQUN5R4VRNTQWJDGD3KS3BVS3KAJ4BZ4GXRCQT2SYQC XSENCWVHKZ5NUODAG3ACCDK7SXBPTN4YF6LL4YXCEV557UKXF5TQC 3DQXSE4YGFBBDUWK4YEOFWW4UPWILWELFSLP37SL6BERGAZJC5YAC Q2NUCKXB4P7DHRXY764F5AMEJO436GV74AVVVOAVGNWKLMSVMDNQC NXYLHBIFJ236BL4EPOGKBHEBHZI4ZTLFFTXKQHFYTOSK2FJCBLIQC extern std::string dgn_Build_Method;mprf("dgn_Build_Method = %s", dgn_Build_Method.c_str());mprf("dgn_Layout_Type = %s", dgn_Layout_Type.c_str());extern bool river_level, lake_level, many_pools_level;if (river_level)mpr("river level");if (lake_level)mpr("lake level");if (many_pools_level)mpr("many pools level");std::vector<std::string> vault_names;for (unsigned int i = 0; i < Level_Vaults.size(); i++)vault_names.push_back(Level_Vaults[i].map.name);if (Level_Vaults.size() > 0)mpr_comma_separated_list("Level_Vaults: ", vault_names," and ", ", ", MSGCH_WARN);vault_names.clear();
for (unsigned int i = 0; i < Temp_Vaults.size(); i++)vault_names.push_back(Temp_Vaults[i].map.name);if (Temp_Vaults.size() > 0)mpr_comma_separated_list("Temp_Vaults: ", vault_names," and ", ", ", MSGCH_WARN);
_dump_levgen();
static void _dump_levgen(){if (!Generating_Level)return;extern std::string dgn_Build_Method;mprf("dgn_Build_Method = %s", dgn_Build_Method.c_str());mprf("dgn_Layout_Type = %s", dgn_Layout_Type.c_str());extern bool river_level, lake_level, many_pools_level;if (river_level)mpr("river level");if (lake_level)mpr("lake level");if (many_pools_level)mpr("many pools level");std::vector<std::string> vault_names;for (unsigned int i = 0; i < Level_Vaults.size(); i++)vault_names.push_back(Level_Vaults[i].map.name);if (Level_Vaults.size() > 0)mpr_comma_separated_list("Level_Vaults: ", vault_names," and ", ", ", MSGCH_WARN);vault_names.clear();for (unsigned int i = 0; i < Temp_Vaults.size(); i++)vault_names.push_back(Temp_Vaults[i].map.name);if (Temp_Vaults.size() > 0)mpr_comma_separated_list("Temp_Vaults: ", vault_names," and ", ", ", MSGCH_WARN);}static void _dump_level_info(FILE* file){fprintf(file, "Place info:" EOL);fprintf(file, "your_level = %d, branch = %d, level_type = %d, ""type_name = %s" EOL EOL,you.your_level, (int) you.where_are_you, (int) you.level_type,you.level_type_name.c_str());if (Generating_Level){fprintf(file, EOL "Crashed while generating level." EOL);_dump_levgen();fprintf(file, EOL);}}static void _dump_player(FILE *file){// Only dump player info during arena mode if the player is likely// the cause of the crash.if ((crawl_state.arena || crawl_state.arena_suspended)&& !in_bounds(you.pos()) && you.hp > 0 && you.hp_max > 0&& you.strength > 0 && you.intel > 0 && you.dex > 0){// Arena mode can change behavior of the rest of the code and/or lead// to asserts.crawl_state.arena = false;crawl_state.arena_suspended = false;return;}// Arena mode can change behavior of the rest of the code and/or lead// to asserts.crawl_state.arena = false;crawl_state.arena_suspended = false;fprintf(file, "Player:" EOL);fprintf(file, "{{{{{{{{{{{" EOL);bool name_overrun = true;for (int i = 0; i < kNameLen; i++){if (you.your_name[i] == '\0'){name_overrun = false;break;}}if (name_overrun){fprintf(file, "Player name runs past end of your_name buffer." EOL);you.your_name[kNameLen - 1] = '\0';}
name_overrun = true;for (int i = 0; i < 30; i++){if (you.class_name[i] == '\0'){name_overrun = false;break;}}if (name_overrun){fprintf(file, "class_name runs past end of buffer." EOL);you.class_name[29] = '\0';}fprintf(file, "Name: [%s]" EOL, you.your_name);fprintf(file, "Species: %s" EOL, species_name(you.species, 27).c_str());fprintf(file, "Class: %s" EOL EOL, get_class_name(you.char_class));fprintf(file, "class_name: %s" EOL EOL, you.class_name);fprintf(file, "HP: %d/%d; base: %d/%d" EOL, you.hp, you.hp_max,you.base_hp, you.base_hp2);fprintf(file, "MP: %d/%d; base: %d/%d" EOL,you.magic_points, you.max_magic_points,you.base_magic_points, you.base_magic_points2);fprintf(file, "Stats: %d (%d) %d (%d) %d (%d)" EOL,you.strength, you.max_strength, you.intel, you.max_intel,you.dex, you.max_dex);fprintf(file, "Position: %s, god:%s (%d), turn_is_over: %d, ""banished: %d" EOL,debug_coord_str(you.pos()).c_str(),god_name(you.religion).c_str(), (int) you.religion,(int) you.turn_is_over, (int) you.banished);if (in_bounds(you.pos())){const dungeon_feature_type feat = grd(you.pos());fprintf(file, "Standing on/in/over feature: %s" EOL,raw_feature_description(feat, NUM_TRAPS, true).c_str());}fprintf(file, EOL);if (you.running.runmode != RMODE_NOT_RUNNING){fprintf(file, "Runrest:" EOL);fprintf(file, " mode: %d" EOL, you.running.runmode);fprintf(file, " mp: %d" EOL, you.running.mp);fprintf(file, " hp: %d" EOL, you.running.hp);fprintf(file, " pos: %s" EOL EOL,debug_coord_str(you.running.pos).c_str());}if (you.delay_queue.size() > 0){fprintf(file, "Delayed (%lu):" EOL,(unsigned long) you.delay_queue.size());for (unsigned int i = 0; i < you.delay_queue.size(); i++){const delay_queue_item &item = you.delay_queue[i];fprintf(file, " type: %d", item.type);if (item.type <= DELAY_NOT_DELAYED|| item.type >= NUM_DELAYS){fprintf(file, " <invalid>");}fprintf(file, EOL);fprintf(file, " duration: %d" EOL, item.duration);fprintf(file, " parm1: %d" EOL, item.parm1);fprintf(file, " parm2: %d" EOL, item.parm2);fprintf(file, " started: %d" EOL EOL, (int) item.started);}fprintf(file, EOL);}fprintf(file, "Spell bugs:" EOL);for (size_t i = 0; i < you.spells.size(); i++){const spell_type spell = you.spells[i];if (spell == SPELL_NO_SPELL)continue;if (!is_valid_spell(spell)){fprintf(file, " spell slot #%d: invalid spell #%d" EOL,i, (int) spell);continue;}const unsigned int flags = get_spell_flags(spell);if (flags & SPFLAG_MONSTER)fprintf(file, " spell slot #%d: monster only spell %s" EOL,i, spell_title(spell));else if (flags & SPFLAG_TESTING)fprintf(file, " spell slot #%d: testing spell %s" EOL,i, spell_title(spell));else if (count_bits(get_spell_disciplines(spell)) == 0)fprintf(file, " spell slot #%d: school-less spell %s" EOL,i, spell_title(spell));}fprintf(file, EOL);fprintf(file, "Durations:" EOL);for (int i = 0; i < NUM_DURATIONS; i++){if (you.duration[i] != 0)fprintf(file, " #%d: %d" EOL, i, you.duration[i]);}fprintf(file, EOL);fprintf(file, "Attributes:" EOL);for (int i = 0; i < NUM_ATTRIBUTES; i++){if (you.attribute[i] != 0)fprintf(file, " #%d: %lu" EOL, i, you.attribute[i]);}fprintf(file, EOL);fprintf(file, "Mutations:" EOL);for (int i = 0; i < NUM_MUTATIONS; i++){if (you.mutation[i] > 0)fprintf(file, " #%d: %d" EOL, i, you.mutation[i]);}fprintf(file, EOL);fprintf(file, "Demon mutations:" EOL);for (int i = 0; i < NUM_MUTATIONS; i++){if (you.demon_pow[i] > 0)fprintf(file, " #%d: %d" EOL, i, you.demon_pow[i]);}fprintf(file, EOL);fprintf(file, "Inventory bugs:" EOL);for (int i = 0; i < ENDOFPACK; i++){item_def &item(you.inv[i]);if (item.base_type == OBJ_UNASSIGNED && item.quantity != 0){fprintf(file, " slot #%d: unassigned item has quant %d" EOL,i, item.quantity);continue;}else if (item.base_type != OBJ_UNASSIGNED && item.quantity < 1){const int orig_quant = item.quantity;item.quantity = 1;fprintf(file, " slot #%d: otherwise valid item '%s' has ""invalid quantity %d" EOL,i, item.name(DESC_PLAIN, false, true).c_str(),orig_quant);item.quantity = orig_quant;continue;}else if (!is_valid_item(item))continue;const std::string name = item.name(DESC_PLAIN, false, true);if (item.link != i)fprintf(file, " slot #%d: item '%s' has invalid link %d" EOL,i, name.c_str(), item.link);if (item.slot < 0 || item.slot > 127)fprintf(file, " slot #%d: item '%s' has invalid slot %d" EOL,i, name.c_str(), item.slot);if (!item.pos.equals(-1, -1))fprintf(file, " slot #%d: item '%s' has invalid pos %s" EOL,i, name.c_str(), debug_coord_str(item.pos).c_str());}fprintf(file, EOL);fprintf(file, "Equipment:" EOL);for (int i = 0; i < NUM_EQUIP; i++){char eq = you.equip[i];if (eq == -1)continue;fprintf(file, " eq slot #%d, inv slot #%d", i, (int) eq);if (eq < 0 || eq >= ENDOFPACK){fprintf(file, " <invalid>" EOL);continue;}fprintf(file, ": %s" EOL,you.inv[eq].name(DESC_PLAIN, false, true).c_str());}fprintf(file, EOL);if (in_bounds(you.pos()) && mgrd(you.pos()) != NON_MONSTER){fprintf(file, "Standing on same square as: ");const unsigned short midx = mgrd(you.pos());if (invalid_monster_index(midx))fprintf(file, "invalid monster index %d" EOL, (int) midx);else{const monsters *mon = &menv[midx];fprintf(file, "%s:" EOL, debug_mon_str(mon).c_str());debug_dump_mon(mon, true);}fprintf(file, EOL);}fprintf(file, "}}}}}}}}}}}" EOL EOL);}
if (Generating_Level){fprintf(file, EOL "Crashed while generating level." EOL);fprintf(file, "your_level = %d, level_type = %d, type_name = %s" EOL,you.your_level, you.level_type, you.level_type_name.c_str());
extern std::string dgn_Build_Method;extern bool river_level, lake_level, many_pools_level;fprintf(file, "dgn_Build_Method = %s" EOL, dgn_Build_Method.c_str());fprintf(file, "dgn_Layout_Type = %s" EOL, dgn_Layout_Type.c_str());
// Next information about the level the player is on, plus level// generation info if the crash happened during level generation._dump_level_info(file);
extern bool river_level, lake_level, many_pools_level;if (river_level)fprintf(file, "river level" EOL);if (lake_level)fprintf(file, "lake level" EOL);if (many_pools_level)fprintf(file, "many pools level" EOL);fprintf(file, EOL);}// Dumping the Lua stacks isn't that likely to crash.fprintf(file, "clua stack:" EOL);print_clua_stack();fprintf(file, "dlua stack:" EOL);print_dlua_stack();// Dumping the crawl state is next least likely to cause another crash,// so do that next.crawl_state.dump();// Dump current messages.
// Dumping current messages is unlikely to crash.