29 #include <gtkmm/box.h> 30 #include <gtkmm/main.h> 31 #include <gtkmm/window.h> 32 #include <gtkmm/stock.h> 33 #include <gtkmm/uimanager.h> 34 #include <gtkmm/radioaction.h> 35 #include <gtkmm/menu.h> 36 #include <gtkmm/iconfactory.h> 48 mode_show_defendables,
49 mode_show_defended_black,
50 mode_show_defended_white,
58 gint M_arrow_begin_col;
59 gint M_arrow_begin_row;
61 gpointer M_en_passant_arrow;
67 virtual bool on_button_press(gint col, gint row, GdkEventButton
const* event);
71 void on_menu_mode_editposition(
void)
76 void on_menu_mode_editgame(
void)
81 void on_menu_mode_showcandidates(
void) { M_mode = mode_show_candidates; }
82 void on_menu_mode_showreachables(
void) { M_mode = mode_show_reachables; }
83 void on_menu_mode_showattacked(
void) { M_mode = mode_show_attacked; }
84 void on_menu_mode_showdefendables(
void) { M_mode = mode_show_defendables; }
85 void on_menu_mode_showdefended_black(
void) { M_mode = mode_show_defended_black; }
86 void on_menu_mode_showdefended_white(
void) { M_mode = mode_show_defended_white; }
87 void on_menu_mode_showmoves(
void) { M_mode = mode_show_moves; }
88 void on_menu_mode_placepieces(
void) { M_mode = mode_popup_menu; }
99 void show_reachables(
int col,
int row, mode_type mode);
100 void update_en_passant_arrow(
void);
113 void init_colors(
void);
114 ColorHandle get_color_handle(
int index, colors_t color);
117 MyChessboardWidget::MyChessboardWidget(Gtk::Window* drawable) :
cwmm::ChessPositionWidget(drawable), M_en_passant_arrow(NULL)
122 struct rgb_t { gdouble red; gdouble green; gdouble blue; };
127 result.red = (col1.red * alpha1 + col2.red * alpha2) / sqrt(alpha1 * alpha1 + alpha2 * alpha2);
128 result.green = (col1.green * alpha1 + col2.green * alpha2) / sqrt(alpha1 * alpha1 + alpha2 * alpha2);
129 result.blue = (col1.blue * alpha1 + col2.blue * alpha2) / sqrt(alpha1 * alpha1 + alpha2 * alpha2);
133 void MyChessboardWidget::init_colors(
void)
137 rgb_t rgb_red = { 1.0, 0, 0 };
138 rgb_t rgb_green = { 0, 1.0, 0 };
139 rgb_t rgb_blue = { 0, 0, 1.0 };
140 rgb_t rgb_brown = { 1.0, 0, 1.0 };
142 GdkColor dark_background;
143 GdkColor light_background;
148 rgb_t rgb_background_dark = { dark_background.red / 65535.0, dark_background.green / 65535.0, dark_background.blue / 65535.0 };
149 rgb_t rgb_background_light = { light_background.red / 65535.0, light_background.green / 65535.0, light_background.blue / 65535.0 };
155 M_colors[2 * background + dark] = 0;
156 M_colors[2 * background + light] = 0;
157 tmp = mix(rgb_background_dark, 1.0, rgb_red, alpha);
159 tmp = mix(rgb_background_light, 1.0, rgb_red, alpha);
161 tmp = mix(rgb_background_dark, 1.0, rgb_green, alpha);
163 tmp = mix(rgb_background_light, 1.0, rgb_green, alpha);
165 tmp = mix(rgb_background_dark, 1.0, rgb_blue, alpha);
167 tmp = mix(rgb_background_light, 1.0, rgb_blue, alpha);
169 tmp = mix(rgb_background_dark, 1.0, rgb_brown, alpha);
171 tmp = mix(rgb_background_light, 1.0, rgb_brown, alpha);
179 int offset = ((index & 1) == ((index >> 3) & 1)) ? dark : light;
180 return M_colors[2 * color + offset];
183 void MyChessboardWidget::show_pinning(
void)
189 std::memset(handles, 0,
sizeof(handles));
191 if (bb1.
test(index) && !bb2.
test(index))
192 handles[index()] = get_color_handle(index(), blue);
193 else if (bb2.
test(index) && !bb1.
test(index))
194 handles[index()] = get_color_handle(index(), red);
195 else if (bb1.
test(index) && bb2.
test(index))
196 handles[index()] = get_color_handle(index(), brown);
200 void MyChessboardWidget::show_reachables(
int col,
int row, mode_type mode)
204 Index index(col, row);
208 case mode_show_candidates:
210 Dout(dc::notice,
"candidates: 0x" << std::hex << bb() << std::dec <<
" " << bb);
212 case mode_show_reachables:
214 Dout(dc::notice,
"reachables: 0x" << std::hex << bb() << std::dec <<
" " << bb);
216 case mode_show_attacked:
218 Dout(dc::notice,
"attacked reachables: 0x" << std::hex << bb() << std::dec <<
" " << bb);
220 case mode_show_defendables:
222 bool battery =
false;
224 Dout(dc::notice,
"defendables: 0x" << std::hex << bb() << std::dec <<
" " << bb);
227 case mode_show_defended_black:
229 bb = get_defended()[
black].any();
230 for (
int row = 7; row >= 0; --row)
232 for (
int col = 0; col <= 7; ++col)
235 std::cout << get_defended()[
black].count(i) <<
" ";
241 case mode_show_defended_white:
243 bb = get_defended()[
white].any();
244 for (
int row = 7; row >= 0; --row)
246 for (
int col = 0; col <= 7; ++col)
249 std::cout << get_defended()[
white].count(i) <<
" ";
264 Dout(dc::notice,
"moves: 0x" << std::hex << bb() << std::dec <<
" " << bb);
268 if (mode != mode_show_defended_black && mode != mode_show_defended_white)
271 std::memset(handles, 0,
sizeof(handles));
274 handles[index()] = get_color_handle(index(), red);
276 update_en_passant_arrow();
279 void MyChessboardWidget::update_en_passant_arrow(
void)
284 if (M_en_passant_arrow_index != en_passant.
index())
287 M_en_passant_arrow = NULL;
289 if (!M_en_passant_arrow)
293 GdkColor color = { 0, 0, 65535, 65535 };
294 M_en_passant_arrow =
add_arrow(from.col(), from.row(), to.col(), to.row(), color);
295 M_en_passant_arrow_index = en_passant.
index();
298 else if (M_en_passant_arrow)
301 M_en_passant_arrow = NULL;
308 if (event->type == GDK_2BUTTON_PRESS)
310 if (event->button == 2)
318 M_arrow_begin_col = col;
319 M_arrow_begin_row = row;
322 else if (event->button == 3)
329 case mode_show_candidates:
330 case mode_show_reachables:
331 case mode_show_attacked:
332 case mode_show_defendables:
333 case mode_show_defended_black:
334 case mode_show_defended_white:
335 case mode_show_moves:
336 show_reachables(col, row, M_mode);
339 case mode_popup_menu:
346 else if (event->button == 10)
349 show_reachables(0, 0, mode_show_defended_white);
357 if (event->button == 2)
359 GdkColor color = { 0, 0, 0, 65535 };
363 if ((M_arrow_begin_col != col || M_arrow_begin_row != row)&&
366 add_arrow(M_arrow_begin_col, M_arrow_begin_row, col, row, color);
373 DoutEntering(dc::notice,
"MyChessboardWidget::moved(" <<
cwchess::ChessNotation(previous_position, move) <<
", ...)");
375 update_en_passant_arrow();
380 DoutEntering(dc::notice,
"MyChessboardWidget::illegal(" <<
cwchess::ChessNotation(*
this, move) <<
", ...)");
385 DoutEntering(dc::notice,
"MyChessboardWidget::picked_up(" <<
cwchess::ChessNotation(*
this, index) <<
", ...)");
389 show_reachables(index.
col(), index.
row(), mode_show_moves);
397 void MyChessboardWidget::dropped(gint col, gint row,
cwchess::ChessPosition const& UNUSED_ARG(chess_position))
399 DoutEntering(dc::notice,
"MyChessboardWidget::dropped(" << col <<
", " << row <<
", ...)");
407 DoutEntering(dc::notice,
"draw_hud_layer(" << cr <<
", " << sside <<
", " << hud <<
")");
408 cairo_text_extents_t extents;
409 cairo_select_font_face(cr,
"Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
410 cairo_set_font_size(cr, 20);
411 cairo_text_extents(cr,
"3",& extents);
413 for (
int col = 0; col < 8; ++col)
415 for (
int row = 0; row < 8; ++row)
417 static char const* number[] = {
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9" };
420 char const* utf8 = number[count % 10];
422 y = (7 - row) * sside + extents.height + 2;
423 cairo_move_to(cr, x, y);
425 cairo_show_text(cr, number[1]);
426 cairo_show_text(cr, utf8);
434 GtkTest(
int width,
int height);
439 MyChessboardWidget const& chessboard_widget(
void)
const {
return m_chessboard_widget; }
442 void setup_menu(
void);
446 virtual void on_menu_file_quit();
447 virtual void on_menu_file_open();
448 virtual void on_menu_file_save();
449 virtual void on_menu_file_new();
450 virtual void on_menu_file_clear();
451 virtual void on_menu_file_export();
452 virtual void on_menu_file_undo();
453 virtual void on_menu_file_flip();
454 virtual void on_menu_mode_editposition(
void)
456 m_chessboard_widget.on_menu_mode_editposition();
458 M_ModePlacePieces_action->set_active(
true);
461 virtual void on_menu_mode_editgame(
void)
463 m_chessboard_widget.on_menu_mode_editgame();
474 Glib::RefPtr<Gtk::UIManager> m_refUIManager;
475 Glib::RefPtr<Gtk::ActionGroup> m_refActionGroup;
476 Glib::RefPtr<Gtk::RadioAction> M_ModePlacePieces_action;
477 Glib::RefPtr<Gtk::RadioAction> M_ModeEditPosition_action;
479 std::stack<cwchess::ChessPosition> M_history;
484 DoutEntering(dc::notice,
"GtkTest::moved(" <<
cwchess::ChessNotation(previous_position, move) <<
", ...)");
485 M_history.push(previous_position);
488 GtkTest::GtkTest(
int width,
int height) : m_vbox(FALSE, 0), m_chessboard_widget(
this)
491 set_title(
"ChessboardWidget Test");
494 set_border_width(10);
497 set_default_size(width, height);
506 m_vbox.add(m_chessboard_widget);
512 m_chessboard_widget.signal_moved().connect(sigc::mem_fun(
this,& GtkTest::moved));
515 m_chessboard_widget.signal_moved().connect(sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::moved));
518 m_chessboard_widget.signal_illegal().connect(sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::illegal));
521 m_chessboard_widget.signal_picked_up().connect(sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::picked_up));
522 m_chessboard_widget.signal_dropped().connect(sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::dropped));
525 void GtkTest::on_menu_file_quit(
void)
530 void GtkTest::on_menu_file_save(
void)
533 file.open(
"FEN.out");
534 file << chessboard_widget().FEN() << std::endl;
538 void GtkTest::on_menu_file_undo(
void)
540 if (M_history.empty())
542 chessboard_widget().set_position(M_history.top());
546 void GtkTest::on_menu_file_new(
void)
548 chessboard_widget().initial_position();
551 void GtkTest::on_menu_file_clear(
void)
553 chessboard_widget().clear();
554 Dout(dc::notice,
"Calling M_ModeEditPosition_action->set_active(true)");
555 M_ModeEditPosition_action->set_active(
true);
558 void GtkTest::on_menu_file_flip(
void)
560 chessboard_widget().set_flip_board(!chessboard_widget().
get_flip_board());
563 void GtkTest::on_menu_file_export(
void)
566 std::cout <<
" chess_position.load_FEN(\"" << chessboard_widget().FEN() <<
"\");\n";
567 std::cout <<
" static mask_t moves1[] = {\n";
570 for (
Color color(
black); color_count < 2; ++color_count, color =
white)
572 for (
PieceIterator piece_iter = chessboard_widget().
piece_begin(color); piece_iter != chessboard_widget().piece_end(); ++piece_iter)
581 std::cout << std::hex <<
"0x" << chessboard_widget().moves(piece_iter.index())() << std::dec;
584 std::cout <<
"\n };" << std::endl;
587 void GtkTest::on_menu_file_open(
void)
590 file.open(
"FEN.out");
592 std::getline(file, fen);
594 chessboard_widget().load_FEN(fen);
597 void GtkTest::setup_menu(
void)
600 m_refActionGroup = Gtk::ActionGroup::create();
603 m_refActionGroup->add(Gtk::Action::create(
"FileMenu",
"File"));
605 m_refActionGroup->add(Gtk::Action::create(
"FileQuit", Gtk::Stock::QUIT),
606 sigc::mem_fun(*
this,& GtkTest::on_menu_file_quit));
608 m_refActionGroup->add(Gtk::Action::create(
"FileOpen", Gtk::Stock::OPEN,
"Load",
"Load position from file FEN.out"),
609 sigc::mem_fun(*
this,& GtkTest::on_menu_file_open));
611 m_refActionGroup->add(Gtk::Action::create(
"FileSave", Gtk::Stock::SAVE,
"Save",
"Save position to file FEN.out"),
612 sigc::mem_fun(*
this,& GtkTest::on_menu_file_save));
614 m_refActionGroup->add(Gtk::Action::create(
"FileConvert", Gtk::Stock::CONVERT,
"Export"),
615 sigc::mem_fun(*
this,& GtkTest::on_menu_file_export));
617 m_refActionGroup->add(Gtk::Action::create(
"FileClear", Gtk::Stock::CLEAR,
"Clear",
"Remove all pieces and switch to Mode 'Edit position'."),
618 sigc::mem_fun(*
this,& GtkTest::on_menu_file_clear));
620 m_refActionGroup->add(Gtk::Action::create(
"FileNew", Gtk::Stock::NEW,
"New",
"Set up initial position."),
621 sigc::mem_fun(*
this,& GtkTest::on_menu_file_new));
623 m_refActionGroup->add(Gtk::Action::create(
"FileUndo", Gtk::Stock::UNDO,
"Undo"),
624 sigc::mem_fun(*
this,& GtkTest::on_menu_file_undo));
626 m_refActionGroup->add(Gtk::Action::create(
"FileFlip", Gtk::Stock::REFRESH,
"Flip"),
627 sigc::mem_fun(*
this,& GtkTest::on_menu_file_flip));
630 m_refActionGroup->add(Gtk::Action::create(
"ModeMenu",
"Mode"));
631 Gtk::RadioAction::Group group_widget_mode;
632 Gtk::RadioAction::Group group_rightclick_mode;
634 M_ModeEditPosition_action = Gtk::RadioAction::create(group_widget_mode,
"ModeEditPosition",
"Edit position");
635 m_refActionGroup->add(M_ModeEditPosition_action, sigc::mem_fun(*
this,& GtkTest::on_menu_mode_editposition));
637 Glib::RefPtr<Gtk::RadioAction> ModeEditGame_action(Gtk::RadioAction::create(group_widget_mode,
"ModeEditGame",
"Edit game"));
638 m_refActionGroup->add(ModeEditGame_action, sigc::mem_fun(*
this,& GtkTest::on_menu_mode_editgame));
640 m_refActionGroup->add(Gtk::RadioAction::create(group_rightclick_mode,
"ModeShowCandidates",
"Show candidates"),
641 sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::on_menu_mode_showcandidates));
643 m_refActionGroup->add(Gtk::RadioAction::create(group_rightclick_mode,
"ModeShowReachables",
"Show reachables"),
644 sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::on_menu_mode_showreachables));
646 m_refActionGroup->add(Gtk::RadioAction::create(group_rightclick_mode,
"ModeShowAttacked",
"Show attacked"),
647 sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::on_menu_mode_showattacked));
649 m_refActionGroup->add(Gtk::RadioAction::create(group_rightclick_mode,
"ModeShowDefendables",
"Show defendables"),
650 sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::on_menu_mode_showdefendables));
652 m_refActionGroup->add(Gtk::RadioAction::create(group_rightclick_mode,
"ModeShowDefendedBlack",
"Show defended by black"),
653 sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::on_menu_mode_showdefended_black));
655 m_refActionGroup->add(Gtk::RadioAction::create(group_rightclick_mode,
"ModeShowDefendedWhite",
"Show defended by white"),
656 sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::on_menu_mode_showdefended_white));
658 Glib::RefPtr<Gtk::RadioAction> ModeShowMoves_action(Gtk::RadioAction::create(group_rightclick_mode,
"ModeShowMoves",
"Show moves"));
659 m_refActionGroup->add(ModeShowMoves_action, sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::on_menu_mode_showmoves));
661 M_ModePlacePieces_action = Gtk::RadioAction::create(group_rightclick_mode,
"ModePlacePieces",
"Place pieces");
662 m_refActionGroup->add(M_ModePlacePieces_action, sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::on_menu_mode_placepieces));
666 Dout(dc::notice,
"Calling ModeEditGame_action->set_active(true)");
667 ModeEditGame_action->set_active(
true);
668 Dout(dc::notice,
"Calling ModeShowMoves_action->set_active(true)");
669 ModeShowMoves_action->set_active(
true);
671 Dout(dc::notice,
"Calling M_ModeEditPosition_action->set_active(true)");
672 M_ModeEditPosition_action->set_active(
true);
673 Dout(dc::notice,
"Calling M_ModePlacePieces_action->set_active(true)");
674 M_ModePlacePieces_action->set_active(
true);
678 m_refUIManager = Gtk::UIManager::create();
679 m_refUIManager->insert_action_group(m_refActionGroup);
682 add_accel_group(m_refUIManager->get_accel_group());
685 Glib::ustring ui_info =
687 " <menubar name='MenuBar'>" 688 " <menu action='FileMenu'>" 689 " <menuitem action='FileOpen'/>" 690 " <menuitem action='FileSave'/>" 691 " <menuitem action='FileQuit'/>" 693 " <menu action='ModeMenu'>" 694 " <menuitem action='ModeEditPosition'/>" 695 " <menuitem action='ModeEditGame'/>" 697 " <menuitem action='ModeShowCandidates'/>" 698 " <menuitem action='ModeShowReachables'/>" 699 " <menuitem action='ModeShowAttacked'/>" 700 " <menuitem action='ModeShowDefendables'/>" 701 " <menuitem action='ModeShowDefendedBlack'/>" 702 " <menuitem action='ModeShowDefendedWhite'/>" 703 " <menuitem action='ModeShowMoves'/>" 704 " <menuitem action='ModePlacePieces'/>" 707 " <toolbar name='ToolBar'>" 708 " <toolitem action='FileQuit'/>" 709 " <toolitem action='FileOpen'/>" 710 " <toolitem action='FileSave'/>" 711 " <toolitem action='FileNew'/>" 712 " <toolitem action='FileClear'/>" 713 " <toolitem action='FileConvert'/>" 714 " <toolitem action='FileUndo'/>" 715 " <toolitem action='FileFlip'/>" 719 #ifdef GLIBMM_EXCEPTIONS_ENABLED 722 m_refUIManager->add_ui_from_string(ui_info);
724 catch(
const Glib::Error& ex)
726 std::cerr <<
"building menus failed: " << ex.what();
729 std::auto_ptr<Glib::Error> ex;
730 m_refUIManager->add_ui_from_string(ui_info, ex);
733 std::cerr <<
"building menus failed: " << ex->what();
735 #endif // GLIBMM_EXCEPTIONS_ENABLED 738 Gtk::Widget* pMenubar = m_refUIManager->get_widget(
"/MenuBar");
740 m_vbox.pack_start(*pMenubar, Gtk::PACK_SHRINK);
742 Gtk::Widget* pToolbar = m_refUIManager->get_widget(
"/ToolBar") ;
744 m_vbox.pack_start(*pToolbar, Gtk::PACK_SHRINK);
747 int main(
int argc,
char* argv[])
751 Debug(NAMESPACE_DEBUG::init());
752 Dout(dc::notice,
"Entered main()");
754 Gtk::Main kit(argc, argv);
764 chess_position.
load_FEN(
"rnbqkbnr/4p1pp/1p6/p1p1PpP1/1P1p4/2P5/P2P1P1P/RNBQKBNR w KQkq f6 0 7");
767 file.open(
"FEN.out");
769 std::getline(file, fen);
771 chess_position.load_FEN(fen);
775 chessboard_widget.set_position(chess_position);
778 uint32_t border_color_html = 0x597359;
779 GdkColor brown = { 0,
static_cast<guint16
>((border_color_html & 0xff0000) >> 8),
static_cast<guint16
>(border_color_html & 0xff00), static_cast<guint16>((border_color_html & 0xff) << 8) };
780 chessboard_widget.set_border_color(brown);
783 Gtk::Main::run(application);
IndexData const index_begin
A constant representing the& #39;first' index.
A namespace for all chess related objects that are not related to the GUI.
bool load_FEN(std::string const& FEN)
Read a FEN code.
ColorData const white
A constant representing the color white.
bool is_nothing(void) const
Returns TRUE if the code represents& #39;nothing'.
Index from_index(void) const
Return the index of the square that pawn came from.
A chess move in a particular chess position.
BitBoard candidates(Index const& index) const
Return a BitBoard with bits set for all squares that are candidates to move to.
A helper class to write other objects to an ostream.
An object representing en passant information.
A one-boolean-per-square chessboard.
The index of a chess square.
bool test() const
Test if any bit is set at all.
int col(void) const
Returns the column.
A particular piece on the board.
Index index(void) const
Return the index of the square that was passed.
Piece piece_at(Index const& index) const
Return the Piece on the square index.
Index pawn_index(void) const
Return the index of the pawn that just advanced two squares.
EnPassant const & en_passant(void) const
Return the en passant object.
PieceIterator piece_begin(Color const& color) const
Return an iterator to the first piece of color color.
int row(void) const
Returns the row.
Color color(void) const
Return the color of the piece.
BitBoard reachables(Index const& index, bool attacked_squares=false) const
Return a BitBoard with bits set for each square that a piece can reach in one move.
bool exists(void) const
Return TRUE if the last move was a pawn advancing two squares.
A color (black or white).
BitBoard defendables(Code const& code, Index const& index, bool& battery) const
Return a BitBoard with bits set for each square that a piece defends, or would defend if an exchange ...
BitBoard moves(Index const& index) const
Return a BitBoard with bits set for each square the piece at index can legally go to...
IndexData const index_end
A constant representing& #39;one past the end'.
Non-mutable iterator over selective chess pieces in a chess position.
Color to_move(void) const
Return whose turn it is.
This file contains the declaration of class ChessNotation.
Code code(void) const
The code of this piece.
ColorData const black
A constant representing the color black.