make7libre  0.8.6
game.cc
Go to the documentation of this file.
1 /*
2  * Make7Libre, free (as in freedom) implementation of the
3  * unfamous game 'Make 7 Hexa Puzzle'
4  * Copyright 2016-2017 (C) Felicien PILLOT <felicien.pillot@member.fsf.org>
5  *
6  * This file is part of Make7Libre.
7  *
8  * Make7Libre is free software: you can redistribute it and/or modify
9  * under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * Make7Libre is distributed in the hope that it will be useful,
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * with Make7Libre. If not, see <http://www.gnu.org/licenses/>.
20  */
21 /***********
22  * game.cc *
23  * ~~~~~~~ *
24  ***********/
25 
26 #include <sys/stat.h> // mkdir () function
27 #include "../include/game.h"
28 
29 
30 /*
31  * /////////////////////////
32  * // Public functions //
33  * /////////////////////////
34  */
35 
42 /* All these widgets are defined in the basic.glade file, and imported with Gtk::Builder */
43 // Windows of the game :
44 make7window (), make7scores (), make7message (), make7error_board (),
45 make7confirm (), make7askname (), make7credits (),
46 // Main window title bar and menu items :
47 headerbar (), appmenu (), newgame (), scores (), credits (), quit (),
48 // Buttons for the interface :
49 button_cancel (), button_credits (), button_help (),
50 button_new (), button_next (), button_quit (), button_rotate (),
51 button_save (), button_scores (), button_erase (),
52 // Buttons forming the Board :
53 nnw (), nn (), nne (), nww (), nw (), ne (), nee (), ww (), w (), m (), e (), ee (), sww (),
54 sw (), se (), see (), ssw (), ss (), sse (),
55 // Buttons (not clickable) forming the SelectionArea (under the Board) :
56 mainNw (), mainNe (), mainW (), mainM (), mainE (), mainSw (), mainSe (),
57 // Other miscellaneous widgets :
58 current_score (), box_score (), user_entry (),
59 /* Now these are global (privates) variables, shared between all functions */
60 Board (), SelectionArea (), BoardSnapshotMap (), Colors (), BoardKeys (), SelectionAreaKeys (), ColorsKeys (),
61 pos2 (), max (), valHexa1 (), valHexa2 (), score (), nMatch (), oldValHexa1 (), oldValHexa2 (),
62 CssProvider ()
63 {
64  // Define keys
65  BoardKeys = { 13, 14, 15, 22, 23, 24, 25,
66  31, 32, 33, 34, 35, 41, 42, 43,
67  44, 51, 52, 53 };
68  SelectionAreaKeys = { -10, -9, -1, 0, 1, 9, 10 };
69  ColorsKeys = {0, 1, 2, 3, 4, 5, 6, 7};
70  Colors = {{0, "nocolor"}, {1, "purple"}, {2, "orange"}, {3, "red"},
71  {4, "blue"}, {5, "green"}, {6, "yellow"}, {7, "multicolor"}};
72  // Define style sheet
73  CssProvider = Gtk::CssProvider::create();
74  if (! CssProvider->load_from_path
75  (Glib::build_filename (UI_DIR, "theme.css")))
76  {
77  std::cout << "Failed to load CSS file" << std::endl;
78  return;
79  }
80 }
81 
82 void
84 {
85  /* Interface buttons */
86  // Cancel action
87  if (button_cancel)
88  button_cancel->signal_clicked ().connect
89  (sigc::mem_fun (*this, &Game::on_cancel_action_activate));
90  // Close scores
92  button_close_scores->signal_clicked ().connect
93  (sigc::mem_fun (*this, &Game::on_close_scores_activate));
94  // Display help
95  if (button_help)
96  button_help->signal_clicked ().connect
97  (sigc::mem_fun (*this, &Game::on_display_help_activate));
98  // Next hexa
99  if (button_next)
100  button_next->signal_clicked ().connect
101  (sigc::mem_fun (*this, &Game::on_next_hexa_activate));
102  /* Menu items */
103  if (newgame)
104  newgame->signal_activate ().connect
105  (sigc::mem_fun (*this, &Game::on_new_game_activate));
106  if (scores)
107  scores->signal_activate ().connect
108  (sigc::mem_fun (*this, &Game::on_display_scores_activate));
109  if (credits)
110  credits->signal_activate ().connect
111  (sigc::mem_fun (*this, &Game::on_display_credits_activate));
112  if (quit)
113  quit->signal_activate ().connect
114  (sigc::mem_fun (*this, &Game::on_quit_game_activate));
115  /* Score save entry */
116  if (user_entry)
117  user_entry->signal_editing_done().connect
118  (sigc::mem_fun (*this, &Game::on_entry_editing_done));
119  /* Game buttons */
120  for (int key : BoardKeys)
121  Board [key]->signal_clicked ().connect
122  (sigc::bind<int> (sigc::mem_fun (*this, &Game::game_button_selected), key) );
123  SelectionArea[0]->signal_clicked () .connect
124  (sigc::mem_fun (*this, &Game::rotate_hexas_left));
125  SelectionArea[0]->signal_button_press_event () .connect
126  (sigc::mem_fun (*this, &Game::rotate_hexas_right));
127 }
128 
129 void
130 Game::display (Glib::RefPtr<Gtk::Application> app)
131 {
133  newgame->add_accelerator ("activate", make7window->get_accel_group (), 'n',
134  Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
135  scores->add_accelerator ("activate", make7window->get_accel_group (), 's',
136  Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
137  credits->add_accelerator ("activate", make7window->get_accel_group (), 'c',
138  Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
139  quit->add_accelerator ("activate", make7window->get_accel_group (), 'q',
140  Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
141  button_help->add_accelerator ("activate", make7window->get_accel_group (), 'h',
142  Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
143  button_erase->add_accelerator ("activate", make7window->get_accel_group (), 'e',
144  Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
145  button_cancel->add_accelerator ("activate", make7window->get_accel_group (), 'z',
146  Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
147  button_next->add_accelerator ("activate", make7window->get_accel_group (), ' ',
148  Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
149 
151  Glib::RefPtr<Gdk::Pixbuf> icon =
152  Gdk::Pixbuf::create_from_file (ICON_DIR "/32x32/apps/make7libre.png");
153  make7window->set_icon (icon);
154  make7window->set_has_resize_grip (true);
155  Glib::RefPtr<Gtk::StyleContext> WinContext =
156  make7window->get_style_context ();
157  WinContext->add_provider (CssProvider,
158  GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
159  make7window->signal_delete_event (). connect
160  (sigc::mem_fun (*this, &Game::on_make7window_hide));
161  app->run (*make7window);
162 }
163 
164 void
166 {
167  Glib::RefPtr<Gtk::Builder> builder = Gtk::Builder::create_from_file
168  (UI_DIR "/basic.glade");
169  // Get every Make 7 windows
170  builder->get_widget ("make7window", make7window);
171  make7window->add_accel_group (Gtk::AccelGroup::create ());
172  builder->get_widget ("make7scores", make7scores);
173  builder->get_widget ("make7credits", make7credits);
174  builder->get_widget ("make7error_board", make7error_board);
175  builder->get_widget ("make7confirm", make7confirm);
176  builder->get_widget ("make7askname", make7askname);
177  builder->get_widget ("make7message", make7message);
178  // Get titlebar and menu actions
179  builder->get_widget ("headerbar", headerbar);
180  make7window->set_titlebar (*headerbar);
181  builder->get_widget ("newgame", newgame);
182  builder->get_widget ("scores", scores);
183  builder->get_widget ("credits", credits);
184  builder->get_widget ("quit", quit);
185  builder->get_widget ("appmenu", appmenu);
186  appmenu->set_accel_group (make7window->get_accel_group ());
187  // Get every interface buttons
188  builder->get_widget ("button_cancel", button_cancel);
189  builder->get_widget ("button_close_scores", button_close_scores);
190  builder->get_widget ("button_erase", button_erase);
191  builder->get_widget ("button_help", button_help);
192  builder->get_widget ("button_next", button_next);
193  builder->get_widget ("button_apply_save", button_save);
194  // Get score label, box and user entry
195  builder->get_widget ("current_score", current_score);
196  builder->get_widget ("box_score", box_score);
197  builder->get_widget ("user_entry", user_entry);
198  // Get every game buttons
199  // (board)
200  builder->get_widget ("nnw", nnw);
201  builder->get_widget ("nn", nn);
202  builder->get_widget ("nne", nne);
203  builder->get_widget ("nww", nww);
204  builder->get_widget ("nw", nw);
205  builder->get_widget ("ne", ne);
206  builder->get_widget ("nee", nee);
207  builder->get_widget ("ww", ww);
208  builder->get_widget ("w", w);
209  builder->get_widget ("m", m);
210  builder->get_widget ("e", e);
211  builder->get_widget ("ee", ee);
212  builder->get_widget ("sww", sww);
213  builder->get_widget ("sw", sw);
214  builder->get_widget ("se", se);
215  builder->get_widget ("see", see);
216  builder->get_widget ("ssw", ssw);
217  builder->get_widget ("ss", ss);
218  builder->get_widget ("sse", sse);
219  // (selection area)
220  builder->get_widget ("mainNw", mainNw);
221  builder->get_widget ("mainNe", mainNe);
222  builder->get_widget ("mainW", mainW);
223  builder->get_widget ("mainM", mainM);
224  builder->get_widget ("mainE", mainE);
225  builder->get_widget ("mainSw", mainSw);
226  builder->get_widget ("mainSe", mainSe);
227  // For much more convenience, all these buttons are stocked in std::maps<int, Glib::ustring>
228  Board = { {13, nnw}, {14, nn}, {15, nne}, {22, nww},
229  {23, nw}, {24, ne}, {25, nee}, {31, ww},
230  {32, w}, {33, m}, {34, e}, {35, ee}, {41, sww},
231  {42, sw}, {43, se}, {44, see}, {51, ssw},
232  {52, ss}, {53, sse} };
233  SelectionArea = { {-10, mainNw}, {-9, mainNe},
234  {-1, mainW}, {0, mainM}, {1, mainE},
235  {9, mainSw}, {10, mainSe} };
236 }
237 
238 void
240 {
241  // Get score list from file
242  get_scores ();
243  // Reset the current score
244  current_score->set_label ("0 pts");
245  // Reset the maximum of values proposed in selection area
246  max = 1;
247  // Clean board
248  reset_board ();
249  // Prepare the selection area
250  get_random_hexas ();
252 }
253 
254 
255 /*
256  * /////////////////////////
257  * // Private functions //
258  * /////////////////////////
259  */
260 
261 void
262 Game::big_badaboom (std::list<int> hexas)
263 {
264  int nb;
265  for (int hexa : hexas)
266  {
267  for (int key : SelectionAreaKeys)
268  {
269  nb = get_neighbour (key, hexa);
270  if (nb != -42 && Board[nb]->get_label () != "")
271  {
272  Board[nb]->set_label ("");
273  update_hexa_color (nb);
274  }
275  }
276  }
277 }
278 
279 void
281 {
282  std::map<int, Glib::ustring> tmpBoard = get_board_snapshot ();
283  int nFull = 0, nEmpty = 0;
284  for (auto const& hexa : tmpBoard)
285  {
286  if (hexa.second == "")
287  nEmpty++;
288  else
289  nFull++;
290  }
291  if (nEmpty == 19)
292  {
293  make7message->set_message ("Congratulation, you win !");
294  if (make7message->run ())
295  {
296  make7message->hide ();
297  write_scores ();
298  /* TODO
299  * Not a new game, but a new board !!!
300  */
301  launch_game ();
302  }
303  }
304  if (nFull == 19)
305  {
306  make7message->set_message ("You lose, no more place available !\nTry again !");
307  make7message->show ();
308  if (make7message->run ())
309  {
310  make7message->hide ();
311  write_scores ();
312  launch_game ();
313  }
314  }
315 }
316 
317 void
319 {
320  Glib::ustring message;
321  if (i == 1)
322  message = "Error ! This location is not empty !";
323  if (i == 2)
324  message = "Error ! One of the hexa is out of the board !";
325  if (i == 3)
326  message = "Error ! You have not enough score points !";
327  if (i == 4)
328  message = "Error ! There is nothing here !";
329  if (i == 5)
330  message = "Error undefined !";
331  make7error_board->set_message (message);
332  make7error_board->show ();
333 }
334 
335 void
336 Game::define_hexa (int ref, Glib::ustring valref)
337 {
338  // Update the label
339  Board[ref]->set_label (valref);
340  update_hexa_color (ref);
341  // This functions calls every half-second define_hexa(), until it returns false
342  Glib::signal_timeout ().connect
343  (sigc::bind (sigc::mem_fun (*this, &Game::triggers), ref), 500);
344 }
345 
346 void
348 {
349  nMatch = -50;
350  if (Board[ref]->get_label () == "")
351  display_error (4);
352  else
353  {
354  if (refresh_score ())
355  {
356  Board[ref]->set_label ("");
357  update_hexa_color (ref);
358  }
359  }
360  button_erase->set_active (false);
361  // At this point, the game could be finished.
362  check_end ();
363  return;
364 }
365 
366 std::map<int, Glib::ustring>
368 {
369  std::map<int, Glib::ustring> map;
370  for (int i : BoardKeys)
371  map[i] = Board[i]->get_label ();
372  return map;
373 }
374 
375 void
377 {
378  // Backup the board and the selection area
381  button_cancel->set_sensitive(true);
382 
383  /* Now the following actions can be triggered : */
384  // Are we erasing this hexa ?
385  if (button_erase->get_active ())
386  erase_hexa (ref);
387  // Are we defining a new hexa(s) ?
388  else if (Board[ref]->get_label () == "")
389  {
390  bool there_is_a_second_hexa_to_define = false;
391  int nb = -42;
392  if (pos2 != -42)
393  {
394  nb = get_neighbour (pos2, ref);
395  if (nb == -42)
396  {
397  display_error (2);
398  return;
399  }
400  else if (Board[nb]->get_label () != "")
401  {
402  display_error (1);
403  return;
404  }
405  else
406  // If there is a second hexa, and it doesn't override an existing value,
407  // neither is out of the board, then put its value on the board
408  there_is_a_second_hexa_to_define = true;
409  }
410  // Put the value of the main hexa on the board it it doesn't override an existing value
411  define_hexa (ref, get_main_hexa ());
412  if (there_is_a_second_hexa_to_define)
413  define_hexa (nb, get_second_hexa ());
414  // Then it starts a new turn
415  get_random_hexas ();
417  }
418  else
419  display_error (1);
420 }
421 
422 Glib::ustring
424 {
425  Glib::ustring configdir = Glib::get_user_config_dir () + "/make7libre";
426  Glib::ustring filepath = configdir + "/history";
427  if (file_test (filepath, Glib::FILE_TEST_IS_REGULAR))
428  return filepath;
429  else
430  {
431  // Create directory
432  mkdir (configdir.c_str (), 0755);
433  Glib::KeyFile *new_config_file = new Glib::KeyFile ();
434  // Get current time
435  Glib::TimeVal *cur_time = new Glib::TimeVal;
436  cur_time->assign_current_time ();
437  Glib::ustring top_comment = " This file was firstly created by Make7Libre, the "
438  + cur_time->as_iso8601 ();
439  // Fill and create the file
440  new_config_file->set_comment (top_comment);
441  new_config_file->save_to_file (filepath);
442  return filepath;
443  }
444 }
445 
446 
447 bool
449 {
450  if (make7confirm->run () == -8)
451  {
452  make7confirm->hide ();
453  if (std::stoi (current_score->get_label ()) != 0)
454  write_scores ();
455  return true;
456  }
457  // else
458  make7confirm->hide ();
459  return false;
460 }
461 
462 Glib::ustring
464 {
465  return mainM->get_label ();
466 }
467 
471 int
472 Game::get_neighbour (int rel, int ref)
473 {
474  if ((rel == -10 && (ref == 15 || ref == 14 || ref == 13 ||
475  ref == 22 || ref == 31))
476  ||
477  (rel == -9 && (ref == 13 || ref == 14 || ref == 15 ||
478  ref == 25 || ref == 35))
479  ||
480  (rel == -1 && (ref == 13 || ref == 22 || ref == 31 ||
481  ref == 41 || ref == 51))
482  ||
483  (rel == 1 && (ref == 15 || ref == 25 || ref == 35 ||
484  ref == 44 || ref == 53))
485  ||
486  (rel == 9 && (ref == 31 || ref == 41 || ref == 51 ||
487  ref == 52 || ref == 53))
488  ||
489  (rel == 10 && (ref == 51 || ref == 52 || ref == 53 ||
490  ref == 44 || ref == 35)))
491  // Forbidden move
492  return -42;
493  else
494  return (rel + ref);
495 }
496 
497 int
499 {
500  return pos2;
501 }
502 
503 void
505 {
506  int nHexa = rand () % 2;
507  if (nHexa == 1)
508  {
509  valHexa1 = rand () % max + 1;
510  set_pos2 (-42);
511  }
512  if (nHexa == 0)
513  {
514  valHexa1 = rand () % max + 1;
515  valHexa2 = rand () % max + 1;
516  set_pos2 (9);
517  }
518 }
519 
520 void
522 {
523  Glib::ustring config_file = get_config_file ();
524  Glib::KeyFile *saved_scores = new Glib::KeyFile ();
525  saved_scores->load_from_file (config_file);
526  // Clear box_score
527  std::vector<Gtk::Widget*> old_score_vect = box_score->get_children();
528  for (Gtk::Widget* old_score : old_score_vect)
529  {
530  box_score->remove (*old_score);
531  }
532  if (saved_scores->has_group ("Scores"))
533  {
534  Glib::ArrayHandle<Glib::ustring> names = saved_scores->get_keys ("Scores");
535  for (Glib::ustring user : names)
536  {
537  std::list<int> user_scores = saved_scores->get_integer_list ("Scores", user);
538  for (int u_score : user_scores)
539  {
540  Gtk::Label *user_score_label = new Gtk::Label ();
541  Glib::ustring line = user + "\t: " + std::to_string (u_score);
542  user_score_label->set_text (line);
543  box_score->pack_start (*user_score_label);
544  }
545  }
546  box_score->show_all ();
547  }
548 }
549 
550 Glib::ustring
552 {
553  if (pos2 != -42)
554  return SelectionArea[pos2]->get_label ();
555  return "nosecondhexa";
556 }
557 
558 void
559 Game::merge_hexas (int newHexa, std::list<int> oldHexas)
560 {
561  // Erase old hexas
562  for (int i : oldHexas)
563  {
564  if (i != newHexa)
565  {
566  Board[i]->set_label ("");
567  update_hexa_color (i);
568  }
569  }
570  // Change label
571  if (Board[newHexa]->get_label () != "")
572  {
573  int val = std::stoi (Board[newHexa]->get_label ()) + 1;
574  if (val > max && val < 8)
575  max = val;
576  if (val == 8)
577  {
578  big_badaboom (oldHexas);
579  nMatch = 100;
580  refresh_score ();
581  }
582  else
583  Board[newHexa]->set_label (std::to_string (val));
584  }
585  else
586  std::cerr << "No label !" << std::endl;
587  update_hexa_color (newHexa);
588 }
589 
590 void
592 {
593  nMatch = -100;
594  if (refresh_score ())
595  reset_snapshot ();
596 }
597 
598 void
600 {
601  make7scores->hide ();
602 }
603 
604 void
606 {
607  if (make7credits->run () == -4)
608  make7credits->hide ();
609 }
610 
611 void
613 {
614  // TODO
615  // Display help
616  system ("yelp");
617 }
618 
619 void
621 {
622  make7scores->show ();
623 }
624 
625 void
627 {
628  std::cout << "Event enter !!!" << std::endl;
629  button_save->clicked ();
630 }
631 
632 bool
633 Game::on_make7window_hide (_GdkEventAny* event)
634 {
635  if (get_confirmation ())
636  return false;
637  else
638  return true;
639 }
640 
641 void
643 {
644  if (get_confirmation ())
645  launch_game ();
646 }
647 
648 void
650 {
651  nMatch = -75;
652  if (refresh_score ())
653  {
654  get_random_hexas ();
656  }
657 }
658 
659 void
661 {
662  make7window->close ();
663 }
664 
665 int
667 {
668  int Iscore = std::stoi (current_score->get_label ());
669  Iscore += nMatch;
670  Glib::ustring Sscore = std::to_string (Iscore) + " pts";
671  if (Iscore >= 0)
672  current_score->set_label (Sscore);
673  else
674  {
675  display_error (3);
676  return 0;
677  }
678  return 1;
679 }
680 
681 void
683 {
685  set_main_hexa (std::to_string (valHexa1));
686  set_second_hexa (std::to_string (valHexa2));
687 }
688 
689 void
691 {
692  for (int key : BoardKeys)
693  {
694  Board[key]->set_label ("");
695  update_hexa_color (key);
696  }
697 }
698 
699 void
701 {
702  for (int key : SelectionAreaKeys)
703  {
704  SelectionArea[key]->set_label ("");
705  Glib::PropertyProxy<Gtk::ReliefStyle> prop =
706  SelectionArea[key]->property_relief ();
707  prop.set_value (Gtk::RELIEF_NONE);
708  SelectionArea[key]->set_sensitive (false);
709  update_hexa_color (key);
710  }
711 }
712 
713 void
715 {
716  for (int i : BoardKeys)
717  {
718  Board[i]->set_label (BoardSnapshotMap[i]);
719  update_hexa_color (i);
720  }
721  set_pos2 (9);
722  valHexa1 = std::stoi (oldValHexa1);
723  if (oldValHexa2 != "nosecondhexa")
724  valHexa2 = std::stoi (oldValHexa2);
725  else
726  pos2 = -42;
729  button_cancel->set_sensitive(false);
730 }
731 
732 void
734 {
735  int actualPos2 = get_pos2 ();
736  if (actualPos2 == -10)
737  set_pos2 (-9);
738  if (actualPos2 == -9)
739  set_pos2 (1);
740  if (actualPos2 == 1)
741  set_pos2 (10);
742  if (actualPos2 == 10)
743  set_pos2 (9);
744  if (actualPos2 == 9)
745  set_pos2 (-1);
746  if (actualPos2 == -1)
747  set_pos2 (-10);
750 }
751 
752 bool
753 Game::rotate_hexas_right (GdkEventButton* event)
754 {
755  int actualPos2 = get_pos2 ();
756  if (event->button == 3)
757  {
758  if (actualPos2 == -10)
759  set_pos2 (-1);
760  if (actualPos2 == -9)
761  set_pos2 (-10);
762  if (actualPos2 == 1)
763  set_pos2 (-9);
764  if (actualPos2 == 10)
765  set_pos2 (1);
766  if (actualPos2 == 9)
767  set_pos2 (10);
768  if (actualPos2 == -1)
769  set_pos2 (9);
770  }
773  return true;
774 }
775 
776 bool
777 Game::scan_neighbours (int ref, std::list<int> &oldRefs)
778 {
779  // Scan every neighbours around ref hexa
780  for (int key : SelectionAreaKeys)
781  {
782  // Skip the central position
783  if (key == 0)
784  continue;
785  int Nb = get_neighbour (key, ref);
786  // Check if we are not out of the board
787  if (Nb == -42)
788  continue;
789  // Check if we don't match the previous hexa
790  bool skip = false;
791  for (int i : oldRefs)
792  if (Nb == i)
793  skip = true;
794  if (skip)
795  continue;
796  // If this matching hexa has the same value as the current one
797  if (Board[ref]->get_label () != "" &&
798  Board[Nb]->get_label () == Board[ref]->get_label ())
799  {
800  nMatch++;
801  oldRefs.push_back (Nb);
802  scan_neighbours (Nb, oldRefs);
803  }
804  }
805  return false;
806 }
807 
808 void
809 Game::set_main_hexa (Glib::ustring Snum)
810 {
811  mainM->set_label (Snum);
812  Glib::PropertyProxy<Gtk::ReliefStyle> prop =
813  mainM->property_relief ();
814  prop.set_value (Gtk::RELIEF_NORMAL);
815  mainM->set_sensitive (true);
816  update_hexa_color (0);
817 }
818 
819 void
820 Game::set_pos2 (int givenPos2)
821 {
822  pos2 = givenPos2;
823 }
824 
825 void
826 Game::set_second_hexa (Glib::ustring Snum)
827 {
828  if (pos2 != -42)
829  {
830  SelectionArea[pos2]->set_label (Snum);
832  Glib::PropertyProxy<Gtk::ReliefStyle> prop =
833  SelectionArea[pos2]->property_relief ();
834  prop.set_value (Gtk::RELIEF_NORMAL);
835  SelectionArea[pos2]->set_sensitive (true);
836  }
837 }
838 
839 void
841 {
843  if (get_second_hexa () != "")
845  else
846  oldValHexa2 = "";
847 }
848 
849 bool
850 Game::triggers (int ref)
851 {
852  std::list<int> matchingNbs;
853  matchingNbs = {ref};
854  scan_neighbours (ref, matchingNbs);
855  // In case there are at least two matching neighbors
856  if (matchingNbs.size () > 2)
857  {
858  // Merge them
859  merge_hexas (ref, matchingNbs);
860  // and update the score
861  nMatch = matchingNbs.size () * 10;
862  refresh_score ();
863  // Then tell to define_hexas() that it is not finished !
864  return true;
865  }
866  // At this point, the game can be finished.
867  check_end ();
868  // Stop
869  return false;
870 }
871 
872 void
874 {
875  Glib::RefPtr<Gtk::StyleContext> HexaContext;
876  int val = -42;
877  if (hexa == -42)
878  return;
879  if (hexa < 13)
880  {
881  HexaContext = SelectionArea[hexa]->get_style_context ();
882  if (SelectionArea[hexa]->get_label () != "")
883  val = std::stoi (SelectionArea[hexa]->get_label ());
884  }
885  else
886  {
887  HexaContext = Board[hexa]->get_style_context();
888  if (Board[hexa]->get_label () != "")
889  val = std::stoi (Board[hexa]->get_label ());
890  }
891  // Customize this hexa
892  HexaContext->add_provider (CssProvider,
893  GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
894  // Clear old class styles
895  for (int key : ColorsKeys)
896  HexaContext->remove_class (Colors [key]);
897  // Assign new color
898  if (val != -42)
899  HexaContext->add_class (Colors [val]);
900  else
901  HexaContext->add_class ("nocolor");
902 }
903 
904 void
906 {
907  // Get config file
908  Glib::ustring config_file = get_config_file ();
909  Glib::KeyFile *saved_scores;
910  saved_scores = new Glib::KeyFile ();
911  saved_scores->load_from_file (config_file);
912  // If the user wants to save his score
913  if (make7askname->run () == 10)
914  {
915  // Get his name
916  Glib::ustring username = user_entry->get_text();
917  // Get his old score (eventually)
918  std::list<int> Lscore;
919  if (saved_scores->has_group("Scores"))
920  {
921  if (saved_scores->has_key("Scores", username))
922  Lscore = saved_scores->get_integer_list ("Scores", username);
923  }
924  // Add current score
925  Lscore.push_back (std::stoi (current_score->get_label ()));
926  saved_scores->set_integer_list ("Scores", username, Lscore);
927  // Save it
928  saved_scores->save_to_file (config_file);
929  make7scores->show ();
930  }
931  make7askname->hide ();
932 }
void big_badaboom(std::list< int > hexas)
Erase all hexas around three (or more) matching "7" hexas.
Definition: game.cc:262
int get_pos2()
Returns pos2 (not very useful)
Definition: game.cc:498
int get_neighbour(int rel, int givenRef)
Calculates the position of a neighbor button.
Definition: game.cc:472
Gtk::Window * make7window
Definition: game.h:99
Gtk::AboutDialog * make7credits
Definition: game.h:101
Gtk::Box * box_score
Definition: game.h:122
Gtk::Button * mainM
Definition: game.h:115
Gtk::Button * w
Definition: game.h:115
Gtk::Button * e
Definition: game.h:115
Glib::ustring get_config_file()
Create config file if it doesn&#39;t exist, then return its path.
Definition: game.cc:423
Gtk::MessageDialog * make7message
Definition: game.h:100
Gtk::Button * se
Definition: game.h:115
void on_display_help_activate()
Signal function activated by button_help.
Definition: game.cc:612
void set_main_hexa(Glib::ustring Snum)
Put the string to the label of the main hexa in SelectionArea.
Definition: game.cc:809
bool triggers(int ref)
Deal with a new hexa on the board.
Definition: game.cc:850
void import_every_widget()
Function containing a lot of lines too.
Definition: game.cc:165
Gtk::Button * mainNw
Definition: game.h:115
std::map< int, Glib::ustring > Colors
Definition: game.h:127
std::map< int, Gtk::Button * > Board
Definition: game.h:126
Gtk::MenuItem * scores
Definition: game.h:106
Gtk::Button * nn
Definition: game.h:115
std::map< int, Glib::ustring > BoardSnapshotMap
Definition: game.h:127
void on_close_scores_activate()
Signal function activated by button_close_scores.
Definition: game.cc:599
void reset_board()
Erase values and colors of all hexas on the Board.
Definition: game.cc:690
void get_random_hexas()
Generate random numbers and fill valHexa1 and valHexa2 with them.
Definition: game.cc:504
int valHexa2
Definition: game.h:129
void game_button_selected(int ref)
Called when any Board button is clicked.
Definition: game.cc:376
std::list< int > SelectionAreaKeys
Definition: game.h:128
Gtk::HeaderBar * headerbar
Definition: game.h:104
Gtk::MessageDialog * make7confirm
Definition: game.h:100
Gtk::Button * nnw
Definition: game.h:115
int refresh_score()
Update the amount of points in the score label.
Definition: game.cc:666
void refresh_selection_area()
Re-display the content of the SelectionArea.
Definition: game.cc:682
std::map< int, Gtk::Button * > SelectionArea
Definition: game.h:126
Gtk::MessageDialog * make7askname
Definition: game.h:100
Gtk::Button * ee
Definition: game.h:115
Glib::ustring get_main_hexa()
Returns the value of the main hexa button label.
Definition: game.cc:463
Gtk::ToggleButton * button_erase
Definition: game.h:113
void on_quit_game_activate()
Signal function activated by button_quit.
Definition: game.cc:660
void store_oldvalhexas()
Definition: game.cc:840
Glib::ustring oldValHexa2
Definition: game.h:130
Gtk::Menu * appmenu
Definition: game.h:105
void display_error(int i)
Spawns a Gtk::MessageDialog containing an appropriated message.
Definition: game.cc:318
void connect_every_button()
Function containing a lot of lines.
Definition: game.cc:83
Gtk::Label * current_score
Definition: game.h:121
void erase_hexa(int ref)
Erase value and color of the given hexa.
Definition: game.cc:347
void get_scores()
Read users scores from saved file.
Definition: game.cc:521
std::list< int > BoardKeys
Definition: game.h:128
Gtk::Button * ww
Definition: game.h:115
Gtk::Button * button_save
Definition: game.h:110
Gtk::MenuItem * quit
Definition: game.h:106
Gtk::Button * nee
Definition: game.h:115
bool get_confirmation()
Ask user to confirm the quitting.
Definition: game.cc:448
Gtk::Button * mainE
Definition: game.h:115
std::list< int > ColorsKeys
Definition: game.h:128
void merge_hexas(int newHexa, std::list< int > oldHexas)
Erase values and colors of matching neighbors.
Definition: game.cc:559
Glib::ustring get_second_hexa()
Same as get_main_hexa () but with the second.
Definition: game.cc:551
bool rotate_hexas_right(GdkEventButton *event)
Signal function activated when user right-clicks on main hexa.
Definition: game.cc:753
Gtk::Button * sse
Definition: game.h:115
Gtk::Button * mainNe
Definition: game.h:115
void set_second_hexa(Glib::ustring Snum)
Same as set_main_hexa (), but with the second.
Definition: game.cc:826
void reset_snapshot()
Re-display an old configuration of Board and SelectionArea, using the std::map created by get_snapsho...
Definition: game.cc:714
Gtk::Button * ne
Definition: game.h:115
void rotate_hexas_left()
Signal function activated when user left-clicks on main hexa.
Definition: game.cc:733
Game()
Constructor.
Definition: game.cc:41
Gtk::Window * make7scores
Definition: game.h:99
int nMatch
Definition: game.h:129
Glib::RefPtr< Gtk::CssProvider > CssProvider
Definition: game.h:131
void set_pos2(int givenPos2)
Set pos2 to the given value (not very useful)
Definition: game.cc:820
void on_cancel_action_activate()
Signal function activated by button_cancel.
Definition: game.cc:591
void write_scores()
Save the score in a file.
Definition: game.cc:905
Gtk::Button * mainSe
Definition: game.h:115
int valHexa1
Definition: game.h:129
void launch_game()
All initializations needed at the beginning of a new game.
Definition: game.cc:239
Gtk::Button * button_cancel
Definition: game.h:110
void reset_selection_area()
Erase values and colors of all hexas on the SelectionArea.
Definition: game.cc:700
bool on_make7window_hide(_GdkEventAny *event)
Signal function activated when user wants to quit.
Definition: game.cc:633
void define_hexa(int ref, Glib::ustring valref)
Define the new hexa then check neighbors while there are.
Definition: game.cc:336
Gtk::Button * button_help
Definition: game.h:110
Gtk::Button * sw
Definition: game.h:115
Gtk::Button * button_next
Definition: game.h:110
Gtk::Button * ss
Definition: game.h:115
bool scan_neighbours(int ref, std::list< int > &oldRefs)
Check if the neighbors of a given hexa have the same value as it.
Definition: game.cc:777
void on_new_game_activate()
Signal function activated by button_new.
Definition: game.cc:642
Gtk::Button * nww
Definition: game.h:115
void on_entry_editing_done()
Activates button_apply_save when user hits &#39;Enter&#39;.
Definition: game.cc:626
void update_hexa_color(int hexa)
Change the color of a given hexa.
Definition: game.cc:873
void display(Glib::RefPtr< Gtk::Application > app)
Here is actually displayed the window.
Definition: game.cc:130
Gtk::Button * button_close_scores
Definition: game.h:110
int max
Definition: game.h:129
Gtk::Button * sww
Definition: game.h:115
Gtk::Button * ssw
Definition: game.h:115
Gtk::MenuItem * newgame
Definition: game.h:106
void on_next_hexa_activate()
Signal function activated by button_next.
Definition: game.cc:649
void on_display_credits_activate()
Signal function activated by button_credits.
Definition: game.cc:605
Gtk::Entry * user_entry
Definition: game.h:123
Gtk::MenuItem * credits
Definition: game.h:106
Gtk::Button * nne
Definition: game.h:115
Gtk::Button * mainSw
Definition: game.h:115
Gtk::Button * m
Definition: game.h:115
Gtk::Button * see
Definition: game.h:115
void on_display_scores_activate()
Signal function activated by button_scores.
Definition: game.cc:620
Gtk::Button * mainW
Definition: game.h:115
Glib::ustring oldValHexa1
Definition: game.h:130
Gtk::MessageDialog * make7error_board
Definition: game.h:100
void check_end()
Definition: game.cc:280
std::map< int, Glib::ustring > get_board_snapshot()
Backup the whole Board and SelectionArea in a std::map.
Definition: game.cc:367
int pos2
Definition: game.h:129
Gtk::Button * nw
Definition: game.h:115