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