team.cpp

Go to the documentation of this file.
00001 /* $Id: team.cpp 26536 2008-05-11 19:34:32Z suokko $ */
00002 /*
00003    Copyright (C) 2003 - 2008 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 //! @file team.cpp
00016 //! Team-management, allies, setup at start of scenario.
00017 
00018 #include "global.hpp"
00019 
00020 #include "game_events.hpp"
00021 #include "game_errors.hpp"
00022 #include "gamestatus.hpp"
00023 #include "log.hpp"
00024 #include "network.hpp"
00025 #include "team.hpp"
00026 #include "util.hpp"
00027 #include "serialization/string_utils.hpp"
00028 
00029 #include <algorithm>
00030 #include <cassert>
00031 #include <cstdlib>
00032 #include <sstream>
00033 
00034 #define LOG_NG LOG_STREAM(info, engine)
00035 
00036 namespace {
00037     std::vector<team>* teams = NULL;
00038 }
00039 
00040 //static member initialization
00041 const int team::default_team_gold = 100;
00042 
00043 teams_manager::teams_manager(std::vector<team>& teams_list)
00044 {
00045     teams = &teams_list;
00046 }
00047 
00048 teams_manager::~teams_manager()
00049 {
00050     teams = NULL;
00051 }
00052 
00053 bool teams_manager::is_observer()
00054 {
00055     for(std::vector<team>::const_iterator i = teams->begin(); i != teams->end(); ++i) {
00056         if(i->is_human() || i->is_persistent()) {
00057             return false;
00058         }
00059     }
00060 
00061     return true;
00062 }
00063 
00064 team::target::target(const config& cfg)
00065               : criteria(cfg), value(atof(cfg["value"].c_str()))
00066 {
00067 }
00068 
00069 void team::target::write(config& cfg) const
00070 {
00071     cfg = criteria;
00072 }
00073 
00074 team::team_info::team_info(const config& cfg) :
00075         name(cfg["name"]),
00076         gold(cfg["gold"]),
00077         start_gold(),
00078         income(cfg["income"]),
00079         income_per_village(),
00080         can_recruit(),
00081         global_recruitment_pattern(),
00082         recruitment_pattern(utils::split(cfg["recruitment_pattern"])),
00083         enemies(),
00084         team_name(cfg["team_name"]),
00085         user_team_name(cfg["user_team_name"]),
00086         save_id(cfg["save_id"]),
00087         current_player(cfg["current_player"]),
00088         countdown_time(cfg["countdown_time"]),
00089         action_bonus_count(lexical_cast_default<int>(cfg["action_bonus_count"])),
00090         flag(cfg["flag"]),
00091         flag_icon(cfg["flag_icon"]),
00092         description(cfg["id"]),
00093         objectives(cfg["objectives"]),
00094         objectives_changed(utils::string_bool(cfg["objectives_changed"])),
00095         controller(),
00096         persistent(),
00097         ai_algorithm(cfg["ai_algorithm"]),
00098         ai_params(),
00099         ai_memory_(),
00100         villages_per_scout(),
00101         leader_value(0.0),
00102         village_value(0.0),
00103         targets(),
00104         share_maps(false),
00105         share_view(false),
00106         disallow_observers(utils::string_bool(cfg["disallow_observers"])),
00107         allow_player(utils::string_bool(cfg["allow_player"], true)),
00108         no_leader(utils::string_bool(cfg["no_leader"])),
00109         music(cfg["music"]),
00110         colour(cfg["colour"].size() ? cfg["colour"] : cfg["side"])
00111 {
00112     config global_ai_params;
00113     const config::child_list& ai_parameters = cfg.get_children("ai");
00114     for(config::child_list::const_iterator aiparam = ai_parameters.begin(); aiparam != ai_parameters.end(); ++aiparam) {
00115         ai_params.push_back(**aiparam);
00116 
00117         if((**aiparam)["turns"].empty() && (**aiparam)["time_of_day"].empty()) {
00118             global_ai_params.append(**aiparam);
00119         }
00120     }
00121 
00122     const config::child_list& ai_mems = cfg.get_children("ai_memory");
00123     for(config::child_list::const_iterator aimem = ai_mems.begin(); aimem != ai_mems.end(); ++aimem) {
00124       ai_memory_.append(**aimem);
00125     }
00126 
00127     // at the start of a scenario "start_gold" is not set, we need to take the
00128     // value from the gold setting (or fall back to the gold default)
00129     if (!cfg["start_gold"].empty())
00130         start_gold = cfg["start_gold"];
00131     else if (!this->gold.empty())
00132         start_gold = this->gold;
00133     else
00134         start_gold = str_cast(default_team_gold);
00135 
00136     if(team_name.empty()) {
00137         team_name = cfg["side"];
00138     }
00139 
00140     if(save_id.empty()) {
00141         save_id = description;
00142     }
00143     if (current_player.empty()) {
00144         current_player = save_id;
00145     }
00146 
00147     int side = atoi(cfg["side"].c_str());
00148 
00149     const std::string temp_rgb_str = cfg["team_rgb"];
00150     std::map<std::string, color_range>::iterator global_rgb = game_config::team_rgb_range.find(cfg["side"]);
00151 
00152     if(!temp_rgb_str.empty()){
00153         std::vector<Uint32> temp_rgb = string2rgb(temp_rgb_str);
00154         team_color_range_[side] = color_range(temp_rgb);
00155     }else if(global_rgb != game_config::team_rgb_range.end()){
00156         team_color_range_[side] = global_rgb->second;
00157     }
00158 
00159     const std::string& village_income = cfg["village_gold"];
00160     if(village_income.empty())
00161         income_per_village = game_config::village_income;
00162     else
00163         income_per_village = lexical_cast_default<int>(village_income, game_config::village_income);
00164 
00165     const std::string& enemies_list = cfg["enemy"];
00166     if(!enemies_list.empty()) {
00167         std::vector<std::string> venemies = utils::split(enemies_list);
00168         for(std::vector<std::string>::const_iterator i = venemies.begin(); i != venemies.end(); ++i) {
00169             enemies.push_back(atoi(i->c_str()));
00170         }
00171     }
00172 
00173     std::string control = cfg["controller"];
00174     if (control == "human")
00175         controller = HUMAN;
00176     else if (control == "network")
00177         controller = NETWORK;
00178     else if (control == "null")
00179     {
00180         disallow_observers = utils::string_bool(cfg["disallow_observers"],true);
00181         controller = EMPTY;
00182     }
00183     else
00184         controller = AI;
00185 
00186     std::string persist = cfg["persistent"];
00187     if (persist.empty()) persistent = controller == HUMAN;
00188     else persistent = persist == "1";
00189 
00190     if(ai_algorithm.empty()) {
00191         ai_algorithm = global_ai_params["ai_algorithm"];
00192     }
00193 
00194     std::string scouts_val = cfg["villages_per_scout"];
00195 
00196     if(scouts_val.empty()) {
00197         scouts_val = global_ai_params["villages_per_scout"];
00198     }
00199 
00200     if(scouts_val.empty()) {
00201         villages_per_scout = 4;
00202     } else {
00203         villages_per_scout = atoi(scouts_val.c_str());
00204     }
00205 
00206     std::string leader_val = cfg["leader_value"];
00207 
00208     if(leader_val.empty()) {
00209         leader_val = global_ai_params["leader_value"];
00210     }
00211 
00212     if(leader_val.empty()) {
00213         leader_value = 3.0;
00214     } else {
00215         leader_value = atof(leader_val.c_str());
00216     }
00217 
00218     std::string village_val = cfg["village_value"];
00219 
00220     if(village_val.empty()) {
00221         village_val = global_ai_params["village_value"];
00222     }
00223 
00224     if(village_val.empty()) {
00225         village_value = 1.0;
00226     } else {
00227         village_value = atof(village_val.c_str());
00228     }
00229 
00230     std::vector<std::string> recruits = utils::split(cfg["recruit"]);
00231     for(std::vector<std::string>::const_iterator i = recruits.begin(); i != recruits.end(); ++i) {
00232         can_recruit.insert(*i);
00233     }
00234     
00235     if(recruitment_pattern.empty()) {
00236         recruitment_pattern = 
00237             utils::split(global_ai_params["recruitment_pattern"]);
00238     }
00239 
00240 /*  // Default recruitment pattern is to buy 2 fighters for every 1 archer
00241     if(recruitment_pattern.empty()) {
00242         recruitment_pattern.push_back("fighter");
00243         recruitment_pattern.push_back("fighter");
00244         recruitment_pattern.push_back("archer");
00245     }
00246 */
00247     // Keep a copy of the initial recruitment_pattern,
00248     // since it can be changed on a per-time-of-day
00249     // or per-turn basis inside [ai] sections.
00250     global_recruitment_pattern = recruitment_pattern;
00251 
00252     // Additional targets
00253     config::const_child_itors tgts;
00254     for(tgts = cfg.child_range("target"); tgts.first != tgts.second; ++tgts.first) {
00255         targets.push_back(target(**tgts.first));
00256     }
00257 
00258     for(tgts = global_ai_params.child_range("target"); tgts.first != tgts.second; ++tgts.first) {
00259         targets.push_back(target(**tgts.first));
00260     }
00261 
00262     // Share_view and share_maps can't both be enabled,
00263     // so share_view overrides share_maps.
00264     share_view = utils::string_bool(cfg["share_view"]);
00265     share_maps = !share_view && utils::string_bool(cfg["share_maps"],true);
00266 
00267     LOG_NG << "team_info::team_info(...): team_name: " << team_name
00268            << ", share_maps: " << share_maps << ", share_view: " << share_view << ".\n";
00269 }
00270 
00271 void team::team_info::write(config& cfg) const
00272 {
00273     for(std::vector<config>::const_iterator ai = ai_params.begin(); ai != ai_params.end(); ++ai) {
00274         cfg.add_child("ai",*ai);
00275     }
00276     if(!ai_memory_.empty()) cfg.add_child("ai_memory",ai_memory_);
00277     cfg["ai_algorithm"] = ai_algorithm;
00278 
00279     cfg["gold"] = gold;
00280     cfg["start_gold"] = start_gold;
00281     cfg["income"] = income;
00282     cfg["name"] = name;
00283     cfg["team_name"] = team_name;
00284     cfg["user_team_name"] = user_team_name;
00285     cfg["save_id"] = save_id;
00286     cfg["current_player"] = current_player;
00287     cfg["flag"] = flag;
00288     cfg["flag_icon"] = flag_icon;
00289     cfg["id"] = description;
00290     cfg["objectives"] = objectives;
00291     cfg["objectives_changed"] = objectives_changed ? "yes" : "no";
00292     cfg["countdown_time"]= countdown_time;
00293     cfg["action_bonus_count"]= str_cast(action_bonus_count);
00294     cfg["village_gold"] = str_cast(income_per_village);
00295     cfg["disallow_observers"] = disallow_observers ? "yes" : "no";
00296     cfg["allow_player"] = allow_player ? "yes" : "no";
00297     cfg["no_leader"] = no_leader ? "yes" : "no";
00298 
00299     std::stringstream enemies_str;
00300     for(std::vector<int>::const_iterator en = enemies.begin(); en != enemies.end(); ++en) {
00301         enemies_str << *en;
00302         if(en+1 != enemies.end())
00303             enemies_str << ",";
00304     }
00305 
00306     cfg["enemy"] = enemies_str.str();
00307 
00308     switch(controller) {
00309     case AI: cfg["controller"] = "ai"; break;
00310     case HUMAN: cfg["controller"] = "human"; break;
00311     case NETWORK: cfg["controller"] = "network"; break;
00312     case EMPTY: cfg["controller"] = "null"; break;
00313     default: assert(false); return;
00314     }
00315 
00316     cfg["persistent"] = persistent ? "1" : "0";
00317     cfg["villages_per_scout"] = str_cast(villages_per_scout);
00318     cfg["leader_value"] = str_cast(leader_value);
00319     cfg["village_value"] = str_cast(village_value);
00320 
00321     for(std::vector<target>::const_iterator tg = targets.begin(); tg != targets.end(); ++tg) {
00322         tg->write(cfg.add_child("target"));
00323     }
00324 
00325     std::stringstream can_recruit_str;
00326     for(std::set<std::string>::const_iterator cr = can_recruit.begin(); cr != can_recruit.end(); ++cr) {
00327         if(cr != can_recruit.begin())
00328             can_recruit_str << ",";
00329 
00330         can_recruit_str << *cr;
00331     }
00332 
00333     cfg["recruit"] = can_recruit_str.str();
00334 
00335     std::stringstream recruit_pattern_str;
00336     std::vector<std::string> rp = global_recruitment_pattern;
00337     for(std::vector<std::string>::const_iterator p = rp.begin(); p != rp.end(); ++p) {
00338         if(p != rp.begin())
00339             recruit_pattern_str << ",";
00340 
00341         recruit_pattern_str << *p;
00342     }
00343 
00344     cfg["recruitment_pattern"] = recruit_pattern_str.str();
00345 
00346     cfg["share_maps"] = share_maps ? "yes" : "no";
00347     cfg["share_view"] = share_view ? "yes" : "no";
00348 
00349     if(music.empty() == false)
00350         cfg["music"] = music;
00351 
00352     cfg["colour"] = lexical_cast_default<std::string>(colour);
00353 }
00354 
00355 void team::merge_shroud_map_data(const std::string& shroud_data)
00356 {
00357     shroud_.merge(shroud_data);
00358 }
00359 
00360 team::team(const config& cfg, int gold) : 
00361         gold_(gold),
00362         villages_(),
00363         shroud_(),
00364         fog_(),
00365         auto_shroud_updates_(true), 
00366         info_(cfg), 
00367         countdown_time_(0),
00368         action_bonus_count_(0),
00369         aiparams_(),
00370         aggression_(0.0), 
00371         caution_(0.0),
00372         enemies_(),
00373         seen_(),
00374         ally_shroud_(),
00375         ally_fog_()
00376 {
00377     fog_.set_enabled( utils::string_bool(cfg["fog"]) );
00378     shroud_.set_enabled( utils::string_bool(cfg["shroud"]) );
00379     shroud_.read(cfg["shroud_data"]);
00380 
00381     LOG_NG << "team::team(...): team_name: " << info_.team_name
00382            << ", shroud: " << uses_shroud() << ", fog: " << uses_fog() << ".\n";
00383 
00384     // To ensure some mimimum starting gold,
00385     // gold is the maximum of 'gold' and what is given in the config file
00386     if(info_.gold.empty() == false)
00387     {
00388         gold_ = maximum(gold,::atoi(info_.gold.c_str()));
00389         if (gold_ != ::atoi(info_.gold.c_str()))
00390             info_.start_gold = str_cast(gold) + " (" + info_.start_gold + ")";
00391     }
00392 
00393     // Load in the villages the side controls at the start
00394     const config::child_list& villages = cfg.get_children("village");
00395     for(config::child_list::const_iterator v = villages.begin(); v != villages.end(); ++v) {
00396         villages_.insert(gamemap::location(**v,game_events::get_state_of_game()));
00397     }
00398 
00399     countdown_time_=lexical_cast_default<int>(cfg["countdown_time"],0);
00400     action_bonus_count_=lexical_cast_default<int>(cfg["action_bonus_count"],0);
00401 }
00402 
00403 void team::write(config& cfg) const
00404 {
00405     info_.write(cfg);
00406     cfg["shroud"] = uses_shroud() ? "yes" : "no";
00407     cfg["fog"] = uses_fog() ? "yes" : "no";
00408     cfg["gold"] = str_cast(gold_);
00409 
00410     // Write village locations
00411     for(std::set<gamemap::location>::const_iterator t = villages_.begin(); t != villages_.end(); ++t) {
00412         t->write(cfg.add_child("village"));
00413     }
00414 
00415     cfg["shroud_data"] = shroud_.write();
00416 
00417     cfg["countdown_time"] = str_cast(countdown_time_);
00418     cfg["action_bonus_count"] = str_cast(action_bonus_count_);
00419 }
00420 
00421 bool team::get_village(const gamemap::location& loc)
00422 {
00423     villages_.insert(loc);
00424     return game_events::fire("capture",loc);
00425 }
00426 
00427 void team::lose_village(const gamemap::location& loc)
00428 {
00429     if(owns_village(loc)) {
00430         villages_.erase(villages_.find(loc));
00431     }
00432 }
00433 
00434 void team::set_time_of_day(int turn, const time_of_day& tod)
00435 {
00436     aiparams_.clear();
00437     for(std::vector<config>::const_iterator i = info_.ai_params.begin(); i != info_.ai_params.end(); ++i) {
00438         const std::string& time_of_day = (*i)["time_of_day"];
00439         if(time_of_day.empty() == false) {
00440             const std::vector<std::string>& times = utils::split(time_of_day);
00441             if(std::count(times.begin(),times.end(),tod.id) == 0) {
00442                 continue;
00443             }
00444         }
00445 
00446         const std::string& turns = (*i)["turns"];
00447         if(turns.empty() == false) {
00448             bool matched = false;
00449 
00450             const std::vector<std::string>& turns_list = utils::split(turns);
00451             for(std::vector<std::string>::const_iterator j = turns_list.begin(); j != turns_list.end(); ++j) {
00452                 const std::pair<int,int> range = utils::parse_range(*j);
00453                 if(turn >= range.first && turn <= range.second) {
00454                     matched = true;
00455                     break;
00456                 }
00457             }
00458 
00459             if(!matched) {
00460                 continue;
00461             }
00462         }
00463 
00464         aiparams_.append(*i);
00465     }
00466 
00467     // Get the recruitment pattern from the matching [ai] section,
00468     // and fall back to the global recruitment pattern otherwise.
00469     info_.recruitment_pattern = utils::split(aiparams_["recruitment_pattern"]);
00470     if (info_.recruitment_pattern.empty())
00471         info_.recruitment_pattern = info_.global_recruitment_pattern;
00472     aggression_ = lexical_cast_default<double>(aiparams_["aggression"],0.5);
00473     caution_ = lexical_cast_default<double>(aiparams_["caution"],0.25);
00474 }
00475 
00476 bool team::calculate_enemies(size_t index) const
00477 {
00478     if(teams == NULL || index >= teams->size()) {
00479         return false;
00480     }
00481 
00482     while(enemies_.size() <= index) {
00483         enemies_.push_back(calculate_is_enemy(enemies_.size()));
00484     }
00485 
00486     return enemies_.back();
00487 }
00488 
00489 bool team::calculate_is_enemy(size_t index) const
00490 {
00491     // We're not enemies of ourselves
00492     if(&(*teams)[index] == this) {
00493         return false;
00494     }
00495 
00496     // If we have a team name, we are friends
00497     // with anyone who has the same team name
00498     if(info_.team_name.empty() == false) {
00499         return (*teams)[index].info_.team_name != info_.team_name;
00500     }
00501 
00502     // If enemies aren't listed, then everyone is an enemy
00503     if(info_.enemies.empty())
00504         return true;
00505 
00506     return std::find(info_.enemies.begin(),info_.enemies.end(),int(index+1)) != info_.enemies.end();
00507 }
00508 
00509 void team::change_controller(const std::string& controller)
00510 {
00511     team::team_info::CONTROLLER cid;
00512     if (controller == "human")
00513         cid = team::team_info::HUMAN;
00514     else if (controller == "network")
00515         cid = team::team_info::NETWORK;
00516     else if (controller == "null")
00517         cid = team::team_info::EMPTY;
00518     else
00519         cid = team::team_info::AI;
00520 
00521     info_.controller = cid;
00522 }
00523 
00524 void team::change_team(const std::string& name, const std::string& user_name)
00525 {
00526     info_.team_name = name;
00527     if (!user_name.empty())
00528     {
00529         info_.user_team_name = user_name;
00530     }
00531     else
00532     {
00533         info_.user_team_name = name;
00534     }
00535 
00536     // Reset the cache of allies for all teams
00537     if(teams != NULL) {
00538         for(std::vector<team>::const_iterator i = teams->begin(); i != teams->end(); ++i) {
00539             i->enemies_.clear();
00540         }
00541     }
00542 }
00543 
00544 void team::set_objectives(const t_string& new_objectives, bool silently)
00545 {
00546     info_.objectives = new_objectives;
00547     if(!silently)
00548         info_.objectives_changed = true;
00549 }
00550 
00551 void team::set_ai_memory(const config& ai_mem){
00552   // It would perhaps be more efficient to allow writing to the memory directly,
00553   // but this method comparmentalizes the functionality and protects against
00554   // accidentally overwriting the memory
00555   info_.ai_memory_=ai_mem;
00556 }
00557 
00558 void team::set_ai_parameters(const config::child_list& ai_parameters)
00559 {
00560     info_.ai_params.clear();        // override
00561     config::child_list::const_iterator i;
00562     for (i = ai_parameters.begin(); i != ai_parameters.end(); ++i) {
00563         info_.ai_params.push_back(**i);
00564     }
00565 }
00566 
00567 bool team::shrouded(const gamemap::location& loc) const
00568 {
00569     if(!teams)
00570         return shroud_.value(loc.x+1,loc.y+1);
00571 
00572     return shroud_.shared_value(ally_shroud(*teams),loc.x+1,loc.y+1);
00573 }
00574 
00575 bool team::fogged(const gamemap::location& loc) const
00576 {
00577     if(shrouded(loc)) return true;
00578 
00579     if(!teams)
00580         return fog_.value(loc.x+1,loc.y+1);
00581 
00582     return fog_.shared_value(ally_fog(*teams),loc.x+1,loc.y+1);
00583 }
00584 
00585 const std::vector<const team::shroud_map*>& team::ally_shroud(const std::vector<team>& teams) const
00586 {
00587     if(ally_shroud_.empty()) {
00588         for(size_t i = 0; i < teams.size(); ++i) {
00589             if(!is_enemy(i + 1) && (&(teams[i]) == this || teams[i].share_view() || teams[i].share_maps())) {
00590                 ally_shroud_.push_back(&(teams[i].shroud_));
00591             }
00592         }
00593     }
00594 
00595     return ally_shroud_;
00596 }
00597 
00598 const std::vector<const team::shroud_map*>& team::ally_fog(const std::vector<team>& teams) const
00599 {
00600     if(ally_fog_.empty()) {
00601         for(size_t i = 0; i < teams.size(); ++i) {
00602             if(!is_enemy(i + 1) && (&(teams[i]) == this || teams[i].share_view())) {
00603                 ally_fog_.push_back(&(teams[i].fog_));
00604             }
00605         }
00606     }
00607 
00608     return ally_fog_;
00609 }
00610 
00611 bool team::knows_about_team(size_t index) const
00612 {
00613     const team& t = (*teams)[index];
00614 
00615     // We know about our own team
00616     if(this == &t) return true;
00617 
00618     // If we aren't using shroud or fog, then we know about everyone
00619     if(!uses_shroud() && !uses_fog()) return true;
00620 
00621     // We don't know about enemies
00622     if(is_enemy(index+1)) return false;
00623 
00624     // We know our allies in multiplayer
00625     if(network::nconnections() > 0) return true;
00626 
00627     // We know about allies we're sharing maps with
00628     if(share_maps() && t.uses_shroud()) return true;
00629 
00630     // We know about allies we're sharing view with
00631     if(share_view() && (t.uses_fog() || t.uses_shroud())) return true;
00632 
00633     return false;
00634 }
00635 
00636 bool team::copy_ally_shroud()
00637 {
00638     if(!teams || !share_maps())
00639         return false;
00640 
00641     return shroud_.copy_from(ally_shroud(*teams));
00642 }
00643 
00644 int team::nteams()
00645 {
00646     if(teams == NULL) {
00647         return 0;
00648     } else {
00649         return teams->size();
00650     }
00651 }
00652 
00653 bool is_observer()
00654 {
00655     if(teams == NULL) {
00656         return true;
00657     }
00658 
00659     for(std::vector<team>::const_iterator i = teams->begin(); i != teams->end(); ++i) {
00660         if(i->is_human()) {
00661             return false;
00662         }
00663     }
00664 
00665     return true;
00666 }
00667 
00668 void validate_side(int side)
00669 {
00670     if(teams == NULL) {
00671         return;
00672     }
00673 
00674     if(side < 1 || side > int(teams->size())) {
00675         throw game::game_error("invalid side(" + str_cast(side) + ") found in unit definition");
00676     }
00677 }
00678 
00679 bool team::shroud_map::clear(size_t x, size_t y)
00680 {
00681     if(enabled_ == false)
00682         return false;
00683 
00684     if(x >= data_.size())
00685         data_.resize(x+1);
00686 
00687     if(y >= data_[x].size())
00688         data_[x].resize(y+1);
00689 
00690     if(data_[x][y] == false) {
00691         data_[x][y] = true;
00692         return true;
00693     } else {
00694         return false;
00695     }
00696 }
00697 
00698 void team::shroud_map::place(size_t x, size_t y)
00699 {
00700     if(enabled_ == false)
00701         return;
00702 
00703     if(x < data_.size() && y < data_[x].size()) {
00704         data_[x][y] = false;
00705     }
00706 }
00707 
00708 void team::shroud_map::reset()
00709 {
00710     if(enabled_ == false)
00711         return;
00712 
00713     for(std::vector<std::vector<bool> >::iterator i = data_.begin(); i != data_.end(); ++i) {
00714         std::fill(i->begin(),i->end(),false);
00715     }
00716 }
00717 
00718 bool team::shroud_map::value(size_t x, size_t y) const
00719 {
00720     if(enabled_ == false)
00721         return false;
00722 
00723     if(x >= data_.size())
00724         return true;
00725 
00726     if(y >= data_[x].size())
00727         return true;
00728 
00729     if(data_[x][y])
00730         return false;
00731     else
00732         return true;
00733 }
00734 
00735 bool team::shroud_map::shared_value(const std::vector<const shroud_map*>& maps, size_t x, size_t y) const
00736 {
00737     if(enabled_ == false)
00738         return false;
00739 
00740     for(std::vector<const shroud_map*>::const_iterator i = maps.begin(); i != maps.end(); ++i) {
00741         if((*i)->enabled_ == true && (*i)->value(x,y) == false)
00742             return false;
00743     }
00744     return true;
00745 }
00746 
00747 std::string team::shroud_map::write() const
00748 {
00749     std::stringstream shroud_str;
00750     for(std::vector<std::vector<bool> >::const_iterator sh = data_.begin(); sh != data_.end(); ++sh) {
00751         shroud_str << '|';
00752 
00753         for(std::vector<bool>::const_iterator i = sh->begin(); i != sh->end(); ++i) {
00754             shroud_str << (*i ? '1' : '0');
00755         }
00756 
00757         shroud_str << '\n';
00758     }
00759 
00760     return shroud_str.str();
00761 }
00762 
00763 void team::shroud_map::read(const std::string& str)
00764 { 
00765     data_.clear();
00766     for(std::string::const_iterator sh = str.begin(); sh != str.end(); ++sh) {
00767         if(*sh == '|')
00768             data_.resize(data_.size()+1);
00769 
00770         if(data_.empty() == false) {
00771             if(*sh == '1')
00772                 data_.back().push_back(true);
00773             else if(*sh == '0')
00774                 data_.back().push_back(false);
00775         }
00776     }
00777 }
00778 
00779 void team::shroud_map::merge(const std::string& str)
00780 { 
00781     int x=0, y=0;
00782     for(std::string::const_iterator sh = str.begin(); sh != str.end(); ++sh) {
00783         if(*sh == '|' && sh != str.begin()) {
00784             y=0;
00785             x++;
00786         } else if(*sh == '1') {
00787             clear(x,y);
00788             y++;
00789         } else if(*sh == '0') {
00790             y++;
00791         }
00792     }
00793 }
00794 
00795 bool team::shroud_map::copy_from(const std::vector<const shroud_map*>& maps)
00796 {
00797     if(enabled_ == false)
00798         return false;
00799 
00800     bool cleared = false;
00801     for(std::vector<const shroud_map*>::const_iterator i = maps.begin(); i != maps.end(); ++i) {
00802         if((*i)->enabled_ == false)
00803             continue;
00804 
00805         const std::vector<std::vector<bool> >& v = (*i)->data_;
00806         for(size_t x = 0; x != v.size(); ++x) {
00807             for(size_t y = 0; y != v[x].size(); ++y) {
00808                 if(v[x][y]) {
00809                     cleared |= clear(x,y);
00810                 }
00811             }
00812         }
00813     }
00814     return cleared;
00815 }
00816 
00817 std::map<int, color_range> team::team_color_range_;
00818 
00819 const color_range team::get_side_color_range(int side){
00820   std::string index = get_side_colour_index(side);
00821   std::map<std::string, color_range>::iterator gp=game_config::team_rgb_range.find(index);
00822 
00823   if(gp != game_config::team_rgb_range.end()){
00824     return(gp->second);
00825   }
00826 
00827   return(color_range(0x00FF0000,0x00FFFFFF,0x00000000,0x00FF0000));
00828 }
00829 
00830 const SDL_Color team::get_minimap_colour(int side)
00831 {
00832     // Note: use mid() instead of rep() unless
00833     // high contrast is needed over a map or minimap!
00834     return int_to_color(get_side_color_range(side).rep());
00835 }
00836 
00837 std::string team::get_side_colour_index(int side)
00838 {
00839     size_t index = size_t(side-1);
00840 
00841     if(teams != NULL && index < teams->size()) {
00842         const std::string side_map = (*teams)[index].map_colour_to();
00843         if(side_map.size()) {
00844             return side_map;
00845         }
00846     }
00847     std::stringstream id;
00848     id<<side;
00849     return id.str();
00850 }
00851 
00852 std::string team::get_side_highlight(int side)
00853 {
00854     return rgb2highlight(get_side_color_range(side+1).mid());
00855 }
00856 
00857 void team::log_recruitable(){
00858     LOG_NG << "Adding recruitable units: \n";
00859     for (std::set<std::string>::const_iterator it = info_.can_recruit.begin();
00860          it != info_.can_recruit.end(); it++) {
00861         LOG_NG << *it << std::endl;
00862     }
00863     LOG_NG << "Added all recruitable units\n";
00864 }
00865 
00866 namespace player_teams {
00867 int village_owner(const gamemap::location& loc)
00868 {
00869     if(! teams) {
00870         return -1;
00871     }
00872     for(size_t i = 0; i != teams->size(); ++i) {
00873         if((*teams)[i].owns_village(loc))
00874             return i;
00875     }
00876     return -1;
00877 }
00878 }

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs