1 // Copyright (C) 2007 Ole Laursen
2 // Copyright (C) 2007, 2008, 2009 Ben Asselstine
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Library General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 #include <sigc++/functors/mem_fun.h>
25 #include "new-random-map-dialog.h"
27 #include "glade-helpers.h"
31 #include "tilesetlist.h"
32 #include "armysetlist.h"
33 #include "citysetlist.h"
34 #include "shieldsetlist.h"
35 #include "ucompose.hpp"
37 #include "GameScenarioOptions.h"
38 #include "CreateScenarioRandomize.h"
39 #include "CreateScenario.h"
44 NewRandomMapDialog::NewRandomMapDialog()
46 Glib::RefPtr<Gtk::Builder> xml
47 = Gtk::Builder::create_from_file(get_glade_path() +
48 "/new-random-map-dialog.ui");
50 xml->get_widget("dialog", dialog);
51 dialog->set_icon_from_file(File::getMiscFile("various/castle_icon.png"));
54 xml->get_widget("dialog-vbox1", dialog_vbox);
55 xml->get_widget("dialog-action_area1", dialog_action_area);
56 xml->get_widget("map_size_combobox", map_size_combobox);
57 xml->get_widget("random_map_container", random_map_container);
58 xml->get_widget("grass_scale", grass_scale);
59 xml->get_widget("water_scale", water_scale);
60 xml->get_widget("swamp_scale", swamp_scale);
61 xml->get_widget("forest_scale", forest_scale);
62 xml->get_widget("hills_scale", hills_scale);
63 xml->get_widget("mountains_scale", mountains_scale);
64 xml->get_widget("cities_scale", cities_scale);
65 xml->get_widget("ruins_scale", ruins_scale);
66 xml->get_widget("temples_scale", temples_scale);
67 xml->get_widget("signposts_scale", signposts_scale);
68 xml->get_widget("progressbar", progressbar);
69 xml->get_widget("accept2_button", accept_button);
70 accept_button->signal_clicked().connect
71 (sigc::mem_fun(*this, &NewRandomMapDialog::on_accept_clicked));
72 xml->get_widget("cancel2_button", cancel_button);
73 cancel_button->signal_clicked().connect
74 (sigc::mem_fun(*this, &NewRandomMapDialog::on_cancel_clicked));
75 xml->get_widget("grass_random_togglebutton", grass_random_togglebutton);
76 grass_random_togglebutton->signal_toggled().connect
77 (sigc::mem_fun(*this, &NewRandomMapDialog::on_grass_random_toggled));
78 xml->get_widget("water_random_togglebutton", water_random_togglebutton);
79 water_random_togglebutton->signal_toggled().connect
80 (sigc::mem_fun(*this, &NewRandomMapDialog::on_water_random_toggled));
81 xml->get_widget("swamp_random_togglebutton", swamp_random_togglebutton);
82 swamp_random_togglebutton->signal_toggled().connect
83 (sigc::mem_fun(*this, &NewRandomMapDialog::on_swamp_random_toggled));
84 xml->get_widget("forest_random_togglebutton", forest_random_togglebutton);
85 forest_random_togglebutton->signal_toggled().connect
86 (sigc::mem_fun(*this, &NewRandomMapDialog::on_forest_random_toggled));
87 xml->get_widget("hills_random_togglebutton", hills_random_togglebutton);
88 hills_random_togglebutton->signal_toggled().connect
89 (sigc::mem_fun(*this, &NewRandomMapDialog::on_hills_random_toggled));
90 xml->get_widget("mountains_random_togglebutton", mountains_random_togglebutton);
91 mountains_random_togglebutton->signal_toggled().connect
92 (sigc::mem_fun(*this, &NewRandomMapDialog::on_mountains_random_toggled));
93 xml->get_widget("cities_random_togglebutton", cities_random_togglebutton);
94 cities_random_togglebutton->signal_toggled().connect
95 (sigc::mem_fun(*this, &NewRandomMapDialog::on_cities_random_toggled));
97 // fill in tile themes combobox
100 guint32 default_id = 0;
103 //fill in tile sizes combobox
104 tile_size_combobox = manage(new Gtk::ComboBoxText);
105 std::list<guint32> sizes;
106 Tilesetlist::getInstance()->getSizes(sizes);
107 Citysetlist::getInstance()->getSizes(sizes);
108 Armysetlist::getInstance()->getSizes(sizes);
109 for (std::list<guint32>::iterator it = sizes.begin(); it != sizes.end();
112 Glib::ustring s = String::ucompose("%1x%1", *it);
113 tile_size_combobox->append_text(s);
114 if ((*it) == Tileset::getDefaultTileSize())
115 default_id = counter;
118 tile_size_combobox->set_active(default_id);
119 xml->get_widget("tile_size_box", box);
120 box->pack_start(*tile_size_combobox, Gtk::PACK_SHRINK);
121 tile_size_combobox->signal_changed().connect
122 (sigc::mem_fun(*this, &NewRandomMapDialog::on_tile_size_changed));
124 // make new tile themes combobox
125 tile_theme_combobox = manage(new Gtk::ComboBoxText);
126 xml->get_widget("tile_theme_box", box);
127 box->pack_start(*tile_theme_combobox, Gtk::PACK_SHRINK);
129 // make new army themes combobox
130 army_theme_combobox = manage(new Gtk::ComboBoxText);
131 xml->get_widget("army_theme_box", box);
132 box->pack_start(*army_theme_combobox, Gtk::PACK_SHRINK);
134 // make new city themes combobox
135 city_theme_combobox = manage(new Gtk::ComboBoxText);
136 xml->get_widget("city_theme_box", box);
137 box->pack_start(*city_theme_combobox, Gtk::PACK_SHRINK);
141 shield_theme_combobox = manage(new Gtk::ComboBoxText);
142 Shieldsetlist *sl = Shieldsetlist::getInstance();
143 std::list<std::string> shield_themes = sl->getNames();
144 for (std::list<std::string>::iterator i = shield_themes.begin(),
145 end = shield_themes.end(); i != end; ++i)
147 if (*i == _("Default"))
148 default_id = counter;
149 shield_theme_combobox->append_text(Glib::filename_to_utf8(*i));
153 shield_theme_combobox->set_active(default_id);
155 xml->get_widget("shield_theme_box", box);
156 box->pack_start(*shield_theme_combobox, Gtk::PACK_SHRINK);
158 on_tile_size_changed();
161 map_size_combobox->set_active(MAP_SIZE_NORMAL);
162 map_size_combobox->signal_changed().connect(
163 sigc::mem_fun(*this, &NewRandomMapDialog::on_map_size_changed));
165 Gtk::Label *temples_label;
166 xml->get_widget("temples_label", temples_label);
167 temples_label->set_sensitive(false);
168 temples_scale->set_sensitive(false);
170 Gtk::Label *signposts_label;
171 xml->get_widget("signposts_label", signposts_label);
172 signposts_label->set_sensitive(false);
173 signposts_scale->set_sensitive(false);
175 Gtk::Label *ruins_label;
176 xml->get_widget("ruins_label", ruins_label);
177 ruins_label->set_sensitive(false);
178 ruins_scale->set_sensitive(false);
180 xml->get_widget("cities_can_produce_allies_checkbutton",
181 cities_can_produce_allies_checkbutton);
182 grass_scale->set_value(78);
183 water_scale->set_value(7);
184 swamp_scale->set_value(2);
185 forest_scale->set_value(3);
186 hills_scale->set_value(5);
187 mountains_scale->set_value(5);
188 on_map_size_changed();
189 grass_scale->signal_value_changed().connect(sigc::mem_fun(*this, &NewRandomMapDialog::on_grass_changed));
190 dialog_response = Gtk::RESPONSE_CANCEL;
193 NewRandomMapDialog::~NewRandomMapDialog()
198 void NewRandomMapDialog::set_parent_window(Gtk::Window &parent)
200 dialog->set_transient_for(parent);
203 int NewRandomMapDialog::run()
206 dialog_action_area->hide();
208 //we're not using the buttons from the action area.
209 //we have our own buttons so that we can show a progress bar after the
212 return dialog_response;
215 void NewRandomMapDialog::on_map_size_changed()
217 switch (map_size_combobox->get_active_row_number()) {
219 map.width = MAP_SIZE_SMALL_WIDTH;
220 map.height = MAP_SIZE_SMALL_HEIGHT;
221 cities_scale->set_value(15);
222 ruins_scale->set_value(20);
223 temples_scale->set_value(4);
227 map.width = MAP_SIZE_TINY_WIDTH;
228 map.height = MAP_SIZE_TINY_HEIGHT;
229 cities_scale->set_value(10);
230 ruins_scale->set_value(15);
231 temples_scale->set_value(4);
234 case MAP_SIZE_NORMAL:
236 map.width = MAP_SIZE_NORMAL_WIDTH;
237 map.height = MAP_SIZE_NORMAL_HEIGHT;
238 cities_scale->set_value(20);
239 ruins_scale->set_value(25);
240 temples_scale->set_value(4);
244 CreateScenario::calculateNumberOfSignposts(map.width, map.height,
245 int(grass_scale->get_value()));
246 signposts_scale->set_value(num_signposts);
249 guint32 NewRandomMapDialog::get_active_tile_size()
251 return (guint32) atoi(tile_size_combobox->get_active_text().c_str());
254 void NewRandomMapDialog::on_tile_size_changed()
256 guint32 default_id = 0;
259 accept_button->set_sensitive(true);
260 tile_theme_combobox->clear_items();
261 Tilesetlist *tl = Tilesetlist::getInstance();
262 std::list<std::string> tile_themes = tl->getNames(get_active_tile_size());
263 for (std::list<std::string>::iterator i = tile_themes.begin(),
264 end = tile_themes.end(); i != end; ++i)
266 if (*i == _("Default"))
267 default_id = counter;
268 tile_theme_combobox->append_text(Glib::filename_to_utf8(*i));
273 tile_theme_combobox->set_active(default_id);
275 accept_button->set_sensitive(false);
277 army_theme_combobox->clear_items();
278 Armysetlist *al = Armysetlist::getInstance();
279 std::list<std::string> army_themes = al->getNames(get_active_tile_size());
282 for (std::list<std::string>::iterator i = army_themes.begin(),
283 end = army_themes.end(); i != end; ++i)
285 if (*i == _("Default"))
286 default_id = counter;
287 army_theme_combobox->append_text(Glib::filename_to_utf8(*i));
292 army_theme_combobox->set_active(default_id);
294 accept_button->set_sensitive(false);
296 city_theme_combobox->clear_items();
297 Citysetlist *cl = Citysetlist::getInstance();
298 std::list<std::string> city_themes = cl->getNames(get_active_tile_size());
301 for (std::list<std::string>::iterator i = city_themes.begin(),
302 end = city_themes.end(); i != end; ++i)
304 if (*i == _("Default"))
305 default_id = counter;
306 city_theme_combobox->append_text(Glib::filename_to_utf8(*i));
311 city_theme_combobox->set_active(default_id);
313 accept_button->set_sensitive(false);
316 GameParameters NewRandomMapDialog::getParams()
318 CreateScenarioRandomize random;
320 GameParameters::Player p;
321 p.type = GameParameters::Player::HUMAN;
323 p.name = random.getPlayerName(Shield::WHITE);
324 p.id = int(Shield::WHITE);
325 g.players.push_back(p);
326 p.id = int(Shield::GREEN);
327 p.name = random.getPlayerName(Shield::Colour(p.id));
328 g.players.push_back(p);
329 p.id = int(Shield::YELLOW);
330 p.name = random.getPlayerName(Shield::Colour(p.id));
331 g.players.push_back(p);
332 p.id = int(Shield::LIGHT_BLUE);
333 p.name = random.getPlayerName(Shield::Colour(p.id));
334 g.players.push_back(p);
335 p.id = int(Shield::ORANGE);
336 p.name = random.getPlayerName(Shield::Colour(p.id));
337 g.players.push_back(p);
338 p.id = int(Shield::DARK_BLUE);
339 p.name = random.getPlayerName(Shield::Colour(p.id));
340 g.players.push_back(p);
341 p.id = int(Shield::RED);
342 p.name = random.getPlayerName(Shield::Colour(p.id));
343 g.players.push_back(p);
344 p.id = int(Shield::BLACK);
345 p.name = random.getPlayerName(Shield::Colour(p.id));
346 g.players.push_back(p);
349 switch (map_size_combobox->get_active_row_number()) {
351 g.map.width = MAP_SIZE_SMALL_WIDTH;
352 g.map.height = MAP_SIZE_SMALL_HEIGHT;
353 g.map.ruins = int(ruins_scale->get_value());
354 g.map.temples = int(temples_scale->get_value());
355 g.map.signposts = int(signposts_scale->get_value());
359 g.map.width = MAP_SIZE_TINY_WIDTH;
360 g.map.height = MAP_SIZE_TINY_HEIGHT;
361 g.map.ruins = int(ruins_scale->get_value());
362 g.map.temples = int(temples_scale->get_value());
363 g.map.signposts = int(signposts_scale->get_value());
366 case MAP_SIZE_NORMAL:
368 g.map.width = MAP_SIZE_NORMAL_WIDTH;
369 g.map.height = MAP_SIZE_NORMAL_HEIGHT;
370 g.map.ruins = int(ruins_scale->get_value());
371 g.map.temples = int(temples_scale->get_value());
372 g.map.signposts = int(signposts_scale->get_value());
376 if (grass_random_togglebutton->get_active())
378 int(grass_scale->get_adjustment()->get_lower()) +
379 (rand() % (int(grass_scale->get_adjustment()->get_upper()) -
380 int(grass_scale->get_adjustment()->get_lower()) + 1));
382 g.map.grass = int(grass_scale->get_value());
384 if (water_random_togglebutton->get_active())
386 int(water_scale->get_adjustment()->get_lower()) +
387 (rand() % (int(water_scale->get_adjustment()->get_upper()) -
388 int(water_scale->get_adjustment()->get_lower()) + 1));
390 g.map.water = int(water_scale->get_value());
392 if (swamp_random_togglebutton->get_active())
394 int(swamp_scale->get_adjustment()->get_lower()) +
395 (rand() % (int(swamp_scale->get_adjustment()->get_upper()) -
396 int(swamp_scale->get_adjustment()->get_lower()) + 1));
398 g.map.swamp = int(swamp_scale->get_value());
400 if (forest_random_togglebutton->get_active())
402 int(forest_scale->get_adjustment()->get_lower()) +
403 (rand() % (int(forest_scale->get_adjustment()->get_upper()) -
404 int(forest_scale->get_adjustment()->get_lower()) + 1));
406 g.map.forest = int(forest_scale->get_value());
408 if (hills_random_togglebutton->get_active())
410 int(hills_scale->get_adjustment()->get_lower()) +
411 (rand() % (int(hills_scale->get_adjustment()->get_upper()) -
412 int(hills_scale->get_adjustment()->get_lower()) + 1));
414 g.map.hills = int(hills_scale->get_value());
416 if (mountains_random_togglebutton->get_active())
418 int(mountains_scale->get_adjustment()->get_lower()) +
419 (rand() % (int(mountains_scale->get_adjustment()->get_upper()) -
420 int(mountains_scale->get_adjustment()->get_lower())
423 g.map.mountains = int(mountains_scale->get_value());
425 if (cities_random_togglebutton->get_active())
427 int(cities_scale->get_adjustment()->get_lower()) +
428 (rand() % (int(cities_scale->get_adjustment()->get_upper()) -
429 int(cities_scale->get_adjustment()->get_lower()) + 1));
431 g.map.cities = int(cities_scale->get_value());
433 Tilesetlist *tl = Tilesetlist::getInstance();
434 Armysetlist *al = Armysetlist::getInstance();
435 Shieldsetlist *sl = Shieldsetlist::getInstance();
436 Citysetlist *cl = Citysetlist::getInstance();
437 g.tile_theme = tl->getTilesetDir
438 (Glib::filename_from_utf8(tile_theme_combobox->get_active_text()),
439 get_active_tile_size());
441 g.army_theme = al->getArmysetDir
442 (Glib::filename_from_utf8(army_theme_combobox->get_active_text()),
443 get_active_tile_size());
445 g.shield_theme = sl->getShieldsetDir
446 (Glib::filename_from_utf8(shield_theme_combobox->get_active_text()));
448 g.city_theme = cl->getCitysetDir
449 (Glib::filename_from_utf8(city_theme_combobox->get_active_text()),
450 get_active_tile_size());
452 g.process_armies = GameParameters::PROCESS_ARMIES_AT_PLAYERS_TURN;
454 g.see_opponents_stacks = GameScenarioOptions::s_see_opponents_stacks;
455 g.see_opponents_production = GameScenarioOptions::s_see_opponents_production;
456 g.play_with_quests = GameScenarioOptions::s_play_with_quests;
457 g.hidden_map = GameScenarioOptions::s_hidden_map;
458 g.neutral_cities = GameScenarioOptions::s_neutral_cities;
459 g.razing_cities = GameScenarioOptions::s_razing_cities;
460 g.diplomacy = GameScenarioOptions::s_diplomacy;
461 g.random_turns = GameScenarioOptions::s_random_turns;
462 g.quick_start = Configuration::s_quick_start;
463 g.intense_combat = GameScenarioOptions::s_intense_combat;
464 g.military_advisor = GameScenarioOptions::s_military_advisor;
465 g.cities_can_produce_allies =
466 cities_can_produce_allies_checkbutton->get_active();
468 g.name = _("Autogenerated");
472 void NewRandomMapDialog::on_grass_random_toggled()
474 grass_scale->set_sensitive(!grass_random_togglebutton->get_active());
477 void NewRandomMapDialog::on_water_random_toggled()
479 water_scale->set_sensitive(!water_random_togglebutton->get_active());
482 void NewRandomMapDialog::on_swamp_random_toggled()
484 swamp_scale->set_sensitive(!swamp_random_togglebutton->get_active());
487 void NewRandomMapDialog::on_forest_random_toggled()
489 forest_scale->set_sensitive(!forest_random_togglebutton->get_active());
492 void NewRandomMapDialog::on_hills_random_toggled()
494 hills_scale->set_sensitive(!hills_random_togglebutton->get_active());
497 void NewRandomMapDialog::on_mountains_random_toggled()
499 mountains_scale->set_sensitive(!mountains_random_togglebutton->get_active());
502 void NewRandomMapDialog::on_cities_random_toggled()
504 cities_scale->set_sensitive(!cities_random_togglebutton->get_active());
507 std::string NewRandomMapDialog::create_and_dump_scenario(const std::string &file,
508 const GameParameters &g, sigc::slot<void> *pulse)
510 CreateScenario creator (g.map.width, g.map.height);
512 // then fill the other players
514 int army_id = Armysetlist::getInstance()->getArmyset(g.army_theme)->getId();
515 Shieldsetlist *ssl = Shieldsetlist::getInstance();
516 guint32 id = ssl->getShieldset(g.shield_theme)->getId();
517 for (std::vector<GameParameters::Player>::const_iterator
518 i = g.players.begin(), end = g.players.end();
519 i != end; ++i, ++c) {
521 if (i->type == GameParameters::Player::OFF)
523 fl_counter->getNextId();
528 if (i->type == GameParameters::Player::EASY)
529 type = Player::AI_FAST;
530 else if (i->type == GameParameters::Player::HARD)
531 type = Player::AI_SMART;
533 type = Player::HUMAN;
535 creator.addPlayer(i->name, army_id, ssl->getColor(id, c), type);
539 CreateScenarioRandomize random;
540 // the neutral player must come last so it has the highest id among players
541 creator.addNeutral(random.getPlayerName(Shield::NEUTRAL), army_id,
542 ssl->getColor(id, MAX_PLAYERS), Player::AI_DUMMY);
544 // now fill in some map information
545 creator.setMapTiles(g.tile_theme);
546 creator.setShieldset(g.shield_theme);
547 creator.setCityset(g.city_theme);
548 creator.setNoCities(g.map.cities);
549 creator.setNoRuins(g.map.ruins);
550 creator.setNoTemples(g.map.temples);
551 int num_signposts = g.map.signposts;
552 if (num_signposts == -1)
553 num_signposts = CreateScenario::calculateNumberOfSignposts(g.map.width,
556 creator.setNoSignposts(num_signposts);
558 // terrain: the scenario generator also accepts input with a sum of
559 // more than 100%, so the thing is rather easy here
560 creator.setPercentages(g.map.grass, g.map.water, g.map.forest, g.map.swamp,
561 g.map.hills, g.map.mountains);
563 // and tell it the turn mode
564 if (g.process_armies == GameParameters::PROCESS_ARMIES_AT_PLAYERS_TURN)
565 creator.setTurnmode(true);
567 creator.setTurnmode(false);
569 // now create the map and dump the created map
570 std::string path = File::getSavePath();
574 //creator.progress.connect(sigc::mem_fun(this, &NewRandomMapDialog::pulse));
575 creator.progress.connect(*pulse);
582 void NewRandomMapDialog::on_accept_clicked()
584 dialog_vbox->set_sensitive(false);
585 progressbar->show_all();
586 progressbar->pulse();
587 while (g_main_context_iteration(NULL, FALSE)); //doEvents
589 switch (map_size_combobox->get_active_row_number()) {
591 map.width = MAP_SIZE_SMALL_WIDTH;
592 map.height = MAP_SIZE_SMALL_HEIGHT;
596 map.width = MAP_SIZE_TINY_WIDTH;
597 map.height = MAP_SIZE_TINY_HEIGHT;
600 case MAP_SIZE_NORMAL:
602 map.width = MAP_SIZE_NORMAL_WIDTH;
603 map.height = MAP_SIZE_NORMAL_HEIGHT;
607 map.tileset = Tilesetlist::getInstance()->getTilesetDir
608 (Glib::filename_from_utf8(tile_theme_combobox->get_active_text()),
609 get_active_tile_size());
611 map.shieldset = Shieldsetlist::getInstance()->getShieldsetDir
612 (Glib::filename_from_utf8(shield_theme_combobox->get_active_text()));
614 map.cityset = Citysetlist::getInstance()->getCitysetDir
615 (Glib::filename_from_utf8(city_theme_combobox->get_active_text()),
616 get_active_tile_size());
618 map.armyset = Armysetlist::getInstance()->getArmysetDir
619 (Glib::filename_from_utf8(army_theme_combobox->get_active_text()),
620 get_active_tile_size());
622 map.grass = int(grass_scale->get_value());
623 map.water = int(water_scale->get_value());
624 map.swamp = int(swamp_scale->get_value());
625 map.forest = int(forest_scale->get_value());
626 map.hills = int(hills_scale->get_value());
627 map.mountains = int(mountains_scale->get_value());
628 map.cities = int(cities_scale->get_value());
629 map.ruins = int(ruins_scale->get_value());
630 map.temples = int(temples_scale->get_value());
631 map.signposts = int(signposts_scale->get_value());
633 GameParameters g = getParams();
634 progressbar->pulse();
635 while (g_main_context_iteration(NULL, FALSE)); //doEvents
637 //creator.progress.connect(sigc::mem_fun(this, &NewRandomMapDialog::pulse));
638 sigc::slot<void> progress = sigc::mem_fun(this, &NewRandomMapDialog::pulse);
639 d_filename = create_and_dump_scenario("random.map", g, &progress);
641 dialog_response = Gtk::RESPONSE_ACCEPT;
645 void NewRandomMapDialog::on_cancel_clicked()
647 dialog_response = Gtk::RESPONSE_CANCEL;
650 void NewRandomMapDialog::pulse()
652 progressbar->pulse();
653 while (g_main_context_iteration(NULL, FALSE)); //doEvents
656 void NewRandomMapDialog::on_grass_changed()
659 CreateScenario::calculateNumberOfSignposts(map.width, map.height,
660 int(grass_scale->get_value()));
661 signposts_scale->set_value(num_signposts);