/********************************************************************** * * FreeDoko a Doppelkopf-Game * * Copyright (C) 2001-2007 by Diether Knof and Borg Enders * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You can find this license in the file 'gpl.txt'. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * Contact: * Diether Knof dknof@gmx.de * Borg Enders borg@borgsoft.de * *********************************************************************/ #include "constants.h" #ifdef USE_UI_GTKMM #include "game_debug.h" #include "ui.h" #include "translations.h" #include "cards.h" #include "widgets/stock_button.h" #include "../../card/trick.h" #include "../../player/ai/ai.h" #include "../ui.wrap.h" #include "../../utils/string.h" #include #include #include #include #include #include #include #include #include namespace UI_GTKMM_NS { /** ** ** Constructor ** ** @param parent the parent widget ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.8 ** **/ GameDebug::GameDebug(Base* const parent) : Base(parent), StickyDialog("Game info", false), OS(), seed(NULL), gametype(NULL), soloplayer(NULL), player_info_model(), player_info_list(NULL), player_info_treeview(NULL), player_info_rows(), team_info_model(), team_info_list(NULL), team_info_treeview(NULL), team_info_rows(), tricks_model(), tricks_store(NULL), tricks_treeview(NULL), tricks_rows(), ai_test_rows() { this->ui->add_window(*this); #ifndef RELEASE dynamic_cast(::ui)->append(this); this->init(); this->set_default_size(static_cast(8 * this->ui->cards->height()), static_cast(5 * this->ui->cards->height())); #endif return ; } // GameDebug::GameDebug(Base* parent) /** ** ** Destruktor ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.8 ** **/ GameDebug::~GameDebug() { dynamic_cast(::ui)->remove(this); return ; } // GameDebug::~GameDebug() /** ** ** the game is opened ** ** @param game game that is opened ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ void GameDebug::game_open(Game const& game) { this->OS::game_open(game); this->tricks_rows.clear(); this->tricks_store->clear(); while (!this->ai_test_rows.empty()) this->ai_test_rows.pop(); for (vector::const_iterator p = game.players_begin(); p != game.players_end(); ++p) this->name_changed(**p); return ; } // void GameDebug::game_open(Game const& game) /** ** ** the game is redistributed ** ** @param - ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ void GameDebug::game_redistribute() { return ; } // void GameDebug::game_redistribute() /** ** ** the game is started ** ** @param - ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof **/ void GameDebug::game_start() { this->update_info(); return ; } // void GameDebug::game_start() /** ** ** a new trick has opened ** ** @param trick new trick ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ void GameDebug::trick_open(::Trick const& trick) { this->OS::trick_open(trick); if (!this->tricks_rows.empty()) this->tricks_treeview->collapse_row(this->tricks_store->get_path(this->tricks_rows.back())); this->tricks_rows.push_back(*this->tricks_store->append()); this->tricks_rows.back()[this->tricks_model.trickno] = DK::Utils::String::to_string(trick.no()); return ; } // void GameDebug::trick_open(Trick trick) /** ** ** 'player' has played 'card' ** ** @param card the played card ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ void GameDebug::card_played(HandCard const& card) { Player const& player = card.player(); Gtk::TreeModel::Row row; if (this->ai_test_rows.empty()) row = *this->tricks_store->append(this->tricks_rows.back().children()); else { row = this->ai_test_rows.top(); this->tricks_treeview->collapse_row(this->tricks_store->get_path(row)); this->ai_test_rows.pop(); while (!this->ai_test_rows.empty()) this->ai_test_rows.pop(); } this->tricks_treeview->expand_row(this->tricks_store->get_path(row.parent()), false); row[this->tricks_model.playerno] = DK::Utils::String::to_string(player.no()); // ToDo: translation in game row[this->tricks_model.card] = ::translation(card).translation(); // ToDo: translation in game if (dynamic_cast(&player)) { if (dynamic_cast(player).lastHeuristic_ == Aiconfig::CHOOSE_BEST_CARD) row[this->tricks_model.heuristic] = ::translation(dynamic_cast(player).aitype()).translation(); else row[this->tricks_model.heuristic] = ::translation(dynamic_cast(player).lastHeuristic_).translation(); } this->update_info(); return ; } // void GameDebug::card_played(HandCard card) /** ** ** the ai tests the card 'card' ** ** @param card the card that is tested ** @param playerno number of the player who plays the card ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** ** @todo translate card automatic ** **/ void GameDebug::ai_test_card(Card const& card, unsigned const playerno) { if (this->ai_test_rows.empty()) { this->ai_test_rows.push(*this->tricks_store->append(this->tricks_rows.back().children())); this->ai_test_rows.top()[this->tricks_model.heuristic] = ::translation(dynamic_cast(this->ui->game().player_current()).aitype()).translation(); } this->ai_test_rows.push(*this->tricks_store->append(this->ai_test_rows.top().children())); if (this->ai_test_rows.size() == 2) this->tricks_treeview->expand_to_path(this->tricks_store->get_path(this->ai_test_rows.top().parent())); this->ai_test_rows.top()[this->tricks_model.card] = ::translation(card).translation(); this->ai_test_rows.top()[this->tricks_model.playerno] = DK::Utils::String::to_string(playerno); return ; } // void GameDebug::ai_test_card(Card card, unsigned playerno) /** ** ** the ai has calculated a weighting for the tested card ** ** @param weighting the weighting for the tested card ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ void GameDebug::ai_card_weighting(int const weighting) { if (this->ai_test_rows.empty()) DEBUG_ASSERTION(false, "GameDebug::ai_card_weighting():\n" " ai_test_rows is empty"); while (this->ai_test_rows.top()[this->tricks_model.isvirtual]) this->ai_test_rows.pop(); if ( (weighting == INT_MIN) || (weighting == INT_MAX) ) this->ai_test_rows.top()[this->tricks_model.heuristic] = "-"; else this->ai_test_rows.top()[this->tricks_model.heuristic] = DK::Utils::String::to_string(weighting); this->ai_test_rows.top()[this->tricks_model.isvirtual] = false; this->tricks_treeview->collapse_row(this->tricks_store->get_path(this->ai_test_rows.top())); this->ai_test_rows.pop(); return ; } // void GameDebug::ai_card_weighting(int weighting) /** ** ** virtual game: card is played ** ** @param card the card that is played ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** ** @todo translate card automatic ** **/ void GameDebug::virtual_card_played(HandCard const& card) { ::Player const& player = card.player(); this->ai_test_rows.push(*this->tricks_store->append(this->ai_test_rows.top().children())); Gtk::TreeModel::Row row = this->ai_test_rows.top(); row[this->tricks_model.card] = ::translation(card).translation(); row[this->tricks_model.playerno] = DK::Utils::String::to_string(player.no()); if (dynamic_cast(&player)) { if (dynamic_cast(player).lastHeuristic_ == Aiconfig::CHOOSE_BEST_CARD) row[this->tricks_model.heuristic] = ::translation(dynamic_cast(player).aitype()).translation(); else row[this->tricks_model.heuristic] = ::translation(dynamic_cast(player).lastHeuristic_).translation(); } row[this->tricks_model.isvirtual] = true; return ; } // void GameDebug::virtual_card_played(HandCard card) /** ** ** the announcement 'announcement' has been made by player 'player' ** ** @param announcement the announcement ** @param player the player, who has made the announcement ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ void GameDebug::announcement_made(Announcement const& announcement, Player const& player) { this->update_info(); return ; } // void GameDebug::announcement_made(Announcement announcement, Player player) /** ** ** the player has swines ** ** @param player the player with the swines ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ void GameDebug::swines_announced(Player const& player) { this->update_info(); return ; } // void GameDebug::swines_announced(Player player) /** ** ** the player has hyperswines ** ** @param player the player with the swines ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ void GameDebug::hyperswines_announced(Player const& player) { this->update_info(); return ; } // void GameDebug::hyperswines_announced(Player player) /** ** ** marriage: Information of the new team ** ** @param bridegroom the player with the marriage ** @param bride the bride ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ void GameDebug::marriage(Player const& bridegroom, Player const& bride) { this->update_info(); return ; } // void GameDebug::marriage(Player bridegroom, Player bride) /** ** genscher: Information of the new team ** ** @param genscher genscher player ** @param partner partner of the genscher player ** ** @return - ** ** @version 0.6.8 ** ** @author Diether Knof ** **/ void GameDebug::genscher(Player const& genscher, Player const& partner) { this->update_info(); return ; } // void GameDebug::genscher(Player genscher, Player partner) /** ** ** create all subelements ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.8 ** **/ void GameDebug::init() { this->ui->translations->add(*this, ::translation("~game information")); this->set_icon(this->ui->icon); { // action area Gtk::StockButton* close_button = Gtk::manage(new Gtk::StockButton(Gtk::Stock::CLOSE, "close")); this->ui->translations->add(*close_button, ::translation("close")); this->add_action_widget(*close_button, Gtk::RESPONSE_CLOSE); close_button->grab_default(); close_button->signal_clicked().connect(sigc::mem_fun(*this, &Gtk::Widget::hide)); } // action area { // content Gtk::Box* content_box = Gtk::manage(new Gtk::HBox(false, 2 em)); this->get_vbox()->add(*content_box); Gtk::Box* left_box = Gtk::manage(new Gtk::VBox(false, 1 ex)); content_box->pack_start(*left_box, false, false); { // game info Gtk::Box* box = Gtk::manage(new Gtk::VBox(true, 1 ex)); box->set_border_width(1 em); { // seed Gtk::Box* box2 = Gtk::manage(new Gtk::HBox(false, 0)); Gtk::Label* label = Gtk::manage(new Gtk::Label("Seed: ")); this->ui->translations->add(*label, ::translation("game seed") + ": "); box2->pack_start(*label, false, false); this->seed = Gtk::manage(new Gtk::Label("")); box2->pack_start(*this->seed, false, false); box->add(*box2); } // seed { // game type Gtk::Box* box2 = Gtk::manage(new Gtk::HBox(false, 0)); Gtk::Label* label = Gtk::manage(new Gtk::Label("gametype: ")); this->ui->translations->add(*label, ::translation("gametype") + ": "); box2->pack_start(*label, false, false); this->gametype = Gtk::manage(new Gtk::Label("")); box2->pack_start(*this->gametype, false, false); box->add(*box2); } // game type { // soloplayer Gtk::Box* box2 = Gtk::manage(new Gtk::HBox(false, 0)); Gtk::Label* label = Gtk::manage(new Gtk::Label("soloplayer: ")); this->ui->translations->add(*label, ::translation("soloplayer") + ": "); box2->pack_start(*label, false, false); this->soloplayer = Gtk::manage(new Gtk::Label("")); box2->pack_start(*this->soloplayer, false, false); box->add(*box2); } // seed Gtk::Frame* frame = Gtk::manage(new Gtk::Frame("game info")); this->ui->translations->add(*dynamic_cast(frame->get_label_widget()), ::translation("game info")); frame->add(*box); frame->set_border_width(1 em); Gtk::Alignment* alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 0, 0)); alignment->add(*frame); left_box->pack_start(*alignment, false, true); } // game info { // player_info this->player_info_list = Gtk::ListStore::create(this->player_info_model); this->player_info_treeview = Gtk::manage(new Gtk::TreeView(this->player_info_list)); this->player_info_treeview->get_selection()->set_mode(Gtk::SELECTION_NONE); unsigned column = 0; this->player_info_treeview->append_column("~name", this->player_info_model.name); column += 1; this->player_info_treeview->append_column("~team", this->player_info_model.team); this->player_info_treeview->get_column_cell_renderer(column)->property_xalign() = 0.5; column += 1; this->player_info_treeview->append_column("~swines", this->player_info_model.swines); this->player_info_treeview->get_column_cell_renderer(column)->property_xalign() = 0.5; column += 1; this->player_info_treeview->append_column("~announcement", this->player_info_model.announcement); this->player_info_treeview->get_column_cell_renderer(column)->property_xalign() = 0.5; column += 1; this->player_info_treeview->append_column("~points", this->player_info_model.points); this->player_info_treeview->get_column_cell_renderer(column)->property_xalign() = 0.5; column += 1; this->player_info_treeview->append_column("~tricks", this->player_info_model.tricks); this->player_info_treeview->get_column_cell_renderer(column)->property_xalign() = 0.5; column += 1; for (unsigned p = 0; p < ::party.rule()(Rule::NUMBER_OF_PLAYERS_IN_GAME); ++p) { this->player_info_rows.push_back(*this->player_info_list->append()); this->player_info_rows.back()[this->player_info_model.name] = ::party.player(p).name(); } Gtk::Alignment* a = Gtk::manage(new Gtk::Alignment); a->set_border_width(1 em); a->add(*this->player_info_treeview); Gtk::Frame* frame = Gtk::manage(new Gtk::Frame("player info")); this->ui->translations->add(*dynamic_cast(frame->get_label_widget()), ::translation("player info")); frame->add(*a); frame->set_border_width(1 em); Gtk::Alignment* alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 0, 0)); alignment->add(*frame); left_box->pack_start(*alignment, false, true); } // player_info { // team_info this->team_info_list = Gtk::ListStore::create(this->team_info_model); this->team_info_treeview = Gtk::manage(new Gtk::TreeView(this->team_info_list)); this->team_info_treeview->get_selection()->set_mode(Gtk::SELECTION_NONE); unsigned column = 0; this->team_info_treeview->append_column("~name", this->team_info_model.name); column += 1; for (unsigned p = 0; p < this->team_info_model.known_team.size(); ++p) { this->team_info_treeview->append_column(::party.player(p).name(), this->team_info_model.known_team[p]); this->team_info_treeview->get_column_cell_renderer(column)->property_xalign() = 0.5; column += 1; } // real team this->team_info_rows.push_back(*this->team_info_list->append()); // teaminfo of the game this->team_info_rows.push_back(*this->team_info_list->append()); for (unsigned p = 0; p < this->team_info_model.known_team.size(); ++p) { this->team_info_rows.push_back(*this->team_info_list->append()); this->team_info_rows.back()[this->team_info_model.name] = ::party.player(p).name(); } // for (p) Gtk::Alignment* a = Gtk::manage(new Gtk::Alignment); a->set_border_width(1 em); a->add(*this->team_info_treeview); Gtk::Frame* frame = Gtk::manage(new Gtk::Frame("team info")); this->ui->translations->add(*dynamic_cast(frame->get_label_widget()), ::translation("team info")); frame->add(*a); frame->set_border_width(1 em); Gtk::Alignment* alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 0, 0)); alignment->add(*frame); left_box->pack_start(*alignment, false, true); } // team_info { // tricks this->tricks_store = Gtk::TreeStore::create(this->tricks_model); this->tricks_treeview = Gtk::manage(new Gtk::TreeView(this->tricks_store)); this->tricks_treeview->get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); this->tricks_treeview->set_rules_hint(true); unsigned column = 0; this->tricks_treeview->append_column("Card", this->tricks_model.card); column += 1; this->tricks_treeview->append_column("Player", this->tricks_model.playerno); this->tricks_treeview->get_column_cell_renderer(column)->property_xalign() = 0.5; column += 1; this->tricks_treeview->append_column("Trick", this->tricks_model.trickno); this->tricks_treeview->get_column_cell_renderer(column)->property_xalign() = 0.5; column += 1; this->tricks_treeview->append_column("heuristic", this->tricks_model.heuristic); column += 1; Gtk::ScrolledWindow* scrolled_window = Gtk::manage(new Gtk::ScrolledWindow); scrolled_window->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); scrolled_window->add(*this->tricks_treeview); scrolled_window->set_hadjustment(this->tricks_treeview->property_hadjustment()); scrolled_window->set_vadjustment(this->tricks_treeview->property_vadjustment()); Gtk::Alignment* a = Gtk::manage(new Gtk::Alignment); a->set_border_width(1 em); a->add(*scrolled_window); Gtk::Frame* frame = Gtk::manage(new Gtk::Frame("tricks")); this->ui->translations->add(*dynamic_cast(frame->get_label_widget()), ::translation("tricks")); frame->add(*a); frame->set_border_width(1 em); content_box->pack_end(*frame, true, true); } // tricks } // content this->show_all_children(); this->realize(); this->language_update(); return ; } // void GameDebug::init() /** ** ** updates the information for the players ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.8 ** **/ void GameDebug::update_info() { if (!(::game_status & GAMESTATUS::GAME)) return ; Game const& game = this->ui->game(); this->seed->set_label(DK::Utils::String::to_string(game.seed())); this->gametype->set_label(::translation(game.type()).translation()); if (game.exists_soloplayer()) this->soloplayer->set_label(game.soloplayer().name()); else this->soloplayer->set_label("-"); for (unsigned p = 0; p < game.playerno(); ++p) { ::Player const& player = game.player(p); { // player info Gtk::TreeModel::Row& row = this->player_info_rows[p]; row[this->player_info_model.team] = ::translation(player.team()).translation(); row[this->player_info_model.swines] = (player.has_swines() ? "S" : ""); if (player.has_hyperswines()) row[this->player_info_model.swines] = row[this->player_info_model.swines] + "H"; row[this->player_info_model.announcement] = ( (player.announcement() == ANNOUNCEMENT::NOANNOUNCEMENT) ? "" : ::translation(player.announcement()).translation() ); row[this->player_info_model.points] = player.points_in_trickpile(); row[this->player_info_model.tricks] = player.number_of_tricks(); } // player info { // team info this->team_info_rows[0][this->team_info_model.known_team[p]] = ::translation("Team::" + ::short_name(player.team())).translation(); this->team_info_rows[1][this->team_info_model.known_team[p]] = ::translation("Team::" + ::short_name(player.game().teaminfo(player))).translation(); for (unsigned q = 0; q < game.playerno(); ++q) { Player const& player2 = player.game().player(q); if (dynamic_cast(&player2)) { Ai const& ai2 = static_cast(player2); this->team_info_rows[2 + q][this->team_info_model.known_team[p]] = (::translation("Team::" + ::short_name(ai2.teaminfo(player))).translation() + " " + DK::Utils::String::to_string(ai2.team_information().team_value(player))); } else { this->team_info_rows[2 + q][this->team_info_model.known_team[p]] = ""; } } // for (q) } // team info } // for (p) return ; } // void GameDebug::update_info() /** ** the name of 'player' has changed ** ** @param player player whose name has changed ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.8 **/ void GameDebug::name_changed(Player const& player) { if (!this->is_realized()) return; if (!(::game_status & GAMESTATUS::GAME)) return ; this->team_info_treeview->get_column(1 + player.no())->set_title(player.name()); this->player_info_rows[player.no()][this->player_info_model.name] = player.name(); this->team_info_rows[2 + player.no()][this->team_info_model.name] = player.name(); return ; } // void GameDebug::name_changed(Player const& player) /** ** ** updates the translations ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.8 ** **/ void GameDebug::language_update() { if (!this->is_realized()) return; { // player info unsigned column = 0; this->player_info_treeview->get_column(column)->set_title(::translation("name").translation()); column += 1; this->player_info_treeview->get_column(column)->set_title(::translation("team").translation()); column += 1; this->player_info_treeview->get_column(column)->set_title(::translation("swines").translation()); column += 1; this->player_info_treeview->get_column(column)->set_title(::translation("announcement").translation()); column += 1; this->player_info_treeview->get_column(column)->set_title(::translation("points").translation()); column += 1; this->player_info_treeview->get_column(column)->set_title(::translation("tricks").translation()); column += 1; } // player info { // team info this->team_info_treeview->get_column(0)->set_title(::translation("~name").translation()); this->team_info_rows[0][this->team_info_model.name] = ::translation("team").translation(); this->team_info_rows[1][this->team_info_model.name] = ::translation("game").translation(); } // team info { // tricks unsigned column = 0; this->tricks_treeview->get_column(column)->set_title(::translation("card").translation()); column += 1; this->tricks_treeview->get_column(column)->set_title(::translation("player").translation()); column += 1; this->tricks_treeview->get_column(column)->set_title(::translation("trick").translation()); column += 1; this->tricks_treeview->get_column(column)->set_title(::translation("heuristic").translation()); column += 1; } // tricks this->update_info(); return ; } // void GameDebug::language_update() /** ** a key has been pressed ** ** @param key the key ** ** @return whether the key was managed ** ** @author Diether Knof ** ** @version 0.7.4 **/ bool GameDebug::on_key_press_event(GdkEventKey* key) { return this->ui->key_press(key); } // bool GameDebug::on_key_press_event(GdkEventKey* key) } // namespace UI_GTKMM_NS #endif // #ifdef USE_UI_GTKMM