initial commit, lordsawar source, slightly modified
[lordsawar] / src / gui / game-preferences-dialog.cpp
1 //  Copyright (C) 2007 Ole Laursen
2 //  Copyright (C) 2007, 2008, 2009 Ben Asselstine
3 //
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.
8 //
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.
13 //
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 
17 //  02110-1301, USA.
18
19 #include <config.h>
20
21 #include <assert.h>
22 #include <sigc++/functors/mem_fun.h>
23 #include <gtkmm.h>
24
25 #include "game-preferences-dialog.h"
26
27 #include "glade-helpers.h"
28 #include "image-helpers.h"
29 #include "ucompose.hpp"
30 #include "defs.h"
31 #include "File.h"
32 #include "xmlhelper.h"
33 #include "armysetlist.h"
34 #include "shieldsetlist.h"
35 #include "GameScenario.h"
36 #include "GraphicsCache.h"
37 #include "tilesetlist.h"
38 #include "citysetlist.h"
39 #include "player.h"
40
41 static bool inhibit_difficulty_combobox = false;
42
43 namespace 
44 {
45   GameParameters::Player::Type player_type_to_enum(const Glib::ustring &s)
46     {
47       if (s == HUMAN_PLAYER_TYPE)
48         return GameParameters::Player::HUMAN;
49       else if (s == EASY_PLAYER_TYPE)
50         return GameParameters::Player::EASY;
51       else if (s == NO_PLAYER_TYPE)
52         return GameParameters::Player::OFF;
53       else
54         return GameParameters::Player::HARD;
55     }
56 }
57 void GamePreferencesDialog::init(std::string filename)
58 {
59   d_filename = filename;
60   bool broken;
61     Glib::RefPtr<Gtk::Builder> xml
62         = Gtk::Builder::create_from_file(get_glade_path() + "/game-preferences-dialog.ui");
63
64     xml->get_widget("dialog", dialog);
65     decorate(dialog);
66     window_closed.connect(sigc::mem_fun(dialog, &Gtk::Dialog::hide));
67
68     xml->get_widget("dialog-vbox1", dialog_vbox);
69     xml->get_widget("start_game_button", start_game_button);
70     xml->get_widget("difficulty_label", difficulty_label);
71     xml->get_widget("difficulty_combobox", difficulty_combobox);
72
73     xml->get_widget("players_vbox", players_vbox);
74     xml->get_widget("game_name_label", game_name_label);
75     xml->get_widget("game_name_entry", game_name_entry);
76
77     difficulty_combobox->set_active(CUSTOM);
78     difficulty_combobox->signal_changed().connect(
79         sigc::mem_fun(*this, &GamePreferencesDialog::on_difficulty_changed));
80
81     start_game_button->signal_clicked().connect
82       (sigc::mem_fun(*this, &GamePreferencesDialog::on_start_game_clicked));
83
84     xml->get_widget("edit_options_button", edit_options_button);
85     edit_options_button->signal_clicked().connect(
86         sigc::mem_fun(*this, &GamePreferencesDialog::on_edit_options_clicked));
87
88   game_options_dialog = new GameOptionsDialog(false);
89   game_options_dialog->difficulty_option_changed.connect(
90         sigc::mem_fun(*this, 
91                       &GamePreferencesDialog::update_difficulty_rating));
92   GameParameters load_map_parameters;
93   load_map_parameters = GameScenario::loadGameParameters(d_filename,
94                                                          broken);
95   if (broken)
96     start_game_button->set_sensitive(false);
97
98   Shieldsetlist *ssl = Shieldsetlist::getInstance();
99   Shieldset *shieldset = ssl->getShieldset(load_map_parameters.shield_theme);
100   d_shieldset = shieldset->getId();
101   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
102     add_player(GameParameters::Player::EASY, "");
103
104   //disable all names, and types
105   std::list<Gtk::ComboBoxText*>::iterator c = player_types.begin();
106   std::list<Gtk::Entry *>::iterator e = player_names.begin();
107   for (; c != player_types.end(); c++, e++)
108     {
109       (*c)->set_sensitive(true);
110       (*c)->set_active(GameParameters::Player::OFF);
111       (*c)->set_sensitive(false);
112       (*e)->set_sensitive(false);
113     }
114   //parse load map parameters.
115
116   int f = 0;
117   int b;
118   for (std::vector<GameParameters::Player>::const_iterator
119        i = load_map_parameters.players.begin(), 
120        end = load_map_parameters.players.end(); i != end; ++i, ++f) 
121     {
122       c = player_types.begin();
123       e = player_names.begin();
124       //zip to correct combobox, entry
125       for (b = 0; b < (*i).id; b++, c++, e++) ;
126       (*c)->set_sensitive(true);
127       (*c)->set_active((*i).type);
128       (*e)->set_sensitive(true);
129       (*e)->set_text((*i).name);
130     }
131   start_game_button->property_can_focus() = true;
132   start_game_button->property_has_focus() = true;
133   start_game_button->receives_default();
134   return;
135 }
136
137 GamePreferencesDialog::GamePreferencesDialog(std::string filename, GameScenario::PlayMode play_mode)
138 {
139   mode = play_mode;
140   init(filename);
141   if (mode != GameScenario::NETWORKED)
142     {
143       delete game_name_label;
144       delete game_name_entry;
145     }
146
147 }
148
149 GamePreferencesDialog::~GamePreferencesDialog()
150 {
151   delete game_options_dialog;
152   delete dialog;
153 }
154
155 void GamePreferencesDialog::set_parent_window(Gtk::Window &parent)
156 {
157   dialog->set_transient_for(parent);
158 }
159
160 void GamePreferencesDialog::hide()
161 {
162   dialog->hide();
163 }
164
165 bool GamePreferencesDialog::run(std::string nickname)
166 {
167
168   dialog->show_all();
169   if (mode == GameScenario::NETWORKED)
170     {
171       std::string text = nickname;
172       text += "'s game";
173       game_name_entry->set_text(text);
174     }
175   update_shields();
176   on_player_type_changed();
177   int response = dialog->run();
178   if (response == Gtk::RESPONSE_ACCEPT)
179     return true;
180   return false;
181 }
182
183 Glib::RefPtr<Gdk::Pixbuf> GamePreferencesDialog::getShieldPic(guint32 type, guint32 owner)
184 {
185   Shieldsetlist *sl = Shieldsetlist::getInstance();
186
187   ShieldStyle *sh= sl->getShield(d_shieldset, type, owner);
188   return GraphicsCache::applyMask(sh->getImage(), sh->getMask(), 
189                                   sl->getColor(d_shieldset, owner), false)->to_pixbuf();
190 }
191
192 void GamePreferencesDialog::add_player(GameParameters::Player::Type type,
193                                        const Glib::ustring &name)
194 {
195   //okay, add a new hbox, with a combo and an entry in it
196   //add it to players_vbox
197   Gtk::HBox *player_hbox = new Gtk::HBox();
198   Gtk::ComboBoxText *player_type = new Gtk::ComboBoxText();
199   player_type->append_text(HUMAN_PLAYER_TYPE);
200   player_type->append_text(EASY_PLAYER_TYPE);
201   player_type->append_text(HARD_PLAYER_TYPE);
202   player_type->append_text(NO_PLAYER_TYPE);
203   player_type->signal_changed().connect
204     (sigc::mem_fun(this, &GamePreferencesDialog::on_player_type_changed));
205   Gtk::Entry *player_name = new Gtk::Entry();
206   player_name->set_text(name);
207
208   if (type == GameParameters::Player::HUMAN)
209     player_type->set_active(0);
210   else if (type == GameParameters::Player::EASY)
211     player_type->set_active(1);
212   else if (type == GameParameters::Player::HARD)
213     player_type->set_active(2);
214   else if (type== GameParameters::Player::OFF)
215     player_type->set_active(3);
216
217   player_types.push_back(player_type);
218   player_names.push_back(player_name);
219   player_hbox->pack_start(*manage(player_name), Gtk::PACK_SHRINK, 10);
220   player_hbox->add(*manage(player_type));
221   players_vbox->add(*manage(player_hbox));
222 }
223
224 void GamePreferencesDialog::on_edit_options_clicked()
225 {
226   inhibit_difficulty_combobox = true;
227   game_options_dialog->set_parent_window(*dialog);
228   game_options_dialog->run();
229
230   update_difficulty_rating();
231   update_difficulty_combobox();
232   inhibit_difficulty_combobox = false;
233 }
234
235 void GamePreferencesDialog::update_difficulty_combobox()
236 {
237   if (is_greatest())
238     difficulty_combobox->set_active(I_AM_THE_GREATEST);
239   else if (is_advanced())
240     difficulty_combobox->set_active(ADVANCED);
241   else if (is_intermediate())
242     difficulty_combobox->set_active(INTERMEDIATE);
243   else if (is_beginner())
244     difficulty_combobox->set_active(BEGINNER);
245   else
246     difficulty_combobox->set_active(CUSTOM);
247 }
248
249 void GamePreferencesDialog::update_shields()
250 {
251   if (dialog->is_realized() == false)
252     return;
253   Shieldsetlist::getInstance()->instantiateImages();
254
255   std::vector<Gtk::Widget*> list;
256   list = players_vbox->get_children();
257   for (unsigned int i = 0; i < MAX_PLAYERS; i++)
258     {
259       Gtk::Image *player_shield = new Gtk::Image ();
260       player_shield->property_pixbuf() = getShieldPic(2, i);
261       player_shields.push_back(player_shield);
262       Gtk::HBox *player_hbox = static_cast<Gtk::HBox*>(list[i+1]);
263       player_hbox->pack_start(*manage(player_shield), Gtk::PACK_SHRINK, 10);
264       player_hbox->reorder_child(*player_shield, 0);
265       player_hbox->show_all();
266     }
267   players_vbox->show_all();
268
269 }
270
271 void GamePreferencesDialog::on_player_type_changed()
272 {
273   guint32 offcount = 0;
274   std::list<Gtk::ComboBoxText *>::iterator c = player_types.begin();
275   for (; c != player_types.end(); c++)
276     {
277       if (player_type_to_enum((*c)->get_active_text()) ==
278           GameParameters::Player::OFF)
279         offcount++;
280     }
281   if (offcount > player_types.size() - 2)
282     start_game_button->set_sensitive(false);
283   else
284     start_game_button->set_sensitive(true);
285   update_difficulty_rating();
286 }
287
288 void GamePreferencesDialog::update_difficulty_rating()
289 {
290   GameParameters g;
291   std::list<Gtk::ComboBoxText *>::iterator c = player_types.begin();
292   for (; c != player_types.end(); c++)
293     {
294       GameParameters::Player p;
295       p.type = player_type_to_enum((*c)->get_active_text());
296       g.players.push_back(p);
297     }
298
299   g.see_opponents_stacks = GameScenarioOptions::s_see_opponents_stacks;
300   g.see_opponents_production = GameScenarioOptions::s_see_opponents_production;
301   g.play_with_quests = GameScenarioOptions::s_play_with_quests;
302   g.hidden_map = GameScenarioOptions::s_hidden_map;
303   g.neutral_cities = GameScenarioOptions::s_neutral_cities;
304   g.razing_cities = GameScenarioOptions::s_razing_cities;
305   g.diplomacy = GameScenarioOptions::s_diplomacy;
306   g.cusp_of_war = GameScenarioOptions::s_cusp_of_war;
307   g.random_turns = GameScenarioOptions::s_random_turns;
308   g.quick_start = Configuration::s_quick_start;
309   g.intense_combat = GameScenarioOptions::s_intense_combat;
310   g.military_advisor = GameScenarioOptions::s_military_advisor;
311
312   int difficulty = GameScenario::calculate_difficulty_rating(g);
313   g.players.clear();
314
315   difficulty_label->set_markup(String::ucompose("<b>%1%%</b>", difficulty));
316 }
317
318 void GamePreferencesDialog::on_start_game_clicked()
319 {
320   dialog_vbox->set_sensitive(false);
321   // read out the values in the widgets
322   GameParameters g;
323
324   g.map_path = d_filename;
325
326   int id = 0;
327   std::list<Gtk::ComboBoxText*>::iterator c = player_types.begin();
328   std::list<Gtk::Entry *>::iterator e = player_names.begin();
329   for (; c != player_types.end(); c++, e++, id++)
330     {
331       GameParameters::Player p;
332       p.type = player_type_to_enum((*c)->get_active_text());
333       Glib::ustring name = (*e)->get_text();
334       p.name = name;
335       p.id = id;
336       g.players.push_back(p);
337     }
338
339   g.process_armies = GameParameters::PROCESS_ARMIES_AT_PLAYERS_TURN;
340
341   g.see_opponents_stacks = GameScenarioOptions::s_see_opponents_stacks;
342   g.see_opponents_production = GameScenarioOptions::s_see_opponents_production;
343   g.play_with_quests = GameScenarioOptions::s_play_with_quests;
344   g.hidden_map = GameScenarioOptions::s_hidden_map;
345   g.neutral_cities = GameScenarioOptions::s_neutral_cities;
346   g.razing_cities = GameScenarioOptions::s_razing_cities;
347   g.diplomacy = GameScenarioOptions::s_diplomacy;
348   g.random_turns = GameScenarioOptions::s_random_turns;
349   g.quick_start = Configuration::s_quick_start;
350   g.intense_combat = GameScenarioOptions::s_intense_combat;
351   g.military_advisor = GameScenarioOptions::s_military_advisor;
352
353   g.difficulty = GameScenario::calculate_difficulty_rating(g);
354
355   if (mode == GameScenario::NETWORKED)
356     g.name = game_name_entry->get_text();
357
358   // and call callback
359   dialog->hide();
360   game_started.emit(g);
361 }
362
363 void GamePreferencesDialog::on_difficulty_changed()
364 {
365   int type_num = 0;
366   switch (difficulty_combobox->get_active_row_number()) 
367     {
368     case BEGINNER:
369       GameScenarioOptions::s_see_opponents_stacks = true;
370       GameScenarioOptions::s_see_opponents_production = true;
371       GameScenarioOptions::s_play_with_quests = GameParameters::NO_QUESTING;
372       GameScenarioOptions::s_hidden_map = false;
373       GameScenarioOptions::s_neutral_cities = GameParameters::AVERAGE;
374       GameScenarioOptions::s_razing_cities = GameParameters::ALWAYS;
375       GameScenarioOptions::s_diplomacy = false;
376       GameScenarioOptions::s_cusp_of_war = false;
377       type_num = 1; break;
378
379     case INTERMEDIATE:
380       GameScenarioOptions::s_see_opponents_stacks = false;
381       GameScenarioOptions::s_see_opponents_production = true;
382       GameScenarioOptions::s_play_with_quests = 
383         GameParameters::ONE_QUEST_PER_PLAYER;
384       GameScenarioOptions::s_hidden_map = false;
385       GameScenarioOptions::s_neutral_cities = GameParameters::STRONG;
386       GameScenarioOptions::s_razing_cities = GameParameters::ALWAYS;
387       GameScenarioOptions::s_diplomacy = true;
388       GameScenarioOptions::s_cusp_of_war = false;
389       type_num = 1; break;
390
391     case ADVANCED:
392       GameScenarioOptions::s_see_opponents_stacks = false;
393       GameScenarioOptions::s_see_opponents_production = false;
394       GameScenarioOptions::s_play_with_quests = 
395         GameParameters::ONE_QUEST_PER_PLAYER;
396       GameScenarioOptions::s_hidden_map = true;
397       GameScenarioOptions::s_neutral_cities = GameParameters::ACTIVE;
398       GameScenarioOptions::s_razing_cities = GameParameters::ON_CAPTURE;
399       GameScenarioOptions::s_diplomacy = true;
400       GameScenarioOptions::s_cusp_of_war = false;
401       type_num = 2; break;
402
403     case I_AM_THE_GREATEST:
404       GameScenarioOptions::s_see_opponents_stacks = false;
405       GameScenarioOptions::s_see_opponents_production = false;
406       GameScenarioOptions::s_play_with_quests = 
407         GameParameters::ONE_QUEST_PER_PLAYER;
408       GameScenarioOptions::s_hidden_map = true;
409       GameScenarioOptions::s_neutral_cities = GameParameters::DEFENSIVE;
410       GameScenarioOptions::s_razing_cities = GameParameters::NEVER;
411       GameScenarioOptions::s_diplomacy = true;
412       GameScenarioOptions::s_cusp_of_war = true;
413       type_num = 2; break;
414
415     case CUSTOM:
416       break;
417     }
418
419   if (inhibit_difficulty_combobox == false)
420     {
421       if (type_num)
422         {
423           std::list<Gtk::ComboBoxText*>::iterator c = player_types.begin();
424           for (; c != player_types.end(); c++)
425             {
426               if ((*c)->get_active_row_number() != 3)
427                 (*c)->set_active (type_num);
428             }
429         }
430       update_difficulty_rating();
431     }
432 }
433
434 bool GamePreferencesDialog::is_beginner()
435 {
436   return (GameScenarioOptions::s_see_opponents_stacks == true &&
437           GameScenarioOptions::s_see_opponents_production == true &&
438           GameScenarioOptions::s_play_with_quests == 
439           GameParameters::NO_QUESTING &&
440           GameScenarioOptions::s_hidden_map == false &&
441           GameScenarioOptions::s_neutral_cities == GameParameters::AVERAGE &&
442           GameScenarioOptions::s_razing_cities == GameParameters::ALWAYS &&
443           GameScenarioOptions::s_diplomacy == false &&
444           GameScenarioOptions::s_cusp_of_war == false);
445 }
446
447 bool GamePreferencesDialog::is_intermediate()
448 {
449   return (GameScenarioOptions::s_see_opponents_stacks == false &&
450           GameScenarioOptions::s_see_opponents_production == true &&
451           GameScenarioOptions::s_play_with_quests == 
452           GameParameters::ONE_QUEST_PER_PLAYER &&
453           GameScenarioOptions::s_hidden_map == false &&
454           GameScenarioOptions::s_neutral_cities == GameParameters::STRONG &&
455           GameScenarioOptions::s_razing_cities == GameParameters::ALWAYS &&
456           GameScenarioOptions::s_diplomacy == true &&
457           GameScenarioOptions::s_cusp_of_war == false);
458 }
459
460 bool GamePreferencesDialog::is_advanced()
461 {
462   return (GameScenarioOptions::s_see_opponents_stacks == false &&
463           GameScenarioOptions::s_see_opponents_production == false &&
464           GameScenarioOptions::s_play_with_quests == 
465           GameParameters::ONE_QUEST_PER_PLAYER &&
466           GameScenarioOptions::s_hidden_map == true &&
467           GameScenarioOptions::s_neutral_cities == GameParameters::ACTIVE &&
468           GameScenarioOptions::s_razing_cities == GameParameters::ON_CAPTURE &&
469           GameScenarioOptions::s_diplomacy == true &&
470           GameScenarioOptions::s_cusp_of_war == false);
471 }
472
473 bool GamePreferencesDialog::is_greatest()
474 {
475   return (GameScenarioOptions::s_see_opponents_stacks == false &&
476           GameScenarioOptions::s_see_opponents_production == false &&
477           GameScenarioOptions::s_play_with_quests == 
478           GameParameters::ONE_QUEST_PER_PLAYER &&
479           GameScenarioOptions::s_hidden_map == true &&
480           GameScenarioOptions::s_neutral_cities == GameParameters::ACTIVE &&
481           GameScenarioOptions::s_razing_cities == GameParameters::NEVER &&
482           GameScenarioOptions::s_diplomacy == true &&
483           GameScenarioOptions::s_cusp_of_war == true);
484 }
485
486 void GamePreferencesDialog::set_title(std::string text)
487 {
488   Decorated::set_title(text);
489 }