with older xlogfiles.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1093 c06c8d41-db1a-0410-9941-cceddc491573
TAVHZJPVNJBZR7CUURAOYNDZPNVQ3AGHTXDEP5K4JGYETBLQJDRQC GNJGG33CNP6IWUW4V2JKIFAC5N43TP5MX4PZOTXROBYZVXQEAJLAC 34C4U6EQWERY75GZJKUCM5KVGU2OUICETS5LGZF6RMKMZT4R5SQAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC LY3EVV7EUNULYH3WSDZDLZYPJM4LHLOJTT3WETKYIJTKUP7UQPZAC RISMOCQM6BKK4XSIRKYLOBB2UPDYJNDAL6OGIIR5GGNZQAK5YSZAC }std::string replace_all(std::string s,const std::string &find,const std::string &repl){std::string::size_type start = 0;std::string::size_type found;while ((found = s.find(find, start)) != std::string::npos){s.replace( found, find.length(), repl );start = found + repl.length();}return (s);
bool verbose = false );
bool verbose = false );class xlog_fields{public:xlog_fields();xlog_fields(const std::string &line);void init(const std::string &line);std::string xlog_line() const;void add_field(const std::string &key,const char *format, ...);std::string str_field(const std::string &) const;int int_field(const std::string &) const;long long_field(const std::string &) const;private:std::string xlog_unescape(const std::string &) const;std::string xlog_escape(const std::string &) const;void map_fields() const;std::string::size_type next_separator(const std::string &s,std::string::size_type start) const;std::vector<std::string> split_fields(const std::string &s) const;private:typedef std::vector< std::pair<std::string, std::string> > xl_fields;typedef std::map<std::string, std::string> xl_map;xl_fields fields;mutable xl_map fieldmap;};struct scorefile_entry{public:char version;char release;long points;std::string name;long uid; // for multiuser systemschar race;char cls;std::string race_class_name; // overrides race & cls if non-empty.char lvl; // player level.char best_skill; // best skill #char best_skill_lvl; // best skill levelint death_type;int death_source; // 0 or monster TYPEint mon_num; // sigh...std::string death_source_name; // overrides death_sourcestd::string auxkilldata; // weapon wielded, spell cast, etcchar dlvl; // dungeon level (relative)char level_type; // what kind of level died on..char branch; // dungeon branchint final_hp; // actual current HPs (probably <= 0)int final_max_hp; // net HPs after rotint final_max_max_hp; // gross HPs before rotint damage; // damage of final attackint str; // final str (useful for nickname)int intel; // final intint dex; // final dex (useful for nickname)int god; // godint piety; // pietyint penance; // penancechar wiz_mode; // character used wiz modetime_t birth_time; // start time of charactertime_t death_time; // end time of characterlong real_time; // real playing time in secondslong num_turns; // number of turns takenint num_diff_runes; // number of rune types in inventoryint num_runes; // total number of runes in inventorypublic:scorefile_entry();scorefile_entry(int damage, int death_source, int death_type,const char *aux, bool death_cause_only = false);scorefile_entry(const scorefile_entry &se);scorefile_entry &operator = (const scorefile_entry &other);void init_death_cause(int damage, int death_source, int death_type,const char *aux);void init();void reset();enum death_desc_verbosity {DDV_TERSE,DDV_ONELINE,DDV_NORMAL,DDV_VERBOSE,DDV_LOGVERBOSE // Semi-verbose for logging purposes};std::string raw_string() const;bool parse(const std::string &line);std::string hiscore_line(death_desc_verbosity verbosity) const;std::string character_description(death_desc_verbosity) const;// Full description of death: Killed by an xyz wielding foostd::string death_description(death_desc_verbosity) const;std::string death_place(death_desc_verbosity) const;std::string game_time(death_desc_verbosity) const;private:mutable std::auto_ptr<xlog_fields> fields;private:std::string single_cdesc() const;std::string strip_article_a(const std::string &s) const;std::string terse_missile_cause() const;std::string terse_missile_name() const;std::string terse_beam_cause() const;std::string terse_wild_magic() const;std::string terse_trap() const;const char *damage_verb() const;const char *death_source_desc() const;std::string damage_string(bool terse = false) const;
bool parse_obsolete_scoreline(const std::string &line);bool parse_scoreline(const std::string &line);void init_with_fields();void add_auxkill_field() const;void set_score_fields() const;std::string short_kill_message() const;std::string long_kill_message() const;std::string make_oneline(const std::string &s) const;void init_from(const scorefile_entry &other);int kludge_branch(int branch_01) const;};
}// xlogfile escape: s/\\/\\\\/g, s/|/\\|/g, s/:/|/g,std::string scorefile_entry::xlog_escape(const std::string &s) const{returnreplace_all_of(replace_all_of(replace_all_of(s, "\\", "\\\\"),"|", "\\|" ),":", "|" );}// xlogfile unescape: s/\\(.)/$1/g, s/|/:/gstd::string scorefile_entry::xlog_unescape(const std::string &s) const{std::string unesc = s;bool escaped = false;for (int i = 0, size = unesc.size(); i < size; ++i){const char c = unesc[i];if (escaped){escaped = false;continue;}if (c == '|')unesc[i] = ':';else if (c == '\\'){escaped = true;unesc.erase(i--, 1);size--;}}return (unesc);
std::string line;for (int i = 0, size = fields->size(); i < size; ++i){const std::pair<std::string, std::string> &f = (*fields)[i];// Don't write empty fields.if (f.second.empty())continue;if (!line.empty())line += ":";
std::vector<std::string> rawfields = split_string(":", line);fields.reset(new hs_fields);for (int i = 0, size = rawfields.size(); i < size; ++i){const std::string field = rawfields[i];std::string::size_type st = field.find('=');if (st == std::string::npos)continue;fields->push_back(std::pair<std::string, std::string>(field.substr(0, st),xlog_unescape(field.substr(st + 1)) ) );}
fields.reset(new xlog_fields(line));
}void scorefile_entry::add_field(const std::string &key,const char *format,...) const{char buf[400];va_list args;va_start(args, format);vsnprintf(buf, sizeof buf, format, args);va_end(args);fields->push_back(std::pair<std::string, std::string>( key, buf ) );}void scorefile_entry::add_auxkill_field() const{add_field("kaux", "%s", auxkilldata.c_str());
void scorefile_entry::read_auxkill_field(){auxkilldata = str_field("kaux");}std::string scorefile_entry::str_field(const std::string &s) const{hs_map::const_iterator i = fieldmap->find(s);if (i == fieldmap->end())return ("");return i->second;}int scorefile_entry::int_field(const std::string &s) const{std::string field = str_field(s);return atoi(field.c_str());}long scorefile_entry::long_field(const std::string &s) const{std::string field = str_field(s);return atol(field.c_str());}void scorefile_entry::map_fields(){fieldmap.reset(new hs_map);for (int i = 0, size = fields->size(); i < size; ++i){const std::pair<std::string, std::string> f = (*fields)[i];(*fieldmap)[f.first] = f.second;}}
best_skill = str_to_skill(str_field("sk"));best_skill_lvl = int_field("sklev");death_type = str_to_kill_method(str_field("ktyp"));death_source_name = str_field("killer");
best_skill = str_to_skill(fields->str_field("sk"));best_skill_lvl = fields->int_field("sklev");death_type = str_to_kill_method(fields->str_field("ktyp"));death_source_name = fields->str_field("killer");auxkilldata = fields->str_field("kaux");branch = str_to_branch(fields->str_field("br"));dlvl = fields->int_field("lvl");level_type = str_to_level_area_type(fields->str_field("ltyp"));
read_auxkill_field();branch = str_to_branch(str_field("br"));dlvl = int_field("lvl");level_type = str_to_level_area_type(str_field("ltyp"));
final_hp = fields->int_field("hp");final_max_hp = fields->int_field("mhp");final_max_max_hp = fields->int_field("mmhp");damage = fields->int_field("dam");str = fields->int_field("str");intel = fields->int_field("int");dex = fields->int_field("dex");
final_hp = int_field("hp");final_max_hp = int_field("mhp");final_max_max_hp = int_field("mmhp");damage = int_field("dam");str = int_field("str");intel = int_field("int");dex = int_field("dex");god = str_to_god(str_field("god"));piety = int_field("piety");penance = int_field("pen");wiz_mode = int_field("wiz");birth_time = parse_time(str_field("start"));death_time = parse_time(str_field("end"));real_time = long_field("dur");num_turns = long_field("turn");num_diff_runes = int_field("urune");num_runes = int_field("nrune");
god = str_to_god(fields->str_field("god"));piety = fields->int_field("piety");penance = fields->int_field("pen");wiz_mode = fields->int_field("wiz");birth_time = parse_time(fields->str_field("start"));death_time = parse_time(fields->str_field("end"));real_time = fields->long_field("dur");num_turns = fields->long_field("turn");num_diff_runes = fields->int_field("urune");num_runes = fields->int_field("nrune");
add_field("v", VER_NUM);add_field("lv", SCORE_VERSION);add_field("sc", "%ld", points);add_field("name", "%s", name.c_str());add_field("uid", "%d", uid);add_field("race", "%s", species_name(race, lvl));add_field("cls", "%s", get_class_name(cls));add_field("xl", "%d", lvl);add_field("sk", "%s", skill_name(best_skill));add_field("sklev", "%d", best_skill_lvl);add_field("title", "%s", skill_title( best_skill, best_skill_lvl,
fields->add_field("v", VER_NUM);fields->add_field("lv", SCORE_VERSION);fields->add_field("sc", "%ld", points);fields->add_field("name", "%s", name.c_str());fields->add_field("uid", "%d", uid);fields->add_field("race", "%s", species_name(race, lvl));fields->add_field("cls", "%s", get_class_name(cls));fields->add_field("xl", "%d", lvl);fields->add_field("sk", "%s", skill_name(best_skill));fields->add_field("sklev", "%d", best_skill_lvl);fields->add_field("title", "%s", skill_title( best_skill, best_skill_lvl,
add_field("br", "%s", short_branch_name(branch));add_field("lvl", "%d", dlvl);add_field("ltyp", "%s", level_area_type_name(level_type));
fields->add_field("br", "%s", short_branch_name(branch));fields->add_field("lvl", "%d", dlvl);fields->add_field("ltyp", "%s", level_area_type_name(level_type));
add_field("hp", "%d", final_hp);add_field("mhp", "%d", final_max_hp);add_field("mmhp", "%d", final_max_max_hp);add_field("dam", "%d", damage);add_field("str", "%d", str);add_field("int", "%d", intel);add_field("dex", "%d", dex);
fields->add_field("hp", "%d", final_hp);fields->add_field("mhp", "%d", final_max_hp);fields->add_field("mmhp", "%d", final_max_max_hp);fields->add_field("dam", "%d", damage);fields->add_field("str", "%d", str);fields->add_field("int", "%d", intel);fields->add_field("dex", "%d", dex);
add_field("start", "%s", make_date_string(birth_time).c_str());add_field("end", "%s", make_date_string(death_time).c_str());add_field("dur", "%ld", real_time);add_field("turn", "%ld", num_turns);
fields->add_field("start", "%s", make_date_string(birth_time).c_str());fields->add_field("end", "%s", make_date_string(death_time).c_str());fields->add_field("dur", "%ld", real_time);fields->add_field("turn", "%ld", num_turns);
}//////////////////////////////////////////////////////////////////////////////// xlog_fieldsxlog_fields::xlog_fields() : fields(), fieldmap(){}xlog_fields::xlog_fields(const std::string &line) : fields(), fieldmap(){init(line);}std::string::size_typexlog_fields::next_separator(const std::string &s,std::string::size_type start) const{std::string::size_type p = s.find(':', start);if (p != std::string::npos && p < s.length() - 1 && s[p + 1] == ':')return next_separator(s, p + 2);return (p);}std::vector<std::string>xlog_fields::split_fields(const std::string &s) const{std::string::size_type start = 0, end = 0;std::vector<std::string> fs;for ( ; (end = next_separator(s, start)) != std::string::npos;start = end + 1 ){fs.push_back( s.substr(start, end - start) );}if (start < s.length())fs.push_back( s.substr(start) );return (fs);}void xlog_fields::init(const std::string &line){std::vector<std::string> rawfields = split_fields(line);for (int i = 0, size = rawfields.size(); i < size; ++i){const std::string field = rawfields[i];std::string::size_type st = field.find('=');if (st == std::string::npos)continue;fields.push_back(std::pair<std::string, std::string>(field.substr(0, st),xlog_unescape(field.substr(st + 1)) ) );}map_fields();}// xlogfile escape: s/:/::/gstd::string xlog_fields::xlog_escape(const std::string &s) const{return replace_all(s, ":", "::");}// xlogfile unescape: s/::/:/gstd::string xlog_fields::xlog_unescape(const std::string &s) const{return replace_all(s, "::", ":");}void xlog_fields::add_field(const std::string &key,const char *format,...){char buf[500];va_list args;va_start(args, format);vsnprintf(buf, sizeof buf, format, args);va_end(args);fields.push_back(std::pair<std::string, std::string>( key, buf ) );fieldmap[key] = buf;
std::string xlog_fields::str_field(const std::string &s) const{xl_map::const_iterator i = fieldmap.find(s);if (i == fieldmap.end())return ("");return i->second;}int xlog_fields::int_field(const std::string &s) const{std::string field = str_field(s);return atoi(field.c_str());}long xlog_fields::long_field(const std::string &s) const{std::string field = str_field(s);return atol(field.c_str());}void xlog_fields::map_fields() const{fieldmap.clear();for (int i = 0, size = fields.size(); i < size; ++i){const std::pair<std::string, std::string> &f = fields[i];fieldmap[f.first] = f.second;}}std::string xlog_fields::xlog_line() const{std::string line;for (int i = 0, size = fields.size(); i < size; ++i){const std::pair<std::string, std::string> &f = fields[i];// Don't write empty fields.if (f.second.empty())continue;if (!line.empty())line += ":";line += f.first;line += "=";line += xlog_escape(f.second);}return (line);}
};struct scorefile_entry{public:char version;char release;long points;std::string name;long uid; // for multiuser systemschar race;char cls;std::string race_class_name; // overrides race & cls if non-empty.char lvl; // player level.char best_skill; // best skill #char best_skill_lvl; // best skill levelint death_type;int death_source; // 0 or monster TYPEint mon_num; // sigh...std::string death_source_name; // overrides death_sourcestd::string auxkilldata; // weapon wielded, spell cast, etcchar dlvl; // dungeon level (relative)char level_type; // what kind of level died on..char branch; // dungeon branchint final_hp; // actual current HPs (probably <= 0)int final_max_hp; // net HPs after rotint final_max_max_hp; // gross HPs before rotint damage; // damage of final attackint str; // final str (useful for nickname)int intel; // final intint dex; // final dex (useful for nickname)int god; // godint piety; // pietyint penance; // penancechar wiz_mode; // character used wiz modetime_t birth_time; // start time of charactertime_t death_time; // end time of characterlong real_time; // real playing time in secondslong num_turns; // number of turns takenint num_diff_runes; // number of rune types in inventoryint num_runes; // total number of runes in inventorypublic:scorefile_entry();scorefile_entry(int damage, int death_source, int death_type,const char *aux, bool death_cause_only = false);scorefile_entry(const scorefile_entry &se);scorefile_entry &operator = (const scorefile_entry &other);void init_death_cause(int damage, int death_source, int death_type,const char *aux);void init();void reset();enum death_desc_verbosity {DDV_TERSE,DDV_ONELINE,DDV_NORMAL,DDV_VERBOSE,DDV_LOGVERBOSE // Semi-verbose for logging purposes};std::string raw_string() const;bool parse(const std::string &line);std::string hiscore_line(death_desc_verbosity verbosity) const;std::string character_description(death_desc_verbosity) const;// Full description of death: Killed by an xyz wielding foostd::string death_description(death_desc_verbosity) const;std::string death_place(death_desc_verbosity) const;std::string game_time(death_desc_verbosity) const;private:typedef std::vector< std::pair<std::string, std::string> > hs_fields;typedef std::map<std::string, std::string> hs_map;mutable std::auto_ptr<hs_fields> fields;mutable std::auto_ptr<hs_map> fieldmap;private:std::string single_cdesc() const;std::string strip_article_a(const std::string &s) const;std::string terse_missile_cause() const;std::string terse_missile_name() const;std::string terse_beam_cause() const;std::string terse_wild_magic() const;std::string terse_trap() const;const char *damage_verb() const;const char *death_source_desc() const;std::string damage_string(bool terse = false) const;bool parse_obsolete_scoreline(const std::string &line);bool parse_scoreline(const std::string &line);void init_with_fields();void add_field(const std::string &key,const char *format, ...) const;void add_auxkill_field() const;void set_score_fields() const;std::string short_kill_message() const;std::string long_kill_message() const;std::string make_oneline(const std::string &s) const;std::string str_field(const std::string &key) const;int int_field(const std::string &key) const;long long_field(const std::string &key) const;std::string xlog_escape(const std::string &s) const;std::string xlog_unescape(const std::string &s) const;void read_auxkill_field();void map_fields();void init_from(const scorefile_entry &other);int kludge_branch(int branch_01) const;