00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "global.hpp"
00016
00017 #define GETTEXT_DOMAIN "wesnoth-lib"
00018
00019 #include "mapgen_dialog.hpp"
00020
00021 #include "display.hpp"
00022 #include "events.hpp"
00023 #include "gettext.hpp"
00024 #include "log.hpp"
00025 #include "mapgen.hpp"
00026 #include "marked-up_text.hpp"
00027 #include "show_dialog.hpp"
00028 #include "util.hpp"
00029 #include "video.hpp"
00030
00031 #include "widgets/button.hpp"
00032 #include "widgets/slider.hpp"
00033
00034 #define DBG_NG LOG_STREAM(debug, engine)
00035
00036 namespace {
00037 const size_t max_island = 10;
00038 const size_t max_coastal = 5;
00039 }
00040
00041 default_map_generator::default_map_generator(const config* cfg)
00042 : width_(40), height_(40), island_size_(0), iterations_(1000), hill_size_(10), max_lakes_(20),
00043 nvillages_(25), castle_size_(9), nplayers_(2), link_castles_(true)
00044 {
00045 if(cfg != NULL) {
00046 cfg_ = *cfg;
00047
00048 const int width = ::atoi((*cfg)["map_width"].c_str());
00049 if(width > 0)
00050 width_ = width;
00051
00052 const int height = ::atoi((*cfg)["map_height"].c_str());
00053 if(height > 0)
00054 height_ = height;
00055
00056 default_width_ = width_;
00057 default_height_ = height_;
00058
00059 const int iterations = ::atoi((*cfg)["iterations"].c_str());
00060 if(iterations > 0)
00061 iterations_ = iterations;
00062
00063 const int hill_size = ::atoi((*cfg)["hill_size"].c_str());
00064 if(hill_size > 0)
00065 hill_size_ = hill_size;
00066
00067 const int max_lakes = ::atoi((*cfg)["max_lakes"].c_str());
00068 if(max_lakes > 0)
00069 max_lakes_ = max_lakes;
00070
00071 const int nvillages = ::atoi((*cfg)["villages"].c_str());
00072 if(nvillages > 0)
00073 nvillages_ = nvillages;
00074
00075 const int castle_size = ::atoi((*cfg)["castle_size"].c_str());
00076 if(castle_size > 0)
00077 castle_size_ = castle_size;
00078
00079 const int nplayers = ::atoi((*cfg)["players"].c_str());
00080 if(nplayers > 0)
00081 nplayers_ = nplayers;
00082
00083 const int island_size = ::atoi((*cfg)["island_size"].c_str());
00084 if(island_size > 0)
00085 island_size_ = island_size;
00086 }
00087 }
00088
00089 bool default_map_generator::allow_user_config() const { return true; }
00090
00091 void default_map_generator::user_config(display& disp)
00092 {
00093 const resize_lock prevent_resizing;
00094 const events::event_context dialog_events_context;
00095
00096 CVideo& screen = disp.video();
00097
00098 const int width = 600;
00099 const int height = 400;
00100 const int xpos = screen.getx()/2 - width/2;
00101 int ypos = screen.gety()/2 - height/2;
00102
00103 gui::button close_button(screen,_("Close Window"));
00104 std::vector<gui::button*> buttons(1,&close_button);
00105
00106 gui::dialog_frame f(screen,_("Map Generator"),gui::dialog_frame::default_style,true,&buttons);
00107 f.layout(xpos,ypos,width,height);
00108 f.draw();
00109
00110 SDL_Rect dialog_rect = {xpos,ypos,width,height};
00111 surface_restorer dialog_restorer(&screen,dialog_rect);
00112
00113 const std::string& players_label = _("Players:");
00114 const std::string& width_label = _("Width:");
00115 const std::string& height_label = _("Height:");
00116 const std::string& iterations_label = _("Number of Hills:");
00117 const std::string& hillsize_label = _("Max Hill Size:");
00118 const std::string& villages_label = _("Villages:");
00119 const std::string& castlesize_label = _("Castle Size:");
00120 const std::string& landform_label = _("Landform:");
00121
00122 SDL_Rect players_rect = font::draw_text(NULL,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,players_label,0,0);
00123 SDL_Rect width_rect = font::draw_text(NULL,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,width_label,0,0);
00124 SDL_Rect height_rect = font::draw_text(NULL,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,height_label,0,0);
00125 SDL_Rect iterations_rect = font::draw_text(NULL,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,iterations_label,0,0);
00126 SDL_Rect hillsize_rect = font::draw_text(NULL,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,hillsize_label,0,0);
00127 SDL_Rect villages_rect = font::draw_text(NULL,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,villages_label,0,0);
00128 SDL_Rect castlesize_rect = font::draw_text(NULL,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,castlesize_label,0,0);
00129 SDL_Rect landform_rect = font::draw_text(NULL,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,landform_label,0,0);
00130
00131 const int horz_margin = 15;
00132 const int text_right = xpos + horz_margin +
00133 maximum<int>(maximum<int>(maximum<int>(maximum<int>(maximum<int>(maximum<int>(
00134 players_rect.w,width_rect.w),height_rect.w),iterations_rect.w),hillsize_rect.w),villages_rect.w),castlesize_rect.w);
00135
00136 players_rect.x = text_right - players_rect.w;
00137 width_rect.x = text_right - width_rect.w;
00138 height_rect.x = text_right - height_rect.w;
00139 iterations_rect.x = text_right - iterations_rect.w;
00140 hillsize_rect.x = text_right - hillsize_rect.w;
00141 villages_rect.x = text_right - villages_rect.w;
00142 castlesize_rect.x = text_right - castlesize_rect.w;
00143 landform_rect.x = text_right - landform_rect.w;
00144
00145 const int vertical_margin = 20;
00146 players_rect.y = ypos + vertical_margin*2;
00147 width_rect.y = players_rect.y + players_rect.h + vertical_margin;
00148 height_rect.y = width_rect.y + width_rect.h + vertical_margin;
00149 iterations_rect.y = height_rect.y + height_rect.h + vertical_margin;
00150 hillsize_rect.y = iterations_rect.y + iterations_rect.h + vertical_margin;
00151 villages_rect.y = hillsize_rect.y + hillsize_rect.h + vertical_margin;
00152 castlesize_rect.y = villages_rect.y + iterations_rect.h + vertical_margin;
00153 landform_rect.y = castlesize_rect.y + villages_rect.h + vertical_margin;
00154
00155 const int right_space = 150;
00156
00157 const int slider_left = text_right + 10;
00158 const int slider_right = xpos + width - horz_margin - right_space;
00159 SDL_Rect slider_rect = { slider_left,players_rect.y,slider_right-slider_left,players_rect.h};
00160 gui::slider players_slider(screen);
00161 players_slider.set_location(slider_rect);
00162 players_slider.set_min(2);
00163 players_slider.set_max(gamemap::MAX_PLAYERS);
00164 players_slider.set_value(nplayers_);
00165
00166 const int min_width = 20;
00167 const int max_width = 100;
00168 const int max_height = 100;
00169 const int extra_size_per_player = 2;
00170
00171 slider_rect.y = width_rect.y;
00172 gui::slider width_slider(screen);
00173 width_slider.set_location(slider_rect);
00174 width_slider.set_min(min_width+(players_slider.value()-2)*extra_size_per_player);
00175 width_slider.set_max(max_width);
00176 width_slider.set_value(width_);
00177
00178 slider_rect.y = height_rect.y;
00179 gui::slider height_slider(screen);
00180 height_slider.set_location(slider_rect);
00181 height_slider.set_min(min_width+(players_slider.value()-2)*extra_size_per_player);
00182 height_slider.set_max(max_height);
00183 height_slider.set_value(height_);
00184
00185 const int min_iterations = 10;
00186 const int max_iterations = 3000;
00187
00188 slider_rect.y = iterations_rect.y;
00189 gui::slider iterations_slider(screen);
00190 iterations_slider.set_location(slider_rect);
00191 iterations_slider.set_min(min_iterations);
00192 iterations_slider.set_max(max_iterations);
00193 iterations_slider.set_value(iterations_);
00194
00195 const int min_hillsize = 1;
00196 const int max_hillsize = 50;
00197
00198 slider_rect.y = hillsize_rect.y;
00199 gui::slider hillsize_slider(screen);
00200 hillsize_slider.set_location(slider_rect);
00201 hillsize_slider.set_min(min_hillsize);
00202 hillsize_slider.set_max(max_hillsize);
00203 hillsize_slider.set_value(hill_size_);
00204
00205 const int min_villages = 0;
00206 const int max_villages = 50;
00207
00208 slider_rect.y = villages_rect.y;
00209 gui::slider villages_slider(screen);
00210 villages_slider.set_location(slider_rect);
00211 villages_slider.set_min(min_villages);
00212 villages_slider.set_max(max_villages);
00213 villages_slider.set_value(nvillages_);
00214
00215 const int min_castlesize = 2;
00216 const int max_castlesize = 14;
00217
00218 slider_rect.y = castlesize_rect.y;
00219 gui::slider castlesize_slider(screen);
00220 castlesize_slider.set_location(slider_rect);
00221 castlesize_slider.set_min(min_castlesize);
00222 castlesize_slider.set_max(max_castlesize);
00223 castlesize_slider.set_value(castle_size_);
00224
00225
00226 const int min_landform = 0;
00227 const int max_landform = int(max_island);
00228 slider_rect.y = landform_rect.y;
00229 gui::slider landform_slider(screen);
00230 landform_slider.set_location(slider_rect);
00231 landform_slider.set_min(min_landform);
00232 landform_slider.set_max(max_landform);
00233 landform_slider.set_value(island_size_);
00234
00235 SDL_Rect link_rect = slider_rect;
00236 link_rect.y = link_rect.y + link_rect.h + vertical_margin;
00237
00238 gui::button link_castles(screen,_("Roads Between Castles"),gui::button::TYPE_CHECK);
00239 link_castles.set_check(link_castles_);
00240 link_castles.set_location(link_rect);
00241
00242 for(bool draw = true;; draw = false) {
00243 nplayers_ = players_slider.value();
00244 width_ = width_slider.value();
00245 height_ = height_slider.value();
00246 iterations_ = iterations_slider.value();
00247 hill_size_ = hillsize_slider.value();
00248 nvillages_ = villages_slider.value();
00249 castle_size_ = castlesize_slider.value();
00250 island_size_ = landform_slider.value();
00251
00252 dialog_restorer.restore();
00253 close_button.set_dirty(true);
00254 if (close_button.pressed())
00255 break;
00256
00257 players_slider.set_dirty();
00258 width_slider.set_dirty();
00259 height_slider.set_dirty();
00260 iterations_slider.set_dirty();
00261 hillsize_slider.set_dirty();
00262 villages_slider.set_dirty();
00263 castlesize_slider.set_dirty();
00264 landform_slider.set_dirty();
00265 link_castles.set_dirty();
00266
00267 width_slider.set_min(min_width+(players_slider.value()-2)*extra_size_per_player);
00268 height_slider.set_min(min_width+(players_slider.value()-2)*extra_size_per_player);
00269
00270 events::raise_process_event();
00271 events::raise_draw_event();
00272
00273 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,players_label,players_rect.x,players_rect.y);
00274 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,width_label,width_rect.x,width_rect.y);
00275 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,height_label,height_rect.x,height_rect.y);
00276 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,iterations_label,iterations_rect.x,iterations_rect.y);
00277 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,hillsize_label,hillsize_rect.x,hillsize_rect.y);
00278 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,villages_label,villages_rect.x,villages_rect.y);
00279 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,castlesize_label,castlesize_rect.x,castlesize_rect.y);
00280 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,landform_label,landform_rect.x,landform_rect.y);
00281
00282 std::stringstream players_str;
00283 players_str << nplayers_;
00284 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,players_str.str(),
00285 slider_right+horz_margin,players_rect.y);
00286
00287 std::stringstream width_str;
00288 width_str << width_;
00289 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,width_str.str(),
00290 slider_right+horz_margin,width_rect.y);
00291
00292 std::stringstream height_str;
00293 height_str << height_;
00294 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,height_str.str(),
00295 slider_right+horz_margin,height_rect.y);
00296
00297 std::stringstream villages_str;
00298 villages_str << nvillages_ << _("/1000 tiles");
00299 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,villages_str.str(),
00300 slider_right+horz_margin,villages_rect.y);
00301
00302 std::stringstream castlesize_str;
00303 castlesize_str << castle_size_;
00304 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,castlesize_str.str(),
00305 slider_right+horz_margin,castlesize_rect.y);
00306
00307 std::stringstream landform_str;
00308 landform_str << gettext(island_size_ == 0 ? N_("Inland") : (island_size_ < max_coastal ? N_("Coastal") : N_("Island")));
00309 font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOUR,landform_str.str(),
00310 slider_right+horz_margin,landform_rect.y);
00311
00312 update_rect(xpos,ypos,width,height);
00313
00314 disp.update_display();
00315 disp.delay(100);
00316 events::pump();
00317 }
00318
00319 link_castles_ = link_castles.checked();
00320 }
00321
00322 std::string default_map_generator::name() const { return "default"; }
00323
00324 std::string default_map_generator::create_map(const std::vector<std::string>& args)
00325 {
00326 return generate_map(args);
00327 }
00328
00329 std::string default_map_generator::generate_map(const std::vector<std::string>& , std::map<gamemap::location,std::string>* labels)
00330 {
00331
00332 if (is_odd(width_))
00333 ++width_;
00334
00335 size_t iterations = (iterations_*width_*height_)/(default_width_*default_height_);
00336 size_t island_size = 0;
00337 size_t island_off_center = 0;
00338 size_t max_lakes = max_lakes_;
00339
00340 if(island_size_ >= max_coastal) {
00341
00342
00343 iterations /= 10;
00344 max_lakes /= 9;
00345
00346
00347 const size_t island_radius = 50 + ((max_island - island_size_)*50)/(max_island - max_coastal);
00348 island_size = (island_radius*(width_/2))/100;
00349 } else if(island_size_ > 0) {
00350 DBG_NG << "coastal...\n";
00351
00352 const size_t island_radius = 40 + ((max_coastal - island_size_)*40)/max_coastal;
00353 island_size = (island_radius*width_*2)/100;
00354 island_off_center = minimum<size_t>(width_,height_);
00355 DBG_NG << "calculated coastal params...\n";
00356 }
00357
00358
00359 std::string map;
00360
00361 std::map<gamemap::location,std::string> labels_copy;
00362 int tries = 10;
00363 do {
00364 if (labels) {
00365 labels_copy = *labels;
00366 }
00367 map = default_generate_map(width_, height_, island_size, island_off_center,
00368 iterations, hill_size_, max_lakes, (nvillages_ * width_ * height_) / 1000,
00369 castle_size_, nplayers_, link_castles_, labels, cfg_);
00370 --tries;
00371 } while (tries && map.empty());
00372 if (labels) {
00373 labels->swap(labels_copy);
00374 }
00375 return map;
00376 }
00377
00378 config default_map_generator::create_scenario(const std::vector<std::string>& args)
00379 {
00380 DBG_NG << "creating scenario...\n";
00381 config res;
00382
00383 const config* const scenario = cfg_.child("scenario");
00384 if(scenario != NULL) {
00385 res = *scenario;
00386 }
00387
00388 DBG_NG << "got scenario data...\n";
00389
00390 std::map<gamemap::location,std::string> labels;
00391 DBG_NG << "generating map...\n";
00392 res["map_data"] = generate_map(args,&labels);
00393 DBG_NG << "done generating map..\n";
00394
00395 for(std::map<gamemap::location,std::string>::const_iterator i =
00396 labels.begin(); i != labels.end(); ++i) {
00397
00398 if(i->first.x >= 0 && i->first.y >= 0 &&
00399 i->first.x < static_cast<long>(width_) &&
00400 i->first.y < static_cast<long>(height_)) {
00401
00402 config& label = res.add_child("label");
00403 label["text"] = i->second;
00404 i->first.write(label);
00405 }
00406 }
00407
00408 return res;
00409 }