summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-03-25 08:58:25 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-03-25 08:58:25 +0000
commitec685f4e71424403b322d3971ac68b31821fe7e1 (patch)
tree11a11f0c7214a74048bcfa0a013a8b7beba204cf
parenteb51ffff58cbb272a5332f946ca9ca903ec4695e (diff)
downloadcrawl-ref-ec685f4e71424403b322d3971ac68b31821fe7e1.tar.gz
crawl-ref-ec685f4e71424403b322d3971ac68b31821fe7e1.zip
Cleaned up hiscores xlog format (suggested by Shawn Moore). Breaks compatbility
with older xlogfiles. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1093 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/externs.h116
-rw-r--r--crawl-ref/source/hiscores.cc425
-rw-r--r--crawl-ref/source/hiscores.h139
-rw-r--r--crawl-ref/source/libutil.cc16
-rw-r--r--crawl-ref/source/libutil.h4
5 files changed, 377 insertions, 323 deletions
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 5266b1ba15..b474245858 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1477,122 +1477,6 @@ struct tagHeader
long offset;
};
-struct scorefile_entry
-{
-public:
- char version;
- char release;
- long points;
- std::string name;
- long uid; // for multiuser systems
- char 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 level
- int death_type;
- int death_source; // 0 or monster TYPE
- int mon_num; // sigh...
- std::string death_source_name; // overrides death_source
- std::string auxkilldata; // weapon wielded, spell cast, etc
- char dlvl; // dungeon level (relative)
- char level_type; // what kind of level died on..
- char branch; // dungeon branch
- int final_hp; // actual current HPs (probably <= 0)
- int final_max_hp; // net HPs after rot
- int final_max_max_hp; // gross HPs before rot
- int damage; // damage of final attack
- int str; // final str (useful for nickname)
- int intel; // final int
- int dex; // final dex (useful for nickname)
- int god; // god
- int piety; // piety
- int penance; // penance
- char wiz_mode; // character used wiz mode
- time_t birth_time; // start time of character
- time_t death_time; // end time of character
- long real_time; // real playing time in seconds
- long num_turns; // number of turns taken
- int num_diff_runes; // number of rune types in inventory
- int num_runes; // total number of runes in inventory
-
-public:
- 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 foo
- std::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;
-};
-
extern const struct coord_def Compass[8];
extern const char* god_gain_power_messages[MAX_NUM_GODS][MAX_GOD_ABILITIES];
diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc
index 72d6dbdac2..3455c3d5e1 100644
--- a/crawl-ref/source/hiscores.cc
+++ b/crawl-ref/source/hiscores.cc
@@ -624,10 +624,10 @@ bool scorefile_entry::parse(const std::string &line)
// 4) 0.2 and onwards, which are xlogfile format - no leading
// colon, fields separated by colons, each field specified as
// key=value. Colons are not allowed in key names, must be escaped to
- // | in values. Literal | must be escaped as || in values.
+ // :: in values.
//
// 0.2 only reads entries of type (3) and (4), and only writes entries of
- // type (4).
+ // type (4). 0.3 or 0.4 may discontinue read support for (3).
// Leading colon implies 4.0 style line:
if (line[0] == ':')
@@ -636,148 +636,24 @@ bool scorefile_entry::parse(const std::string &line)
return (parse_scoreline(line));
}
-// xlogfile escape: s/\\/\\\\/g, s/|/\\|/g, s/:/|/g,
-std::string scorefile_entry::xlog_escape(const std::string &s) const
-{
- return
- replace_all_of(
- replace_all_of(
- replace_all_of(s, "\\", "\\\\"),
- "|", "\\|" ),
- ":", "|" );
-}
-
-// xlogfile unescape: s/\\(.)/$1/g, s/|/:/g
-std::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 scorefile_entry::raw_string() const
{
set_score_fields();
if (!fields.get())
return ("");
-
- 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);
+ return fields->xlog_line();
}
bool scorefile_entry::parse_scoreline(const std::string &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));
init_with_fields();
return (true);
}
-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;
- }
-}
-
static const char *short_branch_name(int branch)
{
if (branch >= 0 && branch < NUM_BRANCHES)
@@ -830,113 +706,110 @@ static int str_to_god(const std::string &god)
void scorefile_entry::init_with_fields()
{
- map_fields();
- points = long_field("sc");
- name = str_field("name");
- uid = int_field("uid");
-
- race = str_to_species(str_field("race"));
- cls = get_class_index_by_name(str_field("cls").c_str());
-
- lvl = int_field("xl");
-
- 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");
-
- 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 = 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");
+ points = fields->long_field("sc");
+ name = fields->str_field("name");
+ uid = fields->int_field("uid");
+
+ race = str_to_species(fields->str_field("race"));
+ cls = get_class_index_by_name(fields->str_field("cls").c_str());
+
+ lvl = fields->int_field("xl");
+
+ 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"));
+
+ 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");
+
+ 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");
}
void scorefile_entry::set_score_fields() const
{
- fields.reset(new hs_fields());
+ fields.reset(new xlog_fields);
if (!fields.get())
return;
- 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,
race, str, dex, god ) );
- add_field("ktyp", ::kill_method_name(kill_method_type(death_type)));
- add_field("killer", death_source_desc());
+ fields->add_field("ktyp", ::kill_method_name(kill_method_type(death_type)));
+ fields->add_field("killer", death_source_desc());
- add_auxkill_field();
+ fields->add_field("kaux", "%s", auxkilldata.c_str());
- add_field("place", "%s",
+ fields->add_field("place", "%s",
place_name(get_packed_place(branch, dlvl, level_type),
false, true).c_str());
- add_field("br", "%s", short_branch_name(branch));
- add_field("lvl", "%d", dlvl);
- 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("br", "%s", short_branch_name(branch));
+ fields->add_field("lvl", "%d", dlvl);
+ fields->add_field("ltyp", "%s", level_area_type_name(level_type));
+
+ 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);
// Don't write No God to save some space.
if (god != -1)
- add_field("god", "%s", god == GOD_NO_GOD? "" : god_name(god));
+ fields->add_field("god", "%s", god == GOD_NO_GOD? "" : god_name(god));
if (piety > 0)
- add_field("piety", "%d", piety);
+ fields->add_field("piety", "%d", piety);
if (penance > 0)
- add_field("pen", "%d", penance);
+ fields->add_field("pen", "%d", penance);
if (wiz_mode)
- add_field("wiz", "%d", wiz_mode);
+ fields->add_field("wiz", "%d", wiz_mode);
- 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);
if (num_diff_runes)
- add_field("urune", "%d", num_diff_runes);
+ fields->add_field("urune", "%d", num_diff_runes);
if (num_runes)
- add_field("nrune", "%d", num_runes);
+ fields->add_field("nrune", "%d", num_runes);
#ifdef DGL_EXTENDED_LOGFILES
const std::string short_msg = short_kill_message();
- add_field("tmsg", "%s", short_msg.c_str());
+ fields->add_field("tmsg", "%s", short_msg.c_str());
const std::string long_msg = long_kill_message();
if (long_msg != short_msg)
- add_field("vmsg", "%s", long_msg.c_str());
+ fields->add_field("vmsg", "%s", long_msg.c_str());
#endif
}
@@ -2058,3 +1931,143 @@ scorefile_entry::death_description(death_desc_verbosity verbosity) const
return (desc);
}
+
+//////////////////////////////////////////////////////////////////////////////
+// xlog_fields
+
+xlog_fields::xlog_fields() : fields(), fieldmap()
+{
+}
+
+xlog_fields::xlog_fields(const std::string &line) : fields(), fieldmap()
+{
+ init(line);
+}
+
+std::string::size_type
+xlog_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/:/::/g
+std::string xlog_fields::xlog_escape(const std::string &s) const
+{
+ return replace_all(s, ":", "::");
+}
+
+// xlogfile unescape: s/::/:/g
+std::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);
+}
diff --git a/crawl-ref/source/hiscores.h b/crawl-ref/source/hiscores.h
index 5332b42baf..3acf677c89 100644
--- a/crawl-ref/source/hiscores.h
+++ b/crawl-ref/source/hiscores.h
@@ -12,6 +12,8 @@
#ifndef HISCORES_H
#define HISCORES_H
+struct scorefile_entry;
+
// last updated 16feb2001 {gdl}
/* ***********************************************************************
* called from: ouch
@@ -37,6 +39,141 @@ void hiscores_print_all(int display_count = -1, int format = SCORE_TERSE);
* *********************************************************************** */
std::string hiscores_format_single( const scorefile_entry &se );
std::string hiscores_format_single_long( const scorefile_entry &se,
- 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 systems
+ char 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 level
+ int death_type;
+ int death_source; // 0 or monster TYPE
+ int mon_num; // sigh...
+ std::string death_source_name; // overrides death_source
+ std::string auxkilldata; // weapon wielded, spell cast, etc
+ char dlvl; // dungeon level (relative)
+ char level_type; // what kind of level died on..
+ char branch; // dungeon branch
+ int final_hp; // actual current HPs (probably <= 0)
+ int final_max_hp; // net HPs after rot
+ int final_max_max_hp; // gross HPs before rot
+ int damage; // damage of final attack
+ int str; // final str (useful for nickname)
+ int intel; // final int
+ int dex; // final dex (useful for nickname)
+ int god; // god
+ int piety; // piety
+ int penance; // penance
+ char wiz_mode; // character used wiz mode
+ time_t birth_time; // start time of character
+ time_t death_time; // end time of character
+ long real_time; // real playing time in seconds
+ long num_turns; // number of turns taken
+ int num_diff_runes; // number of rune types in inventory
+ int num_runes; // total number of runes in inventory
+
+public:
+ 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 foo
+ std::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;
+};
#endif // HISCORES_H
diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc
index 0b7772b531..c7e057a9e0 100644
--- a/crawl-ref/source/libutil.cc
+++ b/crawl-ref/source/libutil.cc
@@ -193,6 +193,22 @@ void lowercase(std::string &s)
s[i] = tolower(s[i]);
}
+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);
+}
+
// Replaces all occurrences of any of the characters in tofind with the
// replacement string.
std::string replace_all_of(std::string s,
diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h
index 4e5db549b3..c790705b7d 100644
--- a/crawl-ref/source/libutil.h
+++ b/crawl-ref/source/libutil.h
@@ -33,6 +33,10 @@ std::string strip_filename_unsafe_chars(const std::string &s);
std::string make_stringf(const char *format, ...);
+std::string replace_all(std::string s,
+ const std::string &tofind,
+ const std::string &replacement);
+
std::string replace_all_of(std::string s,
const std::string &tofind,
const std::string &replacement);