Updated unit_types to use t_token...

...in place of std::string and to replace std::map with
boost::unordered_map in the t_move_cost_cache, both to increase speed.
This commit is contained in:
Thonsew 2011-09-08 19:17:31 +00:00
parent 82e7d2c6f8
commit 3a41db7acd
23 changed files with 343 additions and 290 deletions

View file

@ -234,7 +234,7 @@ protected:
private:
const std::string &get_available_for_recruiting(
const team& my_team);
const unit_type *get_unit_type_known(
const unit_type *get_unit_type_known(
const std::string &recruit);
bool test_enough_gold(
const team& my_team,

View file

@ -62,6 +62,7 @@ namespace{
//They allow for fast comparison operations.
static const config::t_token z_chance_to_hit("chance_to_hit", false);
static const config::t_token z_poison("poison", false);
static const config::t_token z_steadfast("steadfast", false);
}
namespace ai {
@ -206,7 +207,7 @@ bool ai_default_recruitment_stage::recruit_usage(const std::string& usage)
const unit_type *ut = unit_types.find(name);
if (!ut) continue;
// If usage is empty consider any unit.
if (usage.empty() || ut->usage() == usage) {
if (usage.empty() || ut->usage() == config::t_token(usage)) {
LOG_AI << name << " considered for " << usage << " recruitment\n";
found = true;
@ -367,7 +368,7 @@ int ai_default_recruitment_stage::average_resistance_against(const unit_type& a,
int sum = 0, weight_sum = 0;
// calculation of the average damage taken
bool steadfast = a.has_ability_by_id("steadfast");
bool steadfast = a.has_ability_by_id(z_steadfast);
bool living = !a.not_living();
const std::vector<attack_type>& attacks = b.attacks();
for (std::vector<attack_type>::const_iterator i = attacks.begin(),

View file

@ -49,6 +49,7 @@ namespace{
static const config::t_token z_chance_to_hit("chance_to_hit", false);
static const config::t_token z_poison("poison", false);
static const config::t_token z_guardian("guardian", false);
static const config::t_token z_steadfast("steadfast", false);
}
@ -320,7 +321,7 @@ bool recruitment_phase::recruit_usage(const std::string& usage)
const unit_type *ut = unit_types.find(name);
if (!ut) continue;
// If usage is empty consider any unit.
if (usage.empty() || ut->usage() == usage) {
if (usage.empty() || ut->usage() == config::t_token(usage)) { ///todo remove when upgrade to t_token
LOG_AI_TESTING_AI_DEFAULT << name << " considered for " << usage << " recruitment\n";
found = true;
@ -412,7 +413,7 @@ int recruitment_phase::average_resistance_against(const unit_type& a, const unit
int sum = 0, weight_sum = 0;
// calculation of the average damage taken
bool steadfast = a.has_ability_by_id("steadfast");
bool steadfast = a.has_ability_by_id(z_steadfast);
bool living = !a.not_living();
const std::vector<attack_type>& attacks = b.attacks();
for (std::vector<attack_type>::const_iterator i = attacks.begin(),

View file

@ -47,6 +47,7 @@ namespace{
static const config::t_token z_chance_to_hit("chance_to_hit", false);
static const config::t_token z_poison("poison", false);
static const config::t_token z_guardian("guardian", false);
static const config::t_token z_steadfast("steadfast", false);
}
namespace ai {
@ -295,7 +296,7 @@ static int average_resistance_against(const unit_type& a, const unit_type& b)
int sum = 0, weight_sum = 0;
// calculation of the average damage taken
bool steadfast = a.has_ability_by_id("steadfast");
bool steadfast = a.has_ability_by_id(z_steadfast);
bool living = !a.not_living();
const std::vector<attack_type>& attacks = b.attacks();
for (std::vector<attack_type>::const_iterator i = attacks.begin(),

View file

@ -135,9 +135,9 @@ int attack_type_callable::do_compare(const formula_callable* callable) const
return static_cast<std::string const &>(att_.type()).compare(att_callable->att_.type());
if ( att_.range() != att_callable->att_.range() )
return att_.range().compare(att_callable->att_.range());
return static_cast<std::string const &>(att_.range()).compare(att_callable->att_.range());
return att_.weapon_specials().compare(att_callable->att_.weapon_specials());
return static_cast<std::string const &>(att_.weapon_specials()).compare(att_callable->att_.weapon_specials());
}
variant unit_callable::get_value(const std::string& key) const
@ -287,13 +287,13 @@ variant unit_type_callable::get_value(const std::string& key) const
} else if(key == "alignment") {
return variant(u_.alignment_id(u_.alignment()));
} else if(key == "abilities") {
std::vector<std::string> abilities = u_.get_ability_list();
std::vector<config::t_token> abilities = u_.get_ability_list();
std::vector<variant> res;
if (abilities.empty())
return variant( &res );
for (std::vector<std::string>::iterator it = abilities.begin(); it != abilities.end(); ++it)
for (std::vector<config::t_token>::iterator it = abilities.begin(); it != abilities.end(); ++it)
{
res.push_back( variant(*it) );
}

View file

@ -71,6 +71,7 @@ static lg::log_domain log_config("config");
namespace{
static const config::t_token z_advance("advance", false);
static const config::t_token z_post_advance("post_advance", false);
static const config::t_token z_leader("leader", false);
}
namespace dialogs
{
@ -79,12 +80,12 @@ int advance_unit_dialog(const map_location &loc)
{
unit_map::iterator u = resources::units->find(loc);
const std::vector<std::string>& options = u->advances_to();
const std::vector<config::t_token>& options = u->advances_to();
std::vector<std::string> lang_options;
std::vector<unit> sample_units;
for(std::vector<std::string>::const_iterator op = options.begin(); op != options.end(); ++op) {
for(std::vector<config::t_token>::const_iterator op = options.begin(); op != options.end(); ++op) {
sample_units.push_back(::get_advanced_unit(*u, *op));
const unit& type = sample_units.back();
@ -194,7 +195,7 @@ bool animate_unit_advancement(const map_location &loc, size_t choice, const bool
return false;
}
const std::vector<std::string>& options = u->advances_to();
const std::vector<config::t_token>& options = u->advances_to();
std::vector<config> mod_options = u->get_modification_advances();
if(choice >= options.size() + mod_options.size()) {
@ -381,13 +382,14 @@ void save_preview_pane::draw_contents()
int ypos = area.y;
const unit_type *leader = unit_types.find(summary["leader"]);
const unit_type *leader = unit_types.find(summary[z_leader].token());
if (leader)
{
#ifdef LOW_MEM
const surface image(image::get_image(leader->image()));
#else
const surface image(image::get_image(leader->image() + "~RC(" + static_cast<std::string const &>(leader->flag_rgb()) + ">1)"));
const surface image(image::get_image(static_cast<std::string const &>(leader->image())
+ "~RC(" + static_cast<std::string const &>(leader->flag_rgb()) + ">1)"));
#endif
if(image != NULL) {
@ -851,7 +853,7 @@ void unit_preview_pane::draw_contents()
<< at_it->num_attacks()
<< " " << at_it->name() << "\n";
text << font::weapon_details
<< " " << string_table["range_" + at_it->range()]
<< " " << string_table["range_" + static_cast<std::string const &>(at_it->range())]
<< font::weapon_details_sep
<< string_table["type_" + static_cast<std::string const &>(at_it->type() )] << "\n";
@ -988,7 +990,7 @@ const unit_types_preview_pane::details unit_types_preview_pane::get_details() co
unit_types.find(t->id(), unit_type::WITHOUT_ANIMATIONS);
std::string mod = "~RC(" + static_cast<std::string const &>(t->flag_rgb()) + ">" + team::get_side_color_index(side_) + ")";
det.image = image::get_image(t->image()+mod);
det.image = image::get_image(static_cast<std::string const &>(t->image()) + mod);
det.name = "";
det.type_name = t->type_name();

View file

@ -1180,13 +1180,13 @@ std::vector<topic> generate_ability_topics(const bool sort_generated)
abil_vecs[0] = &type.abilities();
abil_vecs[1] = &type.adv_abilities();
std::vector<std::string> const* desc_vecs[2];
std::vector<config::t_token> const* desc_vecs[2];
desc_vecs[0] = &type.ability_tooltips();
desc_vecs[1] = &type.adv_ability_tooltips();
for(int i=0; i<2; ++i) {
std::vector<t_string> const& abil_vec = *abil_vecs[i];
std::vector<std::string> const& desc_vec = *desc_vecs[i];
std::vector<config::t_token> const& desc_vec = *desc_vecs[i];
for(size_t j=0; j < abil_vec.size(); ++j) {
t_string const& abil_name = abil_vec[j];
if (ability_description.find(abil_name) == ability_description.end()) {
@ -1362,11 +1362,11 @@ public:
const bool first_reverse_value = true;
bool reverse = first_reverse_value;
do {
std::vector<std::string> adv_units =
std::vector<config::t_token> adv_units =
reverse ? type_.advances_from() : type_.advances_to();
bool first = true;
foreach (const std::string &adv, adv_units)
foreach (const config::t_token &adv, adv_units)
{
const unit_type *type = unit_types.find(adv);
if (!type || type->hide_help()) continue;
@ -1397,7 +1397,7 @@ public:
// Print the race of the unit, cross-reference it to the
// respective topic.
const std::string race_id = type_.race();
const config::t_token race_id = type_.race();
std::string race_name;
if (const unit_race *r = unit_types.find_race(race_id)) {
race_name = r->plural_name();
@ -1405,7 +1405,7 @@ public:
race_name = _ ("race^Miscellaneous");
}
ss << _("Race: ");
ss << "<ref>dst='" << escape("..race_"+race_id) << "' text='" << escape(race_name) << "'</ref>";
ss << "<ref>dst='" << escape("..race_" + static_cast<std::string const &>(race_id )) << "' text='" << escape(race_name) << "'</ref>";
ss << "\n";
// Print the abilities the units has, cross-reference them
@ -1492,7 +1492,7 @@ public:
attack_ss << attack_it->damage() << utils::unicode_en_dash << attack_it->num_attacks() << " " << attack_it->accuracy_parry_description();
push_tab_pair(row, attack_ss.str());
attack_ss.str(clear_stringstream);
push_tab_pair(row, string_table["range_" + (*attack_it).range()]);
push_tab_pair(row, string_table["range_" + static_cast<std::string const &>( (*attack_it).range() )]);
// Show this attack's special, if it has any. Cross
// reference it to the section describing the
// special.
@ -1715,7 +1715,7 @@ void generate_races_sections(const config *help_cfg, section &sec, int level)
section_cfg["id"] = hidden_symbol(hidden) + race_prefix + *it;
std::string title;
if (const unit_race *r = unit_types.find_race(*it)) {
if (const unit_race *r = unit_types.find_race(config::t_token(*it))) {
title = r->plural_name();
} else {
title = _ ("race^Miscellaneous");
@ -1740,7 +1740,7 @@ std::vector<topic> generate_unit_topics(const bool sort_generated, const std::st
{
const unit_type &type = i.second;
if (type.race() != race)
if (type.race() != config::t_token(race))
continue;
UNIT_DESCRIPTION_TYPE desc_type = description_type(type);
if (desc_type != FULL_DESCRIPTION)
@ -1764,7 +1764,7 @@ std::vector<topic> generate_unit_topics(const bool sort_generated, const std::st
std::string race_id = "..race_"+race;
std::string race_name;
std::string race_description;
if (const unit_race *r = unit_types.find_race(race)) {
if (const unit_race *r = unit_types.find_race(config::t_token(race))) {
race_name = r->plural_name();
race_description = r->description();
// if (description.empty()) description = _("No description Available");

View file

@ -144,11 +144,11 @@ void leader_list_manager::update_gender_list(const std::string& leader)
// Make the internationalized titles for each gender, along with the WML ids
if (*i == unit_race::FEMALE) {
gender_ids_.push_back("female");
genders_.push_back(IMAGE_PREFIX + utg.image() + get_RC_suffix(utg.flag_rgb()) +
genders_.push_back(IMAGE_PREFIX + static_cast<std::string const &>( utg.image() ) + get_RC_suffix(utg.flag_rgb()) +
COLUMN_SEPARATOR + _("Female ♀"));
} else {
gender_ids_.push_back("male");
genders_.push_back(IMAGE_PREFIX + utg.image() + get_RC_suffix(utg.flag_rgb()) +
genders_.push_back(IMAGE_PREFIX + static_cast<std::string const &>( utg.image() ) + get_RC_suffix(utg.flag_rgb()) +
COLUMN_SEPARATOR + _("Male ♂"));
}
}
@ -180,8 +180,8 @@ void leader_list_manager::populate_leader_combo(int selected_index) {
if (gender_combo_ != NULL && !genders_.empty() && size_t(gender_combo_->selected()) < genders_.size()) {
gender = gender_ids_[gender_combo_->selected()];
}
const unit_type& ut = utp->get_gender_unit_type(gender);
leader_strings.push_back(IMAGE_PREFIX + ut.image() + get_RC_suffix(ut.flag_rgb()) + COLUMN_SEPARATOR + ut.type_name());
const unit_type& ut = utp->get_gender_unit_type(config::t_token(gender));
leader_strings.push_back(IMAGE_PREFIX + static_cast<std::string const &>(ut.image()) + get_RC_suffix(ut.flag_rgb()) + COLUMN_SEPARATOR + ut.type_name());
} else {
if(*itor == "random") {

View file

@ -205,7 +205,7 @@ connect::side::side(connect& parent, const config& cfg, int index) :
if (!leader_name) {
leader_name_pseudolist.push_back("-");
} else {
leader_name_pseudolist.push_back(leader_name->get_gender_unit_type(gender_).type_name());
leader_name_pseudolist.push_back(leader_name->get_gender_unit_type(config::t_token(gender_)).type_name());
}
}
combo_leader_.set_items(leader_name_pseudolist);

View file

@ -99,7 +99,7 @@ void wait::leader_preview_pane::draw_contents()
const unit_type *ut = unit_types.find(leader);
if (ut) {
const unit_type &utg = ut->get_gender_unit_type(gender);
const unit_type &utg = ut->get_gender_unit_type(config::t_token(gender));
image = utg.image() + leaders_.get_RC_suffix(utg.flag_rgb());
}
@ -475,7 +475,7 @@ void wait::generate_menu()
const unit_type *ut = unit_types.find(leader_type);
if (ut) {
const unit_type &utg = ut->get_gender_unit_type(gender_id);
const unit_type &utg = ut->get_gender_unit_type(config::t_token(gender_id));
leader_name = utg.type_name();
#ifdef LOW_MEM

View file

@ -26,6 +26,28 @@
#include "random.hpp"
#include "simple_rng.hpp"
namespace {
//Static tokens are replacements for string literals in code
//They allow for fast comparison, copying and hashing operations.
static const config::t_token z_trait("trait", false);
static const config::t_token z_topic("topic", false);
static const config::t_token z_empty("", false);
static const config::t_token z_id("id", false);
static const config::t_token z_plural_name("plural_name", false);
static const config::t_token z_description("description", false);
static const config::t_token z_num_traits("num_traits", false);
static const config::t_token z_markov_chain_size("markov_chain_size", false);
static const config::t_token z_ignore_global_traits("ignore_global_traits", false);
static const config::t_token z_name("name", false);
static const config::t_token z_male_name("male_name", false);
static const config::t_token z_female_name("female_name", false);
static const config::t_token z_male_names("male_names", false);
static const config::t_token z_female_names("female_names", false);
static const config::t_token z_female("female", false);
static const config::t_token z_male("male", false);
}
static const config &empty_traits() {
static config cfg;
return cfg;
@ -46,12 +68,12 @@ static void add_prefixes(const wide_string& str, size_t length, markov_prefix_ma
}
}
static markov_prefix_map markov_prefixes(const std::vector<std::string>& items, size_t length)
static markov_prefix_map markov_prefixes(const std::vector<config::t_token>& items, size_t length)
{
markov_prefix_map res;
for(std::vector<std::string>::const_iterator i = items.begin(); i != items.end(); ++i) {
add_prefixes(utils::string_to_wstring(*i),length,res);
for(std::vector<config::t_token>::const_iterator i = items.begin(); i != items.end(); ++i) {
add_prefixes(utils::string_to_wstring( static_cast<std::string const &>(*i) ),length,res);
}
return res;
@ -144,56 +166,55 @@ unit_race::unit_race() :
description_(),
ntraits_(0),
chain_size_(0),
traits_(empty_traits().child_range("trait")),
topics_(empty_topics().child_range("topic")),
traits_(empty_traits().child_range(z_trait)),
topics_(empty_topics().child_range(z_topic)),
global_traits_(true)
{
name_[MALE] = "";
name_[FEMALE] = "";
name_[MALE] = z_empty;
name_[FEMALE] = z_empty;
}
unit_race::unit_race(const config& cfg) :
cfg_(cfg),
id_(cfg["id"]),
plural_name_(cfg["plural_name"].t_str()),
description_(cfg["description"].t_str()),
ntraits_(cfg["num_traits"]),
chain_size_(cfg["markov_chain_size"]),
traits_(cfg.child_range("trait")),
topics_(cfg.child_range("topic")),
global_traits_(!cfg["ignore_global_traits"].to_bool())
id_(cfg[z_id].token()),
plural_name_(cfg[z_plural_name].t_str()),
description_(cfg[z_description].t_str()),
ntraits_(cfg[z_num_traits]),
chain_size_(cfg[z_markov_chain_size]),
traits_(cfg.child_range(z_trait)),
topics_(cfg.child_range(z_topic)),
global_traits_(!cfg[z_ignore_global_traits].to_bool())
{
if (id_.empty()) {
lg::wml_error << "[race] '" << cfg["name"] << "' is missing an id field.";
lg::wml_error << "[race] '" << cfg[z_name] << "' is missing an id field.";
}
if (plural_name_.empty()) {
lg::wml_error << "[race] '" << cfg["name"] << "' is missing a plural_name field.";
plural_name_ = (cfg["name"]);
lg::wml_error << "[race] '" << cfg[z_name] << "' is missing a plural_name field.";
plural_name_ = (cfg[z_name]);
}
// use "name" if "male_name" or "female_name" aren't available
name_[MALE] = cfg["male_name"];
// use z_name if z_male_name or z_female_name aren't available
name_[MALE] = cfg[z_male_name];
if(name_[MALE].empty()) {
name_[MALE] = (cfg["name"]);
name_[MALE] = (cfg[z_name]);
}
name_[FEMALE] = cfg["female_name"];
name_[FEMALE] = cfg[z_female_name];
if(name_[FEMALE].empty()) {
name_[FEMALE] = (cfg["name"]);
name_[FEMALE] = (cfg[z_name]);
}
if(chain_size_ <= 0)
chain_size_ = 2;
//std::vector<std::string> names = ;
next_[MALE] = markov_prefixes(utils::split(cfg["male_names"]), chain_size_);
next_[FEMALE] = markov_prefixes(utils::split(cfg["female_names"]), chain_size_);
next_[MALE] = markov_prefixes(utils::split_token(cfg[z_male_names]), chain_size_);
next_[FEMALE] = markov_prefixes(utils::split_token(cfg[z_female_names]), chain_size_);
}
std::string unit_race::generate_name(
config::t_token unit_race::generate_name(
unit_race::GENDER gender, rand_rng::simple_rng* rng) const
{
return utils::wstring_to_string(
markov_generate_name(next_[gender], chain_size_, 12, rng));
return config::t_token(utils::wstring_to_string(markov_generate_name(next_[gender], chain_size_, 12, rng)) );
}
bool unit_race::uses_global_traits() const
@ -213,9 +234,9 @@ const config::const_child_itors &unit_race::additional_topics() const
unsigned int unit_race::num_traits() const { return ntraits_; }
std::string const& gender_string(unit_race::GENDER gender) {
static const std::string female_string = "female";
static const std::string male_string = "male";
config::t_token const& gender_string(unit_race::GENDER gender) {
static const config::t_token female_string(z_female);
static const config::t_token male_string(z_male);
switch(gender) {
case unit_race::FEMALE:
return female_string;
@ -225,7 +246,7 @@ std::string const& gender_string(unit_race::GENDER gender) {
}
}
unit_race::GENDER string_gender(const std::string& str, unit_race::GENDER def) {
unit_race::GENDER string_gender(const config::t_token& str, unit_race::GENDER def) {
if(str == gender_string(unit_race::MALE)) {
return unit_race::MALE;
} else if(str == gender_string(unit_race::FEMALE)) {

View file

@ -35,23 +35,23 @@ public:
unit_race(const config& cfg);
const config& get_cfg() const { return cfg_; };
const std::string& id() const { return id_; };
const config::t_token& id() const { return id_; };
const t_string& name(GENDER gender=MALE) const { return name_[gender]; };
const t_string& plural_name() const { return plural_name_; };
const t_string& description() const { return description_; };
std::string generate_name(GENDER gender, rand_rng::simple_rng* rng = 0) const;
config::t_token generate_name(GENDER gender, rand_rng::simple_rng* rng = 0) const;
bool uses_global_traits() const;
const config::const_child_itors &additional_traits() const;
const config::const_child_itors &additional_topics() const;
const config::const_child_itors &additional_topics() const;
unsigned int num_traits() const;
private:
const config cfg_;
std::string id_;
config::t_token id_;
t_string name_[NUM_GENDERS];
t_string plural_name_;
t_string description_;
@ -60,13 +60,13 @@ private:
int chain_size_;
config::const_child_itors traits_;
config::const_child_itors topics_;
config::const_child_itors topics_;
bool global_traits_;
};
unit_race::GENDER string_gender(const std::string& str,unit_race::GENDER def=unit_race::MALE);
std::string const& gender_string(unit_race::GENDER gender);
unit_race::GENDER string_gender(const config::t_token& str,unit_race::GENDER def=unit_race::MALE);
config::t_token const& gender_string(unit_race::GENDER gender);
typedef std::map<std::string,unit_race> race_map;
typedef boost::unordered_map<config::t_token,unit_race> race_map;
#endif

View file

@ -162,7 +162,7 @@ REPORT_GENERATOR(unit_race)
std::ostringstream str, tooltip;
str << span_color(font::race_color) << u->race()->name(u->gender()) << naps;
tooltip << _("Race: ") << "<b>" << u->race()->name(u->gender()) << "</b>";
return text_report(str.str(), tooltip.str(), "..race_" + u->race()->id());
return text_report(str.str(), tooltip.str(), "..race_" + static_cast<std::string const &>( u->race()->id()));
}
REPORT_GENERATOR(unit_side)
@ -186,7 +186,7 @@ REPORT_GENERATOR(unit_level)
std::ostringstream str, tooltip;
str << u->level();
tooltip << _("Level: ") << "<b>" << u->level() << "</b>\n";
const std::vector<std::string> &adv_to = u->advances_to();
const std::vector<config::t_token> &adv_to = u->advances_to();
if (adv_to.empty())
tooltip << _("No advancement");
else
@ -488,7 +488,7 @@ REPORT_GENERATOR(unit_weapons)
add_text(res, flush(str), flush(tooltip));
std::string range = string_table["range_" + at.range()];
std::string range = string_table["range_" + static_cast<std::string const &>( at.range())];
std::string lang_type = string_table["type_" + static_cast<std::string const &>( at.type() )];
str << span_color(font::weapon_details_color) << " "

View file

@ -809,6 +809,19 @@ static int impl_vconfig_collect(lua_State *L)
return 1; \
}
#define return_vector_t_token_attrib(name, accessor) \
if (strcmp(m, name) == 0) { \
const std::vector<config::t_token>& vector = accessor; \
lua_createtable(L, vector.size(), 0); \
int i = 1; \
foreach (const config::t_token & s, vector) { \
lua_pushstring(L, s.c_str()); \
lua_rawseti(L, -2, i); \
++i; \
} \
return 1; \
}
#define modify_tstring_attrib(name, accessor) \
if (strcmp(m, name) == 0) { \
t_string value = luaW_checktstring(L, 3); \
@ -861,6 +874,22 @@ static int impl_vconfig_collect(lua_State *L)
accessor; \
return 0; \
}
#define modify_vector_t_token_attrib(name, accessor) \
if (strcmp(m, name) == 0) { \
std::vector<config::t_token> vector; \
char const* message = "table with unnamed indices holding strings expected"; \
if (!lua_istable(L, 3)) return luaL_argerror(L, 3, message); \
unsigned length = lua_objlen(L, 3); \
for (unsigned i = 1; i <= length; ++i) { \
lua_rawgeti(L, 3, i); \
char const* string = lua_tostring(L, 4); \
if(!string) return luaL_argerror(L, 2 + i, message); \
vector.push_back(config::t_token( string )); \
lua_pop(L, 1); \
} \
accessor; \
return 0; \
}
/**
* Gets some data on a unit type (__index metamethod).
@ -899,7 +928,7 @@ static int impl_race_get(lua_State* L)
char const* m = luaL_checkstring(L, 2);
lua_pushstring(L, "id");
lua_rawget(L, 1);
const unit_race* raceptr = unit_types.find_race(lua_tostring(L, -1));
const unit_race* raceptr = unit_types.find_race(config::t_token( lua_tostring(L, -1) ));
if(!raceptr) return luaL_argerror(L, 1, "unknown race");
unit_race const &race = *raceptr;
@ -972,8 +1001,8 @@ static int impl_unit_get(lua_State *L)
return_tstring_attrib("name", u.name());
return_bool_attrib("canrecruit", u.can_recruit());
return_vector_string_attrib("extra_recruit", u.recruits());
return_vector_string_attrib("advances_to", u.advances_to());
return_vector_t_token_attrib("extra_recruit", u.recruits());
return_vector_t_token_attrib("advances_to", u.advances_to());
if (strcmp(m, "status") == 0) {
lua_createtable(L, 1, 0);
@ -1028,8 +1057,8 @@ static int impl_unit_set(lua_State *L)
modify_string_attrib("facing", u.set_facing(map_location::parse_direction(value)));
modify_bool_attrib("hidden", u.set_hidden(value));
modify_vector_string_attrib("extra_recruit", u.set_recruits(vector));
modify_vector_string_attrib("advances_to", u.set_advances_to(vector));
modify_vector_t_token_attrib("extra_recruit", u.set_recruits(vector));
modify_vector_t_token_attrib("advances_to", u.set_advances_to(vector));
if (!lu->on_map()) {
map_location loc = u.get_location();

View file

@ -66,7 +66,7 @@ terrain_type::terrain_type(const config& cfg) :
minimap_image_(cfg["symbol_image"]),
minimap_image_overlay_(),
editor_image_(cfg["editor_image"]),
id_(cfg["id"]),
id_(cfg["id"].token()),
name_(cfg["name"].t_str()),
editor_name_(cfg["editor_name"].t_str()),
description_(cfg["description"].t_str()),

View file

@ -33,6 +33,7 @@ public:
const t_string& editor_name() const { return editor_name_.empty() ? description() : editor_name_; }
const t_string& description() const { return description_.empty() ? name_ : description_; }
const std::string& id() const { return id_; }
const n_token::t_token& idt() const { return id_; }
bool hide_in_editor() const { return hide_in_editor_; }
@ -83,7 +84,7 @@ private:
* initialized with the value of minimap_image_
*/
std::string editor_image_;
std::string id_;
n_token::t_token id_;
t_string name_;
t_string editor_name_;
t_string description_;

View file

@ -18,6 +18,7 @@
#ifndef TERRAIN_TRANSLATION_H_INCLUDED
#define TERRAIN_TRANSLATION_H_INCLUDED
#include <boost/functional/hash.hpp>
#include <SDL_types.h> //used for Uint32 definition
#include <vector>
#include <map>
@ -51,7 +52,9 @@ namespace t_translation {
t_layer base;
t_layer overlay;
};
const t_terrain NONE_TERRAIN = t_terrain();
inline bool operator<(const t_terrain& a, const t_terrain& b)
@ -69,6 +72,12 @@ namespace t_translation {
inline t_terrain operator|(const t_terrain& a, const t_terrain& b)
{ return t_terrain(a.base | b.base, a.overlay | b.overlay); }
inline std::size_t hash_value(t_terrain const& a) {
std::size_t seed = 0;
boost::hash_combine(seed, a.base);
boost::hash_combine(seed, a.overlay);
return seed; }
// operator<< is defined later
typedef std::vector<t_terrain> t_list;

View file

@ -43,6 +43,10 @@ namespace n_token {
Hence use static tokens as replacements for constant string literals in the code, as follows:
static const t_token z_some_string("some_string", false);
@note It is intentionally inconvenient to convert to std::string. Allowing automatic conversion would allow
the compiler to create std::string temporaries and give up the benefits of the t_token. Do not
make a std::string conversion operator.
*/
class t_token : public n_interned::t_interned_token<std::string> {

View file

@ -279,10 +279,10 @@ static unit_race::GENDER generate_gender(const std::string &type_id, bool random
static unit_race::GENDER generate_gender(const config &cfg, game_state *state)
{
const std::string& gender = cfg[z_gender];
const config::t_token& gender = cfg[z_gender];
if(!gender.empty())
return string_gender(gender);
const std::string &type = cfg[z_type];
const config::t_token &type = cfg[z_type];
if (type.empty())
return unit_race::MALE;
@ -523,7 +523,7 @@ unit::unit(const config &cfg, bool use_traits, game_state* state) :
max_movement_ = std::max(0, cfg[z_max_moves].to_int(max_movement_));
max_experience_ = std::max(1, cfg[z_max_experience].to_int(max_experience_));
std::vector<std::string> temp_advances = utils::split(cfg[z_advances_to]);
std::vector<config::t_token> temp_advances = utils::split_token(cfg[z_advances_to]);
if(temp_advances.size() == 1 && temp_advances.front() == z_null) {
advances_to_.clear();
}else if(temp_advances.size() >= 1 && temp_advances.front() != z_empty) {
@ -661,7 +661,7 @@ unit::unit(const config &cfg, bool use_traits, game_state* state) :
cfg_[z_upkeep] = z_full;
}
set_recruits(utils::split(cfg[z_extra_recruit]));
set_recruits(utils::split_token(cfg[z_extra_recruit]));
cfg_.add_child(z_filter_recall, cfg.child_or_empty(z_filter_recall));
/** @todo Are these modified by read? if not they can be removed. */
@ -1171,7 +1171,7 @@ SDL_Color unit::xp_color() const
return(color);
}
void unit::set_recruits(const std::vector<std::string>& recruits)
void unit::set_recruits(const std::vector<config::t_token>& recruits)
{
unit_types.check_types(recruits);
recruit_list_ = recruits;
@ -1180,7 +1180,7 @@ void unit::set_recruits(const std::vector<std::string>& recruits)
//ai::manager::raise_recruit_list_changed();
}
void unit::set_advances_to(const std::vector<std::string>& advances_to)
void unit::set_advances_to(const std::vector<config::t_token>& advances_to)
{
unit_types.check_types(advances_to);
advances_to_ = advances_to;
@ -2238,9 +2238,7 @@ bool unit::loyal() const
int unit::movement_cost(const t_translation::t_terrain terrain, gamemap const & game_map) const
{
//assert(resources::game_map != NULL);
const int res = movement_cost_internal(movement_costs_,
cfg_, NULL, game_map, terrain);
const int res = movement_cost_internal(movement_costs_, cfg_, NULL, game_map, terrain);
if (res == unit_movement_type::UNREACHABLE) {
return res;
@ -2524,11 +2522,11 @@ void unit::add_modification(const config::t_token& type, const config& mod, bool
bool first_attack = true;
std::string attack_names;
std::string desc;
std::pair<bool, config::t_token> affected;
for(std::vector<attack_type>::iterator a = attacks_.begin();
a != attacks_.end(); ++a) {
bool affected = a->apply_modification(effect, &desc);
if(affected && desc != z_empty) {
affected = a->apply_modification(effect);
if(affected.first && affected.second != z_empty) {
if(first_attack) {
first_attack = false;
} else {
@ -2543,7 +2541,7 @@ void unit::add_modification(const config::t_token& type, const config& mod, bool
if (attack_names.empty() == false) {
utils::string_map symbols;
symbols[z_attack_list] = attack_names;
symbols[z_effect_description] = desc;
symbols[z_effect_description] = affected.second;;
description += vgettext("$attack_list|: $effect_description", symbols);
}
} else if(apply_to == z_hitpoints) {
@ -2724,9 +2722,9 @@ void unit::add_modification(const config::t_token& type, const config& mod, bool
for(std::vector<attack_type>::iterator a = attacks_.begin();
a != attacks_.end(); ++a) {
std::string desc;
bool affected = a->describe_modification(effect, &desc);
if(affected && desc != z_empty) {
std::pair<bool, config::t_token> affected = a->describe_modification(effect);
if(affected.first && affected.second != z_empty) {
std::string const & desc = affected.second;
if(first_attack) {
first_attack = false;
} else {

View file

@ -88,8 +88,8 @@ public:
{
advance_to(cfg_, t, use_traits, state);
}
const std::vector<std::string>& advances_to() const { return advances_to_; }
void set_advances_to(const std::vector<std::string>& advances_to);
const std::vector<config::t_token>& advances_to() const { return advances_to_; }
void set_advances_to(const std::vector<config::t_token>& advances_to);
/** The type id of the unit */
const config::t_token& type_id() const { return type_; }
@ -139,9 +139,9 @@ public:
fixed_t alpha() const { return alpha_; }
bool can_recruit() const { return canrecruit_; }
const std::vector<std::string>& recruits() const
const std::vector<config::t_token>& recruits() const
{ return recruit_list_; }
void set_recruits(const std::vector<std::string>& recruits);
void set_recruits(const std::vector<config::t_token>& recruits);
const config& recall_filter() const { return cfg_.child("filter_recall"); }
bool incapacitated() const { return get_state(STATE_PETRIFIED); }
@ -422,7 +422,7 @@ private:
config cfg_;
map_location loc_;
std::vector<std::string> advances_to_;
std::vector<config::t_token> advances_to_;
config::t_token type_;
const unit_race* race_;
config::t_token id_;
@ -438,7 +438,7 @@ private:
int max_experience_;
int level_;
bool canrecruit_;
std::vector<std::string> recruit_list_;
std::vector<config::t_token> recruit_list_;
unit_type::ALIGNMENT alignment_;
config::t_token flag_rgb_;
std::string image_mods_;
@ -456,7 +456,7 @@ private:
int movement_;
int max_movement_;
mutable std::map<t_translation::t_terrain, int> movement_costs_; // movement cost cache
mutable t_move_cost_cache movement_costs_; // movement cost cache
mutable defense_cache defense_mods_; // defense modifiers cache
bool hold_position_;
bool end_turn_;

View file

@ -603,13 +603,13 @@ std::vector<t_string> attack_type::special_tooltips(bool force) const
}
return res;
}
std::string attack_type::weapon_specials(bool force) const
config::t_token attack_type::weapon_specials(bool force) const
{
// log_scope("weapon_specials");
std::string res;
const config &specials = cfg_.child(z_specials);
if (!specials) return res;
if (!specials) return z_empty;
std::string res;
foreach (const config::any_child &sp, specials.all_children_range())
{
config::t_token const *s = force || special_active(sp.cfg, true) ?
@ -617,12 +617,12 @@ std::string attack_type::weapon_specials(bool force) const
config::t_token const &name = sp.cfg[*s];
if (!name.empty()) {
if (!res.empty()) res += ',';
res += name;
if (!res.empty()) { res += ',' ; }
res += static_cast<std::string const &>( name );
}
}
return res;
return config::t_token( res );
}
@ -654,7 +654,7 @@ bool attack_type::special_active(gamemap const & game_map, unit_map const & unit
if(attacker_) {
{
std::string const &active = cfg[z_active_on];
config::t_token const &active = cfg[z_active_on];
if (!active.empty() && active != z_offense)
return false;
}
@ -681,7 +681,7 @@ bool attack_type::special_active(gamemap const & game_map, unit_map const & unit
}
} else {
{
std::string const &active = cfg[z_active_on];
config::t_token const &active = cfg[z_active_on];
if (!active.empty() && active != z_defense)
return false;
}
@ -750,7 +750,7 @@ bool attack_type::special_active(gamemap const & game_map, unit_map const & unit
foreach (const config &i, cfg.child_range(z_filter_adjacent))
{
foreach (const std::string &j, utils::split(i[z_adjacent]))
foreach (const config::t_token &j, utils::split_token(i[z_adjacent]))
{
map_location::DIRECTION index =
map_location::parse_direction(j);
@ -765,7 +765,7 @@ bool attack_type::special_active(gamemap const & game_map, unit_map const & unit
foreach (const config &i, cfg.child_range(z_filter_adjacent_location))
{
foreach (const std::string &j, utils::split(i[z_adjacent]))
foreach (const config::t_token &j, utils::split_token(i[z_adjacent]))
{
map_location::DIRECTION index =
map_location::parse_direction(j);
@ -787,7 +787,7 @@ bool attack_type::special_active(gamemap const & game_map, unit_map const & unit
bool attack_type::special_affects_opponent(const config& cfg) const
{
// log_scope("special_affects_opponent");
std::string const &apply_to = cfg[z_apply_to];
config::t_token const &apply_to = cfg[z_apply_to];
if (apply_to.empty())
return false;
if (apply_to == z_both)
@ -808,7 +808,7 @@ bool attack_type::special_affects_opponent(const config& cfg) const
bool attack_type::special_affects_self(const config& cfg) const
{
// log_scope("special_affects_self");
std::string const &apply_to = cfg[z_apply_to];
config::t_token const &apply_to = cfg[z_apply_to];
if (apply_to.empty())
return true;
if (apply_to == z_both)
@ -880,9 +880,9 @@ effect::effect(const unit_ability_list& list, int def, bool backstab) :
int value_set = def;
bool value_is_set = false;
std::map<std::string,individual_effect> values_add;
std::map<std::string,individual_effect> values_mul;
std::map<std::string,individual_effect> values_div;
std::map<std::string, individual_effect> values_add;
std::map<std::string, individual_effect> values_mul;
std::map<std::string, individual_effect> values_div;
individual_effect set_effect;

View file

@ -262,8 +262,8 @@ attack_type::attack_type(const config& cfg) :
description_(cfg[z_description].t_str()),
id_(cfg[z_name].token()),
type_(cfg[z_type].token()),
icon_(cfg[z_icon]),
range_(cfg[z_range]),
icon_(cfg[z_icon].token()),
range_(cfg[z_range].token()),
damage_(cfg[z_damage]),
num_attacks_(cfg[z_number]),
attack_weight_(cfg[z_attack_weight].to_double(1.0)),
@ -277,9 +277,11 @@ attack_type::attack_type(const config& cfg) :
if(icon_.empty()){
if (id() != z_empty)
icon_ = "attacks/" + static_cast<std::string const &>(id()) + ".png";
else
icon_ = "attacks/blank-attack.png";
icon_ = config::t_token("attacks/" + static_cast<std::string const &>(id()) + ".png");
else {
static const config::t_token default_icon("attacks/blank-attack.png", false);
icon_ = default_icon;
}
}
}
@ -287,11 +289,10 @@ attack_type::~attack_type()
{
}
std::string attack_type::accuracy_parry_description() const
config::t_token attack_type::accuracy_parry_description() const
{
if(accuracy_ == 0 && parry_ == 0) {
return "";
}
return z_empty; }
std::ostringstream s;
s << utils::signed_percent(accuracy_);
@ -300,15 +301,15 @@ std::string attack_type::accuracy_parry_description() const
s << "/" << utils::signed_percent(parry_);
}
return s.str();
return config::t_token( s.str() );
}
bool attack_type::matches_filter(const config& cfg,bool self) const
{
const std::vector<std::string>& filter_range = utils::split(cfg[z_range]);
const std::string& filter_damage = cfg[z_damage];
const std::vector<std::string> filter_name = utils::split(cfg[z_name]);
const std::vector<std::string> filter_type = utils::split(cfg[z_type]);
const std::vector<config::t_token>& filter_range = utils::split_token(cfg[z_range]);
const config::t_token& filter_damage = cfg[z_damage];
const std::vector<config::t_token> filter_name = utils::split_token(cfg[z_name]);
const std::vector<config::t_token> filter_type = utils::split_token(cfg[z_type]);
const config::t_token filter_special = cfg[z_special];
if(filter_range.empty() == false && std::find(filter_range.begin(),filter_range.end(),range()) == filter_range.end())
@ -330,22 +331,22 @@ bool attack_type::matches_filter(const config& cfg,bool self) const
return true;
}
bool attack_type::apply_modification(const config& cfg,std::string* description)
std::pair<bool, config::t_token> attack_type::apply_modification(const config& cfg)
{
if(!matches_filter(cfg,0))
return false;
if(!matches_filter(cfg,0)) {
return std::make_pair(false, z_empty); }
const config::t_token& set_name = cfg[z_set_name];
const t_string& set_desc = cfg[z_set_description];
const config::t_token& set_type = cfg[z_set_type];
const std::string& del_specials = cfg[z_remove_specials];
const config::t_token& del_specials = cfg[z_remove_specials];
const config &set_specials = cfg.child(z_set_specials);
const std::string& increase_damage = cfg[z_increase_damage];
const std::string& increase_attacks = cfg[z_increase_attacks];
const std::string& set_attack_weight = cfg[z_attack_weight];
const std::string& set_defense_weight = cfg[z_defense_weight];
const std::string& increase_accuracy = cfg[z_increase_accuracy];
const std::string& increase_parry = cfg[z_increase_parry];
const config::t_token& increase_damage = cfg[z_increase_damage];
const config::t_token& increase_attacks = cfg[z_increase_attacks];
const config::t_token& set_attack_weight = cfg[z_attack_weight];
const config::t_token& set_defense_weight = cfg[z_defense_weight];
const config::t_token& increase_accuracy = cfg[z_increase_accuracy];
const config::t_token& increase_parry = cfg[z_increase_parry];
std::stringstream desc;
@ -365,12 +366,12 @@ bool attack_type::apply_modification(const config& cfg,std::string* description)
}
if(del_specials.empty() == false) {
const std::vector<std::string>& dsl = utils::split(del_specials);
const std::vector<config::t_token>& dsl = utils::split_token(del_specials);
if (config &specials = cfg_.child(z_specials))
{
config new_specials;
foreach (const config::any_child &vp, specials.all_children_range()) {
std::vector<std::string>::const_iterator found_id =
std::vector<config::t_token>::const_iterator found_id =
std::find(dsl.begin(), dsl.end(), vp.cfg[z_id]);
if (found_id == dsl.end()) {
new_specials.add_child(vp.key, vp.cfg);
@ -382,7 +383,7 @@ bool attack_type::apply_modification(const config& cfg,std::string* description)
}
if (set_specials) {
const std::string &mode = set_specials[z_mode];
const config::t_token &mode = set_specials[z_mode];
if (mode != z_append) {
cfg_.clear_children(z_specials);
}
@ -399,45 +400,37 @@ bool attack_type::apply_modification(const config& cfg,std::string* description)
}
cfg_[z_damage] = damage_;
if(description != NULL) {
int inc_damage = lexical_cast<int>(increase_damage);
desc << utils::signed_value(inc_damage) << " "
<< _n("damage", "damage", inc_damage);
}
int inc_damage = lexical_cast<int>(increase_damage);
desc << utils::signed_value(inc_damage) << " "
<< _n("damage", "damage", inc_damage);
}
if(increase_attacks.empty() == false) {
num_attacks_ = utils::apply_modifier(num_attacks_, increase_attacks, 1);
cfg_[z_number] = num_attacks_;
if(description != NULL) {
int inc_attacks = lexical_cast<int>(increase_attacks);
desc << utils::signed_value(inc_attacks) << " "
<< _n("strike", "strikes", inc_attacks);
}
int inc_attacks = lexical_cast<int>(increase_attacks);
desc << utils::signed_value(inc_attacks) << " "
<< _n("strike", "strikes", inc_attacks);
}
if(increase_accuracy.empty() == false) {
accuracy_ = utils::apply_modifier(accuracy_, increase_accuracy, 1);
cfg_[z_accuracy] = accuracy_;
if(description != NULL) {
int inc_acc = lexical_cast<int>(increase_accuracy);
// Help xgettext with a directive to recognise the string as a non C printf-like string
// xgettext:no-c-format
desc << utils::signed_value(inc_acc) << _("% accuracy");
}
int inc_acc = lexical_cast<int>(increase_accuracy);
// Help xgettext with a directive to recognise the string as a non C printf-like string
// xgettext:no-c-format
desc << utils::signed_value(inc_acc) << _("% accuracy");
}
if(increase_parry.empty() == false) {
parry_ = utils::apply_modifier(parry_, increase_parry, 1);
cfg_[z_parry] = parry_;
if(description != NULL) {
int inc_parry = lexical_cast<int>(increase_parry);
// xgettext:no-c-format
desc << utils::signed_value(inc_parry) << _("% parry");
}
int inc_parry = lexical_cast<int>(increase_parry);
// xgettext:no-c-format
desc << utils::signed_value(inc_parry) << _("% parry");
}
if(set_attack_weight.empty() == false) {
@ -450,45 +443,33 @@ bool attack_type::apply_modification(const config& cfg,std::string* description)
cfg_[z_defense_weight] = defense_weight_;
}
if(description != NULL) {
*description = desc.str();
}
return true;
return std::make_pair(true, config::t_token(desc.str() ));
}
// Same as above, except only update the descriptions
bool attack_type::describe_modification(const config& cfg,std::string* description)
std::pair<bool, config::t_token> attack_type::describe_modification(const config& cfg)
{
if(!matches_filter(cfg,0))
return false;
if(!matches_filter(cfg,0)) {
return std::make_pair(false, z_empty); }
const std::string& increase_damage = cfg[z_increase_damage];
const std::string& increase_attacks = cfg[z_increase_attacks];
const config::t_token& increase_damage = cfg[z_increase_damage];
const config::t_token& increase_attacks = cfg[z_increase_attacks];
std::stringstream desc;
if(increase_damage.empty() == false) {
if(description != NULL) {
int inc_damage = lexical_cast<int>(increase_damage);
desc << utils::signed_value(inc_damage) << " "
<< _n("damage","damage", inc_damage);
}
int inc_damage = lexical_cast<int>(increase_damage);
desc << utils::signed_value(inc_damage) << " "
<< _n("damage","damage", inc_damage);
}
if(increase_attacks.empty() == false) {
if(description != NULL) {
int inc_attacks = lexical_cast<int>(increase_attacks);
desc << utils::signed_value(inc_attacks) << " "
<< _n("strike", "strikes", inc_attacks);
}
int inc_attacks = lexical_cast<int>(increase_attacks);
desc << utils::signed_value(inc_attacks) << " "
<< _n("strike", "strikes", inc_attacks);
}
if(description != NULL) {
*description = desc.str();
}
return true;
return std::make_pair(true, config::t_token(desc.str() ));
}
unit_movement_type::unit_movement_type(const config& cfg, const unit_movement_type* parent) :
@ -522,7 +503,7 @@ unit_movement_type::unit_movement_type(const config& cfg, const unit_movement_ty
unit_movement_type::unit_movement_type(): moveCosts_(), defenseMods_(), parent_(NULL), cfg_()
{}
std::string unit_movement_type::name() const
config::t_token unit_movement_type::name() const
{
if (!cfg_.has_attribute(z_name) && parent_)
return parent_->name();
@ -574,13 +555,13 @@ bool unit_movement_type::is_flying() const
return cfg_[z_flies].to_bool();
}
int movement_cost_internal(std::map<t_translation::t_terrain, int>& move_costs,
int movement_cost_internal(t_move_cost_cache& move_costs,
const config& cfg, const unit_movement_type* parent,
const gamemap& map, t_translation::t_terrain terrain, int recurse_count)
{
const int impassable = unit_movement_type::UNREACHABLE;
const std::map<t_translation::t_terrain, int>::const_iterator i = move_costs.find(terrain);
const t_move_cost_cache::const_iterator i = move_costs.find(terrain);
if (i != move_costs.end()) return i->second;
@ -635,7 +616,7 @@ int movement_cost_internal(std::map<t_translation::t_terrain, int>& move_costs,
return impassable;
}
const std::string& id = map.get_terrain_info(underlying.front()).id();
const config::t_token& id = map.get_terrain_info(underlying.front()).idt();
if (const config::attribute_value *val = movement_costs.get(id)) {
res = *val;
result_found = true;
@ -714,7 +695,7 @@ const defense_range &defense_range_modifier_internal(defense_cache &defense_mods
if (const config& defense = cfg.child(z_defense))
{
const std::string& id = map.get_terrain_info(underlying.front()).id();
const config::t_token& id = map.get_terrain_info(underlying.front()).idt();
if (const config::attribute_value *val = defense.get(id)) {
int def = *val;
if (def >= 0) res.max_ = def;
@ -891,7 +872,7 @@ void unit_type::build_full(const movement_type_map &mv_types,
}
unit_type *ut = new unit_type(var_cfg);
ut->build_full(mv_types, races, traits);
variations_.insert(std::make_pair(var_cfg[z_variation_name], ut));
variations_.insert(std::make_pair(var_cfg[z_variation_name].token(), ut));
}
for (int i = 0; i < 2; ++i) {
@ -938,12 +919,12 @@ void unit_type::build_full(const movement_type_map &mv_types,
zoc_ = cfg[z_zoc].to_bool(level_ > 0);
const std::string& alpha_blend = cfg[z_alpha];
const config::t_token& alpha_blend = cfg[z_alpha];
if(alpha_blend.empty() == false) {
alpha_ = ftofxp(atof(alpha_blend.c_str()));
}
const std::string& move_type = cfg[z_movement_type];
const config::t_token& move_type = cfg[z_movement_type];
const movement_type_map::const_iterator it = mv_types.find(move_type);
@ -983,7 +964,7 @@ void unit_type::build_help_index(const movement_type_map &mv_types,
movement_ = cfg[z_movement].to_int(1);
max_attacks_ = cfg[z_attacks].to_int(1);
cost_ = cfg[z_cost].to_int(1);
usage_ = cfg_[z_usage].str();
usage_ = cfg_[z_usage].token();
undead_variation_ = cfg_[z_undead_variation].token();
image_ = cfg_[z_image].token();
small_profile_ = cfg_[z_small_profile].token();
@ -1005,8 +986,8 @@ void unit_type::build_help_index(const movement_type_map &mv_types,
// if num_traits is not defined, we use the num_traits from race
num_traits_ = cfg[z_num_traits].to_int(race_->num_traits());
const std::vector<std::string> genders = utils::split(cfg[z_gender]);
for(std::vector<std::string>::const_iterator g = genders.begin(); g != genders.end(); ++g) {
const std::vector<config::t_token> genders = utils::split_token(cfg[z_gender]);
for(std::vector<config::t_token>::const_iterator g = genders.begin(); g != genders.end(); ++g) {
genders_.push_back(string_gender(*g));
}
if(genders_.empty()) {
@ -1016,7 +997,7 @@ void unit_type::build_help_index(const movement_type_map &mv_types,
if (const config &abil_cfg = cfg.child(z_abilities))
{
foreach (const config::any_child &ab, abil_cfg.all_children_range()) {
const std::string &name = ab.cfg[z_name];
const t_string &name = ab.cfg[z_name];
if (!name.empty()) {
abilities_.push_back(name);
ability_tooltips_.push_back(ab.cfg[z_description]);
@ -1033,7 +1014,7 @@ void unit_type::build_help_index(const movement_type_map &mv_types,
continue;
}
foreach (const config::any_child &ab, abil_cfg.all_children_range()) {
const std::string &name = ab.cfg[z_name];
const t_string &name = ab.cfg[z_name];
if (!name.empty()) {
adv_abilities_.push_back(name);
adv_ability_tooltips_.push_back(ab.cfg[z_description]);
@ -1084,9 +1065,9 @@ void unit_type::build_created(const movement_type_map &mv_types,
gender_types_[i]->build_created(mv_types, races, traits);}
}
const std::string& advances_to_val = cfg[z_advances_to];
const config::t_token& advances_to_val = cfg[z_advances_to];
if(advances_to_val != z_null && advances_to_val != z_empty)
advances_to_ = utils::split(advances_to_val);
advances_to_ = utils::split_token(advances_to_val);
DBG_UT << "unit_type '" << id() << "' advances to : " << advances_to_val << "\n";
experience_needed_ = cfg[z_experience].to_int(500);
@ -1094,18 +1075,18 @@ void unit_type::build_created(const movement_type_map &mv_types,
build_status_ = CREATED;
}
const unit_type& unit_type::get_gender_unit_type(config::t_token gender) const
const unit_type& unit_type::get_gender_unit_type(config::t_token const & gender) const
{
if (gender == z_female) return get_gender_unit_type(unit_race::FEMALE);
else if (gender == z_male) return get_gender_unit_type(unit_race::MALE);
else return *this;
}
const unit_type& unit_type::get_gender_unit_type(std::string gender) const
{
if (gender == "female") return get_gender_unit_type(unit_race::FEMALE);
else if (gender == "male") return get_gender_unit_type(unit_race::MALE);
else return *this;
}
// const unit_type& unit_type::get_gender_unit_type(std::string gender) const
// {
// if (gender == "female") return get_gender_unit_type(unit_race::FEMALE);
// else if (gender == "male") return get_gender_unit_type(unit_race::MALE);
// else return *this;
// }
const unit_type& unit_type::get_gender_unit_type(unit_race::GENDER gender) const
{
@ -1118,7 +1099,7 @@ const unit_type& unit_type::get_gender_unit_type(unit_race::GENDER gender) const
return *this;
}
const unit_type& unit_type::get_variation(const std::string& name) const
const unit_type& unit_type::get_variation(const config::t_token& name) const
{
const variations_map::const_iterator i = variations_.find(name);
if(i != variations_.end()) {
@ -1200,7 +1181,7 @@ const char* unit_type::alignment_id(unit_type::ALIGNMENT align)
return (aligns[align]);
}
bool unit_type::has_ability_by_id(const std::string& ability) const
bool unit_type::has_ability_by_id(const config::t_token& ability) const
{
if (const config &abil = cfg_.child(z_abilities))
{
@ -1212,15 +1193,15 @@ bool unit_type::has_ability_by_id(const std::string& ability) const
return false;
}
std::vector<std::string> unit_type::get_ability_list() const
std::vector<config::t_token> unit_type::get_ability_list() const
{
std::vector<std::string> res;
std::vector<config::t_token> res;
const config &abilities = cfg_.child(z_abilities);
if (!abilities) return res;
foreach (const config::any_child &ab, abilities.all_children_range()) {
const std::string &id = ab.cfg[z_id];
const config::t_token &id = ab.cfg[z_id];
if (!id.empty())
res.push_back(id);
}
@ -1234,8 +1215,8 @@ bool unit_type::hide_help() const {
void unit_type::add_advancement(const unit_type &to_unit,int xp)
{
const std::string &to_id = to_unit.cfg_[z_id];
const std::string &from_id = cfg_[z_id];
const config::t_token &to_id = to_unit.cfg_[z_id];
const config::t_token &from_id = cfg_[z_id];
// Add extra advancement path to this unit type
LOG_CONFIG << "adding advancement from " << from_id << " to " << to_id << "\n";
@ -1285,13 +1266,13 @@ void unit_type::add_advancement(const unit_type &to_unit,int xp)
}
}
static void advancement_tree_internal(const std::string& id, std::set<std::string>& tree)
static void advancement_tree_internal(const config::t_token& id, boost::unordered_set<config::t_token>& tree)
{
const unit_type *ut = unit_types.find(id);
if (!ut)
return;
foreach(const std::string& adv, ut->advances_to()) {
foreach(const config::t_token& adv, ut->advances_to()) {
if (tree.insert(adv).second) {
// insertion succeed, expand the new type
advancement_tree_internal(adv, tree);
@ -1299,22 +1280,22 @@ static void advancement_tree_internal(const std::string& id, std::set<std::strin
}
}
std::set<std::string> unit_type::advancement_tree() const
boost::unordered_set<config::t_token> unit_type::advancement_tree() const
{
std::set<std::string> tree;
boost::unordered_set<config::t_token> tree;
advancement_tree_internal(id(), tree);
return tree;
}
const std::vector<std::string> unit_type::advances_from() const
const std::vector<config::t_token> unit_type::advances_from() const
{
// currently not needed (only help call us and already did it)
unit_types.build_all(unit_type::HELP_INDEX);
std::vector<std::string> adv_from;
std::vector<config::t_token> adv_from;
foreach (const unit_type_data::unit_type_map::value_type &ut, unit_types.types())
{
foreach(const std::string& adv, ut.second.advances_to()) {
foreach(const config::t_token& adv, ut.second.advances_to()) {
if (adv == id())
adv_from.push_back(ut.second.id());
}
@ -1345,20 +1326,20 @@ void unit_type_data::set_config(config &cfg)
{
const unit_movement_type move_type(mt);
movement_types_.insert(
std::pair<std::string,unit_movement_type>(move_type.name(), move_type));
std::pair<config::t_token,unit_movement_type>(move_type.name(), move_type));
loadscreen::increment_progress();
}
foreach (const config &r, cfg.child_range(z_race))
{
const unit_race race(r);
races_.insert(std::pair<std::string,unit_race>(race.id(),race));
races_.insert(std::pair<config::t_token,unit_race>(race.id(),race));
loadscreen::increment_progress();
}
foreach (config &ut, cfg.child_range(z_unit_type))
{
std::string id = ut[z_id];
config::t_token id = ut[z_id];
if (const config &bu = ut.child(z_base_unit))
{
// Derive a new unit type from an existing base unit id
@ -1381,7 +1362,7 @@ void unit_type_data::set_config(config &cfg)
}
}
const unit_type *unit_type_data::find(const std::string& key, unit_type::BUILD_STATUS status) const
const unit_type *unit_type_data::find(const config::t_token& key, unit_type::BUILD_STATUS status) const
{
if (key.empty() || key == z_random) return NULL;
@ -1403,14 +1384,14 @@ const unit_type *unit_type_data::find(const std::string& key, unit_type::BUILD_S
return &itor->second;
}
void unit_type_data::check_types(const std::vector<std::string>& types) const
void unit_type_data::check_types(const std::vector<config::t_token>& types) const
{
foreach(const std::string& type, types) {
if(!find(type)) throw game::game_error("unknown unit type: " + type);
foreach(const config::t_token& type, types) {
if(!find(type)) throw game::game_error("unknown unit type: " + static_cast<std::string const &>(type));
}
}
const config& unit_type_data::find_config(const std::string& key) const
const config& unit_type_data::find_config(const config::t_token& key) const
{
const config &cfg = unit_cfg_->find_child(z_unit_type, z_id, key);
@ -1420,7 +1401,7 @@ const config& unit_type_data::find_config(const std::string& key) const
ERR_CF << "unit type not found: " << key << "\n";
ERR_CF << *unit_cfg_ << "\n";
throw config::error("unit type not found: "+key);
throw config::error("unit type not found: "+ static_cast<std::string const &>(key));
}
void unit_type_data::clear()
@ -1478,21 +1459,21 @@ void unit_type_data::read_hide_help(const config& cfg)
if (!cfg)
return;
hide_help_race_.push_back(std::set<std::string>());
hide_help_type_.push_back(std::set<std::string>());
hide_help_race_.push_back(boost::unordered_set<config::t_token>());
hide_help_type_.push_back(boost::unordered_set<config::t_token>());
std::vector<std::string> races = utils::split(cfg[z_race]);
std::vector<config::t_token> races = utils::split_token(cfg[z_race]);
hide_help_race_.back().insert(races.begin(), races.end());
std::vector<std::string> types = utils::split(cfg[z_type]);
std::vector<config::t_token> types = utils::split_token(cfg[z_type]);
hide_help_type_.back().insert(types.begin(), types.end());
std::vector<std::string> trees = utils::split(cfg[z_type_adv_tree]);
std::vector<config::t_token> trees = utils::split_token(cfg[z_type_adv_tree]);
hide_help_type_.back().insert(trees.begin(), trees.end());
foreach(const std::string& t_id, trees) {
foreach(const config::t_token& t_id, trees) {
unit_type_map::iterator ut = types_.find(t_id);
if (ut != types_.end()) {
std::set<std::string> adv_tree = ut->second.advancement_tree();
boost::unordered_set<config::t_token> adv_tree = ut->second.advancement_tree();
hide_help_type_.back().insert(adv_tree.begin(), adv_tree.end());
}
}
@ -1501,7 +1482,7 @@ void unit_type_data::read_hide_help(const config& cfg)
read_hide_help(cfg.child(z_not));
}
bool unit_type_data::hide_help(const std::string& type, const std::string& race) const
bool unit_type_data::hide_help(const config::t_token& type, const config::t_token& race) const
{
bool res = hide_help_all_;
int lvl = hide_help_all_ ? 1 : 0; // first level is covered by 'all=yes'
@ -1522,7 +1503,7 @@ void unit_type_data::add_advancement(unit_type& to_unit) const
foreach (const config &af, cfg.child_range(z_advancefrom))
{
const std::string &from = af[z_unit];
const config::t_token &from = af[z_unit];
int xp = af[z_experience];
unit_type_data::unit_type_map::iterator from_unit = types_.find(from);
@ -1541,7 +1522,7 @@ void unit_type_data::add_advancement(unit_type& to_unit) const
}
}
const unit_race *unit_type_data::find_race(const std::string &key) const
const unit_race *unit_type_data::find_race(const config::t_token &key) const
{
race_map::const_iterator i = races_.find(key);
return i != races_.end() ? &i->second : NULL;
@ -1571,9 +1552,9 @@ bool unit_type::not_living() const
// about gender checks, since we don't
// know what the gender of the
// hypothetical recruit is.
const std::string &ut = effect[z_unit_type];
const config::t_token &ut = effect[z_unit_type];
if (!ut.empty()) {
const std::vector<std::string> &types = utils::split(ut);
const std::vector<config::t_token> &types = utils::split_token(ut);
if(std::find(types.begin(), types.end(), id()) == types.end())
continue;
}

View file

@ -15,6 +15,8 @@
#ifndef UNIT_TYPES_H_INCLUDED
#define UNIT_TYPES_H_INCLUDED
#include <boost/unordered_map.hpp>
#include "unit_animation.hpp"
#include "portrait.hpp"
#include "race.hpp"
@ -44,9 +46,9 @@ public:
const t_string& name() const { return description_; }
const config::t_token& id() const { return id_; }
const config::t_token& type() const { return type_; }
const std::string& icon() const { return icon_; }
const std::string& range() const { return range_; }
std::string accuracy_parry_description() const;
const config::t_token& icon() const { return icon_; }
const config::t_token& range() const { return range_; }
config::t_token accuracy_parry_description() const;
int accuracy() const { return accuracy_; }
int parry() const { return parry_; }
int damage() const { return damage_; }
@ -57,14 +59,14 @@ public:
bool get_special_bool(const config::t_token& special,bool force=false) const;
unit_ability_list get_specials(const config::t_token& special) const;
std::vector<t_string> special_tooltips(bool force=false) const;
std::string weapon_specials(bool force=false) const;
config::t_token weapon_specials(bool force=false) const;
void set_specials_context(const map_location& aloc,const map_location& dloc,
const unit_map &unitmap, bool attacker, const attack_type *other_attack) const;
void set_specials_context(const map_location& loc,const map_location& dloc, const unit& un, bool attacker =true) const;
bool matches_filter(const config& cfg,bool self=false) const;
bool apply_modification(const config& cfg,std::string* description);
bool describe_modification(const config& cfg,std::string* description);
std::pair<bool, config::t_token> apply_modification(const config& cfg);
std::pair<bool, config::t_token> describe_modification(const config& cfg);
int movement_used() const { return cfg_[z_movement_used].to_int(100000); }
@ -96,8 +98,8 @@ private:
t_string description_;
config::t_token id_;
config::t_token type_;
std::string icon_;
std::string range_;
config::t_token icon_;
config::t_token range_;
int damage_;
int num_attacks_;
double attack_weight_;
@ -118,7 +120,7 @@ struct defense_range
int min_, max_;
};
typedef std::map<t_translation::t_terrain, defense_range> defense_cache;
typedef boost::unordered_map<t_translation::t_terrain, defense_range> defense_cache;
const defense_range &defense_range_modifier_internal(defense_cache &defense_mods,
const config &cfg, const unit_movement_type *parent,
@ -128,7 +130,8 @@ int defense_modifier_internal(defense_cache &defense_mods,
const config &cfg, const unit_movement_type *parent,
const gamemap &map, t_translation::t_terrain terrain, int recurse_count = 0);
int movement_cost_internal(std::map<t_translation::t_terrain, int> &move_costs,
typedef boost::unordered_map<t_translation::t_terrain, int> t_move_cost_cache;
int movement_cost_internal( t_move_cost_cache &move_costs,
const config &cfg, const unit_movement_type *parent,
const gamemap &map, t_translation::t_terrain terrain, int recurse_count = 0);
@ -147,7 +150,7 @@ public:
unit_movement_type(const config& cfg, const unit_movement_type* parent=NULL);
unit_movement_type();
std::string name() const;
config::t_token name() const;
int movement_cost(const gamemap &map, t_translation::t_terrain terrain) const
{ return movement_cost_internal(moveCosts_, cfg_, parent_, map, terrain); }
int defense_modifier(const gamemap &map, t_translation::t_terrain terrain) const
@ -166,7 +169,7 @@ public:
const config& get_cfg() const { return cfg_; }
const unit_movement_type* get_parent() const { return parent_; }
private:
mutable std::map<t_translation::t_terrain, int> moveCosts_;
mutable t_move_cost_cache moveCosts_;
mutable defense_cache defenseMods_;
const unit_movement_type* parent_;
@ -174,7 +177,7 @@ private:
config cfg_;
};
typedef std::map<std::string,unit_movement_type> movement_type_map;
typedef boost::unordered_map<config::t_token, unit_movement_type> movement_type_map;
class unit_type
{
@ -211,18 +214,18 @@ public:
/** Get the advancement tree
* Build a set of unit type's id of this unit type's advancement tree */
std::set<std::string> advancement_tree() const;
boost::unordered_set<config::t_token> advancement_tree() const;
const std::vector<std::string>& advances_to() const { return advances_to_; }
const std::vector<std::string> advances_from() const;
const std::vector<config::t_token>& advances_to() const { return advances_to_; }
const std::vector<config::t_token> advances_from() const;
config::const_child_itors modification_advancements() const
{ return cfg_.child_range(z_advancement); }
const unit_type& get_gender_unit_type(config::t_token gender) const;
const unit_type& get_gender_unit_type(std::string gender) const;
const unit_type& get_gender_unit_type(config::t_token const & gender) const;
//const unit_type& get_gender_unit_type(std::string gender) const;
const unit_type& get_gender_unit_type(unit_race::GENDER gender) const;
const unit_type& get_variation(const std::string& name) const;
const unit_type& get_variation(const config::t_token& name) const;
/** Info on the type of unit that the unit reanimates as. */
const config::t_token& undead_variation() const { return undead_variation_; }
@ -240,8 +243,8 @@ public:
int movement() const { return movement_; }
int max_attacks() const { return max_attacks_; }
int cost() const { return cost_; }
const std::string& usage() const { return usage_; }
const std::string& image() const { return image_; }
const config::t_token& usage() const { return usage_; }
const config::t_token& image() const { return image_; }
const config::t_token &small_profile() const { return small_profile_; }
const config::t_token &big_profile() const { return big_profile_; }
@ -271,11 +274,11 @@ public:
fixed_t alpha() const { return alpha_; }
const std::vector<t_string>& abilities() const { return abilities_; }
const std::vector<std::string>& ability_tooltips() const { return ability_tooltips_; }
const std::vector<config::t_token>& ability_tooltips() const { return ability_tooltips_; }
// some extra abilities may be gained through AMLA advancements
const std::vector<t_string>& adv_abilities() const { return adv_abilities_; }
const std::vector<std::string>& adv_ability_tooltips() const { return adv_ability_tooltips_; }
const std::vector<config::t_token>& adv_ability_tooltips() const { return adv_ability_tooltips_; }
bool can_advance() const { return !advances_to_.empty(); }
@ -283,8 +286,8 @@ public:
bool has_zoc() const { return zoc_; }
bool has_ability_by_id(const std::string& ability) const;
std::vector<std::string> get_ability_list() const;
bool has_ability_by_id(const config::t_token& ability) const;
std::vector<config::t_token> get_ability_list() const;
config::const_child_itors possible_traits() const
{ return possibleTraits_.child_range(z_trait); }
@ -292,7 +295,7 @@ public:
const std::vector<unit_race::GENDER>& genders() const { return genders_; }
const std::string& race() const { return race_->id(); }
const config::t_token& race() const { return race_->id(); }
bool hide_help() const;
enum BUILD_STATUS {NOT_BUILT, CREATED, HELP_INDEX, WITHOUT_ANIMATIONS, FULL};
@ -316,7 +319,7 @@ private:
int movement_;
int max_attacks_;
int cost_;
std::string usage_;
config::t_token usage_;
config::t_token undead_variation_;
config::t_token image_;
@ -328,7 +331,7 @@ private:
unit_type* gender_types_[2];
typedef std::map<std::string,unit_type*> variations_map;
typedef boost::unordered_map<config::t_token, unit_type*> variations_map;
variations_map variations_;
const unit_race* race_;
@ -336,11 +339,11 @@ private:
fixed_t alpha_;
std::vector<t_string> abilities_, adv_abilities_;
std::vector<std::string> ability_tooltips_, adv_ability_tooltips_;
std::vector<config::t_token> ability_tooltips_, adv_ability_tooltips_;
bool zoc_, hide_help_;
std::vector<std::string> advances_to_;
std::vector<config::t_token> advances_to_;
int experience_needed_;
bool in_advancefrom_;
@ -367,21 +370,23 @@ class unit_type_data
public:
unit_type_data();
typedef std::map<std::string,unit_type> unit_type_map;
typedef boost::unordered_map<config::t_token, unit_type> unit_type_map;
const unit_type_map &types() const { return types_; }
const race_map &races() const { return races_; }
const config::const_child_itors traits() const { return unit_cfg_->child_range("trait"); }
void set_config(config &cfg);
const unit_type *find(const std::string &key, unit_type::BUILD_STATUS status = unit_type::FULL) const;
void check_types(const std::vector<std::string>& types) const;
const unit_race *find_race(const std::string &) const;
const unit_type *find(const config::t_token &key, unit_type::BUILD_STATUS status = unit_type::FULL) const;
const unit_type *find(const std::string &key, unit_type::BUILD_STATUS status = unit_type::FULL) const {
return find(config::t_token(key), status); }
void check_types(const std::vector<config::t_token>& types) const;
const unit_race *find_race(const config::t_token &) const;
void build_all(unit_type::BUILD_STATUS status);
/** Checks if the [hide_help] tag contains these IDs. */
bool hide_help(const std::string &type_id, const std::string &race_id) const;
bool hide_help(const config::t_token &type_id, const config::t_token &race_id) const;
private:
unit_type_data(const unit_type_data &);
@ -391,8 +396,8 @@ private:
void set_unit_config(const config& unit_cfg) { unit_cfg_ = &unit_cfg; }
const config &find_config(const std::string &key) const;
std::pair<unit_type_map::iterator, bool> insert(const std::pair<std::string, unit_type> &utype) { return types_.insert(utype); }
const config &find_config(const config::t_token &key) const;
std::pair<unit_type_map::iterator, bool> insert(const std::pair<config::t_token, unit_type> &utype) { return types_.insert(utype); }
void clear();
unit_type& build_unit_type(const unit_type_map::iterator &ut, unit_type::BUILD_STATUS status) const;
@ -406,8 +411,8 @@ private:
/** True if [hide_help] contains a 'all=yes' at its root. */
bool hide_help_all_;
// vectors containing the [hide_help] and its sub-tags [not]
std::vector< std::set<std::string> > hide_help_type_;
std::vector< std::set<std::string> > hide_help_race_;
std::vector< boost::unordered_set<config::t_token> > hide_help_type_;
std::vector< boost::unordered_set<config::t_token> > hide_help_race_;
const config *unit_cfg_;
unit_type::BUILD_STATUS build_status_;