terrain.cpp

Go to the documentation of this file.
00001 /* $Id: terrain.cpp 26689 2008-05-18 12:53:14Z mog $ */
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 #include "global.hpp"
00016 
00017 #include "config.hpp"
00018 #include "gettext.hpp"
00019 #include "log.hpp"
00020 #include "util.hpp"
00021 #include "terrain.hpp"
00022 #include "serialization/string_utils.hpp"
00023 #include "tstring.hpp"
00024 #include "wml_exception.hpp"
00025 
00026 #include <algorithm>
00027 #include <cstdlib>
00028 #include <iostream>
00029 
00030 
00031 terrain_type::terrain_type() :
00032         minimap_image_("void"), 
00033         minimap_image_overlay_("void"), 
00034         editor_image_("void"),
00035         id_(),
00036         name_(),
00037         number_(t_translation::VOID_TERRAIN),
00038         mvt_type_(1, t_translation::VOID_TERRAIN),
00039         def_type_(1, t_translation::VOID_TERRAIN),
00040         union_type_(1, t_translation::VOID_TERRAIN),
00041         height_adjust_(0), 
00042         submerge_(0.0), 
00043         light_modification_(0),
00044         heals_(0), 
00045         income_description_(),
00046         income_description_ally_(),
00047         income_description_enemy_(),
00048         income_description_own_(),
00049         editor_group_(),
00050         village_(false), 
00051         castle_(false), 
00052         keep_(false),
00053         overlay_(false), 
00054         combined_(false),
00055         editor_default_base_(t_translation::VOID_TERRAIN)
00056 {}
00057 
00058 terrain_type::terrain_type(const config& cfg) :
00059         minimap_image_(cfg["symbol_image"]),
00060         minimap_image_overlay_("void"), 
00061         editor_image_(cfg["editor_image"]),
00062         id_(cfg["id"]),
00063         name_(cfg["name"]),
00064         number_(t_translation::read_terrain_code(cfg["string"])),
00065         mvt_type_(),
00066         def_type_(),
00067         union_type_(),
00068         height_adjust_(atoi(cfg["unit_height_adjust"].c_str())),
00069         submerge_(atof(cfg["submerge"].c_str())),
00070         light_modification_(atoi(cfg["light"].c_str())),
00071         heals_(lexical_cast_default<int>(cfg["heals"], 0)),
00072         income_description_(),
00073         income_description_ally_(),
00074         income_description_enemy_(),
00075         income_description_own_(),
00076         editor_group_(cfg["editor_group"]),
00077         village_(utils::string_bool(cfg["gives_income"])),
00078         castle_(utils::string_bool(cfg["recruit_onto"])),
00079         keep_(utils::string_bool(cfg["recruit_from"])),
00080         editor_default_base_(t_translation::read_terrain_code(cfg["default_base"]))
00081 {
00082 //! @todo reenable these validations. The problem is that all MP 
00083 //! scenarios/campaigns share the same namespace and one rogue scenario
00084 //! can avoid the player to create a MP game. So every scenario/campaign
00085 //! should get it's own namespace to be save. 
00086 #if 0
00087     VALIDATE(number_ != t_translation::NONE_TERRAIN, 
00088         missing_mandatory_wml_key("terrain", "string"));
00089     VALIDATE(!minimap_image_.empty(), 
00090         missing_mandatory_wml_key("terrain", "symbol_image", "string", 
00091         t_translation::write_terrain_code(number_)));
00092     VALIDATE(!name_.empty(), 
00093         missing_mandatory_wml_key("terrain", "name", "string", 
00094         t_translation::write_terrain_code(number_)));
00095 #endif
00096 
00097     if(editor_image_.empty()) {
00098         editor_image_ = minimap_image_;
00099     }
00100 
00101     combined_ = false;
00102     overlay_ = (number_.base == t_translation::NO_LAYER) ? true : false; 
00103 
00104     mvt_type_.push_back(number_);
00105     def_type_.push_back(number_);
00106     const t_translation::t_list& alias = t_translation::read_list(cfg["aliasof"]);
00107     if(!alias.empty()) {
00108         mvt_type_ = alias;
00109         def_type_ = alias;
00110     }
00111 
00112     const t_translation::t_list& mvt_alias = t_translation::read_list(cfg["mvt_alias"]);
00113     if(!mvt_alias.empty()) {
00114         mvt_type_ = mvt_alias;
00115     }
00116 
00117     const t_translation::t_list& def_alias = t_translation::read_list(cfg["def_alias"]);
00118     if(!def_alias.empty()) {
00119         def_type_ = def_alias;
00120     }
00121     union_type_ = mvt_type_;
00122     union_type_.insert( union_type_.end(), def_type_.begin(), def_type_.end() );
00123 
00124     // remove + and -
00125     union_type_.erase(std::remove(union_type_.begin(), union_type_.end(),
00126                 t_translation::MINUS), union_type_.end());
00127 
00128     union_type_.erase(std::remove(union_type_.begin(), union_type_.end(),
00129                 t_translation::PLUS), union_type_.end());
00130 
00131     // remove doubles
00132     std::sort(union_type_.begin(),union_type_.end());
00133     union_type_.erase(std::unique(union_type_.begin(), union_type_.end()), union_type_.end());
00134 
00135 #ifdef USE_TINY_GUI
00136     height_adjust_ /= 2;
00137 #endif
00138 
00139 
00140     //mouse over message are only shown on villages
00141     if(village_) {
00142         income_description_ = cfg["income_description"];
00143         if(income_description_ == "") {
00144             income_description_ = _("Village");
00145         }
00146 
00147         income_description_ally_ = cfg["income_description_ally"];
00148         if(income_description_ally_ == "") {
00149             income_description_ally_ = _("Allied village");
00150         }
00151 
00152         income_description_enemy_ = cfg["income_description_enemy"];
00153         if(income_description_enemy_ == "") {
00154             income_description_enemy_ = _("Enemy village");
00155         }
00156 
00157         income_description_own_ = cfg["income_description_own"];
00158         if(income_description_own_ == "") {
00159             income_description_own_ = _("Owned village");
00160         }
00161     }
00162 }
00163 
00164 terrain_type::terrain_type(const terrain_type& base, const terrain_type& overlay) : 
00165     overlay_(false), 
00166     combined_(true)
00167 {
00168     number_ = t_translation::t_terrain(base.number_.base, overlay.number_.overlay);
00169 
00170     minimap_image_ = base.minimap_image_;
00171     minimap_image_overlay_ = overlay.minimap_image_;
00172     editor_image_ = overlay.editor_image_;
00173 
00174     name_ = overlay.name_;
00175     id_ = base.id_+"^"+overlay.id_;
00176 
00177     mvt_type_ = overlay.mvt_type_;
00178     def_type_ = overlay.def_type_;
00179 
00180     merge_alias_lists(mvt_type_, base.mvt_type_); 
00181     merge_alias_lists(def_type_, base.def_type_); 
00182 
00183     union_type_ = mvt_type_;
00184     union_type_.insert( union_type_.end(), def_type_.begin(), def_type_.end() );
00185 
00186     // remove + and -
00187     union_type_.erase(std::remove(union_type_.begin(), union_type_.end(),
00188                 t_translation::MINUS), union_type_.end());
00189 
00190     union_type_.erase(std::remove(union_type_.begin(), union_type_.end(),
00191                 t_translation::PLUS), union_type_.end());
00192 
00193     // remove doubles
00194     std::sort(union_type_.begin(),union_type_.end());
00195     union_type_.erase(std::unique(union_type_.begin(), union_type_.end()), union_type_.end());
00196 
00197 
00198     height_adjust_ = overlay.height_adjust_;
00199     submerge_ = overlay.submerge_;
00200     light_modification_ = base.light_modification_ + overlay.light_modification_;
00201 
00202     heals_ = maximum<int>(base.heals_, overlay.heals_);
00203 
00204     village_ = base.village_ | overlay.village_;
00205     castle_ = base.castle_ | overlay.castle_;
00206     keep_ = base.keep_ | overlay.keep_;
00207 
00208     //mouse over message are only shown on villages
00209     if(base.village_) {
00210         income_description_ = base.income_description_;
00211         income_description_ally_ = base.income_description_ally_;
00212         income_description_enemy_ = base.income_description_enemy_;
00213         income_description_own_ = base.income_description_own_;
00214     }
00215     else if (overlay.village_) {
00216         income_description_ = overlay.income_description_;
00217         income_description_ally_ = overlay.income_description_ally_;
00218         income_description_enemy_ = overlay.income_description_enemy_;
00219         income_description_own_ = overlay.income_description_own_;
00220     }
00221 
00222     editor_group_ = ""; 
00223     
00224 }
00225 
00226 t_translation::t_terrain terrain_type::terrain_with_default_base() const {
00227     if(overlay_ && editor_default_base_ != t_translation::NONE_TERRAIN) {
00228         return t_translation::t_terrain(editor_default_base_.base, number_.overlay);
00229     }
00230     return number_;
00231 }
00232 
00233 void create_terrain_maps(const std::vector<config*>& cfgs,
00234                          t_translation::t_list& terrain_list,
00235                          std::map<t_translation::t_terrain, terrain_type>& letter_to_terrain)
00236 {
00237     for(std::vector<config*>::const_iterator i = cfgs.begin();
00238         i != cfgs.end(); ++i) {
00239         terrain_type terrain(**i);
00240         terrain_list.push_back(terrain.number());
00241         letter_to_terrain.insert(std::pair<t_translation::t_terrain, terrain_type>(
00242                                       terrain.number(),terrain));
00243     }
00244 }
00245 
00246 void merge_alias_lists(t_translation::t_list& first, const t_translation::t_list& second)
00247 {
00248     // Insert second vector into first when the terrain _ref^base is encountered
00249 
00250     bool revert = (first.front() == t_translation::MINUS ? true : false);
00251     t_translation::t_list::iterator i;
00252 
00253     for(i = first.begin(); i != first.end(); i++) {
00254         if(*i == t_translation::PLUS) {
00255             revert = false;
00256             continue;
00257         } else if(*i == t_translation::MINUS) {
00258             revert = true;
00259             continue;
00260         }
00261 
00262         if(*i == t_translation::BASE) {
00263             t_translation::t_list::iterator insert_it = first.erase(i);
00264             //if we are in reverse mode, insert PLUS before and MINUS after the base list
00265             //so calculation of base aliases will work normal
00266             if(revert) {
00267                 insert_it = first.insert(insert_it, t_translation::PLUS);
00268                 insert_it++;
00269                 insert_it = first.insert(insert_it, t_translation::MINUS);
00270             }
00271             else {
00272                 //else insert PLUS after the base aliases to restore previous "reverse state"
00273                 insert_it =  first.insert(insert_it, t_translation::PLUS);
00274             }
00275 
00276             first.insert(insert_it, second.begin(), second.end());
00277 
00278             break;
00279         }
00280     }
00281 
00282 }

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