tstcpp.cc
Go to the documentation of this file.
1 // cwchessboard -- A C++ chessboard tool set for gtkmm
2 //
3 //! @file tstcpp.cc A full-blown test application used for debugging %cwchess::%ChessPosition.
4 //
5 // Copyright (C) 2008 - 2010, by
6 //
7 // Carlo Wood, Run on IRC <carlo@alinoe.com>
8 // RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt
9 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 2 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 // cwmm::ChessboardWidget usage example in C++ code.
24 //
25 
26 #include "sys.h"
27 #include <iomanip>
28 #include <gtk/gtk.h>
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>
37 #include <cstring>
38 #include <stack>
39 #include <fstream>
40 #include "ChessPositionWidget.h"
41 #include "debug.h"
42 #include "ChessNotation.h"
43 
44 enum mode_type {
45  mode_show_candidates,
46  mode_show_reachables,
47  mode_show_attacked,
48  mode_show_defendables,
49  mode_show_defended_black,
50  mode_show_defended_white,
51  mode_show_moves,
52  mode_popup_menu
53 };
54 
55 // The chessboard.
57  private:
58  gint M_arrow_begin_col;
59  gint M_arrow_begin_row;
60  ColorHandle M_colors[10];
61  gpointer M_en_passant_arrow;
62  cwchess::Index M_en_passant_arrow_index;
63  mode_type M_mode;
64 
65  protected:
66  virtual void draw_hud_layer(cairo_t* cr, gint sside, guint hud);
67  virtual bool on_button_press(gint col, gint row, GdkEventButton const* event);
68  virtual bool on_button_release(gint col, gint row, GdkEventButton const* event);
69 
70  public:
71  void on_menu_mode_editposition(void)
72  {
75  }
76  void on_menu_mode_editgame(void)
77  {
80  }
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; }
89 
90  void picked_up(cwchess::Index const& index, cwchess::ChessPosition const& chess_position);
91  void dropped(gint col, gint row, cwchess::ChessPosition const& chess_position);
92  void moved(cwchess::Move const& move, cwchess::ChessPosition const& previous_position, cwchess::ChessPosition const& current_position);
93  void illegal(cwchess::Move const& move, cwchess::ChessPosition const& chess_position);
94 
95  public:
96  MyChessboardWidget(Gtk::Window* drawable);
97 
98  private:
99  void show_reachables(int col, int row, mode_type mode);
100  void update_en_passant_arrow(void);
101  void show_pinning();
102 
103  private:
104  enum colors_t {
105  background = 0,
106  red,
107  green,
108  blue,
109  brown
110  };
111 
112  private:
113  void init_colors(void);
114  ColorHandle get_color_handle(int index, colors_t color);
115 };
116 
117 MyChessboardWidget::MyChessboardWidget(Gtk::Window* drawable) : cwmm::ChessPositionWidget(drawable), M_en_passant_arrow(NULL)
118 {
119  init_colors();
120 }
121 
122 struct rgb_t { gdouble red; gdouble green; gdouble blue; };
123 
124 rgb_t mix(rgb_t col1, gdouble alpha1, rgb_t col2, gdouble alpha2)
125 {
126  rgb_t result;
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);
130  return result;
131 }
132 
133 void MyChessboardWidget::init_colors(void)
134 {
135  gdouble alpha = 0.5;
136 
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 };
141 
142  GdkColor dark_background;
143  GdkColor light_background;
144 
145  get_dark_square_color(dark_background);
146  get_light_square_color(light_background);
147 
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 };
150 
151  rgb_t tmp;
152 
153  int const dark = 0;
154  int const light = 1;
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);
158  M_colors[2 * red + dark] = allocate_color_handle_rgb(tmp.red, tmp.green, tmp.blue);
159  tmp = mix(rgb_background_light, 1.0, rgb_red, alpha);
160  M_colors[2 * red + light] = allocate_color_handle_rgb(tmp.red, tmp.green, tmp.blue);
161  tmp = mix(rgb_background_dark, 1.0, rgb_green, alpha);
162  M_colors[2 * green + dark] = allocate_color_handle_rgb(tmp.red, tmp.green, tmp.blue);
163  tmp = mix(rgb_background_light, 1.0, rgb_green, alpha);
164  M_colors[2 * green + light] = allocate_color_handle_rgb(tmp.red, tmp.green, tmp.blue);
165  tmp = mix(rgb_background_dark, 1.0, rgb_blue, alpha);
166  M_colors[2 * blue + dark] = allocate_color_handle_rgb(tmp.red, tmp.green, tmp.blue);
167  tmp = mix(rgb_background_light, 1.0, rgb_blue, alpha);
168  M_colors[2 * blue + light] = allocate_color_handle_rgb(tmp.red, tmp.green, tmp.blue);
169  tmp = mix(rgb_background_dark, 1.0, rgb_brown, alpha);
170  M_colors[2 * brown + dark] = allocate_color_handle_rgb(tmp.red, tmp.green, tmp.blue);
171  tmp = mix(rgb_background_light, 1.0, rgb_brown, alpha);
172  M_colors[2 * brown + light] = allocate_color_handle_rgb(tmp.red, tmp.green, tmp.blue);
173 }
174 
175 MyChessboardWidget::ColorHandle MyChessboardWidget::get_color_handle(int index, colors_t color)
176 {
177  int const dark = 0;
178  int const light = 1;
179  int offset = ((index & 1) == ((index >> 3) & 1)) ? dark : light;
180  return M_colors[2 * color + offset];
181 }
182 
183 void MyChessboardWidget::show_pinning(void)
184 {
185  using namespace cwchess;
186  BitBoard bb1 = attackers(black) | attackers(white);
187  BitBoard bb2 = pinned(black) | pinned(white);
188  ColorHandle handles[64];
189  std::memset(handles, 0, sizeof(handles));
190  for (Index index = index_begin; index != index_end; ++index)
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);
197  set_background_colors(handles);
198 }
199 
200 void MyChessboardWidget::show_reachables(int col, int row, mode_type mode)
201 {
202  using namespace cwchess;
203 
204  Index index(col, row);
205  BitBoard bb;
206  switch (mode)
207  {
208  case mode_show_candidates:
209  bb = candidates(index);
210  Dout(dc::notice, "candidates: 0x" << std::hex << bb() << std::dec << " " << bb);
211  break;
212  case mode_show_reachables:
213  bb = reachables(index);
214  Dout(dc::notice, "reachables: 0x" << std::hex << bb() << std::dec << " " << bb);
215  break;
216  case mode_show_attacked:
217  bb = reachables(index, true);
218  Dout(dc::notice, "attacked reachables: 0x" << std::hex << bb() << std::dec << " " << bb);
219  break;
220  case mode_show_defendables:
221  {
222  bool battery = false;
223  bb = defendables(piece_at(index).code(), index, battery);
224  Dout(dc::notice, "defendables: 0x" << std::hex << bb() << std::dec << " " << bb);
225  break;
226  }
227  case mode_show_defended_black:
228  {
229  bb = get_defended()[black].any();
230  for (int row = 7; row >= 0; --row)
231  {
232  for (int col = 0; col <= 7; ++col)
233  {
234  Index i(col, row);
235  std::cout << get_defended()[black].count(i) << " ";
236  }
237  std::cout << '\n';
238  }
239  break;
240  }
241  case mode_show_defended_white:
242  {
243  bb = get_defended()[white].any();
244  for (int row = 7; row >= 0; --row)
245  {
246  for (int col = 0; col <= 7; ++col)
247  {
248  Index i(col, row);
249  std::cout << get_defended()[white].count(i) << " ";
250  }
251  std::cout << '\n';
252  }
253  break;
254  }
255  default:
256  {
257  cwchess::Color color(to_move());
258  cwchess::Piece piece(piece_at(col, row));
259  if (!piece.code().is_nothing())
260  to_move(piece.color());
261  bb = moves(index);
263  to_move(color);
264  Dout(dc::notice, "moves: 0x" << std::hex << bb() << std::dec << " " << bb);
265  break;
266  }
267  }
268  if (mode != mode_show_defended_black && mode != mode_show_defended_white)
270  ColorHandle handles[64];
271  std::memset(handles, 0, sizeof(handles));
272  for (Index index = index_begin; index != index_end; ++index)
273  if (bb.test(index))
274  handles[index()] = get_color_handle(index(), red);
275  set_background_colors(handles);
276  update_en_passant_arrow();
277 }
278 
279 void MyChessboardWidget::update_en_passant_arrow(void)
280 {
281  cwchess::EnPassant const& en_passant(this->en_passant());
282  if (en_passant.exists())
283  {
284  if (M_en_passant_arrow_index != en_passant.index())
285  {
286  remove_arrow(M_en_passant_arrow);
287  M_en_passant_arrow = NULL;
288  }
289  if (!M_en_passant_arrow)
290  {
291  cwchess::Index from(en_passant.from_index());
292  cwchess::Index to(en_passant.pawn_index());
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();
296  }
297  }
298  else if (M_en_passant_arrow)
299  {
300  remove_arrow(M_en_passant_arrow);
301  M_en_passant_arrow = NULL;
302  }
303 }
304 
305 bool MyChessboardWidget::on_button_press(gint col, gint row, GdkEventButton const* event)
306 {
307  // Ignore double clicks.
308  if (event->type == GDK_2BUTTON_PRESS)
309  return false;
310  if (event->button == 2)
311  {
312  // Inside board?
313  if (col != -1)
314  {
315  show_cursor();
316  // Marker the start square.
317  set_marker_color(col, row, 1);
318  M_arrow_begin_col = col;
319  M_arrow_begin_row = row;
320  }
321  }
322  else if (event->button == 3)
323  {
324  // Inside board?
325  if (col != -1)
326  {
327  switch (M_mode)
328  {
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);
337  show_cursor();
338  return true; // Don't show the popup menu.
339  case mode_popup_menu:
340  // The default of ChessPositionWidget already does this.
341  break;
342  }
343  show_cursor();
344  }
345  }
346  else if (event->button == 10)
347  {
348  enable_hud_layer(1);
349  show_reachables(0, 0, mode_show_defended_white);
350  }
351  return false;
352 }
353 
354 bool MyChessboardWidget::on_button_release(gint col, gint row, GdkEventButton const* event)
355 {
356  hide_cursor();
357  if (event->button == 2)
358  {
359  GdkColor color = { 0, 0, 0, 65535 };
360  // Clear the marker on the start square again.
361  set_marker_color(M_arrow_begin_col, M_arrow_begin_row, 0);
362  // Draw an arrow.
363  if ((M_arrow_begin_col != col || M_arrow_begin_row != row)&&
364  is_inside_board(M_arrow_begin_col, M_arrow_begin_row)&&
365  is_inside_board(col, row))
366  add_arrow(M_arrow_begin_col, M_arrow_begin_row, col, row, color);
367  }
368  return false;
369 }
370 
371 void MyChessboardWidget::moved(cwchess::Move const& move, cwchess::ChessPosition const& previous_position, cwchess::ChessPosition const& UNUSED_ARG(current_position))
372 {
373  DoutEntering(dc::notice, "MyChessboardWidget::moved(" << cwchess::ChessNotation(previous_position, move) << ", ...)");
374  // Having executed a move, we might need to draw or erase the en passant arrow.
375  update_en_passant_arrow();
376 }
377 
378 void MyChessboardWidget::illegal(cwchess::Move const& move, cwchess::ChessPosition const& UNUSED_ARG(chess_position))
379 {
380  DoutEntering(dc::notice, "MyChessboardWidget::illegal(" << cwchess::ChessNotation(*this, move) << ", ...)");
381 }
382 
383 void MyChessboardWidget::picked_up(cwchess::Index const& index, cwchess::ChessPosition const& UNUSED_ARG(chess_position))
384 {
385  DoutEntering(dc::notice, "MyChessboardWidget::picked_up(" << cwchess::ChessNotation(*this, index) << ", ...)");
387  {
388  // If we pick up a piece to do a move, show all legal moves and the cursor.
389  show_reachables(index.col(), index.row(), mode_show_moves);
390  show_cursor();
391  }
392  else if (get_widget_mode() == mode_edit_position)
393  // In 'edit position' mode, show the pinning information instead.
394  show_pinning();
395 }
396 
397 void MyChessboardWidget::dropped(gint col, gint row, cwchess::ChessPosition const& UNUSED_ARG(chess_position))
398 {
399  DoutEntering(dc::notice, "MyChessboardWidget::dropped(" << col << ", " << row << ", ...)");
400  // The piece that was picked up is dropped again. Return to regular standing.
401  hide_cursor();
402  show_pinning();
403 }
404 
405 void MyChessboardWidget::draw_hud_layer(cairo_t* cr, gint sside, guint hud)
406 {
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);
412  double x, y;
413  for (int col = 0; col < 8; ++col)
414  {
415  for (int row = 0; row < 8; ++row)
416  {
417  static char const* number[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
418  cwchess::Index i(col, row);
419  int count = get_defended()[cwchess::white].count(i);
420  char const* utf8 = number[count % 10];
421  x = col * sside + 1;
422  y = (7 - row) * sside + extents.height + 2;
423  cairo_move_to(cr, x, y);
424  if (count > 9)
425  cairo_show_text(cr, number[1]);
426  cairo_show_text(cr, utf8);
427  }
428  }
429 }
430 
431 // The main application.
432 class GtkTest : public Gtk::Window {
433  public:
434  GtkTest(int width, int height);
435  virtual ~GtkTest() { }
436 
437  // Accessors for the chessboard widget.
438  MyChessboardWidget& chessboard_widget(void) { return m_chessboard_widget; }
439  MyChessboardWidget const& chessboard_widget(void) const { return m_chessboard_widget; }
440 
441  private:
442  void setup_menu(void);
443 
444  protected:
445  //Signal handlers:
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)
455  {
456  m_chessboard_widget.on_menu_mode_editposition();
457  if (m_chessboard_widget.get_widget_mode() == cwmm::ChessPositionWidget::mode_edit_game)
458  M_ModePlacePieces_action->set_active(true);
459  m_chessboard_widget.set_widget_mode(cwmm::ChessPositionWidget::mode_edit_position);
460  }
461  virtual void on_menu_mode_editgame(void)
462  {
463  m_chessboard_widget.on_menu_mode_editgame();
464  m_chessboard_widget.set_widget_mode(cwmm::ChessPositionWidget::mode_edit_game);
465  }
466 
467  void moved(cwchess::Move const& move, cwchess::ChessPosition const& previous_position, cwchess::ChessPosition const& current_position);
468 
469  //Member widgets:
470  Gtk::VBox m_vbox;
471  MyChessboardWidget m_chessboard_widget;
472 
473  // Menu and tool bar stuff.
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;
478 
479  std::stack<cwchess::ChessPosition> M_history;
480 };
481 
482 void GtkTest::moved(cwchess::Move const& move, cwchess::ChessPosition const& previous_position, cwchess::ChessPosition const& UNUSED_ARG(current_position))
483 {
484  DoutEntering(dc::notice, "GtkTest::moved(" << cwchess::ChessNotation(previous_position, move) << ", ...)");
485  M_history.push(previous_position);
486 }
487 
488 GtkTest::GtkTest(int width, int height) : m_vbox(FALSE, 0), m_chessboard_widget(this)
489 {
490  // Set a title.
491  set_title("ChessboardWidget Test");
492 
493  // Sets the border width of the window.
494  set_border_width(10);
495 
496  // Set a default width and height.
497  set_default_size(width, height);
498 
499  // A vbox to put a menu and chessboard in.
500  add(m_vbox);
501 
502  // Set up the menu.
503  setup_menu();
504 
505  // Add the chessboard to m_vbox.
506  m_vbox.add(m_chessboard_widget);
507 
508  // Show everything.
509  show_all_children();
510 
511  // Record moves.
512  m_chessboard_widget.signal_moved().connect(sigc::mem_fun(this,& GtkTest::moved));
513 
514  // Update en passant arrow.
515  m_chessboard_widget.signal_moved().connect(sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::moved));
516 
517  // Just show that we can catch this event too.
518  m_chessboard_widget.signal_illegal().connect(sigc::mem_fun(m_chessboard_widget,& MyChessboardWidget::illegal));
519 
520  // Show cursor, reachables and pinning as function of whether we picked up a piece or not.
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));
523 }
524 
525 void GtkTest::on_menu_file_quit(void)
526 {
527  hide();
528 }
529 
530 void GtkTest::on_menu_file_save(void)
531 {
532  std::ofstream file;
533  file.open("FEN.out");
534  file << chessboard_widget().FEN() << std::endl;
535  file.close();
536 }
537 
538 void GtkTest::on_menu_file_undo(void)
539 {
540  if (M_history.empty())
541  return;
542  chessboard_widget().set_position(M_history.top());
543  M_history.pop();
544 }
545 
546 void GtkTest::on_menu_file_new(void)
547 {
548  chessboard_widget().initial_position();
549 }
550 
551 void GtkTest::on_menu_file_clear(void)
552 {
553  chessboard_widget().clear();
554  Dout(dc::notice, "Calling M_ModeEditPosition_action->set_active(true)");
555  M_ModeEditPosition_action->set_active(true);
556 }
557 
558 void GtkTest::on_menu_file_flip(void)
559 {
560  chessboard_widget().set_flip_board(!chessboard_widget().get_flip_board());
561 }
562 
563 void GtkTest::on_menu_file_export(void)
564 {
565  using namespace cwchess;
566  std::cout << " chess_position.load_FEN(\"" << chessboard_widget().FEN() << "\");\n";
567  std::cout << " static mask_t moves1[] = {\n";
568  int color_count = 0;
569  bool first = true;
570  for (Color color(black); color_count < 2; ++color_count, color = white)
571  {
572  for (PieceIterator piece_iter = chessboard_widget().piece_begin(color); piece_iter != chessboard_widget().piece_end(); ++piece_iter)
573  {
574  if (first)
575  {
576  std::cout << " ";
577  first = false;
578  }
579  else
580  std::cout << ", ";
581  std::cout << std::hex << "0x" << chessboard_widget().moves(piece_iter.index())() << std::dec;
582  }
583  }
584  std::cout << "\n };" << std::endl;
585 }
586 
587 void GtkTest::on_menu_file_open(void)
588 {
589  std::ifstream file;
590  file.open("FEN.out");
591  std::string fen;
592  std::getline(file, fen);
593  file.close();
594  chessboard_widget().load_FEN(fen);
595 }
596 
597 void GtkTest::setup_menu(void)
598 {
599  // Create the action group.
600  m_refActionGroup = Gtk::ActionGroup::create();
601 
602  // File menu:
603  m_refActionGroup->add(Gtk::Action::create("FileMenu", "File"));
604  // Add the QUIT action.
605  m_refActionGroup->add(Gtk::Action::create("FileQuit", Gtk::Stock::QUIT),
606  sigc::mem_fun(*this,& GtkTest::on_menu_file_quit));
607  // Add the OPEN action.
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));
610  // Add the SAVE action.
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));
613  // Add the CONVERT action.
614  m_refActionGroup->add(Gtk::Action::create("FileConvert", Gtk::Stock::CONVERT, "Export"),
615  sigc::mem_fun(*this,& GtkTest::on_menu_file_export));
616  // Add the CLEAR action.
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));
619  // Add the NEW action.
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));
622  // Add the UNDO action.
623  m_refActionGroup->add(Gtk::Action::create("FileUndo", Gtk::Stock::UNDO, "Undo"),
624  sigc::mem_fun(*this,& GtkTest::on_menu_file_undo));
625  // Add the FLIP action.
626  m_refActionGroup->add(Gtk::Action::create("FileFlip", Gtk::Stock::REFRESH, "Flip"),
627  sigc::mem_fun(*this,& GtkTest::on_menu_file_flip));
628 
629  // Mode menu:
630  m_refActionGroup->add(Gtk::Action::create("ModeMenu", "Mode"));
631  Gtk::RadioAction::Group group_widget_mode;
632  Gtk::RadioAction::Group group_rightclick_mode;
633  // Add SET UP POSITION action.
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));
636  // Add EDIT GAME action.
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));
639  // Add the SHOW CANDIDATES action.
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));
642  // Add the SHOW REACHABLES action.
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));
645  // Add the SHOW ATTACKED action.
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));
648  // Add the SHOW DEFENDABLES action.
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));
651  // Add the SHOW DEFENDED BLACK action.
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));
654  // Add the SHOW DEFENDED WHITE action.
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));
657  // Add the SHOW MOVES action.
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));
660  // Add the PLACE PIECES action.
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));
663 
664  // Default.
665 #if 1
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);
670 #else
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);
675 #endif
676 
677  // Create a UIManager and add the ActionGroup to the UIManager.
678  m_refUIManager = Gtk::UIManager::create();
679  m_refUIManager->insert_action_group(m_refActionGroup);
680 
681  // Tell the parent window to respond to the specified keyboard shortcuts.
682  add_accel_group(m_refUIManager->get_accel_group());
683 
684  // Layout the actions in a menubar and toolbar.
685  Glib::ustring ui_info =
686  "<ui>"
687  " <menubar name='MenuBar'>"
688  " <menu action='FileMenu'>"
689  " <menuitem action='FileOpen'/>"
690  " <menuitem action='FileSave'/>"
691  " <menuitem action='FileQuit'/>"
692  " </menu>"
693  " <menu action='ModeMenu'>"
694  " <menuitem action='ModeEditPosition'/>"
695  " <menuitem action='ModeEditGame'/>"
696  " <separator/>"
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'/>"
705  " </menu>"
706  " </menubar>"
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'/>"
716  " </toolbar>"
717  "</ui>";
718 
719 #ifdef GLIBMM_EXCEPTIONS_ENABLED
720  try
721  {
722  m_refUIManager->add_ui_from_string(ui_info);
723  }
724  catch(const Glib::Error& ex)
725  {
726  std::cerr << "building menus failed: " << ex.what();
727  }
728 #else
729  std::auto_ptr<Glib::Error> ex;
730  m_refUIManager->add_ui_from_string(ui_info, ex);
731  if(ex.get())
732  {
733  std::cerr << "building menus failed: " << ex->what();
734  }
735 #endif // GLIBMM_EXCEPTIONS_ENABLED
736 
737  // Get the menubar and toolbar widgets, and add them to a container widget.
738  Gtk::Widget* pMenubar = m_refUIManager->get_widget("/MenuBar");
739  if(pMenubar)
740  m_vbox.pack_start(*pMenubar, Gtk::PACK_SHRINK);
741 
742  Gtk::Widget* pToolbar = m_refUIManager->get_widget("/ToolBar") ;
743  if(pToolbar)
744  m_vbox.pack_start(*pToolbar, Gtk::PACK_SHRINK);
745 }
746 
747 int main(int argc, char* argv[])
748 {
749  using namespace cwchess;
750 
751  Debug(NAMESPACE_DEBUG::init());
752  Dout(dc::notice, "Entered main()");
753 
754  Gtk::Main kit(argc, argv);
755 
756  // Create the application window, passing a default size.
757  GtkTest application(500, 532);
758 
759  // Get a reference to the chessboard widget.
760  MyChessboardWidget& chessboard_widget(application.chessboard_widget());
761 
762  ChessPosition chess_position;
763  //chess_position.initial_position();
764  chess_position.load_FEN("rnbqkbnr/4p1pp/1p6/p1p1PpP1/1P1p4/2P5/P2P1P1P/RNBQKBNR w KQkq f6 0 7");
765 #if 0
766  std::ifstream file;
767  file.open("FEN.out");
768  std::string fen;
769  std::getline(file, fen);
770  file.close();
771  chess_position.load_FEN(fen);
772 #endif
773  //chess_position.swap_colors();
774 
775  chessboard_widget.set_position(chess_position);
776 
777  // Set the border color.
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);
781 
782  //open_gdb = true;
783  Gtk::Main::run(application);
784 
785  return 0;
786 }
IndexData const index_begin
A constant representing the& #39;first&#39; index.
Definition: Index.h:184
static widget_mode_type const mode_edit_position
The value used for the& #39;Edit Position&#39; mode.
void set_background_colors(ColorHandle const* handles)
Set new background colors of any number of squares.
A namespace for all chess related objects that are not related to the GUI.
Definition: Array.h:39
bool load_FEN(std::string const& FEN)
Read a FEN code.
virtual bool on_button_press(gint col, gint row, GdkEventButton const* event)
Called when a mouse button is pressed while the mouse is on the chessboard.
Definition: tstcpp.cc:305
void disable_hud_layer(guint hud)
Disable the HUD layer again.
ColorData const white
A constant representing the color white.
Definition: Color.h:55
bool is_nothing(void) const
Returns TRUE if the code represents& #39;nothing&#39;.
Definition: Code.h:160
static gboolean is_inside_board(gint col, gint row)
Test if a given column and row are on the chessboard.
Index from_index(void) const
Return the index of the square that pawn came from.
Definition: EnPassant.h:105
A chess move in a particular chess position.
Definition: Move.h:44
BitBoard candidates(Index const& index) const
Return a BitBoard with bits set for all squares that are candidates to move to.
widget_mode_type get_widget_mode(void) const
Return the current widget mode.
A helper class to write other objects to an ostream.
Definition: ChessNotation.h:51
virtual bool on_button_release(gint col, gint row, GdkEventButton const* event)
Called when a mouse button is released.
Definition: tstcpp.cc:354
void show_cursor(void)
Show the cursor.
An object representing en passant information.
Definition: EnPassant.h:49
gint sside(void) const
The side of a square in pixels.
A one-boolean-per-square chessboard.
Definition: BitBoard.h:266
This file contains the declaration of class ChessPositionWidget.
The index of a chess square.
Definition: Index.h:211
bool test() const
Test if any bit is set at all.
Definition: BitBoard.h:450
A chessboard widget that is synchronized with a ChessPosition .
int col(void) const
Returns the column.
Definition: Index.h:337
void hide_cursor(void)
Hide the cursor.
static widget_mode_type const mode_edit_game
The value used for the& #39;Edit Game&#39; mode.
A particular piece on the board.
Definition: Piece.h:45
Index index(void) const
Return the index of the square that was passed.
Definition: EnPassant.h:85
Piece piece_at(Index const& index) const
Return the Piece on the square index.
void remove_arrow(gpointer ptr)
Remove a previously added arrow.
Index pawn_index(void) const
Return the index of the pawn that just advanced two squares.
Definition: EnPassant.h:95
void get_dark_square_color(GdkColor& color) const
Retrieve the current background color of the dark 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.
Definition: Index.h:334
Color color(void) const
Return the color of the piece.
Definition: Piece.h:112
A chess position.
Definition: ChessPosition.h:50
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.
void set_widget_mode(widget_mode_type widget_mode)
Set the widget mode.
Definition: tstcpp.cc:122
CwChessboardColorHandle ColorHandle
A color handle used for background markers.
void set_marker_color(gint col, gint row, ColorHandle mahandle)
Change the color of the marker.
bool exists(void) const
Return TRUE if the last move was a pawn advancing two squares.
Definition: EnPassant.h:79
A color (black or white).
Definition: Color.h:67
void get_light_square_color(GdkColor& color) const
Retrieve the current background color of the light squares.
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 ...
gpointer add_arrow(gint begin_col, gint begin_row, gint end_col, gint end_row, GdkColor const& color)
Draw an arrow on the board.
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&#39;.
Definition: Index.h:186
virtual void draw_hud_layer(cairo_t* cr, gint sside, guint hud)
Draw the HUD layer.
Definition: tstcpp.cc:405
Non-mutable iterator over selective chess pieces in a chess position.
Definition: PieceIterator.h:42
void enable_hud_layer(guint hud)
Active a HUD layer.
Color to_move(void) const
Return whose turn it is.
This file contains the declaration of class ChessNotation.
gboolean get_flip_board(void) const
Get the boolean which determines whether white is playing bottom up or top down.
ColorHandle allocate_color_handle_rgb(gdouble red, gdouble green, gdouble blue)
Allocate a new ColorHandle.
Code code(void) const
The code of this piece.
Definition: Piece.h:121
ColorData const black
A constant representing the color black.
Definition: Color.h:53

Copyright © 2006 - 2010 Carlo Wood.  All rights reserved.