Updated parts of unit class to use t_token...

...in place of std:string in order to speed up comparisons, copies and
hashing which are 1 cycle operations.

Added z_sub t_token.

Added lru_cache unit test
This commit is contained in:
Thonsew 2011-09-08 19:16:26 +00:00
parent abb678b080
commit 576a3feab1
25 changed files with 1873 additions and 990 deletions

View File

@ -545,6 +545,7 @@ test_sources = Split("""
tests/test_image_modifications.cpp
tests/test_interpolate_variables_into_thing.cpp
tests/test_lexical_cast.cpp
tests/test_lru_cache.cpp
tests/test_network_worker.cpp
tests/test_team.cpp
tests/test_unit_map.cpp

View File

@ -57,6 +57,13 @@ static lg::log_domain log_ai("ai/general");
#pragma warning(disable:4250)
#endif
namespace{
//Static tokens are replacements for string literals in code
//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);
}
namespace ai {
typedef util::array<map_location,6> adjacent_tiles_array;
@ -370,10 +377,10 @@ int ai_default_recruitment_stage::average_resistance_against(const unit_type& a,
if (steadfast && resistance < 100)
resistance = std::max<int>(resistance * 2 - 100, 50);
// Do not look for filters or values, simply assume 70% if CTH is customized.
int cth = i->get_special_bool("chance_to_hit", true) ? 70 : defense;
int cth = i->get_special_bool(z_chance_to_hit, true) ? 70 : defense;
int weight = i->damage() * i->num_attacks();
// if cth == 0 the division will do 0/0 so don't execute this part
if (living && cth != 0 && i->get_special_bool("poison", true)) {
if (living && cth != 0 && i->get_special_bool(z_poison, true)) {
// Compute the probability of not poisoning the unit.
int prob = 100;
for (int j = 0; j < i->num_attacks(); ++j)

View File

@ -40,6 +40,15 @@ static lg::log_domain log_ai_testing_aspect_attacks("ai/aspect/attacks");
#define LOG_AI LOG_STREAM(info, log_ai_testing_aspect_attacks)
#define ERR_AI LOG_STREAM(err, log_ai_testing_aspect_attacks)
namespace{
//Static tokens are replacements for string literals in code
//They allow for fast comparison operations.
static const config::t_token z_backstab("backstab", false);
static const config::t_token z_slow("slow", false);
static const config::t_token z_value("value", false);
}
aspect_attacks::aspect_attacks(readonly_context &context, const config &cfg, const std::string &id)
: typesafe_aspect<attacks_vector>(context,cfg,id)
, filter_own_()
@ -165,11 +174,11 @@ void aspect_attacks::do_attack_analysis(
std::vector<attack_type>& attacks = unit_itor->attacks();
for(std::vector<attack_type>::iterator a = attacks.begin(); a != attacks.end(); ++a) {
a->set_specials_context(map_location(), map_location(), units_, true, NULL);
if(a->get_special_bool("backstab")) {
if(a->get_special_bool(z_backstab)) {
backstab = true;
}
if(a->get_special_bool("slow")) {
if(a->get_special_bool(z_slow)) {
slow = true;
}
}
@ -255,7 +264,7 @@ void aspect_attacks::do_attack_analysis(
}
unit_ability_list abil = unit_itor->get_abilities("leadership",tiles[j]);
int best_leadership_bonus = abil.highest("value").first;
int best_leadership_bonus = abil.highest(z_value).first;
double leadership_bonus = static_cast<double>(best_leadership_bonus+100)/100.0;
if (leadership_bonus > 1.1) {
LOG_AI << unit_itor->name() << " is getting leadership " << leadership_bonus << "\n";

View File

@ -43,6 +43,15 @@ static lg::log_domain log_ai_testing_ai_default("ai/ca/testing_ai_default");
#define ERR_AI_TESTING_AI_DEFAULT LOG_STREAM(err, log_ai_testing_ai_default)
namespace{
//Static tokens are replacements for string literals in code
//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_guardian("guardian", false);
}
namespace ai {
namespace testing_ai_default {
@ -414,10 +423,10 @@ int recruitment_phase::average_resistance_against(const unit_type& a, const unit
if (steadfast && resistance < 100)
resistance = std::max<int>(resistance * 2 - 100, 50);
// Do not look for filters or values, simply assume 70% if CTH is customized.
int cth = i->get_special_bool("chance_to_hit", true) ? 70 : defense;
int cth = i->get_special_bool(z_chance_to_hit, true) ? 70 : defense;
int weight = i->damage() * i->num_attacks();
// if cth == 0 the division will do 0/0 so don't execute this part
if (living && cth != 0 && i->get_special_bool("poison", true)) {
if (living && cth != 0 && i->get_special_bool(z_poison, true)) {
// Compute the probability of not poisoning the unit.
int prob = 100;
for (int j = 0; j < i->num_attacks(); ++j)
@ -1029,7 +1038,7 @@ void get_villages_phase::find_villages(
}
const unit_map::const_iterator u = resources::units->find(j->second);
if (u == resources::units->end() || u->get_state("guardian")) {
if (u == resources::units->end() || u->get_state(z_guardian)) {
continue;
}

View File

@ -32,6 +32,12 @@
#include <deque>
namespace{
//Static tokens are replacements for string literals in code
//They allow for fast comparison operations.
static const config::t_token z_guardian("guardian", false);
}
namespace ai {
namespace testing_ai_default {
@ -292,7 +298,7 @@ std::pair<map_location,map_location> testing_move_to_targets_phase::choose_move(
}
//guardian units stay put
if (u->get_state("guardian")) {
if (u->get_state(z_guardian)) {
LOG_AI << u->type_id() << " is guardian, staying still\n";
return std::make_pair(u->get_location(), u->get_location());
}
@ -386,7 +392,7 @@ std::pair<map_location,map_location> testing_move_to_targets_phase::choose_move(
//now see if any other unit can put a better bid forward
for(++u; u != units_.end(); ++u) {
if (u->side() != get_side() || u->can_recruit() ||
u->movement_left() <= 0 || u->get_state("guardian") ||
u->movement_left() <= 0 || u->get_state(z_guardian) ||
u->incapacitated())
{
continue;

View File

@ -41,6 +41,13 @@
#include <iostream>
#include <map>
namespace{
//Static tokens are replacements for string literals in code
//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_guardian("guardian", false);
}
namespace ai {
@ -299,10 +306,10 @@ static int average_resistance_against(const unit_type& a, const unit_type& b)
if (steadfast && resistance < 100)
resistance = std::max<int>(resistance * 2 - 100, 50);
// Do not look for filters or values, simply assume 70% if CTH is customized.
int cth = i->get_special_bool("chance_to_hit", true) ? 70 : defense;
int cth = i->get_special_bool(z_chance_to_hit, true) ? 70 : defense;
int weight = i->damage() * i->num_attacks();
// if cth == 0 the division will do 0/0 so don't execute this part
if (living && cth != 0 && i->get_special_bool("poison", true)) {
if (living && cth != 0 && i->get_special_bool(z_poison, true)) {
// Compute the probability of not poisoning the unit.
int prob = 100;
for (int j = 0; j < i->num_attacks(); ++j)

View File

@ -24,6 +24,12 @@
#include "resources.hpp"
#include "unit_abilities.hpp"
namespace {
//Static tokens are replacements for string literals in code
//They allow for fast comparison operations.
static const config::t_token z_damage("damage", false);
}
// Conversion routine for both unscathed and damage change percentage.
static void format_prob(char str_buf[10], double prob)
{
@ -158,7 +164,7 @@ void battle_prediction_pane::get_unit_strings(const battle_context_unit_stats& s
weapon->set_specials_context(u_loc, opp_loc, *resources::units, stats.is_attacker, opp_weapon);
// Get damage modifiers.
unit_ability_list dmg_specials = weapon->get_specials("damage");
unit_ability_list dmg_specials = weapon->get_specials(z_damage);
unit_abilities::effect dmg_effect(dmg_specials, weapon->damage(), stats.backstab_pos);
// Get the SET damage modifier, if any.

View File

@ -171,7 +171,8 @@ variant unit_callable::get_value(const std::string& key) const
} else if(key == "leader") {
return variant(u_.can_recruit());
} else if(key == "undead") {
return variant(u_.get_state("not_living") ? 1 : 0);
static const config::t_token z_not_living("not_living");
return variant(u_.get_state(z_not_living) ? 1 : 0);
} else if(key == "attacks") {
const std::vector<attack_type>& att = u_.attacks();
std::vector<variant> res;
@ -208,19 +209,19 @@ variant unit_callable::get_value(const std::string& key) const
} else if(key == "attacks_left") {
return variant(u_.attacks_left());
} else if(key == "traits") {
const std::vector<std::string> traits = u_.get_traits_list();
const std::vector<config::t_token> traits = u_.get_traits_list();
std::vector<variant> res;
if(traits.empty())
return variant( &res );
for (std::vector<std::string>::const_iterator it = traits.begin(); it != traits.end(); ++it)
for (std::vector<config::t_token>::const_iterator it = traits.begin(); it != traits.end(); ++it)
{
res.push_back( variant(*it) );
}
return variant( &res );
} else if(key == "states") {
const std::map<std::string, std::string>& states_map = u_.get_states();
const std::map<config::t_token, config::t_token>& states_map = u_.get_states();
return convert_map( states_map );
} else if(key == "side") {

View File

@ -664,8 +664,8 @@ void config::remove_child(const t_token &key, unsigned index)
void config::remove_child(const std::string &key, unsigned index) {return remove_child(t_token( key ), index);}
#ifdef DEBUG
//#define COUNT_THE_NUMBER_OF_STRING_TO_TOKEN_CONVERSIONS
#ifdef COUNT_THE_NUMBER_OF_STRING_TO_TOKEN_CONVERSIONS
namespace{
static n_count_logger::t_count_logger<std::string> count_btok1("config index as std::string (BAD)",11);
}
@ -697,7 +697,7 @@ config::attribute_value &config::operator[](const attribute_value &key){
return operator[](key.token());}
config::attribute_value &config::operator[](const std::string &key){
#ifdef DEBUG
#ifdef COUNT_THE_NUMBER_OF_STRING_TO_TOKEN_CONVERSIONS
count_btok1.inc(key); //debug
#endif
return operator[](t_token(key));}

View File

@ -68,6 +68,9 @@ static lg::log_domain log_display("display");
static lg::log_domain log_config("config");
#define ERR_CF LOG_STREAM(err, log_config)
namespace{
static const config::t_token z_advance("advance");
}
namespace dialogs
{
@ -97,7 +100,7 @@ int advance_unit_dialog(const map_location &loc)
{
if (mod["always_display"].to_bool()) always_display = true;
sample_units.push_back(::get_advanced_unit(*u, u->type_id()));
sample_units.back().add_modification("advance", mod);
sample_units.back().add_modification(z_advance, mod);
const unit& type = sample_units.back();
if (!mod["image"].empty()) {
lang_options.push_back(IMAGE_PREFIX + mod["image"].str() + COLUMN_SEPARATOR + mod["description"].str());
@ -224,7 +227,7 @@ bool animate_unit_advancement(const map_location &loc, size_t choice, const bool
}
amla_unit.set_experience(amla_unit.experience() - amla_unit.max_experience());
amla_unit.add_modification("advance",mod_option);
amla_unit.add_modification(z_advance,mod_option);
resources::units->replace(loc, amla_unit);
if(fire_event)
@ -383,7 +386,7 @@ void save_preview_pane::draw_contents()
#ifdef LOW_MEM
const surface image(image::get_image(leader->image()));
#else
const surface image(image::get_image(leader->image() + "~RC(" + leader->flag_rgb() + ">1)"));
const surface image(image::get_image(leader->image() + "~RC(" + static_cast<std::string const &>(leader->flag_rgb()) + ">1)"));
#endif
if(image != NULL) {
@ -977,7 +980,7 @@ const unit_types_preview_pane::details unit_types_preview_pane::get_details() co
//FIXME: There should be a better way to deal with this
unit_types.find(t->id(), unit_type::WITHOUT_ANIMATIONS);
std::string mod = "~RC(" + t->flag_rgb() + ">" + team::get_side_color_index(side_) + ")";
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.name = "";

View File

@ -288,25 +288,6 @@ private:
*/
class t_operation_interp : public t_operation {
///interpolates the attribute_value value into a token
///todo remove this once you can type x.token() where x is a config
// struct do_interp_visitor : public boost::static_visitor<void> {
// ///todo put back thonsew
// // : public config::attribute_value::default_visitor {
// // using default_visitor::operator();
// t_token & self_;
// do_interp_visitor(t_token & t):self_(t) {}
// void operator()() { self_ = z_empty; }
// void operator()(bool const b) {self_ = t_token(str_cast(b)); }
// void operator()(int const i) {self_ = t_token(str_cast(i)); }
// void operator()(double const d) {self_ = t_token( str_cast(d)); }
// void operator()(n_token::t_token const & tok){self_ = tok; }
// void operator()(const t_string &s){ self_=t_token(s);}
// ///todo remove 3 lines
// void operator()(boost::blank const &){self_ = z_empty; }
// void operator()(std::string const & s){self_=t_token(s);}
// };
public :
///Grab the top item on the stack, look it up in the variable set and append it to the second item on the stack
@ -315,13 +296,6 @@ public :
t_token var_name(stack.back());
config::attribute_value stuffing(variable_set.get_variable_const(var_name ));
DEBUG_INTERP << string(var_name, stuffing) << "\n";
///todo replace next 4 lines with this->lhs_ = stuffing.token();
// t_token rhs;
// do_interp_visitor visitor(rhs);
// ///todo swap next 2
// //stuffing.apply_visitor(visitor);
// boost::apply_visitor(visitor, stuffing.to_value());
stack.pop_back();
t_operation_append append(stuffing.token());

View File

@ -79,6 +79,201 @@ static lg::log_domain log_wml("wml");
static lg::log_domain log_config("config");
#define ERR_CF LOG_STREAM(err, log_config)
namespace{
static const config::t_token z_id("id");
static const config::t_token z_this_unit("this_unit");
static const config::t_token z_variable("variable");
static const config::t_token z_time_of_day("time_of_day");
static const config::t_token z_x("x");
static const config::t_token z_y("y");
static const config::t_token z_x1("x1");
static const config::t_token z_x2("x2");
static const config::t_token z_y1("y1");
static const config::t_token z_y2("y2");
static const config::t_token z_have_unit("have_unit");
static const config::t_token z_count("count");
static const config::t_token z_search_recall_list("search_recall_list");
static const config::t_token z_have_location("have_location");
static const config::t_token z_name("name");
static const config::t_token z_equals("equals");
static const config::t_token z_not_equals("not_equals");
static const config::t_token z_numerical_equals("numerical_equals");
static const config::t_token z_numerical_not_equals("numerical_not_equals");
static const config::t_token z_boolean_equals("boolean_equals");
static const config::t_token z_boolean_not_equals("boolean_not_equals");
static const config::t_token z_less_than("less_than");
static const config::t_token z_greater_than("greater_than");
static const config::t_token z_greater_than_equal_to("greater_than_equal_to");
static const config::t_token z_less_than_equal_to("less_than_equal_to");
static const config::t_token z_and("and");
static const config::t_token z_or("or");
static const config::t_token z_not("not");
static const config::t_token z_contains("contains");
static const config::t_token z_backwards_compat("backwards_compat");
static const config::t_token z_logger("logger");
static const config::t_token z_message("message");
static const config::t_token z_side("side");
static const config::t_token z_filter_side("filter_side");
static const config::t_token z_remove("remove");
static const config::t_token z_source("source");
static const config::t_token z_target("target");
static const config::t_token z_bidirectional("bidirectional");
static const config::t_token z_check_passability("check_passability");
static const config::t_token z_clear_shroud("clear_shroud");
static const config::t_token z_animate("animate");
static const config::t_token z_type("type");
static const config::t_token z_filter("filter");
static const config::t_token z_music("music");
static const config::t_token z_sound("sound");
static const config::t_token z_red("red");
static const config::t_token z_green("green");
static const config::t_token z_blue("blue");
static const config::t_token z_turn("turn");
static const config::t_token z_team_name("team_name");
static const config::t_token z_user_team_name("user_team_name");
static const config::t_token z_controller("controller");
static const config::t_token z_recruit("recruit");
static const config::t_token z_shroud_data("shroud_data");
static const config::t_token z_ai("ai");
static const config::t_token z_switch_ai("switch_ai");
static const config::t_token z_income("income");
static const config::t_token z_gold("gold");
static const config::t_token z_shroud("shroud");
static const config::t_token z_hidden("hidden");
static const config::t_token z_fog("fog");
static const config::t_token z_village_gold("village_gold");
static const config::t_token z_value("value");
static const config::t_token z_share_view("share_view");
static const config::t_token z_add("add");
static const config::t_token z_current("current");
static const config::t_token z_turn_number("turn_number");
static const config::t_token z_variation("variation");
static const config::t_token z_image_mods("image_mods");
static const config::t_token z_gender("gender");
static const config::t_token z_effect("effect");
static const config::t_token z_apply_to("apply_to");
static const config::t_token z_fake_unit("fake_unit");
static const config::t_token z_skip_steps("skip_steps");
static const config::t_token z_literal("literal");
static const config::t_token z_sub("sub");
static const config::t_token z_multiply("multiply");
static const config::t_token z_share_maps("share_maps");
static const config::t_token z_image_mod("image_mod");
static const config::t_token z_divide("divide");
static const config::t_token z_modulo("modulo");
static const config::t_token z_round("round");
static const config::t_token z_ceil("ceil");
static const config::t_token z_floor("floor");
static const config::t_token z_ipart("ipart");
static const config::t_token z_fpart("fpart");
static const config::t_token z_string_length("string_length");
static const config::t_token z_time("time");
static const config::t_token z_stamp("stamp");
static const config::t_token z_rand("rand");
static const config::t_token z_join("join");
static const config::t_token z_separator("separartor");
static const config::t_token z_key("key");
static const config::t_token z_to_variable("to_variable");
static const config::t_token z_remove_empty("remove_empty");
static const config::t_token z_mode("mode");
static const config::t_token z_extend("extend");
static const config::t_token z_append("append");
static const config::t_token z_merge("merge");
static const config::t_token z_insert("insert");
static const config::t_token z_split("split");
static const config::t_token z_replace("replace");
static const config::t_token z_list("list");
static const config::t_token z_role("role");
static const config::t_token z_mask("mask");
static const config::t_token z_border("border");
static const config::t_token z_show("show");
static const config::t_token z_fire_event("fire_event");
static const config::t_token z_then("then");
static const config::t_token z_object("object");
static const config::t_token z_size("size");
static const config::t_token z_text("text");
static const config::t_token z_duration("duration");
static const config::t_token z_secondary_unit("secondary_unit");
static const config::t_token z_die("die");
static const config::t_token z_needs_select("needs_select");
static const config::t_token z_show_if("show_if");
static const config::t_token z_filter_location("filter_location");
static const config::t_token z_command("command");
static const config::t_token z_find_vacant("find_vacant");
static const config::t_token z_cannot_use_message("cannot_use_message");
static const config::t_token z_recall("recall");
static const config::t_token z_else("else");
static const config::t_token z_silent("silent");
//static const config::t_token z_("");
static const config::t_token z_advance("advance");
static const config::t_token z_choose("choose");
static const config::t_token z_location("location");
static const config::t_token z_owner_side("owner_side");
static const config::t_token z_store_villages("store_villages");
static const config::t_token z_next_scenario("next_scenario");
static const config::t_token z_end_text("end_text");
static const config::t_token z_end_text_duration("end_text_duration");
static const config::t_token z_result("result");
static const config::t_token z_victory("victory");
static const config::t_token z_defeat("defeat");
static const config::t_token z_carryover_report("carryover_report");
static const config::t_token z_save("save");
static const config::t_token z_linger_mode("linger_mode");
static const config::t_token z_reveal_map("reveal_map");
static const config::t_token z_bonus("bonus");
static const config::t_token z_carryover_percentage("carryover_percentage");
static const config::t_token z_carryover_add("carryover_add");
static const config::t_token z_filter_second("filter_second");
static const config::t_token z_heals("heals");
static const config::t_token z_amount("amount");
static const config::t_token z_moves("moves");
static const config::t_token z_restore_attacks("restore_attacks");
static const config::t_token z_restore_statuses("restore_statuses");
static const config::t_token z_full("full");
static const config::t_token z_heal_amount("heal_amount");
static const config::t_token z_topic("topic");
static const config::t_token z_speaker("speaker");
static const config::t_token z_unit("unit");
static const config::t_token z_second_unit("second_unit");
static const config::t_token z_narrator("narrator");
static const config::t_token z_caption("caption");
static const config::t_token z_label("label");
static const config::t_token z_option("option");
static const config::t_token z_text_input("text_input");
static const config::t_token z_max_length("max_length");
static const config::t_token z_side_for("side_for");
static const config::t_token z_scroll("scroll");
static const config::t_token z_time_area("time_area");
static const config::t_token z_input("input");
static const config::t_token z_map("map");
static const config::t_token z_delayed("delayed");
static const config::t_token z_expand("expand");
static const config::t_token z_shrink("shrink");
static const config::t_token z_first_time_only("first_time_only");
static const config::t_token z_allow_undo("allow_undo");
static const config::t_token z_weapon("weapon");
static const config::t_token z_first("first");
static const config::t_token z_second("second");
static const config::t_token z_second_weapon("second_weapon");
static const config::t_token z_filter_condition("filter_condition");
static const config::t_token z_filter_attack("filter_attack");
static const config::t_token z_filter_second_attack("filter_second_attack");
static const config::t_token z_handle_event_command("handle_event_command");
static const config::t_token z_empty("empty");
static const config::t_token z_event("event");
static const config::t_token z_unit_wml_ids("unit_wml_ids");
static const config::t_token z_used_items("used_items");
static const config::t_token z_select("select");
static const config::t_token z_delayed_variable_substitution("delayed_variable_substitution");
// static const config::t_token z_("");
// static const config::t_token z_("");
}
/**
* State when processing a flight of events or commands.
*/
@ -1036,7 +1231,7 @@ game_display::fake_unit *create_fake_unit(const vconfig& cfg)
config &effect = mod.add_child("effect");
effect["apply_to"] = "variation";
effect["name"] = variation;
fake_unit->add_modification("variation",mod);
fake_unit->add_modification(z_variation,mod);
}
if(!img_mods.empty()) {
@ -1044,7 +1239,7 @@ game_display::fake_unit *create_fake_unit(const vconfig& cfg)
config &effect = mod.add_child("effect");
effect["apply_to"] = "image_mod";
effect["add"] = img_mods;
fake_unit->add_modification("image_mod",mod);
fake_unit->add_modification(z_image_mod,mod);
}
return fake_unit;
@ -1408,8 +1603,8 @@ WML_HANDLER_FUNCTION(set_variable, /*event_info*/, cfg)
WML_HANDLER_FUNCTION(set_variables, /*event_info*/, cfg)
{
const t_string& name = cfg["name"];
{
const config::attribute_value & name = cfg["name"];
variable_info dest(name, true, variable_info::TYPE_CONTAINER);
std::string mode = cfg["mode"]; // replace, append, merge, or insert
@ -1441,7 +1636,7 @@ WML_HANDLER_FUNCTION(set_variables, /*event_info*/, cfg)
{
variable_info tovar(cfg["to_variable"], false, variable_info::TYPE_CONTAINER);
if(tovar.is_valid()) {
if(tovar.explicit_index) {
if(tovar.is_explicit_index()) {
data.add_child(dest.key, tovar.as_container());
} else {
variable_info::array_range range = tovar.as_array();
@ -1497,7 +1692,7 @@ WML_HANDLER_FUNCTION(set_variables, /*event_info*/, cfg)
}
if(mode == "replace")
{
if(dest.explicit_index) {
if(dest.is_explicit_index()) {
dest.vars->remove_child(dest.key, dest.index);
} else {
dest.vars->clear_children(dest.key);
@ -1507,7 +1702,7 @@ WML_HANDLER_FUNCTION(set_variables, /*event_info*/, cfg)
{
if(mode == "merge")
{
if(dest.explicit_index) {
if(dest.is_explicit_index()) {
// merging multiple children into a single explicit index
// requires that they first be merged with each other
data.merge_children(dest.key);
@ -1515,7 +1710,7 @@ WML_HANDLER_FUNCTION(set_variables, /*event_info*/, cfg)
} else {
dest.vars->merge_with(data);
}
} else if(mode == "insert" || dest.explicit_index) {
} else if(mode == "insert" || dest.is_explicit_index()) {
foreach (const config &child, data.child_range(dest.key))
{
dest.vars->add_child_at(dest.key, child, dest.index++);
@ -1548,7 +1743,7 @@ WML_HANDLER_FUNCTION(role, /*event_info*/, cfg)
unit_map::iterator itor;
foreach (unit &u, *resources::units) {
if (game_events::unit_matches_filter(u, filter)) {
u.set_role(cfg["role"]);
u.set_role(cfg[z_role].token());
found = true;
break;
}
@ -1585,7 +1780,7 @@ WML_HANDLER_FUNCTION(role, /*event_info*/, cfg)
unit& u = pi->recall_list()[i];
scoped_recall_unit auto_store("this_unit", player_id, i);
if (u.matches_filter(filter, map_location())) {
u.set_role(cfg["role"]);
u.set_role(cfg[z_role].token());
found=true;
break;
}
@ -1796,7 +1991,7 @@ WML_HANDLER_FUNCTION(object, event_info, cfg)
{
text = cfg["description"].str();
u->add_modification("object", cfg.get_parsed_config());
u->add_modification(z_object, cfg.get_parsed_config());
resources::screen->select_hex(event_info.loc1);
resources::screen->invalidate_unit();

View File

@ -170,8 +170,7 @@ namespace{
static const config::t_token z_scroll_to_leader("scroll_to_leader", false);
static const config::t_token z_color_lock("color_lock", false);
static const config::t_token z_faction("faction", false);
static const config::t_token z_image("image", false);
static const config::t_token z_description("description", false);
static const config::t_token z_empty("", false);
}
game_classification::game_classification():
@ -500,7 +499,7 @@ void extract_summary_from_config(config& cfg_save, config& cfg_summary)
cfg_summary[z_campaign] = cfg_save[z_campaign];
cfg_summary[z_difficulty] = cfg_save[z_difficulty];
cfg_summary[z_version] = cfg_save[z_version];
cfg_summary[z_corrupt] = "";
cfg_summary[z_corrupt] = z_empty;
if(has_snapshot) {
cfg_summary[z_turn] = cfg_snapshot[z_turn_at];
@ -559,7 +558,7 @@ void extract_summary_from_config(config& cfg_save, config& cfg_summary)
cfg_summary[z_leader] = leader;
cfg_summary[z_leader_image] = leader_image;
cfg_summary[z_map_data] = "";
cfg_summary[z_map_data] = z_empty;
if(!shrouded) {
if(has_snapshot) {
@ -578,6 +577,7 @@ config::attribute_value &game_state::get_variable(const config::t_token& key) {
return variable_info(key, true, variable_info::TYPE_SCALAR).as_scalar(); }
config::attribute_value game_state::get_variable_const(const config::t_token &key) const {
variable_info to_get(key, false, variable_info::TYPE_SCALAR);
if (!to_get.is_valid()) {
config::attribute_value &to_return = temporaries_[key];
@ -607,7 +607,7 @@ config& game_state::add_variable_cfg(const config::t_token& key, const config& v
void game_state::clear_variable_cfg(const config::t_token& varname) {
variable_info to_clear(varname, false, variable_info::TYPE_CONTAINER);
if(!to_clear.is_valid()) return;
if(to_clear.explicit_index) {
if(to_clear.is_explicit_index()) {
to_clear.vars->remove_child(to_clear.key, to_clear.index);
} else {
to_clear.vars->clear_children(to_clear.key);
@ -617,7 +617,7 @@ void game_state::clear_variable_cfg(const config::t_token& varname) {
void game_state::clear_variable(const config::t_token& varname) {
variable_info to_clear(varname, false);
if(!to_clear.is_valid()) return;
if(to_clear.explicit_index) {
if(to_clear.is_explicit_index()) {
to_clear.vars->remove_child(to_clear.key, to_clear.index);
} else {
to_clear.vars->clear_children(to_clear.key);

View File

@ -34,6 +34,14 @@
#include <cassert>
#include <ctime>
namespace {
//Static tokens are replacements for string literals in code
//They allow for fast comparison operations.
static const config::t_token z_swarm("swarm", false);
static const config::t_token z_swarm_attacks_min("swarm_attacks_min", false);
static const config::t_token z_swarm_attacks_max("swarm_attacks_max", false);
}
static void add_text(config &report, const std::string &text,
const std::string &tooltip, const std::string &help = "")
{
@ -432,11 +440,11 @@ REPORT_GENERATOR(unit_weapons)
int base_nattacks = at.num_attacks();
int nattacks = base_nattacks;
unit_ability_list swarm = at.get_specials("swarm");
unit_ability_list swarm = at.get_specials(z_swarm);
if (!swarm.empty())
{
int swarm_max_attacks = swarm.highest("swarm_attacks_max", nattacks).first;
int swarm_min_attacks = swarm.highest("swarm_attacks_min").first;
int swarm_max_attacks = swarm.highest(z_swarm_attacks_max, nattacks).first;
int swarm_min_attacks = swarm.highest(z_swarm_attacks_min).first;
int hitp = u->hitpoints();
int mhitp = u->max_hitpoints();
nattacks = swarm_min_attacks + (swarm_max_attacks - swarm_min_attacks) * hitp / mhitp;

View File

@ -1342,12 +1342,12 @@ static int intf_fire_event(lua_State *L)
static int intf_get_variable(lua_State *L)
{
char const *m = luaL_checkstring(L, 1);
variable_info v(m, false, variable_info::TYPE_SCALAR);
variable_info v(config::t_token(m), false, variable_info::TYPE_SCALAR);
if (v.is_valid()) {
luaW_pushscalar(L, v.as_scalar());
return 1;
} else {
variable_info w(m, false, variable_info::TYPE_CONTAINER);
variable_info w(config::t_token(m), false, variable_info::TYPE_CONTAINER);
if (w.is_valid()) {
lua_newtable(L);
if (lua_toboolean(L, 2))
@ -1371,7 +1371,8 @@ static int intf_set_variable(lua_State *L)
return 0;
}
variable_info v(m);
config::t_token mm(m);
variable_info v(mm);
switch (lua_type(L, 2)) {
case LUA_TBOOLEAN:
v.as_scalar() = bool(lua_toboolean(L, 2));

View File

@ -371,7 +371,7 @@ void terrain_filter::get_locations(t_maploc_set& locs, bool with_border, gamemap
variable_info vi(cfg_[z_find_in].token(), false, variable_info::TYPE_CONTAINER);
if(!vi.is_valid()) {
xy_set.clear();
} else if(vi.explicit_index) {
} else if(vi.is_explicit_index()) {
map_location test_loc(vi.as_container(),NULL);
if(xy_set.count(test_loc)) {
xy_set.clear();

View File

@ -42,7 +42,7 @@ namespace{
BOOST_AUTO_TEST_CASE( test_1 ) {
#ifdef DEBUG
lg::set_log_domain_severity("interpolate", 0); //4 is debug comments
// lg::set_log_domain_severity("interpolate", 0); //4 is debug comments
#endif
utils::string_map symbols;
std::string nothing = "no change";

View File

@ -0,0 +1,67 @@
/* $Id$ */
/*
Copyright (C) 2008 - 2011 by Pauli Nieminen <paniemin@cc.hut.fi>
Part of thie Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include <boost/test/unit_test.hpp>
#include "utils/lru_cache.hpp"
#include "log.hpp"
/*
./test --report_level=detailed --log_level=all --run_test=lru_cache_suite
*/
BOOST_AUTO_TEST_SUITE( lru_cache_suite )
namespace{
static const uint CACHE_SIZE = 10;
static const uint STEP_SIZE = 1000;
void check_equal(int l, int r) {
int ll(l + STEP_SIZE);
BOOST_CHECK_MESSAGE(ll == r, "\nLeft \""<< ll <<"\"" << "should equal right \""<<r<<"\"\n"); }
void check_not_equal(int l, int r) {
int ll(l + STEP_SIZE);
BOOST_CHECK_MESSAGE(ll != r, "\nLeft \""<< ll <<"\"" << "should not equal right \""<<r<<"\"\n"); }
struct t_gen_cache_item {
int operator()(int const & in) const {
return in + STEP_SIZE ; }
};
}
BOOST_AUTO_TEST_CASE( test_lru_cache1 ) {
typedef n_lru_cache::t_lru_cache<int, int, t_gen_cache_item> t_cache;
static t_cache cache( t_gen_cache_item(), CACHE_SIZE);
for (int i = 1; i<20; ++i){
int from_cache(cache.check( i ));
int hit_me(cache.check( 1 ));
cache.invalidate(4);
check_equal(1, hit_me);
check_equal(i, from_cache);
}
}
/* vim: set ts=4 sw=4: */
BOOST_AUTO_TEST_SUITE_END()

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,17 @@ class game_display;
class game_state;
class vconfig;
class team;
typedef std::vector<team> t_teams;
namespace{
static const config::t_token z_description("description", false);
// static const config::t_token z_advancement("advancement", false);
static const config::t_token z_ellipse("ellipse", false);
static const config::t_token z_image("image", false);
static const config::t_token z_halo("halo", false);
static const config::t_token z_usage("usage", false);
//static const config::t_token z_("", false);
}
class unit_ability_list
{
@ -37,8 +48,8 @@ public:
bool empty() const;
std::pair<int,map_location> highest(const std::string& key, int def=0) const;
std::pair<int,map_location> lowest(const std::string& key, int def=0) const;
std::pair<int,map_location> highest(const config::t_token& key, int def=0) const;
std::pair<int,map_location> lowest(const config::t_token& key, int def=0) const;
std::vector<std::pair<const config *, map_location> > cfgs;
};
@ -85,24 +96,24 @@ public:
const unit_type* type() const;
/** id assigned by wml */
const std::string& id() const { if (id_.empty()) return type_name(); else return id_; }
const std::string& id() const { if (id_.empty()){ return type_name();} else return id_; }
/** The unique internal ID of the unit */
size_t underlying_id() const { return underlying_id_; }
/** The unit type name */
const t_string& type_name() const {return type_name_;}
const std::string& undead_variation() const {return undead_variation_;}
const config::t_token& undead_variation() const {return undead_variation_;}
/** The unit name for display */
const t_string &name() const { return name_; }
void set_name(const t_string &name) { name_ = name; }
void rename(const std::string& name) {if (!unrenamable_) name_= name;}
void rename(const std::string& name) {if (!unrenamable_) name_= t_string(name);}
/** The unit's profile */
std::string small_profile() const;
std::string big_profile() const;
/** Information about the unit -- a detailed description of it */
t_string unit_description() const { return cfg_["description"]; }
t_string unit_description() const { return cfg_[z_description]; }
int hitpoints() const { return hit_points_; }
int max_hitpoints() const { return max_hit_points_; }
@ -122,7 +133,7 @@ public:
bool unrenamable() const { return unrenamable_; }
int side() const { return side_; }
std::string side_id() const;
const std::string& team_color() const { return flag_rgb_; }
const config::t_token& team_color() const { return flag_rgb_; }
unit_race::GENDER gender() const { return gender_; }
void set_side(unsigned int new_side) { side_ = new_side; }
fixed_t alpha() const { return alpha_; }
@ -157,35 +168,43 @@ public:
bool resting() const { return resting_; }
void set_resting(bool rest) { resting_ = rest; }
const std::map<std::string,std::string> get_states() const;
bool get_state(const std::string& state) const;
void set_state(const std::string &state, bool value);
const std::map<config::t_token,config::t_token> get_states() const;
bool get_state(const config::t_token& state) const;
void set_state(const config::t_token &state, bool value);
enum state_t { STATE_SLOWED = 0, STATE_POISONED, STATE_PETRIFIED,
STATE_UNCOVERED, STATE_NOT_MOVED, STATE_UNHEALABLE, STATE_UNKNOWN = -1 };
void set_state(state_t state, bool value);
bool get_state(state_t state) const;
static state_t get_known_boolean_state_id(const std::string &state);
static std::map<std::string, state_t> get_known_boolean_state_names();
static state_t get_known_boolean_state_id(const config::t_token &state);
static std::map<config::t_token, state_t> get_known_boolean_state_names();
bool has_moved() const { return movement_left() != total_movement(); }
bool has_goto() const { return get_goto().valid(); }
bool emits_zoc() const { return emit_zoc_ && !incapacitated();}
bool matches_id(const std::string& unit_id) const;
bool matches_idt(const config::t_token& unit_id) const{ return id_ == unit_id; }
bool matches_id(const std::string& unit_id) const {return matches_idt(config::t_token(unit_id));}
/* cfg: standard unit filter */
bool matches_filter(const vconfig& cfg,const map_location& loc,bool use_flat_tod=false) const;
bool matches_filter(const vconfig& cfg,const map_location& loc,bool use_flat_tod=false
, gamemap const & game_map = *resources::game_map
, unit_map const & units =*resources::units
, t_teams const & teams = *resources::teams
, LuaKernel & lua_kernel = *resources::lua_kernel
, tod_manager const & tod_manager = *resources::tod_manager) const;
const std::vector<std::string>& overlays() const { return overlays_; }
void write(config& cfg) const;
void set_role(const std::string& role) { role_ = role; }
const std::string &get_role() const { return role_; }
void set_role(const config::t_token& role) { role_ = role; }
void set_role(const std::string& role) { set_role(role);}
const config::t_token &get_role() const { return role_; }
void assign_ai_special(const std::string& s) { ai_special_ = s;}
std::string get_ai_special() const { return(ai_special_); }
void assign_ai_special(const config::t_token& s) { ai_special_ = s;}
config::t_token get_ai_special() const { return(ai_special_); }
const std::vector<attack_type>& attacks() const { return attacks_; }
std::vector<attack_type>& attacks() { return attacks_; }
int damage_from(const attack_type& attack,bool attacker,const map_location& loc) const { return resistance_against(attack,attacker,loc); }
int damage_from(const attack_type& attack,bool attacker,const map_location& loc) const {
return resistance_against(attack,attacker,loc); }
/** A SDL surface, ready for display for place where we need a still-image of the unit. */
const surface still_image(bool scaled = false) const;
@ -210,7 +229,7 @@ public:
bool invalidate(const map_location &loc);
const std::vector<t_string>& trait_names() const { return trait_names_; }
const std::vector<t_string>& trait_descriptions() const { return trait_descriptions_; }
std::vector<std::string> get_traits_list() const;
std::vector<config::t_token> get_traits_list() const;
int cost () const { return unit_value_; }
@ -229,11 +248,11 @@ public:
bool is_flying() const { return flying_; }
bool is_fearless() const { return is_fearless_; }
bool is_healthy() const { return is_healthy_; }
int movement_cost(const t_translation::t_terrain terrain) const;
int defense_modifier(t_translation::t_terrain terrain) const;
int movement_cost(const t_translation::t_terrain terrain, gamemap const & game_map = *resources::game_map) const;
int defense_modifier(t_translation::t_terrain terrain, gamemap const & game_map = *resources::game_map ) const;
int resistance_against(const std::string& damage_name,bool attacker,const map_location& loc) const;
int resistance_against(const attack_type& damage_type,bool attacker,const map_location& loc) const
{return resistance_against(damage_type.type(), attacker, loc);};
int resistance_against(const attack_type& damage_type,bool attacker,const map_location& loc) const {
return resistance_against(damage_type.type(), attacker, loc);};
//return resistances without any abilities applied
utils::string_map get_base_resistances() const;
@ -247,12 +266,16 @@ public:
std::vector<config> get_modification_advances() const;
config::const_child_itors modification_advancements() const
{ return cfg_.child_range("advancement"); }
{ return cfg_.child_range(z_advancement); }
size_t modification_count(const std::string& type, const std::string& id) const;
size_t modification_count(const config::t_token& type, const std::string& id) const;
void add_modification(const std::string& type, const config& modification,
bool no_add=false);
void add_modification(const config::t_token& type, const config& mod, bool no_add=false
, gamemap const & game_map = *resources::game_map
, unit_map const & units =*resources::units
, t_teams const & teams = *resources::teams
, LuaKernel & lua_kernel = *resources::lua_kernel
, tod_manager const & tod_manager = *resources::tod_manager);
bool move_interrupted() const { return movement_left() > 0 && interrupted_move_.x >= 0 && interrupted_move_.y >= 0; }
const map_location& get_interrupted_move() const { return interrupted_move_; }
@ -268,15 +291,15 @@ public:
Uint32 text_color = 0, STATE state = STATE_ANIM);
/** The name of the file to game_display (used in menus). */
std::string absolute_image() const { return cfg_["image"]; }
std::string image_halo() const { return cfg_["halo"]; }
std::string absolute_image() const { return cfg_[z_image]; }
config::t_token image_halo() const { return cfg_[z_halo]; }
std::string image_ellipse() const { return cfg_["ellipse"]; }
config::t_token image_ellipse() const { return cfg_[z_ellipse]; }
config &variables() { return variables_; }
const config &variables() const { return variables_; }
std::string usage() const { return cfg_["usage"]; }
config::t_token usage() const { return cfg_[z_usage]; }
unit_type::ALIGNMENT alignment() const { return alignment_; }
const unit_race* race() const { return race_; }
@ -288,15 +311,32 @@ public:
const attack_type* attack=NULL,const attack_type* second_attack = NULL,
int swing_num =0) const;
bool get_ability_bool(const std::string& ability, const map_location& loc) const;
bool get_ability_bool(const std::string &ability) const
{ return get_ability_bool(ability, loc_); }
unit_ability_list get_abilities(const std::string &ability, const map_location& loc) const;
unit_ability_list get_abilities(const std::string &ability) const
{ return get_abilities(ability, loc_); }
bool get_ability_bool(const config::t_token& ability, const map_location& loc
, gamemap const & game_map = *resources::game_map
, unit_map const & units =*resources::units
, t_teams const & teams = *resources::teams
, LuaKernel & lua_kernel = *resources::lua_kernel
, tod_manager const & tod_manager = *resources::tod_manager) const;
bool get_ability_bool(const config::t_token& ability
, gamemap const & game_map = *resources::game_map
, unit_map const & units =*resources::units
, t_teams const & teams = *resources::teams
, LuaKernel & lua_kernel = *resources::lua_kernel
, tod_manager const & tod_manager = *resources::tod_manager) const {
return get_ability_bool(ability, loc_, game_map, units, teams, lua_kernel, tod_manager);}
inline bool get_ability_bool(const std::string& ability, const map_location& loc ) const {
return get_ability_bool(config::t_token(ability), loc); }
inline bool get_ability_bool(const std::string& ability) const {
return get_ability_bool(config::t_token(ability), loc_); }
unit_ability_list get_abilities(const config::t_token &ability, const map_location& loc) const;
unit_ability_list get_abilities(const config::t_token &ability) const {return get_abilities(ability, loc_); }
unit_ability_list get_abilities(const std::string &ability, const map_location& loc) const {
return get_abilities(config::t_token(ability), loc);}
unit_ability_list get_abilities(const std::string &ability) const {return get_abilities(config::t_token(ability), loc_); }
std::vector<std::string> ability_tooltips(bool force_active = false) const;
std::vector<std::string> get_ability_list() const;
bool has_ability_type(const std::string& ability) const;
bool has_ability_type(const config::t_token& ability) const;
bool has_ability_type(const std::string& ability) const {return has_ability_type(config::t_token(ability));}
const game_logic::map_formula_callable_ptr& formula_vars() const { return formula_vars_; }
void add_formula_var(std::string str, variant var);
@ -313,7 +353,7 @@ public:
void generate_name(rand_rng::simple_rng *rng = 0);
// Only see_all=true use caching
bool invisible(const map_location& loc, bool see_all=true) const;
bool invisible(const map_location& loc, bool see_all=true,unit_map const & units = *resources::units, t_teams const & teams = *resources::teams) const;
/** Mark this unit as clone so it can be inserted to unit_map
* @returns self (for convenience)
@ -338,15 +378,37 @@ public:
private:
void advance_to(const config &old_cfg, const unit_type *t,
bool use_traits, game_state *state);
bool internal_matches_filter(const vconfig& cfg, const map_location& loc, bool use_flat_tod
, gamemap const & game_map = *resources::game_map
, unit_map const & units =*resources::units
, t_teams const & teams = *resources::teams
, LuaKernel & lua_kernel = *resources::lua_kernel
, tod_manager const & tod_manager = *resources::tod_manager) const;
bool internal_matches_filter(const vconfig& cfg,const map_location& loc,
bool use_flat_tod) const;
/*
* cfg: an ability WML structure
*/
bool ability_active(const std::string& ability,const config& cfg,const map_location& loc) const;
bool ability_affects_adjacent(const std::string& ability,const config& cfg,int dir,const map_location& loc) const;
bool ability_affects_self(const std::string& ability,const config& cfg,const map_location& loc) const;
bool ability_active(const std::string& ability,const config& cfg,const map_location& loc
, gamemap const & game_map = *resources::game_map
, unit_map const & units =*resources::units
, t_teams const & teams = *resources::teams
, LuaKernel & lua_kernel = *resources::lua_kernel
, tod_manager const & tod_manager = *resources::tod_manager) const;
bool ability_affects_adjacent(const std::string& ability,const config& cfg,int dir,const map_location& loc
, gamemap const & game_map = *resources::game_map
, unit_map const & units =*resources::units
, t_teams const & teams = *resources::teams
, LuaKernel & lua_kernel = *resources::lua_kernel
, tod_manager const & tod_manager = *resources::tod_manager) const;
bool ability_affects_self(const std::string& ability,const config& cfg,const map_location& loc
, gamemap const & game_map = *resources::game_map
, unit_map const & units =*resources::units
, t_teams const & teams = *resources::teams
, LuaKernel & lua_kernel = *resources::lua_kernel
, tod_manager const & tod_manager = *resources::tod_manager) const;
bool resistance_filter_matches(const config& cfg,bool attacker,const std::string& damage_name, int res) const;
bool has_ability_by_id(const std::string& ability) const;
@ -363,12 +425,12 @@ private:
std::vector<std::string> advances_to_;
std::string type_;
const unit_race* race_;
std::string id_;
config::t_token id_;
t_string name_;
size_t underlying_id_;
t_string type_name_;
std::string undead_variation_;
std::string variation_;
config::t_token undead_variation_;
config::t_token variation_;
int hit_points_;
int max_hit_points_;
@ -378,7 +440,7 @@ private:
bool canrecruit_;
std::vector<std::string> recruit_list_;
unit_type::ALIGNMENT alignment_;
std::string flag_rgb_;
config::t_token flag_rgb_;
std::string image_mods_;
bool unrenamable_;
@ -402,17 +464,17 @@ private:
int attacks_left_;
int max_attacks_;
std::set<std::string> states_;
std::set<config::t_token> states_;
std::vector<bool> known_boolean_states_;
static std::map<std::string, state_t> known_boolean_state_names_;
static std::map<config::t_token, state_t> known_boolean_state_names_;
config variables_;
bool emit_zoc_;
STATE state_;
std::vector<std::string> overlays_;
std::string role_;
std::string ai_special_;
config::t_token role_;
config::t_token ai_special_;
std::vector<attack_type> attacks_;
map_location::DIRECTION facing_;
@ -444,7 +506,7 @@ private:
friend void attack_type::set_specials_context(const map_location& loc, const map_location&, const unit& un, bool) const;
/** Hold the visibility status cache for a unit, mutable since it's a cache. */
mutable std::map<map_location, bool> invisibility_cache_;
mutable boost::unordered_map<map_location, bool> invisibility_cache_;
/**
* Clears the cache.
@ -467,18 +529,21 @@ private:
};
/** Returns the number of units of the side @a side_num. */
int side_units(int side_num);
int side_units(int side_num, unit_map const & units = *resources::units) ;
/** Returns the total cost of units of side @a side_num. */
int side_units_cost(int side_num);
int side_units_cost(int side_num, unit_map const & units = *resources::units);
int side_upkeep(int side_num);
int side_upkeep(int side_num, unit_map const & units = *resources::units);
unit_map::iterator find_visible_unit(const map_location &loc,
const team &current_team, bool see_all = false);
//The ackward orderding here allows the linker to disambiguate the return type using the passed in unit_map
unit_map::const_iterator find_visible_unit(unit_map const & units, const map_location &loc, const team &current_team, bool const see_all = false, gamemap const & map = *resources::game_map);
unit_map::iterator find_visible_unit(unit_map & units, const map_location &loc, const team &current_team, bool const see_all = false, gamemap const & map = *resources::game_map);
unit *get_visible_unit(const map_location &loc,
const team &current_team, bool see_all = false);
inline unit_map::iterator find_visible_unit(const map_location &loc, const team &current_team, bool const see_all = false) {
return find_visible_unit( *resources::units, loc, current_team, see_all, *resources::game_map); }
unit *get_visible_unit(const map_location &loc, const team &current_team, bool const see_all = false, gamemap const & map = *resources::game_map, unit_map & units = *resources::units);
struct team_data
{

View File

@ -105,40 +105,100 @@ A poisoned unit cannot be cured of its poison by a healer, and must seek the car
*/
namespace {
//Static tokens are replacements for string literals in code
//They allow for fast comparison operations.
static const config::t_token z_affect_allies("affect_allies", false);
static const config::t_token z_affect_enemies("affect_enemies", false);
static const config::t_token z_affect_self("affect_self", false);
static const config::t_token z_abilities("abilities", false);
static const config::t_token z_id("id", false);
static const config::t_token z_female("female", false);
static const config::t_token z_female_name("female_name", false);
static const config::t_token z_name("name", false);
static const config::t_token z_name_inactive("name_inactive", false);
static const config::t_token z_female_name_inactive("female_name_inactive", false);
static const config::t_token z_description_inactive("description_inactive", false);
static const config::t_token z_illuminates("illuminates", false);
static const config::t_token z_filter("filter", false);
static const config::t_token z_filter_adjacent("filter_adjacent", false);
static const config::t_token z_filter_adjacent_location("filter_adjacent_location", false);
static const config::t_token z_adjacent("adjacent", false);
static const config::t_token z_n("n", false);
static const config::t_token z_ne("ne", false);
static const config::t_token z_se("se", false);
static const config::t_token z_s("s", false);
static const config::t_token z_sw("sw", false);
static const config::t_token z_nw("nw", false);
static const config::t_token z_affect_adjacent("affect_adjacent", false);
static const config::t_token z_filter_self("filter_self", false);
static const config::t_token z_cumulative("cumulative", false);
static const config::t_token z_specials("specials", false);
static const config::t_token z_apply_to("apply_to", false);
static const config::t_token z_both("both", false);
static const config::t_token z_opponent("opponent", false);
static const config::t_token z_defender("defender", false);
static const config::t_token z_attacker("attacker", false);
static const config::t_token z_filter_base_value("filter_base_value", false);
static const config::t_token z_equals("equals", false);
static const config::t_token z_not_equals("not_equals", false);
static const config::t_token z_less_than("less_than", false);
static const config::t_token z_greater_than("greater_than", false);
static const config::t_token z_greater_than_equal_to("greater_than_equal_to", false);
static const config::t_token z_less_than_equal_to("less_than_equal_to", false);
static const config::t_token z_backstab("backstab", false);
static const config::t_token z_value("value", false);
static const config::t_token z_add("add", false);
static const config::t_token z_sub("sub", false);
static const config::t_token z_multiply("multiply", false);
static const config::t_token z_active_on("active_on", false);
static const config::t_token z_offense("offense", false);
static const config::t_token z_filter_weapon("filter_weapon", false);
static const config::t_token z_filter_opponent("filter_opponent", false);
static const config::t_token z_defense("defense", false);
static const config::t_token z_filter_attacker("filter_attacker", false);
static const config::t_token z_filter_defender("filter_defender", false);
static const config::t_token z_self("self", false);
static const config::t_token z_divide("divide", false);
// static const config::t_token z_("", false);
// static const config::t_token z_("", false);
// static const config::t_token z_("", false);
}
namespace unit_abilities {
static bool affects_side(const config& cfg, const std::vector<team>& teams, size_t side, size_t other_side)
static bool affects_side(const config& cfg, const t_teams& teams, size_t side, size_t other_side)
{
if (side == other_side)
return cfg["affect_allies"].to_bool(true);
return cfg[z_affect_allies].to_bool(true);
if (teams[side - 1].is_enemy(other_side))
return cfg["affect_enemies"].to_bool();
return cfg[z_affect_enemies].to_bool();
else
return cfg["affect_allies"].to_bool();
return cfg[z_affect_allies].to_bool();
}
}
bool unit::get_ability_bool(const std::string& ability, const map_location& loc) const
bool unit::get_ability_bool(const config::t_token& ability, const map_location& loc, gamemap const & game_map, unit_map const & units, t_teams const & teams, LuaKernel & lua_kernel, tod_manager const & tod_manager) const
{
if (const config &abilities = cfg_.child("abilities"))
if (const config &abilities = cfg_.child(z_abilities))
{
foreach (const config &i, abilities.child_range(ability)) {
if (ability_active(ability, i, loc) &&
ability_affects_self(ability, i, loc))
if (ability_active(ability, i, loc, game_map, units, teams, lua_kernel, tod_manager)
&& ability_affects_self(ability, i, loc))
return true;
}
}
const unit_map& units = *resources::units;
//const unit_map& units = *resources::units;
map_location adjacent[6];
get_adjacent_tiles(loc,adjacent);
for(int i = 0; i != 6; ++i) {
const unit_map::const_iterator it = units.find(adjacent[i]);
if (it == units.end() || it->incapacitated())
continue;
const config &adj_abilities = it->cfg_.child("abilities");
const config &adj_abilities = it->cfg_.child(z_abilities);
if (!adj_abilities)
continue;
foreach (const config &j, adj_abilities.child_range(ability)) {
@ -152,11 +212,11 @@ bool unit::get_ability_bool(const std::string& ability, const map_location& loc)
return false;
}
unit_ability_list unit::get_abilities(const std::string& ability, const map_location& loc) const
unit_ability_list unit::get_abilities(const config::t_token& ability, const map_location& loc) const
{
unit_ability_list res;
if (const config &abilities = cfg_.child("abilities"))
if (const config &abilities = cfg_.child(z_abilities))
{
foreach (const config &i, abilities.child_range(ability)) {
if (ability_active(ability, i, loc) &&
@ -172,7 +232,7 @@ unit_ability_list unit::get_abilities(const std::string& ability, const map_loca
const unit_map::const_iterator it = units.find(adjacent[i]);
if (it == units.end() || it->incapacitated())
continue;
const config &adj_abilities = it->cfg_.child("abilities");
const config &adj_abilities = it->cfg_.child(z_abilities);
if (!adj_abilities)
continue;
foreach (const config &j, adj_abilities.child_range(ability)) {
@ -191,10 +251,10 @@ std::vector<std::string> unit::get_ability_list() const
{
std::vector<std::string> res;
const config &abilities = cfg_.child("abilities");
const config &abilities = cfg_.child(z_abilities);
if (!abilities) return res;
foreach (const config::any_child &ab, abilities.all_children_range()) {
std::string const &id = ab.cfg["id"];
std::string const &id = ab.cfg[z_id];
if (!id.empty())
res.push_back(id);
}
@ -205,7 +265,7 @@ std::vector<std::string> unit::ability_tooltips(bool force_active) const
{
std::vector<std::string> res;
const config &abilities = cfg_.child("abilities");
const config &abilities = cfg_.child(z_abilities);
if (!abilities) return res;
foreach (const config::any_child &ab, abilities.all_children_range())
@ -213,23 +273,23 @@ std::vector<std::string> unit::ability_tooltips(bool force_active) const
if (force_active || ability_active(ab.key, ab.cfg, loc_))
{
std::string const &name =
gender_ == unit_race::MALE || ab.cfg["female_name"].empty() ?
ab.cfg["name"] : ab.cfg["female_name"];
gender_ == unit_race::MALE || ab.cfg[z_female_name].empty() ?
ab.cfg[z_name] : ab.cfg[z_female_name];
if (!name.empty()) {
res.push_back(name);
res.push_back(ab.cfg["description"]);
res.push_back(ab.cfg[z_description]);
}
}
else
{
std::string const &name =
gender_ == unit_race::MALE || ab.cfg["female_name_inactive"].empty() ?
ab.cfg["name_inactive"] : ab.cfg["female_name_inactive"];
gender_ == unit_race::MALE || ab.cfg[z_female_name_inactive].empty() ?
ab.cfg[z_name_inactive] : ab.cfg[z_female_name_inactive];
if (!name.empty()) {
res.push_back(name);
res.push_back(ab.cfg["description_inactive"]);
res.push_back(ab.cfg[z_description_inactive]);
}
}
}
@ -244,26 +304,29 @@ std::vector<std::string> unit::ability_tooltips(bool force_active) const
static bool cache_illuminates(int &cache, std::string const &ability)
{
if (cache < 0)
cache = (ability == "illuminates");
cache = (ability == z_illuminates);
return (cache != 0);
}
bool unit::ability_active(const std::string& ability,const config& cfg,const map_location& loc) const
bool unit::ability_active(const std::string& ability,const config& cfg,const map_location& loc
, gamemap const & game_map, unit_map const & units
, t_teams const & teams, LuaKernel & lua_kernel
, tod_manager const & tod_manager) const
{
int illuminates = -1;
assert(resources::units && resources::game_map && resources::teams && resources::tod_manager);
//assert(resources::units && resources::game_map && resources::teams && resources::tod_manager);
if (const config &afilter = cfg.child("filter"))
if (!matches_filter(vconfig(afilter), loc, cache_illuminates(illuminates, ability)))
if (const config &afilter = cfg.child(z_filter))
if (!matches_filter(vconfig(afilter), loc, cache_illuminates(illuminates, ability),game_map, units, teams, lua_kernel, tod_manager))
return false;
map_location adjacent[6];
get_adjacent_tiles(loc,adjacent);
const unit_map& units = *resources::units;
//const unit_map& units = *resources::units;
foreach (const config &i, cfg.child_range("filter_adjacent"))
foreach (const config &i, cfg.child_range(z_filter_adjacent))
{
foreach (const std::string &j, utils::split(i["adjacent"]))
foreach (const std::string &j, utils::split(i[z_adjacent]))
{
map_location::DIRECTION index =
map_location::parse_direction(j);
@ -273,14 +336,14 @@ bool unit::ability_active(const std::string& ability,const config& cfg,const map
if (unit == units.end())
return false;
if (!unit->matches_filter(vconfig(i), unit->get_location(),
cache_illuminates(illuminates, ability)))
cache_illuminates(illuminates, ability), game_map, units, teams, lua_kernel, tod_manager))
return false;
}
}
foreach (const config &i, cfg.child_range("filter_adjacent_location"))
foreach (const config &i, cfg.child_range(z_filter_adjacent_location))
{
foreach (const std::string &j, utils::split(i["adjacent"]))
foreach (const std::string &j, utils::split(i[z_adjacent]))
{
map_location::DIRECTION index = map_location::parse_direction(j);
if (index == map_location::NDIRECTIONS) {
@ -300,19 +363,24 @@ bool unit::ability_active(const std::string& ability,const config& cfg,const map
* cfg: an ability WML structure
*
*/
bool unit::ability_affects_adjacent(const std::string& ability, const config& cfg,int dir,const map_location& loc) const
bool unit::ability_affects_adjacent(const std::string& ability, const config& cfg,int dir,
const map_location& loc,
gamemap const & game_map, unit_map const & units,
t_teams const & teams, LuaKernel & lua_kernel,
tod_manager const & tod_manager
) const
{
int illuminates = -1;
assert(dir >=0 && dir <= 5);
static const std::string adjacent_names[6] = {"n","ne","se","s","sw","nw"};
foreach (const config &i, cfg.child_range("affect_adjacent"))
static const std::string adjacent_names[6] = {z_n,z_ne,z_se,z_s,z_sw,z_nw};
foreach (const config &i, cfg.child_range(z_affect_adjacent))
{
std::vector<std::string> dirs = utils::split(i["adjacent"]);
std::vector<std::string> dirs = utils::split(i[z_adjacent]);
if(std::find(dirs.begin(),dirs.end(),adjacent_names[dir]) != dirs.end()) {
if (const config &filter = i.child("filter")) {
if (const config &filter = i.child(z_filter)) {
if (matches_filter(vconfig(filter), loc,
cache_illuminates(illuminates, ability)))
cache_illuminates(illuminates, ability), game_map, units, teams, lua_kernel, tod_manager))
return true;
} else
return true;
@ -325,18 +393,22 @@ bool unit::ability_affects_adjacent(const std::string& ability, const config& cf
* cfg: an ability WML structure
*
*/
bool unit::ability_affects_self(const std::string& ability,const config& cfg,const map_location& loc) const
{
bool unit::ability_affects_self(const std::string& ability,const config& cfg,const map_location& loc
, gamemap const & game_map, unit_map const & units
, t_teams const & teams, LuaKernel & lua_kernel
, tod_manager const & tod_manager
) const {
int illuminates = -1;
const config &filter = cfg.child("filter_self");
bool affect_self = cfg["affect_self"].to_bool(true);
const config &filter = cfg.child(z_filter_self);
bool affect_self = cfg[z_affect_self].to_bool(true);
if (!filter || !affect_self) return affect_self;
return matches_filter(vconfig(filter), loc,cache_illuminates(illuminates, ability));
return matches_filter(vconfig(filter),
loc, cache_illuminates(illuminates, ability),game_map, units, teams, lua_kernel, tod_manager);
}
bool unit::has_ability_type(const std::string& ability) const
bool unit::has_ability_type(const config::t_token& ability) const
{
if (const config &list = cfg_.child("abilities")) {
if (const config &list = cfg_.child(z_abilities)) {
config::const_child_itors itors = list.child_range(ability);
return itors.first != itors.second;
}
@ -349,8 +421,7 @@ bool unit_ability_list::empty() const
return cfgs.empty();
}
std::pair<int,map_location> unit_ability_list::highest(const std::string& key, int def) const
{
std::pair<int,map_location> unit_ability_list::highest(const config::t_token& key, int def) const {
if (cfgs.empty()) {
return std::make_pair(def, map_location());
}
@ -365,7 +436,7 @@ std::pair<int,map_location> unit_ability_list::highest(const std::string& key, i
foreach (pt const &p, cfgs)
{
int value = (*p.first)[key].to_int(def);
if ((*p.first)["cumulative"].to_bool()) {
if ((*p.first)[z_cumulative].to_bool()) {
stack += value;
if (value < 0) value = -value;
if (only_cumulative && value >= abs_max) {
@ -381,7 +452,7 @@ std::pair<int,map_location> unit_ability_list::highest(const std::string& key, i
return std::make_pair(flat + stack, best_loc);
}
std::pair<int,map_location> unit_ability_list::lowest(const std::string& key, int def) const
std::pair<int,map_location> unit_ability_list::lowest(const config::t_token& key, int def) const
{
if (cfgs.empty()) {
return std::make_pair(def, map_location());
@ -397,7 +468,7 @@ std::pair<int,map_location> unit_ability_list::lowest(const std::string& key, in
foreach (pt const &p, cfgs)
{
int value = (*p.first)[key].to_int(def);
if ((*p.first)["cumulative"].to_bool()) {
if ((*p.first)[z_cumulative].to_bool()) {
stack += value;
if (value < 0) value = -value;
if (only_cumulative && value <= abs_max) {
@ -443,10 +514,10 @@ std::pair<int,map_location> unit_ability_list::lowest(const std::string& key, in
namespace {
bool get_special_children(std::vector<const config*>& result, const config& parent,
const std::string& id, bool just_peeking=false) {
const config::t_token& id, bool just_peeking=false) {
foreach (const config::any_child &sp, parent.all_children_range())
{
if (sp.key == config::t_token(id) || sp.cfg["id"] == config::t_token(id)) {
if (sp.key == id || sp.cfg[z_id] == id) {
if(just_peeking) {
return true; // peek succeeded, abort
} else {
@ -458,10 +529,10 @@ namespace {
}
}
bool attack_type::get_special_bool(const std::string& special,bool force) const
bool attack_type::get_special_bool(const config::t_token& special,bool force) const
{
// log_scope("get_special_bool");
if (const config &specials = cfg_.child("specials"))
if (const config &specials = cfg_.child(z_specials))
{
std::vector<const config*> list;
if (get_special_children(list, specials, special, force)) return true;
@ -472,7 +543,7 @@ bool attack_type::get_special_bool(const std::string& special,bool force) const
}
}
if (force || !other_attack_) return false;
if (const config &specials = other_attack_->cfg_.child("specials"))
if (const config &specials = other_attack_->cfg_.child(z_specials))
{
std::vector<const config*> list;
get_special_children(list, specials, special);
@ -485,11 +556,10 @@ bool attack_type::get_special_bool(const std::string& special,bool force) const
return false;
}
unit_ability_list attack_type::get_specials(const std::string& special) const
{
unit_ability_list attack_type::get_specials(const config::t_token& special) const {
// log_scope("get_specials");
unit_ability_list res;
if (const config &specials = cfg_.child("specials"))
if (const config &specials = cfg_.child(z_specials))
{
foreach (const config &i, specials.child_range(special)) {
if (special_active(i, true))
@ -498,7 +568,7 @@ unit_ability_list attack_type::get_specials(const std::string& special) const
}
}
if (!other_attack_) return res;
if (const config &specials = other_attack_->cfg_.child("specials"))
if (const config &specials = other_attack_->cfg_.child(z_specials))
{
foreach (const config &i, specials.child_range(special)) {
if (other_attack_->special_active(i, false))
@ -512,22 +582,22 @@ std::vector<t_string> attack_type::special_tooltips(bool force) const
{
// log_scope("special_tooltips");
std::vector<t_string> res;
const config &specials = cfg_.child("specials");
const config &specials = cfg_.child(z_specials);
if (!specials) return res;
foreach (const config::any_child &sp, specials.all_children_range())
{
if (force || special_active(sp.cfg, true)) {
const t_string &name = sp.cfg["name"];
const t_string &name = sp.cfg[z_name];
if (!name.empty()) {
res.push_back(name);
res.push_back(sp.cfg["description"]);
res.push_back(sp.cfg[z_description]);
}
} else {
t_string const &name = sp.cfg["name_inactive"];
t_string const &name = sp.cfg[z_name_inactive];
if (!name.empty()) {
res.push_back(name);
res.push_back(sp.cfg["description_inactive"]);
res.push_back(sp.cfg[z_description_inactive]);
}
}
}
@ -537,14 +607,14 @@ std::string attack_type::weapon_specials(bool force) const
{
// log_scope("weapon_specials");
std::string res;
const config &specials = cfg_.child("specials");
const config &specials = cfg_.child(z_specials);
if (!specials) return res;
foreach (const config::any_child &sp, specials.all_children_range())
{
char const *s = force || special_active(sp.cfg, true) ?
"name" : "name_inactive";
std::string const &name = sp.cfg[s];
config::t_token const *s = force || special_active(sp.cfg, true) ?
&z_name : &z_name_inactive;
config::t_token const &name = sp.cfg[*s];
if (!name.empty()) {
if (!res.empty()) res += ',';
@ -562,7 +632,10 @@ std::string attack_type::weapon_specials(bool force) const
* cfg: a weapon special WML structure
*
*/
bool attack_type::special_active(const config& cfg, bool self) const
bool attack_type::special_active(gamemap const & game_map, unit_map const & units,
t_teams const & teams, LuaKernel & lua_kernel,
tod_manager const & tod_manager,
const config& cfg, bool self) const
{
// log_scope("special_active");
assert(unitmap_ != NULL);
@ -581,85 +654,85 @@ bool attack_type::special_active(const config& cfg, bool self) const
if(attacker_) {
{
std::string const &active = cfg["active_on"];
if (!active.empty() && active != "offense")
std::string const &active = cfg[z_active_on];
if (!active.empty() && active != z_offense)
return false;
}
if (const config &filter_self = cfg.child("filter_self"))
if (const config &filter_self = cfg.child(z_filter_self))
{
if (att == unitmap_->end() ||
!att->matches_filter(vconfig(filter_self), aloc_))
!att->matches_filter(vconfig(filter_self), aloc_, false, game_map, units, teams, lua_kernel, tod_manager))
return false;
if (const config &filter_weapon = filter_self.child("filter_weapon")) {
if (const config &filter_weapon = filter_self.child(z_filter_weapon)) {
if (!matches_filter(filter_weapon, true))
return false;
}
}
if (const config &filter_opponent = cfg.child("filter_opponent"))
if (const config &filter_opponent = cfg.child(z_filter_opponent))
{
if (def == unitmap_->end() ||
!def->matches_filter(vconfig(filter_opponent), dloc_))
!def->matches_filter(vconfig(filter_opponent), dloc_,false, game_map, units, teams, lua_kernel, tod_manager))
return false;
if (const config &filter_weapon = filter_opponent.child("filter_weapon")) {
if (const config &filter_weapon = filter_opponent.child(z_filter_weapon)) {
if (!other_attack_ ||
!other_attack_->matches_filter(filter_weapon, true))
!other_attack_->matches_filter( filter_weapon, true))
return false;
}
}
} else {
{
std::string const &active = cfg["active_on"];
if (!active.empty() && active != "defense")
std::string const &active = cfg[z_active_on];
if (!active.empty() && active != z_defense)
return false;
}
if (const config &filter_self = cfg.child("filter_self"))
if (const config &filter_self = cfg.child(z_filter_self))
{
if (def == unitmap_->end() ||
!def->matches_filter(vconfig(filter_self), dloc_))
!def->matches_filter(vconfig(filter_self), dloc_, false, game_map, units, teams, lua_kernel, tod_manager))
return false;
if (const config &filter_weapon = filter_self.child("filter_weapon")) {
if (!matches_filter(filter_weapon, true))
if (const config &filter_weapon = filter_self.child(z_filter_weapon)) {
if (!matches_filter( filter_weapon, true))
return false;
}
}
if (const config &filter_opponent = cfg.child("filter_opponent"))
if (const config &filter_opponent = cfg.child(z_filter_opponent))
{
if (att == unitmap_->end() ||
!att->matches_filter(vconfig(filter_opponent), aloc_))
!att->matches_filter(vconfig(filter_opponent), aloc_, false, game_map, units, teams, lua_kernel, tod_manager))
return false;
if (const config &filter_weapon = filter_opponent.child("filter_weapon")) {
if (const config &filter_weapon = filter_opponent.child(z_filter_weapon)) {
if (!other_attack_ ||
!other_attack_->matches_filter(filter_weapon, true))
!other_attack_->matches_filter( filter_weapon, true))
return false;
}
}
}
if (const config &filter_attacker = cfg.child("filter_attacker"))
if (const config &filter_attacker = cfg.child(z_filter_attacker))
{
if (att == unitmap_->end() ||
!att->matches_filter(vconfig(filter_attacker), aloc_))
!att->matches_filter(vconfig(filter_attacker), aloc_, false, game_map, units, teams, lua_kernel, tod_manager))
return false;
if (const config &filter_weapon = filter_attacker.child("filter_weapon"))
if (const config &filter_weapon = filter_attacker.child(z_filter_weapon))
{
if (attacker_) {
if (!matches_filter(filter_weapon, true))
return false;
} else {
if (!other_attack_ ||
!other_attack_->matches_filter(filter_weapon, true))
!other_attack_->matches_filter( filter_weapon, true))
return false;
}
}
}
if (const config &filter_defender = cfg.child("filter_defender"))
if (const config &filter_defender = cfg.child(z_filter_defender))
{
if (def == unitmap_->end() ||
!def->matches_filter(vconfig(filter_defender), dloc_))
!def->matches_filter(vconfig(filter_defender), dloc_, false, game_map, units, teams, lua_kernel, tod_manager))
return false;
if (const config &filter_weapon = filter_defender.child("filter_weapon"))
if (const config &filter_weapon = filter_defender.child(z_filter_weapon))
{
if (!attacker_) {
if(!matches_filter(filter_weapon, true))
if(!matches_filter( filter_weapon, true))
return false;
} else {
if (!other_attack_ ||
@ -675,9 +748,9 @@ bool attack_type::special_active(const config& cfg, bool self) const
get_adjacent_tiles(dloc_,adjacent);
}
foreach (const config &i, cfg.child_range("filter_adjacent"))
foreach (const config &i, cfg.child_range(z_filter_adjacent))
{
foreach (const std::string &j, utils::split(i["adjacent"]))
foreach (const std::string &j, utils::split(i[z_adjacent]))
{
map_location::DIRECTION index =
map_location::parse_direction(j);
@ -685,14 +758,14 @@ bool attack_type::special_active(const config& cfg, bool self) const
continue;
unit_map::const_iterator unit = unitmap_->find(adjacent[index]);
if (unit == unitmap_->end() ||
!unit->matches_filter(vconfig(i), unit->get_location()))
!unit->matches_filter(vconfig(i), unit->get_location(), false, game_map, units, teams, lua_kernel, tod_manager))
return false;
}
}
foreach (const config &i, cfg.child_range("filter_adjacent_location"))
foreach (const config &i, cfg.child_range(z_filter_adjacent_location))
{
foreach (const std::string &j, utils::split(i["adjacent"]))
foreach (const std::string &j, utils::split(i[z_adjacent]))
{
map_location::DIRECTION index =
map_location::parse_direction(j);
@ -714,16 +787,16 @@ bool attack_type::special_active(const config& cfg, bool self) const
bool attack_type::special_affects_opponent(const config& cfg) const
{
// log_scope("special_affects_opponent");
std::string const &apply_to = cfg["apply_to"];
std::string const &apply_to = cfg[z_apply_to];
if (apply_to.empty())
return false;
if (apply_to == "both")
if (apply_to == z_both)
return true;
if (apply_to == "opponent")
if (apply_to == z_opponent)
return true;
if (attacker_ && apply_to == "defender")
if (attacker_ && apply_to == z_defender)
return true;
if (!attacker_ && apply_to == "attacker")
if (!attacker_ && apply_to == z_attacker)
return true;
return false;
}
@ -735,16 +808,16 @@ 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["apply_to"];
std::string const &apply_to = cfg[z_apply_to];
if (apply_to.empty())
return true;
if (apply_to == "both")
if (apply_to == z_both)
return true;
if (apply_to == "self")
if (apply_to == z_self)
return true;
if (attacker_ && apply_to == "attacker")
if (attacker_ && apply_to == z_attacker)
return true;
if (!attacker_ && apply_to == "defender")
if (!attacker_ && apply_to == z_defender)
return true;
return false;
}
@ -783,13 +856,13 @@ void individual_effect::set(value_modifier t, int val, const config *abil, const
bool filter_base_matches(const config& cfg, int def)
{
if (const config &apply_filter = cfg.child("filter_base_value")) {
config::attribute_value cond_eq = apply_filter["equals"];
config::attribute_value cond_ne = apply_filter["not_equals"];
config::attribute_value cond_lt = apply_filter["less_than"];
config::attribute_value cond_gt = apply_filter["greater_than"];
config::attribute_value cond_ge = apply_filter["greater_than_equal_to"];
config::attribute_value cond_le = apply_filter["less_than_equal_to"];
if (const config &apply_filter = cfg.child(z_filter_base_value)) {
config::attribute_value cond_eq = apply_filter[z_equals];
config::attribute_value cond_ne = apply_filter[z_not_equals];
config::attribute_value cond_lt = apply_filter[z_less_than];
config::attribute_value cond_gt = apply_filter[z_greater_than];
config::attribute_value cond_ge = apply_filter[z_greater_than_equal_to];
config::attribute_value cond_le = apply_filter[z_less_than_equal_to];
return (cond_eq.empty() || def == cond_eq.to_int()) &&
(cond_ne.empty() || def != cond_ne.to_int()) &&
(cond_lt.empty() || def < cond_lt.to_int()) &&
@ -816,16 +889,16 @@ effect::effect(const unit_ability_list& list, int def, bool backstab) :
for (std::vector< std::pair<const config *, map_location> >::const_iterator
i = list.cfgs.begin(), i_end = list.cfgs.end(); i != i_end; ++i) {
const config& cfg = (*i->first);
std::string const &effect_id = cfg[cfg["id"].empty() ? "name" : "id"];
std::string const &effect_id = cfg[cfg[z_id].empty() ? z_name : z_id];
if (!backstab && cfg["backstab"].to_bool())
if (!backstab && cfg[z_backstab].to_bool())
continue;
if (!filter_base_matches(cfg, def))
continue;
if (const config::attribute_value *v = cfg.get("value")) {
if (const config::attribute_value *v = cfg.get(z_value)) {
int value = *v;
bool cumulative = cfg["cumulative"].to_bool();
bool cumulative = cfg[z_cumulative].to_bool();
if (!value_is_set && !cumulative) {
value_set = value;
set_effect.set(SET, value, i->first, i->second);
@ -839,29 +912,29 @@ effect::effect(const unit_ability_list& list, int def, bool backstab) :
value_is_set = true;
}
if (const config::attribute_value *v = cfg.get("add")) {
if (const config::attribute_value *v = cfg.get(z_add)) {
int add = *v;
std::map<std::string,individual_effect>::iterator add_effect = values_add.find(effect_id);
if(add_effect == values_add.end() || add > add_effect->second.value) {
values_add[effect_id].set(ADD,add,i->first,i->second);
}
}
if (const config::attribute_value *v = cfg.get("sub")) {
if (const config::attribute_value *v = cfg.get(z_sub)) {
int sub = - *v;
std::map<std::string,individual_effect>::iterator sub_effect = values_add.find(effect_id);
if(sub_effect == values_add.end() || sub > sub_effect->second.value) {
values_add[effect_id].set(ADD,sub,i->first,i->second);
}
}
if (const config::attribute_value *v = cfg.get("multiply")) {
if (const config::attribute_value *v = cfg.get(z_multiply)) {
int multiply = int(v->to_double() * 100);
std::map<std::string,individual_effect>::iterator mul_effect = values_mul.find(effect_id);
if(mul_effect == values_mul.end() || multiply > mul_effect->second.value) {
values_mul[effect_id].set(MUL,multiply,i->first,i->second);
}
}
if (const config::attribute_value *v = cfg.get("divide")) {
if (*v == 0) {
if (const config::attribute_value *v = cfg.get(z_divide)) {
if (v->to_int() == 0) {
ERR_NG << "division by zero with divide= in ability/weapon special " << effect_id << "\n";
}
else {

View File

@ -39,6 +39,226 @@ static lg::log_domain log_config("config");
static lg::log_domain log_unit("unit");
#define DBG_UT LOG_STREAM(debug, log_unit)
namespace{
//Static tokens are replacements for string literals in code
//They allow for fast comparison operations.
static const config::t_token z_gender("gender", false);
static const config::t_token z_type("type", false);
static const config::t_token z_id("id", false);
static const config::t_token z_name("name", false);
static const config::t_token z_random_gender("random_gender", false);
static const config::t_token z_x("x", false);
static const config::t_token z_y("y", false);
static const config::t_token z_variation("variation", false);
static const config::t_token z_canrecruit("canrecruit", false);
static const config::t_token z_role("role", false);
static const config::t_token z_ai_special("ai_special", false);
static const config::t_token z_side("side", false);
static const config::t_token z_underlying_id("underlying_id", false);
static const config::t_token z_overlays("overlays", false);
static const config::t_token z_variables("variables", false);
static const config::t_token z_facing("facing", false);
static const config::t_token z_flying("flying", false);
static const config::t_token z_modification("modifications", false);
static const config::t_token z_race("race", false);
static const config::t_token z_undead_variation("undead_variation", false);
static const config::t_token z_max_attacks("max_attacks", false);
static const config::t_token z_attacks_left("attacks_left", false);
static const config::t_token z_alpha("alpha", false);
static const config::t_token z_zoc("zoc", false);
static const config::t_token z_description("description", false);
static const config::t_token z_cost("cost", false);
static const config::t_token z_profile("profile", false);
static const config::t_token z_small_profile("small_profile", false);
static const config::t_token z_max_hitpoints("max_hitpoints", false);
static const config::t_token z_max_moves("max_moves", false);
static const config::t_token z_max_experience("max_experience", false);
static const config::t_token z_advances_to("advances_to", false);
static const config::t_token z_null("null", false);
static const config::t_token z_ai("ai", false);
static const config::t_token z_formula("formula", false);
static const config::t_token z_loop_formula("loop_formula", false);
static const config::t_token z_priority("priority", false);
static const config::t_token z_vars("vars", false);
static const config::t_token z_guardian("guardian", false);
static const config::t_token z_hitpoints("hitpoints", false);
static const config::t_token z_goto_x("goto_x", false);
static const config::t_token z_goto_y("goto_y", false);
static const config::t_token z_experience("experience", false);
static const config::t_token z_resting("resting", false);
static const config::t_token z_unrenamable("unrenamable", false);
static const config::t_token z_lawful("lawful", false);
static const config::t_token z_neutral("neutral", false);
static const config::t_token z_chaotic("chaotic", false);
static const config::t_token z_liminal("liminal", false);
static const config::t_token z_upkeep("upkeep", false);
static const config::t_token z_full("full", false);
static const config::t_token z_flag_rgb("flag_rgb", false);
static const config::t_token z_language_name("language_name", false);
// static const config::t_token z_halo("halo", false);
// static const config::t_token z_ellipse("ellipse", false);
// static const config::t_token z_usage("usage", false);
static const config::t_token z_generate_name("generate_name", false);
static const config::t_token z_availability("availability", false);
static const config::t_token z_musthave("musthave", false);
// static const config::t_token z_trait("trait", false);
static const config::t_token z_random_traits("random_traits", false);
static const config::t_token z_male("male", false);
static const config::t_token z_female("female", false);
static const config::t_token z_unit_image("unit_image", false);
static const config::t_token z_duration("duration", false);
static const config::t_token z_prev_type("prev_type", false);
static const config::t_token z_forever("forever", false);
static const config::t_token z_abilities("abilities", false);
static const config::t_token z_speaker("speaker", false);
static const config::t_token z_has_weapon("has_weapon", false);
static const config::t_token z_defense("defense", false);
static const config::t_token z_visible("visible", false);
static const config::t_token z_viewing_side("viewing_side", false);
static const config::t_token z_filter_vision("filter_vision", false);
static const config::t_token z_adjacent("adjacent", false);
static const config::t_token z_is_enemy("is_enemy", false);
static const config::t_token z_count("count", false);
static const config::t_token z_find_in("find_in", false);
static const config::t_token z_lua_function("lua_function", false);
static const config::t_token z_status("status", false);
static const config::t_token z_loyal("loyal", false);
static const config::t_token z_free("free", false);
static const config::t_token z_active_on("active_on", false);
static const config::t_token z_apply_to("apply_to", false);
static const config::t_token z_icon("icon", false);
static const config::t_token z_strict_amla("strict_amla", false);
static const config::t_token z_require_amla("require_amla", false);
static const config::t_token z_times("times", false);
static const config::t_token z_empty("", false);
static const config::t_token z_modifications("modifications", false);
static const config::t_token z_level("level", false);
static const config::t_token z_attack("attack", false);
static const config::t_token z_resistance("resistance", false);
static const config::t_token z_healable("healable", false);
static const config::t_token z_unhealable("unhealable", false);
static const config::t_token z_waypoints("waypoints", false);
static const config::t_token z_moves("moves", false);
static const config::t_token z_alignment("alignment", false);
static const config::t_token z_placement("placement", false);
static const config::t_token z_do_not_list("do_not_list", false);
static const config::t_token z_event("event", false);
static const config::t_token z_any("any", false);
static const config::t_token z_die("die", false);
static const config::t_token z_flies("flies", false);
static const config::t_token z_inherit("inherit", false);
static const config::t_token z_variation_name("variation_name", false);
static const config::t_token z_ignore_race_traits("ignore_race_traits", false);
static const config::t_token z_hide_help("hide_help", false);
static const config::t_token z_yes("yes", false);
static const config::t_token z_no("no", false);
static const config::t_token z_slowed("slowed", false);
static const config::t_token z_poisoned("poisoned", false);
static const config::t_token z_petrified("petrified", false);
static const config::t_token z_uncovered("uncovered", false);
static const config::t_token z_not_moved("not_moved", false);
static const config::t_token z_this_unit("this_unit", false);
static const config::t_token z_and("and", false);
static const config::t_token z_or("or", false);
static const config::t_token z_not("not", false);
static const config::t_token z_filter("filter", false);
static const config::t_token z_recall("recall", false);
static const config::t_token z_ability("ability", false);
static const config::t_token z_movement_cost("movement_cost", false);
static const config::t_token z_movement_costs("movement_costs", false);
static const config::t_token z_filter_wml("filter_wml", false);
static const config::t_token z_filter_adjacent("filter_adjacent", false);
static const config::t_token z_standing("standing", false);
static const config::t_token z_ghosted("ghosted", false);
static const config::t_token z_disabled_ghosted("disabled_ghosted", false);
static const config::t_token z_image("image", false);
static const config::t_token z_movement("movement", false);
static const config::t_token z_die_sound("die_sound", false);
static const config::t_token z_movement_type("movement_type", false);
static const config::t_token z_filter_location("filter_location", false);
static const config::t_token z__disabled_("_disabled_", false);
static const config::t_token z_idling("idling", false);
static const config::t_token z_selected("selected", false);
static const config::t_token z__disabled_selected_("_disabled_selected_", false);
static const config::t_token z_offense("offense", false);
static const config::t_token z_max_value("max_value", false);
static const config::t_token z_advance("advance", false);
static const config::t_token z_max_times("max_times", false);
static const config::t_token z_fearless("fearless", false);
static const config::t_token z_healthy("healthy", false);
static const config::t_token z_effect("effect", false);
static const config::t_token z_unit_type("unit_type", false);
static const config::t_token z_unit_gender("unit_gender", false);
static const config::t_token z_portrait("portriat", false);
static const config::t_token z_small_portrait("small_portriat", false);
static const config::t_token z_new_attack("new_attack", false);
static const config::t_token z_remove_attacks("remove_attacks", false);
static const config::t_token z_wesnoth("wesnoth", false);
static const config::t_token z_attack_list("attack_list", false);
static const config::t_token z_effect_description("effect_description", false);
static const config::t_token z_increase("increase", false);
static const config::t_token z_increase_total("increase_total", false);
static const config::t_token z_set("set", false);
static const config::t_token z_set_total("set_total", false);
static const config::t_token z_violate_maximum("violate_maximum", false);
static const config::t_token z_HP("HP", false);
static const config::t_token z_remove("remove", false);
static const config::t_token z_replace("replace", false);
static const config::t_token z_heal_full("heal_full", false);
static const config::t_token z_add("add", false);
static const config::t_token z_value("value", false);
static const config::t_token z_new_ability("new_ability", false);
static const config::t_token z_remove_ability("remove_ability", false);
static const config::t_token z_image_mod("image_mod", false);
static const config::t_token z_new_animation("new_animation", false);
static const config::t_token z_female_name("female_name", false);
static const config::t_token z_male_name("male_name", false);
static const config::t_token z_ignore_global_traits("ignore_global_traits", false);
static const config::t_token z_range("range", false);
static const config::t_token z_damage("damage", false);
static const config::t_token z_number("number", false);
static const config::t_token z_specials("specials", false);
static const config::t_token z_description_inactive("description_inactive", false);
static const config::t_token z_name_inactive("name_inactive", false);
static const config::t_token z_advance_from("advance_from", false);
static const config::t_token z_hides("hides", false);
static const config::t_token z_Unit("Unit", false);
static const config::t_token z_attack_weight("attack_weight", false);
static const config::t_token z_defense_weight("defense_weight", false);
static const config::t_token z_accuracy("accuracy", false);
static const config::t_token z_parry("parry", false);
static const config::t_token z_special("special", false);
static const config::t_token z_set_name("set_name", false);
static const config::t_token z_set_description("set_description", false);
static const config::t_token z_set_type("set_type", false);
static const config::t_token z_remove_specials("remove_specials", false);
static const config::t_token z_set_specials("set_specials", false);
static const config::t_token z_increase_damage("increase_damage", false);
static const config::t_token z_increase_attacks("increase_attacks", false);
static const config::t_token z_attacks("attacks", false);
static const config::t_token z_usage("usage", false);
static const config::t_token z_num_traits("num_traits", false);
static const config::t_token z_movetype("movetype", false);
static const config::t_token z_base_unit("base_unit", false);
static const config::t_token z_all("all", false);
static const config::t_token z_random("random", false);
static const config::t_token z_type_adv_tree("type_adv_tree", false);
static const config::t_token z_unit("unit", false);
static const config::t_token z_not_living("not_living", false);
static const config::t_token z_increase_parry("increase_parry", false);
static const config::t_token z_increase_accuracy("increase_accuracy", false);
static const config::t_token z_mode("mode", false);
static const config::t_token z_append("append", false);
static const config::t_token z_advancefrom("advancefrom", false);
// static const config::t_token z_("", false);
// static const config::t_token z_("", false);
// static const config::t_token z_("", false);
// static const config::t_token z_("", false);
// static const config::t_token z_("", false);
}
attack_type::attack_type(const config& cfg) :
aloc_(),
dloc_(),
@ -46,25 +266,25 @@ attack_type::attack_type(const config& cfg) :
unitmap_(NULL),
other_attack_(NULL),
cfg_(cfg),
description_(cfg["description"].t_str()),
id_(cfg["name"]),
type_(cfg["type"]),
icon_(cfg["icon"]),
range_(cfg["range"]),
damage_(cfg["damage"]),
num_attacks_(cfg["number"]),
attack_weight_(cfg["attack_weight"].to_double(1.0)),
defense_weight_(cfg["defense_weight"].to_double(1.0)),
accuracy_(cfg["accuracy"]),
parry_(cfg["parry"])
description_(cfg[z_description].t_str()),
id_(cfg[z_name]),
type_(cfg[z_type]),
icon_(cfg[z_icon]),
range_(cfg[z_range]),
damage_(cfg[z_damage]),
num_attacks_(cfg[z_number]),
attack_weight_(cfg[z_attack_weight].to_double(1.0)),
defense_weight_(cfg[z_defense_weight].to_double(1.0)),
accuracy_(cfg[z_accuracy]),
parry_(cfg[z_parry])
{
if (description_.empty())
description_ = egettext(id_.c_str());
description_ = egettext(id().c_str());
if(icon_.empty()){
if (id_ != "")
icon_ = "attacks/" + id_ + ".png";
if (id() != z_empty)
icon_ = "attacks/" + id() + ".png";
else
icon_ = "attacks/blank-attack.png";
}
@ -92,11 +312,11 @@ std::string attack_type::accuracy_parry_description() const
bool attack_type::matches_filter(const config& cfg,bool self) const
{
const std::vector<std::string>& filter_range = utils::split(cfg["range"]);
const std::string& filter_damage = cfg["damage"];
const std::vector<std::string> filter_name = utils::split(cfg["name"]);
const std::vector<std::string> filter_type = utils::split(cfg["type"]);
const std::string filter_special = cfg["special"];
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 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())
return false;
@ -122,58 +342,58 @@ bool attack_type::apply_modification(const config& cfg,std::string* description)
if(!matches_filter(cfg,0))
return false;
const std::string& set_name = cfg["set_name"];
const t_string& set_desc = cfg["set_description"];
const std::string& set_type = cfg["set_type"];
const std::string& del_specials = cfg["remove_specials"];
const config &set_specials = cfg.child("set_specials");
const std::string& increase_damage = cfg["increase_damage"];
const std::string& increase_attacks = cfg["increase_attacks"];
const std::string& set_attack_weight = cfg["attack_weight"];
const std::string& set_defense_weight = cfg["defense_weight"];
const std::string& increase_accuracy = cfg["increase_accuracy"];
const std::string& increase_parry = cfg["increase_parry"];
const std::string& set_name = cfg[z_set_name];
const t_string& set_desc = cfg[z_set_description];
const std::string& set_type = cfg[z_set_type];
const std::string& 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];
std::stringstream desc;
if(set_name.empty() == false) {
id_ = set_name;
cfg_["name"] = id_;
cfg_[z_name] = id();
}
if(set_desc.empty() == false) {
description_ = set_desc;
cfg_["description"] = description_;
cfg_[z_description] = description_;
}
if(set_type.empty() == false) {
type_ = set_type;
cfg_["type"] = type_;
cfg_[z_type] = type_;
}
if(del_specials.empty() == false) {
const std::vector<std::string>& dsl = utils::split(del_specials);
if (config &specials = cfg_.child("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::find(dsl.begin(), dsl.end(), vp.cfg["id"]);
std::find(dsl.begin(), dsl.end(), vp.cfg[z_id]);
if (found_id == dsl.end()) {
new_specials.add_child(vp.key, vp.cfg);
}
}
cfg_.clear_children("specials");
cfg_.add_child("specials",new_specials);
cfg_.clear_children(z_specials);
cfg_.add_child(z_specials,new_specials);
}
}
if (set_specials) {
const std::string &mode = set_specials["mode"];
if (mode != "append") {
cfg_.clear_children("specials");
const std::string &mode = set_specials[z_mode];
if (mode != z_append) {
cfg_.clear_children(z_specials);
}
config &new_specials = cfg_.child_or_add("specials");
config &new_specials = cfg_.child_or_add(z_specials);
foreach (const config::any_child &value, set_specials.all_children_range()) {
new_specials.add_child(value.key, value.cfg);
}
@ -184,18 +404,18 @@ bool attack_type::apply_modification(const config& cfg,std::string* description)
if (damage_ < 0) {
damage_ = 0;
}
cfg_["damage"] = damage_;
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);
<< _n("damage", "damage", inc_damage);
}
}
if(increase_attacks.empty() == false) {
num_attacks_ = utils::apply_modifier(num_attacks_, increase_attacks, 1);
cfg_["number"] = num_attacks_;
cfg_[z_number] = num_attacks_;
if(description != NULL) {
int inc_attacks = lexical_cast<int>(increase_attacks);
@ -206,7 +426,7 @@ bool attack_type::apply_modification(const config& cfg,std::string* description)
if(increase_accuracy.empty() == false) {
accuracy_ = utils::apply_modifier(accuracy_, increase_accuracy, 1);
cfg_["accuracy"] = accuracy_;
cfg_[z_accuracy] = accuracy_;
if(description != NULL) {
int inc_acc = lexical_cast<int>(increase_accuracy);
@ -218,7 +438,7 @@ bool attack_type::apply_modification(const config& cfg,std::string* description)
if(increase_parry.empty() == false) {
parry_ = utils::apply_modifier(parry_, increase_parry, 1);
cfg_["parry"] = parry_;
cfg_[z_parry] = parry_;
if(description != NULL) {
int inc_parry = lexical_cast<int>(increase_parry);
@ -229,12 +449,12 @@ bool attack_type::apply_modification(const config& cfg,std::string* description)
if(set_attack_weight.empty() == false) {
attack_weight_ = lexical_cast_default<double>(set_attack_weight,1.0);
cfg_["attack_weight"] = attack_weight_;
cfg_[z_attack_weight] = attack_weight_;
}
if(set_defense_weight.empty() == false) {
defense_weight_ = lexical_cast_default<double>(set_defense_weight,1.0);
cfg_["defense_weight"] = defense_weight_;
cfg_[z_defense_weight] = defense_weight_;
}
if(description != NULL) {
@ -250,8 +470,8 @@ bool attack_type::describe_modification(const config& cfg,std::string* descripti
if(!matches_filter(cfg,0))
return false;
const std::string& increase_damage = cfg["increase_damage"];
const std::string& increase_attacks = cfg["increase_attacks"];
const std::string& increase_damage = cfg[z_increase_damage];
const std::string& increase_attacks = cfg[z_increase_attacks];
std::stringstream desc;
@ -288,22 +508,22 @@ unit_movement_type::unit_movement_type(const config& cfg, const unit_movement_ty
//so we filter to keep only keys related to movement_type
//FIXME: This helps but it's still not clean, both cfg use a "name" key
const t_string& name = cfg["name"];
const t_string& name = cfg[z_name];
if (!name.empty())
cfg_["name"]= cfg["name"];
cfg_[z_name]= cfg[z_name];
const t_string& flies = cfg["flies"];
const t_string& flies = cfg[z_flies];
if (!flies.empty())
cfg_["flies"]= cfg["flies"];
cfg_[z_flies]= cfg[z_flies];
if (const config &movement_costs = cfg.child("movement_costs"))
cfg_.add_child("movement_costs", movement_costs);
if (const config &movement_costs = cfg.child(z_movement_costs))
cfg_.add_child(z_movement_costs, movement_costs);
if (const config &defense = cfg.child("defense"))
cfg_.add_child("defense", defense);
if (const config &defense = cfg.child(z_defense))
cfg_.add_child(z_defense, defense);
if (const config &resistance = cfg.child("resistance"))
cfg_.add_child("resistance", resistance);
if (const config &resistance = cfg.child(z_resistance))
cfg_.add_child(z_resistance, resistance);
}
unit_movement_type::unit_movement_type(): moveCosts_(), defenseMods_(), parent_(NULL), cfg_()
@ -311,10 +531,10 @@ unit_movement_type::unit_movement_type(): moveCosts_(), defenseMods_(), parent_(
std::string unit_movement_type::name() const
{
if (!cfg_.has_attribute("name") && parent_)
if (!cfg_.has_attribute(z_name) && parent_)
return parent_->name();
else
return cfg_["name"];
return cfg_[z_name];
}
int unit_movement_type::resistance_against(const attack_type& attack) const
@ -322,7 +542,7 @@ int unit_movement_type::resistance_against(const attack_type& attack) const
bool result_found = false;
int res = 100;
if (const config &resistance = cfg_.child("resistance"))
if (const config &resistance = cfg_.child(z_resistance))
{
if (const::config::attribute_value *val = resistance.get(attack.type())) {
res = *val;
@ -343,7 +563,7 @@ utils::string_map unit_movement_type::damage_table() const
if(parent_ != NULL)
res = parent_->damage_table();
if (const config &resistance = cfg_.child("resistance"))
if (const config &resistance = cfg_.child(z_resistance))
{
foreach (const config::attribute &i, resistance.attribute_range()) {
res[i.first] = i.second;
@ -355,10 +575,10 @@ utils::string_map unit_movement_type::damage_table() const
bool unit_movement_type::is_flying() const
{
if (!cfg_.has_attribute("flies") && parent_)
if (!cfg_.has_attribute(z_flies) && parent_)
return parent_->is_flying();
return cfg_["flies"].to_bool();
return cfg_[z_flies].to_bool();
}
int movement_cost_internal(std::map<t_translation::t_terrain, int>& move_costs,
@ -413,7 +633,7 @@ int movement_cost_internal(std::map<t_translation::t_terrain, int>& move_costs,
bool result_found = false;
int res = impassable;
if (const config& movement_costs = cfg.child("movement_costs")) {
if (const config& movement_costs = cfg.child(z_movement_costs)) {
if (underlying.size() != 1) {
ERR_CF << "Terrain '" << terrain << "' has "
<< underlying.size() << " underlying names - 0 expected.\n";
@ -499,7 +719,7 @@ const defense_range &defense_range_modifier_internal(defense_cache &defense_mods
goto check;
}
if (const config& defense = cfg.child("defense"))
if (const config& defense = cfg.child(z_defense))
{
const std::string& id = map.get_terrain_info(underlying.front()).id();
if (const config::attribute_value *val = defense.get(id)) {
@ -603,7 +823,7 @@ unit_type::unit_type(const unit_type& o) :
unit_type::unit_type(config &cfg) :
cfg_(cfg),
id_(cfg["id"]),
id_(cfg[z_id]),
type_name_(),
description_(),
hitpoints_(0),
@ -666,32 +886,33 @@ void unit_type::build_full(const movement_type_map &mv_types,
foreach (const config &t, traits)
{
possibleTraits_.add_child("trait", t);
possibleTraits_.add_child(z_trait, t);
}
foreach (config &var_cfg, cfg.child_range("variation"))
foreach (config &var_cfg, cfg.child_range(z_variation))
{
if (var_cfg["inherit"].to_bool()) {
if (var_cfg[z_inherit].to_bool()) {
config nvar_cfg(cfg);
nvar_cfg.merge_with(var_cfg);
nvar_cfg.clear_children("variation");
nvar_cfg.clear_children(z_variation);
var_cfg.swap(nvar_cfg);
}
unit_type *ut = new unit_type(var_cfg);
ut->build_full(mv_types, races, traits);
variations_.insert(std::make_pair(var_cfg["variation_name"], ut));
variations_.insert(std::make_pair(var_cfg[z_variation_name], ut));
}
for (int i = 0; i < 2; ++i) {
if (gender_types_[i])
if (gender_types_[i]){
gender_types_[i]->build_full(mv_types, races, traits);
}
}
const std::string& align = cfg["alignment"];
if(align == "lawful")
const config::attribute_value& align = cfg[z_alignment];
if(align == z_lawful)
alignment_ = LAWFUL;
else if(align == "chaotic")
else if(align == z_chaotic)
alignment_ = CHAOTIC;
else if(align == "neutral")
else if(align == z_neutral)
alignment_ = NEUTRAL;
else if(align == "liminal")
alignment_ = LIMINAL;
@ -705,31 +926,31 @@ void unit_type::build_full(const movement_type_map &mv_types,
if (!race_->uses_global_traits()) {
possibleTraits_.clear();
}
if (cfg["ignore_race_traits"].to_bool()) {
if (cfg[z_ignore_race_traits].to_bool()) {
possibleTraits_.clear();
} else {
foreach (const config &t, race_->additional_traits())
{
if (alignment_ != NEUTRAL || t["id"] != "fearless")
possibleTraits_.add_child("trait", t);
if (alignment_ != NEUTRAL || t[z_id] != z_fearless)
possibleTraits_.add_child(z_trait, t);
}
}
}
// Insert any traits that are just for this unit type
foreach (const config &trait, cfg.child_range("trait"))
foreach (const config &trait, cfg.child_range(z_trait))
{
possibleTraits_.add_child("trait", trait);
possibleTraits_.add_child(z_trait, trait);
}
zoc_ = cfg["zoc"].to_bool(level_ > 0);
zoc_ = cfg[z_zoc].to_bool(level_ > 0);
const std::string& alpha_blend = cfg["alpha"];
const std::string& alpha_blend = cfg[z_alpha];
if(alpha_blend.empty() == false) {
alpha_ = ftofxp(atof(alpha_blend.c_str()));
}
const std::string& move_type = cfg["movement_type"];
const std::string& move_type = cfg[z_movement_type];
const movement_type_map::const_iterator it = mv_types.find(move_type);
@ -741,11 +962,11 @@ void unit_type::build_full(const movement_type_map &mv_types,
DBG_UT << "no parent found for movement_type " << move_type << "\n";
}
flag_rgb_ = cfg["flag_rgb"].str();
flag_rgb_ = cfg[z_flag_rgb].token();
game_config::add_color_info(cfg);
foreach (const config &portrait, cfg_.child_range("portrait")) {
foreach (const config &portrait, cfg_.child_range(z_portrait)) {
portraits_.push_back(tportrait(portrait));
}
@ -762,18 +983,18 @@ void unit_type::build_help_index(const movement_type_map &mv_types,
const config &cfg = cfg_;
type_name_ = cfg_["name"];
description_ = cfg_["description"];
hitpoints_ = cfg["hitpoints"].to_int(1);
level_ = cfg["level"];
movement_ = cfg["movement"].to_int(1);
max_attacks_ = cfg["attacks"].to_int(1);
cost_ = cfg["cost"].to_int(1);
usage_ = cfg_["usage"].str();
undead_variation_ = cfg_["undead_variation"].str();
image_ = cfg_["image"].str();
small_profile_ = cfg_["small_profile"].str();
big_profile_ = cfg_["profile"].str();
type_name_ = cfg_[z_name];
description_ = cfg_[z_description];
hitpoints_ = cfg[z_hitpoints].to_int(1);
level_ = cfg[z_level];
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();
undead_variation_ = cfg_[z_undead_variation].token();
image_ = cfg_[z_image].str();
small_profile_ = cfg_[z_small_profile].str();
big_profile_ = cfg_[z_profile].str();
adjust_profile(small_profile_, big_profile_, image_);
for (int i = 0; i < 2; ++i) {
@ -781,7 +1002,7 @@ void unit_type::build_help_index(const movement_type_map &mv_types,
gender_types_[i]->build_help_index(mv_types, races, traits);
}
const race_map::const_iterator race_it = races.find(cfg["race"]);
const race_map::const_iterator race_it = races.find(cfg[z_race]);
if(race_it != races.end()) {
race_ = &race_it->second;
} else {
@ -789,9 +1010,9 @@ 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["num_traits"].to_int(race_->num_traits());
num_traits_ = cfg[z_num_traits].to_int(race_->num_traits());
const std::vector<std::string> genders = utils::split(cfg["gender"]);
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) {
genders_.push_back(string_gender(*g));
}
@ -799,36 +1020,36 @@ void unit_type::build_help_index(const movement_type_map &mv_types,
genders_.push_back(unit_race::MALE);
}
if (const config &abil_cfg = cfg.child("abilities"))
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["name"];
const std::string &name = ab.cfg[z_name];
if (!name.empty()) {
abilities_.push_back(name);
ability_tooltips_.push_back(ab.cfg["description"]);
ability_tooltips_.push_back(ab.cfg[z_description]);
}
}
}
foreach (const config &adv, cfg.child_range("advancement"))
foreach (const config &adv, cfg.child_range(z_advancement))
{
foreach (const config &effect, adv.child_range("effect"))
foreach (const config &effect, adv.child_range(z_effect))
{
const config &abil_cfg = effect.child("abilities");
if (!abil_cfg || effect["apply_to"] != "new_ability") {
const config &abil_cfg = effect.child(z_abilities);
if (!abil_cfg || effect[z_apply_to] != z_new_ability) {
continue;
}
foreach (const config::any_child &ab, abil_cfg.all_children_range()) {
const std::string &name = ab.cfg["name"];
const std::string &name = ab.cfg[z_name];
if (!name.empty()) {
adv_abilities_.push_back(name);
adv_ability_tooltips_.push_back(ab.cfg["description"]);
adv_ability_tooltips_.push_back(ab.cfg[z_description]);
}
}
}
}
hide_help_= cfg["hide_help"].to_bool();
hide_help_= cfg[z_hide_help].to_bool();
build_status_ = HELP_INDEX;
}
@ -841,45 +1062,51 @@ void unit_type::build_created(const movement_type_map &mv_types,
config &cfg = cfg_;
if (config &male_cfg = cfg.child("male"))
if (config &male_cfg = cfg.child(z_male))
{
if (male_cfg["inherit"].to_bool(true)) {
if (male_cfg[z_inherit].to_bool(true)) {
config m_cfg(cfg);
m_cfg.merge_with(male_cfg);
male_cfg.swap(m_cfg);
}
male_cfg.clear_children("male");
male_cfg.clear_children("female");
male_cfg.clear_children(z_male);
male_cfg.clear_children(z_female);
gender_types_[0] = new unit_type(male_cfg);
}
if (config &female_cfg = cfg.child("female"))
if (config &female_cfg = cfg.child(z_female))
{
if (female_cfg["inherit"].to_bool(true)) {
if (female_cfg[z_inherit].to_bool(true)) {
config f_cfg(cfg);
f_cfg.merge_with(female_cfg);
female_cfg.swap(f_cfg);
}
female_cfg.clear_children("male");
female_cfg.clear_children("female");
female_cfg.clear_children(z_male);
female_cfg.clear_children(z_female);
gender_types_[1] = new unit_type(female_cfg);
}
for (int i = 0; i < 2; ++i) {
if (gender_types_[i])
gender_types_[i]->build_created(mv_types, races, traits);
if (gender_types_[i]){
gender_types_[i]->build_created(mv_types, races, traits);}
}
const std::string& advances_to_val = cfg["advances_to"];
if(advances_to_val != "null" && advances_to_val != "")
const std::string& 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);
DBG_UT << "unit_type '" << id_ << "' advances to : " << advances_to_val << "\n";
DBG_UT << "unit_type '" << id() << "' advances to : " << advances_to_val << "\n";
experience_needed_ = cfg["experience"].to_int(500);
experience_needed_ = cfg[z_experience].to_int(500);
build_status_ = CREATED;
}
const unit_type& unit_type::get_gender_unit_type(config::t_token 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);
@ -928,7 +1155,7 @@ const std::vector<unit_animation>& unit_type::animations() const {
std::vector<attack_type> unit_type::attacks() const
{
std::vector<attack_type> res;
foreach (const config &att, cfg_.child_range("attack")) {
foreach (const config &att, cfg_.child_range(z_attack)) {
res.push_back(attack_type(att));
}
@ -982,10 +1209,10 @@ const char* unit_type::alignment_id(unit_type::ALIGNMENT align)
bool unit_type::has_ability_by_id(const std::string& ability) const
{
if (const config &abil = cfg_.child("abilities"))
if (const config &abil = cfg_.child(z_abilities))
{
foreach (const config::any_child &ab, abil.all_children_range()) {
if (ab.cfg["id"] == ability)
if (ab.cfg[z_id] == ability)
return true;
}
}
@ -996,11 +1223,11 @@ std::vector<std::string> unit_type::get_ability_list() const
{
std::vector<std::string> res;
const config &abilities = cfg_.child("abilities");
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["id"];
const std::string &id = ab.cfg[z_id];
if (!id.empty())
res.push_back(id);
}
@ -1009,13 +1236,13 @@ std::vector<std::string> unit_type::get_ability_list() const
}
bool unit_type::hide_help() const {
return hide_help_ || unit_types.hide_help(id_, race_->id());
return hide_help_ || unit_types.hide_help(id(), race_->id());
}
void unit_type::add_advancement(const unit_type &to_unit,int xp)
{
const std::string &to_id = to_unit.cfg_["id"];
const std::string &from_id = cfg_["id"];
const std::string &to_id = to_unit.cfg_[z_id];
const std::string &from_id = cfg_[z_id];
// Add extra advancement path to this unit type
LOG_CONFIG << "adding advancement from " << from_id << " to " << to_id << "\n";
@ -1082,7 +1309,7 @@ static void advancement_tree_internal(const std::string& id, std::set<std::strin
std::set<std::string> unit_type::advancement_tree() const
{
std::set<std::string> tree;
advancement_tree_internal(id_, tree);
advancement_tree_internal(id(), tree);
return tree;
}
@ -1095,7 +1322,7 @@ const std::vector<std::string> unit_type::advances_from() const
foreach (const unit_type_data::unit_type_map::value_type &ut, unit_types.types())
{
foreach(const std::string& adv, ut.second.advances_to()) {
if (adv == id_)
if (adv == id())
adv_from.push_back(ut.second.id());
}
}
@ -1116,12 +1343,12 @@ unit_type_data::unit_type_data() :
void unit_type_data::set_config(config &cfg)
{
DBG_UT << "unit_type_data::set_config, name: " << cfg["name"] << "\n";
DBG_UT << "unit_type_data::set_config, name: " << cfg[z_name] << "\n";
clear();
set_unit_config(cfg);
foreach (const config &mt, cfg.child_range("movetype"))
foreach (const config &mt, cfg.child_range(z_movetype))
{
const unit_movement_type move_type(mt);
movement_types_.insert(
@ -1129,21 +1356,21 @@ void unit_type_data::set_config(config &cfg)
loadscreen::increment_progress();
}
foreach (const config &r, cfg.child_range("race"))
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));
loadscreen::increment_progress();
}
foreach (config &ut, cfg.child_range("unit_type"))
foreach (config &ut, cfg.child_range(z_unit_type))
{
std::string id = ut["id"];
if (const config &bu = ut.child("base_unit"))
std::string id = ut[z_id];
if (const config &bu = ut.child(z_base_unit))
{
// Derive a new unit type from an existing base unit id
config merge_cfg = find_config(bu["id"]);
ut.clear_children("base_unit");
config merge_cfg = find_config(bu[z_id]);
ut.clear_children(z_base_unit);
merge_cfg.merge_with(ut);
ut.swap(merge_cfg);
}
@ -1155,15 +1382,15 @@ void unit_type_data::set_config(config &cfg)
build_all(unit_type::CREATED);
if (const config &hide_help = cfg.child("hide_help")) {
hide_help_all_ = hide_help["all"].to_bool();
if (const config &hide_help = cfg.child(z_hide_help)) {
hide_help_all_ = hide_help[z_all].to_bool();
read_hide_help(hide_help);
}
}
const unit_type *unit_type_data::find(const std::string& key, unit_type::BUILD_STATUS status) const
{
if (key.empty() || key == "random") return NULL;
if (key.empty() || key == z_random) return NULL;
DBG_CF << "trying to find " << key << " in unit_type list (unit_type_data.unit_types)\n";
const unit_type_map::iterator itor = types_.find(key);
@ -1192,7 +1419,7 @@ void unit_type_data::check_types(const std::vector<std::string>& types) const
const config& unit_type_data::find_config(const std::string& key) const
{
const config &cfg = unit_cfg_->find_child("unit_type", "id", key);
const config &cfg = unit_cfg_->find_child(z_unit_type, z_id, key);
if (cfg)
return cfg;
@ -1240,14 +1467,14 @@ unit_type &unit_type_data::build_unit_type(const unit_type_map::iterator &ut, un
switch (status) {
case unit_type::CREATED:
ut->second.build_created(movement_types_, races_, unit_cfg_->child_range("trait"));
ut->second.build_created(movement_types_, races_, unit_cfg_->child_range(z_trait));
break;
case unit_type::HELP_INDEX:
// Build the data needed to feed the help index.
ut->second.build_help_index(movement_types_, races_, unit_cfg_->child_range("trait"));
ut->second.build_help_index(movement_types_, races_, unit_cfg_->child_range(z_trait));
break;
default:
ut->second.build_full(movement_types_, races_, unit_cfg_->child_range("trait"));
ut->second.build_full(movement_types_, races_, unit_cfg_->child_range(z_trait));
}
return ut->second;
@ -1261,13 +1488,13 @@ void unit_type_data::read_hide_help(const config& cfg)
hide_help_race_.push_back(std::set<std::string>());
hide_help_type_.push_back(std::set<std::string>());
std::vector<std::string> races = utils::split(cfg["race"]);
std::vector<std::string> races = utils::split(cfg[z_race]);
hide_help_race_.back().insert(races.begin(), races.end());
std::vector<std::string> types = utils::split(cfg["type"]);
std::vector<std::string> types = utils::split(cfg[z_type]);
hide_help_type_.back().insert(types.begin(), types.end());
std::vector<std::string> trees = utils::split(cfg["type_adv_tree"]);
std::vector<std::string> trees = utils::split(cfg[z_type_adv_tree]);
hide_help_type_.back().insert(trees.begin(), trees.end());
foreach(const std::string& t_id, trees) {
unit_type_map::iterator ut = types_.find(t_id);
@ -1278,7 +1505,7 @@ void unit_type_data::read_hide_help(const config& cfg)
}
// we call recursively all the imbricated [not] tags
read_hide_help(cfg.child("not"));
read_hide_help(cfg.child(z_not));
}
bool unit_type_data::hide_help(const std::string& type, const std::string& race) const
@ -1300,10 +1527,10 @@ void unit_type_data::add_advancement(unit_type& to_unit) const
{
const config& cfg = to_unit.get_cfg();
foreach (const config &af, cfg.child_range("advancefrom"))
foreach (const config &af, cfg.child_range(z_advancefrom))
{
const std::string &from = af["unit"];
int xp = af["experience"];
const std::string &from = af[z_unit];
int xp = af[z_experience];
unit_type_data::unit_type_map::iterator from_unit = types_.find(from);
@ -1341,17 +1568,17 @@ bool unit_type::not_living() const
// that unit::apply_modifications does things.
foreach (const config &mod, possible_traits())
{
if (mod["availability"] != "musthave")
if (mod[z_availability] != z_musthave)
continue;
foreach (const config &effect, mod.child_range("effect"))
foreach (const config &effect, mod.child_range(z_effect))
{
// See if the effect only applies to
// certain unit types But don't worry
// about gender checks, since we don't
// know what the gender of the
// hypothetical recruit is.
const std::string &ut = effect["unit_type"];
const std::string &ut = effect[z_unit_type];
if (!ut.empty()) {
const std::vector<std::string> &types = utils::split(ut);
if(std::find(types.begin(), types.end(), id()) == types.end())
@ -1359,13 +1586,13 @@ bool unit_type::not_living() const
}
// We're only interested in status changes.
if (effect["apply_to"] != "status") {
if (effect[z_apply_to] != z_status) {
continue;
}
if (effect["add"] == "not_living") {
if (effect[z_add] == z_not_living) {
not_living = true;
}
if (effect["remove"] == "not_living") {
if (effect[z_remove] == z_not_living) {
not_living = false;
}
}

View File

@ -18,6 +18,7 @@
#include "unit_animation.hpp"
#include "portrait.hpp"
#include "race.hpp"
#include "resources.hpp"
class gamemap;
class unit;
@ -26,6 +27,12 @@ class unit_map;
class unit_type_data;
namespace{
static const config::t_token z_movement_used("movement_used", false);
static const config::t_token z_advancement("advancement", false);
static const config::t_token z_trait("trait", false);
//static const config::t_token z_("", false);
}
//and how much damage it does.
class attack_type
{
@ -47,8 +54,8 @@ public:
double attack_weight() const { return attack_weight_; }
double defense_weight() const { return defense_weight_; }
bool get_special_bool(const std::string& special,bool force=false) const;
unit_ability_list get_specials(const std::string& special) const;
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;
void set_specials_context(const map_location& aloc,const map_location& dloc,
@ -59,7 +66,7 @@ public:
bool apply_modification(const config& cfg,std::string* description);
bool describe_modification(const config& cfg,std::string* description);
int movement_used() const { return cfg_["movement_used"].to_int(100000); }
int movement_used() const { return cfg_[z_movement_used].to_int(100000); }
config& get_cfg() { return cfg_; }
const config& get_cfg() const { return cfg_; }
@ -70,7 +77,13 @@ public:
/*
* cfg: a weapon special WML structure
*/
bool special_active(const config& cfg, bool self) const;
bool special_active(gamemap const & game_map, unit_map const & units,
t_teams const & teams, LuaKernel & lua_kernel,
tod_manager const & tod_manager,
const config& cfg, bool self) const;
inline bool special_active(const config& cfg, bool self) const {
return special_active(*resources::game_map, *resources::units,*resources::teams,
*resources::lua_kernel, *resources::tod_manager, cfg, self);}
bool special_affects_opponent(const config& cfg) const;
bool special_affects_self(const config& cfg) const;
@ -204,13 +217,14 @@ public:
const std::vector<std::string> advances_from() const;
config::const_child_itors modification_advancements() const
{ return cfg_.child_range("advancement"); }
{ 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(unit_race::GENDER gender) const;
const unit_type& get_variation(const std::string& name) const;
/** Info on the type of unit that the unit reanimates as. */
const std::string& undead_variation() const { return undead_variation_; }
const config::t_token& undead_variation() const { return undead_variation_; }
unsigned int num_traits() const { return num_traits_; }
@ -233,7 +247,7 @@ public:
const std::vector<unit_animation>& animations() const;
const std::string& flag_rgb() const { return flag_rgb_; }
const config::t_token& flag_rgb() const { return flag_rgb_; }
std::vector<attack_type> attacks() const;
const unit_movement_type& movement_type() const { return movementType_; }
@ -273,7 +287,7 @@ public:
std::vector<std::string> get_ability_list() const;
config::const_child_itors possible_traits() const
{ return possibleTraits_.child_range("trait"); }
{ return possibleTraits_.child_range(z_trait); }
bool has_random_traits() const;
const std::vector<unit_race::GENDER>& genders() const { return genders_; }
@ -303,12 +317,12 @@ private:
int max_attacks_;
int cost_;
std::string usage_;
std::string undead_variation_;
config::t_token undead_variation_;
std::string image_;
std::string small_profile_;
std::string big_profile_;
std::string flag_rgb_;
config::t_token flag_rgb_;
unsigned int num_traits_;

View File

@ -625,7 +625,7 @@ public:
assert(false);
break;
case ']':
std::string index_str(skey.substr(i_start_of_token, i ));
std::string index_str(skey.substr(i_start_of_token, i - i_start_of_token ));
std::istringstream is(index_str);
size_t index;
is >> index;
@ -647,11 +647,11 @@ public:
} else {
switch(c){
case '.' :
parsed_tokens.push_back(t_parsed(t_token(skey.substr(i_start_of_token, i ))));
parsed_tokens.push_back(t_parsed(t_token(skey.substr(i_start_of_token, i - i_start_of_token ))));
i_start_of_token = i + 1;
break;
case '[':
parsed_tokens.push_back(t_parsed(t_token(skey.substr(i_start_of_token, i ))));
parsed_tokens.push_back(t_parsed(t_token(skey.substr(i_start_of_token, i - i_start_of_token ))));
i_start_of_token = i + 1;
is_lbrack=true;
break;
@ -662,7 +662,7 @@ public:
++i;
}
if(i_start_of_token != i){
parsed_tokens.push_back(t_token(skey.substr(i_start_of_token, i )));
parsed_tokens.push_back(t_token(skey.substr(i_start_of_token, i - i_start_of_token )));
}
return parsed_tokens;
@ -670,7 +670,7 @@ public:
};
// typedef boost::unordered_map<config::t_token, t_parsed_tokens> t_all_parsed;
static const uint CACHE_SIZE = 1000;
static const uint CACHE_SIZE = 10000;
typedef n_lru_cache::t_lru_cache<config::t_token, t_parsed_tokens, t_parse_token> t_all_parsed;
@ -712,7 +712,7 @@ void variable_info::init(const config::t_token& varname, bool force_valid) {
t_parsed_tokens tokens(cache.check(varname));
if(tokens.empty()){return;}
if(tokens.empty()){ return; }
activate_scope_variable(tokens);
vars = &repos->variables_;
@ -724,8 +724,10 @@ void variable_info::init(const config::t_token& varname, bool force_valid) {
while (i < last_token){
int inner_index = 0;
int size = vars->child_count( i->token);
if(i->index != t_parsed::NO_INDEX){
inner_index = i->index;
if(size <= inner_index) {
bool last_key_is_not_length ((i == second_last_token) && (last_token->token != z_length));
if(force_valid) {
@ -772,6 +774,7 @@ void variable_info::init(const config::t_token& varname, bool force_valid) {
key = i->token;
if(i->index != t_parsed::NO_INDEX){
explicit_index_ = true;
size_t size = vars->child_count(key);
index = i->index;
if(size <= index) {
@ -804,7 +807,7 @@ void variable_info::init(const config::t_token& varname, bool force_valid) {
WRN_NG << "variable_info: using explicitly indexed "
"container as wrong WML type, " << varname << '\n';
}
explicit_index = false;
explicit_index_ = false;
index = 0;
} else {
// Final variable is not an explicit index [...]
@ -825,15 +828,19 @@ void variable_info::init(const config::t_token& varname, bool force_valid) {
}
variable_info::variable_info(const config::t_token& varname, bool force_valid, TYPE validation_type)
: vartype(validation_type), is_valid_(false), key(varname), explicit_index(false), index(0), vars(NULL) {
: vartype(validation_type), is_valid_(false), explicit_index_(false), key(varname), index(0), vars(NULL) {
init( varname, force_valid) ;}
variable_info::variable_info(const t_string& varname, bool force_valid, TYPE validation_type)
: vartype(validation_type), is_valid_(false), explicit_index_(false),key(varname.token()), index(0), vars(NULL) {
init(varname.token(), force_valid);}
variable_info::variable_info(const std::string& varname, bool force_valid, TYPE validation_type)
: vartype(validation_type), is_valid_(false), key(varname), explicit_index(false), index(0), vars(NULL) {
: vartype(validation_type), is_valid_(false), explicit_index_(false), key(varname), index(0), vars(NULL) {
init(config::t_token(varname), force_valid);}
variable_info::variable_info(const config::attribute_value& varname, bool force_valid, TYPE validation_type)
: vartype(validation_type), is_valid_(false), key(varname.token()), explicit_index(false), index(0), vars(NULL) {
: vartype(validation_type), is_valid_(false), explicit_index_(false), key(varname.token()), index(0), vars(NULL) {
init(varname.token(), force_valid);}
@ -845,7 +852,7 @@ config::attribute_value &variable_info::as_scalar() {
config& variable_info::as_container() {
assert(is_valid_);
if(explicit_index) {
if(explicit_index_) {
// Empty data for explicit index was already created if it was needed
return vars->child(key, index);
}

View File

@ -229,6 +229,7 @@ public:
TYPE_UNSPECIFIED };
variable_info(const config::t_token& varname, bool force_valid=true, TYPE validation_type=TYPE_UNSPECIFIED);
variable_info(const t_string& varname, bool force_valid=true, TYPE validation_type=TYPE_UNSPECIFIED);
variable_info(const std::string& varname, bool force_valid=true, TYPE validation_type=TYPE_UNSPECIFIED);
variable_info(const config::attribute_value& varname, bool force_valid=true, TYPE validation_type=TYPE_UNSPECIFIED);
@ -240,17 +241,17 @@ public:
config& as_container();
array_range as_array(); //range may be empty
bool is_valid() const {return is_valid_;}
bool is_explicit_index() const {return explicit_index;}
bool is_explicit_index() const {return explicit_index_;}
private:
void init(const config::t_token& varname, bool force_valid=true);
public: ///todo make these private
TYPE vartype; ///default is TYPE_UNSPECIFIED
bool is_valid_;
config::t_token key; ///the name of the internal attribute or child
bool explicit_index; ///true if query ended in [...] specifier
size_t index; //'the index of the child
config *vars; ///the containing node in game_state::variables
bool explicit_index_; ///true if query ended in [...] specifier
public: ///todo make these private
config::t_token key; /// the name of the internal attribute or child
size_t index; /// the index of the child
config *vars; /// the containing node in game_state::variables
};
#endif