From 673bdae75485d14f759af597c3c62b99601f9a43 Mon Sep 17 00:00:00 2001 From: peterb12 Date: Thu, 21 Jul 2005 02:34:44 +0000 Subject: Initial revision git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3 c06c8d41-db1a-0410-9941-cceddc491573 --- trunk/source/chardump.cc | 893 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 893 insertions(+) create mode 100644 trunk/source/chardump.cc (limited to 'trunk/source/chardump.cc') diff --git a/trunk/source/chardump.cc b/trunk/source/chardump.cc new file mode 100644 index 0000000000..7131da279a --- /dev/null +++ b/trunk/source/chardump.cc @@ -0,0 +1,893 @@ +/* + * File: chardump.cc + * Summary: Dumps character info out to the morgue file. + * Written by: Linley Henzell + * + * Change History (most recent first): + * + * + * <4> 19 June 2000 GDL Changed handles to FILE * + * <3> 6/13/99 BWR Improved spell listing + * <2> 5/30/99 JDJ dump_spells dumps failure rates (from Brent). + * <1> 4/20/99 JDJ Reformatted, uses string objects, split out 7 + * functions from dump_char, dumps artifact info. + */ + +#include "AppHdr.h" +#include "chardump.h" + +#include +#include +#include +#include +#include +#if !(defined(__IBMCPP__) || defined(__BCPLUSPLUS__)) +#include +#endif +#include + +#ifdef USE_EMX +#include +#endif + +#ifdef OS9 +#include +#else +#include +#endif + +#ifdef DOS +#include +#endif + +#include "externs.h" + +#include "debug.h" +#include "describe.h" +#include "itemname.h" +#include "items.h" +#include "macro.h" +#include "mutation.h" +#include "player.h" +#include "religion.h" +#include "shopping.h" +#include "skills2.h" +#include "spl-book.h" +#include "spl-cast.h" +#include "spl-util.h" +#include "stuff.h" +#include "version.h" + + + // ======================================================================== + // Internal Functions + // ======================================================================== + + // fillstring() is a hack to get around a missing constructor in + // Borland C++ implementation of the STD basic_string. Argh!!! +static std::string fillstring(size_t strlen, char filler) +{ + std::string s; + + for (size_t i=0; i= 79) + { + outStr += EOL; + outStr += fillstring(kIndent, ' '); + lineLen = kIndent; + + } + else if (lineLen > 0) + { + outStr += ch; + ++lineLen; + } + ++i; + } + else + { + std::string word; + + while (i < (long) inStr.length() + && lineLen + (long) word.length() < 79 + && !isspace(inStr[i]) && inStr[i] != '$') + { + word += inStr[i++]; + } + + if (lineLen + word.length() >= 79) + { + outStr += EOL; + outStr += fillstring(kIndent, ' '); + lineLen = kIndent; + } + + outStr += word; + lineLen += word.length(); + } + } + + outStr += EOL; + + return (outStr); +} // end munge_description() + + //--------------------------------------------------------------- + // + // dump_stats + // + //--------------------------------------------------------------- +static void dump_stats( std::string & text ) +{ + char st_prn[20]; + + text += you.your_name; + text += " the "; + + text += player_title(); + text += " ("; + text += species_name(you.species, you.experience_level); + text += ")"; + text += EOL; + + text += "(Level "; + itoa(you.experience_level, st_prn, 10); + text += st_prn; + text += " "; + text += you.class_name; + text += ")"; + text += EOL EOL; + + if (you.real_time != -1) + { + const time_t curr = you.real_time + (time(NULL) - you.start_time); + char buff[200]; + + make_time_string( curr, buff, sizeof(buff) ); + + text += "Play time: "; + text += buff; + + text += " Number of turns: "; + itoa( you.num_turns, st_prn, 10 ); + text += st_prn; + text += EOL EOL; + } + + text += "Experience : "; + itoa(you.experience_level, st_prn, 10); + text += st_prn; + text += "/"; + itoa(you.experience, st_prn, 10); + text += st_prn; + text += EOL; + + text += "Strength "; + itoa(you.strength, st_prn, 10); + text += st_prn; + if (you.strength < you.max_strength) + { + text += "/"; + itoa(you.max_strength, st_prn, 10); + text += st_prn; + } + + text += " Dexterity "; + itoa(you.dex, st_prn, 10); + text += st_prn; + if (you.dex < you.max_dex) + { + text += "/"; + itoa(you.max_dex, st_prn, 10); + text += st_prn; + } + + text += " Intelligence "; + itoa(you.intel, st_prn, 10); + text += st_prn; + if (you.intel < you.max_intel) + { + text += "/"; + itoa(you.max_intel, st_prn, 10); + text += st_prn; + } + text += EOL; + + text += "Hit Points : "; + itoa(you.hp, st_prn, 10); + text += st_prn; + + int max_max_hp = you.hp_max + player_rotted(); + + if (you.hp < you.hp_max || max_max_hp != you.hp_max) + { + text += "/"; + itoa(you.hp_max, st_prn, 10); + text += st_prn; + + if (max_max_hp != you.hp_max) + { + text += " ("; + itoa(max_max_hp, st_prn, 10); + text += st_prn; + text += ")"; + } + + if (you.hp < 1) + { + text += " "; + text += ((!you.deaths_door) ? "(dead)" : "(almost dead)"); + } + } + + text += " Magic Points : "; + itoa(you.magic_points, st_prn, 10); + text += st_prn; + if (you.magic_points < you.max_magic_points) + { + text += "/"; + itoa(you.max_magic_points, st_prn, 10); + text += st_prn; + } + text += EOL; + + text += "AC : "; + itoa(player_AC(), st_prn, 10); + text += st_prn; + + text += " Evasion : "; + itoa(player_evasion(), st_prn, 10); + text += st_prn; + + text += " Shield : "; + itoa(player_shield_class(), st_prn, 10); + text += st_prn; + text += EOL; + + text += "GP : "; + itoa( you.gold, st_prn, 10 ); + text += st_prn; + text += EOL; + text += EOL; +} // end dump_stats() + + //--------------------------------------------------------------- + // + // dump_location + // + //--------------------------------------------------------------- +static void dump_location( std::string & text ) +{ + if (you.level_type != LEVEL_DUNGEON || you.your_level != -1) + text += "You are "; + + if (you.level_type == LEVEL_PANDEMONIUM) + text += "in Pandemonium"; + else if (you.level_type == LEVEL_ABYSS) + text += "in the Abyss"; + else if (you.level_type == LEVEL_LABYRINTH) + text += "in a labyrinth"; + else if (you.where_are_you == BRANCH_DIS) + text += "in Dis"; + else if (you.where_are_you == BRANCH_GEHENNA) + text += "in Gehenna"; + else if (you.where_are_you == BRANCH_VESTIBULE_OF_HELL) + text += "in the Vestibule of Hell"; + else if (you.where_are_you == BRANCH_COCYTUS) + text += "in Cocytus"; + else if (you.where_are_you == BRANCH_TARTARUS) + text += "in Tartarus"; + else if (you.where_are_you == BRANCH_INFERNO) + text += "in the Inferno"; + else if (you.where_are_you == BRANCH_THE_PIT) + text += "in the Pit"; + else if (you.where_are_you == BRANCH_ORCISH_MINES) + text += "in the Mines"; + else if (you.where_are_you == BRANCH_HIVE) + text += "in the Hive"; + else if (you.where_are_you == BRANCH_LAIR) + text += "in the Lair"; + else if (you.where_are_you == BRANCH_SLIME_PITS) + text += "in the Slime Pits"; + else if (you.where_are_you == BRANCH_VAULTS) + text += "in the Vaults"; + else if (you.where_are_you == BRANCH_CRYPT) + text += "in the Crypt"; + else if (you.where_are_you == BRANCH_HALL_OF_BLADES) + text += "in the Hall of Blades"; + else if (you.where_are_you == BRANCH_HALL_OF_ZOT) + text += "in the Hall of Zot"; + else if (you.where_are_you == BRANCH_ECUMENICAL_TEMPLE) + text += "in the Ecumenical Temple"; + else if (you.where_are_you == BRANCH_SNAKE_PIT) + text += "in the Snake Pit"; + else if (you.where_are_you == BRANCH_ELVEN_HALLS) + text += "in the Elven Halls"; + else if (you.where_are_you == BRANCH_TOMB) + text += "in the Tomb"; + else if (you.where_are_you == BRANCH_SWAMP) + text += "in the Swamp"; + else + { + if (you.your_level == -1) + text += "You escaped"; + else + { + text += "on level "; + + char st_prn[20]; + itoa(you.your_level + 1, st_prn, 10); + text += st_prn; + } + } + + text += "."; + text += EOL; +} // end dump_location() + + //--------------------------------------------------------------- + // + // dump_religion + // + //--------------------------------------------------------------- +static void dump_religion( std::string & text ) +{ + if (you.religion != GOD_NO_GOD) + { + text += "You worship "; + text += god_name(you.religion); + text += "."; + text += EOL; + + if (!player_under_penance()) + { + if (you.religion != GOD_XOM) + { // Xom doesn't care + text += god_name(you.religion); + text += " is "; + text += ((you.piety <= 5) ? "displeased" : + (you.piety <= 20) ? "noncommittal" : + (you.piety <= 40) ? "pleased with you" : + (you.piety <= 70) ? "most pleased with you" : + (you.piety <= 100) ? "greatly pleased with you" : + (you.piety <= 130) ? "extremely pleased with you" + : "exalted by your worship"); + text += "."; + text += EOL; + } + } + else + { + text += god_name(you.religion); + text += " is demanding penance."; + text += EOL; + } + } +} // end dump_religion() + + //--------------------------------------------------------------- + // + // dump_inventory + // + //--------------------------------------------------------------- +static void dump_inventory( std::string & text, bool show_prices ) +{ + int i, j; + char temp_id[4][50]; + + std::string text2; + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 50; j++) + { + temp_id[i][j] = 1; + } + } + + char st_pass[ ITEMNAME_SIZE ] = ""; + int inv_class2[OBJ_GOLD]; + int inv_count = 0; + char tmp_quant[20]; + + for (i = 0; i < OBJ_GOLD; i++) + { + inv_class2[i] = 0; + } + + for (i = 0; i < ENDOFPACK; i++) + { + if (is_valid_item( you.inv[i] )) + { + // adds up number of each class in invent. + inv_class2[you.inv[i].base_type]++; + inv_count++; + } + } + + if (!inv_count) + { + text += "You aren't carrying anything."; + text += EOL; + } + else + { + text += " Inventory:"; + text += EOL; + + for (i = 0; i < OBJ_GOLD; i++) + { + if (inv_class2[i] != 0) + { + switch (i) + { + case OBJ_WEAPONS: text += "Hand weapons"; break; + case OBJ_MISSILES: text += "Missiles"; break; + case OBJ_ARMOUR: text += "Armour"; break; + case OBJ_WANDS: text += "Magical devices"; break; + case OBJ_FOOD: text += "Comestibles"; break; + case OBJ_SCROLLS: text += "Scrolls"; break; + case OBJ_JEWELLERY: text += "Jewellery"; break; + case OBJ_POTIONS: text += "Potions"; break; + case OBJ_BOOKS: text += "Books"; break; + case OBJ_STAVES: text += "Magical staves"; break; + case OBJ_ORBS: text += "Orbs of Power"; break; + case OBJ_MISCELLANY: text += "Miscellaneous"; break; + case OBJ_CORPSES: text += "Carrion"; break; + + default: + DEBUGSTR("Bad item class"); + } + text += EOL; + + for (j = 0; j < ENDOFPACK; j++) + { + if (is_valid_item(you.inv[j]) && you.inv[j].base_type == i) + { + text += " "; + + in_name( j, DESC_INVENTORY_EQUIP, st_pass ); + text += st_pass; + + inv_count--; + + if (show_prices) + { + text += " ("; + + itoa( item_value( you.inv[j], temp_id, true ), + tmp_quant, 10 ); + + text += tmp_quant; + text += " gold)"; + } + + if (is_dumpable_artifact( you.inv[j], + Options.verbose_dump )) + { + text2 = get_item_description( you.inv[j], + Options.verbose_dump, + true ); + + text += munge_description(text2); + } + else + { + text += EOL; + } + } + } + } + } + } +} // end dump_inventory() + +//--------------------------------------------------------------- +// +// dump_skills +// +//--------------------------------------------------------------- +static void dump_skills( std::string & text ) +{ + char tmp_quant[20]; + + text += EOL; + text += EOL; + text += " Skills:"; + text += EOL; + + for (unsigned char i = 0; i < 50; i++) + { + if (you.skills[i] > 0) + { + text += ( (you.skills[i] == 27) ? " * " : + (you.practise_skill[i]) ? " + " + : " - " ); + + text += "Level "; + itoa( you.skills[i], tmp_quant, 10 ); + text += tmp_quant; + text += " "; + text += skill_name(i); + text += EOL; + } + } + + text += EOL; + text += EOL; +} // end dump_skills() + +//--------------------------------------------------------------- +// +// Return string of the i-th spell type, with slash if required +// +//--------------------------------------------------------------- +static std::string spell_type_name(int spell_class, bool slash) +{ + std::string ret; + + if (slash) + ret = "/"; + + ret += spelltype_name(spell_class); + + return (ret); +} // end spell_type_name() + +//--------------------------------------------------------------- +// +// dump_spells +// +//--------------------------------------------------------------- +static void dump_spells( std::string & text ) +{ + char tmp_quant[20]; + +// This array helps output the spell types in the traditional order. +// this can be tossed as soon as I reorder the enum to the traditional order {dlb} + const int spell_type_index[] = { + SPTYP_HOLY, + SPTYP_POISON, + SPTYP_FIRE, + SPTYP_ICE, + SPTYP_EARTH, + SPTYP_AIR, + SPTYP_CONJURATION, + SPTYP_ENCHANTMENT, + SPTYP_DIVINATION, + SPTYP_TRANSLOCATION, + SPTYP_SUMMONING, + SPTYP_TRANSMIGRATION, + SPTYP_NECROMANCY, + 0 + }; + + int spell_levels = player_spell_levels(); + + if (spell_levels == 1) + text += "You have one spell level left."; + else if (spell_levels == 0) + text += "You cannot memorise any spells."; + else + { + text += "You have "; + itoa( spell_levels, tmp_quant, 10 ); + text += tmp_quant; + text += " spell levels left."; + } + + text += EOL; + + if (!you.spell_no) + { + text += "You don't know any spells."; + text += EOL; + + } + else + { + text += "You know the following spells:" EOL; + text += EOL; + + text += " Your Spells Type Success Level" EOL; + + for (int j = 0; j < 52; j++) + { + const char letter = index_to_letter( j ); + const int spell = get_spell_by_letter( letter ); + + if (spell != SPELL_NO_SPELL) + { + std::string spell_line = " "; + + char strng[2]; + strng[0] = letter; + strng[1] = '\0'; + + spell_line += strng; + spell_line += " - "; + spell_line += spell_title( spell ); + + for (int i = spell_line.length(); i < 34; i++) + { + spell_line += ' '; + } + + bool already = false; + + for (int i = 0; spell_type_index[i] != 0; i++) + { + if (spell_typematch( spell, spell_type_index[i] )) + { + spell_line += + spell_type_name(spell_type_index[i], already); + already = true; + } + } + + for (int i = spell_line.length(); i < 58; i++) + { + spell_line += ' '; + } + + int fail_rate = spell_fail( spell ); + + spell_line += (fail_rate == 100) ? "Useless" : + (fail_rate > 90) ? "Terrible" : + (fail_rate > 80) ? "Cruddy" : + (fail_rate > 70) ? "Bad" : + (fail_rate > 60) ? "Very Poor" : + (fail_rate > 50) ? "Poor" : + (fail_rate > 40) ? "Fair" : + (fail_rate > 30) ? "Good" : + (fail_rate > 20) ? "Very Good" : + (fail_rate > 10) ? "Great" : + (fail_rate > 0) ? "Excellent" + : "Perfect"; + + for (int i = spell_line.length(); i < 70; i++) + spell_line += ' '; + + itoa((int) spell_difficulty( spell ), tmp_quant, 10 ); + spell_line += tmp_quant; + spell_line += EOL; + + text += spell_line; + } + } + } +} // end dump_spells() + +//--------------------------------------------------------------- +// +// dump_mutations +// +//--------------------------------------------------------------- +static void dump_mutations( std::string & text ) +{ + // Can't use how_mutated() here, as it doesn't count demonic powers + int xz = 0; + + for (int xy = 0; xy < 100; xy++) + { + if (you.mutation[xy] > 0) + xz++; + } + + if (xz > 0) + { + text += ""; + text += EOL; + text += " Mutations & Other Weirdness"; + text += EOL; + + for (int j = 0; j < 100; j++) + { + if (you.mutation[j]) + { + if (you.demon_pow[j] > 0) + text += "* "; + + text += mutation_name(j); + text += EOL; + } + } + } +} // end dump_mutations() + +#if MAC +#pragma mark - +#endif + +// ======================================================================== +// Public Functions +// ======================================================================== + +//--------------------------------------------------------------- +// +// dump_char +// +// Creates a disk record of a character. Returns true if the +// character was successfully saved. +// +//--------------------------------------------------------------- +bool dump_char( const char fname[30], bool show_prices ) // $$$ a try block? +{ + bool succeeded = false; + + std::string text; + + // start with enough room for 100 80 character lines + text.reserve(100 * 80); + + text += " Dungeon Crawl version " VERSION " character file."; + text += EOL; + text += EOL; + + dump_stats(text); + dump_location(text); + dump_religion(text); + + switch (you.burden_state) + { + case BS_OVERLOADED: + text += "You are overloaded with stuff."; + text += EOL; + break; + case BS_ENCUMBERED: + text += "You are encumbered."; + text += EOL; + break; + } + + text += "You are "; + + text += ((you.hunger <= 1000) ? "starving" : + (you.hunger <= 2600) ? "hungry" : + (you.hunger < 7000) ? "not hungry" : + (you.hunger < 11000) ? "full" : "completely stuffed"); + + text += "."; + text += EOL; + text += EOL; + + if (you.attribute[ATTR_TRANSFORMATION]) + { + switch (you.attribute[ATTR_TRANSFORMATION]) + { + case TRAN_SPIDER: + text += "You are in spider-form."; + break; + case TRAN_BLADE_HANDS: + text += "Your hands are blades."; + break; + case TRAN_STATUE: + text += "You are a stone statue."; + break; + case TRAN_ICE_BEAST: + text += "You are a creature of crystalline ice."; + break; + case TRAN_DRAGON: + text += "You are a fearsome dragon!"; + break; + case TRAN_LICH: + text += "You are in lich-form."; + break; + case TRAN_SERPENT_OF_HELL: + text += "You are a huge, demonic serpent!"; + break; + case TRAN_AIR: + text += "You are a cloud of diffuse gas."; + break; + } + + text += EOL; + text += EOL; + } + + dump_inventory(text, show_prices); + + char tmp_quant[20]; + + text += EOL; + text += EOL; + text += " You have "; + itoa( you.exp_available, tmp_quant, 10 ); + text += tmp_quant; + text += " experience left."; + + dump_skills(text); + dump_spells(text); + dump_mutations(text); + + char file_name[kPathLen] = "\0"; + + if (SysEnv.crawl_dir) + strncpy(file_name, SysEnv.crawl_dir, kPathLen); + + strncat(file_name, fname, kPathLen); + + if (strcmp(fname, "morgue.txt") != 0) + strncat(file_name, ".txt", kPathLen); + + FILE *handle = fopen(file_name, "wb"); + +#if DEBUG_DIAGNOSTICS + strcpy( info, "File name: " ); + strcat( info, file_name ); + mpr( info, MSGCH_DIAGNOSTICS ); +#endif + + if (handle != NULL) + { + size_t begin = 0; + size_t end = text.find(EOL); + + while (end != std::string::npos) + { + end += strlen(EOL); + + size_t len = end - begin; + + if (len > 80) + len = 80; + + fwrite(text.c_str() + begin, len, 1, handle); + + begin = end; + end = text.find(EOL, end); + } + + fclose(handle); + succeeded = true; + } + else + mpr("Error opening file."); + + return (succeeded); +} // end dump_char() -- cgit v1.2.3-54-g00ecf